From 4f59a6462a6adccfd88e8ef50cb7740e5b131ac5 Mon Sep 17 00:00:00 2001 From: Ronit Mehta Date: Sat, 14 Nov 2026 04:50:09 +0530 Subject: [PATCH] ppd-ipp.c: Prevent stack buffer overflow on >20-item PPD attributes In ppdLoadAttributes(), bound the comma-separated attribute splitting loop to the capacity of items[20] (sizeof(items) / sizeof(items[0])), guard against NULL ppd_attr->value, and explicitly null-terminate buf after strncpy(). Previously, a cupsUrfSupported, cupsPwgRaster*, or cupsPclm* attribute with more than 20 comma-separated values wrote past items[20] (and res_x[20]/res_y[20]/int_item[20]) on the stack. Add regression test T70 in ppd/test_ppd_ipp.c verifying a 21-item cupsPwgRasterAuditSupported attribute is safely capped at 20 items. Fixes #85 Signed-off-by: Ronit Mehta --- ppd/ppd-ipp.c | 5 ++++- ppd/test_ppd_ipp.c | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/ppd/ppd-ipp.c b/ppd/ppd-ipp.c index c21d36c5..8f23ff04 100644 --- a/ppd/ppd-ipp.c +++ b/ppd/ppd-ipp.c @@ -612,8 +612,11 @@ ppdLoadAttributes( { // Convert PPD-style names into IPP-style names ppdPwgUnppdizeName(ppd_attr->name + 4, item_buf, sizeof(item_buf), NULL); + if (!ppd_attr->value) + continue; // Make array from comma-separated list strncpy(buf, ppd_attr->value, sizeof(buf) - 1); + buf[sizeof(buf) - 1] = '\0'; num_items = 0; char *p = buf; do @@ -633,7 +636,7 @@ ppdLoadAttributes( items[num_items - 1][0] == 'R' && items[num_items - 1][1] == 'S') xres = yres = atoi(items[num_items - 1] + 2); } - while (p); + while (p && num_items < (int)(sizeof(items) / sizeof(items[0]))); if (strlen(items[0]) > 3 && strncasecmp(items[0] + strlen(items[0]) - 3, "dpi", 3) == 0 && isdigit(*(items[0] + strlen(items[0]) - 4))) diff --git a/ppd/test_ppd_ipp.c b/ppd/test_ppd_ipp.c index 42910ea8..8814390c 100644 --- a/ppd/test_ppd_ipp.c +++ b/ppd/test_ppd_ipp.c @@ -1002,6 +1002,29 @@ main(void) ippDelete(job_attrs); + // T70 — 21-item comma-separated raster attribute must not overflow items[20] + // in ppdLoadAttributes() (Issue #85). + testBegin("ppdLoadAttributes(21-item cupsPwgRaster attribute) caps at 20 items"); + { + FILE *f21 = tmpfile(); + fputs(test_ppd_text, f21); + fputs("*cupsFilter: \"image/pwg-raster 0 rastertopwg\"\n" + "*cupsPwgRasterAuditSupported: \"v1,v2,v3,v4,v5,v6,v7,v8,v9,v10," + "v11,v12,v13,v14,v15,v16,v17,v18,v19,v20,v21\"\n", f21); + rewind(f21); + ppd_file_t *ppd21 = ppdOpen(f21); + fclose(f21); + ipp_t *attrs21 = ppdLoadAttributes(ppd21); + ipp_attribute_t *audit_attr = ippFindAttribute(attrs21, + "pwg-raster-audit-supported", + IPP_TAG_KEYWORD); + int count = audit_attr ? ippGetCount(audit_attr) : -1; + testEndMessage(attrs21 != NULL && count == 20, "count=%d", count); + ippDelete(attrs21); + ppdClose(ppd21); + } + + // ========================================================================= // Cleanup // =========================================================================