Bugzilla will be upgraded to version 5.0 on a still to be determined date in the near future. The original upgrade date has been delayed.
Bug 358111 - glibc's printf(3) tries to allocate a 2^64-byte buffer
glibc's printf(3) tries to allocate a 2^64-byte buffer
Product: Fedora
Classification: Fedora
Component: glibc (Show other bugs)
x86_64 Linux
low Severity low
: ---
: ---
Assigned To: Jakub Jelinek
Fedora Extras Quality Assurance
Depends On:
  Show dependency treegraph
Reported: 2007-10-30 08:35 EDT by Jim Meyering
Modified: 2016-11-24 10:49 EST (History)
2 users (show)

See Also:
Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Last Closed: 2008-04-10 06:08:33 EDT
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---

Attachments (Terms of Use)
add check of malloc return value (722 bytes, patch)
2007-10-30 09:12 EDT, Jim Meyering
no flags Details | Diff
* stdio-common/vfprintf.c (vfprintf): Remove dead code. (650 bytes, patch)
2008-02-17 13:47 EST, Jim Meyering
no flags Details | Diff

  None (edit)
Description Jim Meyering 2007-10-30 08:35:43 EDT
Description of problem:printf format string abuse can make the function try to
allocate a buffer of length just short of 2^64 bytes.

Version-Release number of selected component (if applicable): glibc-2.7-2

How reproducible: every time

Steps to Reproduce:
1. strace /usr/bin/printf %.2147483647f 1
2. note attempt to allocate ridiculously large amount of memory:
mmap(NULL, 18446744071562072064, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = -1 ENOMEM (Cannot allocate memory)
Actual results: see above

Expected results:
At worst, I would expect it to try to allocate ~2^31 bytes, not 2^64.

Even better would be if it worked like FreeBSD 6.1's printf and didn't
allocate all of that memory for nothing.

Additional info:
Comment 1 Jim Meyering 2007-10-30 09:12:32 EDT
Created attachment 243321 [details]
add check of malloc return value

I looked at the code and see two problems.
First, an unchecked malloc, then there's the fact that
both prec and width are of type "int", so it looks like this expression can
overflow, when either approaches 2^31:

workstart = (CHAR_T *) malloc ((MAX (prec, width) + 32) * sizeof (CHAR_T));

besides, this is the only assignment of malloc'd memory to "workstart" that is
not checked.  The patch below adds the missing check. This doesn't fix the bug,
but at least keeps glibc from trying to allocate so much memory a second time.
Comment 2 Ulrich Drepper 2007-11-06 16:46:06 EST
I've fixed the computation of the buffer size but I won't change the
implementation to avoid the allocations since this only means that reasonable
code doesn't run as well.  We're not optimizing for the ridiculous.
Comment 3 Jim Meyering 2008-02-17 13:46:07 EST
Hi Uli!

Thanks for looking at that.

However, don't you want the following patch, too?
From my reading, your new __builtin_expect-0 test will always be false,
since prec is a positive signed int value: thus guaranteed to be smaller
than the unsigned SIZE_MAX-31.

And even if an "int" value could approach the maximum size_t in magnitude,
your "31" would then have to be "32".  Otherwise, with prec = SIZE_MAX - 31,
that test would fail (because it'd be ==, not > ) and the subsequent
(size_t) prec + 32 would overflow to 0.

attached patch below...
Comment 4 Jim Meyering 2008-02-17 13:47:15 EST
Created attachment 295108 [details]
* stdio-common/vfprintf.c (vfprintf): Remove dead code.
Comment 5 Ulrich Drepper 2008-03-30 01:40:50 EDT
No, that test is not dead, it's just incomplete.  I've checked in a patch.

This bug can be closed, I think.
Comment 6 Jim Meyering 2008-03-30 03:03:02 EDT
Thanks.  That looks good now.  For the record, even now, the test/block *is*
still dead code in most cases: when sizeof CHAR_T == 1 || sizeof int < sizeof
So it's *not* dead only for the wide-char functions and then, only when compiled
with int and size_t having the same width.

Note You need to log in before you can comment on or make changes to this bug.