[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#553206: libc6: Similar fail for %llu on 0x200000-long string of '9's



OK, I've now built glibc (overnight - it took nearly four hours) in
debug and caught the crash in gdb.  We're in ADDW (L_('\0')), right
after the comment /* Convert the number.  */ <quote src="gdb">

(gdb) run
Starting program: /disk/home/eddy/work/mine/toys/sscanferange 

Program received signal SIGSEGV, Segmentation fault.
0xb7ee1e81 in _IO_vfscanf_internal (s=0xbfdff2dc, format=0x80485a0 "%llu", argptr=0xbfdff3a8 "¸óÿ¿", errp=0x0) at vfscanf.c:1760
(gdb) p wpsize
$1 = 2097152
(gdb) p wpmax
$2 = 4194304
(gdb) p old
$3 = <value optimized out>
(gdb) p wp
$4 = 0xbf5fef70 <Address 0xbf5fef70 out of bounds>
(gdb) p/x wpmax
$5 = 0x400000

</quote> OK, that sounds like it's probably the problem.  Perhaps
alloca can't handle 4MiB allocations !  Unfortunately, its return, in
this case, isn't the NULL checked for.  Indeed, ADDW's check for NULL
is pointless - alloca() is not specified to do so:
<quote src="man alloca">

RETURN VALUE
       The alloca() function returns a pointer to the beginning of the
       allocated space.  If the allocation causes stack overflow,
       program behavior is undefined.

</quote>

It's also worth noting that, by the time it comes to this call to
alloca, the code has previously alloca()-ed 0x3fff00 bytes of memory,
since ADDW does a doubling game to get to this point; using realloc
might be more apt.  Of course, since this is in read-number code, it
might be better yet for the code to notice it's overflowed, set ERANGE
and simply skip over digits of input until it finds something else,
without any copying.  Unfortunately, the code is sufficiently
convoluted that I don't see how to change it to do that ...

For reference: <quote src="gdb">

(gdb) p *s
$6 = {_flags = -72515583, _IO_read_ptr = 0xbffff3b7 "", _IO_read_end = 0xbffff3b7 "", _IO_read_base = 0xbfdff3b7 '9' <repeats 200 times>..., _IO_write_base = 0xbfdff3b7 '9' <repeats 200 times>..., _IO_write_ptr = 0xbfdff3b7 '9' <repeats 200 times>..., _IO_write_end = 0xbfdff3b7 '9' <repeats 200 times>..., _IO_buf_base = 0xbfdff3b7 '9' <repeats 200 times>..., _IO_buf_end = 0xbffff3b7 "", _IO_save_base = 0x0, _IO_backup_base = 0x0, _IO_save_end = 0x0, _markers = 0x0, _chain = 0x0, _fileno = 0, _flags2 = 16, _old_offset = 0, _cur_column = 0, _vtable_offset = 0 '\000', _shortbuf = "", _lock = 0x0, _offset = 3086879200, _codecvt = 0xffffffff, _wide_data = 0xb7ffeff4, _freeres_list = 0x0, _freeres_buf = 0xb7fff670, _freeres_size = 3219125120, _mode = -1, _unused2 = "(øÿ·p\rþ·\001\000\000\000\001\000\000\000\000\000\000\000U\202\004\b\003\000\000\000\000\000\000\000¨\226\004\b\001\000\000"}
(gdb) bt
#0  0xb7ee1e81 in _IO_vfscanf_internal (s=0xbfdff2dc, format=0x80485a0 "%llu", argptr=0xbfdff3a8 "¸óÿ¿", errp=0x0) at vfscanf.c:1760
#1  0xb7ee7a65 in *__GI___isoc99_vsscanf (string=0xbfdff3b7 '9' <repeats 200 times>..., format=0x80485a0 "%llu", args=0xbfdff3a8 "¸óÿ¿") at isoc99_vsscanf.c:44
#2  0xb7ee79bf in __isoc99_sscanf (s=0xbfdff3b7 '9' <repeats 200 times>..., format=0x80485a0 "%llu") at isoc99_sscanf.c:33
#3  0x080484bf in main () at sscanferange.c:13
(gdb) up 3
#3  0x080484bf in main () at sscanferange.c:13
(gdb) p &(buf[0])
$8 = 0xbfdff3b7 '9' <repeats 200 times>...

</quote> so it's just copied the very last character when this
happens.

If there are other things maintainers would like to know about details
of this bug, I can easilly reproduce and ferret out the information
you need - although I'll probably delete my debug build of glibc
before many weeks have passed,

	Eddy.



Reply to: