This is the mail archive of the
glibc-bugs@sourceware.org
mailing list for the glibc project.
[Bug libc/4438] New: vfprintf() segfault with multibyte string and long precision
- From: "victor dot stinner at inl dot fr" <sourceware-bugzilla at sourceware dot org>
- To: glibc-bugs at sources dot redhat dot com
- Date: 30 Apr 2007 12:46:19 -0000
- Subject: [Bug libc/4438] New: vfprintf() segfault with multibyte string and long precision
- Reply-to: sourceware-bugzilla at sourceware dot org
(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.