Fix PatchUtil charAt OOB on truncated new mode / new file mode lines#29624
Closed
moraneus wants to merge 1 commit into
Closed
Fix PatchUtil charAt OOB on truncated new mode / new file mode lines#29624moraneus wants to merge 1 commit into
moraneus wants to merge 1 commit into
Conversation
PatchUtil.applyInternal calls line.charAt(12 or 17) without checking the line length first. A truncated "new mode 1" or "new file mode 1" patch line crashes the parser with an uncaught StringIndexOutOfBoundsException that propagates up through Skyframe and terminates the Bazel server daemon. Add a length guard so the parser raises the declared PatchFailedException instead. Reported via Google OSS-VRP issue 515719440. Signed-off-by: Moran Omer <moraneus@gmail.com>
Member
|
Thanks for the bug fix.
Just to temper your expectations: this is most definitely not fixing a memory corruption. It's making Bazel return a nicer error message when a patch file is malformed, and that's all it is. Also, a word of advice: next time you open a PR with the help of an AI agent, don't copy the instructions the agent left for you into the PR description. |
Contributor
Author
|
Thanks, fair point. I've updated the description.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
PatchUtil.applyInternalcallsline.charAt(12)forNEW_MODElines andline.charAt(17)forNEW_FILE_MODElines without verifying the line is long enough. A patch file containing a truncated mode line — for examplenew mode 1ornew file mode 1— passes the prefix-based line-type classification (because the classifier only checksstartsWith("new mode ")/startsWith("new file mode ")) and then crashes incharAtwithStringIndexOutOfBoundsException.That exception is not declared on
PatchUtil.apply(which throwsIOExceptionandPatchFailedException) and is not caught by the callers (StarlarkRepositoryContext.patch,ModuleFileFunction.applyPatchesToModuleFile). It propagates all the way up through Skyframe'sRepositoryFetchFunctionasRuntimeException: Unrecoverable error..., hits Bazel's top-level fatal handler, and causes:The Bazel server daemon then exits. Confirmed end-to-end on Bazel 9.1.0 with a 35-byte patch supplied through a Bzlmod
module_extensionand reproduced on master HEAD.Reachability
PatchUtil.applyis reached from:http_archive(patches=...)/git_repository(patches=...)single_version_override(patches=...)inMODULE.bazelsource.json#patchesmap (any module in any configured registry, including the Bazel Central Registry)ctx.patch()from anyrepository_rule/module_extensionAll of these accept attacker-influenced patch content. A malicious or compromised module in a registry can ship a 35-byte patch that crashes every Bazel server that resolves it.
Fix
Add a length guard before the
charAt(index)so that a truncated mode line produces the declaredPatchFailedExceptioninstead of an uncheckedStringIndexOutOfBoundsException.Tests added
Two new regression tests in
PatchUtilTestcovering both index sites:testTruncatedNewFileModeRaisesPatchFailed—"new file mode 1"(length 15) at thecharAt(17)site.testTruncatedNewModeRaisesPatchFailed—"new mode 1"(length 10) at thecharAt(12)site.Both assert the call throws
PatchFailedExceptionwith"Truncated file mode"in the message.How to reproduce on master before the fix
Workspace (3 files):
Then
bazel build //:allprints the FATAL crash above; the Bazel server PID is gone after the command exits.With this patch applied the same input fails cleanly with a
Truncated file mode at line 2: new mode 1error and the server stays alive.Notes
Found via Jazzer fuzzing of
PatchUtil.apply.