Skip to content

Commit 608fcda

Browse files
committed
platform: posix: ipc: expose fuzz-case staging-state hooks
The libFuzzer entry point in fuzz.c stages each testcase by writing posix_fuzz_buf/sz and raising the fuzz IRQ; fuzz_isr() then drains those bytes into the static fuzz_in[] queue and feeds them into the IPC layer one message at a time. Two pieces of state therefore survive across LLVMFuzzerTestOneInput() calls: * `posix_fuzz_sz` - the raw input length still to consume, * `fuzz_in[] / _sz` - the per-call staging queue. The fuzzer harness has no way to inspect either of them today, which makes it impossible to tell whether a previous testcase fully drained before the next one begins. That is the root cause of the "not reproducible" crashes documented in FUZZER_ISOLATION_RESEARCH.md. Introduce three small helpers, kept in the module that owns the state, with no callers yet: posix_fuzz_case_begin() - drop the staging queue at the start of a new testcase, posix_fuzz_case_pending() - true while either buffer still has bytes to deliver, posix_fuzz_case_abort() - wipe both buffers (used when a case exceeds the simulator tick budget). A follow-up commit wires these into LLVMFuzzerTestOneInput(). This commit is a pure code-addition refactor: no callers, no behaviour change, the build still emits the same object code for the existing entry points. Signed-off-by: Tomasz Leman <tomasz.m.leman@intel.com>
1 parent accf902 commit 608fcda

2 files changed

Lines changed: 59 additions & 0 deletions

File tree

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/* SPDX-License-Identifier: BSD-3-Clause */
2+
/* Copyright(c) 2026 Intel Corporation. All rights reserved. */
3+
4+
#ifndef PLATFORM_POSIX_FUZZ_H
5+
#define PLATFORM_POSIX_FUZZ_H
6+
7+
#include <stdbool.h>
8+
9+
/**
10+
* @brief Reset IPC staging state at the start of a new fuzz testcase.
11+
*
12+
* Must be called before staging new fuzz input so that any leftover
13+
* state from a previous testcase that failed to drain within the tick
14+
* budget cannot influence the new one.
15+
*/
16+
void posix_fuzz_case_begin(void);
17+
18+
/**
19+
* @brief Query whether any staged IPC fuzz input is still pending.
20+
*
21+
* @return true if the raw input buffer or the IPC staging queue is
22+
* non-empty, false when fully drained.
23+
*/
24+
bool posix_fuzz_case_pending(void);
25+
26+
/**
27+
* @brief Hard-reset all staged IPC fuzz state.
28+
*
29+
* Called when the simulator tick budget is exhausted before the input
30+
* has been fully drained, ensuring the next testcase starts clean.
31+
*/
32+
void posix_fuzz_case_abort(void);
33+
34+
#endif /* PLATFORM_POSIX_FUZZ_H */

‎src/platform/posix/ipc.c‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
// SPDX-License-Identifier: BSD-3-Clause
22
// Copyright(c) 2022 Google LLC. All rights reserved.
33
// Author: Andy Ross <andyross@google.com>
4+
#include <platform/fuzz.h>
45
#include <sof/lib/uuid.h>
56
#include <sof/ipc/msg.h>
67
#include <sof/lib/mailbox.h>
78
#include <sof/ipc/common.h>
89
#include <sof/ipc/schedule.h>
910
#include <sof/schedule/edf_schedule.h>
1011
#include <sof/audio/component_ext.h>
12+
#include <stdbool.h>
13+
#include <stddef.h>
1114

1215
// 6c8f0d53-ff77-4ca1-b825-c0c4e1b0d322
1316
SOF_DEFINE_REG_UUID(ipc_task_posix);
@@ -33,6 +36,28 @@ extern size_t posix_fuzz_sz;
3336
static uint8_t fuzz_in[65536];
3437
static size_t fuzz_in_sz;
3538

39+
/*
40+
* Testcase-isolation helpers used by the libFuzzer entry point in
41+
* fuzz.c. They keep ownership of the cross-call state in one module
42+
* so a new testcase never observes leftovers from a previous one that
43+
* failed to drain inside the simulator tick budget.
44+
*/
45+
void posix_fuzz_case_begin(void)
46+
{
47+
fuzz_in_sz = 0;
48+
}
49+
50+
bool posix_fuzz_case_pending(void)
51+
{
52+
return posix_fuzz_sz != 0 || fuzz_in_sz != 0;
53+
}
54+
55+
void posix_fuzz_case_abort(void)
56+
{
57+
posix_fuzz_sz = 0;
58+
fuzz_in_sz = 0;
59+
}
60+
3661
// The protocol here is super simple: the first byte is a message size
3762
// in units of 16 bits (the buffer maximum defaults to 384 bytes, and
3863
// I didn't want to waste space early in the buffer lest I confuse the

0 commit comments

Comments
 (0)