diff --git a/SOURCES/0001-Bug-701844-fixed-output-buffer-size-worst-case-in-lp.patch b/SOURCES/0001-Bug-701844-fixed-output-buffer-size-worst-case-in-lp.patch new file mode 100644 index 0000000..07b5391 --- /dev/null +++ b/SOURCES/0001-Bug-701844-fixed-output-buffer-size-worst-case-in-lp.patch @@ -0,0 +1,31 @@ +From 4f6bc662909ab79e8fbe9822afb36e8a0eafc2b7 Mon Sep 17 00:00:00 2001 +From: Julian Smith +Date: Wed, 6 Nov 2019 12:41:28 +0000 +Subject: [PATCH] Bug 701844: fixed output buffer size worst case in + lp8000_print_page(). + +Fixes: + ./sanbin/gs -dBATCH -dNOPAUSE -dSAFER -dFIXEDMEDIA -sPAPERSIZE=legal -sOutputFile=tmp -sDEVICE=lp8000 ../bug-701844.pdf +--- + devices/gdevlp8k.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/devices/gdevlp8k.c b/devices/gdevlp8k.c +index 0a9bc03c8..55af94df0 100644 +--- a/devices/gdevlp8k.c ++++ b/devices/gdevlp8k.c +@@ -185,7 +185,10 @@ lp8000_print_page(gx_device_printer *pdev, gp_file *prn_stream) + unsigned int report_size; + + byte *buf1 = (byte *)gs_malloc(pdev->memory, in_size, 1, "lp8000_print_page(buf1)"); +- byte *buf2 = (byte *)gs_malloc(pdev->memory, in_size, 1, "lp8000_print_page(buf2)"); ++ ++ /* Worst case for rle compression below is 3 bytes for each 2 bytes of ++ input, with extra final byte. */ ++ byte *buf2 = (byte *)gs_malloc(pdev->memory, in_size * 3 / 2 + 2, 1, "lp8000_print_page(buf2)"); + byte *in = buf1; + byte *out = buf2; + +-- +2.49.0 + diff --git a/SOURCES/0001-Bug-705911-Fix-Ghostscript-s-encoding-decoding-of-UT.patch b/SOURCES/0001-Bug-705911-Fix-Ghostscript-s-encoding-decoding-of-UT.patch new file mode 100644 index 0000000..36b70b2 --- /dev/null +++ b/SOURCES/0001-Bug-705911-Fix-Ghostscript-s-encoding-decoding-of-UT.patch @@ -0,0 +1,239 @@ +From 4fcf527584da20538ebf9c3c43c3fda25d97cd18 Mon Sep 17 00:00:00 2001 +From: Robin Watts +Date: Tue, 4 Oct 2022 17:36:56 +0100 +Subject: [PATCH] Bug 705911: Fix Ghostscript's encoding/decoding of UTF-8 from + UTF-16. + +We were not coping with high/low surrogate pairs in UTF-16, +meaning that we could encode/decode strings fine for our own +purposes, but when we passed them off to other users (such +as SmartOffice), it would fail to understand our utf-8 encoded +surrogate pairs. + +Thanks to Pete, Joseph and Fred for their help here, and to Silver +for having spotted it! +--- + base/gp_wutf8.c | 162 +++++++++++++++++++++++++++++++++++++----------- + 1 file changed, 127 insertions(+), 35 deletions(-) + +diff --git a/base/gp_wutf8.c b/base/gp_wutf8.c +index b7b1d0758..920114cd1 100644 +--- a/base/gp_wutf8.c ++++ b/base/gp_wutf8.c +@@ -16,6 +16,56 @@ + + #include "windows_.h" + ++static int ++decode_utf8(const char **inp, unsigned int i) ++{ ++ const char *in = *inp; ++ unsigned char c; ++ ++ if (i < 0x80) { ++ } else if ((i & 0xE0) == 0xC0) { ++ i &= 0x1F; ++ c = (unsigned char)*in++; ++ if ((c & 0xC0) != 0x80) ++ goto fail; ++ i = (i<<6) | (c & 0x3f); ++ } else if ((i & 0xF0) == 0xE0) { ++ i &= 0xF; ++ c = (unsigned char)*in++; ++ if ((c & 0xC0) != 0x80) ++ goto fail; ++ i = (i<<6) | (c & 0x3f); ++ c = (unsigned char)*in++; ++ if ((c & 0xC0) != 0x80) ++ goto fail; ++ i = (i<<6) | (c & 0x3f); ++ } else if ((i & 0xF8) == 0xF0) { ++ i &= 0x7; ++ c = (unsigned char)*in++; ++ if ((c & 0xC0) != 0x80) ++ goto fail; ++ i = (i<<6) | (c & 0x3f); ++ c = (unsigned char)*in++; ++ if ((c & 0xC0) != 0x80) ++ goto fail; ++ i = (i<<6) | (c & 0x3f); ++ c = (unsigned char)*in++; ++ if ((c & 0xC0) != 0x80) ++ goto fail; ++ i = (i<<6) | (c & 0x3f); ++ } ++ if (0) ++ { ++ /* If we fail, unread the last one, and return the unicode replacement char. */ ++fail: ++ in--; ++ i = 0xfffd; ++ } ++ *inp = in; ++ ++ return i; ++} ++ + int utf8_to_wchar(wchar_t *out, const char *in) + { + unsigned int i; +@@ -24,47 +74,37 @@ int utf8_to_wchar(wchar_t *out, const char *in) + + if (out) { + while (i = *(unsigned char *)in++) { +- if (i < 0x80) { +- *out++ = (wchar_t)i; +- len++; +- } else if ((i & 0xE0) == 0xC0) { +- i &= 0x1F; +- c = (unsigned char)*in++; +- if ((c & 0xC0) != 0x80) +- return -1; +- i = (i<<6) | (c & 0x3f); +- *out++ = (wchar_t)i; +- len++; +- } else if ((i & 0xF0) == 0xE0) { +- i &= 0xF; +- c = (unsigned char)*in++; +- if ((c & 0xC0) != 0x80) +- return -1; +- i = (i<<6) | (c & 0x3f); +- c = (unsigned char)*in++; +- if ((c & 0xC0) != 0x80) +- return -1; +- i = (i<<6) | (c & 0x3f); +- *out++ = (wchar_t)i; ++ /* Decode UTF-8 */ ++ i = decode_utf8(&in, i); ++ ++ /* Encode, allowing for surrogates. */ ++ if (i >= 0x10000 && i <= 0x10ffff) ++ { ++ i -= 0x10000; ++ *out++ = 0xd800 + (i>>10); ++ *out++ = 0xdc00 + (i & 0x3ff); + len++; +- } else { ++ } ++ else if (i > 0x10000) ++ { + return -1; + } ++ else ++ *out++ = (wchar_t)i; ++ len++; + } + *out = 0; + } else { + while (i = *(unsigned char *)in++) { +- if (i < 0x80) { +- len++; +- } else if ((i & 0xE0) == 0xC0) { +- in++; +- len++; +- } else if ((i & 0xF0) == 0xE0) { +- in+=2; ++ /* Decode UTF-8 */ ++ i = decode_utf8(&in, i); ++ ++ /* Encode, allowing for surrogates. */ ++ if (i >= 0x10000 && i <= 0x10ffff) + len++; +- } else { ++ else if (i > 0x10000) + return -1; +- } ++ len++; + } + } + return len; +@@ -74,9 +114,32 @@ int wchar_to_utf8(char *out, const wchar_t *in) + { + unsigned int i; + unsigned int len = 1; ++ int hi = -1; + + if (out) { + while (i = (unsigned int)*in++) { ++ /* Decode surrogates */ ++ if (i >= 0xD800 && i <= 0xDBFF) ++ { ++ /* High surrogate. Must be followed by a low surrogate, or this is a failure. */ ++ int hi = i & 0x3ff; ++ int j = (unsigned int)*in++; ++ if (j == 0 || (j <= 0xDC00 || j >= 0xDFFF)) ++ { ++ /* Failure! Unicode replacement char! */ ++ in--; ++ i = 0xfffd; ++ } else { ++ /* Decode surrogates */ ++ i = 0x10000 + (hi<<10) + (j & 0x3ff); ++ } ++ } else if (i >= 0xDC00 && i <= 0xDFFF) ++ { ++ /* Lone low surrogate. Failure. Unicode replacement char. */ ++ i = 0xfffd; ++ } ++ ++ /* Encode output */ + if (i < 0x80) { + *out++ = (char)i; + len++; +@@ -84,22 +147,51 @@ int wchar_to_utf8(char *out, const wchar_t *in) + *out++ = 0xC0 | ( i>> 6 ); + *out++ = 0x80 | ( i & 0x3F); + len+=2; +- } else /* if (i < 0x10000) */ { ++ } else if (i < 0x10000) { + *out++ = 0xE0 | ( i>>12 ); + *out++ = 0x80 | ((i>> 6) & 0x3F); + *out++ = 0x80 | ( i & 0x3F); + len+=3; ++ } else { ++ *out++ = 0xF0 | ( i>>18 ); ++ *out++ = 0x80 | ((i>>12) & 0x3F); ++ *out++ = 0x80 | ((i>> 6) & 0x3F); ++ *out++ = 0x80 | ( i & 0x3F); ++ len+=4; + } + } + *out = 0; + } else { + while (i = (unsigned int)*in++) { ++ /* Decode surrogates */ ++ if (i >= 0xD800 && i <= 0xDBFF) ++ { ++ /* High surrogate. Must be followed by a low surrogate, or this is a failure. */ ++ int hi = i & 0x3ff; ++ int j = (unsigned int)*in++; ++ if (j == 0 || (j <= 0xDC00 || j >= 0xDFFF)) ++ { ++ /* Failure! Unicode replacement char! */ ++ in--; ++ i = 0xfffd; ++ } else { ++ /* Decode surrogates */ ++ i = 0x10000 + (hi<<10) + (j & 0x3ff); ++ } ++ } else if (i >= 0xDC00 && i <= 0xDFFF) ++ { ++ /* Lone low surrogate. Failure. Unicode replacement char. */ ++ i = 0xfffd; ++ } ++ + if (i < 0x80) { + len++; + } else if (i < 0x800) { + len += 2; +- } else /* if (i < 0x10000) */ { ++ } else if (i < 0x10000) { + len += 3; ++ } else { ++ len += 4; + } + } + } +-- +2.49.0 + diff --git a/SOURCES/0001-Bug-707788-Fix-decode_utf8-to-forbid-overlong-encodi.patch b/SOURCES/0001-Bug-707788-Fix-decode_utf8-to-forbid-overlong-encodi.patch new file mode 100644 index 0000000..078a505 --- /dev/null +++ b/SOURCES/0001-Bug-707788-Fix-decode_utf8-to-forbid-overlong-encodi.patch @@ -0,0 +1,42 @@ +diff --git a/base/gp_wutf8.c b/base/gp_wutf8.c +index 56bedc1..23fcdd1 100644 +--- a/base/gp_wutf8.c ++++ b/base/gp_wutf8.c +@@ -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; diff --git a/SOURCES/0001-Bug-707793-Check-for-overflow-validating-format-stri.patch b/SOURCES/0001-Bug-707793-Check-for-overflow-validating-format-stri.patch new file mode 100644 index 0000000..4cafbfc --- /dev/null +++ b/SOURCES/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/SOURCES/0001-PS-interpreter-check-the-type-of-the-Pattern-Impleme.patch b/SOURCES/0001-PS-interpreter-check-the-type-of-the-Pattern-Impleme.patch new file mode 100644 index 0000000..4fd4c18 --- /dev/null +++ b/SOURCES/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/SOURCES/0001-PostScript-interpreter-fix-buffer-length-check.patch b/SOURCES/0001-PostScript-interpreter-fix-buffer-length-check.patch new file mode 100644 index 0000000..0dcf0d5 --- /dev/null +++ b/SOURCES/0001-PostScript-interpreter-fix-buffer-length-check.patch @@ -0,0 +1,13 @@ +diff --git a/psi/zfile.c b/psi/zfile.c +index 05b8203..ee40a75 100644 +--- a/psi/zfile.c ++++ b/psi/zfile.c +@@ -437,7 +437,7 @@ file_continue(i_ctx_t *i_ctx_p) + if (code == ~(uint) 0) { /* all done */ + esp -= 5; /* pop proc, pfen, 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) diff --git a/SOURCES/gs-CVE-2023-46751.patch b/SOURCES/gs-CVE-2023-46751.patch new file mode 100644 index 0000000..0c8c6c8 --- /dev/null +++ b/SOURCES/gs-CVE-2023-46751.patch @@ -0,0 +1,12 @@ +diff --git a/base/gdevprn.c b/base/gdevprn.c +index 459846a..84802d9 100644 +--- a/base/gdevprn.c ++++ b/base/gdevprn.c +@@ -1331,6 +1331,7 @@ gdev_prn_open_printer_seekable(gx_device *pdev, bool binary_mode, + && !IS_LIBCTX_STDERR(pdev->memory ,ppdev->file)) { + + code = gx_device_close_output_file(pdev, ppdev->fname, ppdev->file); ++ ppdev->file = NULL; + if (code < 0) + return code; + } diff --git a/SPECS/ghostscript.spec b/SPECS/ghostscript.spec index dcf52c8..eb8e142 100644 --- a/SPECS/ghostscript.spec +++ b/SPECS/ghostscript.spec @@ -37,7 +37,7 @@ Name: ghostscript Summary: Interpreter for PostScript language & PDF Version: 9.27 -Release: 15%{?dist} +Release: 16%{?dist} License: AGPLv3+ @@ -130,6 +130,26 @@ Patch024: gs-cve-2024-33871.patch Patch025: 0001-Bug-701568-Fix-gdevpx.c-RLE-stream-handling.patch Patch026: 0001-Bug-701568-followup-Fix-RLE-compressor.patch Patch027: 0001-Bug-701949-Add-omitEOD-flag-to-RLE-compressor-and-us.patch +# RHEL-18396 CVE-2023-46751 ghostscript: dangling pointer in gdev_prn_open_printer_seekable() +# partially taken from https://cgit.ghostscript.com/cgi-bin/cgit.cgi/ghostpdl.git/commit/?id=dcdbc595c13c9 +Patch028: gs-CVE-2023-46751.patch +# RHEL-67046 CVE-2024-46951 ghostscript: Arbitrary Code Execution in Artifex Ghostscript Pattern Color Space +# https://cgit.ghostscript.com/cgi-bin/cgit.cgi/ghostpdl.git/commit/?id=f49812186baa7 +Patch029: 0001-PS-interpreter-check-the-type-of-the-Pattern-Impleme.patch +# RHEL-15067 CVE-2020-27792 ghostscript: heap buffer over write vulnerability in GhostScript's lp8000_print_page() in gdevlp8k.c +# https://cgit.ghostscript.com/cgi-bin/cgit.cgi/ghostpdl.git/commit/?id=4f6bc662909a +Patch030: 0001-Bug-701844-fixed-output-buffer-size-worst-case-in-lp.patch +# RHEL-67051 CVE-2024-46954 ghostscript: Directory Traversal in Ghostscript via Overlong UTF-8 Encoding +# implementing decode_utf8() https://cgit.ghostscript.com/cgi-bin/cgit.cgi/ghostpdl.git/commit/?id=4fcf527584da2053 +# CVE fix, updated for gp_wutf8() in 9.27 https://cgit.ghostscript.com/cgi-bin/cgit.cgi/ghostpdl.git/commit/?id=282f691f5e57b6b +Patch031: 0001-Bug-705911-Fix-Ghostscript-s-encoding-decoding-of-UT.patch +Patch032: 0001-Bug-707788-Fix-decode_utf8-to-forbid-overlong-encodi.patch +# RHEL-67051 CVE-2024-46953 ghostscript: Path Traversal and Code Execution via Integer Overflow in Ghostscript +# https://cgit.ghostscript.com/cgi-bin/cgit.cgi/ghostpdl.git/commit/?id=1f21a45df0fa3abec +Patch033: 0001-Bug-707793-Check-for-overflow-validating-format-stri.patch +# RHEL-67051 CVE-2024-46956 ghostscript: Out-of-Bounds Data Access in Ghostscript Leads to Arbitrary Code Execution +# https://cgit.ghostscript.com/cgi-bin/cgit.cgi/ghostpdl.git/commit/?id=f4151f12db32cd3 +Patch034: 0001-PostScript-interpreter-fix-buffer-length-check.patch # Downstream patches -- these should be always included when doing rebase: @@ -470,6 +490,14 @@ done # ============================================================================= %changelog +* Tue Apr 15 2025 Zdenek Dohnal - 9.27-16 +- RHEL-18396 CVE-2023-46751 ghostscript: dangling pointer in gdev_prn_open_printer_seekable() +- RHEL-67046 CVE-2024-46951 ghostscript: Arbitrary Code Execution in Artifex Ghostscript Pattern Color Space +- RHEL-15067 CVE-2020-27792 ghostscript: heap buffer over write vulnerability in GhostScript's lp8000_print_page() in gdevlp8k.c +- RHEL-67051 CVE-2024-46954 ghostscript: Directory Traversal in Ghostscript via Overlong UTF-8 Encoding +- RHEL-67051 CVE-2024-46953 ghostscript: Path Traversal and Code Execution via Integer Overflow in Ghostscript +- RHEL-67051 CVE-2024-46956 ghostscript: Out-of-Bounds Data Access in Ghostscript Leads to Arbitrary Code Execution + * Mon Oct 14 2024 Zdenek Dohnal - 9.27-15 - fix printing PCL XL on some printers