diff --git a/0001-Bug-707130-Cast-to-void-to-avoid-compiler-warning.patch b/0001-Bug-707130-Cast-to-void-to-avoid-compiler-warning.patch new file mode 100644 index 0000000000000000000000000000000000000000..4fcd14aab1db767c215ee710a17d7fe8345e19f7 --- /dev/null +++ b/0001-Bug-707130-Cast-to-void-to-avoid-compiler-warning.patch @@ -0,0 +1,25 @@ +From b7beb19ad06e08b889a44694ff813ed5f6c96da4 Mon Sep 17 00:00:00 2001 +From: Chris Liddell +Date: Thu, 14 Sep 2023 09:01:43 +0100 +Subject: [PATCH] Bug 707130: Cast to void ** to avoid compiler warning + +--- + base/fapi_ft.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/base/fapi_ft.c b/base/fapi_ft.c +index ccd629757..fc185bfd7 100644 +--- a/base/fapi_ft.c ++++ b/base/fapi_ft.c +@@ -1280,7 +1280,7 @@ gs_fapi_ft_get_scaled_font(gs_fapi_server * a_server, gs_fapi_font * a_font, + + if (a_font->retrieve_tt_font != NULL) { + unsigned int ms; +- code = a_font->retrieve_tt_font(a_font, &own_font_data, &ms); ++ code = a_font->retrieve_tt_font(a_font, (void **)&own_font_data, &ms); + if (code == 0) { + data_owned = false; + open_args.memory_base = own_font_data; +-- +2.43.0 + diff --git a/0001-Bug-707510-3-Bounds-checks-when-using-CIDFont-relate.patch b/0001-Bug-707510-3-Bounds-checks-when-using-CIDFont-relate.patch new file mode 100644 index 0000000000000000000000000000000000000000..f8df7d96450eb1304e0e5cc90cb67b76360b5c08 --- /dev/null +++ b/0001-Bug-707510-3-Bounds-checks-when-using-CIDFont-relate.patch @@ -0,0 +1,76 @@ +diff --git a/pdf/pdf_font.c b/pdf/pdf_font.c +index 5f82b7f..6819cb7 100644 +--- a/pdf/pdf_font.c ++++ b/pdf/pdf_font.c +@@ -297,22 +297,55 @@ pdfi_open_CIDFont_substitute_file(pdf_context *ctx, pdf_dict *font_dict, pdf_dic + memcpy(fontfname, fsprefix, fsprefixlen); + } + else { +- memcpy(fontfname, ctx->args.cidfsubstpath.data, ctx->args.cidfsubstpath.size); +- fsprefixlen = ctx->args.cidfsubstpath.size; ++ if (ctx->args.cidfsubstpath.size + 1 > gp_file_name_sizeof) { ++ code = gs_note_error(gs_error_rangecheck); ++ pdfi_set_warning(ctx, code, NULL, W_PDF_BAD_CONFIG, "pdfi_open_CIDFont_substitute_file", "CIDFSubstPath parameter too long"); ++ if (ctx->args.pdfstoponwarning != 0) { ++ goto exit; ++ } ++ code = 0; ++ memcpy(fontfname, fsprefix, fsprefixlen); ++ } ++ else { ++ memcpy(fontfname, ctx->args.cidfsubstpath.data, ctx->args.cidfsubstpath.size); ++ fsprefixlen = ctx->args.cidfsubstpath.size; ++ } + } + + if (ctx->args.cidfsubstfont.data == NULL) { + int len = 0; +- if (gp_getenv("CIDFSUBSTFONT", (char *)0, &len) < 0 && len + fsprefixlen + 1 < gp_file_name_sizeof) { +- (void)gp_getenv("CIDFSUBSTFONT", (char *)(fontfname + fsprefixlen), &defcidfallacklen); ++ if (gp_getenv("CIDFSUBSTFONT", (char *)0, &len) < 0) { ++ if (len + fsprefixlen + 1 > gp_file_name_sizeof) { ++ code = gs_note_error(gs_error_rangecheck); ++ pdfi_set_warning(ctx, code, NULL, W_PDF_BAD_CONFIG, "pdfi_open_CIDFont_substitute_file", "CIDFSUBSTFONT environment variable too long"); ++ if (ctx->args.pdfstoponwarning != 0) { ++ goto exit; ++ } ++ code = 0; ++ memcpy(fontfname + fsprefixlen, defcidfallack, defcidfallacklen); ++ } ++ else { ++ (void)gp_getenv("CIDFSUBSTFONT", (char *)(fontfname + fsprefixlen), &defcidfallacklen); ++ } + } + else { + memcpy(fontfname + fsprefixlen, defcidfallack, defcidfallacklen); + } + } + else { +- memcpy(fontfname, ctx->args.cidfsubstfont.data, ctx->args.cidfsubstfont.size); +- defcidfallacklen = ctx->args.cidfsubstfont.size; ++ if (ctx->args.cidfsubstfont.size > gp_file_name_sizeof - 1) { ++ code = gs_note_error(gs_error_rangecheck); ++ pdfi_set_warning(ctx, code, NULL, W_PDF_BAD_CONFIG, "pdfi_open_CIDFont_substitute_file", "CIDFSubstFont parameter too long"); ++ if (ctx->args.pdfstoponwarning != 0) { ++ goto exit; ++ } ++ code = 0; ++ memcpy(fontfname + fsprefixlen, defcidfallack, defcidfallacklen); ++ } ++ else { ++ memcpy(fontfname, ctx->args.cidfsubstfont.data, ctx->args.cidfsubstfont.size); ++ defcidfallacklen = ctx->args.cidfsubstfont.size; ++ } + } + fontfname[fsprefixlen + defcidfallacklen] = '\0'; + +diff --git a/pdf/pdf_warnings.h b/pdf/pdf_warnings.h +index 6402d8f..d1e0019 100644 +--- a/pdf/pdf_warnings.h ++++ b/pdf/pdf_warnings.h +@@ -97,4 +97,5 @@ PARAM(W_PDF_MISMATCH_GENERATION, "The generation number of an indirectly refe + PARAM(W_PDF_BAD_RENDERINGINTENT, "A ri or /RI used an unknown named rendering intent"), + PARAM(W_PDF_BAD_VIEW, "Couldn't read the initial document view"), + PARAM(W_PDF_BAD_WMODE, "A Font or CMap has a WMode which is neither 0 (horizontal) nor 1 (vertical)"), ++PARAM(W_PDF_BAD_CONFIG, "A configuration or command line parameter was invalid or incorrect."), + #undef PARAM diff --git a/0001-Bug-707510-don-t-allow-PDF-files-with-bad-Filters-to.patch b/0001-Bug-707510-don-t-allow-PDF-files-with-bad-Filters-to.patch new file mode 100644 index 0000000000000000000000000000000000000000..26f1057df5a748519c1169ef6821f3ff2e59016a --- /dev/null +++ b/0001-Bug-707510-don-t-allow-PDF-files-with-bad-Filters-to.patch @@ -0,0 +1,46 @@ +From 77dc7f699beba606937b7ea23b50cf5974fa64b1 Mon Sep 17 00:00:00 2001 +From: Ken Sharp +Date: Thu, 25 Jan 2024 11:55:49 +0000 +Subject: [PATCH] Bug 707510 - don't allow PDF files with bad Filters to + overflow the debug buffer + +Item #2 of the report. + +Allocate a buffer to hold the filter name, instead of assuming it will +fit in a fixed buffer. + +Reviewed all the other PDFDEBUG cases, no others use a fixed buffer like +this. +--- + pdf/pdf_file.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/pdf/pdf_file.c b/pdf/pdf_file.c +index 6680ae2db..4b04e3582 100644 +--- a/pdf/pdf_file.c ++++ b/pdf/pdf_file.c +@@ -1,4 +1,4 @@ +-/* Copyright (C) 2018-2023 Artifex Software, Inc. ++/* Copyright (C) 2018-2024 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or +@@ -777,10 +777,14 @@ static int pdfi_apply_filter(pdf_context *ctx, pdf_dict *dict, pdf_name *n, pdf_ + + if (ctx->args.pdfdebug) + { +- char str[100]; ++ char *str; ++ str = gs_alloc_bytes(ctx->memory, n->length + 1, "temp string for debug"); ++ if (str == NULL) ++ return_error(gs_error_VMerror); + memcpy(str, (const char *)n->data, n->length); + str[n->length] = '\0'; + dmprintf1(ctx->memory, "FILTER NAME:%s\n", str); ++ gs_free_object(ctx->memory, str, "temp string for debug"); + } + + if (pdfi_name_is(n, "RunLengthDecode")) { +-- +2.45.2 + diff --git a/0001-Bug-707510-don-t-use-strlen-on-passwords.patch b/0001-Bug-707510-don-t-use-strlen-on-passwords.patch new file mode 100644 index 0000000000000000000000000000000000000000..a66f4f512555e75ffe56e7ddc855d7be1cf6693b --- /dev/null +++ b/0001-Bug-707510-don-t-use-strlen-on-passwords.patch @@ -0,0 +1,46 @@ +From 917b3a71fb20748965254631199ad98210d6c2fb Mon Sep 17 00:00:00 2001 +From: Ken Sharp +Date: Thu, 25 Jan 2024 11:58:22 +0000 +Subject: [PATCH] Bug 707510 - don't use strlen on passwords + +Item #1 of the report. This looks like an oversight when first coding +the routine. We should use the PostScript string length, because +PostScript strings may not be NULL terminated (and as here may contain +internal NULL characters). + +Fix the R6 handler which has the same problem too. +--- + pdf/pdf_sec.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/pdf/pdf_sec.c b/pdf/pdf_sec.c +index e968b89c5..e02e040f9 100644 +--- a/pdf/pdf_sec.c ++++ b/pdf/pdf_sec.c +@@ -1,4 +1,4 @@ +-/* Copyright (C) 2020-2023 Artifex Software, Inc. ++/* Copyright (C) 2020-2024 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or +@@ -1283,7 +1283,7 @@ static int check_password_R5(pdf_context *ctx, char *Password, int PasswordLen, + /* If the supplied Password fails as the user *and* owner password, maybe its in + * the locale, not UTF-8, try converting to UTF-8 + */ +- code = pdfi_object_alloc(ctx, PDF_STRING, strlen(ctx->encryption.Password), (pdf_obj **)&P); ++ code = pdfi_object_alloc(ctx, PDF_STRING, PasswordLen, (pdf_obj **)&P); + if (code < 0) + return code; + memcpy(P->data, Password, PasswordLen); +@@ -1330,7 +1330,7 @@ static int check_password_R6(pdf_context *ctx, char *Password, int PasswordLen, + /* If the supplied Password fails as the user *and* owner password, maybe its in + * the locale, not UTF-8, try converting to UTF-8 + */ +- code = pdfi_object_alloc(ctx, PDF_STRING, strlen(ctx->encryption.Password), (pdf_obj **)&P); ++ code = pdfi_object_alloc(ctx, PDF_STRING, PasswordLen, (pdf_obj **)&P); + if (code < 0) + return code; + memcpy(P->data, Password, PasswordLen); +-- +2.45.2 + diff --git a/0001-Bug-707510-review-printing-of-pointers.patch b/0001-Bug-707510-review-printing-of-pointers.patch new file mode 100644 index 0000000000000000000000000000000000000000..a8697a5ec454a85bae1e7decc62e6c3c21810a77 --- /dev/null +++ b/0001-Bug-707510-review-printing-of-pointers.patch @@ -0,0 +1,430 @@ +From ff1013a0ab485b66783b70145e342a82c670906a Mon Sep 17 00:00:00 2001 +From: Ken Sharp +Date: Thu, 25 Jan 2024 11:53:44 +0000 +Subject: [PATCH] Bug 707510 - review printing of pointers + +This is for item 4 of the report, which is addressed by the change in +gdevpdtb.c. That change uses a fixed name for fonts which have no name +instead of using the pointer to the address of the font. + +The remaining changes are all due to reviewing the use of PRI_INTPTR. +In general we only use that for debugging purposes but there were a few +places which were printing pointers arbitrarily, even in a release build. + +We really don't want to do that so I've modified the places which were +printing pointer unconditionally so that they only do so if DEBUG is +set at compile time, or a specific debug flag is set. +--- + base/gsfont.c | 4 ++-- + base/gsicc_cache.c | 8 ++++---- + base/gsmalloc.c | 4 ++-- + base/gxclmem.c | 5 ++--- + base/gxcpath.c | 6 +++++- + base/gxpath.c | 8 +++++++- + base/szlibc.c | 4 +++- + devices/gdevupd.c | 7 ++++++- + devices/vector/gdevpdtb.c | 4 ++-- + psi/ialloc.c | 4 ++-- + psi/igc.c | 6 +++--- + psi/igcstr.c | 6 +++--- + psi/iinit.c | 6 +++++- + psi/imainarg.c | 5 +++-- + psi/isave.c | 4 ++-- + psi/iutil.c | 6 +++++- + 16 files changed, 56 insertions(+), 31 deletions(-) + +diff --git a/base/gsfont.c b/base/gsfont.c +index 351954776..8b0da819b 100644 +--- a/base/gsfont.c ++++ b/base/gsfont.c +@@ -1,4 +1,4 @@ +-/* Copyright (C) 2001-2023 Artifex Software, Inc. ++/* Copyright (C) 2001-2024 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or +@@ -791,7 +791,7 @@ gs_purge_font(gs_font * pfont) + else if (pdir->scaled_fonts == pfont) + pdir->scaled_fonts = next; + else { /* Shouldn't happen! */ +- lprintf1("purged font "PRI_INTPTR" not found\n", (intptr_t)pfont); ++ if_debug1m('u', pfont->memory, "purged font "PRI_INTPTR" not found\n", (intptr_t)pfont); + } + + /* Purge the font from the scaled font cache. */ +diff --git a/base/gsicc_cache.c b/base/gsicc_cache.c +index c2a59107e..c3026c136 100644 +--- a/base/gsicc_cache.c ++++ b/base/gsicc_cache.c +@@ -1,4 +1,4 @@ +-/* Copyright (C) 2001-2023 Artifex Software, Inc. ++/* Copyright (C) 2001-2024 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or +@@ -161,7 +161,7 @@ icc_linkcache_finalize(const gs_memory_t *mem, void *ptr) + return; + while (link_cache->head != NULL) { + if (link_cache->head->ref_count != 0) { +- emprintf2(link_cache->memory, "link at "PRI_INTPTR" being removed, but has ref_count = %d\n", ++ if_debug2m(gs_debug_flag_icc, link_cache->memory, "link at "PRI_INTPTR" being removed, but has ref_count = %d\n", + (intptr_t)link_cache->head, link_cache->head->ref_count); + link_cache->head->ref_count = 0; /* force removal */ + } +@@ -586,7 +586,7 @@ gsicc_findcachelink(gsicc_hashlink_t hash, gsicc_link_cache_t *icc_link_cache, + /* that was building it failed to be able to complete building it. Try this only + a limited number of times before we bail. */ + if (curr->valid == false) { +- emprintf1(curr->memory, "link "PRI_INTPTR" lock released, but still not valid.\n", (intptr_t)curr); /* Breakpoint here */ ++ if_debug1m(gs_debug_flag_icc, curr->memory, "link "PRI_INTPTR" lock released, but still not valid.\n", (intptr_t)curr); /* Breakpoint here */ + } + gx_monitor_enter(icc_link_cache->lock); /* re-enter to loop and check */ + } +@@ -614,7 +614,7 @@ gsicc_remove_link(gsicc_link_t *link) + /* NOTE: link->ref_count must be 0: assert ? */ + gx_monitor_enter(icc_link_cache->lock); + if (link->ref_count != 0) { +- emprintf2(memory, "link at "PRI_INTPTR" being removed, but has ref_count = %d\n", (intptr_t)link, link->ref_count); ++ if_debug2m(gs_debug_flag_icc, memory, "link at "PRI_INTPTR" being removed, but has ref_count = %d\n", (intptr_t)link, link->ref_count); + } + curr = icc_link_cache->head; + prev = NULL; +diff --git a/base/gsmalloc.c b/base/gsmalloc.c +index 5d5b0f4d1..6b8da1fba 100644 +--- a/base/gsmalloc.c ++++ b/base/gsmalloc.c +@@ -1,4 +1,4 @@ +-/* Copyright (C) 2001-2023 Artifex Software, Inc. ++/* Copyright (C) 2001-2024 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or +@@ -420,7 +420,7 @@ gs_heap_resize_string(gs_memory_t * mem, byte * data, size_t old_num, size_t new + client_name_t cname) + { + if (gs_heap_object_type(mem, data) != &st_bytes) +- lprintf2("%s: resizing non-string "PRI_INTPTR"!\n", ++ if_debug2m('a', mem, "%s: resizing non-string "PRI_INTPTR"!\n", + client_name_string(cname), (intptr_t)data); + return gs_heap_resize_object(mem, data, new_num, cname); + } +diff --git a/base/gxclmem.c b/base/gxclmem.c +index 9b9bbcf35..68125303e 100644 +--- a/base/gxclmem.c ++++ b/base/gxclmem.c +@@ -1,4 +1,4 @@ +-/* Copyright (C) 2001-2023 Artifex Software, Inc. ++/* Copyright (C) 2001-2024 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or +@@ -490,8 +490,7 @@ memfile_fclose(clist_file_ptr cf, const char *fname, bool delete) + /* leaks if other users of the memfile don't 'fclose with delete=true */ + if (f->openlist != NULL || ((f->base_memfile != NULL) && f->base_memfile->is_open)) { + /* TODO: do the cleanup rather than just giving an error */ +- emprintf1(f->memory, +- "Attempt to delete a memfile still open for read: "PRI_INTPTR"\n", ++ if_debug1(':', "Attempt to delete a memfile still open for read: "PRI_INTPTR"\n", + (intptr_t)f); + return_error(gs_error_invalidfileaccess); + } else { +diff --git a/base/gxcpath.c b/base/gxcpath.c +index e277f3172..a7a127db2 100644 +--- a/base/gxcpath.c ++++ b/base/gxcpath.c +@@ -1,4 +1,4 @@ +-/* Copyright (C) 2001-2023 Artifex Software, Inc. ++/* Copyright (C) 2001-2024 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or +@@ -178,8 +178,10 @@ gx_cpath_init_contained_shared(gx_clip_path * pcpath, + { + if (shared) { + if (shared->path.segments == &shared->path.local_segments) { ++#ifdef DEBUG + lprintf1("Attempt to share (local) segments of clip path "PRI_INTPTR"!\n", + (intptr_t)shared); ++#endif + return_error(gs_error_Fatal); + } + *pcpath = *shared; +@@ -236,8 +238,10 @@ gx_cpath_init_local_shared_nested(gx_clip_path * pcpath, + if (shared) { + if ((shared->path.segments == &shared->path.local_segments) && + !safely_nested) { ++#ifdef DEBUG + lprintf1("Attempt to share (local) segments of clip path "PRI_INTPTR"!\n", + (intptr_t)shared); ++#endif + return_error(gs_error_Fatal); + } + pcpath->path = shared->path; +diff --git a/base/gxpath.c b/base/gxpath.c +index eb0f3bf2e..817c247b2 100644 +--- a/base/gxpath.c ++++ b/base/gxpath.c +@@ -1,4 +1,4 @@ +-/* Copyright (C) 2001-2023 Artifex Software, Inc. ++/* Copyright (C) 2001-2024 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or +@@ -137,8 +137,10 @@ gx_path_init_contained_shared(gx_path * ppath, const gx_path * shared, + { + if (shared) { + if (shared->segments == &shared->local_segments) { ++#ifdef DEBUG + lprintf1("Attempt to share (local) segments of path "PRI_INTPTR"!\n", + (intptr_t)shared); ++#endif + return_error(gs_error_Fatal); + } + *ppath = *shared; +@@ -172,8 +174,10 @@ gx_path_alloc_shared(const gx_path * shared, gs_memory_t * mem, + ppath->procs = &default_path_procs; + if (shared) { + if (shared->segments == &shared->local_segments) { ++#ifdef DEBUG + lprintf1("Attempt to share (local) segments of path "PRI_INTPTR"!\n", + (intptr_t)shared); ++#endif + gs_free_object(mem, ppath, cname); + return 0; + } +@@ -203,8 +207,10 @@ gx_path_init_local_shared(gx_path * ppath, const gx_path * shared, + { + if (shared) { + if (shared->segments == &shared->local_segments) { ++#ifdef DEBUG + lprintf1("Attempt to share (local) segments of path "PRI_INTPTR"!\n", + (intptr_t)shared); ++#endif + return_error(gs_error_Fatal); + } + *ppath = *shared; +diff --git a/base/szlibc.c b/base/szlibc.c +index e2b0d68c3..5f315c3c3 100644 +--- a/base/szlibc.c ++++ b/base/szlibc.c +@@ -1,4 +1,4 @@ +-/* Copyright (C) 2001-2023 Artifex Software, Inc. ++/* Copyright (C) 2001-2024 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or +@@ -110,7 +110,9 @@ s_zlib_free(void *zmem, void *data) + gs_free_object(mem, data, "s_zlib_free(data)"); + for (; ; block = block->next) { + if (block == 0) { ++#ifdef DEBUG + lprintf1("Freeing unrecorded data "PRI_INTPTR"!\n", (intptr_t)data); ++#endif + return; + } + if (block->data == data) +diff --git a/devices/gdevupd.c b/devices/gdevupd.c +index 740dae012..cb479d21f 100644 +--- a/devices/gdevupd.c ++++ b/devices/gdevupd.c +@@ -1,4 +1,4 @@ +-/* Copyright (C) 2001-2023 Artifex Software, Inc. ++/* Copyright (C) 2001-2024 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or +@@ -1040,8 +1040,13 @@ upd_print_page(gx_device_printer *pdev, gp_file *out) + */ + if(!upd || B_OK4GO != (upd->flags & (B_OK4GO | B_ERROR))) { + #if UPD_MESSAGES & (UPD_M_ERROR | UPD_M_TOPCALLS) ++#ifdef DEBUG + errprintf(pdev->memory, "CALL-REJECTED upd_print_page(" PRI_INTPTR "," PRI_INTPTR ")\n", + (intptr_t)udev,(intptr_t) out); ++#else ++ errprintf(pdev->memory, "CALL-REJECTED upd_print_page\n", ++ (intptr_t)udev,(intptr_t) out); ++#endif + #endif + return_error(gs_error_undefined); + } +diff --git a/devices/vector/gdevpdtb.c b/devices/vector/gdevpdtb.c +index 41046aa21..3d7dcae53 100644 +--- a/devices/vector/gdevpdtb.c ++++ b/devices/vector/gdevpdtb.c +@@ -1,4 +1,4 @@ +-/* Copyright (C) 2001-2023 Artifex Software, Inc. ++/* Copyright (C) 2001-2024 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or +@@ -373,7 +373,7 @@ pdf_base_font_alloc(gx_device_pdf *pdev, pdf_base_font_t **ppbfont, + font_name.size -= SUBSET_PREFIX_SIZE; + } + } else { +- gs_snprintf(fnbuf, sizeof(fnbuf), ".F" PRI_INTPTR, (intptr_t)copied); ++ gs_snprintf(fnbuf, sizeof(fnbuf), "Anonymous"); + font_name.data = (byte *)fnbuf; + font_name.size = strlen(fnbuf); + } +diff --git a/psi/ialloc.c b/psi/ialloc.c +index 6d22110e8..40216e41c 100644 +--- a/psi/ialloc.c ++++ b/psi/ialloc.c +@@ -1,4 +1,4 @@ +-/* Copyright (C) 2001-2023 Artifex Software, Inc. ++/* Copyright (C) 2001-2024 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or +@@ -391,7 +391,7 @@ gs_free_ref_array(gs_ref_memory_t * mem, ref * parr, client_name_t cname) + size = num_refs * sizeof(ref); + break; + default: +- lprintf3("Unknown type 0x%x in free_ref_array(%u,"PRI_INTPTR")!", ++ if_debug3('A', "Unknown type 0x%x in free_ref_array(%u,"PRI_INTPTR")!", + r_type(parr), num_refs, (intptr_t)obj); + return; + } +diff --git a/psi/igc.c b/psi/igc.c +index 121723f79..ab6565c6b 100644 +--- a/psi/igc.c ++++ b/psi/igc.c +@@ -1,4 +1,4 @@ +-/* Copyright (C) 2001-2023 Artifex Software, Inc. ++/* Copyright (C) 2001-2024 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or +@@ -1062,7 +1062,7 @@ gc_extend_stack(gc_mark_stack * pms, gc_state_t * pstate) + + if (cp == 0) { /* We were tracing outside collectible */ + /* storage. This can't happen. */ +- lprintf1("mark stack overflowed while outside collectible space at "PRI_INTPTR"!\n", ++ if_debug1('6', "mark stack overflowed while outside collectible space at "PRI_INTPTR"!\n", + (intptr_t)cptr); + gs_abort(pstate->heap); + } +@@ -1291,7 +1291,7 @@ igc_reloc_struct_ptr(const void /*obj_header_t */ *obj, gc_state_t * gcst) + + if (cp != 0 && cp->cbase <= (byte *)obj && (byte *)obj ctop) { + if (back > (cp->ctop - cp->cbase) >> obj_back_shift) { +- lprintf2("Invalid back pointer %u at "PRI_INTPTR"!\n", ++ if_debug2('6', "Invalid back pointer %u at "PRI_INTPTR"!\n", + back, (intptr_t)obj); + gs_abort(NULL); + } +diff --git a/psi/igcstr.c b/psi/igcstr.c +index bfaee419b..c43c12875 100644 +--- a/psi/igcstr.c ++++ b/psi/igcstr.c +@@ -1,4 +1,4 @@ +-/* Copyright (C) 2001-2023 Artifex Software, Inc. ++/* Copyright (C) 2001-2024 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or +@@ -152,7 +152,7 @@ gc_string_mark(const byte * ptr, uint size, bool set, gc_state_t * gcst) + return false; + #ifdef DEBUG + if (ptr < cp->ctop) { +- lprintf4("String pointer "PRI_INTPTR"[%u] outside ["PRI_INTPTR".."PRI_INTPTR")\n", ++ if_debug4('6', "String pointer "PRI_INTPTR"[%u] outside ["PRI_INTPTR".."PRI_INTPTR")\n", + (intptr_t)ptr, size, (intptr_t)cp->ctop, (intptr_t)cp->climit); + return false; + } else if (ptr + size > cp->climit) { /* +@@ -171,7 +171,7 @@ gc_string_mark(const byte * ptr, uint size, bool set, gc_state_t * gcst) + while (ptr == scp->climit && scp->outer != 0) + scp = scp->outer; + if (ptr + size > scp->climit) { +- lprintf4("String pointer "PRI_INTPTR"[%u] outside ["PRI_INTPTR".."PRI_INTPTR")\n", ++ if_debug4('6', "String pointer "PRI_INTPTR"[%u] outside ["PRI_INTPTR".."PRI_INTPTR")\n", + (intptr_t)ptr, size, + (intptr_t)scp->ctop, (intptr_t)scp->climit); + return false; +diff --git a/psi/iinit.c b/psi/iinit.c +index ed41b36da..0af7ee9c1 100644 +--- a/psi/iinit.c ++++ b/psi/iinit.c +@@ -1,4 +1,4 @@ +-/* Copyright (C) 2001-2023 Artifex Software, Inc. ++/* Copyright (C) 2001-2024 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or +@@ -395,8 +395,12 @@ zop_init(i_ctx_t *i_ctx_p) + if (def->proc != 0) { + code = def->proc(i_ctx_p); + if (code < 0) { ++#ifdef DEBUG + lprintf2("op_init proc "PRI_INTPTR" returned error %d!\n", + (intptr_t)def->proc, code); ++#else ++ lprintf("op_init proc returned error !\n"); ++#endif + return code; + } + } +diff --git a/psi/imainarg.c b/psi/imainarg.c +index 638694ba2..29ad1d633 100644 +--- a/psi/imainarg.c ++++ b/psi/imainarg.c +@@ -1,4 +1,4 @@ +-/* Copyright (C) 2001-2023 Artifex Software, Inc. ++/* Copyright (C) 2001-2024 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or +@@ -229,7 +229,8 @@ gs_main_init_with_args01(gs_main_instance * minst, int argc, char *argv[]) + if (gs_debug[':'] && !have_dumped_args) { + int i; + +- dmprintf1(minst->heap, "%% Args passed to instance "PRI_INTPTR": ", ++ if (gs_debug_c(gs_debug_flag_init_details)) ++ dmprintf1(minst->heap, "%% Args passed to instance "PRI_INTPTR": ", + (intptr_t)minst); + for (i=1; iheap, "%s ", argv[i]); +diff --git a/psi/isave.c b/psi/isave.c +index 80cf9c1f7..795170fcb 100644 +--- a/psi/isave.c ++++ b/psi/isave.c +@@ -1,4 +1,4 @@ +-/* Copyright (C) 2001-2023 Artifex Software, Inc. ++/* Copyright (C) 2001-2024 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or +@@ -487,7 +487,7 @@ alloc_save_change_in(gs_ref_memory_t *mem, const ref * pcont, + else if (r_is_struct(pcont)) + cp->offset = (byte *) where - (byte *) pcont->value.pstruct; + else { +- lprintf3("Bad type %u for save! pcont = "PRI_INTPTR", where = "PRI_INTPTR"\n", ++ if_debug3('u', "Bad type %u for save! pcont = "PRI_INTPTR", where = "PRI_INTPTR"\n", + r_type(pcont), (intptr_t) pcont, (intptr_t) where); + gs_abort((const gs_memory_t *)mem); + } +diff --git a/psi/iutil.c b/psi/iutil.c +index 405869666..239c26b85 100644 +--- a/psi/iutil.c ++++ b/psi/iutil.c +@@ -1,4 +1,4 @@ +-/* Copyright (C) 2001-2023 Artifex Software, Inc. ++/* Copyright (C) 2001-2024 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or +@@ -537,7 +537,11 @@ other: + break; + } + /* Internal operator, no name. */ ++#if DEBUG + gs_snprintf(buf, sizeof(buf), "@"PRI_INTPTR, (intptr_t) op->value.opproc); ++#else ++ gs_snprintf(buf, sizeof(buf), "@anonymous_operator", (intptr_t) op->value.opproc); ++#endif + break; + } + case t_real: +-- +2.45.2 + diff --git a/0001-Bug-707686.patch b/0001-Bug-707686.patch new file mode 100644 index 0000000000000000000000000000000000000000..d5152b5c5abf6b37a0be141b3e05b849d3d03c2f --- /dev/null +++ b/0001-Bug-707686.patch @@ -0,0 +1,94 @@ +From 79aef19c685984dc3da2dc090450407d9fbcff80 Mon Sep 17 00:00:00 2001 +From: Ken Sharp +Date: Tue, 26 Mar 2024 12:00:14 +0000 +Subject: [PATCH] Bug #707686 + +See bug thread for details + +In addition to the noted bug; an error path (return from +gp_file_name_reduce not successful) could elad to a memory leak as we +did not free 'bufferfull'. Fix that too. + +This addresses CVE-2024-33870 +--- + base/gpmisc.c | 36 ++++++++++++++++++++++++++++++++---- + 1 file changed, 32 insertions(+), 4 deletions(-) + +diff --git a/base/gpmisc.c b/base/gpmisc.c +index 2b0064bea..c4a69b03a 100644 +--- a/base/gpmisc.c ++++ b/base/gpmisc.c +@@ -1,4 +1,4 @@ +-/* Copyright (C) 2001-2023 Artifex Software, Inc. ++/* Copyright (C) 2001-2024 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or +@@ -1042,7 +1042,7 @@ gp_validate_path_len(const gs_memory_t *mem, + const uint len, + const char *mode) + { +- char *buffer, *bufferfull; ++ char *buffer, *bufferfull = NULL; + uint rlen; + int code = 0; + const char *cdirstr = gp_file_name_current(); +@@ -1096,8 +1096,10 @@ gp_validate_path_len(const gs_memory_t *mem, + return gs_error_VMerror; + + buffer = bufferfull + prefix_len; +- if (gp_file_name_reduce(path, (uint)len, buffer, &rlen) != gp_combine_success) +- return gs_error_invalidfileaccess; ++ if (gp_file_name_reduce(path, (uint)len, buffer, &rlen) != gp_combine_success) { ++ code = gs_note_error(gs_error_invalidfileaccess); ++ goto exit; ++ } + buffer[rlen] = 0; + } + while (1) { +@@ -1132,9 +1134,34 @@ gp_validate_path_len(const gs_memory_t *mem, + code = gs_note_error(gs_error_invalidfileaccess); + } + if (code < 0 && prefix_len > 0 && buffer > bufferfull) { ++ uint newlen = rlen + cdirstrl + dirsepstrl; ++ char *newbuffer; ++ int code; ++ + buffer = bufferfull; + memcpy(buffer, cdirstr, cdirstrl); + memcpy(buffer + cdirstrl, dirsepstr, dirsepstrl); ++ ++ /* We've prepended a './' or similar for the current working directory. We need ++ * to execute file_name_reduce on that, to eliminate any '../' or similar from ++ * the (new) full path. ++ */ ++ newbuffer = (char *)gs_alloc_bytes(mem->thread_safe_memory, newlen + 1, "gp_validate_path"); ++ if (newbuffer == NULL) { ++ code = gs_note_error(gs_error_VMerror); ++ goto exit; ++ } ++ ++ memcpy(newbuffer, buffer, rlen + cdirstrl + dirsepstrl); ++ newbuffer[newlen] = 0x00; ++ ++ code = gp_file_name_reduce(newbuffer, (uint)newlen, buffer, &newlen); ++ gs_free_object(mem->thread_safe_memory, newbuffer, "gp_validate_path"); ++ if (code != gp_combine_success) { ++ code = gs_note_error(gs_error_invalidfileaccess); ++ goto exit; ++ } ++ + continue; + } + else if (code < 0 && cdirstrl > 0 && prefix_len == 0 && buffer == bufferfull) { +@@ -1153,6 +1180,7 @@ gp_validate_path_len(const gs_memory_t *mem, + gs_path_control_flag_is_scratch_file); + } + ++exit: + gs_free_object(mem->thread_safe_memory, bufferfull, "gp_validate_path"); + #ifdef EACCES + if (code == gs_error_invalidfileaccess) +-- +2.45.2 + diff --git a/0001-Bug-707691.patch b/0001-Bug-707691.patch new file mode 100644 index 0000000000000000000000000000000000000000..65c01cc3d7b2277079a3ae355c60371415e5d3f4 --- /dev/null +++ b/0001-Bug-707691.patch @@ -0,0 +1,43 @@ +diff --git a/base/gpmisc.c b/base/gpmisc.c +index c4a69b0..b0d5c71 100644 +--- a/base/gpmisc.c ++++ b/base/gpmisc.c +@@ -1090,6 +1090,27 @@ gp_validate_path_len(const gs_memory_t *mem, + rlen = len; + } + else { ++ char *test = (char *)path, *test1; ++ uint tlen = len, slen; ++ ++ /* Look for any pipe (%pipe% or '|' specifications between path separators ++ * Reject any path spec which has a %pipe% or '|' anywhere except at the start. ++ */ ++ while (tlen > 0) { ++ if (test[0] == '|' || (tlen > 5 && memcmp(test, "%pipe", 5) == 0)) { ++ code = gs_note_error(gs_error_invalidfileaccess); ++ goto exit; ++ } ++ test1 = test; ++ slen = search_separator((const char **)&test, path + len, test1, 1); ++ if(slen == 0) ++ break; ++ test += slen; ++ tlen -= test - test1; ++ if (test >= path + len) ++ break; ++ } ++ + rlen = len+1; + bufferfull = (char *)gs_alloc_bytes(mem->thread_safe_memory, rlen + prefix_len, "gp_validate_path"); + if (bufferfull == NULL) +@@ -1164,8 +1185,8 @@ gp_validate_path_len(const gs_memory_t *mem, + + continue; + } +- else if (code < 0 && cdirstrl > 0 && prefix_len == 0 && buffer == bufferfull) { +- buffer = bufferfull + cdirstrl + dirsepstrl; ++ else if (code < 0 && cdirstrl > 0 && prefix_len == 0 && buffer == bufferfull ++ && memcmp(buffer, cdirstr, cdirstrl) && !memcmp(buffer + cdirstrl, dirsepstr, dirsepstrl)) { + continue; + } + break; diff --git a/0001-Bug-707788-Fix-decode_utf8-to-forbid-overlong-encodi.patch b/0001-Bug-707788-Fix-decode_utf8-to-forbid-overlong-encodi.patch new file mode 100644 index 0000000000000000000000000000000000000000..cb08b28fc7a024606bc221cf17022c774974127a --- /dev/null +++ b/0001-Bug-707788-Fix-decode_utf8-to-forbid-overlong-encodi.patch @@ -0,0 +1,63 @@ +From 282f691f5e57b6bf55ba51ad8c2be2cce8edb938 Mon Sep 17 00:00:00 2001 +From: Robin Watts +Date: Tue, 18 Jun 2024 18:22:55 +0100 +Subject: [PATCH] Bug 707788: Fix decode_utf8 to forbid overlong encodings. + +These can be used by malicious code to escape directories. + +CVE-2024-46954 +--- + base/gp_utf8.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/base/gp_utf8.c b/base/gp_utf8.c +index c33fc3550..b78977e37 100644 +--- a/base/gp_utf8.c ++++ b/base/gp_utf8.c +@@ -1,4 +1,4 @@ +-/* Copyright (C) 2001-2023 Artifex Software, Inc. ++/* Copyright (C) 2001-2024 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or +@@ -25,12 +25,16 @@ decode_utf8(const char **inp, unsigned int i) + if (i < 0x80) { + } else if ((i & 0xE0) == 0xC0) { + i &= 0x1F; ++ if (i == 0) ++ goto fail_overlong; + c = (unsigned char)*in++; + if ((c & 0xC0) != 0x80) + goto fail; + i = (i<<6) | (c & 0x3f); + } else if ((i & 0xF0) == 0xE0) { + i &= 0xF; ++ if (i == 0) ++ goto fail_overlong; + c = (unsigned char)*in++; + if ((c & 0xC0) != 0x80) + goto fail; +@@ -41,6 +45,8 @@ decode_utf8(const char **inp, unsigned int i) + i = (i<<6) | (c & 0x3f); + } else if ((i & 0xF8) == 0xF0) { + i &= 0x7; ++ if (i == 0) ++ goto fail_overlong; + c = (unsigned char)*in++; + if ((c & 0xC0) != 0x80) + goto fail; +@@ -59,6 +65,11 @@ decode_utf8(const char **inp, unsigned int i) + /* If we fail, unread the last one, and return the unicode replacement char. */ + fail: + in--; ++fail_overlong: ++ /* If we jump to here it's because we've detected an 'overlong' encoding. ++ * While this seems harmless, it's actually illegal, for good reason; ++ * this is typically an attempt to sneak stuff past security checks, like ++ * "../" in paths. Fail this. */ + i = 0xfffd; + } + *inp = in; +-- +2.49.0 + diff --git a/0001-Bug-707793-Check-for-overflow-validating-format-stri.patch b/0001-Bug-707793-Check-for-overflow-validating-format-stri.patch new file mode 100644 index 0000000000000000000000000000000000000000..4cafbfca1a38edab94f80cf4aa7419cc7ed4e9fd --- /dev/null +++ b/0001-Bug-707793-Check-for-overflow-validating-format-stri.patch @@ -0,0 +1,67 @@ +From 1f21a45df0fa3abec4cff12951022b192dda3c00 Mon Sep 17 00:00:00 2001 +From: Zdenek Hutyra +Date: Mon, 27 May 2024 13:38:36 +0100 +Subject: [PATCH] Bug 707793: Check for overflow validating format string + +for the output file name + +CVE-2024-46953 +--- + base/gsdevice.c | 19 ++++++++++++++----- + 1 file changed, 14 insertions(+), 5 deletions(-) + +diff --git a/base/gsdevice.c b/base/gsdevice.c +index 90e699ab4..49354d833 100644 +--- a/base/gsdevice.c ++++ b/base/gsdevice.c +@@ -1070,7 +1070,7 @@ static int + gx_parse_output_format(gs_parsed_file_name_t *pfn, const char **pfmt) + { + bool have_format = false, field; +- int width[2], int_width = sizeof(int) * 3, w = 0; ++ uint width[2], int_width = sizeof(int) * 3, w = 0; + uint i; + + /* Scan the file name for a format string, and validate it if present. */ +@@ -1099,6 +1099,8 @@ gx_parse_output_format(gs_parsed_file_name_t *pfn, const char **pfmt) + default: /* width (field = 0) and precision (field = 1) */ + if (strchr("0123456789", pfn->fname[i])) { + width[field] = width[field] * 10 + pfn->fname[i] - '0'; ++ if (width[field] > max_int) ++ return_error(gs_error_undefinedfilename); + continue; + } else if (0 == field && '.' == pfn->fname[i]) { + field++; +@@ -1127,8 +1129,10 @@ gx_parse_output_format(gs_parsed_file_name_t *pfn, const char **pfmt) + /* Calculate a conservative maximum width. */ + w = max(width[0], width[1]); + w = max(w, int_width) + 5; ++ if (w > max_int) ++ return_error(gs_error_undefinedfilename); + } +- return w; ++ return (int)w; + } + + /* +@@ -1181,10 +1185,15 @@ gx_parse_output_file_name(gs_parsed_file_name_t *pfn, const char **pfmt, + if (!pfn->fname) + return 0; + code = gx_parse_output_format(pfn, pfmt); +- if (code < 0) ++ if (code < 0) { + return code; +- if (strlen(pfn->iodev->dname) + pfn->len + code >= gp_file_name_sizeof) ++ } ++ ++ if (pfn->len >= gp_file_name_sizeof - strlen(pfn->iodev->dname) || ++ code >= gp_file_name_sizeof - strlen(pfn->iodev->dname) - pfn->len) { + return_error(gs_error_undefinedfilename); ++ } ++ + return 0; + } + +-- +2.49.0 + diff --git a/0001-Bug-708133-Avoid-integer-overflow-leading-to-buffer-.patch b/0001-Bug-708133-Avoid-integer-overflow-leading-to-buffer-.patch new file mode 100644 index 0000000000000000000000000000000000000000..09f9b86f28bf61aa5f11b4e33e2314353d90fcdc --- /dev/null +++ b/0001-Bug-708133-Avoid-integer-overflow-leading-to-buffer-.patch @@ -0,0 +1,41 @@ +From 57291c846334f1585552010faa42d7cb2cbd5c41 Mon Sep 17 00:00:00 2001 +From: Zdenek Hutyra +Date: Wed, 20 Nov 2024 11:42:31 +0000 +Subject: [PATCH] Bug 708133: Avoid integer overflow leading to buffer overflow + +The calculation of the buffer size was being done with int values, and +overflowing that data type. By leaving the total size calculation to the +memory manager, the calculation ends up being done in size_t values, and +avoiding the overflow in this case, but also meaning the memory manager +overflow protection will be effective. + +CVE-2025-27832 +--- + contrib/japanese/gdevnpdl.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/contrib/japanese/gdevnpdl.c b/contrib/japanese/gdevnpdl.c +index 60065bacf..4967282bd 100644 +--- a/contrib/japanese/gdevnpdl.c ++++ b/contrib/japanese/gdevnpdl.c +@@ -587,7 +587,7 @@ npdl_print_page_copies(gx_device_printer * pdev, gp_file * prn_stream, int num_c + int code; + int maxY = lprn->BlockLine / lprn->nBh * lprn->nBh; + +- if (!(lprn->CompBuf = gs_malloc(pdev->memory->non_gc_memory, line_size * maxY, sizeof(byte), "npdl_print_page_copies(CompBuf)"))) ++ if (!(lprn->CompBuf = gs_malloc(pdev->memory->non_gc_memory, line_size, maxY, "npdl_print_page_copies(CompBuf)"))) + return_error(gs_error_VMerror); + + /* Initialize printer */ +@@ -683,7 +683,7 @@ npdl_print_page_copies(gx_device_printer * pdev, gp_file * prn_stream, int num_c + /* Form Feed */ + gp_fputs("\014", prn_stream); + +- gs_free(pdev->memory->non_gc_memory, lprn->CompBuf, line_size * maxY, sizeof(byte), "npdl_print_page_copies(CompBuf)"); ++ gs_free(pdev->memory->non_gc_memory, lprn->CompBuf, line_size, maxY, "npdl_print_page_copies(CompBuf)"); + return 0; + } + +-- +2.49.0 + diff --git a/0001-OPVP-device-prevent-unsafe-parameter-change-with-SAF.patch b/0001-OPVP-device-prevent-unsafe-parameter-change-with-SAF.patch new file mode 100644 index 0000000000000000000000000000000000000000..9c736b7a1765370df444258bb8e4476bfbed8ea6 --- /dev/null +++ b/0001-OPVP-device-prevent-unsafe-parameter-change-with-SAF.patch @@ -0,0 +1,26 @@ +diff --git a/contrib/opvp/gdevopvp.c b/contrib/opvp/gdevopvp.c +index 74200cf..dc45b22 100644 +--- a/contrib/opvp/gdevopvp.c ++++ b/contrib/opvp/gdevopvp.c +@@ -3296,7 +3296,7 @@ _get_params(gx_device* dev, gs_param_list *plist) + /* vector driver name */ + pname = "Driver"; + vdps.data = (byte *)opdev->globals.vectorDriver; +- vdps.size = (opdev->globals.vectorDriver ? strlen(opdev->globals.vectorDriver) + 1 : 0); ++ vdps.size = (opdev->globals.vectorDriver ? strlen(opdev->globals.vectorDriver) : 0); + vdps.persistent = false; + code = param_write_string(plist, pname, &vdps); + if (code) ecode = code; +@@ -3456,6 +3456,12 @@ _put_params(gx_device *dev, gs_param_list *plist) + code = param_read_string(plist, pname, &vdps); + switch (code) { + case 0: ++ if (gs_is_path_control_active(dev->memory) ++ && (!opdev->globals.vectorDriver || strlen(opdev->globals.vectorDriver) != vdps.size ++ || memcmp(opdev->globals.vectorDriver, vdps.data, vdps.size) != 0)) { ++ param_signal_error(plist, pname, gs_error_invalidaccess); ++ return_error(gs_error_invalidaccess); ++ } + buff = realloc(buff, vdps.size + 1); + memcpy(buff, vdps.data, vdps.size); + buff[vdps.size] = 0; diff --git a/0001-PDF-interpreter-sanitise-W-array-values-in-Xref-stre.patch b/0001-PDF-interpreter-sanitise-W-array-values-in-Xref-stre.patch new file mode 100644 index 0000000000000000000000000000000000000000..d5d332e60ff52d944a06cb4f64ff98676a70e06b --- /dev/null +++ b/0001-PDF-interpreter-sanitise-W-array-values-in-Xref-stre.patch @@ -0,0 +1,62 @@ +From b1f0827c30f59a2dcbc8a39e42cace7a1de35f7f Mon Sep 17 00:00:00 2001 +From: Ken Sharp +Date: Mon, 2 Sep 2024 15:14:01 +0100 +Subject: [PATCH] PDF interpreter - sanitise W array values in Xref streams + +Bug #708001 "Buffer overflow in PDF XRef stream" + +See bug report. I've chosen to fix this by checking the values in the +W array; these can (currently at least) only have certain relatively +small values. + +As a future proofing fix I've also updated field_size in +pdf_xref_stream_entries() to be a 64-bit integer. This is far bigger +than required, but matches the W array values and so prevents the +mismatch which could lead to a buffer overrun. + +CVE-2024-46952 +--- + pdf/pdf_xref.c | 20 +++++++++++++++++++- + 1 file changed, 19 insertions(+), 1 deletion(-) + +diff --git a/pdf/pdf_xref.c b/pdf/pdf_xref.c +index fefd08abe..4ad0f548f 100644 +--- a/pdf/pdf_xref.c ++++ b/pdf/pdf_xref.c +@@ -53,7 +53,7 @@ static int resize_xref(pdf_context *ctx, uint64_t new_size) + static int read_xref_stream_entries(pdf_context *ctx, pdf_c_stream *s, int64_t first, int64_t last, int64_t *W) + { + uint i, j; +- uint field_width = 0; ++ uint64_t field_width = 0; + uint32_t type = 0; + uint64_t objnum = 0, gen = 0; + byte *Buffer; +@@ -305,6 +305,24 @@ static int pdfi_process_xref_stream(pdf_context *ctx, pdf_stream *stream_obj, pd + } + pdfi_countdown(a); + ++ /* W[0] is either: ++ * 0 (no type field) or a single byte with the type. ++ * W[1] is either: ++ * The object number of the next free object, the byte offset of this object in the file or the object5 number of the object stream where this object is stored. ++ * W[2] is either: ++ * The generation number to use if this object is used again, the generation number of the object or the index of this object within the object stream. ++ * ++ * Object and generation numbers are limited to unsigned 64-bit values, as are bytes offsets in the file, indexes of objects within the stream likewise (actually ++ * most of these are generally 32-bit max). So we can limit the field widths to 8 bytes, enough to hold a 64-bit number. ++ * Even if a later version of the spec makes these larger (which seems unlikely!) we still cna't cope with integers > 64-bits. ++ */ ++ if (W[0] > 1 || W[1] > 8 || W[2] > 8) { ++ pdfi_close_file(ctx, XRefStrm); ++ pdfi_countdown(ctx->xref_table); ++ ctx->xref_table = NULL; ++ return code; ++ } ++ + code = pdfi_dict_get_type(ctx, sdict, "Index", PDF_ARRAY, (pdf_obj **)&a); + if (code == gs_error_undefined) { + code = read_xref_stream_entries(ctx, XRefStrm, 0, size - 1, W); +-- +2.49.0 + diff --git a/0001-PS-interpreter-check-the-type-of-the-Pattern-Impleme.patch b/0001-PS-interpreter-check-the-type-of-the-Pattern-Impleme.patch new file mode 100644 index 0000000000000000000000000000000000000000..4fd4c189890b57d45ac0c02d8b8c5b6e5ab9bb58 --- /dev/null +++ b/0001-PS-interpreter-check-the-type-of-the-Pattern-Impleme.patch @@ -0,0 +1,31 @@ +From f49812186baa7d1362880673408a6fbe8719b4f8 Mon Sep 17 00:00:00 2001 +From: Zdenek Hutyra +Date: Fri, 30 Aug 2024 13:16:39 +0100 +Subject: [PATCH] PS interpreter - check the type of the Pattern Implementation + +Bug #707991 + +See bug report for details. + +CVE-2024-46951 +--- + psi/zcolor.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/psi/zcolor.c b/psi/zcolor.c +index d4e7a4438..d3384d75d 100644 +--- a/psi/zcolor.c ++++ b/psi/zcolor.c +@@ -5276,6 +5276,9 @@ static int patterncomponent(i_ctx_t * i_ctx_p, ref *space, int *n) + code = array_get(imemory, pImpl, 0, &pPatInst); + if (code < 0) + return code; ++ ++ if (!r_is_struct(&pPatInst) || (!r_has_stype(&pPatInst, imemory, st_pattern1_instance) && !r_has_stype(&pPatInst, imemory, st_pattern2_instance))) ++ return_error(gs_error_typecheck); + cc.pattern = r_ptr(&pPatInst, gs_pattern_instance_t); + if (pattern_instance_uses_base_space(cc.pattern)) + *n = n_comps; +-- +2.49.0 + diff --git a/0001-PostScript-interpreter-fix-buffer-length-check.patch b/0001-PostScript-interpreter-fix-buffer-length-check.patch new file mode 100644 index 0000000000000000000000000000000000000000..ca02452f6a5b97507b221eb00cfbddf04d8d7f44 --- /dev/null +++ b/0001-PostScript-interpreter-fix-buffer-length-check.patch @@ -0,0 +1,36 @@ +From f4151f12db32cd3ed26c24327de714bf2c3ed6ca Mon Sep 17 00:00:00 2001 +From: Zdenek Hutyra +Date: Tue, 23 Jul 2024 11:48:39 +0100 +Subject: [PATCH] PostScript interpreter - fix buffer length check + +Bug 707895 + +See bug report for details. + +CVE-2024-46956 +--- + psi/zfile.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/psi/zfile.c b/psi/zfile.c +index a4f5439cd..cb056494b 100644 +--- a/psi/zfile.c ++++ b/psi/zfile.c +@@ -1,4 +1,4 @@ +-/* Copyright (C) 2001-2023 Artifex Software, Inc. ++/* Copyright (C) 2001-2024 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or +@@ -443,7 +443,7 @@ file_continue(i_ctx_t *i_ctx_p) + if (code == ~(uint) 0) { /* all done */ + esp -= 6; /* pop proc, pfen, scratch, devlen, iodev , mark */ + return o_pop_estack; +- } else if (code > len) { /* overran string */ ++ } else if (code > len - devlen) { /* overran string */ + return_error(gs_error_rangecheck); + } + else if (iodev != iodev_default(imemory) +-- +2.49.0 + diff --git a/0001-Uniprint-device-prevent-string-configuration-changes.patch b/0001-Uniprint-device-prevent-string-configuration-changes.patch new file mode 100644 index 0000000000000000000000000000000000000000..0adbfa6863c580545744fbe66c34ff9bc70dc051 --- /dev/null +++ b/0001-Uniprint-device-prevent-string-configuration-changes.patch @@ -0,0 +1,79 @@ +From 3b1735085ecef20b29e8db3416ab36de93e86d1f Mon Sep 17 00:00:00 2001 +From: Ken Sharp +Date: Thu, 21 Mar 2024 09:01:15 +0000 +Subject: [PATCH] Uniprint device - prevent string configuration changes when + SAFER + +Bug #707662 + +We cannot sanitise the string arguments used by the Uniprint device +because they can potentially include anything. + +This commit ensures that these strings are locked and cannot be +changed by PostScript once SAFER is activated. Full configuration from +the command line is still possible (see the *.upp files in lib). + +This addresses CVE-2024-29510 +--- + devices/gdevupd.c | 31 +++++++++++++++++++++++++++++++ + 1 file changed, 31 insertions(+) + +diff --git a/devices/gdevupd.c b/devices/gdevupd.c +index c9389e7bc..016a9260a 100644 +--- a/devices/gdevupd.c ++++ b/devices/gdevupd.c +@@ -1891,6 +1891,16 @@ out on this copies. + if(!upd_strings[i]) continue; + UPD_PARAM_READ(param_read_string,upd_strings[i],value,udev->memory); + if(0 == code) { ++ if (gs_is_path_control_active(udev->memory)) { ++ if (strings[i].size != value.size) ++ error = gs_error_invalidaccess; ++ else { ++ if (strings[i].data && memcmp(strings[i].data, value.data, strings[i].size) != 0) ++ error = gs_error_invalidaccess; ++ } ++ if (error < 0) ++ goto exit; ++ } + if(0 <= error) error |= UPD_PUT_STRINGS; + UPD_MM_DEL_PARAM(udev->memory, strings[i]); + if(!value.size) { +@@ -1908,6 +1918,26 @@ out on this copies. + if(!upd_string_a[i]) continue; + UPD_PARAM_READ(param_read_string_array,upd_string_a[i],value,udev->memory); + if(0 == code) { ++ if (gs_is_path_control_active(udev->memory)) { ++ if (string_a[i].size != value.size) ++ error = gs_error_invalidaccess; ++ else { ++ int loop; ++ for (loop = 0;loop < string_a[i].size;loop++) { ++ gs_param_string *tmp1 = (gs_param_string *)&(string_a[i].data[loop]); ++ gs_param_string *tmp2 = (gs_param_string *)&value.data[loop]; ++ ++ if (tmp1->size != tmp2->size) ++ error = gs_error_invalidaccess; ++ else { ++ if (tmp1->data && memcmp(tmp1->data, tmp2->data, tmp1->size) != 0) ++ error = gs_error_invalidaccess; ++ } ++ } ++ } ++ if (error < 0) ++ goto exit; ++ } + if(0 <= error) error |= UPD_PUT_STRING_A; + UPD_MM_DEL_APARAM(udev->memory, string_a[i]); + if(!value.size) { +@@ -2102,6 +2132,7 @@ transferred into the device-structure. In the case of "uniprint", this may + if(0 > code) error = code; + } + ++exit: + if(0 < error) { /* Actually something loaded without error */ + + if(!(upd = udev->upd)) { +-- +2.45.2 + diff --git a/0001-X-device-fix-compiler-warning.patch b/0001-X-device-fix-compiler-warning.patch new file mode 100644 index 0000000000000000000000000000000000000000..6bb9eafa772cab49d0264ddbd839ebc3a12e3dd1 --- /dev/null +++ b/0001-X-device-fix-compiler-warning.patch @@ -0,0 +1,60 @@ +From 8f5c77af6c0b84bdea719010cf4f67877e857b2b Mon Sep 17 00:00:00 2001 +Message-ID: <8f5c77af6c0b84bdea719010cf4f67877e857b2b.1705768875.git.mjg@fedoraproject.org> +From: Ken Sharp +Date: Fri, 19 Jan 2024 08:44:33 +0000 +Subject: [PATCH] X device - fix compiler 'warning' + +Bug #707502 "- -Wincompatible-pointer-types warning in devices/gdevxini.c" + +This is probably an oversight from when we changed a load of variables +to size_t. + +Seems odd that compilers (well gcc) should refuse to compile becuase of +a warning, but that's compilers. The pointer type is incorrect so let's +fix it. +--- + devices/gdevx.h | 4 ++-- + devices/gdevxini.c | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/devices/gdevx.h b/devices/gdevx.h +index 82855ae15..1a513afcd 100644 +--- a/devices/gdevx.h ++++ b/devices/gdevx.h +@@ -1,4 +1,4 @@ +-/* Copyright (C) 2001-2023 Artifex Software, Inc. ++/* Copyright (C) 2001-2024 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or +@@ -39,7 +39,7 @@ typedef struct gx_device_X_s { + bool is_buffered; + bool IsPageDevice; + byte *buffer; /* full-window image */ +- long buffer_size; ++ size_t buffer_size; + gx_device_color_info orig_color_info; + + /* An XImage object for writing bitmap images to the screen */ +diff --git a/devices/gdevxini.c b/devices/gdevxini.c +index df489617c..5f68ce035 100644 +--- a/devices/gdevxini.c ++++ b/devices/gdevxini.c +@@ -1,4 +1,4 @@ +-/* Copyright (C) 2001-2023 Artifex Software, Inc. ++/* Copyright (C) 2001-2024 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or +@@ -621,7 +621,7 @@ x_set_buffer(gx_device_X * xdev) + } + if (mdev->width != xdev->width || mdev->height != xdev->height) { + byte *buffer; +- ulong space; ++ size_t space; + + if (gdev_mem_data_size(mdev, xdev->width, xdev->height, &space) < 0 || + space > xdev->space_params.MaxBitmap) { +-- +2.43.0.462.gcdfa2ea447 + diff --git a/ghostscript-10.02.1-PostScript-Fix-selectdevice.patch b/ghostscript-10.02.1-PostScript-Fix-selectdevice.patch new file mode 100644 index 0000000000000000000000000000000000000000..3aefed84591b5da3139bd2c3c344f5229ab60ffa --- /dev/null +++ b/ghostscript-10.02.1-PostScript-Fix-selectdevice.patch @@ -0,0 +1,33 @@ +From 2febe352146a62c77d62a5b5dde9607f66575d14 Mon Sep 17 00:00:00 2001 +Message-ID: <2febe352146a62c77d62a5b5dde9607f66575d14.1699398720.git.mjg@fedoraproject.org> +From: Ken Sharp +Date: Mon, 6 Nov 2023 15:30:18 +0000 +Subject: [PATCH] PostScript - Fix selectdevice + +Bug 707310 "`selectdevice` no longer works" + +This was an oversight. Fixed here. + +In future I anticipate removing selectdevice as well, as it doesn't do +anything that can't be done using setpagedevice (and .defaultscreen). +However, it is currently documented, so this restores the behaviour. +--- + Resource/Init/gs_init.ps | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps +index 958e8247c..d6b55efb2 100644 +--- a/Resource/Init/gs_init.ps ++++ b/Resource/Init/gs_init.ps +@@ -871,7 +871,7 @@ currentdict /.makeinternaldict .undef + ifelse + } bind def + /selectdevice +- { finddevice setdevice .setdefaultscreen } bind def ++ { finddevice setdevice .setdefaultscreen } bind odef + /signalerror % signalerror - + { /errordict .systemvar exch get exec } bind def + /signaloperror { % signaloperror - +-- +2.43.0.rc0.447.g76a1efa614 + diff --git a/ghostscript-10.02.1-txtwrite-device-needs-to-countdown-the-device-on-tex.patch b/ghostscript-10.02.1-txtwrite-device-needs-to-countdown-the-device-on-tex.patch new file mode 100644 index 0000000000000000000000000000000000000000..2eddb0489246fd2657671ba5854412c25a2ca0ab --- /dev/null +++ b/ghostscript-10.02.1-txtwrite-device-needs-to-countdown-the-device-on-tex.patch @@ -0,0 +1,31 @@ +From ea661034db7eb667375981dae883d0c9e7d79799 Mon Sep 17 00:00:00 2001 +Message-ID: +From: Ken Sharp +Date: Mon, 18 Sep 2023 17:40:18 +0100 +Subject: [PATCH] txtwrite device - needs to countdown the device on + text_release + +Bug #707132 "Error: finalizing subclassing device while child refcount > 1" + +The txtwrite device calls gs_text_enum_init() which counts up the +device, but does not count it down again when the enumertor is +released. Fixed here. +--- + devices/vector/gdevtxtw.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/devices/vector/gdevtxtw.c b/devices/vector/gdevtxtw.c +index f64284f07..089d32f7e 100644 +--- a/devices/vector/gdevtxtw.c ++++ b/devices/vector/gdevtxtw.c +@@ -2059,6 +2059,7 @@ textw_text_release(gs_text_enum_t *pte, client_name_t cname) + gs_free(tdev->memory, penum->text_state, 1, sizeof(penum->text_state), "txtwrite free text state"); + penum->text_state = NULL; + } ++ rc_decrement_only(pte->dev, "textw_text_release"); + } + + /* This is the list of methods for the text enumerator */ +-- +2.43.0.rc0.447.g76a1efa614 + diff --git a/ghostscript-10.02.1.tar.xz b/ghostscript-10.02.1.tar.xz new file mode 100644 index 0000000000000000000000000000000000000000..54364a456a2a57d31e02d57719a54ce6edb02e3d Binary files /dev/null and b/ghostscript-10.02.1.tar.xz differ diff --git a/ghostscript.spec b/ghostscript.spec index d46fb7aa7bd00a892f167a324bc7c45a6073a39b..1fab1c0aec7fb79e74fdc33694bd2ec26cf39595 100644 --- a/ghostscript.spec +++ b/ghostscript.spec @@ -1,4 +1,4 @@ -%define anolis_release 1 +%define anolis_release 2 %global _hardened_build 1 %global _docdir_fmt %{name} @@ -9,11 +9,11 @@ Name: ghostscript Summary: Interpreter for PostScript language & PDF -Version: 10.05.1 +Version: 10.05.1 Release: %{anolis_release}%{?dist} License: AGPLv3+ URL: https://ghostscript.com/ -Source0: https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs%{version_short}/ghostscript-%{version}.tar.xz +Source0: https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs10021/ghostscript-10.02.1.tar.xz BuildRequires: gcc gcc-c++ automake autoconf BuildRequires: adobe-mappings-cmap-devel adobe-mappings-pdf-devel @@ -23,6 +23,9 @@ BuildRequires: jbig2dec-devel = %{jbig2dec_version} jbig2dec-libs = %{jbig2de BuildRequires: lcms2-devel libidn2-devel libjpeg-turbo-devel libpng-devel BuildRequires: libpaper-devel libtiff-devel openjpeg2-devel zlib-devel BuildRequires: gtk3-devel libXt-devel make +BuildRequires: fontconfig +BuildRequires: git +BuildRequires: libijs-devel Requires: libgs = %{version}-%{release} jbig2dec-libs = %{jbig2dec_version} Requires: %{name}-tools-fonts = %{version}-%{release} Requires: %{name}-tools-printing = %{version}-%{release} @@ -32,6 +35,24 @@ Provides: ghostscript-core = %{version}-%{release} Obsoletes: ghostscript-core < 9.53.3-6 Patch0: ghostscript-10.01.0-fix-linkage.patch +Patch1: 0001-Bug-707130-Cast-to-void-to-avoid-compiler-warning.patch +Patch2: 0001-Bug-708133-Avoid-integer-overflow-leading-to-buffer-.patch +Patch3: 0001-Bug-707510-3-Bounds-checks-when-using-CIDFont-relate.patch +Patch4: 0001-Uniprint-device-prevent-string-configuration-changes.patch +Patch5: 0001-Bug-707510-don-t-use-strlen-on-passwords.patch +Patch6: ghostscript-10.02.1-txtwrite-device-needs-to-countdown-the-device-on-tex.patch +Patch7: 0001-PostScript-interpreter-fix-buffer-length-check.patch +Patch8: 0001-PS-interpreter-check-the-type-of-the-Pattern-Impleme.patch +Patch9: 0001-OPVP-device-prevent-unsafe-parameter-change-with-SAF.patch +Patch10: 0001-PDF-interpreter-sanitise-W-array-values-in-Xref-stre.patch +Patch11: 0001-Bug-707691.patch +Patch12: 0001-X-device-fix-compiler-warning.patch +Patch13: ghostscript-10.02.1-PostScript-Fix-selectdevice.patch +Patch14: 0001-Bug-707686.patch +Patch15: 0001-Bug-707510-review-printing-of-pointers.patch +Patch16: 0001-Bug-707510-don-t-allow-PDF-files-with-bad-Filters-to.patch +Patch17: 0001-Bug-707788-Fix-decode_utf8-to-forbid-overlong-encodi.patch +Patch18: 0001-Bug-707793-Check-for-overflow-validating-format-stri.patch # CVE-2024-29510 # Tracking bug: https://security-tracker.debian.org/tracker/CVE-2024-29510 @@ -296,6 +317,23 @@ install -m 0755 -d %{buildroot}%{_datadir}/%{name}/conf.d/ %changelog +* Fri Oct 17 2025 zhoujiajia111 - 10.05.1-2 +- Fix compiler warning by ensuring proper pointer type casting for stricter type compliance. +- Apply patch to prevent integer overflow that could lead to buffer overflow and potential remote code execution. +- Apply patch to prevent unauthorized configuration changes and strengthen security under SAFER mode. +- Fix password handling by using correct length to support null bytes and prevent truncation. +- Fix reference count leak to prevent device finalization errors. +- Apply patch to prevent buffer overflow vulnerabilities and enhance security against potential exploits. +- Apply patch to prevent type confusion and block potential exploits via malformed pattern inputs. +- Fix string length reporting and prevent unauthorized driver changes under path control. +- Apply patch to prevent buffer overflows by validating W array values and ensuring secure PDF parsing. +- Fix type inconsistencies to ensure clean compilation and prevent build failures on strict compilers. +- Fix the typo in selectdevice to restore functionality and maintain backward compatibility. +- Apply patch to fix a critical security vulnerability and prevent memory leaks in file path handling. +- Improve security, ensure deterministic output, and reduce debug noise by preventing unintended pointer exposure. +- Fix buffer overflow risk by dynamically allocating memory for filter names during debug logging. +- Apply patch to block overlong UTF-8 encodings and prevent potential directory traversal attacks. +- Apply patch to prevent integer overflow vulnerabilities and ensure safe handling of format strings in output filenames. * Fri May 23 2025 yangxinyu - 10.05.1-1 - New version 10.05.1