From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 30410 invoked by alias); 30 Apr 2007 12:46:36 -0000 Received: (qmail 30327 invoked by uid 48); 30 Apr 2007 12:46:19 -0000 Date: Mon, 30 Apr 2007 12:46:00 -0000 From: "victor dot stinner at inl dot fr" To: glibc-bugs@sources.redhat.com Message-ID: <20070430134618.4438.victor.stinner@inl.fr> Reply-To: sourceware-bugzilla@sourceware.org Subject: [Bug libc/4438] New: vfprintf() segfault with multibyte string and long precision X-Bugzilla-Reason: CC Mailing-List: contact glibc-bugs-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: glibc-bugs-owner@sourceware.org X-SW-Source: 2007-04/txt/msg00135.txt.bz2 (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 #include #include 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.