Skip to content

Commit 271b839

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. 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 0d9b5ec commit 271b839

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)