summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--tests/custom/99_bugs/42_types_binary_string_comparison28
-rw-r--r--types.c11
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 --
diff --git a/types.c b/types.c
index 226c874..c9472f7 100644
--- a/types.c
+++ b/types.c
@@ -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... */