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.
Bugs 17829 and 21127 are other instances of this. (Indeed, the large-width case is mentioned in bug 17829 comment 7.)