This service will be undergoing maintenance at 00:00 UTC, 2016-09-28. It is expected to last about 1 hours
Bug 441945 - [RFE] snprintf must not fail with ENOMEM
[RFE] snprintf must not fail with ENOMEM
Status: NEW
Product: Fedora
Classification: Fedora
Component: glibc (Show other bugs)
rawhide
All Linux
low Severity low
: ---
: ---
Assigned To: Carlos O'Donell
Fedora Extras Quality Assurance
: Reopened, Triaged
Depends On:
Blocks:
  Show dependency treegraph
 
Reported: 2008-04-10 16:00 EDT by Jim Meyering
Modified: 2016-02-04 01:26 EST (History)
7 users (show)

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


Attachments (Terms of Use)

  None (edit)
Description Jim Meyering 2008-04-10 16:00:43 EDT
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 18:12:53 EDT
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 06:32:05 EDT
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 07:58:13 EDT
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 06:08:51 EDT
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 14:14:41 EST
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-14 23:46:45 EST
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 15:03:16 EST
Just changing status so this pops up in my searches for bugs needing my attention
Comment 8 Fedora Admin XMLRPC Client 2013-01-28 15:07:30 EST
This package has changed ownership in the Fedora Package Database.  Reassigning to the new owner of this component.

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