Actually check for parse errors when using fu_firmware_strparse_uintX_safe

Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=38141
This commit is contained in:
Richard Hughes 2021-09-05 10:16:58 +01:00
parent cf34c8f1dd
commit 9c6f676656
2 changed files with 88 additions and 5 deletions

View File

@ -36,6 +36,8 @@ fu_firmware_strparse_uint4_safe(const gchar *data,
GError **error)
{
gchar buffer[2] = {'\0'};
gchar *endptr = NULL;
guint64 valuetmp;
if (!fu_memcpy_safe((guint8 *)buffer,
sizeof(buffer),
0x0, /* dst */
@ -45,8 +47,18 @@ fu_firmware_strparse_uint4_safe(const gchar *data,
sizeof(buffer) - 1,
error))
return FALSE;
valuetmp = g_ascii_strtoull(buffer, &endptr, 16);
if (endptr - buffer != sizeof(buffer) - 1) {
g_autofree gchar *str = fu_common_strsafe(buffer, sizeof(buffer));
g_set_error(error,
G_IO_ERROR,
G_IO_ERROR_INVALID_DATA,
"cannot parse %s as hex",
str);
return FALSE;
}
if (value != NULL)
*value = (guint8)g_ascii_strtoull(buffer, NULL, 16);
*value = (guint8)valuetmp;
return TRUE;
}
@ -73,6 +85,8 @@ fu_firmware_strparse_uint8_safe(const gchar *data,
GError **error)
{
gchar buffer[3] = {'\0'};
gchar *endptr = NULL;
guint64 valuetmp;
if (!fu_memcpy_safe((guint8 *)buffer,
sizeof(buffer),
0x0, /* dst */
@ -82,8 +96,18 @@ fu_firmware_strparse_uint8_safe(const gchar *data,
sizeof(buffer) - 1,
error))
return FALSE;
valuetmp = g_ascii_strtoull(buffer, &endptr, 16);
if (endptr - buffer != sizeof(buffer) - 1) {
g_autofree gchar *str = fu_common_strsafe(buffer, sizeof(buffer));
g_set_error(error,
G_IO_ERROR,
G_IO_ERROR_INVALID_DATA,
"cannot parse %s as hex",
str);
return FALSE;
}
if (value != NULL)
*value = (guint8)g_ascii_strtoull(buffer, NULL, 16);
*value = (guint8)valuetmp;
return TRUE;
}
@ -110,6 +134,8 @@ fu_firmware_strparse_uint16_safe(const gchar *data,
GError **error)
{
gchar buffer[5] = {'\0'};
gchar *endptr = NULL;
guint64 valuetmp;
if (!fu_memcpy_safe((guint8 *)buffer,
sizeof(buffer),
0x0, /* dst */
@ -119,8 +145,18 @@ fu_firmware_strparse_uint16_safe(const gchar *data,
sizeof(buffer) - 1,
error))
return FALSE;
valuetmp = g_ascii_strtoull(buffer, &endptr, 16);
if (endptr - buffer != sizeof(buffer) - 1) {
g_autofree gchar *str = fu_common_strsafe(buffer, sizeof(buffer));
g_set_error(error,
G_IO_ERROR,
G_IO_ERROR_INVALID_DATA,
"cannot parse %s as hex",
str);
return FALSE;
}
if (value != NULL)
*value = (guint16)g_ascii_strtoull(buffer, NULL, 16);
*value = (guint16)valuetmp;
return TRUE;
}
@ -147,6 +183,8 @@ fu_firmware_strparse_uint24_safe(const gchar *data,
GError **error)
{
gchar buffer[7] = {'\0'};
gchar *endptr = NULL;
guint64 valuetmp;
if (!fu_memcpy_safe((guint8 *)buffer,
sizeof(buffer),
0x0, /* dst */
@ -156,8 +194,18 @@ fu_firmware_strparse_uint24_safe(const gchar *data,
sizeof(buffer) - 1,
error))
return FALSE;
valuetmp = g_ascii_strtoull(buffer, &endptr, 16);
if (endptr - buffer != sizeof(buffer) - 1) {
g_autofree gchar *str = fu_common_strsafe(buffer, sizeof(buffer));
g_set_error(error,
G_IO_ERROR,
G_IO_ERROR_INVALID_DATA,
"cannot parse %s as hex",
str);
return FALSE;
}
if (value != NULL)
*value = (guint16)g_ascii_strtoull(buffer, NULL, 16);
*value = (guint16)valuetmp;
return TRUE;
}
@ -184,6 +232,8 @@ fu_firmware_strparse_uint32_safe(const gchar *data,
GError **error)
{
gchar buffer[9] = {'\0'};
gchar *endptr = NULL;
guint64 valuetmp;
if (!fu_memcpy_safe((guint8 *)buffer,
sizeof(buffer),
0x0, /* dst */
@ -193,7 +243,17 @@ fu_firmware_strparse_uint32_safe(const gchar *data,
sizeof(buffer) - 1,
error))
return FALSE;
valuetmp = g_ascii_strtoull(buffer, &endptr, 16);
if (endptr - buffer != sizeof(buffer) - 1) {
g_autofree gchar *str = fu_common_strsafe(buffer, sizeof(buffer));
g_set_error(error,
G_IO_ERROR,
G_IO_ERROR_INVALID_DATA,
"cannot parse %s as hex",
str);
return FALSE;
}
if (value != NULL)
*value = (guint32)g_ascii_strtoull(buffer, NULL, 16);
*value = (guint32)valuetmp;
return TRUE;
}

View File

@ -2750,6 +2750,28 @@ fu_firmware_func(void)
g_assert_false(ret);
}
static void
fu_firmware_common_func(void)
{
gboolean ret;
guint8 value = 0;
g_autoptr(GError) error = NULL;
ret = fu_firmware_strparse_uint8_safe("ff00XX", 6, 0, &value, &error);
g_assert_no_error(error);
g_assert_true(ret);
g_assert_cmpint(value, ==, 0xFF);
ret = fu_firmware_strparse_uint8_safe("ff00XX", 6, 2, &value, &error);
g_assert_no_error(error);
g_assert_true(ret);
g_assert_cmpint(value, ==, 0x00);
ret = fu_firmware_strparse_uint8_safe("ff00XX", 6, 4, &value, &error);
g_assert_error(error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA);
g_assert_false(ret);
}
static void
fu_firmware_dedupe_func(void)
{
@ -3444,6 +3466,7 @@ main(int argc, char **argv)
g_test_add_func("/fwupd/smbios{dt}", fu_smbios_dt_func);
g_test_add_func("/fwupd/smbios{class}", fu_smbios_class_func);
g_test_add_func("/fwupd/firmware", fu_firmware_func);
g_test_add_func("/fwupd/firmware{common}", fu_firmware_common_func);
g_test_add_func("/fwupd/firmware{dedupe}", fu_firmware_dedupe_func);
g_test_add_func("/fwupd/firmware{build}", fu_firmware_build_func);
g_test_add_func("/fwupd/firmware{ihex}", fu_firmware_ihex_func);