diff --git a/libfwupdplugin/fu-firmware.c b/libfwupdplugin/fu-firmware.c index da74eaa69..6d5346e53 100644 --- a/libfwupdplugin/fu-firmware.c +++ b/libfwupdplugin/fu-firmware.c @@ -683,6 +683,13 @@ fu_firmware_parse_full(FuFirmware *self, g_return_val_if_fail(error == NULL || *error == NULL, FALSE); /* sanity check */ + if (fu_firmware_has_flag(self, FU_FIRMWARE_FLAG_DONE_PARSE)) { + g_set_error_literal(error, + FWUPD_ERROR, + FWUPD_ERROR_NOT_SUPPORTED, + "firmware object cannot be reused"); + return FALSE; + } if (g_bytes_get_size(fw) == 0) { g_set_error_literal(error, FWUPD_ERROR, @@ -691,6 +698,10 @@ fu_firmware_parse_full(FuFirmware *self, return FALSE; } + /* any FuFirmware subclass that gets past this point might have allocated memory in + * ->tokenize() or ->parse() and needs to be destroyed before parsing again */ + fu_firmware_add_flag(self, FU_FIRMWARE_FLAG_DONE_PARSE); + /* subclassed */ if (klass->tokenize != NULL) { if (!klass->tokenize(self, fw, flags, error)) diff --git a/libfwupdplugin/fu-firmware.h b/libfwupdplugin/fu-firmware.h index a4b3434a7..75bf71772 100644 --- a/libfwupdplugin/fu-firmware.h +++ b/libfwupdplugin/fu-firmware.h @@ -108,6 +108,14 @@ struct _FuFirmwareClass { * Since: 1.5.6 **/ #define FU_FIRMWARE_FLAG_HAS_VID_PID (1u << 3) +/** + * FU_FIRMWARE_FLAG_DONE_PARSE: + * + * The firmware object has been used by fu_firmware_parse_full(). + * + * Since: 1.7.3 + **/ +#define FU_FIRMWARE_FLAG_DONE_PARSE (1u << 4) /** * FuFirmwareFlags: diff --git a/libfwupdplugin/fu-fuzzer-firmware.c.in b/libfwupdplugin/fu-fuzzer-firmware.c.in index 57c1551d3..de161f0c4 100644 --- a/libfwupdplugin/fu-fuzzer-firmware.c.in +++ b/libfwupdplugin/fu-fuzzer-firmware.c.in @@ -18,6 +18,8 @@ LLVMFuzzerTestOneInput(const guint8 *data, gsize size) g_setenv("G_DEBUG", "fatal-criticals", FALSE); ret = fu_firmware_parse(firmware, fw, FWUPD_INSTALL_FLAG_NONE, NULL); if (!ret && fu_firmware_has_flag(firmware, FU_FIRMWARE_FLAG_HAS_CHECKSUM)) { + g_clear_object(&firmware); + firmware = FU_FIRMWARE(@FIRMWARENEW@()); ret = fu_firmware_parse(firmware, fw, FWUPD_INSTALL_FLAG_NO_SEARCH |