From 9c0495d23e6999375976ca44e3812fc65b73626e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Sun, 1 Dec 2013 09:45:38 +0700 Subject: [PATCH] gettext.c: detect the vsnprintf bug at runtime MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Bug 6530 [1] in glibc causes "git show v0.99.6~1" to fail with error "your vsnprintf is broken". The workaround avoids that, but it corrupts system error messages in non-C locales. The bug has been fixed since 2.17. We could know running glibc version with gnu_get_libc_version(). But version is not a sure way to detect the bug because downstream may back port the fix to older versions. Do a runtime test that immitates the call flow that leads to "your vsnprintf is broken". Only enable the workaround if the test fails. Tested on Gentoo Linux, glibc 2.16.0 and 2.17, amd64. [1] http://sourceware.org/bugzilla/show_bug.cgi?id=6530 Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- gettext.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/gettext.c b/gettext.c index 71e954563d..8b2da4641f 100644 --- a/gettext.c +++ b/gettext.c @@ -29,6 +29,17 @@ int use_gettext_poison(void) #endif #ifndef NO_GETTEXT +static int test_vsnprintf(const char *fmt, ...) +{ + char buf[26]; + int ret; + va_list ap; + va_start(ap, fmt); + ret = vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + return ret; +} + static const char *charset; static void init_gettext_charset(const char *domain) { @@ -99,9 +110,7 @@ static void init_gettext_charset(const char *domain) $ LANGUAGE= LANG=de_DE.utf8 ./test test: Kein passendes Ger?t gefunden - In the long term we should probably see about getting that - vsnprintf bug in glibc fixed, and audit our code so it won't - fall apart under a non-C locale. + The vsnprintf bug has been fixed since glibc 2.17. Then we could simply set LC_CTYPE from the environment, which would make things like the external perror(3) messages work. @@ -115,7 +124,9 @@ static void init_gettext_charset(const char *domain) setlocale(LC_CTYPE, ""); charset = locale_charset(); bind_textdomain_codeset(domain, charset); - setlocale(LC_CTYPE, "C"); + /* the string is taken from v0.99.6~1 */ + if (test_vsnprintf("%.*s", 13, "David_K\345gedal") < 0) + setlocale(LC_CTYPE, "C"); } void git_setup_gettext(void) -- 2.11.4.GIT