This is the mail archive of the
glibc-bugs@sourceware.org
mailing list for the glibc project.
[Bug stdio/24988] New: [RFE] snprintf must not fail with ENOMEM
- From: "carlos at redhat dot com" <sourceware-bugzilla at sourceware dot org>
- To: glibc-bugs at sourceware dot org
- Date: Tue, 10 Sep 2019 13:37:16 +0000
- Subject: [Bug stdio/24988] New: [RFE] snprintf must not fail with ENOMEM
- Auto-submitted: auto-generated
https://sourceware.org/bugzilla/show_bug.cgi?id=24988
Bug ID: 24988
Summary: [RFE] snprintf must not fail with ENOMEM
Product: glibc
Version: 2.31
Status: NEW
Severity: normal
Priority: P2
Component: stdio
Assignee: unassigned at sourceware dot org
Reporter: carlos at redhat dot com
Target Milestone: ---
Originally submitted to Fedora:
https://bugzilla.redhat.com/show_bug.cgi?id=441945
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.
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 7000; ./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=
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.
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.
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.
This is a RFE therefore to improve the QoI for the implementation to avoid
allocations.
--
You are receiving this mail because:
You are on the CC list for the bug.