Bug 441945

Summary: glibc: [RFE] snprintf must not fail with ENOMEM
Product: [Fedora] Fedora Reporter: Jim Meyering <meyering>
Component: glibcAssignee: glibc team <glibc-bugzilla>
Status: CLOSED UPSTREAM QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: low Docs Contact:
Priority: low    
Version: rawhideCC: calimocho.fedora, codonell, fweimer, jim, law, maggu2810, rjones
Target Milestone: ---Keywords: Reopened, Triaged
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2019-09-10 13:38:22 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

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