Project

General

Profile

Bug #9162 » regression_test_snippet_pcap_directory.c

Jason Ish, 10/05/2026 05:57 PM

 
// Suggested regression tests for PcapDirectoryDispatchForTimeRange() in
// src/source-pcap-file-directory-helper.c.
//
// source-pcap-file-directory-helper.c has no unit tests in oisf/main today, so
// three pieces are needed:
//
// 1. The tests, appended at the end of source-pcap-file-directory-helper.c
// together with their registration function:

#ifdef UNITTESTS

/** \test CleanupPcapFileDirectoryVars(NULL) must not crash. */
static int PcapDirectoryHelperCleanupNullTest(void)
{
CleanupPcapFileDirectoryVars(NULL);
PASS;
}

/** \test CleanupPendingFile(NULL) must not crash. */
static int PcapDirectoryHelperCleanupPendingFileNullTest(void)
{
CleanupPendingFile(NULL);
PASS;
}

/**
* \test After CleanupPcapFileFileVars() the pointer
* must be NULLed before any early return so that
* CleanupPcapFileDirectoryVars() cannot double-free it on teardown.
*
* Simulates the FAILED branch of PcapDirectoryDispatchForTimeRange():
* pv->current_file = pftv;
* PcapFileDispatch(pftv); -- returns TM_ECODE_FAILED
* CleanupPcapFileFileVars(pftv); -- frees pftv
* pv->current_file = NULL; -- the fix
* ... early return ...
* Then thread teardown calls CleanupPcapFileDirectoryVars(pv).
* Without the fix, current_file would still point at freed memory and
* CleanupPcapFileDirectoryVars would call CleanupPcapFileFileVars again
* (double-free / use-after-free).
*/
static int PcapDirectoryHelperCurrentFileNullAfterFileCleanupTest(void)
{
PcapFileDirectoryVars *pv = SCCalloc(1, sizeof(PcapFileDirectoryVars));
FAIL_IF_NULL(pv);
TAILQ_INIT(&pv->directory_content);

PcapFileFileVars *pftv = SCCalloc(1, sizeof(PcapFileFileVars));
if (unlikely(pftv == NULL)) {
SCFree(pv);
FAIL;
}

pv->current_file = pftv;

/* mirror the fixed code path in PcapDirectoryDispatchForTimeRange */
CleanupPcapFileFileVars(pftv);
pv->current_file = NULL;

/* verify the invariant the fix establishes */
FAIL_IF_NOT_NULL(pv->current_file);

/* teardown must not double-free; hands ownership of pv to the callee */
CleanupPcapFileDirectoryVars(pv);
PASS;
}

void PcapDirectoryHelperRegisterTests(void)
{
UtRegisterTest("PcapDirectoryHelperCleanupNullTest",
PcapDirectoryHelperCleanupNullTest);
UtRegisterTest("PcapDirectoryHelperCleanupPendingFileNullTest",
PcapDirectoryHelperCleanupPendingFileNullTest);
UtRegisterTest("PcapDirectoryHelperCurrentFileNullAfterFileCleanupTest",
PcapDirectoryHelperCurrentFileNullAfterFileCleanupTest);
}
#endif /* UNITTESTS */

// 2. The declaration, in src/source-pcap-file-directory-helper.h before the
// final #endif:
//
// #ifdef UNITTESTS
// void PcapDirectoryHelperRegisterTests(void);
// #endif
//
// 3. The call, in src/runmode-unittests.c right after
// SourcePcapFileHelperRegisterTests():
//
// PcapDirectoryHelperRegisterTests();
//
// and, next to the existing `#include "source-pcap-file-helper.h"`:
//
// #include "source-pcap-file-directory-helper.h"
(2-2/2)