Full Disclosure mailing list archives
new class of printf issue: int overflow
From: Felix von Leitner <felix-fulldisclosure () fefe de>
Date: Thu, 11 Jan 2007 02:00:53 +0100
This is about two issues. First: abs within vasprintf. I just read some gnupg source code and stumbled upon their vasprintf implementation. Basically they make one pass over the format string to find out how much memory to malloc, and then they call sprintf on the malloced buffer. Here is an excerpt: if (*p == '*') { ++p; total_width += abs (va_arg (ap, int)); } I noticed this code because it calls abs on an int. A little known fact about abs is that it can return negative values. If the int is 0x80000000, for example, abs() will also return 0x80000000. So, I thought, mhh, if someone can control this value but not the format string, he can cause total_width to be very small but then write lots of stuff to it. Second issue: int overflow in *printf: But that got me thinking. *printf return an int, and it's supposed to be the number of chars written. So a typical idiom is size_t memory_needed=snprintf(NULL,0,format_string,...); char* ptr=malloc(memory_needed+1); sprintf(ptr,format_string,...); What if sprintf returns a negative value? printf can return -1 if write() failed, but sprintf can not traditionally return -1. The single unix specification says this about sprintf: If the value of n is zero on a call to snprintf(), nothing shall be written, the number of bytes that would have been written had n been sufficiently large excluding the terminating null shall be returned, and s may be a null pointer. So my guess is that nobody expects sprintf to return a negative value. Out of curiosity, I wrote this test program: $ cat > t.c #include <stdio.h> int main() { printf("%d\n",snprintf(0,0,"%*d %*d",0x40000000,1,0x40000000,1)); } $ gcc -o t t.c $ ./t -2147483647 ./t 17.02s user 0.03s system 99% cpu 17.161 total $ the second line comes from my zsh, and as you can see running this program took 17 seconds. top shows that the process used 1 gig of memory while it ran. :-) This scenario is pretty far fetched, obviously. In the above code snippet, returning a negative number doesn't hurt, because malloc will interpret it as unsigned really big number. But hey, there could be other scenarios. The question is: do we want to do something about it? What should printf do if it detects an int overflow? Return -1? Is there a good solution to this? Solaris apparently returns -1. Felix PS: Does anyone understand why sprintf does not count the \0 at the end? I think that's pretty brain-dead. _______________________________________________ Full-Disclosure - We believe in it. Charter: http://lists.grok.org.uk/full-disclosure-charter.html Hosted and sponsored by Secunia - http://secunia.com/
Current thread:
- new class of printf issue: int overflow Felix von Leitner (Jan 10)
- Re: new class of printf issue: int overflow Pierre Habouzit (Jan 11)
- Re: new class of printf issue: int overflow Felix von Leitner (Jan 11)
- Re: new class of printf issue: int overflow Pierre Habouzit (Jan 11)
- Re: new class of printf issue: int overflow Pierre Habouzit (Jan 11)
- Re: new class of printf issue: int overflow Felix von Leitner (Jan 11)
- Re: new class of printf issue: int overflow Pierre Habouzit (Jan 11)
- Re: new class of printf issue: int overflow Mihai Dontu (Jan 11)
- Re: new class of printf issue: int overflow Thomas (Jan 11)
- Re: new class of printf issue: int overflow Felix von Leitner (Jan 11)
- Re: new class of printf issue: int overflow Thomas (Jan 11)
- Re: new class of printf issue: int overflow Felix von Leitner (Jan 11)