Skip to content

Commit 9c0495d

Browse files
pcloudsgitster
authored andcommitted
gettext.c: detect the vsnprintf bug at runtime
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 <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent a155a5f commit 9c0495d

1 file changed

Lines changed: 15 additions & 4 deletions

File tree

gettext.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,17 @@ int use_gettext_poison(void)
2929
#endif
3030

3131
#ifndef NO_GETTEXT
32+
static int test_vsnprintf(const char *fmt, ...)
33+
{
34+
char buf[26];
35+
int ret;
36+
va_list ap;
37+
va_start(ap, fmt);
38+
ret = vsnprintf(buf, sizeof(buf), fmt, ap);
39+
va_end(ap);
40+
return ret;
41+
}
42+
3243
static const char *charset;
3344
static void init_gettext_charset(const char *domain)
3445
{
@@ -99,9 +110,7 @@ static void init_gettext_charset(const char *domain)
99110
$ LANGUAGE= LANG=de_DE.utf8 ./test
100111
test: Kein passendes Ger?t gefunden
101112
102-
In the long term we should probably see about getting that
103-
vsnprintf bug in glibc fixed, and audit our code so it won't
104-
fall apart under a non-C locale.
113+
The vsnprintf bug has been fixed since glibc 2.17.
105114
106115
Then we could simply set LC_CTYPE from the environment, which would
107116
make things like the external perror(3) messages work.
@@ -115,7 +124,9 @@ static void init_gettext_charset(const char *domain)
115124
setlocale(LC_CTYPE, "");
116125
charset = locale_charset();
117126
bind_textdomain_codeset(domain, charset);
118-
setlocale(LC_CTYPE, "C");
127+
/* the string is taken from v0.99.6~1 */
128+
if (test_vsnprintf("%.*s", 13, "David_K\345gedal") < 0)
129+
setlocale(LC_CTYPE, "C");
119130
}
120131

121132
void git_setup_gettext(void)

0 commit comments

Comments
 (0)