If zip 3.0-14 is built with _FORTIFY_SOURCE=3 (GCC 14.1, glibc 2.40),
this can happen when compressing a file with non-ASCII characters in its UTF-8 name:
$ echo -n "There’s a Baby in the House.flac" | od -c
0000000 T h e r e 342 200 231 s a B a b y 0000020 i n t h e H o u s e . f l 0000040 a c
$ zip /tmp/t.zip "There’s a Baby in the House.flac"
*** buffer overflow detected ***: terminated
The problem is in local_to_wide_string, where mbstowcs is being run with
the UTF-8 source length rather than the widechar destination length --
this correctly trips a fortify error because GCC 14 can infer the actual
size of the destination.
In theory, this was already fixed by Fedora here:
@@ -3502,7 +3502,7 @@
if ((wc_string = (wchar_t *)malloc((wsize + 1) * sizeof(wchar_t))) == NULL) {
ZIPERR(ZE_MEM, "local_to_wide_string");
}
- wsize = mbstowcs(wc_string, local_string, strlen(local_string) + 1);
+ wsize = mbstowcs(wc_string, local_string, wsize + 1);
wc_string[wsize] = (wchar_t) 0;
/* in case wchar_t is not zwchar */
Looking at the source I see that the code does an initial dummy conversion to get wsize
/* for now try to convert as string - fails if a bad char in string */.
wsize = mbstowcs(NULL, local_string, MB_CUR_MAX );
if (wsize == (size_t)-1) {
/* could not convert */
return NULL;
}
That wsize is then used to malloc the wc_string buffer
/* convert it */
if ((wc_string = (wchar_t *)malloc((wsize + 1) * sizeof(wchar_t))) == NULL) {
ZIPERR(ZE_MEM, "local_to_wide_string");
}
wsize = mbstowcs(wc_string, local_string, strlen(local_string) + 1);
Is there a path through that that means mbstowcs will not create a wsize output buffer?
Paul
[...]Looking at the source I see that the code does an initial dummy
conversion to get wsize
Is there a path through that that means mbstowcs will not create a
wsize output buffer?
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 490 |
Nodes: | 16 (1 / 15) |
Uptime: | 70:22:40 |
Calls: | 9,678 |
Calls today: | 2 |
Files: | 13,722 |
Messages: | 6,172,122 |