Compare commits

...

No commits in common. "c8" and "c8-beta" have entirely different histories.
c8 ... c8-beta

13 changed files with 1 additions and 955 deletions

View File

@ -1,64 +0,0 @@
From 68c7275d4a580dca6c0ed3798f3717eea3513403 Mon Sep 17 00:00:00 2001
From: Robin Watts <Robin.Watts@artifex.com>
Date: Thu, 12 Sep 2019 09:35:01 +0100
Subject: [PATCH] Bug 701568: Fix gdevpx.c RLE stream handling.
The current code in pclxl_write_image_data_RLE passes
lines of data to the RLE compression routine. It tells
each invocation of that routine that this is the "last"
block of data, when clearly it is not.
Accordingly, the compression routine inserts the "EOD" byte
into the stream, and returns EOFC.
Independently of the return value used, having multiple EOD
bytes in the data is clearly wrong. Update the caller to only
pass "last" in for the last block.
The code still returns EOFC at the end of the data, so update
this final call to accept (indeed, expect) that return value
there.
---
devices/vector/gdevpx.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/devices/vector/gdevpx.c b/devices/vector/gdevpx.c
index 825e6b4c5..5d2d0edf5 100644
--- a/devices/vector/gdevpx.c
+++ b/devices/vector/gdevpx.c
@@ -714,6 +714,7 @@ pclxl_write_image_data_RLE(gx_device_pclxl * xdev, const byte * base,
uint num_bytes = ROUND_UP(width_bytes, 4) * height;
bool compress = num_bytes >= 8;
int i;
+ int code;
/* cannot handle data_bit not multiple of 8, but we don't invoke this routine that way */
int offset = data_bit >> 3;
@@ -752,19 +753,20 @@ pclxl_write_image_data_RLE(gx_device_pclxl * xdev, const byte * base,
r.ptr = data + i * raster - 1;
r.limit = r.ptr + width_bytes;
if ((*s_RLE_template.process)
- ((stream_state *) & rlstate, &r, &w, true) != 0 ||
+ ((stream_state *) & rlstate, &r, &w, false) != 0 ||
r.ptr != r.limit)
goto ncfree;
r.ptr = (const byte *)"\000\000\000\000\000";
r.limit = r.ptr + (-(int)width_bytes & 3);
if ((*s_RLE_template.process)
- ((stream_state *) & rlstate, &r, &w, true) != 0 ||
+ ((stream_state *) & rlstate, &r, &w, false) != 0 ||
r.ptr != r.limit)
goto ncfree;
}
r.ptr = r.limit;
- if ((*s_RLE_template.process)
- ((stream_state *) & rlstate, &r, &w, true) != 0)
+ code = (*s_RLE_template.process)
+ ((stream_state *) & rlstate, &r, &w, true);
+ if (code != EOFC && code != 0)
goto ncfree;
{
uint count = w.ptr + 1 - buf;
--
2.46.2

View File

@ -1,118 +0,0 @@
From 3b2ad1f24d2e9705481f9feb6835aa3e851726ac Mon Sep 17 00:00:00 2001
From: Robin Watts <Robin.Watts@artifex.com>
Date: Thu, 12 Sep 2019 17:09:50 +0100
Subject: [PATCH] Bug 701568 followup: Fix RLE compressor.
The previous fix to the RLE compressor reveals an additional
existing issue to do with us not checking whether we have
space in the buffer to write the EOD byte.
Fixed here.
---
base/srle.c | 78 ++++++++++++++++++++++++++++++-----------------------
1 file changed, 45 insertions(+), 33 deletions(-)
diff --git a/base/srle.c b/base/srle.c
index 50de0d847..0c0186e04 100644
--- a/base/srle.c
+++ b/base/srle.c
@@ -59,7 +59,13 @@ enum {
state_gt_012,
/* -n bytes into a repeated run, n0 and n1 read. */
- state_lt_01
+ state_lt_01,
+
+ /* We have reached the end of data, but not written the marker. */
+ state_eod_unmarked,
+
+ /* We have reached the end of data, and written the marker. */
+ state_eod
};
#ifdef DEBUG_RLE
@@ -294,43 +300,49 @@ run_len_0_n0_read:
}
}
}
- }
- /* n1 is never valid here */
+ /* n1 is never valid here */
- if (last) {
- if (run_len == 0) {
- /* EOD */
- if (wlimit - q < 1) {
- ss->state = state_0;
- goto no_output_room;
- }
- } else if (run_len > 0) {
- /* Flush literal run + EOD */
- if (wlimit - q < run_len+2) {
- ss->state = state_0;
- goto no_output_room;
+ if (last) {
+ if (run_len == 0) {
+ /* EOD */
+ if (wlimit - q < 1) {
+ ss->state = state_0;
+ goto no_output_room;
+ }
+ } else if (run_len > 0) {
+ /* Flush literal run + EOD */
+ if (wlimit - q < run_len+2) {
+ ss->state = state_0;
+ goto no_output_room;
+ }
+ *++q = run_len;
+ memcpy(q+1, ss->literals, run_len);
+ q += run_len;
+ *++q = n0;
+ } else if (run_len < 0) {
+ /* Flush repeated run + EOD */
+ if (wlimit - q < 3) {
+ ss->state = state_0;
+ goto no_output_room;
+ }
+ *++q = 257+run_len; /* Repeated run */
+ *++q = n0;
}
- *++q = run_len;
- memcpy(q+1, ss->literals, run_len);
- q += run_len;
- *++q = n0;
- } else if (run_len < 0) {
- /* Flush repeated run + EOD */
- if (wlimit - q < 3) {
- ss->state = state_0;
+ case state_eod_unmarked:
+ if (wlimit - q < 1) {
+ ss->state = state_eod_unmarked;
goto no_output_room;
}
- *++q = 257+run_len; /* Repeated run */
- *++q = n0;
+ *++q = 128; /* EOD */
+ case state_eod:
+ ss->run_len = 0;
+ ss->state = state_0;
+ pr->ptr = p;
+ pw->ptr = q;
+ ss->record_left = rlimit - p;
+ debug_ate(pinit, p, qinit, q, EOFC);
+ return EOFC;
}
- *++q = 128; /* EOD */
- ss->run_len = 0;
- ss->state = state_0;
- pr->ptr = p;
- pw->ptr = q;
- ss->record_left = rlimit - p;
- debug_ate(pinit, p, qinit, q, EOFC);
- return EOFC;
}
/* Normal exit */
--
2.46.2

View File

@ -1,31 +0,0 @@
From 4f6bc662909ab79e8fbe9822afb36e8a0eafc2b7 Mon Sep 17 00:00:00 2001
From: Julian Smith <jules@op59.net>
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

View File

@ -1,101 +0,0 @@
From b772aaf901a3cd37baf5c06eb141c689829bf673 Mon Sep 17 00:00:00 2001
From: Robin Watts <Robin.Watts@artifex.com>
Date: Tue, 26 Nov 2019 14:35:05 +0000
Subject: [PATCH] Bug 701949: Add 'omitEOD' flag to RLE compressor and use for
PXL.
It turns out that some printers (Samsung ML-2250 and Canon
ImageRunner iRC2380i at least) object to the EOD byte appearing
in RLE data in PXL streams.
Ken kindly checked the PXL spec for me, and found that: "The PXL
spec does say a control code of -128 is ignored and not included
in the decompressed data and the byte following a control byte
of 128 (I assume they mean -128 here) is treated as the next
control byte. And PCL only uses RLE data for images, so they do
know how much data they expect."
Thus, the conclusion we reached is that PCL/PXL don't need
(indeed, really does not want) the EOD byte.
The Postscript spec clearly defines the EOD byte though. Rather
than break the streams for postscript, we introduce a flag
'omitEOD' that can be set for the encoder when we want to produce
a stream for use with PCL/PXL.
---
base/srle.c | 10 ++++++----
base/srlx.h | 3 ++-
devices/vector/gdevpx.c | 1 +
psi/zfilter.c | 1 +
4 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/base/srle.c b/base/srle.c
index 0c0186e04..21b729f31 100644
--- a/base/srle.c
+++ b/base/srle.c
@@ -329,11 +329,13 @@ run_len_0_n0_read:
*++q = n0;
}
case state_eod_unmarked:
- if (wlimit - q < 1) {
- ss->state = state_eod_unmarked;
- goto no_output_room;
+ if (!ss->omitEOD) {
+ if (wlimit - q < 1) {
+ ss->state = state_eod_unmarked;
+ goto no_output_room;
+ }
+ *++q = 128; /* EOD */
}
- *++q = 128; /* EOD */
case state_eod:
ss->run_len = 0;
ss->state = state_0;
diff --git a/base/srlx.h b/base/srlx.h
index ebf172064..98309dbdb 100644
--- a/base/srlx.h
+++ b/base/srlx.h
@@ -32,6 +32,7 @@ typedef struct stream_RLE_state_s {
stream_RL_state_common;
/* The following parameters are set by the client. */
ulong record_size;
+ bool omitEOD;
/* The following change dynamically. */
ulong record_left; /* bytes left in current record */
byte n0;
@@ -47,7 +48,7 @@ typedef struct stream_RLE_state_s {
/* We define the initialization procedure here, so that clients */
/* can avoid a procedure call. */
#define s_RLE_set_defaults_inline(ss)\
- ((ss)->EndOfData = true, (ss)->record_size = 0)
+ ((ss)->EndOfData = true, (ss)->omitEOD = false, (ss)->record_size = 0)
#define s_RLE_init_inline(ss)\
((ss)->record_left =\
((ss)->record_size == 0 ? ((ss)->record_size = max_uint) :\
diff --git a/devices/vector/gdevpx.c b/devices/vector/gdevpx.c
index 5d2d0edf5..a1fce1b7c 100644
--- a/devices/vector/gdevpx.c
+++ b/devices/vector/gdevpx.c
@@ -741,6 +741,7 @@ pclxl_write_image_data_RLE(gx_device_pclxl * xdev, const byte * base,
goto nc;
s_RLE_set_defaults_inline(&rlstate);
rlstate.EndOfData = false;
+ rlstate.omitEOD = true;
s_RLE_init_inline(&rlstate);
w.ptr = buf - 1;
w.limit = w.ptr + num_bytes;
diff --git a/psi/zfilter.c b/psi/zfilter.c
index dfe3a1d5b..3ce7652c6 100644
--- a/psi/zfilter.c
+++ b/psi/zfilter.c
@@ -109,6 +109,7 @@ zRLE(i_ctx_t *i_ctx_p)
stream_RLE_state state;
int code;
+ s_RLE_template.set_defaults((stream_state *)&state);
check_op(2);
code = rl_setup(op - 1, &state.EndOfData);
if (code < 0)
--
2.47.0

View File

@ -1,239 +0,0 @@
From 4fcf527584da20538ebf9c3c43c3fda25d97cd18 Mon Sep 17 00:00:00 2001
From: Robin Watts <Robin.Watts@artifex.com>
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

View File

@ -1,42 +0,0 @@
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;

View File

@ -1,67 +0,0 @@
From 1f21a45df0fa3abec4cff12951022b192dda3c00 Mon Sep 17 00:00:00 2001
From: Zdenek Hutyra <zhutyra@centrum.cz>
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

View File

@ -1,22 +0,0 @@
diff --git a/contrib/japanese/gdevnpdl.c b/contrib/japanese/gdevnpdl.c
index 597ecc8..0aa5128 100644
--- a/contrib/japanese/gdevnpdl.c
+++ b/contrib/japanese/gdevnpdl.c
@@ -580,7 +580,7 @@ npdl_print_page_copies(gx_device_printer * pdev, FILE * prn_stream, int num_copi
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 */
@@ -675,7 +675,7 @@ npdl_print_page_copies(gx_device_printer * pdev, FILE * prn_stream, int num_copi
/* Form Feed */
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;
}

View File

@ -1,31 +0,0 @@
From f49812186baa7d1362880673408a6fbe8719b4f8 Mon Sep 17 00:00:00 2001
From: Zdenek Hutyra <zhutyra@centrum.cz>
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

View File

@ -1,13 +0,0 @@
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)

View File

@ -1,12 +0,0 @@
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;
}

View File

@ -1,154 +0,0 @@
diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
index 55a785e..be77534 100644
--- a/Resource/Init/gs_init.ps
+++ b/Resource/Init/gs_init.ps
@@ -2607,4 +2607,6 @@ WRITESYSTEMDICT {
% be 'true' in some cases.
userdict /AGM_preserve_spots //false put
+.opvpactivatepathcontrol
+
% The interpreter will run the initial procedure (start).
diff --git a/base/gslibctx.c b/base/gslibctx.c
index 1ed6093..14fb57c 100644
--- a/base/gslibctx.c
+++ b/base/gslibctx.c
@@ -435,3 +435,27 @@ gs_check_file_permission (gs_memory_t *mem, const char *fname, const int len, co
}
return code;
}
+
+void
+opvp_activate_path_control(gs_memory_t *mem, int enable)
+{
+ gs_lib_ctx_core_t *core;
+
+ if (mem == NULL || mem->gs_lib_ctx == NULL ||
+ (core = mem->gs_lib_ctx->core) == NULL)
+ return;
+
+ core->opvp_path_control_active = enable;
+}
+
+int
+opvp_is_path_control_active(const gs_memory_t *mem)
+{
+ gs_lib_ctx_core_t *core;
+
+ if (mem == NULL || mem->gs_lib_ctx == NULL ||
+ (core = mem->gs_lib_ctx->core) == NULL)
+ return 0;
+
+ return core->opvp_path_control_active;
+}
diff --git a/base/gslibctx.h b/base/gslibctx.h
index 1481cb5..e4b3924 100644
--- a/base/gslibctx.h
+++ b/base/gslibctx.h
@@ -61,6 +61,8 @@ typedef struct {
bool CPSI_mode;
int scanconverter;
int act_on_uel;
+
+ int opvp_path_control_active;
} gs_lib_ctx_core_t;
typedef struct gs_lib_ctx_s
@@ -167,4 +169,10 @@ int sjpxd_create(gs_memory_t *mem);
void sjpxd_destroy(gs_memory_t *mem);
+void
+opvp_activate_path_control(gs_memory_t *mem, int enable);
+
+int
+opvp_is_path_control_active(const gs_memory_t *mem);
+
#endif /* GSLIBCTX_H */
diff --git a/contrib/opvp/gdevopvp.c b/contrib/opvp/gdevopvp.c
index 9a6b45b..9693673 100644
--- a/contrib/opvp/gdevopvp.c
+++ b/contrib/opvp/gdevopvp.c
@@ -185,7 +185,7 @@ static int opvp_copy_color(gx_device *, const byte *, int, int,
static int _get_params(gs_param_list *);
static int opvp_get_params(gx_device *, gs_param_list *);
static int oprp_get_params(gx_device *, gs_param_list *);
-static int _put_params(gs_param_list *);
+static int _put_params(gx_device *, gs_param_list *);
static int opvp_put_params(gx_device *, gs_param_list *);
static int oprp_put_params(gx_device *, gs_param_list *);
static int opvp_fill_path(gx_device *, const gs_gstate *, gx_path *,
@@ -3039,7 +3039,7 @@ _get_params(gs_param_list *plist)
/* vector driver name */
pname = "Driver";
vdps.data = (byte *)vectorDriver;
- vdps.size = (vectorDriver ? strlen(vectorDriver) + 1 : 0);
+ vdps.size = (vectorDriver ? strlen(vectorDriver) : 0);
vdps.persistent = false;
code = param_write_string(plist, pname, &vdps);
if (code) ecode = code;
@@ -3176,7 +3176,7 @@ oprp_get_params(gx_device *dev, gs_param_list *plist)
* put params
*/
static int
-_put_params(gs_param_list *plist)
+_put_params(gx_device *dev, gs_param_list *plist)
{
int code;
int ecode = 0;
@@ -3198,6 +3198,12 @@ _put_params(gs_param_list *plist)
code = param_read_string(plist, pname, &vdps);
switch (code) {
case 0:
+ if (opvp_is_path_control_active(dev->memory)
+ && (!vectorDriver || strlen(vectorDriver) != vdps.size
+ || memcmp(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;
@@ -3399,7 +3405,7 @@ opvp_put_params(gx_device *dev, gs_param_list *plist)
int code;
/* put params */
- code = _put_params(plist);
+ code = _put_params(dev, plist);
if (code) return code;
/* put default params */
@@ -3415,7 +3421,7 @@ oprp_put_params(gx_device *dev, gs_param_list *plist)
int code;
/* put params */
- code = _put_params(plist);
+ code = _put_params(dev, plist);
if (code) return code;
/* put default params */
diff --git a/psi/zfile.c b/psi/zfile.c
index 271a1a0..05b8203 100644
--- a/psi/zfile.c
+++ b/psi/zfile.c
@@ -875,6 +875,12 @@ static int zgetfilename(i_ctx_t *i_ctx_p)
return 0;
}
+static int zopvpactivatepathcontrol(i_ctx_t *i_ctx_p)
+{
+ opvp_activate_path_control(imemory, 1);
+ return 0;
+}
+
/* ------ Initialization procedure ------ */
const op_def zfile_op_defs[] =
@@ -893,6 +899,7 @@ const op_def zfile_op_defs[] =
{"0%file_continue", file_continue},
{"0%execfile_finish", execfile_finish},
{"1.getfilename", zgetfilename},
+ {"0.opvpactivatepathcontrol", zopvpactivatepathcontrol},
op_def_end(0)
};

View File

@ -37,7 +37,7 @@
Name: ghostscript
Summary: Interpreter for PostScript language & PDF
Version: 9.27
Release: 17%{?dist}
Release: 12%{?dist}
License: AGPLv3+
@ -113,46 +113,6 @@ Patch020: ghostscript-9.27-CVE-2023-28879.patch
Patch021: ghostscript-9.27-CVE-2023-38559.patch
Patch022: ghostscript-9.27-CVE-2023-4042.patch
Patch023: ghostscript-9.27-avoid-divide-by-zero-in-devices.patch
# RHEL-38837 CVE-2024-33871 ghostscript: OPVP device arbitrary code execution via custom Driver library
# the patch is based on upstream code from 9.50, where a new -dSAFER implementation was introduced and
# -dSAFER was made default for any gs calls. To do not backport the whole new -dSAFER implementation,
# to do not collide with any future backports related with -dSAFER and to do not change the current default
# for ghostscript in RHEL 8, only part of the new -dSAFER implementation was backported,
# and the several functions, variables and macros prefix was changed to 'opvp' and used only
# for OPVP device, which results in changing the default only for this device and fixing the CVE.
# Downside of the fix is if someone depends on unsafe settings of driver for OPVP device
# (via Postscript code in command -c, via Postscript code in input file), gs will start to fail.
Patch024: gs-cve-2024-33871.patch
# RHEL-61729 Ghostscript is generating PJL of a significantly larger size
# Patches: 0001-Bug-701568-Fix-gdevpx.c-RLE-stream-handling.patch
# 0001-Bug-701568-followup-Fix-RLE-compressor.patch
# 0001-Bug-701949-Add-omitEOD-flag-to-RLE-compressor-and-us.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
# RHEL-88965 CVE-2025-27832 ghostscript: NPDL device: Compression buffer overflow
# https://github.com/ArtifexSoftware/ghostpdl/commit/57291c8463
Patch035: 0001-Bug-708133-Avoid-integer-overflow-leading-to-buffer-.patch
# Downstream patches -- these should be always included when doing rebase:
@ -493,26 +453,6 @@ done
# =============================================================================
%changelog
* Wed May 07 2025 Zdenek Dohnal <zdohnal@redhat.com> - 9.27-17
- RHEL-88965 CVE-2025-27832 ghostscript: NPDL device: Compression buffer overflow
* Tue Apr 15 2025 Zdenek Dohnal <zdohnal@redhat.com> - 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 <zdohnal@redhat.com> - 9.27-15
- fix printing PCL XL on some printers
* Thu Oct 10 2024 Zdenek Dohnal <zdohnal@redhat.com> - 9.27-14
- RHEL-61729 Ghostscript is generating PJL of a significantly larger size
* Wed Jun 12 2024 Zdenek Dohnal <zdohnal@redhat.com> - 9.27-13
- CVE-2024-33871 ghostscript: OPVP device arbitrary code execution via custom Driver library
* Tue Sep 19 2023 Richard Lescak <rlescak@redhat.com> - 9.27-12
- fix to prevent divison by zero in devices
- Resolves: rhbz#2235009