Fix off-by-one bounds checks in Paint_SetPixel() (out-of-bounds write) - #426
Open
timmg wants to merge 1 commit into
Open
Fix off-by-one bounds checks in Paint_SetPixel() (out-of-bounds write)#426timmg wants to merge 1 commit into
timmg wants to merge 1 commit into
Conversation
Paint.Width/Height and Paint.WidthMemory/HeightMemory are counts, so the last valid index is one less. Both guards used '>', which let Xpoint == Paint.Width and Ypoint == Paint.Height through and wrote outside the caller's buffer. This is reachable from the public API: Paint_DrawRectangle() validates its own arguments with '>' as well, so passing Xend == Paint.Width is accepted, and at DOT_PIXEL_2X2 or larger Paint_DrawPoint() reaches Paint_SetPixel() with Xpoint == Paint.Width. Paint_SetPixel() is the single point through which all pixel writes pass, so correcting it here protects every drawing primitive. Applied to all 42 copies of GUI_Paint.c in the repository; the change is identical in each.
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.
Both bounds checks in
Paint_SetPixel()use>where they need>=, so a coordinate equal to the width or height passes validation and writes outside the caller's buffer.Paint.Width/Paint.Height(andPaint.WidthMemory/Paint.HeightMemory) are counts, so the last valid index is one less than the value.This is reachable from the public API
Paint_DrawRectangle()validates its own arguments with>too, soXend == Paint.Widthis accepted. AtDOT_PIXEL_2X2or larger,Paint_DrawPoint()'s loop reachesPaint_SetPixel(Xpoint + XDir_Num - 1, ...)withXDir_Num == 1, i.e.Xpointitself — soPaint_SetPixel()is called withXpoint == Paint.Width.(At
DOT_PIXEL_1X1the- 1happens to pull it back in bounds, which is why this rarely shows up.)Compiling the unmodified
RaspberryPi_JetsonNano/c/lib/GUI/GUI_Paint.cwith AddressSanitizer and an exactly-sized buffer:With this change applied, the same program is ASan-clean.
Rendering is unchanged
The guard now rejects only writes that were already out of bounds, so no legitimate pixel is lost. Verified by rendering a scene using in-range coordinates only — nested rectangles filled and unfilled, diagonal lines at
DOT_PIXEL_3X3and dotted, filled and unfilled circles, and a row ofDOT_FILL_AROUNDpoints along the last row — then comparing the output buffers:Scope
The repository contains 42 copies of
GUI_Paint.cand all 42 have both bugs. The change is applied to every copy and is byte-identical in each — reviewing one file covers all of them:Paint_SetPixel()is the single point every pixel write passes through, so fixing it there protects all the drawing primitives without touching them individually.Note: callers that relied on
Paint_DrawRectangle(0, 0, W, H, ...)will now have that last row/column clipped rather than written out of bounds.W-1, H-1is the correct call and is unaffected.🤖 Generated with Claude Code
Fixes #427 — that issue has the full write-up and a standalone reproduction.