diff options
author | Jo-Philipp Wich <jo@mein.io> | 2023-08-22 11:54:40 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-08-22 11:54:40 +0200 |
commit | ce39326dbc26a1b9cfe063f8961da61013fd1bd1 (patch) | |
tree | fb5736feee7dce6e15f38d79c2fcfaf81dcd9ebc | |
parent | 5d265bd52f40dd94671783148e4e6ff068c8153a (diff) | |
parent | 8f852eaf9c870de2078649410f029e0846117de2 (diff) |
Merge pull request #168 from jow-/fix-binary-string-compare
types: improve comparison reliability of binary strings
-rw-r--r-- | tests/custom/99_bugs/42_types_binary_string_comparison | 28 | ||||
-rw-r--r-- | types.c | 11 |
2 files changed, 38 insertions, 1 deletions
diff --git a/tests/custom/99_bugs/42_types_binary_string_comparison b/tests/custom/99_bugs/42_types_binary_string_comparison new file mode 100644 index 0000000..bc566c6 --- /dev/null +++ b/tests/custom/99_bugs/42_types_binary_string_comparison @@ -0,0 +1,28 @@ +When comparing strings with embedded null bytes, ensure that the comparison +takes the entire string length into account. + +-- Testcase -- +printf("%.J\n", [ + "" == "\u0000", + "" < "\u0000", + "" > "\u0000", + "foo\u0000bar" == "foo\u0000baz", + "foo\u0000bar" < "foo\u0000baz", + "foo\u0000bar" > "foo\u0000baz", +]); +-- End -- + +-- Args -- +-R +-- End -- + +-- Expect stdout -- +[ + false, + true, + false, + false, + true, + false +] +-- End -- @@ -2006,7 +2006,16 @@ ucv_compare(int how, uc_value_t *v1, uc_value_t *v2, int *deltap) /* ... otherwise if both operands are strings, compare bytewise ... */ else if (t1 == UC_STRING && t2 == UC_STRING) { - delta = strcmp(ucv_string_get(v1), ucv_string_get(v2)); + u1 = ucv_string_length(v1); + u2 = ucv_string_length(v2); + + delta = memcmp(ucv_string_get(v1), ucv_string_get(v2), + (u1 < u2) ? u1 : u2); + + if (delta == 0 && u1 < u2) + delta = -1; + else if (delta == 0 && u1 > u2) + delta = 1; } /* handle non-string cases... */ |