From a8e56396d5d9c604b7e11ea9a0a2614173abb42d Mon Sep 17 00:00:00 2001 From: Richard Hughes Date: Thu, 29 Sep 2022 11:42:21 +0100 Subject: [PATCH] Prevent a partial fuzzing DoS when loading corrupt SREC files The SREC parser attempts to fill 1Mb of data when parsing corrupt data sections -- which in the static fuzz targets takes a long time. Correctly check that the data exists to mitigate. Fixes https://oss-fuzz.com/testcase-detail/6102934106013696 --- libfwupdplugin/fu-srec-firmware.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/libfwupdplugin/fu-srec-firmware.c b/libfwupdplugin/fu-srec-firmware.c index cc5f332c8..52ec8e390 100644 --- a/libfwupdplugin/fu-srec-firmware.c +++ b/libfwupdplugin/fu-srec-firmware.c @@ -133,6 +133,7 @@ fu_srec_firmware_tokenize_cb(GString *token, guint token_idx, gpointer user_data FuSrecFirmwareTokenHelper *helper = (FuSrecFirmwareTokenHelper *)user_data; FuSrecFirmwarePrivate *priv = GET_PRIVATE(helper->self); g_autoptr(FuSrecFirmwareRecord) rcd = NULL; + gboolean require_data = FALSE; guint32 rec_addr32; guint16 rec_addr16; guint8 addrsz = 0; /* bytes */ @@ -230,15 +231,19 @@ fu_srec_firmware_tokenize_cb(GString *token, guint token_idx, gpointer user_data switch (rec_kind) { case FU_FIRMWARE_SREC_RECORD_KIND_S0_HEADER: addrsz = 2; + require_data = TRUE; break; case FU_FIRMWARE_SREC_RECORD_KIND_S1_DATA_16: addrsz = 2; + require_data = TRUE; break; case FU_FIRMWARE_SREC_RECORD_KIND_S2_DATA_24: addrsz = 3; + require_data = TRUE; break; case FU_FIRMWARE_SREC_RECORD_KIND_S3_DATA_32: addrsz = 4; + require_data = TRUE; break; case FU_FIRMWARE_SREC_RECORD_KIND_S5_COUNT_16: addrsz = 2; @@ -306,6 +311,14 @@ fu_srec_firmware_tokenize_cb(GString *token, guint token_idx, gpointer user_data rec_addr32, (guint)rec_count - addrsz - 1); } + if (require_data && rec_count == addrsz) { + g_set_error(error, + FWUPD_ERROR, + FWUPD_ERROR_INVALID_FILE, + "S%u required data but not provided", + rec_kind); + return FALSE; + } /* data */ rcd = fu_srec_firmware_record_new(token_idx + 1, rec_kind, rec_addr32);