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 <[EMAIL PROTECTED]>):
$ /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 ------------------