We met with a situation where we are suspecting unsigned data type when assigned a negative value can cause overflow in glibc. #1 __GI___mempcpy (dest=<optimized out>, src=src@entry=0x97fffcdc, len=len@entry=4096) ---> crash #2 __GI__IO_default_xsputn (f=f@entry=0xb24b7918, data=data@entry=0x97fffcdc, n=n@entry=12396) #3 _IO_new_file_xsputn (f=0xb24b7918, data=<optimized out>, n=16455) #4 __GI__IO_fwrite (buf=0x97ffbd00, size=1, count=16455, fp=0xb24b7918) So from application a valid address and valid size is passed to glibc fwrite function. but if we cehck frame 2 base address is increased by (0x97fffcdc - 0x97ffbd00) = 16348 bytes and still n left is 12396 which leads to overflow and crash afterwards. if we check code snippet:- if (do_write) { count = new_do_write (f, s, do_write); to_do -= count; if (count < do_write) return n - to_do; } In this code when we call new_do_write which calls _IO_SYSWRITE and which can return -1 in failure case. So comparison of unsigned data type(having -1) is not correct. as count is IO_size_t , which is unsigned , so it should be IO_ssize_t as _IO_SYSWRITE return _IO_ssize_t type. We checked with small testcase:- #include<stdio.h> size_t test() { return -1; } void main() { size_t data = 13989; size_t data1 = 27827; size_t count; count = test(); data -= count; if(count < data1) { printf("PASS %d\n", count); return; } printf("FAIL %d \n", data); } output # ./a.out FAIL 13990 So can you please check whether it is correct or we are in wrong direction.
I don't think _IO_SYSWRITE will return zero in the failure case. Instead, it will set the _IO_ERR_SEEN flag.
(In reply to Florian Weimer from comment #1) > I don't think _IO_SYSWRITE will return zero in the failure case. Instead, > it will set the _IO_ERR_SEEN flag. But as per our checking it is returning -1. 1298 _IO_size_t 1299 _IO_new_file_xsputn (_IO_FILE *f, const void *data, _IO_size_t n) 1300 { ... 1344 s += count; 1345 to_do -= count; 1346 } ==> at this point to_do value was 12395. and at below code position it was increased by 1:- 1371 if (to_do) 1372 to_do -= _IO_default_xsputn (f, s+do_write, to_do); // tod:-12396 1373 } Which means it is increased by 1, which is possible if 1360 if (do_write) 1361 { 1362 count = new_do_write (f, s, do_write); 1363 to_do -= count; new_do_write returns -ve value, which means IO_SYSWRTE returns -ve value. we are not sure about IO_SYSWRTE return value, but man page of write system call says it will return -1 on failure.
Please provide a full test case.
No details supplied in nearly two months. Closing.