Skip to content

Commit f8d2572

Browse files
committed
fix(sdk): reject oversized command timeouts
1 parent 3714170 commit f8d2572

3 files changed

Lines changed: 23 additions & 2 deletions

File tree

sdks/sandbox/kotlin/sandbox/src/main/kotlin/com/alibaba/opensandbox/sandbox/infrastructure/adapters/converter/ExecutionConverter.kt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package com.alibaba.opensandbox.sandbox.infrastructure.adapters.converter
1818

1919
import com.alibaba.opensandbox.sandbox.domain.models.execd.executions.CommandStatus
2020
import com.alibaba.opensandbox.sandbox.domain.models.execd.executions.RunCommandRequest
21+
import java.time.Duration
2122
import com.alibaba.opensandbox.sandbox.api.models.execd.CommandStatusResponse as ApiCommandStatusResponse
2223
import com.alibaba.opensandbox.sandbox.api.models.execd.RunCommandRequest as ApiRunCommandRequest
2324

@@ -27,7 +28,7 @@ object ExecutionConverter {
2728
command = command,
2829
background = background,
2930
cwd = workingDirectory,
30-
timeout = timeout?.toMillis(),
31+
timeout = timeout?.toCommandTimeoutMillis(),
3132
uid = uid,
3233
gid = gid,
3334
envs = envs,
@@ -46,3 +47,12 @@ object ExecutionConverter {
4647
)
4748
}
4849
}
50+
51+
internal fun Duration.toCommandTimeoutMillis(): Long {
52+
require(!isNegative) { "Timeout must be non-negative, got: $this" }
53+
return try {
54+
toMillis()
55+
} catch (e: ArithmeticException) {
56+
throw IllegalArgumentException("Timeout is too large to represent in milliseconds: $this", e)
57+
}
58+
}

sdks/sandbox/kotlin/sandbox/src/main/kotlin/com/alibaba/opensandbox/sandbox/infrastructure/adapters/service/CommandsAdapter.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import com.alibaba.opensandbox.sandbox.infrastructure.adapters.converter.Executi
4242
import com.alibaba.opensandbox.sandbox.infrastructure.adapters.converter.ExecutionEventDispatcher
4343
import com.alibaba.opensandbox.sandbox.infrastructure.adapters.converter.jsonParser
4444
import com.alibaba.opensandbox.sandbox.infrastructure.adapters.converter.parseSandboxError
45+
import com.alibaba.opensandbox.sandbox.infrastructure.adapters.converter.toCommandTimeoutMillis
4546
import com.alibaba.opensandbox.sandbox.infrastructure.adapters.converter.toSandboxException
4647
import okhttp3.Headers.Companion.toHeaders
4748
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
@@ -196,7 +197,7 @@ internal class CommandsAdapter(
196197
RunInSessionRequestApi(
197198
command = request.command,
198199
cwd = request.workingDirectory,
199-
timeout = request.timeout?.toMillis(),
200+
timeout = request.timeout?.toCommandTimeoutMillis(),
200201
)
201202
val runUrl =
202203
execdBaseUrl

sdks/sandbox/kotlin/sandbox/src/test/kotlin/com/alibaba/opensandbox/sandbox/infrastructure/adapters/service/CommandsAdapterTest.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import com.alibaba.opensandbox.sandbox.domain.models.execd.executions.ExecutionH
2525
import com.alibaba.opensandbox.sandbox.domain.models.execd.executions.RunCommandRequest
2626
import com.alibaba.opensandbox.sandbox.domain.models.execd.executions.RunInSessionRequest
2727
import com.alibaba.opensandbox.sandbox.domain.models.sandboxes.SandboxEndpoint
28+
import com.alibaba.opensandbox.sandbox.infrastructure.adapters.converter.toCommandTimeoutMillis
2829
import kotlinx.serialization.json.Json
2930
import kotlinx.serialization.json.booleanOrNull
3031
import kotlinx.serialization.json.intOrNull
@@ -359,6 +360,15 @@ data: {"type":"execution_complete","execution_time":100,"timestamp":167253120100
359360
assertEquals(5000L, requestBodyJson["timeout"]?.jsonPrimitive?.content?.toLong())
360361
}
361362

363+
@Test
364+
fun `command timeout conversion should reject durations too large for milliseconds`() {
365+
val exception =
366+
assertThrows(IllegalArgumentException::class.java) {
367+
Duration.ofSeconds(Long.MAX_VALUE).toCommandTimeoutMillis()
368+
}
369+
assertTrue(exception.message!!.contains("too large to represent in milliseconds"))
370+
}
371+
362372
@Test
363373
fun `runInSession should infer non-zero exit code from command error event`() {
364374
val initEvent = """data: {"type":"init","text":"cmd-123","timestamp":1672531200000}"""

0 commit comments

Comments
 (0)