bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

glibc's snprintf bug causes printf(1) failure with MALLOC_PERTURB_ != 0


From: Jim Meyering
Subject: glibc's snprintf bug causes printf(1) failure with MALLOC_PERTURB_ != 0
Date: Tue, 11 Nov 2008 19:35:18 +0100

Using printf from GNU coreutils newer than 6.9, I get this
on rawhide (glibc-2.8.90-16) which looks wrong, but isn't serious:
(it shouldn't allocate a 30MB buffer just to fill it with '0's and
print it)

      $ (ulimit -v 20000; env MALLOC_PERTURB_=1 printf '%.30000000f' 0)
      printf: write error

But, on Debian unstable (libc6 2.7-16) there's a bigger problem:

      $ (ulimit -v 20000; env MALLOC_PERTURB_=1 printf '%.30000000f' 0)
      zsh: segmentation fault
      $ dmesg|tail -1
      [75236.189009] printf[26494]: segfault at 0 ip 7f9e90598520 sp \
        7fff98a87c28 error 6 in libc-2.7.so[7f9e9051c000+14a000]

The latter failure is due to a glibc snprintf bug discussed in:

    http://bugs.debian.org/481543
    http://bugzilla.redhat.com/470831 (RHEL5)

If you're into development and can deal with occasional
tool/infrastructure misbehavior, I strongly recommend that you
set the MALLOC_PERTURB_ envvar -- if you do, use a value in 1..255.
I use the following:

    # http://udrepper.livejournal.com/11429.html
    export MALLOC_PERTURB_=$(($RANDOM % 255 + 1))

It would be good for gnulib to detect the bug and to use
the replacement snprintf on losing systems.


=========================================================
For reference, here's a C-only reproducer based on what
I wrote in the bug reports:

cat <<EOF > k.c
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char **argv)
{
  char buf[200];
  char *fmt = argv[1];
  if (argc < 2)
    abort ();
  int n = snprintf (buf, sizeof buf, fmt, 1);
  return 0*n;
}
EOF

I chose to eliminate the shared-libraries:

    gcc -static -W -Wall k.c

Then run it like this:

    env -i -- zsh -f -c \
      'ulimit -v 5000; MALLOC_PERTURB_=9 ./a.out %$[5*2**20]d' || dmesg|tail -1

This example also demonstrates a problem with glibc
(whether it's a standards violation or merely a QoI issue is debatable)
IMHO, such a use of snprintf should not fail with ENOMEM, given
any but the most pathological floating point input arguments.
And with a format directives like s d i u o, etc., it should *never* fail.
Of course, if you want to use "%$[5*2**20]s" on the command
line, you'll have to change the `1' argument above to a string, e.g., `"1"'.

FYI, the libc in freebsd 6.1 and newer has no problem with the above
snprintf usage.  And coreutils' printf command prints the 30 million 0's
without allocating an inordinate amount of storage.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]