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.