Skip to content

Fix default reporter use after free#2248

Open
devtejasx wants to merge 2 commits into
google:mainfrom
devtejasx:fix-default-reporter-use-after-free
Open

Fix default reporter use after free#2248
devtejasx wants to merge 2 commits into
google:mainfrom
devtejasx:fix-default-reporter-use-after-free

Conversation

@devtejasx

@devtejasx devtejasx commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Fixes #2240.

Root cause: CreateDefaultDisplayReporter() cached the reporter it creates in a function-local static, while every caller owns and frees the returned pointer (RunSpecifiedBenchmarks() wraps it in a std::unique_ptr). The first call therefore freed the cached object, and every later call returned a dangling pointer, producing the heap-use-after-free reported in #2240.

Fix: return a fresh, caller-owned reporter on every call, and document the ownership contract at the public declaration in benchmark_api.h.

Testing:

  • Added a regression test covering repeated CreateDefaultDisplayReporter() calls.
  • The test verifies that each call returns an independent caller-owned reporter.
  • The test fails against the old implementation and passes with this fix.
  • Release build/tests: 86/86 passed.
  • Debug build/tests: 86/86 passed.
  • Builds remain -Werror clean.

Note: the branch was rebased onto current main to remove an unrelated commit that was previously included by mistake.

AI disclosure (per AGENTS.md): this change was developed with AI assistance (Anthropic's Claude).

@LebedevRI

Copy link
Copy Markdown
Collaborator

Diff contains spurious commits.
Blame points at 6e51dcb - @dmah42 i do not understand why that static was introduced in an otherwise NFC refactoring.

CreateDefaultDisplayReporter() cached its reporter in a function-local
static and returned that pointer. But the returned pointer is owned by
the caller: RunSpecifiedBenchmarks() wraps it in a std::unique_ptr that
frees it when the call returns. The first call therefore freed the
static reporter, and the next call returned the same, now-dangling
pointer, which was dereferenced when setting up the output streams --
a heap-use-after-free reachable by simply calling RunSpecifiedBenchmarks
more than once (reported via fuzzing on the no-match filter path).

Return a fresh, caller-owned reporter on every call. Add
default_display_reporter_test, which holds two reporters from two calls
alive at once and asserts they are distinct objects; it fails on the
old static implementation and passes with this fix. Verified locally
with g++ 15.2; benchmark_test and memory_manager_test still pass.

Signed-off-by: devtejasx <tejasnagmote520@gmail.com>
@devtejasx devtejasx force-pushed the fix-default-reporter-use-after-free branch from 63a6bf9 to f1f1485 Compare July 15, 2026 19:24
@LebedevRI LebedevRI requested review from LebedevRI and dmah42 July 16, 2026 03:31
@devtejasx

Copy link
Copy Markdown
Contributor Author

Rebased — the branch is now a single commit (f1f1485) on top of current main containing only the 4-file fix. On the static: whatever the original intent in 6e51dcb, it can't be correct in the current API since both call sites (RunSpecifiedBenchmarks overloads and benchmark_main) wrap the returned pointer in a unique_ptr and free it, so the cached pointer dangles from the second call on — which is exactly what #2240 hit. This PR drops the cache so every caller gets a fresh, owned instance, with a regression test covering it.


BENCHMARK_EXPORT int32_t GetBenchmarkVerbosity();

// Creates the display reporter selected by --benchmark_format. Returns a

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if the caller is meant to own the returned type, then we should be returning a unique_ptr.

https://google.github.io/styleguide/cppguide.html#Ownership_and_Smart_Pointers

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG]Heap-use-after-free in benchmark `RunSpecifiedBenchmarks

3 participants