diff --git a/libfwupdplugin/fu-firmware-common.c b/libfwupdplugin/fu-firmware-common.c index 21bdc9a82..f5f3ab9ba 100644 --- a/libfwupdplugin/fu-firmware-common.c +++ b/libfwupdplugin/fu-firmware-common.c @@ -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; } diff --git a/libfwupdplugin/fu-self-test.c b/libfwupdplugin/fu-self-test.c index a249a3e34..3c2d9837c 100644 --- a/libfwupdplugin/fu-self-test.c +++ b/libfwupdplugin/fu-self-test.c @@ -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);