Apache IoTDB: JEXL Expression Injection Vulnerability
Description
Improper Input Validation vulnerability in Apache IoTDB.
This issue affects Apache IoTDB: from 1.0.0 before 1.3.7, from 2.0.0 before 2.0.7.
Users are recommended to upgrade to version 1.3.7 or 2.0.7, which fixes the issue.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Apache IoTDB versions before 1.3.7 and 2.0.7 contain an improper input validation vulnerability that could allow remote code execution via crafted JEXL expressions.
Vulnerability
Overview
CVE-2026-24713 is an improper input validation vulnerability in Apache IoTDB, a time series database management system. The issue affects versions from 1.0.0 before 1.3.7 and from 2.0.0 before 2.0.7. The root cause lies in the handling of user-defined transformation functions (UDTFs) that use JEXL (Java Expression Language) expressions. The built-in JEXL function in tree mode did not properly validate or sanitize or restrict the expressions passed to it, allowing an attacker to inject arbitrary JEXL code [2].
Exploitation
An attacker with the ability to submit SQL-like queries to IoTDB can exploit this vulnerability by crafting a malicious JEXL expression within a UDTF call. No special privileges beyond query access are required, as the vulnerable function is available to any authenticated user who can execute queries. The attack surface is the IoTDB query interface, which is typically exposed on a network port [1][2].
Impact
Successful exploitation allows an attacker to execute arbitrary code on the IoTDB server. This could lead to full compromise of the database, including data exfiltration, modification, or deletion, and potentially lateral movement within the network. The vulnerability is particularly severe because IoTDB is often deployed in industrial IoT environments where it handles sensitive time series data [1][3].
Mitigation
Apache has released fixed versions 1.3.7 and 2.0.7, which remove the built-in JEXL function in tree mode [2]. Users are strongly recommended to upgrade immediately. No workarounds have been provided for older versions [3]. The vulnerability is not yet listed in CISA's Known Exploited Vulnerabilities (KEV) catalog as of publication date.
AI Insight generated on May 18, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
org.apache.iotdb:iotdb-coreMaven | >= 1.0.0, < 1.3.7 | 1.3.7 |
org.apache.iotdb:iotdb-coreMaven | >= 2.0.0, < 2.0.7 | 2.0.7 |
Affected products
2- Apache Software Foundation/Apache IoTDBv5Range: 1.0.0
Patches
18fbfddc5f837Remove built-in jexl function in tree mode (#17092)
12 files changed · +36 −627
dependencies.json+0 −2 modified@@ -52,7 +52,6 @@ "io.netty:netty-codec", "io.netty:netty-codec-dns", "io.netty:netty-codec-http", - "io.netty:netty-codec-http", "io.netty:netty-codec-http2", "io.netty:netty-codec-mqtt", "io.netty:netty-codec-socks", @@ -97,7 +96,6 @@ "org.antlr:antlr4-runtime", "org.apache.commons:commons-collections4", "org.apache.commons:commons-csv", - "org.apache.commons:commons-jexl3", "org.apache.commons:commons-lang3", "org.apache.commons:commons-math3", "org.apache.commons:commons-pool2",
example/pipe-count-point-processor/pom.xml+1 −1 modified@@ -59,7 +59,7 @@ <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.2.2</version> - <configuration /> + <configuration/> </plugin> </plugins> </build>
integration-test/pom.xml+5 −5 modified@@ -29,16 +29,16 @@ <artifactId>integration-test</artifactId> <name>IoTDB: Integration-Test</name> <properties> - <integrationTest.excludedGroups /> + <integrationTest.excludedGroups/> <integrationTest.forkCount>1</integrationTest.forkCount> - <integrationTest.includedGroups /> + <integrationTest.includedGroups/> <integrationTest.launchNodeInSameJVM>true</integrationTest.launchNodeInSameJVM> <integrationTest.nodeMaxHeapSize>200m</integrationTest.nodeMaxHeapSize> <integrationTest.nodeNewHeapSize>200m</integrationTest.nodeNewHeapSize> <integrationTest.randomSelectWriteNode>true</integrationTest.randomSelectWriteNode> <integrationTest.readAndVerifyWithMultiNode>true</integrationTest.readAndVerifyWithMultiNode> <integrationTest.dataRegionPerDataNode>0</integrationTest.dataRegionPerDataNode> - <integrationTest.testEnv /> + <integrationTest.testEnv/> <lightWeightStandaloneMode.configNodeConsensus>Simple</lightWeightStandaloneMode.configNodeConsensus> <!-- -DClusterConfigurations values configured here --> <lightWeightStandaloneMode.configNodeNumber>1</lightWeightStandaloneMode.configNodeNumber> @@ -672,7 +672,7 @@ <activeByDefault>false</activeByDefault> </activation> <properties> - <integrationTest.excludedGroups /> + <integrationTest.excludedGroups/> <integrationTest.includedGroups>org.apache.iotdb.itbase.category.DailyIT</integrationTest.includedGroups> <integrationTest.launchNodeInSameJVM>false</integrationTest.launchNodeInSameJVM> <integrationTest.randomSelectWriteNode>true</integrationTest.randomSelectWriteNode> @@ -714,7 +714,7 @@ <activeByDefault>false</activeByDefault> </activation> <properties> - <integrationTest.excludedGroups /> + <integrationTest.excludedGroups/> <integrationTest.includedGroups>org.apache.iotdb.itbase.category.ManualIT</integrationTest.includedGroups> <integrationTest.launchNodeInSameJVM>false</integrationTest.launchNodeInSameJVM> <integrationTest.randomSelectWriteNode>true</integrationTest.randomSelectWriteNode>
integration-test/src/main/java/org/apache/iotdb/itbase/constant/BuiltinTimeSeriesGeneratingFunctionEnum.java+0 −1 modified@@ -72,7 +72,6 @@ public enum BuiltinTimeSeriesGeneratingFunctionEnum { EQUAL_SIZE_BUCKET_AGG_SAMPLE("EQUAL_SIZE_BUCKET_AGG_SAMPLE"), EQUAL_SIZE_BUCKET_M4_SAMPLE("EQUAL_SIZE_BUCKET_M4_SAMPLE"), EQUAL_SIZE_BUCKET_OUTLIER_SAMPLE("EQUAL_SIZE_BUCKET_OUTLIER_SAMPLE"), - JEXL("JEXL"), MASTER_REPAIR("MASTER_REPAIR"), FORECAST("FORECAST"), M4("M4");
integration-test/src/test/java/org/apache/iotdb/db/it/udf/IoTDBUDTFBuiltinFunctionIT.java+0 −235 modified@@ -1490,241 +1490,6 @@ private void test_M4_constantTimeSeries() { } } - @Test - public void testUDTFJexl() { - try (Connection connection = EnvFactory.getEnv().getConnection(); - Statement statement = connection.createStatement()) { - statement.execute("CREATE TIMESERIES root.sg.d7.s1 with datatype=INT32,encoding=PLAIN"); - statement.execute("CREATE TIMESERIES root.sg.d7.s2 with datatype=FLOAT,encoding=PLAIN"); - statement.execute("CREATE TIMESERIES root.sg.d7.s3 with datatype=DOUBLE,encoding=PLAIN"); - statement.execute("CREATE TIMESERIES root.sg.d7.s4 with datatype=TEXT,encoding=PLAIN"); - statement.execute("CREATE TIMESERIES root.sg.d7.s5 with datatype=BOOLEAN,encoding=PLAIN"); - statement.execute("CREATE TIMESERIES root.sg.d7.s6 with datatype=INT64,encoding=PLAIN"); - statement.execute("CREATE TIMESERIES root.sg.d7.s7 with datatype=INT64,encoding=PLAIN"); - statement.execute("CREATE TIMESERIES root.sg.d7.s8 with datatype=FLOAT,encoding=PLAIN"); - statement.execute("CREATE TIMESERIES root.sg.d7.s9 with datatype=TEXT,encoding=PLAIN"); - } catch (SQLException throwable) { - fail(throwable.getMessage()); - } - String[] SQL_FOR_SAMPLE_1 = new String[6]; - String[] SQL_FOR_SAMPLE_2 = new String[6]; - String[] SQL_FOR_SAMPLE_3 = new String[6]; - String[] SQL_FOR_SAMPLE_4 = new String[6]; - String[] SQL_FOR_SAMPLE_5 = new String[6]; - String[] SQL_FOR_SAMPLE_6 = new String[6]; - String[] SQL_FOR_SAMPLE_7 = new String[6]; - String[] SQL_FOR_SAMPLE_8 = new String[6]; - String[] SQL_FOR_SAMPLE_9 = new String[6]; - for (int i = 0; i < 5; i++) { - SQL_FOR_SAMPLE_1[i] = - String.format( - Locale.ENGLISH, "insert into root.sg.d7(time, s1) values (%d, %d)", i, i + 1); - SQL_FOR_SAMPLE_2[i] = - String.format( - Locale.ENGLISH, "insert into root.sg.d7(time, s2) values (%d, %f)", i, i + 1.0); - SQL_FOR_SAMPLE_3[i] = - String.format( - Locale.ENGLISH, "insert into root.sg.d7(time, s3) values (%d, %f)", i, i + 1.0); - SQL_FOR_SAMPLE_4[i] = - String.format( - Locale.ENGLISH, "insert into root.sg.d7(time, s4) values (%d, '%s')", i, "string"); - SQL_FOR_SAMPLE_5[i] = String.format("insert into root.sg.d7(time, s5) values (%d, true)", i); - SQL_FOR_SAMPLE_6[i] = - String.format( - Locale.ENGLISH, "insert into root.sg.d7(time, s6) values (%d, %d)", i, i + 8); - SQL_FOR_SAMPLE_7[i] = - String.format( - Locale.ENGLISH, "insert into root.sg.d7(time, s7) values (%d, %d)", i, i + 1); - SQL_FOR_SAMPLE_8[i] = - String.format( - Locale.ENGLISH, "insert into root.sg.d7(time, s8) values (%d, %f)", i, i + 1.0); - SQL_FOR_SAMPLE_9[i] = - String.format( - Locale.ENGLISH, "insert into root.sg.d7(time, s9) values (%d, '%s')", i, "string"); - } - SQL_FOR_SAMPLE_1[5] = - String.format( - Locale.ENGLISH, - "insert into root.sg.d7(time, s1) values (%d, %d)", - 10000000000L, - 5 + 1); - SQL_FOR_SAMPLE_2[5] = - String.format( - Locale.ENGLISH, - "insert into root.sg.d7(time, s2) values (%d, %f)", - 10000000000L, - 5 + 1.0); - SQL_FOR_SAMPLE_3[5] = - String.format( - Locale.ENGLISH, - "insert into root.sg.d7(time, s3) values (%d, %f)", - 10000000000L, - 5 + 1.0); - SQL_FOR_SAMPLE_4[5] = - String.format( - Locale.ENGLISH, - "insert into root.sg.d7(time, s4) values (%d, '%s')", - 10000000000L, - "string"); - SQL_FOR_SAMPLE_5[5] = String.format("insert into root.sg.d7(time, s5) values (%d, true)", 5); - SQL_FOR_SAMPLE_6[5] = - String.format( - Locale.ENGLISH, - "insert into root.sg.d7(time, s6) values (%d, %d)", - 10000000000L, - 5 + 8); - SQL_FOR_SAMPLE_7[5] = - String.format( - Locale.ENGLISH, - "insert into root.sg.d7(time, s7) values (%d, %d)", - 10000000000L, - 5 + 1); - SQL_FOR_SAMPLE_8[5] = - String.format( - Locale.ENGLISH, - "insert into root.sg.d7(time, s8) values (%d, %f)", - 10000000000L, - 5 + 1.0); - SQL_FOR_SAMPLE_9[5] = - String.format( - Locale.ENGLISH, - "insert into root.sg.d7(time, s9) values (%d, '%s')", - 10000000000L, - "string"); - double[] ANSWER1 = new double[] {2, 4, 6, 8, 10, 12}; - double[] ANSWER2 = new double[] {2, 4, 6, 8, 10, 12}; - double[] ANSWER3 = new double[] {4, 7, 10, 13, 16, 19}; - String[] ANSWER4 = - new String[] {"string2", "string2", "string2", "string2", "string2", "string2"}; - double[] ANSWER7 = new double[] {1, 4, 9, 16, 25, 36}; - String[] ANSWER8 = - new String[] {"string1", "string4", "string9", "string16", "string25", "string36"}; - double[] ANSWER9 = new double[] {2, 9, 28, 65, 126, 469}; - try (Connection connection = EnvFactory.getEnv().getConnection(); - Statement statement = connection.createStatement()) { - for (int i = 0; i < 5; i++) { - statement.execute(SQL_FOR_SAMPLE_1[i]); - statement.execute(SQL_FOR_SAMPLE_2[i]); - statement.execute(SQL_FOR_SAMPLE_3[i]); - statement.execute(SQL_FOR_SAMPLE_4[i]); - statement.execute(SQL_FOR_SAMPLE_5[i]); - statement.execute(SQL_FOR_SAMPLE_6[i]); - statement.execute(SQL_FOR_SAMPLE_7[i]); - statement.execute(SQL_FOR_SAMPLE_8[i]); - statement.execute(SQL_FOR_SAMPLE_9[i]); - } - } catch (SQLException throwable) { - fail(throwable.getMessage()); - } - - try (Connection connection = EnvFactory.getEnv().getConnection(); - Statement statement = connection.createStatement()) { - String functionName = "JEXL"; - String expr1 = "x -> {2 * x}"; - String expr2 = "x -> {x + x}"; - String expr3 = "x -> {x * 3 + 1}"; - String expr4 = "x -> {x + 2}"; - String expr5 = "x -> {x == true}"; - String expr6 = "x -> {x == x}"; - String expr7 = "(x, y) -> {x * y}"; - String expr8 = "(x, y, z) -> {x + y * z}"; - String expr9 = "(x, y, z, a) -> {x * y * z + (a ? 1 : -1)}"; - ResultSet resultSet = - statement.executeQuery( - String.format( - "select %s(s1, 'expr'='%s'), " - + "%s(s2, 'expr'='%s'), " - + "%s(s3, 'expr'='%s'), " - + "%s(s4, 'expr'='%s'), " - + "%s(s5, 'expr'='%s'), " - + "%s(s6, 'expr'='%s'), " - + "%s(s7, s8, 'expr'='%s'), " - + "%s(s4, s7, s1, 'expr'='%s'), " - + "%s(s1, s7, s8, s5, 'expr'='%s') " - + "from root.sg.d7", - functionName, - expr1, - functionName, - expr2, - functionName, - expr3, - functionName, - expr4, - functionName, - expr5, - functionName, - expr6, - functionName, - expr7, - functionName, - expr8, - functionName, - expr9)); - int columnCount = resultSet.getMetaData().getColumnCount(); - assertEquals(1 + 9, columnCount); - for (int i = 0; i < 5; i++) { - resultSet.next(); - assertEquals(ANSWER1[i], resultSet.getDouble(2), 0.01); - assertEquals(ANSWER2[i], resultSet.getDouble(3), 0.01); - assertEquals(ANSWER3[i], resultSet.getDouble(4), 0.01); - assertEquals(ANSWER4[i], resultSet.getString(5)); - assertTrue(resultSet.getBoolean(6)); - assertTrue(resultSet.getBoolean(7)); - assertEquals(ANSWER7[i], resultSet.getDouble(8), 0.01); - assertEquals(ANSWER8[i], resultSet.getString(9)); - assertEquals(ANSWER9[i], resultSet.getDouble(10), 0.01); - } - - resultSet = - statement.executeQuery( - String.format( - "select %s(s1, 'expr'='%s'), " - + "%s(s2, 'expr'='%s'), " - + "%s(s3, 'expr'='%s'), " - + "%s(s4, 'expr'='%s'), " - + "%s(s5, 'expr'='%s'), " - + "%s(s6, 'expr'='%s'), " - + "%s(s7, s8, 'expr'='%s'), " - + "%s(s4, s7, s1, 'expr'='%s'), " - + "%s(s1, s7, s8, s5, 'expr'='%s') " - + "from root.sg.d7 align by device", - functionName, - expr1, - functionName, - expr2, - functionName, - expr3, - functionName, - expr4, - functionName, - expr5, - functionName, - expr6, - functionName, - expr7, - functionName, - expr8, - functionName, - expr9)); - columnCount = resultSet.getMetaData().getColumnCount(); - assertEquals(2 + 9, columnCount); - for (int i = 0; i < 5; i++) { - resultSet.next(); - assertEquals(ANSWER1[i], resultSet.getDouble(2 + 1), 0.01); - assertEquals(ANSWER2[i], resultSet.getDouble(3 + 1), 0.01); - assertEquals(ANSWER3[i], resultSet.getDouble(4 + 1), 0.01); - assertEquals(ANSWER4[i], resultSet.getString(5 + 1)); - assertTrue(resultSet.getBoolean(6 + 1)); - assertTrue(resultSet.getBoolean(7 + 1)); - assertEquals(ANSWER7[i], resultSet.getDouble(8 + 1), 0.01); - assertEquals(ANSWER8[i], resultSet.getString(9 + 1)); - assertEquals(ANSWER9[i], resultSet.getDouble(10 + 1), 0.01); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - @Test public void testStringFunctions() { String[] createSQLs =
iotdb-client/jdbc/pom.xml+1 −1 modified@@ -266,7 +266,7 @@ </goals> </pluginExecutionFilter> <action> - <ignore /> + <ignore/> </action> </pluginExecution> </pluginExecutions>
iotdb-core/ainode/iotdb/conf/git.properties+3 −0 added@@ -0,0 +1,3 @@ +#Generated by Git-Commit-Id-Plugin +git.commit.id.abbrev=370df98 +git.dirty=false
iotdb-core/ainode/iotdb/conf/pom.properties+21 −0 added@@ -0,0 +1,21 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +artifactId=iotdb-ainode +groupId=org.apache.iotdb +version=1.3.7-SNAPSHOT \ No newline at end of file
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/udf/BuiltinTimeSeriesGeneratingFunction.java+0 −2 modified@@ -51,7 +51,6 @@ import org.apache.iotdb.commons.udf.builtin.UDTFExp; import org.apache.iotdb.commons.udf.builtin.UDTFFloor; import org.apache.iotdb.commons.udf.builtin.UDTFInRange; -import org.apache.iotdb.commons.udf.builtin.UDTFJexl; import org.apache.iotdb.commons.udf.builtin.UDTFLog; import org.apache.iotdb.commons.udf.builtin.UDTFLog10; import org.apache.iotdb.commons.udf.builtin.UDTFM4; @@ -136,7 +135,6 @@ public enum BuiltinTimeSeriesGeneratingFunction { EQUAL_SIZE_BUCKET_M4_SAMPLE("EQUAL_SIZE_BUCKET_M4_SAMPLE", UDTFEqualSizeBucketM4Sample.class), EQUAL_SIZE_BUCKET_OUTLIER_SAMPLE( "EQUAL_SIZE_BUCKET_OUTLIER_SAMPLE", UDTFEqualSizeBucketOutlierSample.class), - JEXL("JEXL", UDTFJexl.class), MASTER_REPAIR("MASTER_REPAIR", UDTFMasterRepair.class), M4("M4", UDTFM4.class), FORECAST("FORECAST", UDTFForecast.class),
iotdb-core/node-commons/pom.xml+0 −4 modified@@ -159,10 +159,6 @@ <groupId>com.github.ben-manes.caffeine</groupId> <artifactId>caffeine</artifactId> </dependency> - <dependency> - <groupId>org.apache.commons</groupId> - <artifactId>commons-jexl3</artifactId> - </dependency> <dependency> <groupId>com.github.luben</groupId> <artifactId>zstd-jni</artifactId>
iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/UDTFJexl.java+0 −365 removed@@ -1,365 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.apache.iotdb.commons.udf.builtin; - -import org.apache.iotdb.commons.exception.MetadataException; -import org.apache.iotdb.commons.udf.utils.UDFDataTypeTransformer; -import org.apache.iotdb.udf.api.UDTF; -import org.apache.iotdb.udf.api.access.Row; -import org.apache.iotdb.udf.api.collector.PointCollector; -import org.apache.iotdb.udf.api.customizer.config.UDTFConfigurations; -import org.apache.iotdb.udf.api.customizer.parameter.UDFParameterValidator; -import org.apache.iotdb.udf.api.customizer.parameter.UDFParameters; -import org.apache.iotdb.udf.api.customizer.strategy.RowByRowAccessStrategy; -import org.apache.iotdb.udf.api.exception.UDFException; -import org.apache.iotdb.udf.api.exception.UDFInputSeriesDataTypeNotValidException; -import org.apache.iotdb.udf.api.exception.UDFOutputSeriesDataTypeNotValidException; -import org.apache.iotdb.udf.api.type.Type; - -import org.apache.commons.jexl3.JexlBuilder; -import org.apache.commons.jexl3.JexlEngine; -import org.apache.commons.jexl3.JexlScript; -import org.apache.tsfile.enums.TSDataType; - -import java.io.IOException; -import java.util.HashMap; - -public class UDTFJexl implements UDTF { - - private int inputSeriesNumber; - private TSDataType[] inputDataType; - private TSDataType outputDataType; - private JexlScript script; - private Evaluator evaluator; - - @Override - public void validate(UDFParameterValidator validator) throws UDFException { - inputSeriesNumber = validator.getParameters().getChildExpressionsSize(); - for (int i = 0; i < inputSeriesNumber; i++) { - validator.validateInputSeriesDataType( - i, Type.INT32, Type.INT64, Type.FLOAT, Type.DOUBLE, Type.TEXT, Type.BOOLEAN); - } - validator.validateRequiredAttribute("expr"); - } - - @Override - public void beforeStart(UDFParameters parameters, UDTFConfigurations configurations) - throws UDFInputSeriesDataTypeNotValidException, - UDFOutputSeriesDataTypeNotValidException, - MetadataException { - String expr = parameters.getString("expr"); - JexlEngine jexl = new JexlBuilder().create(); - script = jexl.createScript(expr); - - inputDataType = new TSDataType[inputSeriesNumber]; - for (int i = 0; i < inputSeriesNumber; i++) { - inputDataType[i] = UDFDataTypeTransformer.transformToTsDataType(parameters.getDataType(i)); - } - outputDataType = probeOutputDataType(); - - if (inputSeriesNumber == 1) { - switch (inputDataType[0]) { - case INT32: - evaluator = new EvaluatorIntInput(); - break; - case INT64: - evaluator = new EvaluatorLongInput(); - break; - case FLOAT: - evaluator = new EvaluatorFloatInput(); - break; - case DOUBLE: - evaluator = new EvaluatorDoubleInput(); - break; - case TEXT: - evaluator = new EvaluatorStringInput(); - break; - case BOOLEAN: - evaluator = new EvaluatorBooleanInput(); - break; - case STRING: - case TIMESTAMP: - case DATE: - case BLOB: - default: - throw new UDFInputSeriesDataTypeNotValidException( - 0, - UDFDataTypeTransformer.transformToUDFDataType(inputDataType[0]), - Type.INT32, - Type.INT64, - Type.FLOAT, - Type.DOUBLE, - Type.TEXT, - Type.BOOLEAN); - } - } else { - evaluator = new EvaluatorMulInput(); - } - - configurations - .setAccessStrategy(new RowByRowAccessStrategy()) - .setOutputDataType(UDFDataTypeTransformer.transformToUDFDataType(outputDataType)); - } - - // 23, 23L, 23f, 23d, "string", true are hard codes for probing - private HashMap<TSDataType, Object> initialMap() { - HashMap<TSDataType, Object> map = new HashMap<>(); - map.put(TSDataType.INT32, 23); - map.put(TSDataType.INT64, 23L); - map.put(TSDataType.FLOAT, 23f); - map.put(TSDataType.DOUBLE, 23d); - map.put(TSDataType.TEXT, "string"); - map.put(TSDataType.BOOLEAN, true); - return map; - } - - private TSDataType probeOutputDataType() throws UDFOutputSeriesDataTypeNotValidException { - // initial inputHardCodes to probe OutputDataType - HashMap<TSDataType, Object> map = initialMap(); - Object[] inputHardCodes = new Object[inputSeriesNumber]; - for (int i = 0; i < inputSeriesNumber; i++) { - inputHardCodes[i] = map.get(inputDataType[i]); - } - - Object o = script.execute(null, inputHardCodes); - - if (o instanceof Number) { - return TSDataType.DOUBLE; - } else if (o instanceof String) { - return TSDataType.TEXT; - } else if (o instanceof Boolean) { - return TSDataType.BOOLEAN; - } else { - throw new UDFOutputSeriesDataTypeNotValidException(0, "[Number, String, Boolean]"); - } - } - - @Override - public void transform(Row row, PointCollector collector) - throws IOException, - UDFOutputSeriesDataTypeNotValidException, - UDFInputSeriesDataTypeNotValidException { - switch (outputDataType) { - case DOUBLE: - evaluator.evaluateDouble(row, collector); - break; - case TEXT: - evaluator.evaluateText(row, collector); - break; - case BOOLEAN: - evaluator.evaluateBoolean(row, collector); - break; - case TIMESTAMP: - case DATE: - case STRING: - case BLOB: - case INT64: - case INT32: - case FLOAT: - default: - // This will not happen. - throw new UDFOutputSeriesDataTypeNotValidException(0, "[Number, String, Boolean]"); - } - } - - private interface Evaluator { - void evaluateDouble(Row row, PointCollector collector) - throws IOException, UDFInputSeriesDataTypeNotValidException; - - void evaluateText(Row row, PointCollector collector) - throws IOException, UDFInputSeriesDataTypeNotValidException; - - void evaluateBoolean(Row row, PointCollector collector) - throws IOException, UDFInputSeriesDataTypeNotValidException; - } - - private class EvaluatorIntInput implements Evaluator { - @Override - public void evaluateDouble(Row row, PointCollector collector) throws IOException { - collector.putDouble( - row.getTime(), ((Number) script.execute(null, row.getInt(0))).doubleValue()); - } - - @Override - public void evaluateText(Row row, PointCollector collector) throws IOException { - collector.putString(row.getTime(), (String) script.execute(null, row.getInt(0))); - } - - @Override - public void evaluateBoolean(Row row, PointCollector collector) throws IOException { - collector.putBoolean(row.getTime(), (Boolean) script.execute(null, row.getInt(0))); - } - } - - private class EvaluatorLongInput implements Evaluator { - @Override - public void evaluateDouble(Row row, PointCollector collector) throws IOException { - collector.putDouble( - row.getTime(), ((Number) script.execute(null, row.getLong(0))).doubleValue()); - } - - @Override - public void evaluateText(Row row, PointCollector collector) throws IOException { - collector.putString(row.getTime(), (String) script.execute(null, row.getLong(0))); - } - - @Override - public void evaluateBoolean(Row row, PointCollector collector) throws IOException { - collector.putBoolean(row.getTime(), (Boolean) script.execute(null, row.getLong(0))); - } - } - - private class EvaluatorFloatInput implements Evaluator { - @Override - public void evaluateDouble(Row row, PointCollector collector) throws IOException { - collector.putDouble( - row.getTime(), ((Number) script.execute(null, row.getFloat(0))).doubleValue()); - } - - @Override - public void evaluateText(Row row, PointCollector collector) throws IOException { - collector.putString(row.getTime(), (String) script.execute(null, row.getFloat(0))); - } - - @Override - public void evaluateBoolean(Row row, PointCollector collector) throws IOException { - collector.putBoolean(row.getTime(), (Boolean) script.execute(null, row.getFloat(0))); - } - } - - private class EvaluatorDoubleInput implements Evaluator { - @Override - public void evaluateDouble(Row row, PointCollector collector) throws IOException { - collector.putDouble( - row.getTime(), ((Number) script.execute(null, row.getDouble(0))).doubleValue()); - } - - @Override - public void evaluateText(Row row, PointCollector collector) throws IOException { - collector.putString(row.getTime(), (String) script.execute(null, row.getDouble(0))); - } - - @Override - public void evaluateBoolean(Row row, PointCollector collector) throws IOException { - collector.putBoolean(row.getTime(), (Boolean) script.execute(null, row.getDouble(0))); - } - } - - private class EvaluatorStringInput implements Evaluator { - @Override - public void evaluateDouble(Row row, PointCollector collector) throws IOException { - collector.putDouble( - row.getTime(), ((Number) script.execute(null, row.getString(0))).doubleValue()); - } - - @Override - public void evaluateText(Row row, PointCollector collector) throws IOException { - collector.putString(row.getTime(), (String) script.execute(null, row.getString(0))); - } - - @Override - public void evaluateBoolean(Row row, PointCollector collector) throws IOException { - collector.putBoolean(row.getTime(), (Boolean) script.execute(null, row.getString(0))); - } - } - - private class EvaluatorBooleanInput implements Evaluator { - @Override - public void evaluateDouble(Row row, PointCollector collector) throws IOException { - collector.putDouble( - row.getTime(), ((Number) script.execute(null, row.getBoolean(0))).doubleValue()); - } - - @Override - public void evaluateText(Row row, PointCollector collector) throws IOException { - collector.putString(row.getTime(), (String) script.execute(null, row.getBoolean(0))); - } - - @Override - public void evaluateBoolean(Row row, PointCollector collector) throws IOException { - collector.putBoolean(row.getTime(), (Boolean) script.execute(null, row.getBoolean(0))); - } - } - - private class EvaluatorMulInput implements Evaluator { - - Object[] values = new Object[inputSeriesNumber]; - - @Override - public void evaluateDouble(Row row, PointCollector collector) - throws IOException, UDFInputSeriesDataTypeNotValidException { - getValues(row); - collector.putDouble(row.getTime(), ((Number) script.execute(null, values)).doubleValue()); - } - - @Override - public void evaluateText(Row row, PointCollector collector) - throws IOException, UDFInputSeriesDataTypeNotValidException { - getValues(row); - collector.putString(row.getTime(), (String) script.execute(null, values)); - } - - @Override - public void evaluateBoolean(Row row, PointCollector collector) - throws IOException, UDFInputSeriesDataTypeNotValidException { - getValues(row); - collector.putBoolean(row.getTime(), (Boolean) script.execute(null, values)); - } - - public void getValues(Row row) throws IOException, UDFInputSeriesDataTypeNotValidException { - for (int i = 0; i < inputSeriesNumber; i++) { - switch (inputDataType[i]) { - case INT32: - values[i] = row.getInt(i); - break; - case INT64: - values[i] = row.getLong(i); - break; - case FLOAT: - values[i] = row.getFloat(i); - break; - case DOUBLE: - values[i] = row.getDouble(i); - break; - case TEXT: - values[i] = row.getString(i); - break; - case BOOLEAN: - values[i] = row.getBoolean(i); - break; - case STRING: - case BLOB: - case DATE: - case TIMESTAMP: - default: - throw new UDFInputSeriesDataTypeNotValidException( - i, - UDFDataTypeTransformer.transformToUDFDataType(inputDataType[i]), - Type.INT32, - Type.INT64, - Type.FLOAT, - Type.DOUBLE, - Type.TEXT, - Type.BOOLEAN); - } - } - } - } -}
pom.xml+5 −11 modified@@ -57,9 +57,9 @@ <!-- This was the last version to support Java 8 --> <antlr4.version>4.9.3</antlr4.version> <!-- By default, the argLine is empty--> - <argLine /> + <argLine/> <awaitility.version>4.2.0</awaitility.version> - <boost.include.dir /> + <boost.include.dir/> <!-- This was the last version to support Java 8 --> <caffeine.version>2.9.3</caffeine.version> <cglib.version>3.3.0</cglib.version> @@ -69,7 +69,6 @@ <commons-codec.version>1.16.1</commons-codec.version> <commons-csv.version>1.10.0</commons-csv.version> <commons-io.version>2.14.0</commons-io.version> - <commons-jexl3.version>3.3</commons-jexl3.version> <commons-lang3.version>3.18.0</commons-lang3.version> <commons-math3.version>3.6.1</commons-math3.version> <commons-pool2.version>2.11.1</commons-pool2.version> @@ -165,7 +164,7 @@ <!-- This was the last version to support Java 8 --> <swagger.version>1.6.14</swagger.version> <thrift.exec-cmd.executable>chmod</thrift.exec-cmd.executable> - <thrift.exec.absolute.path /> + <thrift.exec.absolute.path/> <!-- Thrift 0.17.0 was the last version that could be used in Java 8 applications, However Thrift 0.17.0 has an invalid entry in the META-INF/MANIFEST.mf file. @@ -510,11 +509,6 @@ <artifactId>cglib</artifactId> <version>${cglib.version}</version> </dependency> - <dependency> - <groupId>org.apache.commons</groupId> - <artifactId>commons-jexl3</artifactId> - <version>${commons-jexl3.version}</version> - </dependency> <dependency> <groupId>com.github.luben</groupId> <artifactId>zstd-jni</artifactId> @@ -888,7 +882,7 @@ <importOrder> <order>org.apache.iotdb,,javax,java,\#</order> </importOrder> - <removeUnusedImports /> + <removeUnusedImports/> </java> <lineEndings>UNIX</lineEndings> </configuration> @@ -1126,7 +1120,7 @@ <phase>validate</phase> <configuration> <rules> - <dependencyConvergence /> + <dependencyConvergence/> </rules> </configuration> </execution>
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
9- github.com/advisories/GHSA-6w48-2g9j-v9q5ghsaADVISORY
- lists.apache.org/thread/vopgv6y2ccw403b0zv7rvojjrh7x1j5pghsavendor-advisoryWEB
- nvd.nist.gov/vuln/detail/CVE-2026-24713ghsaADVISORY
- www.openwall.com/lists/oss-security/2026/03/09/4ghsaWEB
- github.com/apache/iotdb/commit/8fbfddc5f83771f1b339c457de597fe877f686d2ghsaWEB
- github.com/apache/iotdb/compare/v1.3.6...v1.3.7ghsaWEB
- github.com/apache/iotdb/compare/v2.0.6...v2.0.7ghsaWEB
- github.com/apache/iotdb/releases/tag/v1.3.7ghsaWEB
- github.com/apache/iotdb/releases/tag/v2.0.7ghsaWEB
News mentions
0No linked articles in our index yet.