Bug 441945 - glibc: [RFE] snprintf must not fail with ENOMEM
Summary: glibc: [RFE] snprintf must not fail with ENOMEM
Keywords:
Status: CLOSED UPSTREAM
Alias: None
Product: Fedora
Classification: Fedora
Component: glibc
Version: rawhide
Hardware: All
OS: Linux
low
low
Target Milestone: ---
Assignee: glibc team
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2008-04-10 20:00 UTC by Jim Meyering
Modified: 2019-09-10 13:38 UTC (History)
7 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2019-09-10 13:38:22 UTC
Type: ---
Embargoed:


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
Sourceware 24988 0 None None None 2019-09-10 13:38:21 UTC

Description Jim Meyering 2008-04-10 20:00:43 UTC
Description of problem: snprintf can fail with ENOMEM
Printing into a 200-byte buffer should never have to allocate an arbitrarily
large amount of memory.  In fact, snprintf should never allocate memory in a
manner that can fail, period.

Version-Release number of selected component (if applicable):
glibc-2.7.90-13.x86_64

How reproducible: every time


Steps to Reproduce:
cat <<\EOF > k.c
/* snprintf should not allocate memory, *ever*.
   POSIX says that snprintf may fail with EOVERFLOW (n > INT_MAX or size of
   output would exceed INT_MAX).  It appears not to allow failure with ENOMEM,
   as happens here:

   $ zsh -c 'ulimit -v 5000; ./a.out %$[5*2**20]d'
   fmt: %5242880d  retval=-1  errno=Cannot allocate memory
   # Same with bash, but it requires more memory:
   $ bash -c 'ulimit -v 12000; ./a.out %$[12*2**20]d'
  */
#include <stdio.h>
#include <string.h>
#include <errno.h>
int
main(int argc, char **argv)
{
  char buf[200];
  char *fmt = argv[1];
  if (argc < 2)
    return 1;
  int n = snprintf (buf, sizeof buf, fmt, 1);
  int saved_errno = errno;
  printf ("fmt: %s  retval=%d  errno=%s\n", fmt, n,
	   n < 0 ? strerror(saved_errno) : "");
  return 0;
}
EOF
gcc k.c
zsh -c 'ulimit -v 5000; ./a.out %$[5*2**20]d'
  
Actual results:
fmt: %5242880d  retval=-1  errno=Cannot allocate memory

Expected results:
fmt: %5242880d  retval=5242880  errno=

Additional info:

Comment 1 Jim Meyering 2008-04-10 22:12:53 UTC
Regarding POSIX conformance, consider this:
snprintf (NULL, 0, fmt, 1); currently, that fails just like the example above. 
However, POSIX requires something else:

   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.


Comment 2 Jakub Jelinek 2008-04-14 10:32:05 UTC
That applies only upon successful completion.  Even for n 0 if there are errors
snprintf is supposed to return -1 and set errno.
For cases like:
#include <errno.h>
#include <locale.h>
#include <stdio.h>

int
main (void)
{
  setlocale (LC_ALL, "en_US.ISO-8859-1");
  int ret = snprintf (NULL, 0, "%lC\n", (wint_t) 0x10c);
  printf ("%d %m\n", ret);
  return 0;
}

where ret should be -1 and errno EILSEQ, but even cases where memory was needed
and -1/ENOMEM is returned.

Comment 3 Jim Meyering 2008-04-14 11:58:13 UTC
Hi Jakub,

That's a fine example, but it merely suggests that the crystal clear wording in
POSIX (quoted above) should be relaxed to allow snprintf to return -1 upon
EILSEQ.  There is already explicit language that implies snprintf w/n=0 will not
fail with ENOMEM, so at least in that latter case, glibc violates the intent of
the standard.

Comment 4 Jim Meyering 2010-11-03 10:08:51 UTC
Hi guys,

Please do not close this until snprintf stops allocating from the heap at least for integer and string formats.  If you prefer, I can change the title to a request for improved QoI, so it doesn't look like a bug, but imho, it should be considered a bug for snprintf(NULL,0, ...) to allocate memory when the format involves no floating point conversion specifier.

http://thread.gmane.org/gmane.comp.lib.gnulib.bugs/23838

As I said there, FreeBSD's snprintf appears to get this right,
so glibc's should, too.

Comment 5 Fedora Admin XMLRPC Client 2011-11-14 19:14:41 UTC
This package has changed ownership in the Fedora Package Database.  Reassigning to the new owner of this component.

Comment 6 Fedora Admin XMLRPC Client 2011-11-15 04:46:45 UTC
This package has changed ownership in the Fedora Package Database.  Reassigning to the new owner of this component.

Comment 7 Jeff Law 2012-02-03 20:03:16 UTC
Just changing status so this pops up in my searches for bugs needing my attention

Comment 8 Fedora Admin XMLRPC Client 2013-01-28 20:07:30 UTC
This package has changed ownership in the Fedora Package Database.  Reassigning to the new owner of this component.

Comment 10 Carlos O'Donell 2019-09-10 13:38:22 UTC
This is now being tracked upstream: https://sourceware.org/bugzilla/show_bug.cgi?id=24988


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