Skip to content

Compute the attribution pc with integer arithmetic - #835

Merged
rkennke merged 1 commit into
mainfrom
fix/attribution-pc-ub
Oct 3, 2026
Merged

rkennke merged 1 commit into
mainfrom
fix/attribution-pc-ub

Conversation

@rkennke

@rkennke rkennke commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?:

Makes attributionPC() subtract 1 from the return address with uintptr_t arithmetic instead of const char* arithmetic.

Motivation:

During an optimistic unwind, walkVM can read garbage such as 0 or 0x1 from a return-address slot and hand it to resolveNativeFrameForWalkVM() → attributionPC(). Offsetting a pointer to or from null is undefined behavior, and UBSan's pointer-overflow check reports it:

  • Nightly Sanitized Run on main (2026-09-30 onward): stackWalker.inline.h:64:65: runtime error: applying non-zero offset 18446744073709551615 to null pointer (pc == nullptr), about 30 reports per run.
  • feat(wall): support signal suppression for unfiltered threads #663 CI, glibc-aarch64/asan/JDK 25: applying non-zero offset to non-null pointer 0x000000000001 produced null pointer (pc == 0x1), from both the wall-clock and CPU signal handlers.

In the sanitized test config (halt_on_error=0, log_path=/tmp/asan.log) these don't fail a test. Instead the test JVM exits with code 1 at shutdown, and the report only appears in the asan-logs-* artifact.

Unsigned wrap-around is well defined, and the resulting address (UINTPTR_MAX or 0) still matches no library and no FDE, so attribution output is unchanged. This also covers the 0x1 case, which a pc != nullptr guard does not.

I checked the other address arithmetic added by the return-address attribution changes (#786, #813, #830, #831). The remaining sites already use integer arithmetic (pc() -= 1 on uintptr_t&, pc_offset on uintptr_t) or operate on addresses already validated to lie inside a library (the DW_PC_OFFSET recovered pc in dwarfStep.inline.h), so attributionPC() is the only place that needed changing.

How to test the change?:

New gtest ReturnAddressAttributionCharacterizationTest.AttributionPcOfGarbageNearNullIsDefined feeds 0 and 0x1 through attributionPC().

  • gtestAsan_returnAddressAttribution_ut (glibc aarch64 container): aborts with the UBSan report without the fix and passes with it.
  • gtestDebug_returnAddressAttribution_ut (macOS): passes.

For Datadog employees:

  • If this PR touches code that signs or publishes builds or packages, or handles credentials of any kind, I've requested a security review.
  • This PR doesn't touch any of that.
  • JIRA: [PROF-XXXX]

🤖 Generated with Claude Code

attributionPC() subtracted 1 from a char pointer. During an optimistic
unwind the pc can be garbage read from a return-address slot; for 0 or
0x1 that offsets a pointer to or from null, which is undefined behavior
and is reported by UBSan's pointer-overflow check from walkVM's native
frame resolution. Do the subtraction on uintptr_t instead, where
wrap-around is defined; the resulting address still matches no library
and no FDE, so attribution is unchanged.

Add a gtest that feeds 0 and 0x1 through attributionPC(), which aborts
under the asan config's -fsanitize=pointer-overflow before this change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rkennke
rkennke requested a review from a team as a code owner October 2, 2026 17:34

@datadog-datadog-prod-us1 datadog-datadog-prod-us1 Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Bits Code Review: PASS

More details

Near-null return addresses now wrap through uintptr_t arithmetic without pointer-overflow undefined behavior while retaining the same attribution outcome.

Was this helpful? React 👍 or 👎

Open Bits AI session

🤖 Bits Code Review · Commit 17db8d9 · @DataDog review to ask questions

@dd-octo-sts

dd-octo-sts Bot commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

✅ All 40 integration tests passed

📊 Dashboard · 👷 Pipeline · 📦 17db8d91

@dd-octo-sts

dd-octo-sts Bot commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

CI Test Results

Run: #37041712180 | Commit: 231199d | Duration: 1h 45m 22s (longest job)

✅ All 32 test jobs passed

Status Overview

JDK glibc-aarch64/debug glibc-amd64/debug musl-aarch64/debug musl-amd64/debug
8 - ✅ - -
8-ibm - ✅ - -
8-j9 ✅ ✅ - -
8-librca - - ✅ ✅
8-orcl - ✅ - -
11 - ✅ - -
11-j9 ✅ ✅ - -
11-librca - - ✅ ✅
17 ✅ ✅ - -
17-graal ✅ ✅ - -
17-j9 ✅ ✅ - -
17-librca - - ✅ ✅
21 ✅ ✅ - -
21-graal ✅ ✅ - -
21-librca - - ✅ ✅
25 ✅ ✅ - -
25-graal ✅ ✅ - -
25-librca - - ✅ ✅

Legend: ✅ passed | ❌ failed | ⚪ skipped | 🚫 cancelled

Summary: Total: 32 | Passed: 32 | Failed: 0


Updated: 2026-10-03 07:04:29 UTC

@rkennke
rkennke merged commit 041b24a into main Oct 3, 2026
195 of 196 checks passed
@rkennke
rkennke deleted the fix/attribution-pc-ub branch October 3, 2026 08:08
@github-actions github-actions Bot added this to the 1.52.0 milestone Oct 3, 2026
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.

1 participant