[dfsan] Fix a bug in strcasecmp() and strncasecmp(): Compare the lowercase versions...
authorSam Kerner <skerner@chromium.org>
Tue, 21 Apr 2020 00:13:00 +0000 (17:13 -0700)
committerMatt Morehouse <mascasa@google.com>
Tue, 21 Apr 2020 00:13:40 +0000 (17:13 -0700)
Summary:
Resolves this bug:

  https://bugs.llvm.org/show_bug.cgi?id=38369

Reviewers: morehouse, pcc

Reviewed By: morehouse

Subscribers: #sanitizers

Tags: #sanitizers

Differential Revision: https://reviews.llvm.org/D78490

compiler-rt/lib/dfsan/dfsan_custom.cpp
compiler-rt/test/dfsan/custom.cpp

index 78790a8..1acd2d4 100644 (file)
@@ -157,14 +157,17 @@ SANITIZER_INTERFACE_ATTRIBUTE int
 __dfsw_strcasecmp(const char *s1, const char *s2, dfsan_label s1_label,
                   dfsan_label s2_label, dfsan_label *ret_label) {
   for (size_t i = 0;; ++i) {
-    if (tolower(s1[i]) != tolower(s2[i]) || s1[i] == 0 || s2[i] == 0) {
+    char s1_lower = tolower(s1[i]);
+    char s2_lower = tolower(s2[i]);
+
+    if (s1_lower != s2_lower || s1[i] == 0 || s2[i] == 0) {
       if (flags().strict_data_dependencies) {
         *ret_label = 0;
       } else {
         *ret_label = dfsan_union(dfsan_read_label(s1, i + 1),
                                  dfsan_read_label(s2, i + 1));
       }
-      return s1[i] - s2[i];
+      return s1_lower - s2_lower;
     }
   }
   return 0;
@@ -212,15 +215,17 @@ __dfsw_strncasecmp(const char *s1, const char *s2, size_t n,
   }
 
   for (size_t i = 0;; ++i) {
-    if (tolower(s1[i]) != tolower(s2[i]) || s1[i] == 0 || s2[i] == 0 ||
-        i == n - 1) {
+    char s1_lower = tolower(s1[i]);
+    char s2_lower = tolower(s2[i]);
+
+    if (s1_lower != s2_lower || s1[i] == 0 || s2[i] == 0 || i == n - 1) {
       if (flags().strict_data_dependencies) {
         *ret_label = 0;
       } else {
         *ret_label = dfsan_union(dfsan_read_label(s1, i + 1),
                                  dfsan_read_label(s2, i + 1));
       }
-      return s1[i] - s2[i];
+      return s1_lower - s2_lower;
     }
   }
   return 0;
index 96c897a..22dc395 100644 (file)
@@ -207,6 +207,19 @@ void test_strcasecmp() {
 #else
   ASSERT_LABEL(rv, dfsan_union(i_label, j_label));
 #endif
+
+  char s1[] = "AbZ";
+  char s2[] = "aBy";
+  dfsan_set_label(i_label, &s1[2], 1);
+  dfsan_set_label(j_label, &s2[2], 1);
+
+  rv = strcasecmp(s1, s2);
+  assert(rv > 0); // 'Z' > 'y'
+#ifdef STRICT_DATA_DEPENDENCIES
+  ASSERT_ZERO_LABEL(rv);
+#else
+  ASSERT_LABEL(rv, dfsan_union(i_label, j_label));
+#endif
 }
 
 void test_strncasecmp() {
@@ -225,6 +238,31 @@ void test_strncasecmp() {
   rv = strncasecmp(str1, str2, 3);
   assert(rv == 0);
   ASSERT_ZERO_LABEL(rv);
+
+  char s1[] = "AbZ";
+  char s2[] = "aBy";
+  dfsan_set_label(i_label, &s1[2], 1);
+  dfsan_set_label(j_label, &s2[2], 1);
+
+  rv = strncasecmp(s1, s2, 0);
+  assert(rv == 0); // Compare zero chars.
+  ASSERT_ZERO_LABEL(rv);
+
+  rv = strncasecmp(s1, s2, 1);
+  assert(rv == 0); // 'A' == 'a'
+  ASSERT_ZERO_LABEL(rv);
+
+  rv = strncasecmp(s1, s2, 2);
+  assert(rv == 0); // 'b' == 'B'
+  ASSERT_ZERO_LABEL(rv);
+
+  rv = strncasecmp(s1, s2, 3);
+  assert(rv > 0); // 'Z' > 'y'
+#ifdef STRICT_DATA_DEPENDENCIES
+  ASSERT_ZERO_LABEL(rv);
+#else
+  ASSERT_LABEL(rv, dfsan_union(i_label, j_label));
+#endif
 }
 
 void test_strchr() {