Fix Nashorn sandbox script compile error (ScriptCPUAbuseException)

This commit is contained in:
ViacheslavKlimov 2024-07-30 12:02:01 +03:00
parent e62665bdcd
commit f34361e1ea
2 changed files with 45 additions and 4 deletions

View File

@ -39,12 +39,13 @@ import java.util.concurrent.TimeoutException;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.thingsboard.server.common.data.msg.TbMsgType.POST_TELEMETRY_REQUEST;
@DaoSqlTest
@TestPropertySource(properties = {
"js.evaluator=local",
"js.max_script_body_size=50",
"js.max_script_body_size=10000",
"js.max_total_args_size=50",
"js.max_result_size=50",
"js.local.max_errors=2",
@ -87,7 +88,7 @@ class NashornJsInvokeServiceTest extends AbstractControllerTest {
@Test
void givenSimpleScriptMultiThreadTestPerformance() throws ExecutionException, InterruptedException, TimeoutException {
int iterations = 1000*4;
int iterations = 1000 * 4;
List<ListenableFuture<Object>> futures = new ArrayList<>(iterations);
UUID scriptId = evalScript("return msg.temperature > 20 ;");
// warmup
@ -125,7 +126,7 @@ class NashornJsInvokeServiceTest extends AbstractControllerTest {
@Test
void givenTooBigScriptForEval_thenReturnError() {
String hugeScript = "var a = 'qwertyqwertywertyqwabababer'; return {a: a};";
String hugeScript = "var a = '" + "a".repeat(10000) + "'; return {a: a};";
assertThatThrownBy(() -> {
evalScript(hugeScript);
@ -159,6 +160,46 @@ class NashornJsInvokeServiceTest extends AbstractControllerTest {
assertThatScriptIsBlocked(scriptId);
}
@Test
void givenComplexScript_testCompile() {
String script = """
function(data) {
if (data.get("propertyA") == "a special value 1" || data.get("propertyA") == "a special value 2") {
return "a special value 1";
} else if (data.get("propertyB") == "a special value 3" && (data.get("propertyC") == "a special value 1" || data.get("propertyJ") == "a special value 1" || data.get("propertyV") == "a special value 1")) {
return "a special value 1";
} else if (data.get("propertyB") == "4" && (data.get("propertyD") == "a special value 1" || data.get("propertyV") == "a special value 1" || data.get("propertyW") == "a special value 1")) {
return "a special value 1";
} else if (data.get("propertyB") == "a special value 2" && (data.get("propertyE") == "a special value 1" || data.get("propertyF") == "a special value 1" || data.get("propertyL") == "a special value 1")) {
return "a special value 1";
} else if (data.get("propertyB") == "a special value 3" && (data.get("propertyE") == "a special value 1" || data.get("propertyF") == "a special value 1" || data.get("propertyL") == "a special value 1")) {
return "a special value 1";
} else if (data.get("propertyB") == "a special value 3" && (data.get("propertyM") == "a special value 1" || data.get("propertyY") == "a special value 1" || data.get("propertyH") == "a special value 1")) {
return "a special value 1";
} else if (data.get("propertyB") == "a special value 3" && (data.get("propertyM") == "a special value 1" || data.get("propertyY") == "a special value 1" || data.get("propertyH") == "a special value 1")) {
return "a special value 1";
} else if (data.get("propertyB") == "a special value 3" && (data.get("propertyM") == "a special value 1" || data.get("propertyY") == "a special value 1" || data.get("propertyH") == "a special value 1")) {
return "a special value 1";
} else if (data.get("propertyB") == "a special value 3" && (data.get("propertyM") == "a special value 1" || data.get("propertyY") == "a special value 1" || data.get("propertyH") == "a special value 1")) {
return "a special value 1";
} else if (data.get("propertyB") == "a special value 3" && (data.get("propertyM") == "a special value 1" || data.get("propertyY") == "a special value 1" || data.get("propertyH") == "a special value 1")) {
return "a special value 1";
} else if (data.get("propertyB") == "a special value 3" && (data.get("propertyM") == "a special value 1" || data.get("propertyY") == "a special value 1" || data.get("propertyH") == "a special value 1")) {
return "a special value 1";
} else if (data.get("propertyB") == "a special value 3" && (data.get("propertyM") == "a special value 1" || data.get("propertyY") == "a special value 1" || data.get("propertyH") == "a special value 1")) {
return "a special value 1";
} else {
return "0"
};
}
""";
// with delight-nashorn-sandbox 0.4.2, this would throw delight.nashornsandbox.exceptions.ScriptCPUAbuseException: Regular expression running for too many iterations. The operation could NOT be gracefully interrupted.
assertDoesNotThrow(() -> {
evalScript(script);
});
}
private void assertThatScriptIsBlocked(UUID scriptId) {
assertThatThrownBy(() -> {
invokeScript(scriptId, "{}");

View File

@ -105,7 +105,7 @@
org/thingsboard/server/extensions/core/plugin/telemetry/gen/**/*
</sonar.exclusions>
<elasticsearch.version>8.13.2</elasticsearch.version>
<delight-nashorn-sandbox.version>0.4.2</delight-nashorn-sandbox.version>
<delight-nashorn-sandbox.version>0.4.5</delight-nashorn-sandbox.version>
<nashorn-core.version>15.4</nashorn-core.version>
<!-- IMPORTANT: If you change the version of the kafka client, make sure to synchronize our overwritten implementation of the
org.apache.kafka.common.network.NetworkReceive class in the application module. It addresses the issue https://issues.apache.org/jira/browse/KAFKA-4090.