From 3b04b7673178197110ec10f6ef2db727327a1c2f Mon Sep 17 00:00:00 2001 From: Denis Balashov Date: Mon, 10 Aug 2026 11:48:36 +0300 Subject: [PATCH] util/file: add unit test for inspect window overflow Ticket: 8678 With an inspect window of 0xAAAAAAAB the `window * 3` guard wrapped to 1 in uint32_t arithmetic, so it passed for a 64 byte file and content_inspected was set to `file->size - window`, an underflow. (cherry picked from commit 8e551f2860f1c5a1e1ad1de4dc374fdd0cfe9598) --- src/runmode-unittests.c | 2 ++ src/util-file.c | 46 +++++++++++++++++++++++++++++++++++++++++ src/util-file.h | 4 ++++ 3 files changed, 52 insertions(+) diff --git a/src/runmode-unittests.c b/src/runmode-unittests.c index ffa82ef5aa..4898f39a00 100644 --- a/src/runmode-unittests.c +++ b/src/runmode-unittests.c @@ -89,6 +89,7 @@ #include "util-hashlist.h" #include "util-pool.h" #include "util-byte.h" +#include "util-file.h" #include "util-proto-name.h" #include "util-macset.h" #include "util-flow-rate.h" @@ -217,6 +218,7 @@ static void RegisterUnittests(void) SourceWinDivertRegisterTests(); #endif SCProtoNameRegisterTests(); + FileRegisterTests(); UtilCIDRTests(); OutputJsonStatsRegisterTests(); CoredumpConfigRegisterTests(); diff --git a/src/util-file.c b/src/util-file.c index 8a153779f5..d4a5baccaf 100644 --- a/src/util-file.c +++ b/src/util-file.c @@ -1192,3 +1192,49 @@ static void FileEndSha256(File *ff) ff->flags |= FILE_SHA256; } } + +#ifdef UNITTESTS +#include "util-unittest.h" + +/** + * \test the inspect window guard must not wrap around + * + * `window * 3` used to be computed in uint32_t arithmetic. The guard is there + * to make sure `file->size > window`, so on wrap around `file->size - window` + * underflows and content_inspected ends up bogus. + */ +static int FilePruneInspectWindowOverflowTest(void) +{ + const int detect_disabled = g_detect_disabled; + g_detect_disabled = 0; + + StreamingBufferConfig sbcfg = STREAMING_BUFFER_CONFIG_INITIALIZER; + FileContainer *ffc = FileContainerAlloc(); + FAIL_IF_NULL(ffc); + + uint8_t data[64]; + memset(data, 'A', sizeof(data)); + + FAIL_IF(FileOpenFileWithId(ffc, &sbcfg, 0, (const uint8_t *)"f", 1, NULL, 0, + FILE_NOMAGIC | FILE_NOMD5 | FILE_NOSHA1 | FILE_NOSHA256) != 0); + FAIL_IF_NULL(ffc->tail); + + /* 0xAAAAAAAB * 3 is 1 when truncated to 32 bits */ + FileSetInspectSizes(ffc->tail, 0xAAAAAAABU, 1); + FAIL_IF(FileAppendData(ffc, &sbcfg, data, sizeof(data)) != 0); + + FilePrune(ffc, &sbcfg); + + FAIL_IF_NULL(ffc->head); + FAIL_IF(ffc->head->content_inspected != 0); + + FileContainerFree(ffc, &sbcfg); + g_detect_disabled = detect_disabled; + PASS; +} + +void FileRegisterTests(void) +{ + UtRegisterTest("FilePruneInspectWindowOverflowTest", FilePruneInspectWindowOverflowTest); +} +#endif /* UNITTESTS */ diff --git a/src/util-file.h b/src/util-file.h index 3e42efda65..69e2f9a0a5 100644 --- a/src/util-file.h +++ b/src/util-file.h @@ -252,4 +252,8 @@ void FilePrintFlags(const File *file); void FilesPrune(FileContainer *fc, const StreamingBufferConfig *sbcfg, const bool trunc); +#ifdef UNITTESTS +void FileRegisterTests(void); +#endif + #endif /* SURICATA_UTIL_FILE_H */