Bug #6961
64-bit octal printf may overflow internal buffer
100%
Description
There is a problem with printf family in 64bit libc.
[repro steps]
$ cat print.c #include <stdio.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
Unexpectedly, first output character is NUL.
additional evidence:
#include <stdio.h>
#include <string.h>
int
main(void)
{
int i;
char buf[32];
memset(buf, 'r', sizeof (buf));
sprintf(buf + 4, "%lo", ~0L);
for (i = 0; i < 32; i++) {
printf("%2d: %2x\n", i, buf[i]);
}
return (0);
}
output:
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
[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
p = bp = buf + MAXLLDIGS;
This allocates MAXLLDIGS (==21)
chars, but ~0 (64bit)
otcal is 1777777777777777777777
, 22 chars.
https://github.com/illumos/illumos-gate/blob/master/usr/src/lib/libc/port/print/doprnt.c#L1237-L1241
Finally,
buf[-1] is '1' buf[ 0] is '7' ... buf[20] is '7'
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):
%rbp-0xff0 char *p (declared at #L457) ... %rbp-0xfd8 ssize_t n (declared at #L661) %rbp-0xfd0 char buf[] (declared at #L509)
n = p - bp;
Thus n
becomes 22 and buf[-1]
becomes 0.
[solution]
I think, simply, we should set MAXLLDIGS
to 22.