This is the mail archive of the glibc-bugs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug libc/4438] New: vfprintf() segfault with multibyte string and long precision


(Since the bug has been reported on Debian and Fedora Core, I create a bug 
report on libc bugtracker)

Hi,

I use your personnal emails because the bug might be a security vulnerability 
(I don't know Linux kernel enough to guess). If it is not, I can open a bug 
report on Bugzilla if you would like to.

I found a bug in dpkg program (from apt-get of Debian project):
   COLUMNS=10000000 dpkg -l
=> Crash with segfault (SIGSEGV)

After long investigation (around one week :-)), I'm certain that the bug comes
from GNU libc. The crash is not specific to this program, any program allowing
to change format string of printf() may crash. Smallest C testcase:
-------------------------------------------------------------
#include <stdlib.h>
#include <stdio.h>
#include <locale.h>

int main()
{
    setlocale (LC_CTYPE, "");
    printf("%-1.30500200s\n", "Hello");
    return 0;
}
-------------------------------------------------------------

If your locale is not UTF-8, specify another multibyte locale to setlocale(). 
The value "30500200" just have to be bigger than current stack size limit.

You can also try with bash/core-utils printf:
-------------------------------------------------------------
printf '%-1.25000000s' 'Hello'
-------------------------------------------------------------


The bug is located in stdio-common/vfprintf.c, macro "process_string_arg", in 
this block:
-------------------------------------------------------------
   if (prec != -1)
     {
       /* Search for the end of the string, but don't search past
          the length (in bytes) specified by the precision.  Also
          don't use incomplete characters.  */
       if (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MB_CUR_MAX) == 1)
         len = __strnlen (string, prec);
       else
         {
           /* In case we have a multibyte character set the
              situation is more compilcated.  We must not copy
              bytes at the end which form an incomplete character. */
           wchar_t ignore[prec];
           const char *str2 = string;
           mbstate_t ps;

           memset (&ps, '\0', sizeof (ps));
           if (__mbsnrtowcs (ignore, &str2, prec, prec, &ps)
        == (size_t) -1)
             {
        done = -1;
        goto all_done;
             }
           if (str2 == NULL)
             len = strlen (string);
           else
             len = str2 - string - (ps.__count & 7);
         }
     }
   else
     len = strlen (string);
-------------------------------------------------------------

If 1 < prec and 1 < LC_CTYPE[_NL_CTYPE_MB_CUR_MAX], we go in "complicated" 
block :-)

Now imagine that prec is equal to 30500200: 30 MB will be "allocated" on the 
stack (by "wchar_t ignore[prec]") whereas Linux use 8 MB (in default config) 
for stack limit. Stack *should* grow up/down, but on my compute (i386) gcc 
just use "sub $eax, $esp" instruction to allocated memory and Linux just 
raises the signal SIGSEGV.

I don't know enough locale API (mbsnrtowcs() function) to fix the bug.

Victor Stinner
http://www.inl.fr/

---

Other bug report of the same bug:
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=238406
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=421555

-- 
           Summary: vfprintf() segfault with multibyte string and long
                    precision
           Product: glibc
           Version: unspecified
            Status: NEW
          Severity: critical
          Priority: P1
         Component: libc
        AssignedTo: drepper at redhat dot com
        ReportedBy: victor dot stinner at inl dot fr
                CC: glibc-bugs at sources dot redhat dot com


http://sourceware.org/bugzilla/show_bug.cgi?id=4438

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]