diff --git a/bugfix-for-cve-2025-27837.patch b/bugfix-for-cve-2025-27837.patch new file mode 100644 index 0000000000000000000000000000000000000000..363e32e9c841381cda74c99dc060a4cc0417ae0a --- /dev/null +++ b/bugfix-for-cve-2025-27837.patch @@ -0,0 +1,386 @@ +From 2cc7667188d65d350f9416c8f65637e39db23112 Mon Sep 17 00:00:00 2001 +From: Zdenek Hutyra +Date: Mon, 20 Jan 2025 14:43:42 +0000 +Subject: Windows platform code - error check UTF-8 conversions + +Bug #708238 see bug for details + +CVE-2025-27837 +--- + base/gp_mswin.c | 103 +++++++++++++++++++++++++++++++++-------------------- + base/gp_ntfs.c | 14 ++++++-- + base/gp_wgetv.c | 16 ++++++--- + base/gp_winfs.c | 8 +++-- + base/gsdparam.c | 5 +-- + base/winrtsup.cpp | 6 ++-- + devices/gdevwpr2.c | 15 +++++--- + 7 files changed, 110 insertions(+), 57 deletions(-) + +diff --git a/base/gp_mswin.c b/base/gp_mswin.c +index 1d995f25a..24d6de33e 100644 +--- a/base/gp_mswin.c ++++ b/base/gp_mswin.c +@@ -365,12 +365,20 @@ BOOL gp_OpenPrinter(char *port, LPHANDLE printer) + #ifdef METRO + return FALSE; + #else +- BOOL opened; +- wchar_t *uni = malloc(gp_utf8_to_uint16(NULL, port) * sizeof(wchar_t)); +- if (uni) ++ BOOL opened = false; ++ wchar_t *uni = NULL; ++ int size = 0; ++ ++ size = gp_utf8_to_uint16(NULL, port); ++ if (size <= 0) ++ return opened; ++ ++ uni = malloc(size * sizeof(wchar_t)); ++ if (uni) { + gp_utf8_to_uint16(uni, port); +- opened = OpenPrinterW(uni, printer, NULL); +- free(uni); ++ opened = OpenPrinterW(uni, printer, NULL); ++ free(uni); ++ } + return opened; + #endif + } +@@ -515,8 +523,11 @@ FILE *mswin_popen(const char *cmd, const char *mode) + siStartInfo.hStdError = hChildStderrWr; + + if (handle == 0) { +- command = (wchar_t *)malloc(sizeof(wchar_t)*gp_utf8_to_uint16(NULL, cmd)); +- if (command) ++ int size = gp_utf8_to_uint16(NULL, cmd); ++ ++ if (size > 0) ++ command = (wchar_t *)malloc(sizeof(wchar_t)*size); ++ if (command != NULL) + gp_utf8_to_uint16(command, cmd); + else + handle = -1; +@@ -566,6 +577,18 @@ FILE *mswin_popen(const char *cmd, const char *mode) + + /* ------ File naming and accessing ------ */ + ++static int limited_uint16_to_utf8(char* out, const unsigned short* in, size_t outlen) ++{ ++ int len = gp_uint16_to_utf8(NULL, in); ++ return (len < 0 || len > outlen) ? -1 : gp_uint16_to_utf8(out, in); ++} ++ ++static int limited_utf8_to_uint16(unsigned short* out, const char* in, size_t outlen) ++{ ++ int len = gp_utf8_to_uint16(NULL, in); ++ return (len < 0 || len > outlen) ? -1 : gp_utf8_to_uint16(out, in); ++} ++ + /* Create and open a scratch file with a given name prefix. */ + /* Write the actual file name at fname. */ + FILE * +@@ -599,9 +622,15 @@ gp_open_scratch_file_impl(const gs_memory_t *mem, + * local encoding. */ + l = GetTempPathWRT(_MAX_PATH, wTempDir); + #else +- GetTempPathW(_MAX_PATH, wTempDir); ++ l = GetTempPathW(_MAX_PATH, wTempDir); + #endif +- l = gp_uint16_to_utf8(sTempDir, wTempDir); ++ if (l == 0 || l > _MAX_PATH) ++ return NULL; ++ ++ l = limited_uint16_to_utf8(sTempDir, wTempDir, _MAX_PATH); ++ /* gp_uint16_to_utf8 returns a count including the terminator */ ++ if (l < 1) ++ return NULL; + } else + l = strlen(sTempDir); + } else { +@@ -614,14 +643,17 @@ gp_open_scratch_file_impl(const gs_memory_t *mem, + sTempDir[l-1] = '\\'; /* What Windoze prefers */ + + if (l <= _MAX_PATH) { +- gp_utf8_to_uint16(wTempDir, sTempDir); +- gp_utf8_to_uint16(wPrefix, prefix); ++ if (limited_utf8_to_uint16(wTempDir, sTempDir, _MAX_PATH) < 0) ++ return NULL; ++ if (limited_utf8_to_uint16(wPrefix, prefix, _MAX_PATH) < 0) ++ return NULL; ++ + #ifdef METRO + n = GetTempFileNameWRT(wTempDir, wPrefix, wTempFileName); + #else +- GetTempFileNameW(wTempDir, wPrefix, 0, wTempFileName); ++ n = GetTempFileNameW(wTempDir, wPrefix, 0, wTempFileName); + #endif +- n = gp_uint16_to_utf8(sTempFileName, wTempFileName); ++ + if (n == 0) { + /* If 'prefix' is not a directory, it is a path prefix. */ + int l = strlen(sTempDir), i; +@@ -636,38 +668,32 @@ gp_open_scratch_file_impl(const gs_memory_t *mem, + } + } + if (i > 0) { +- gp_utf8_to_uint16(wPrefix, sTempDir + i); ++ if (limited_utf8_to_uint16(wTempDir, sTempDir, _MAX_PATH) < 0) ++ return NULL; ++ if (limited_utf8_to_uint16(wPrefix, sTempDir + i, _MAX_PATH) < 0) ++ return NULL; + #ifdef METRO +- GetTempFileNameWRT(wTempDir, wPrefix, wTempFileName); ++ n = GetTempFileNameWRT(wTempDir, wPrefix, wTempFileName); + #else +- GetTempFileNameW(wTempDir, wPrefix, 0, wTempFileName); ++ n = GetTempFileNameW(wTempDir, wPrefix, 0, wTempFileName); + #endif +- n = gp_uint16_to_utf8(sTempFileName, wTempFileName); + } + } +- if (n != 0) { +- int len = gp_utf8_to_uint16(NULL, sTempFileName); +- wchar_t *uni = (len > 0 ? malloc(sizeof(wchar_t)*len) : NULL); +- if (uni == NULL) +- hfile = INVALID_HANDLE_VALUE; +- else { +- gp_utf8_to_uint16(uni, sTempFileName); ++ if (n > 0) { + #ifdef METRO +- hfile = CreateFile2(uni, +- GENERIC_READ | GENERIC_WRITE | DELETE, +- FILE_SHARE_READ | FILE_SHARE_WRITE, +- CREATE_ALWAYS | (remove ? FILE_FLAG_DELETE_ON_CLOSE : 0), +- NULL); ++ hfile = CreateFile2(wTempFileName, ++ GENERIC_READ | GENERIC_WRITE | DELETE, ++ FILE_SHARE_READ | FILE_SHARE_WRITE, ++ CREATE_ALWAYS | (remove ? FILE_FLAG_DELETE_ON_CLOSE : 0), ++ NULL); + #else +- hfile = CreateFileW(uni, +- GENERIC_READ | GENERIC_WRITE | DELETE, +- FILE_SHARE_READ | FILE_SHARE_WRITE, +- NULL, CREATE_ALWAYS, +- FILE_ATTRIBUTE_NORMAL | (remove ? FILE_FLAG_DELETE_ON_CLOSE : 0), +- NULL); ++ hfile = CreateFileW(wTempFileName, ++ GENERIC_READ | GENERIC_WRITE | DELETE, ++ FILE_SHARE_READ | FILE_SHARE_WRITE, ++ NULL, CREATE_ALWAYS, ++ FILE_ATTRIBUTE_NORMAL | (remove ? FILE_FLAG_DELETE_ON_CLOSE : 0), ++ NULL); + #endif +- free(uni); +- } + } + } + if (hfile != INVALID_HANDLE_VALUE) { +@@ -681,7 +707,8 @@ gp_open_scratch_file_impl(const gs_memory_t *mem, + } + } + if (f != NULL) { +- if ((strlen(sTempFileName) < gp_file_name_sizeof)) ++ l = limited_uint16_to_utf8(sTempFileName, wTempFileName, _MAX_PATH); ++ if (l >= 0 && (strlen(sTempFileName) < gp_file_name_sizeof)) + strncpy(fname, sTempFileName, gp_file_name_sizeof - 1); + else { + /* The file name is too long. */ +diff --git a/base/gp_ntfs.c b/base/gp_ntfs.c +index bf2a9805f..3419aca1b 100644 +--- a/base/gp_ntfs.c ++++ b/base/gp_ntfs.c +@@ -231,7 +231,7 @@ gp_enumerate_files_next_impl(gs_memory_t * mem, file_enum * pfen, char *ptr, uin + { + directory_enum *new_denum = NULL, *pden = pfen->current; + int code = 0; +- uint len; ++ uint len, outsize = (sizeof(pden->find_data.cFileName)*3+1)/2; + char outfname[(sizeof(pden->find_data.cFileName)*3+1)/2]; + + if (pfen->illegal) { +@@ -241,8 +241,12 @@ gp_enumerate_files_next_impl(gs_memory_t * mem, file_enum * pfen, char *ptr, uin + + for(;;) { + if (pden->first_time) { +- wchar_t *pat; +- pat = malloc(gp_utf8_to_uint16(NULL, pden->pattern)*sizeof(wchar_t)); ++ wchar_t *pat = NULL; ++ int size = 0; ++ ++ size = gp_utf8_to_uint16(NULL, pden->pattern); ++ if (size > 0) ++ pat = malloc(size*sizeof(wchar_t)); + if (pat == NULL) { + code = -1; + break; +@@ -319,6 +323,10 @@ gp_enumerate_files_next_impl(gs_memory_t * mem, file_enum * pfen, char *ptr, uin + gp_enumerate_files_close(mem, pfen); + return ~(uint) 0; + } ++ len = gp_uint16_to_utf8(outfname, pden->find_data.cFileName); ++ if (len >= outsize) ++ return ~(uint) 0; ++ + gp_uint16_to_utf8(outfname, pden->find_data.cFileName); + len = strlen(outfname); + +diff --git a/base/gp_wgetv.c b/base/gp_wgetv.c +index d4185a399..ad97de631 100644 +--- a/base/gp_wgetv.c ++++ b/base/gp_wgetv.c +@@ -39,8 +39,8 @@ gp_getenv_registry(HKEY hkeyroot, const wchar_t *key, const char *name, + LONG rc; + wchar_t *wptr; + wchar_t *wp = NULL; +- wchar_t *wname; +- int l = -1; ++ wchar_t *wname = NULL; ++ int l = -1, size = 0; + + if (*plen) { + wp = malloc((*plen)*sizeof(wchar_t)); +@@ -49,7 +49,10 @@ gp_getenv_registry(HKEY hkeyroot, const wchar_t *key, const char *name, + } + wptr = wp; + +- wname = malloc(gp_utf8_to_uint16(NULL, name)*sizeof(wchar_t)); ++ size = gp_utf8_to_uint16(NULL, name); ++ if (size >= 0) ++ wname = malloc(size*sizeof(wchar_t)); ++ + if (wname == NULL) { + if (wp) + free(wp); +@@ -113,10 +116,13 @@ gp_getenv_registry(HKEY hkeyroot, const wchar_t *key, const char *name, + int + gp_getenv(const char *name, char *ptr, int *plen) + { +- wchar_t *wname; ++ wchar_t *wname = NULL; + wchar_t *str; ++ int size; + +- wname = malloc(gp_utf8_to_uint16(NULL, name)*sizeof(wchar_t)); ++ size = gp_utf8_to_uint16(NULL, name); ++ if (size >= 0) ++ wname = malloc(size*sizeof(wchar_t)); + if (wname == NULL) { + return -1; + } +diff --git a/base/gp_winfs.c b/base/gp_winfs.c +index abb376bbb..a0d9ea83b 100644 +--- a/base/gp_winfs.c ++++ b/base/gp_winfs.c +@@ -44,8 +44,12 @@ gp_fopen_impl(gs_memory_t *mem, const char *fname, const char *mode) + if (uni == NULL) + return NULL; + gp_utf8_to_uint16(uni, fname); +- gp_utf8_to_uint16(wmode, mode); +- file = _wfopen(uni, wmode); ++ ++ len = gp_utf8_to_uint16(NULL, mode); ++ if (len >= 0) { ++ gp_utf8_to_uint16(wmode, mode); ++ file = _wfopen(uni, wmode); ++ } + gs_free_object(mem, uni, "gs_fopen_impl"); + + return file; +diff --git a/base/gsdparam.c b/base/gsdparam.c +index 5552ee4cb..80ba7cfcb 100644 +--- a/base/gsdparam.c ++++ b/base/gsdparam.c +@@ -1532,7 +1532,7 @@ gx_default_put_icc_colorants(gs_param_string *colorants, gx_device * dev) + char *tempstr; + int code; + int len; +- unsigned short *tempstr2; ++ unsigned short *tempstr2 = NULL; + unsigned short *s; + char *d; + +@@ -1554,7 +1554,8 @@ gx_default_put_icc_colorants(gs_param_string *colorants, gx_device * dev) + * UTF-8 chars that do not decode to 8 bits will be flagged up as a rangecheck. + */ + len = gp_utf8_to_uint16(NULL, tempstr); +- tempstr2 = (unsigned short *)gs_alloc_bytes(dev->memory, len * sizeof(unsigned short), ++ if (len >= 0) ++ tempstr2 = (unsigned short *)gs_alloc_bytes(dev->memory, len * sizeof(unsigned short), + "gx_default_put_icc_colorants"); + if (tempstr2 == NULL) + { +diff --git a/base/winrtsup.cpp b/base/winrtsup.cpp +index 937825201..e607130c5 100644 +--- a/base/winrtsup.cpp ++++ b/base/winrtsup.cpp +@@ -78,7 +78,7 @@ extern "C" UINT GetTempFileNameWRT(LPCWSTR lpPathName, LPCWSTR lpPrefixString, L + path.push_back('\\'); + + if (path.length() > _MAX_PATH - 14) +- return ERROR_BUFFER_OVERFLOW; ++ return 0; + + GetSystemTimeAsFileTime(&systemTimeAsFileTime); + +@@ -110,11 +110,11 @@ extern "C" UINT GetTempFileNameWRT(LPCWSTR lpPathName, LPCWSTR lpPrefixString, L + time++; + } + +- return ERROR_BUFFER_OVERFLOW; ++ return 0; + } + catch(...) + { +- return ERROR_BUFFER_OVERFLOW; ++ return 0; + } + } + +diff --git a/devices/gdevwpr2.c b/devices/gdevwpr2.c +index 666280a69..e7edbc616 100644 +--- a/devices/gdevwpr2.c ++++ b/devices/gdevwpr2.c +@@ -1079,7 +1079,7 @@ win_pr2_getdc(gx_device_win_pr2 * wdev) + HANDLE hprinter = NULL; + + /* fall back to prompting user */ +- int result = FALSE; ++ int result = FALSE, size; + + WCHAR* unidev = NULL; + WCHAR* unidriver = NULL; +@@ -1103,7 +1103,10 @@ win_pr2_getdc(gx_device_win_pr2 * wdev) + wchar_t *devices; + wchar_t *p; + int devices_size = 128, returned_length = 0; +- unidev = malloc(gp_utf8_to_uint16(NULL, device)*sizeof(wchar_t)); ++ ++ size = gp_utf8_to_uint16(NULL, device); ++ if (size >= 0) ++ unidev = malloc(size*sizeof(wchar_t)); + if (unidev == NULL) + goto cleanup; + gp_utf8_to_uint16(unidev, device); +@@ -1144,12 +1147,16 @@ win_pr2_getdc(gx_device_win_pr2 * wdev) + driver = gs_strtok(driverbuf, ",", &dbuflast); + output = gs_strtok(NULL, ",", &dbuflast); + +- unidriver = malloc(gp_utf8_to_uint16(NULL, driver) * sizeof(wchar_t)); ++ size = gp_utf8_to_uint16(NULL, driver); ++ if (size >= 0) ++ unidriver = malloc(size * sizeof(wchar_t)); + if (unidriver == NULL) + goto cleanup; + gp_utf8_to_uint16(unidriver, driver); + +- unioutput = malloc(gp_utf8_to_uint16(NULL, output) * sizeof(wchar_t)); ++ size = gp_utf8_to_uint16(NULL, output); ++ if (size >= 0) ++ unioutput = malloc(size * sizeof(wchar_t)); + if (unioutput == NULL) + goto cleanup; + gp_utf8_to_uint16(unioutput, output); +-- +cgit v1.2.3 + diff --git a/ghostscript.spec b/ghostscript.spec index 699579f59a55d17c8902800d99780997df2a7892..fbac4c98b597b2d793d28e9eb230a75ab98292d8 100644 --- a/ghostscript.spec +++ b/ghostscript.spec @@ -1,4 +1,4 @@ -%define anolis_release 6 +%define anolis_release 7 %global _hardened_build 1 %global _docdir_fmt %{name} @@ -88,6 +88,11 @@ Patch10: bugfix-for-cve-2025-27835.patch # Upstream fix: https://cgit.ghostscript.com/cgi-bin/cgit.cgi/ghostpdl.git/commit/?id=db77f4c0ce0 Patch11: bugfix-for-cve-2025-27836.patch +# CVE-2025-27837 +# Tracking bug: https://bugs.ghostscript.com/show_bug.cgi?id=708192 +# Upstream fix: https://cgit.ghostscript.com/cgi-bin/cgit.cgi/ghostpdl.git/commit/?id=db77f4c0ce0 +Patch12: bugfix-for-cve-2025-27837.patch + %description Ghostscript is an interpreter for PostScript® and Portable Document Format (PDF) files. @@ -281,6 +286,9 @@ install -m 0755 -d %{buildroot}%{_datadir}/%{name}/conf.d/ %changelog +* Mon Apr 28 2025 tomcruiseqi <10762123+tomcruiseqi@user.noreply.gitee.com> - 10.03.0-7 +- Fix CVE-2025-27837 + * Sun Apr 27 2025 tomcruiseqi <10762123+tomcruiseqi@user.noreply.gitee.com> - 10.03.0-6 - Fix CVE-2025-27836