new file mode 100644
@@ -0,0 +1,134 @@
+From 0cae41b23a9669e801211dd4cf97b6dadd6dbdd7 Mon Sep 17 00:00:00 2001
+From: Ken Sharp <Ken.Sharp@artifex.com>
+Date: Thu, 22 May 2025 12:25:41 +0100
+Subject: [PATCH] pdfwrite - avoid buffer overrun
+
+Bug #708539 "Buffer overflow in pdf_write_cmap"
+
+The proposed fix in the report solves the buffer overrun, but does not
+tackle a number of other problems.
+
+This commit checks the result of stream_puts() in
+pdf_write_cid_system_info_to_stream() and correctly signals an error to
+the caller if that fails.
+
+In pdf_write_cid_system_info we replace a (rather small!) fixed size
+buffer with a dynamically allocated one using the lengths of the strings
+which pdf_write_cid_system_info_to_stream() will write, and a small
+fixed overhead to deal with the keys and initial byte '/'.
+
+Because 'buf' is used in the stream 's', if it is too small to hold all
+the CIDSystemInfo then we would get an error which was simply discarded
+previously.
+
+We now should avoid the potential error by ensuring the buffer is large
+enough for all the information, and if we do get an error we no longer
+silently ignore it, which would write an invalid PDF file.
+
+CVE: CVE-2025-59798
+Upstream-Status: Backport [https://github.com/ArtifexSoftware/ghostpdl/commit/0cae41b23a9669e801211dd4cf97b6dadd6dbdd7]
+Signed-off-by: Peter Marko <peter.marko@siemens.com>
+---
+ devices/vector/gdevpdtw.c | 52 ++++++++++++++++++++++++++++++---------
+ 1 file changed, 41 insertions(+), 11 deletions(-)
+
+diff --git a/devices/vector/gdevpdtw.c b/devices/vector/gdevpdtw.c
+index ced15c9b2..fe24dd73a 100644
+--- a/devices/vector/gdevpdtw.c
++++ b/devices/vector/gdevpdtw.c
+@@ -703,7 +703,8 @@ static int
+ pdf_write_cid_system_info_to_stream(gx_device_pdf *pdev, stream *s,
+ const gs_cid_system_info_t *pcidsi, gs_id object_id)
+ {
+- byte *Registry, *Ordering;
++ byte *Registry = NULL, *Ordering = NULL;
++ int code = 0;
+
+ Registry = gs_alloc_bytes(pdev->pdf_memory, pcidsi->Registry.size, "temporary buffer for Registry");
+ if (!Registry)
+@@ -734,14 +735,19 @@ pdf_write_cid_system_info_to_stream(gx_device_pdf *pdev, stream *s,
+ }
+ s_arcfour_process_buffer(&sarc4, Ordering, pcidsi->Ordering.size);
+ }
+- stream_puts(s, "<<\n/Registry");
++ code = stream_puts(s, "<<\n/Registry");
++ if (code < 0)
++ goto error;
+ s_write_ps_string(s, Registry, pcidsi->Registry.size, PRINT_HEX_NOT_OK);
+- stream_puts(s, "\n/Ordering");
++ code = stream_puts(s, "\n/Ordering");
++ if(code < 0)
++ goto error;
+ s_write_ps_string(s, Ordering, pcidsi->Ordering.size, PRINT_HEX_NOT_OK);
++error:
+ pprintd1(s, "\n/Supplement %d\n>>\n", pcidsi->Supplement);
+ gs_free_object(pdev->pdf_memory, Registry, "free temporary Registry buffer");
+ gs_free_object(pdev->pdf_memory, Ordering, "free temporary Ordering buffer");
+- return 0;
++ return code;
+ }
+
+ int
+@@ -786,31 +792,55 @@ pdf_write_cmap(gx_device_pdf *pdev, const gs_cmap_t *pcmap,
+ *ppres = writer.pres;
+ writer.pres->where_used = 0; /* CMap isn't a PDF resource. */
+ if (!pcmap->ToUnicode) {
+- byte buf[200];
++ byte *buf = NULL;
++ uint64_t buflen = 0;
+ cos_dict_t *pcd = (cos_dict_t *)writer.pres->object;
+ stream s;
+
++ /* We use 'buf' for the stream 's' below and that needs to have some extra
++ * space for the CIDSystemInfo. We also need an extra byte for the leading '/'
++ * 100 bytes is ample for the overhead.
++ */
++ buflen = pcmap->CIDSystemInfo->Registry.size + pcmap->CIDSystemInfo->Ordering.size + pcmap->CMapName.size + 100;
++ if (buflen > max_uint)
++ return_error(gs_error_limitcheck);
++
++ buf = gs_alloc_bytes(pdev->memory, buflen, "pdf_write_cmap");
++ if (buf == NULL)
++ return_error(gs_error_VMerror);
++
+ code = cos_dict_put_c_key_int(pcd, "/WMode", pcmap->WMode);
+- if (code < 0)
++ if (code < 0) {
++ gs_free_object(pdev->memory, buf, "pdf_write_cmap");
+ return code;
++ }
+ buf[0] = '/';
+ memcpy(buf + 1, pcmap->CMapName.data, pcmap->CMapName.size);
+ code = cos_dict_put_c_key_string(pcd, "/CMapName",
+ buf, pcmap->CMapName.size + 1);
+- if (code < 0)
++ if (code < 0) {
++ gs_free_object(pdev->memory, buf, "pdf_write_cmap");
+ return code;
++ }
+ s_init(&s, pdev->memory);
+- swrite_string(&s, buf, sizeof(buf));
++ swrite_string(&s, buf, buflen);
+ code = pdf_write_cid_system_info_to_stream(pdev, &s, pcmap->CIDSystemInfo, 0);
+- if (code < 0)
++ if (code < 0) {
++ gs_free_object(pdev->memory, buf, "pdf_write_cmap");
+ return code;
++ }
+ code = cos_dict_put_c_key_string(pcd, "/CIDSystemInfo",
+ buf, stell(&s));
+- if (code < 0)
++ if (code < 0) {
++ gs_free_object(pdev->memory, buf, "pdf_write_cmap");
+ return code;
++ }
+ code = cos_dict_put_string_copy(pcd, "/Type", "/CMap");
+- if (code < 0)
++ if (code < 0) {
++ gs_free_object(pdev->memory, buf, "pdf_write_cmap");
+ return code;
++ }
++ gs_free_object(pdev->memory, buf, "pdf_write_cmap");
+ }
+ if (pcmap->CMapName.size == 0) {
+ /* Create an arbitrary name (for ToUnicode CMap). */
@@ -25,6 +25,7 @@ def gs_verdir(v):
SRC_URI = "https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs${@gs_verdir("${PV}")}/${BPN}-${PV}.tar.gz \
file://ghostscript-9.16-Werror-return-type.patch \
file://avoid-host-contamination.patch \
+ file://CVE-2025-59798.patch \
"
SRC_URI[sha256sum] = "121861b6d29b2461dec6575c9f3cab665b810bd408d4ec02c86719fa708b0a49"