Skip to content

imagetoraster: reject output dimensions that overflow cupsBytesPerLine - #264

Open
ManasBagul23 wants to merge 1 commit into
OpenPrinting:masterfrom
ManasBagul23:fix-imagetoraster-bytesperline-overflow
Open

ManasBagul23 wants to merge 1 commit into
OpenPrinting:masterfrom
ManasBagul23:fix-imagetoraster-bytesperline-overflow

Conversation

@ManasBagul23

Copy link
Copy Markdown

Fixes #184.

header.cupsBytesPerLine was computed as:

header.cupsBytesPerLine = (header.cupsBitsPerPixel *
                           header.cupsWidth + 7) / 8;

Both operands are unsigned 32-bit fields. A PPD offering an extreme RGB16 resolution together with a small, low-PPI image can drive cupsWidth into the tens of millions; multiplied by a wide pixel depth (e.g. 48 bits for RGB16), the product overflows 32-bit unsigned arithmetic and wraps to a small value before the +7/8 rounds it down to bytes. The formatter (format_cmy/format_RGB) still writes a full row's worth of pixels, well past the undersized buffer that was allocated from the wrapped cupsBytesPerLine.

Compute the row size in a wider type (size_t, including the CUPS_ORDER_BANDED multiply, which could also push a borderline value over) and reject the page if it doesn't fit in the unsigned field cupsBytesPerLine actually is, instead of silently wrapping and handing a too-small value downstream.

Verified: traced header.cupsBytesPerLine's consumers (the allocation at the row-buffer setup, and the format_cmy/format_RGB write loops that iterate cupsWidth pixels regardless of what cupsBytesPerLine says) to confirm all of them are protected once this guard holds. No C build toolchain available locally to compile-check.

header.cupsBytesPerLine was computed as:

    header.cupsBytesPerLine = (header.cupsBitsPerPixel *
                               header.cupsWidth + 7) / 8;

Both operands are unsigned 32-bit fields. A PPD offering an extreme
RGB16 resolution together with a small, low-PPI image can drive
cupsWidth into the tens of millions; multiplied by a wide pixel depth
(e.g. 48 bits for RGB16), the product overflows 32-bit unsigned
arithmetic and wraps to a small value before the +7/8 rounds it down
to bytes. The formatter (format_cmy/format_RGB) still writes a full
row's worth of pixels, well past the undersized buffer that was
allocated from the wrapped cupsBytesPerLine.

Compute the row size in a wider type (size_t, including the
CUPS_ORDER_BANDED multiply, which could also push a borderline value
over) and reject the page if it doesn't fit in the unsigned field
cupsBytesPerLine actually is, instead of silently wrapping and handing
a too-small value downstream.

Verified by tracing header.cupsBytesPerLine's consumers (the
allocation at the cupsRasterOpen/row-buffer setup further down, and
the format_cmy/format_RGB write loops that iterate cupsWidth pixels
regardless of what cupsBytesPerLine says) to confirm all of them are
protected once this guard holds. No C build toolchain available
locally to compile-check.

Fixes OpenPrinting#184
Copilot AI balanced review requested due to automatic review settings October 2, 2026 23:16

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

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.

imagetoraster: RGB16 row-size multiplication wraps before allocation

2 participants