title: How does strncmp using SSE 4.2 avoid reading beyond the page boundaries when loading 16 bytes?
body: <p>glibc now uses SSE 4.2 to optimize <code>strncmp</code>:</p>
  <ul>
  <li><a href="https://github.com/lattera/glibc/blob/master/sysdeps/x86_64/multiarch/strcmp-sse42.S" rel="nofollow noreferrer">https://github.com/lattera/glibc/blob/master/sysdeps/x86_64/multiarch/strcmp-sse42.S</a></li>
  <li><a href="https://www.strchr.com/strcmp_and_strlen_using_sse_4.2" rel="nofollow noreferrer">https://www.strchr.com/strcmp_and_strlen_using_sse_4.2</a></li>
  </ul>
  <p>This can be seen in a debugger:</p>
  <pre><code>   0xf7f20218 &lt;__strncmp_sse4_2+40&gt;    movdqu xmm2, xmmword ptr [edx]
     0xf7f2021c &lt;__strncmp_sse4_2+44&gt;    mov    ecx, eax
   ► 0xf7f2021e &lt;__strncmp_sse4_2+46&gt;    and    ecx, 0xfff
     0xf7f20224 &lt;__strncmp_sse4_2+52&gt;    cmp    ecx, 0xff0
     0xf7f2022a &lt;__strncmp_sse4_2+58&gt;    ja     __strncmp_sse4_2+125                    &lt;__strncmp_sse4_2+125&gt;
  </code></pre>
  <p>I'm not steeped in SSE 4.2 for strings, but my understanding is that it allows it to compare up to 16 bytes at a time.  The <code>movdqu xmm2, xmmword ptr [edx]</code> loads 16 bytes from one of the strings.</p>
  <p>My question is: If a short string (say 3 bytes) is at the end of a page, with the NULL termination within the page limits, but some of the remaining 13 bytes outside of the page, couldn't that cause a segfault, since we're now trying to load beyond the page we have access to?</p>
  <p>This question came up in working on an emulator, which trapped an unconstrained access (that is, a read of memory which my application never wrote to):</p>
  <pre><code>strncmp(0x8064dd8, 0x7ffeff48, 0x4)
  WARNING Filling memory at 0x7ffeff60 with 4 unconstrained bytes referenced from 0x818ba90 (strncmp+0x0 in libc.so.6 (0x8ba90))
  </code></pre>
  <p>This is perplexing, because:</p>
  <ul>
  <li>Why is strncmp of <strong>max 4 bytes</strong> starting at 0x7ffeff48 reading values from 0x7ffeff60</li>
  </ul>
  <p>That is, it doesn't seem to be a bug in the caller, but rather unexpected behavior by strncmp.  Debugging strncmp led me to the SSE 4.2, which explains partially why it's reading beyond the limit set by <code>n</code>: it simply uses SSE 4.2 to load many bytes at once, even if it doesn't need them at all.</p>
  <p>Questions:</p>
  <ul>
  <li>Is this correct? Does <code>strncmp_sse4_2</code> read more than <code>n</code> bytes?</li>
  <li>Even if it does: Doing 16 bytes at a time should stop at 0x7ffeff58.  Why does it read till 0x7ffeff60?</li>
  <li>If so, how does this not potentially cause a page fault?</li>
  <li>If so, how do we tell distinguish acceptable read of uninitialized data from cases indicating bugs? E.g. how would Valgrind avoid reporting this as an uninitialized read?</li>
  </ul>