mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-12 15:36:17 +01:00
gprintf: Fix invalid size allocation in g_vasprintf()
As per the previous commit, it’s possible for `g_printf_string_upper_bound()` to return an error. We need to catch and handle that error in `g_vasprintf()` to avoid it trying to write to a `NULL` string allocation and crashing. So, call `g_vsnprintf()` directly instead of calling `g_printf_string_upper_bound()`, so that the error case can be handled. There was already a test for some of this behaviour (`test_vasprintf_invalid_format_placeholder()`). Because it tested an invalid format string, the `_g_vsprintf()` call bailed out before checking whether the buffer it had been passed was `NULL`. The new test has a valid format string, but an invalid arg. When running the tests locally, I have disabled the `USE_SYSTEM_PRINTF` and `HAVE_VASPRINTF` code paths in `g_vasprintf()`. Signed-off-by: Philip Withnall <pwithnall@gnome.org> Fixes: #3187
This commit is contained in:
parent
e2cd0962c2
commit
3c6052f318
@ -359,19 +359,29 @@ g_vasprintf (gchar **string,
|
||||
|
||||
{
|
||||
va_list args2;
|
||||
char c;
|
||||
int max_len;
|
||||
|
||||
va_copy (args2, args);
|
||||
|
||||
*string = g_new (gchar, g_printf_string_upper_bound (format, args));
|
||||
max_len = _g_vsnprintf (&c, 1, format, args);
|
||||
if (max_len < 0)
|
||||
{
|
||||
/* This can happen if @format contains `%ls` or `%lc` and @args contains
|
||||
* something not representable in the current locale’s encoding (which
|
||||
* should be UTF-8, but ymmv). Basically: don’t use `%ls` or `%lc`. */
|
||||
va_end (args2);
|
||||
*string = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*string = g_new (gchar, (size_t) max_len + 1);
|
||||
|
||||
len = _g_vsprintf (*string, format, args2);
|
||||
va_end (args2);
|
||||
|
||||
if (len < 0)
|
||||
{
|
||||
g_free (*string);
|
||||
*string = NULL;
|
||||
}
|
||||
/* _g_vsprintf() should have exactly the same failure modes as _g_vsnprintf() */
|
||||
g_assert (len >= 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -948,6 +948,30 @@ test_vasprintf_invalid_format_placeholder (void)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
test_vasprintf_invalid_wide_string (void)
|
||||
{
|
||||
#if !defined(__APPLE__) && !defined(__FreeBSD__)
|
||||
gint len = 0;
|
||||
gchar *buf = "some non-null string";
|
||||
#endif
|
||||
|
||||
g_test_summary ("Test error handling for invalid wide strings in g_vasprintf()");
|
||||
|
||||
#if !defined(__APPLE__) && !defined(__FreeBSD__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wformat"
|
||||
#pragma GCC diagnostic ignored "-Wformat-extra-args"
|
||||
len = test_vasprintf_va (&buf, "%ls", L"\xD800" /* incomplete surrogate pair */);
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
g_assert_cmpint (len, ==, -1);
|
||||
g_assert_null (buf);
|
||||
#else
|
||||
g_test_skip ("vasprintf() placeholder checks on BSDs are less strict");
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
@ -989,6 +1013,7 @@ main (int argc,
|
||||
g_test_add_func ("/sprintf/upper-bound", test_upper_bound);
|
||||
|
||||
g_test_add_func ("/vasprintf/invalid-format-placeholder", test_vasprintf_invalid_format_placeholder);
|
||||
g_test_add_func ("/vasprintf/invalid-wide-string", test_vasprintf_invalid_wide_string);
|
||||
|
||||
return g_test_run();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user