This is an automated email from the ASF dual-hosted git repository. github-merge-queue[bot] pushed a commit to branch gh-readonly-queue/dev/pr-12717-3c6e5851cb31b91395b6d60f89e81482157617b4 in repository https://gitbox.apache.org/repos/asf/seatunnel.git
commit c3d30aff7c61bd038f906f0ba7d03211dd7ad3ac Author: Jast <[email protected]> AuthorDate: Thu Oct 22 13:41:01 2026 +0000 [Fix][Transform-V2] Reject array input for the MD5 function (#12717) Co-authored-by: jast <[email protected]> --- .../transform/sql/zeta/functions/StringFunction.java | 11 +++++++++-- .../sql/zeta/functions/StringFunctionTest.java | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/seatunnel-transforms-v2/src/main/java/org/apache/seatunnel/transform/sql/zeta/functions/StringFunction.java b/seatunnel-transforms-v2/src/main/java/org/apache/seatunnel/transform/sql/zeta/functions/StringFunction.java index ace22df5de..097df4d2f6 100644 --- a/seatunnel-transforms-v2/src/main/java/org/apache/seatunnel/transform/sql/zeta/functions/StringFunction.java +++ b/seatunnel-transforms-v2/src/main/java/org/apache/seatunnel/transform/sql/zeta/functions/StringFunction.java @@ -842,8 +842,10 @@ public class StringFunction { * string, matching Hive's {@code md5(string|binary)}. * * <p>String inputs are hashed as UTF-8 bytes; binary (byte[]) inputs are hashed as raw bytes. - * Non-string, non-binary values are converted via {@code toString()} and hashed as UTF-8, - * mirroring Hive's implicit cast to string. + * Non-string, non-binary scalar values are converted via {@code toString()} and hashed as + * UTF-8, mirroring Hive's implicit cast to string. Array values are rejected: SeaTunnel array + * columns are boxed arrays (e.g. {@code Byte[]}), which would otherwise be hashed as their JVM + * identity string, producing a nondeterministic value unrelated to the data. * * @param args list containing a single string, binary, or implicitly castable value * @return 32-char lowercase hex MD5 digest, or null if the input is null @@ -861,6 +863,11 @@ public class StringFunction { if (arg instanceof byte[]) { return Hashing.md5().hashBytes((byte[]) arg).toString(); } + if (arg.getClass().isArray()) { + throw new IllegalArgumentException( + "MD5 expects a scalar string or binary argument, unsupported array type: " + + arg.getClass().getName()); + } return Hashing.md5().hashString(arg.toString(), StandardCharsets.UTF_8).toString(); } } diff --git a/seatunnel-transforms-v2/src/test/java/org/apache/seatunnel/transform/sql/zeta/functions/StringFunctionTest.java b/seatunnel-transforms-v2/src/test/java/org/apache/seatunnel/transform/sql/zeta/functions/StringFunctionTest.java index 21a713d4d8..112bf52f4a 100644 --- a/seatunnel-transforms-v2/src/test/java/org/apache/seatunnel/transform/sql/zeta/functions/StringFunctionTest.java +++ b/seatunnel-transforms-v2/src/test/java/org/apache/seatunnel/transform/sql/zeta/functions/StringFunctionTest.java @@ -327,6 +327,25 @@ public class StringFunctionTest { Assertions.assertEquals("900150983cd24fb0d6963f7d28e17f72", StringFunction.md5(args)); } + @Test + public void testMd5RejectsArrayInput() { + // SeaTunnel ARRAY<BYTE> columns are boxed Byte[] at runtime, which must not silently be + // hashed as their JVM identity string + List<Object> args = new ArrayList<>(); + args.add(new Byte[] {97, 98, 99}); + IllegalArgumentException boxedArray = + Assertions.assertThrows( + IllegalArgumentException.class, () -> StringFunction.md5(args)); + Assertions.assertEquals( + "MD5 expects a scalar string or binary argument, unsupported array type: " + + "[Ljava.lang.Byte;", + boxedArray.getMessage()); + + args.clear(); + args.add(new String[] {"a", "b"}); + Assertions.assertThrows(IllegalArgumentException.class, () -> StringFunction.md5(args)); + } + @Test public void testToBase64BytesInputRejectsCharset() { IllegalArgumentException bytesWithCharset =
