From f34361e1eac041bf4de5002e5101ed6a50697b2b Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Tue, 30 Jul 2024 12:02:01 +0300 Subject: [PATCH] Fix Nashorn sandbox script compile error (ScriptCPUAbuseException) --- .../script/NashornJsInvokeServiceTest.java | 47 +++++++++++++++++-- pom.xml | 2 +- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/service/script/NashornJsInvokeServiceTest.java b/application/src/test/java/org/thingsboard/server/service/script/NashornJsInvokeServiceTest.java index 28834a0ab7..33e7ccea23 100644 --- a/application/src/test/java/org/thingsboard/server/service/script/NashornJsInvokeServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/service/script/NashornJsInvokeServiceTest.java @@ -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> 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, "{}"); diff --git a/pom.xml b/pom.xml index f75e782bef..9b8943cff3 100755 --- a/pom.xml +++ b/pom.xml @@ -105,7 +105,7 @@ org/thingsboard/server/extensions/core/plugin/telemetry/gen/**/* 8.13.2 - 0.4.2 + 0.4.5 15.4