<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - __dfsw_strncasecmp is implemented incorrectly"
   href="https://bugs.llvm.org/show_bug.cgi?id=38369">38369</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>__dfsw_strncasecmp is implemented incorrectly
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>compiler-rt
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>6.0
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>Linux
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>dfsan
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>huhong789@gmail.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org
          </td>
        </tr></table>
      <p>
        <div>
        <pre>The implementation of __dfsw_strncasecmp in
compiler-rt/lib/dfsan/dfsan_custom.cc has a bug. 

Here is the test code. 

/* test.c */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main() {
    char * s1 = "ABC";
    char * s2 = "abc";
    size_t n = 2;

    if (strncasecmp(s1, s2, n)) {
        printf("%s != %s for first %lu bytes\n", s1, s2, n);
    } else {
        printf("%s == %s for first %lu bytes\n", s1, s2, n);
    }

    return 0;
}

First compile with clang
$ clang test.c -o test-clang
$ ./test-clang 
ABC == abc for first 2 bytes

Then compile with clang + dfsan 
$ clang test.c -fsanitize=dataflow -o test-dfsan
$ ./test-dfsan
ABC != abc for first 2 bytes

The source code of __dfsw_strncasecmp is as follows:

 200 SANITIZER_INTERFACE_ATTRIBUTE int
 201 __dfsw_strncasecmp(const char *s1, const char *s2, size_t n,
 202                    dfsan_label s1_label, dfsan_label s2_label,
 203                    dfsan_label n_label, dfsan_label *ret_label) {
 204   if (n == 0) {
 205     *ret_label = 0;
 206     return 0;
 207   }
 208
 209   for (size_t i = 0;; ++i) {
 210     if (tolower(s1[i]) != tolower(s2[i]) || s1[i] == 0 || s2[i] == 0 ||
 211         i == n-1) {
 212       if (flags().strict_data_dependencies) {
 213         *ret_label = 0;
 214       } else {
 215         *ret_label = dfsan_union(dfsan_read_label(s1, i + 1),
 216                                  dfsan_read_label(s2, i + 1));
 217       }
 218       return s1[i] - s2[i];
 219     }
 220   }
 221   return 0;
 222 }

When i == 1, condition in line 211 is matched. The execution finally reaches
line 218, which only compares s1[1] and s2[1], instead of tolower(s1[1])
tolower(s2[1]).

Possible fix: 

Use tolower in line 218.</pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>