title: sscanf linux kernel differs from sscanf glibc
body: <p>Running the following code (<code>make runtest</code>) on my machine (<code>4.6.4-1-ARCH</code>)</p>
  
  <pre><code>/* scanf userland &amp; kernelspace test */
  
  #if __KERNEL__
  
  #include &lt;linux/kernel.h&gt;
  #include &lt;linux/module.h&gt;
  #include &lt;linux/string.h&gt;
  
  MODULE_AUTHOR("Enteee (duckpond.ch) ");
  MODULE_DESCRIPTION("scanf test");
  MODULE_LICENSE("GPL");
  MODULE_ALIAS("scanf_test");
  
  #else
  
  #include &lt;stdio.h&gt;
  #include &lt;string.h&gt;
  #define printk printf
  
  #endif
  
  void test(void){
      int ret = 0;
      char fp[20] = { 0 };
  
      memset(fp, 0xaa, sizeof(fp));
      printk("init, ret = %d fp = "
              "%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx"
              "%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx"
              "%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx"
              "%2.2hhx%2.2hhx, "
              // overflow prints (hacky)
              "after fp = "
              "%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx, "
              "before fp = "
              "%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx"
              "\n",
              ret,
              (fp)[0],  (fp)[1],  (fp)[2],  (fp)[3],  (fp)[4],  (fp)[5],
              (fp)[6],  (fp)[7],  (fp)[8],  (fp)[9],  (fp)[10], (fp)[11],
              (fp)[12], (fp)[13], (fp)[14], (fp)[15], (fp)[16], (fp)[17],
              (fp)[18], (fp)[19],
              // overflow
              (fp)[20], (fp)[21], (fp)[22], (fp)[23], (fp)[24], (fp)[25],
              (fp)[-1], (fp)[-2], (fp)[-3], (fp)[-4], (fp)[-5], (fp)[-6]
            );
  
      ret = sscanf("aabb", "%2hhx%2hhx", &amp;fp[0], &amp;fp[1]);
      printk("ret = %d fp = %2.2hhx%2.2hhx\n", ret, fp[0], fp[1]);
  
      ret = sscanf(
              "ffffffffffffffffffffffffffffffffffffffff", 
              "%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx"
              "%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx"
              "%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx"
              "%2hhx%2hhx",
              &amp;(fp)[0],  &amp;(fp)[1],  &amp;(fp)[2],  &amp;(fp)[3],  &amp;(fp)[4],  &amp;(fp)[5],
              &amp;(fp)[6],  &amp;(fp)[7],  &amp;(fp)[8],  &amp;(fp)[9],  &amp;(fp)[10], &amp;(fp)[11],
              &amp;(fp)[12], &amp;(fp)[13], &amp;(fp)[14], &amp;(fp)[15], &amp;(fp)[16], &amp;(fp)[17],
              &amp;(fp)[18], &amp;(fp)[19]
              );
  
      printk("ret = %d fp = "
              "%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx"
              "%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx"
              "%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx"
              "%2.2hhx%2.2hhx, "
              // overflow prints (hacky)
              "after fp = "
              "%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx, "
              "before fp = "
              "%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx"
              "\n",
              ret,
              (fp)[0],  (fp)[1],  (fp)[2],  (fp)[3],  (fp)[4],  (fp)[5],
              (fp)[6],  (fp)[7],  (fp)[8],  (fp)[9],  (fp)[10], (fp)[11],
              (fp)[12], (fp)[13], (fp)[14], (fp)[15], (fp)[16], (fp)[17],
              (fp)[18], (fp)[19],
              (fp)[20], (fp)[21], (fp)[22], (fp)[23], (fp)[24], (fp)[25],
              (fp)[-1], (fp)[-2], (fp)[-3], (fp)[-4], (fp)[-5], (fp)[-6]
            );
  }
  
  #ifndef __KERNEL__
  
  int main(void){
      test();
      return 0;
  }
  
  #else
  
  static int __init test_init(void) {
      test();
      return 0;
  }
  
  static void __exit test_exit(void) {
  }
  
  module_init(test_init);
  module_exit(test_exit);
  
  #endif
  </code></pre>
  
  <p>yields:</p>
  
  <pre><code>=== user space ===
  init, ret = 0 fp = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, after fp = 65005f5f7664, before fp = 000000000000
  ret = 2 fp = aabb
  ret = 20 fp = ffffffffffffffffffffffffffffffffffffffff, after fp = 65005f5f7664, before fp = 000000000000
  === kernel space ===
  [386177.161037] init, ret = 0 fp = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, after fp = baae0dbc0000, before fp = bc0daebaffff
  [386177.161044] ret = 2 fp = aabb
  [386177.161061] ret = 20 fp = 000000000000000000000000ffffffffffffffff, after fp = baae0dbc0000, before fp = bc0daebaffff
  </code></pre>
  
  <p>The <a href="https://gist.github.com/Enteee/7ceec987924d3446c384a449a085ee8d" rel="nofollow">test.c</a> basically reads <code>ffffffffffffffffffffffffffffffffffffffff</code> to <code>fp</code> using <code>sscanf</code> with a sequence of <code>%2hhx</code> format specifiers. After that, it prints <code>fp</code> using <code>printf</code> / <code>printk</code> with a sequence of <code>%2.2hhx</code> format specifiers.</p>
  
  <p>Can somebody explain me why <code>fp</code> is no the same when read with <a href="https://github.molgen.mpg.de/git-mirror/glibc/blob/20003c49884422da7ffbc459cdeee768a6fee07b/stdio-common/scanf.c" rel="nofollow">glibc sscanf</a> and <a href="http://lxr.free-electrons.com/source/lib/vsprintf.c#L2596" rel="nofollow">linux sscanf</a>. In addition, why is the <code>aabb</code>-test working just fine?</p>
  
  <p>I already checked the <a href="http://lxr.free-electrons.com/source/lib/vsprintf.c#L2596" rel="nofollow">linux sscanf</a> impelmentation and from what I can see it should be similar to the <a href="https://github.molgen.mpg.de/git-mirror/glibc/blob/20003c49884422da7ffbc459cdeee768a6fee07b/stdio-common/scanf.c" rel="nofollow">glibc sscanf</a>.</p>
  
  <p>I do think I'm missing the obvious here..</p>
  
  <hr>
  
  <p>Notes:</p>
  
  <ul>
  <li>the gist containing the Makefile can be found <a href="https://gist.github.com/Enteee/7ceec987924d3446c384a449a085ee8d" rel="nofollow">here</a></li>
  <li>this is just an example, please don't tell me that this is an ugly implementation. There are even 24 invalid reads! thx, I'm aware of that.</li>
  </ul>