Do not leak when calling fu_firmware_parse() multiple times

This commit is contained in:
Richard Hughes 2021-11-24 10:12:22 +00:00
parent 019a210c94
commit 0e175181ea
3 changed files with 21 additions and 0 deletions

View File

@ -683,6 +683,13 @@ fu_firmware_parse_full(FuFirmware *self,
g_return_val_if_fail(error == NULL || *error == NULL, FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
/* sanity check */ /* 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) { if (g_bytes_get_size(fw) == 0) {
g_set_error_literal(error, g_set_error_literal(error,
FWUPD_ERROR, FWUPD_ERROR,
@ -691,6 +698,10 @@ fu_firmware_parse_full(FuFirmware *self,
return FALSE; 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 */ /* subclassed */
if (klass->tokenize != NULL) { if (klass->tokenize != NULL) {
if (!klass->tokenize(self, fw, flags, error)) if (!klass->tokenize(self, fw, flags, error))

View File

@ -108,6 +108,14 @@ struct _FuFirmwareClass {
* Since: 1.5.6 * Since: 1.5.6
**/ **/
#define FU_FIRMWARE_FLAG_HAS_VID_PID (1u << 3) #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: * FuFirmwareFlags:

View File

@ -18,6 +18,8 @@ LLVMFuzzerTestOneInput(const guint8 *data, gsize size)
g_setenv("G_DEBUG", "fatal-criticals", FALSE); g_setenv("G_DEBUG", "fatal-criticals", FALSE);
ret = fu_firmware_parse(firmware, fw, FWUPD_INSTALL_FLAG_NONE, NULL); ret = fu_firmware_parse(firmware, fw, FWUPD_INSTALL_FLAG_NONE, NULL);
if (!ret && fu_firmware_has_flag(firmware, FU_FIRMWARE_FLAG_HAS_CHECKSUM)) { 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, ret = fu_firmware_parse(firmware,
fw, fw,
FWUPD_INSTALL_FLAG_NO_SEARCH | FWUPD_INSTALL_FLAG_NO_SEARCH |