Repository navigation
pclmtoraster: reject a page whose image stream is shorter than declared - #276
Open
ManasBagul23 wants to merge 1 commit into
Open
ManasBagul23 wants to merge 1 commit into
ManasBagul23 wants to merge 1 commit into
Conversation
process_image() grows data->bitmap by exactly the number of bytes it actually reads from each PDF image's decoded stream (data->pixel_count), independently of the Width/Height the same image object declares in its dictionary. out_page() then derives data->rowsize from the declared cupsWidth/colorspace and walks data->bitmap for cupsHeight rows of rowsize bytes each -- both in rotate_bitmap() and in the per-line convertline()/cupsRasterWritePixels() loop -- without ever checking that pixel_count actually covers rowsize * cupsHeight. A syntactically valid PDF/PCLm page that declares large dimensions but supplies a short (or near-empty) image stream reaches a heap-buffer-overflow read in both paths, and a heap-buffer-overflow write in rotate_bitmap()'s destination once a rotation is applied (OpenPrinting#185). Validate pixel_count against the declared geometry (in size_t, so a large declared width/height can't wrap the comparison itself) right after the convert function -- and therefore rowsize -- is selected, and before any rotation or pixel conversion touches the buffer. Reject the page the same way the existing cupsRasterWriteHeader() failure a few lines above does: log and return 1. The check only applies when the page actually declares pixel rows (cupsHeight > 0) and a page actually decoded some data (rowsize > 0), so a legitimate empty/blank page still raster-writes just its header as before. Verified by tracing data->pixel_count's only producer (process_image(), now already fixed upstream to read each image stream to completion) and rowsize's definition (header.cupsWidth and the selected colorspace, both attacker-declared) against both consumers this guard protects: rotate_bitmap() and the convertline() loop in out_page(). No C build toolchain available locally to compile-check. Fixes OpenPrinting#185
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.
process_image()growsdata->bitmapby exactly the number of bytes it actually reads from each PDF image's decoded stream (data->pixel_count), independently of the Width/Height the same image object declares in its dictionary.out_page()then derivesdata->rowsizefrom the declaredcupsWidth/colorspace and walksdata->bitmapforcupsHeightrows ofrowsizebytes each -- both inrotate_bitmap()and in the per-lineconvertline()/cupsRasterWritePixels()loop -- without ever checking thatpixel_countactually coversrowsize * cupsHeight.A syntactically valid PDF/PCLm page that declares large dimensions but supplies a short (or near-empty) image stream reaches a heap-buffer-overflow read in both paths, and a heap-buffer-overflow write in
rotate_bitmap()'s destination once a rotation is applied (#185).Validate
pixel_countagainst the declared geometry (insize_t, so a large declared width/height can't wrap the comparison itself) right after the convert function -- and thereforerowsize-- is selected, and before any rotation or pixel conversion touches the buffer. Reject the page the same way the existingcupsRasterWriteHeader()failure a few lines above does: log and return 1. The check only applies when the page actually declares pixel rows (cupsHeight > 0) and a page actually decoded some data (rowsize > 0), so a legitimate empty/blank page still raster-writes just its header as before.Verified by tracing
data->pixel_count's only producer (process_image(), now already fixed upstream to read each image stream to completion) androwsize's definition (header.cupsWidthand the selected colorspace, both attacker-declared) against both consumers this guard protects:rotate_bitmap()and theconvertline()loop inout_page(). No C build toolchain available locally to compile-check.Fixes #185