The public source passed. The phone did not.
An Android NDK bug report describes wcscspn() and wcspbrk() returning the wrong position on September Android 17 builds when a wide string contains a character at or above U+0100. The report includes device fingerprints, a small C reproducer, expected output, measured output, a full Unicode sweep, and a downstream failure involving scripts and paths.[1]
The public android17-release source available to the reporter used a plain nested loop and did not contain the observed defect. The reporter inspected the shipped libc.so and found another path. That code used a 256-byte lookup table, then stopped when the input character reached U+0100. An Android project collaborator replied that the report was correct and that the public latest-release source was too old to contain the relevant changes.[1]
Source availability is not source identity. Pin the bytes that ran before you explain why they failed.
The release policy explains the gap.
Android's download documentation says that, effective in 2026, source is published to AOSP in the second and fourth quarters. It directs builders and contributors to android-latest-release, which points to the most recent release pushed to AOSP.[2] The site update page says that manifest currently points to android17-release.[3]
That policy tells a developer what the public branch means. It does not promise that the branch matches every newer binary already present on a device. In this report, the public June source and the September device build were different evidence. Treating them as one artifact would hide the bug instead of explaining it.
Disassembly is a witness, not a source release.
The reporter's disassembly supports a narrow claim about the shipped function. It shows the branch structure that matches the measured failure. It does not recover comments, original names, build flags, every source-level transformation, or the complete unpublished change history.
Keep the verbs calibrated. Say the runtime reproducer failed. Say the shipped function contains instructions consistent with that failure. Say the public source did not contain those instructions. Do not claim to have reconstructed the private source or identified the authoring mistake unless another artifact proves it.
A good report survives the source gap.
Start with the exact device fingerprint and library path. Save the library digest if policy allows it. Make the smallest reproducer that shows expected and observed values. Add an unaffected comparison. Record the public source tag and file you inspected. Only then use symbols or disassembly to narrow the mechanism.
The issue did this well. It separated affected and unaffected devices. It tested one-character and multi-character sets. It swept the Unicode range. It named the public source version. It linked a downstream workaround. That packet gave the maintainer enough evidence to confirm the defect even though the matching source had not been published.
Fix the test at the boundary that failed.
The issue notes that an existing test used ASCII input and missed the behavior. A project collaborator then found another test with a wrong expected value and said new non-ASCII tests would be added. The lesson is concrete. If an optimization divides input into a fast path and a fallback path, test values on both sides of the split.
For this defect, that means values below U+0100, the first value at U+0100, characters above it, one-character sets, multi-character sets, and complement functions that reverse the stopping condition. A fix without those boundary tests can remove one bad branch while leaving the same assumption elsewhere.