Skip to content

Reject custom page size parameters of the wrong type - #94

Merged
tillkamppeter merged 1 commit into
OpenPrinting:masterfrom
alepacheco:fix-custom-pagesize-param-types
Oct 31, 2026
Merged

tillkamppeter merged 1 commit into
OpenPrinting:masterfrom
alepacheco:fix-custom-pagesize-param-types

Conversation

@alepacheco

Copy link
Copy Markdown
Contributor

Fixes #83.

ppdPageSize() stores a custom page size in the Width and Height parameters of the PageSize custom option as points (current.custom_points), but _ppdOpen() accepted any type for them. With a PPD declaring, for example,

*ParamCustomPageSize Height: 2 string 0 80

selecting a custom size writes a float into the parameter's value, and ppdClose() then frees current.custom_string, that is the float's bits, as a pointer.

This ports OpenPrinting/cups@46c5a984 ("Reject invalid custom page parameter types"): Width, Height, WidthOffset and HeightOffset must be points and Orientation must be int, otherwise ppdOpen() fails with PPD_BAD_CUSTOM_PARAM.

Two differences from the CUPS commit:

  • The option and parameter names are compared case-insensitively. ppdFindCustomOption() and ppdFindCustomParam() match names case-insensitively, so with an exact strcmp() a parameter declared as height (or under *ParamCustompagesize) passes the check and is still found and overwritten by ppdPageSize().
  • ppdPageSize() only updates the Width and Height values of points parameters, as a defensive check for code that changes a PPD's custom parameters after opening it.

Tests: a new group in test_ppd_custom (T25-T33) checks the custom size update, that valid parameter sets still open (including a non-PageSize option's Width of another type), and that each wrong type, also with lower-case names, fails with PPD_BAD_CUSTOM_PARAM. Without the fix the six rejection cases fail; with it all 33 pass, and the rest of make check passes as before.

Compatibility: I checked the PPDs of the foomatic-db, OpenPrinting, HP PostScript and HPLIP PPD archives (about 12,400 files). All of the roughly 9,000 with a custom page size declare exactly these types, so none of them is rejected.

ppdPageSize() stores a custom page size in the Width and Height
parameters of the PageSize custom option as points, but the PPD parser
accepted any type for them.  A PPD declaring Width or Height as a
string, passcode or password parameter therefore got a float written
into the parameter's value, and ppdClose() later freed it as a string
pointer (issue OpenPrinting#83).

Port CUPS commit 46c5a984: reject Width, Height, WidthOffset and
HeightOffset parameters that are not points, and an Orientation that is
not an int, with PPD_BAD_CUSTOM_PARAM.  Compare the option and
parameter names case-insensitively, as ppdFindCustomOption() and
ppdFindCustomParam() look them up: with an exact compare, a parameter
named "height" passes the check and is still found and overwritten by
ppdPageSize().  Also only update the Width and Height values in
ppdPageSize() when they are points parameters.

Add tests for both to test_ppd_custom.

Fixes OpenPrinting#83
@alepacheco

Copy link
Copy Markdown
Contributor Author

Thanks for approving the CI run. The 12 Build & Test failures are all in test_ppd_generator: the three printer-make-and-model checks added in #89 ('\n', '"' and '\\'), which have failed the same way on master since 0598346 (and in the a07efcb run). This PR only touches ppd.c, ppd-page.c and test_ppd_custom.c, and test_ppd_custom passes on all 12 legs.

For whoever picks up the master failure: in each of those checks the make-and-model ends up a single word. It's "Acme" once ppdCreatePPDFromIPP2() cuts it at the first control character or quote, and "Acme\Model" in the backslash case. With no model part, the generator falls back to *Manufacturer: "Unknown", so the strings the checks look for never appear. The generated PPD has no injected line; the test inputs just need a make and a model (e.g. "Acme Laser\n...").

@tillkamppeter

Copy link
Copy Markdown
Member

Thanks for approving the CI run. The 12 Build & Test failures are all in test_ppd_generator: the three printer-make-and-model checks added in #89 ('\n', '"' and '\\'), which have failed the same way on master since 0598346 (and in the a07efcb run). This PR only touches ppd.c, ppd-page.c and test_ppd_custom.c, and test_ppd_custom passes on all 12 legs.

For whoever picks up the master failure: in each of those checks the make-and-model ends up a single word. It's "Acme" once ppdCreatePPDFromIPP2() cuts it at the first control character or quote, and "Acme\Model" in the backslash case. With no model part, the generator falls back to *Manufacturer: "Unknown", so the strings the checks look for never appear. The generated PPD has no injected line; the test inputs just need a make and a model (e.g. "Acme Laser\n...").

Could you fix that in a separate PR? Thanks.

@tillkamppeter
tillkamppeter merged commit 758c24e into OpenPrinting:master Oct 31, 2026
3 of 15 checks passed
@alepacheco

Copy link
Copy Markdown
Contributor Author

Thanks for merging! Sure, I'll open a separate PR that fixes those test_ppd_generator inputs.

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.

libppd: Custom PageSize type confusion reaches an invalid free

2 participants