Project

General

Profile

Bug #6961

Updated by Kiichi Ozaki almost 5 years ago

There is a problem with printf family in 64bit libc. 

 *[repro steps]* 

 <pre> 
 $ cat print.c 
 #include <stdio.h> <stdin.h> 
 int main() 
 { 
     printf("%lo", ~0L); 
     return 0; 
 } 
 $ gcc -m64 print.c 
 $ ./a.out 
 777777777777777777777 
 $ ./a.out | od -Ax -tx1 
 000000 00 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 
 000010 37 37 37 37 37 37 
 000016 
 </pre> 

 Unexpectedly, first output character is NUL. 

 additional other evidence: 

 <pre><code class="c"> 
 #include <stdio.h> char b[32]; 
 #include <string.h> 

 int 
 main(void) 
 { 
         int i; 
         char buf[32]; 

         memset(buf, 'r', sizeof (buf)); 
         sprintf(buf + 4, sprintf(b, "%lo", ~0L); 

         for (i = 0; i < 32; i++) { 
                 printf("%2d: %2x\n", i, buf[i]); 
         } 

         return (0); 
 } 
 </code></pre> 

 output: <code>b[0]</code> becomes NUL. 

 <pre> 
  0: 72 
  1: 72 
  2: 72 
  3: 72 
  4:    0 
  5: 37 
  6: 37 
  7: 37 
  8: 37 
  9: 37 
 10: 37 
 11: 37 
 12: 37 
 13: 37 
 14: 37 
 15: 37 
 16: 37 
 17: 37 
 18: 37 
 19: 37 
 20: 37 
 21: 37 
 22: 37 
 23: 37 
 24: 37 
 25: 37 
 26:    0 
 27: 72 
 28: 72 
 29: 72 
 30: 72 
 31: 72 
 </pre> 

 *[environment]* 

 OpenIndiana (hipster) and maybe other illumos distributions. 

 *[cause]* 

 https://github.com/illumos/illumos-gate/blob/master/usr/src/lib/libc/port/print/doprnt.c#L1213 
 https://github.com/illumos/illumos-gate/blob/master/usr/src/lib/libc/port/print/print.h#L66 

 <pre><code class="c">p = bp = buf + MAXLLDIGS;</code></pre> 

 This allocates <code>MAXLLDIGS (==21)</code> chars, but <code>~0 (64bit)</code> otcal is <code>1777777777777777777777</code>, 22 chars. 

 https://github.com/illumos/illumos-gate/blob/master/usr/src/lib/libc/port/print/doprnt.c#L1237-L1241 

 Finally, 

 <pre> 
 buf[-1] is '1' 
 buf[ 0] is '7' 
 ... 
 buf[20] is '7' 
 </pre> 

 and bp points &buf[-1]. This is out-of-bound error. 

 https://github.com/illumos/illumos-gate/blob/master/usr/src/lib/libc/port/print/doprnt.c#L2098 

 Stack layout is maybe below (OpenIndiana, 64bit libc): 

 <pre> 
 %rbp-0xff0    char     *p       (declared at #L457) 
 ... 
 %rbp-0xfd8    ssize_t n       (declared at #L661) 
 %rbp-0xfd0    char      buf[] (declared at #L509) 
 </pre> 

 <pre><code class="c"> 
 n = p - bp; 
 </code></pre> 

 Thus <code>n</code> becomes 22 and <code>buf[-1]</code> becomes 0. 

 *[solution]* 

 I think, simply, we should set <code>MAXLLDIGS</code> to 22.

Back