[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
portability note about 'printf'
From: |
Bruno Haible |
Subject: |
portability note about 'printf' |
Date: |
Tue, 24 Apr 2007 00:40:30 +0200 |
User-agent: |
KMail/1.5.4 |
The autoconf manual mentions two portability problem of the 'printf' command.
But there is a third one: a buffer overflow that crashes /bin/printf of
Solaris 9 and Solaris 10. Example (originally reported by
Arto C. Nirkko <address@hidden>):
$ /bin/printf '%010000x' 123
Segmentation fault
$ truss -u libc /bin/printf '%010000x' 123
execve("/usr/bin/printf", 0xFFBFF20C, 0xFFBFF21C) argc = 3
resolvepath("/usr/bin/printf", "/usr/bin/printf", 1023) = 15
resolvepath("/usr/lib/ld.so.1", "/usr/lib/ld.so.1", 1023) = 16
stat("/usr/bin/printf", 0xFFBFEFE0) = 0
open("/var/ld/ld.config", O_RDONLY) Err#2 ENOENT
stat("/usr/lib/libgen.so.1", 0xFFBFEAE8) = 0
resolvepath("/usr/lib/libgen.so.1", "/usr/lib/libgen.so.1", 1023) = 20
open("/usr/lib/libgen.so.1", O_RDONLY) = 3
mmap(0x00010000, 8192, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_ALIGN, 3, 0) =
0xFF3A0000
mmap(0x00010000, 98304, PROT_NONE,
MAP_PRIVATE|MAP_NORESERVE|MAP_ANON|MAP_ALIGN, -1, 0) = 0xFF380000
mmap(0xFF380000, 22677, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) =
0xFF380000
mmap(0xFF396000, 2343, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED,
3, 24576) = 0xFF396000
munmap(0xFF386000, 65536) = 0
memcntl(0xFF380000, 6304, MC_ADVISE, MADV_WILLNEED, 0, 0) = 0
close(3) = 0
stat("/usr/lib/libc.so.1", 0xFFBFEAE8) = 0
resolvepath("/usr/lib/libc.so.1", "/usr/lib/libc.so.1", 1023) = 18
open("/usr/lib/libc.so.1", O_RDONLY) = 3
mmap(0xFF3A0000, 8192, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) =
0xFF3A0000
mmap(0x00010000, 794624, PROT_NONE,
MAP_PRIVATE|MAP_NORESERVE|MAP_ANON|MAP_ALIGN, -1, 0) = 0xFF280000
mmap(0xFF280000, 688972, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) =
0xFF280000
mmap(0xFF33A000, 24000, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED,
3, 696320) = 0xFF33A000
mmap(0xFF340000, 6304, PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_FIXED|MAP_ANON, -1, 0) = 0xFF340000
munmap(0xFF32A000, 65536) = 0
memcntl(0xFF280000, 115592, MC_ADVISE, MADV_WILLNEED, 0, 0) = 0
close(3) = 0
stat("/usr/lib/libdl.so.1", 0xFFBFEAE8) = 0
resolvepath("/usr/lib/libdl.so.1", "/usr/lib/libdl.so.1", 1023) = 19
open("/usr/lib/libdl.so.1", O_RDONLY) = 3
mmap(0xFF3A0000, 8192, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) =
0xFF3A0000
mmap(0x00002000, 8192, PROT_NONE, MAP_PRIVATE|MAP_NORESERVE|MAP_ANON|MAP_ALIGN,
-1, 0) = 0xFF3FA000
mmap(0xFF3FA000, 1894, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED,
3, 0) = 0xFF3FA000
close(3) = 0
stat("/usr/platform/SUNW,Sun-Fire-280R/lib/libc_psr.so.1", 0xFFBFE8D8) = 0
resolvepath("/usr/platform/SUNW,Sun-Fire-280R/lib/libc_psr.so.1",
"/usr/platform/sun4u-us3/lib/libc_psr.so.1", 1023) = 41
open("/usr/platform/SUNW,Sun-Fire-280R/lib/libc_psr.so.1", O_RDONLY) = 3
mmap(0xFF3A0000, 8192, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) =
0xFF3A0000
close(3) = 0
mmap(0x00000000, 8192, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANON,
-1, 0) = 0xFF370000
-> libc:atexit(0xff3bfaac, 0x22800, 0x0, 0x0)
<- libc:atexit() = 0
-> libc:atexit(0x12424, 0x22800, 0x0, 0x0)
<- libc:atexit() = 0
-> libc:setlocale(0x6, 0x124ac, 0x0, 0x0)
<- libc:setlocale() = 0xff325e8e
-> libc:textdomain(0x124b0, 0x124ac, 0x0, 0x0)
brk(0x00022CB8) = 0
brk(0x00024CB8) = 0
<- libc:textdomain() = 0x234d0
-> libc:strcmp(0xffbff418, 0x124c0, 0x0, 0x0)
<- libc:strcmp() = -8
-> libc:strlen(0xffbff418, 0x124c4, 0x0, 0x0)
<- libc:strlen() = 8
-> libc:malloc(0x801, 0xffbff424, 0x313233, 0x7efefeff)
<- libc:malloc() = 0x23ad0
-> libc:malloc(0x801, 0xffbff424, 0x313233, 0x7efefeff)
<- libc:malloc() = 0x242e0
-> libc:strdup(0xffbff418, 0x0, 0x0, 0x0)
<- libc:strdup() = 0x234e8
-> libc:mbtowc(0xffbff134, 0xffbff418, 0x1, 0x0)
-> libc:__mbtowc_sb(0xff33f728, 0xffbff134, 0xffbff418, 0x1)
<- libc:mbtowc() = 1
-> libc:wctomb(0x234e8, 0x25, 0xffbff418, 0x1)
-> libc:__wctomb_sb(0xff33f728, 0x234e8, 0x25, 0x1)
<- libc:wctomb() = 1
-> libc:mbtowc(0xffbff134, 0xffbff419, 0x1, 0x1)
-> libc:__mbtowc_sb(0xff33f728, 0xffbff134, 0xffbff419, 0x1)
<- libc:mbtowc() = 1
-> libc:wctomb(0x234e9, 0x30, 0xffbff419, 0x1)
-> libc:__wctomb_sb(0xff33f728, 0x234e9, 0x30, 0x1)
<- libc:wctomb() = 1
-> libc:mbtowc(0xffbff134, 0xffbff41a, 0x1, 0x1)
-> libc:__mbtowc_sb(0xff33f728, 0xffbff134, 0xffbff41a, 0x1)
<- libc:mbtowc() = 1
-> libc:wctomb(0x234ea, 0x31, 0xffbff41a, 0x1)
-> libc:__wctomb_sb(0xff33f728, 0x234ea, 0x31, 0x1)
<- libc:wctomb() = 1
-> libc:mbtowc(0xffbff134, 0xffbff41b, 0x1, 0x1)
-> libc:__mbtowc_sb(0xff33f728, 0xffbff134, 0xffbff41b, 0x1)
<- libc:mbtowc() = 1
-> libc:wctomb(0x234eb, 0x30, 0xffbff41b, 0x1)
-> libc:__wctomb_sb(0xff33f728, 0x234eb, 0x30, 0x1)
<- libc:wctomb() = 1
-> libc:mbtowc(0xffbff134, 0xffbff41c, 0x1, 0x1)
-> libc:__mbtowc_sb(0xff33f728, 0xffbff134, 0xffbff41c, 0x1)
<- libc:mbtowc() = 1
-> libc:wctomb(0x234ec, 0x30, 0xffbff41c, 0x1)
-> libc:__wctomb_sb(0xff33f728, 0x234ec, 0x30, 0x1)
<- libc:wctomb() = 1
-> libc:mbtowc(0xffbff134, 0xffbff41d, 0x1, 0x1)
-> libc:__mbtowc_sb(0xff33f728, 0xffbff134, 0xffbff41d, 0x1)
<- libc:mbtowc() = 1
-> libc:wctomb(0x234ed, 0x30, 0xffbff41d, 0x1)
-> libc:__wctomb_sb(0xff33f728, 0x234ed, 0x30, 0x1)
<- libc:wctomb() = 1
-> libc:mbtowc(0xffbff134, 0xffbff41e, 0x1, 0x1)
-> libc:__mbtowc_sb(0xff33f728, 0xffbff134, 0xffbff41e, 0x1)
<- libc:mbtowc() = 1
-> libc:wctomb(0x234ee, 0x30, 0xffbff41e, 0x1)
-> libc:__wctomb_sb(0xff33f728, 0x234ee, 0x30, 0x1)
<- libc:wctomb() = 1
-> libc:mbtowc(0xffbff134, 0xffbff41f, 0x1, 0x1)
-> libc:__mbtowc_sb(0xff33f728, 0xffbff134, 0xffbff41f, 0x1)
<- libc:mbtowc() = 1
-> libc:wctomb(0x234ef, 0x78, 0xffbff41f, 0x1)
-> libc:__wctomb_sb(0xff33f728, 0x234ef, 0x78, 0x1)
<- libc:wctomb() = 1
-> libc:mbtowc(0xffbff134, 0x234e8, 0x1, 0x1)
-> libc:__mbtowc_sb(0xff33f728, 0xffbff134, 0x234e8, 0x1)
<- libc:mbtowc() = 1
-> libc:strtol(0x234e9, 0xffbff134, 0x0, 0x1)
<- libc:strtol() = 4096
-> libc:strtoul(0xffbff421, 0xffbff134, 0x0, 0x1)
<- libc:strtoul() = 123
-> libc:realloc(0x242e0, 0x1001, 0x0, 0x0)
brk(0x00024CB8) = 0
brk(0x00024CB8) = 0
brk(0x00026CB8) = 0
<- libc:realloc() = 0x242e0
-> libc:vsprintf(0x242e0, 0x234e8, 0xffbff100, 0x242d8)
<- libc:vsprintf() = 10000
-> libc:realloc(0x23ad0, 0x2710, 0x0, 0x0)
Incurred fault #6, FLTBOUNDS %pc = 0xFF2C1E7C
siginfo: SIGSEGV SEGV_MAPERR addr=0x30328320
Received signal #11, SIGSEGV [default]
siginfo: SIGSEGV SEGV_MAPERR addr=0x30328320
You can see that vsprintf() is used to write the format directive into a
buffer that has been allocated with size 2049 and reallocated to size 4097.
Here's a proposed doc patch:
*** autoconf.texi.bak 2007-04-24 00:31:05.000000000 +0200
--- autoconf.texi 2007-04-24 00:33:13.000000000 +0200
***************
*** 12700,12705 ****
--- 12700,12712 ----
bash: printf: `%': missing format character
@end example
+ A format directive that produces more than 2048 bytes of output crashes
+ the @command{printf} of Solaris 10:
+
+ @example
+ printf %010000x 123
+ @end example
+
@item @command{read}
@c ------------------
- portability note about 'printf',
Bruno Haible <=