diff --git a/CHANGES.md b/CHANGES.md index 2894a7773..616c7042b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -42,6 +42,8 @@ v3.0.4 - YYYY-MM-DD - Fixed error checking in `cupsOAuthGetAuthorizationCode` (Issue #182) - Fixed a potential race condition in `cupsEnumDests` (Issue #186) - Fixed a bug in `cupsJSONExportString` when exporting a child node (Issue #187) +- Fixed a potential buffer overflow in `ipptransform` when transforming a + job with more than 10000 output pages - Fixed PAM support in `ippeveprinter`. - Fixed a typo in the JWT HS verification code. - Fixed `ippValidateAttribute` not returning `false` for too-long URIs. diff --git a/tools/ipptransform.c b/tools/ipptransform.c index 7e3e75e61..46700e256 100644 --- a/tools/ipptransform.c +++ b/tools/ipptransform.c @@ -213,7 +213,7 @@ static pdfio_stream_t *pdfio_start_page(xform_prepare_t *p, pdfio_dict_t *dict); static bool prepare_documents(size_t num_documents, xform_document_t *documents, ipp_options_t *options, const char *sheet_back, char *outfile, size_t outsize, const char *outformat, unsigned *outpages, bool generate_copies); static void prepare_log(xform_prepare_t *p, bool error, const char *message, ...); static void prepare_number_up(xform_prepare_t *p); -static void prepare_pages(xform_prepare_t *p, size_t num_documents, xform_document_t *documents); +static bool prepare_pages(xform_prepare_t *p, size_t num_documents, xform_document_t *documents); static void raster_end_job(xform_raster_t *ras, xform_write_cb_t cb, void *ctx); static void raster_end_page(xform_raster_t *ras, unsigned page, xform_write_cb_t cb, void *ctx); static void raster_init(xform_raster_t *ras); @@ -3372,7 +3372,11 @@ prepare_documents( options->print_scaling = IPPOPT_SCALING_FIT; // Prepare output pages... - prepare_pages(&p, num_documents, documents); + if (!prepare_pages(&p, num_documents, documents)) + { + cupsLangPrintf(stderr, _("%s: Too many pages to transform (%d maximum)."), Prefix, XFORM_MAX_PAGES); + goto done; + } // Add job-sheets content... if (options->job_sheets[0] && strcmp(options->job_sheets, "none")) @@ -3731,7 +3735,7 @@ prepare_number_up(xform_prepare_t *p) // I - Preparation data // 'prepare_pages()' - Prepare the pages for the output document. // -static void +static bool // O - `true` on success, `false` if too many pages prepare_pages( xform_prepare_t *p, // I - Preparation data size_t num_documents, // I - Number of documents @@ -3754,6 +3758,9 @@ prepare_pages( if (p->num_outpages & 1) p->num_outpages ++; + if (p->num_outpages > XFORM_MAX_PAGES) + return (false); + for (current = 0, layout = 0, page = 1, i = num_documents, d = documents; i > 0; i --, d ++) { while (page <= d->last_page) @@ -3797,6 +3804,9 @@ prepare_pages( if (use_page) { + if (current >= XFORM_MAX_PAGES) + return (false); + outpage->pdf = p->pdf; outpage->input[layout] = pdfioFileGetPage(d->pdf, (size_t)(page - d->first_page)); @@ -3839,6 +3849,8 @@ prepare_pages( p->num_outpages = current; } + + return (true); }