Package: release.debian.org Severity: normal Tags: bookworm X-Debbugs-Cc: [email protected], [email protected] Control: affects -1 + src:mapserver User: [email protected] Usertags: pu
[ Reason ] Fix <no-dsa> issue CVE-2025-59431 and heap-buffer-overflow + double-free issues in the lexer. [ Impact ] Users will remain vulnerable to CVE-2025-59431, and will regress when upgrading (a fix was uploaded to Bullseye LTS). [ Tests ] PoC at https://github.com/MapServer/MapServer/security/advisories/GHSA-256m-rx4h-r55w and msautotest/wxs tests from the upstream fix https://github.com/MapServer/MapServer/commit/1c73acaa2d7a8b1d3955f076186e57fc8c06e0c6 (msautotests are not run at build-time nor via autopkgtests, but I ran them manually.) [ Risks ] Fixes are simple, come from upstream branch-8-0 and branch-8-4, and apply cleanly except for the *generated* maplexer.c. [ Checklist ] [x] *all* changes are documented in the d/changelog [x] I reviewed all changes and I approve them [x] attach debdiff against the package in oldstable [x] the issue is verified as fixed in unstable [ Changes ] * Fix CVE-2025-59431: Boolean-based SQL injection vulnerability in directive PropertyName of the XML Filter Query. * Fix heap-buffer-overflow and double-free issues in maplexer. * Add d/salsa-ci.yml for Salsa CI. [ Other info ] The attached debdiff excludes d/p/9999-Update-maplexer.c.patch as the resulted maplexer.c is autogenerated. Unfortunately generation is not part of the build process so needs to be done via d/patches, and the resulting patch adds a lot of clutter. I separately attach this patch anyway. An alternative would be to change d/rules to call `touch maplexer.l && make lexer`, at the expense of a new "Build-Depends: flex". Regarding the changes to d/libmapserver2.symbols, I'd like to point out that libmapserver2 has no (Build-)Depends outside src:mapserver, and "internal" symbols msyystring_buffer_ptr and msyystring_size_tmp were only used by the lexer which belongs to libmapserver2. -- Guilhem.
diffstat for mapserver-8.0.0 mapserver-8.0.0 changelog | 10 libmapserver2.symbols | 3 patches/0005-maplexer.l-avoid-non-null-terminated-msyystring_buff.patch | 250 +++++++++ patches/0006-maplexer.l-fix-heap-buffer-overflow-issues-with-NUL-.patch | 200 +++++++ patches/0007-mapfile-parser-fix-double-free-when-included-file-do.patch | 36 + patches/CVE-2025-59431.patch | 255 ++++++++++ patches/series | 5 salsa-ci.yml | 9 8 files changed, 766 insertions(+), 2 deletions(-) diff -Nru --exclude 9999-Update-maplexer.c.patch mapserver-8.0.0/debian/changelog mapserver-8.0.0/debian/changelog --- mapserver-8.0.0/debian/changelog 2022-11-05 14:38:38.000000000 +0100 +++ mapserver-8.0.0/debian/changelog 2026-03-23 15:02:59.000000000 +0100 @@ -1,3 +1,13 @@ +mapserver (8.0.0-3+deb12u1) bookworm; urgency=high + + * Non-maintainer upload. + * Fix CVE-2025-59431: Boolean-based SQL injection vulnerability in directive + PropertyName of the XML Filter Query. + * Fix heap-buffer-overflow and double-free issues in maplexer. + * Add d/salsa-ci.yml for Salsa CI. + + -- Guilhem Moulin <[email protected]> Mon, 23 Mar 2026 15:02:59 +0100 + mapserver (8.0.0-3) unstable; urgency=medium * Move from experimental to unstable. diff -Nru --exclude 9999-Update-maplexer.c.patch mapserver-8.0.0/debian/libmapserver2.symbols mapserver-8.0.0/debian/libmapserver2.symbols --- mapserver-8.0.0/debian/libmapserver2.symbols 2022-11-03 20:18:11.000000000 +0100 +++ mapserver-8.0.0/debian/libmapserver2.symbols 2026-03-23 15:02:59.000000000 +0100 @@ -2938,6 +2938,7 @@ msStringTrimBlanks@Base 6.2.1 msStringTrimEOL@Base 6.2.1 msStringTrimLeft@Base 6.2.1 + msStringUnescape@Base 8.0.0-3+deb12u1~ msStripPath@Base 6.2.1 msStrptime@Base 6.2.1 msStyleGetGeomTransform@Base 6.2.1 @@ -3135,12 +3136,10 @@ msyystring_begin@Base 6.2.1 msyystring_begin_state@Base 6.2.1 msyystring_buffer@Base 6.2.1 - msyystring_buffer_ptr@Base 6.2.1 msyystring_buffer_size@Base 6.2.1 msyystring_icase@Base 6.2.1 msyystring_return_state@Base 6.2.1 msyystring_size@Base 6.2.1 - msyystring_size_tmp@Base 6.2.1 msyytext@Base 6.2.1 msyywrap@Base 6.2.1 mvtWriteShape@Base 7.2.0 diff -Nru --exclude 9999-Update-maplexer.c.patch mapserver-8.0.0/debian/patches/0005-maplexer.l-avoid-non-null-terminated-msyystring_buff.patch mapserver-8.0.0/debian/patches/0005-maplexer.l-avoid-non-null-terminated-msyystring_buff.patch --- mapserver-8.0.0/debian/patches/0005-maplexer.l-avoid-non-null-terminated-msyystring_buff.patch 1970-01-01 01:00:00.000000000 +0100 +++ mapserver-8.0.0/debian/patches/0005-maplexer.l-avoid-non-null-terminated-msyystring_buff.patch 2026-03-23 15:02:59.000000000 +0100 @@ -0,0 +1,250 @@ +From: Even Rouault <[email protected]> +Date: Fri, 7 Oct 2022 13:11:43 +0200 +Subject: maplexer.l: avoid non-null terminated msyystring_buffer that can + cause read heap-buffer-overflow + +Origin: https://github.com/MapServer/MapServer/commit/76c504a8acacde15781179c4b29e4123d0858c52 +Bug: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=52175 +--- + maplexer.l | 81 ++++++++++++++++++++++++++++---------------------------------- + 1 file changed, 36 insertions(+), 45 deletions(-) + +diff --git a/maplexer.l b/maplexer.l +index a3987da..00b3c85 100644 +--- a/maplexer.l ++++ b/maplexer.l +@@ -46,7 +46,6 @@ double msyynumber; + int msyystate=MS_TOKENIZE_DEFAULT; + char *msyystring=NULL; + char *msyybasepath=NULL; +-char *msyystring_buffer_ptr; + int msyystring_buffer_size = 0; + int msyystring_size; + char msyystring_begin; +@@ -54,25 +53,21 @@ char *msyystring_buffer = NULL; + int msyystring_icase = MS_FALSE; + int msyystring_return_state; + int msyystring_begin_state; +-int msyystring_size_tmp; + + int msyyreturncomments = 0; + +-#define MS_LEXER_STRING_REALLOC(string, string_size, max_size, string_ptr) \ ++#define MS_LEXER_STRING_REALLOC(string, string_size, max_size) \ + do { \ + const int string_size_macro = (int)(string_size); \ + if (string_size_macro >= (int)(max_size)) { \ +- msyystring_size_tmp = (max_size); \ + max_size = (((int)(max_size)*2) > string_size_macro) ? ((int)(max_size))*2 : string_size_macro+1; \ + string = (char *) msSmallRealloc(string, sizeof(char *) * (max_size)); \ +- string_ptr = string; \ +- string_ptr += msyystring_size_tmp; \ + } \ + } while(0) + + #define MS_LEXER_RETURN_TOKEN(token) \ + MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), \ +- msyystring_buffer_size, msyystring_buffer_ptr); \ ++ msyystring_buffer_size); \ + strcpy(msyystring_buffer, msyytext); \ + return(token); + +@@ -491,7 +486,7 @@ char path[MS_MAXPATHLEN]; + msyytext++; + msyytext[strlen(msyytext)-1] = '\0'; + MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), +- msyystring_buffer_size, msyystring_buffer_ptr); ++ msyystring_buffer_size); + strcpy(msyystring_buffer,msyytext); + return(MS_BINDING); + } +@@ -513,7 +508,7 @@ char path[MS_MAXPATHLEN]; + msyytext++; + msyytext[strlen(msyytext)-1] = '\0'; + MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), +- msyystring_buffer_size, msyystring_buffer_ptr); ++ msyystring_buffer_size); + strcpy(msyystring_buffer, msyytext); + return(MS_TOKEN_BINDING_DOUBLE); + } +@@ -522,7 +517,7 @@ char path[MS_MAXPATHLEN]; + msyytext+=2; + msyytext[strlen(msyytext)-2] = '\0'; + MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), +- msyystring_buffer_size, msyystring_buffer_ptr); ++ msyystring_buffer_size); + strcpy(msyystring_buffer, msyytext); + return(MS_TOKEN_BINDING_STRING); + } +@@ -531,14 +526,14 @@ char path[MS_MAXPATHLEN]; + msyytext+=2; + msyytext[strlen(msyytext)-2] = '\0'; + MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), +- msyystring_buffer_size, msyystring_buffer_ptr); ++ msyystring_buffer_size); + strcpy(msyystring_buffer, msyytext); + return(MS_TOKEN_BINDING_TIME); + } + + <INITIAL>-?[0-9]+|-?[0-9]+\.[0-9]*|-?\.[0-9]*|-?[0-9]+[eE][+-]?[0-9]+|-?[0-9]+\.[0-9]*[eE][+-]?[0-9]+|-?\.[0-9]*[eE][+-]?[0-9]+ { + MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), +- msyystring_buffer_size, msyystring_buffer_ptr); ++ msyystring_buffer_size); + strcpy(msyystring_buffer,msyytext); + msyynumber = atof(msyytext); + return(MS_NUMBER); +@@ -546,7 +541,7 @@ char path[MS_MAXPATHLEN]; + + <EXPRESSION_STRING>-?[0-9]+|-?[0-9]+\.[0-9]*|-?\.[0-9]*|-?[0-9]+[eE][+-]?[0-9]+|-?[0-9]+\.[0-9]*[eE][+-]?[0-9]+|-?\.[0-9]*[eE][+-]?[0-9]+ { + MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), +- msyystring_buffer_size, msyystring_buffer_ptr); ++ msyystring_buffer_size); + strcpy(msyystring_buffer,msyytext); + msyynumber = atof(msyytext); + return(MS_TOKEN_LITERAL_NUMBER); +@@ -556,7 +551,7 @@ char path[MS_MAXPATHLEN]; + msyytext++; + msyytext[strlen(msyytext)-1] = '\0'; + MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), +- msyystring_buffer_size, msyystring_buffer_ptr); ++ msyystring_buffer_size); + strcpy(msyystring_buffer, msyytext); + return(MS_TOKEN_LITERAL_TIME); + } +@@ -565,7 +560,7 @@ char path[MS_MAXPATHLEN]; + msyytext++; + msyytext[strlen(msyytext)-2] = '\0'; + MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), +- msyystring_buffer_size, msyystring_buffer_ptr); ++ msyystring_buffer_size); + strcpy(msyystring_buffer, msyytext); + return(MS_IREGEX); + } +@@ -574,7 +569,7 @@ char path[MS_MAXPATHLEN]; + msyytext++; + msyytext[strlen(msyytext)-1] = '\0'; + MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), +- msyystring_buffer_size, msyystring_buffer_ptr); ++ msyystring_buffer_size); + strcpy(msyystring_buffer, msyytext); + return(MS_REGEX); + } +@@ -583,7 +578,7 @@ char path[MS_MAXPATHLEN]; + msyytext++; + msyytext[strlen(msyytext)-1] = '\0'; + MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), +- msyystring_buffer_size, msyystring_buffer_ptr); ++ msyystring_buffer_size); + strcpy(msyystring_buffer, msyytext); + return(MS_EXPRESSION); + } +@@ -592,7 +587,7 @@ char path[MS_MAXPATHLEN]; + msyytext++; + msyytext[strlen(msyytext)-1] = '\0'; + MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), +- msyystring_buffer_size, msyystring_buffer_ptr); ++ msyystring_buffer_size); + strcpy(msyystring_buffer, msyytext); + return(MS_LIST); + } +@@ -601,18 +596,13 @@ char path[MS_MAXPATHLEN]; + msyystring_return_state = MS_STRING; + msyystring_begin = msyytext[0]; + msyystring_size = 0; +- msyystring_buffer_ptr = msyystring_buffer; ++ msyystring_buffer[0] = '\0'; + BEGIN(MSSTRING); + } + + <MSSTRING>\'|\"|\"i|\'i { +- MS_LEXER_STRING_REALLOC(msyystring_buffer, msyystring_size, +- msyystring_buffer_size, msyystring_buffer_ptr); + if (msyystring_begin == msyytext[0]) { + BEGIN(msyystring_begin_state); +- +- *msyystring_buffer_ptr = '\0'; +- + if (msyystring_return_state == MS_STRING) { + if (msyystring_icase && strlen(msyytext)==2) { + msyystring_icase = MS_FALSE; // reset +@@ -624,36 +614,37 @@ char path[MS_MAXPATHLEN]; + + } + else { +- ++msyystring_size; +- *msyystring_buffer_ptr++ = *msyytext; ++ int old_size = msyystring_size; ++ msyystring_size += (strlen(msyytext)==2) ? 2 : 1; ++ MS_LEXER_STRING_REALLOC(msyystring_buffer, msyystring_size, ++ msyystring_buffer_size); ++ msyystring_buffer[old_size] = *msyytext; + if (strlen(msyytext)==2) { +- MS_LEXER_STRING_REALLOC(msyystring_buffer, msyystring_size, +- msyystring_buffer_size, msyystring_buffer_ptr); +- ++msyystring_size; +- *msyystring_buffer_ptr++ = msyytext[1]; ++ msyystring_buffer[old_size+1] = msyytext[1]; + } ++ msyystring_buffer[msyystring_size] = '\0'; + } + } + + <MSSTRING>\\\'|\\\"|\\\\|\\ { +- MS_LEXER_STRING_REALLOC(msyystring_buffer, msyystring_size, +- msyystring_buffer_size, msyystring_buffer_ptr); +- + ++msyystring_size; ++ MS_LEXER_STRING_REALLOC(msyystring_buffer, msyystring_size, ++ msyystring_buffer_size); ++ + if (strlen(msyytext) == 2) +- *msyystring_buffer_ptr++ = msyytext[1]; ++ msyystring_buffer[msyystring_size-1] = msyytext[1]; + else +- *msyystring_buffer_ptr++ = msyytext[0]; ++ msyystring_buffer[msyystring_size-1] = msyytext[0]; ++ msyystring_buffer[msyystring_size] = '\0'; + } + + <MSSTRING>[^\\\'\\\"]+ { +- char *yptr = msyytext; +- while ( *yptr ) { +- MS_LEXER_STRING_REALLOC(msyystring_buffer, msyystring_size, +- msyystring_buffer_size, msyystring_buffer_ptr); +- ++msyystring_size; +- *msyystring_buffer_ptr++ = *yptr++; +- } ++ int old_size = msyystring_size; ++ int msyytext_len = (int)strlen(msyytext); ++ msyystring_size += msyytext_len; ++ MS_LEXER_STRING_REALLOC(msyystring_buffer, msyystring_size, ++ msyystring_buffer_size); ++ memcpy(msyystring_buffer + old_size, msyytext, msyytext_len + 1); + } + + <INCLUDE>\"[^\"]*\"|\'[^\']*\' { +@@ -686,13 +677,13 @@ char path[MS_MAXPATHLEN]; + msyystring_return_state = MS_TOKEN_LITERAL_STRING; + msyystring_begin = msyytext[0]; + msyystring_size = 0; +- msyystring_buffer_ptr = msyystring_buffer; ++ msyystring_buffer[0] = '\0'; + BEGIN(MSSTRING); + } + + <INITIAL,CONFIG_FILE>[a-z/\.][a-z0-9/\._\-\=]* { + MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), +- msyystring_buffer_size, msyystring_buffer_ptr); ++ msyystring_buffer_size); + strcpy(msyystring_buffer, msyytext); + return(MS_STRING); + } +@@ -716,7 +707,7 @@ char path[MS_MAXPATHLEN]; + + <INITIAL,CONFIG_FILE>. { + MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), +- msyystring_buffer_size, msyystring_buffer_ptr); ++ msyystring_buffer_size); + strcpy(msyystring_buffer, msyytext); + return(0); + } diff -Nru --exclude 9999-Update-maplexer.c.patch mapserver-8.0.0/debian/patches/0006-maplexer.l-fix-heap-buffer-overflow-issues-with-NUL-.patch mapserver-8.0.0/debian/patches/0006-maplexer.l-fix-heap-buffer-overflow-issues-with-NUL-.patch --- mapserver-8.0.0/debian/patches/0006-maplexer.l-fix-heap-buffer-overflow-issues-with-NUL-.patch 1970-01-01 01:00:00.000000000 +0100 +++ mapserver-8.0.0/debian/patches/0006-maplexer.l-fix-heap-buffer-overflow-issues-with-NUL-.patch 2026-03-23 15:02:59.000000000 +0100 @@ -0,0 +1,200 @@ +From: Even Rouault <[email protected]> +Date: Tue, 11 Oct 2022 00:48:52 +0200 +Subject: maplexer.l: fix heap-buffer-overflow issues with NUL characters + +Origin: https://github.com/MapServer/MapServer/commit/700ea8243c496f3d574102c432deaf1a85472271 +Bug: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=52305 +--- + maplexer.l | 59 +++++++++++++++++++++++++++++------------------------------ + 1 file changed, 29 insertions(+), 30 deletions(-) + +diff --git a/maplexer.l b/maplexer.l +index 00b3c85..7a67479c 100644 +--- a/maplexer.l ++++ b/maplexer.l +@@ -484,8 +484,8 @@ char path[MS_MAXPATHLEN]; + + <INITIAL>\[[^\]]*\] { + msyytext++; +- msyytext[strlen(msyytext)-1] = '\0'; +- MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), ++ msyytext[msyyleng-1-1] = '\0'; ++ MS_LEXER_STRING_REALLOC(msyystring_buffer, msyyleng, + msyystring_buffer_size); + strcpy(msyystring_buffer,msyytext); + return(MS_BINDING); +@@ -506,8 +506,8 @@ char path[MS_MAXPATHLEN]; + <EXPRESSION_STRING>\[[^\]]*\] { + /* attribute binding - numeric (no quotes) */ + msyytext++; +- msyytext[strlen(msyytext)-1] = '\0'; +- MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), ++ msyytext[msyyleng-1-1] = '\0'; ++ MS_LEXER_STRING_REALLOC(msyystring_buffer, msyyleng, + msyystring_buffer_size); + strcpy(msyystring_buffer, msyytext); + return(MS_TOKEN_BINDING_DOUBLE); +@@ -515,8 +515,8 @@ char path[MS_MAXPATHLEN]; + <EXPRESSION_STRING>\"\[[^\"]*\]\"|\'\[[^\']*\]\' { + /* attribute binding - string (single or double quotes) */ + msyytext+=2; +- msyytext[strlen(msyytext)-2] = '\0'; +- MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), ++ msyytext[msyyleng-2-2] = '\0'; ++ MS_LEXER_STRING_REALLOC(msyystring_buffer, msyyleng, + msyystring_buffer_size); + strcpy(msyystring_buffer, msyytext); + return(MS_TOKEN_BINDING_STRING); +@@ -524,15 +524,15 @@ char path[MS_MAXPATHLEN]; + <EXPRESSION_STRING>\`\[[^\`]*\]\` { + /* attribute binding - time */ + msyytext+=2; +- msyytext[strlen(msyytext)-2] = '\0'; +- MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), ++ msyytext[msyyleng-2-2] = '\0'; ++ MS_LEXER_STRING_REALLOC(msyystring_buffer, msyyleng, + msyystring_buffer_size); + strcpy(msyystring_buffer, msyytext); + return(MS_TOKEN_BINDING_TIME); + } + + <INITIAL>-?[0-9]+|-?[0-9]+\.[0-9]*|-?\.[0-9]*|-?[0-9]+[eE][+-]?[0-9]+|-?[0-9]+\.[0-9]*[eE][+-]?[0-9]+|-?\.[0-9]*[eE][+-]?[0-9]+ { +- MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), ++ MS_LEXER_STRING_REALLOC(msyystring_buffer, msyyleng, + msyystring_buffer_size); + strcpy(msyystring_buffer,msyytext); + msyynumber = atof(msyytext); +@@ -540,7 +540,7 @@ char path[MS_MAXPATHLEN]; + } + + <EXPRESSION_STRING>-?[0-9]+|-?[0-9]+\.[0-9]*|-?\.[0-9]*|-?[0-9]+[eE][+-]?[0-9]+|-?[0-9]+\.[0-9]*[eE][+-]?[0-9]+|-?\.[0-9]*[eE][+-]?[0-9]+ { +- MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), ++ MS_LEXER_STRING_REALLOC(msyystring_buffer, msyyleng, + msyystring_buffer_size); + strcpy(msyystring_buffer,msyytext); + msyynumber = atof(msyytext); +@@ -549,8 +549,8 @@ char path[MS_MAXPATHLEN]; + + <EXPRESSION_STRING>\`[^\`]*\` { + msyytext++; +- msyytext[strlen(msyytext)-1] = '\0'; +- MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), ++ msyytext[msyyleng-1-1] = '\0'; ++ MS_LEXER_STRING_REALLOC(msyystring_buffer, msyyleng, + msyystring_buffer_size); + strcpy(msyystring_buffer, msyytext); + return(MS_TOKEN_LITERAL_TIME); +@@ -558,8 +558,8 @@ char path[MS_MAXPATHLEN]; + + <INITIAL>\/[^*]{1}[^\/]*\/i { + msyytext++; +- msyytext[strlen(msyytext)-2] = '\0'; +- MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), ++ msyytext[msyyleng-1-2] = '\0'; ++ MS_LEXER_STRING_REALLOC(msyystring_buffer, msyyleng, + msyystring_buffer_size); + strcpy(msyystring_buffer, msyytext); + return(MS_IREGEX); +@@ -567,8 +567,8 @@ char path[MS_MAXPATHLEN]; + + <INITIAL>\/[^*]{1}[^\/]*\/ { + msyytext++; +- msyytext[strlen(msyytext)-1] = '\0'; +- MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), ++ msyytext[msyyleng-1-1] = '\0'; ++ MS_LEXER_STRING_REALLOC(msyystring_buffer, msyyleng, + msyystring_buffer_size); + strcpy(msyystring_buffer, msyytext); + return(MS_REGEX); +@@ -576,8 +576,8 @@ char path[MS_MAXPATHLEN]; + + <INITIAL>\(.*\) { + msyytext++; +- msyytext[strlen(msyytext)-1] = '\0'; +- MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), ++ msyytext[msyyleng-1-1] = '\0'; ++ MS_LEXER_STRING_REALLOC(msyystring_buffer, msyyleng, + msyystring_buffer_size); + strcpy(msyystring_buffer, msyytext); + return(MS_EXPRESSION); +@@ -585,8 +585,8 @@ char path[MS_MAXPATHLEN]; + + <INITIAL>\{.*\} { + msyytext++; +- msyytext[strlen(msyytext)-1] = '\0'; +- MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), ++ msyytext[msyyleng-1-1] = '\0'; ++ MS_LEXER_STRING_REALLOC(msyystring_buffer, msyyleng, + msyystring_buffer_size); + strcpy(msyystring_buffer, msyytext); + return(MS_LIST); +@@ -604,7 +604,7 @@ char path[MS_MAXPATHLEN]; + if (msyystring_begin == msyytext[0]) { + BEGIN(msyystring_begin_state); + if (msyystring_return_state == MS_STRING) { +- if (msyystring_icase && strlen(msyytext)==2) { ++ if (msyystring_icase && msyyleng==2) { + msyystring_icase = MS_FALSE; // reset + return MS_ISTRING; + } else +@@ -615,11 +615,11 @@ char path[MS_MAXPATHLEN]; + } + else { + int old_size = msyystring_size; +- msyystring_size += (strlen(msyytext)==2) ? 2 : 1; ++ msyystring_size += (msyyleng==2) ? 2 : 1; + MS_LEXER_STRING_REALLOC(msyystring_buffer, msyystring_size, + msyystring_buffer_size); + msyystring_buffer[old_size] = *msyytext; +- if (strlen(msyytext)==2) { ++ if (msyyleng==2) { + msyystring_buffer[old_size+1] = msyytext[1]; + } + msyystring_buffer[msyystring_size] = '\0'; +@@ -631,7 +631,7 @@ char path[MS_MAXPATHLEN]; + MS_LEXER_STRING_REALLOC(msyystring_buffer, msyystring_size, + msyystring_buffer_size); + +- if (strlen(msyytext) == 2) ++ if (msyyleng == 2) + msyystring_buffer[msyystring_size-1] = msyytext[1]; + else + msyystring_buffer[msyystring_size-1] = msyytext[0]; +@@ -640,16 +640,15 @@ char path[MS_MAXPATHLEN]; + + <MSSTRING>[^\\\'\\\"]+ { + int old_size = msyystring_size; +- int msyytext_len = (int)strlen(msyytext); +- msyystring_size += msyytext_len; ++ msyystring_size += msyyleng; + MS_LEXER_STRING_REALLOC(msyystring_buffer, msyystring_size, + msyystring_buffer_size); +- memcpy(msyystring_buffer + old_size, msyytext, msyytext_len + 1); ++ memcpy(msyystring_buffer + old_size, msyytext, msyyleng + 1); + } + + <INCLUDE>\"[^\"]*\"|\'[^\']*\' { + msyytext++; +- msyytext[strlen(msyytext)-1] = '\0'; ++ msyytext[msyyleng-1-1] = '\0'; + + if(include_stack_ptr >= MAX_INCLUDE_DEPTH) { + msSetError(MS_IOERR, "Includes nested to deeply.", "msyylex()"); +@@ -682,7 +681,7 @@ char path[MS_MAXPATHLEN]; + } + + <INITIAL,CONFIG_FILE>[a-z/\.][a-z0-9/\._\-\=]* { +- MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), ++ MS_LEXER_STRING_REALLOC(msyystring_buffer, msyyleng, + msyystring_buffer_size); + strcpy(msyystring_buffer, msyytext); + return(MS_STRING); +@@ -706,7 +705,7 @@ char path[MS_MAXPATHLEN]; + } + + <INITIAL,CONFIG_FILE>. { +- MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), ++ MS_LEXER_STRING_REALLOC(msyystring_buffer, msyyleng, + msyystring_buffer_size); + strcpy(msyystring_buffer, msyytext); + return(0); diff -Nru --exclude 9999-Update-maplexer.c.patch mapserver-8.0.0/debian/patches/0007-mapfile-parser-fix-double-free-when-included-file-do.patch mapserver-8.0.0/debian/patches/0007-mapfile-parser-fix-double-free-when-included-file-do.patch --- mapserver-8.0.0/debian/patches/0007-mapfile-parser-fix-double-free-when-included-file-do.patch 1970-01-01 01:00:00.000000000 +0100 +++ mapserver-8.0.0/debian/patches/0007-mapfile-parser-fix-double-free-when-included-file-do.patch 2026-03-23 15:02:59.000000000 +0100 @@ -0,0 +1,36 @@ +From: Even Rouault <[email protected]> +Date: Sat, 8 Apr 2023 13:18:50 +0200 +Subject: mapfile parser: fix double-free when included file doesn't exist + +Origin: https://github.com/MapServer/MapServer/commit/e3ca3cb2007c494d7dec8aec0e6443abd5ce62a2 +Bug: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=57788 +--- + maplexer.l | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/maplexer.l b/maplexer.l +index 7a67479c..bc37858 100644 +--- a/maplexer.l ++++ b/maplexer.l +@@ -655,10 +655,6 @@ char path[MS_MAXPATHLEN]; + return(-1); + } + +- include_stack[include_stack_ptr] = YY_CURRENT_BUFFER; /* save state */ +- include_lineno[include_stack_ptr] = msyylineno; +- include_stack_ptr++; +- + msyyin = fopen(msBuildPath(path, msyybasepath, msyytext), "r"); + if(!msyyin) { + msSetError(MS_IOERR, "Error opening included file \"%s\".", "msyylex()", msyytext); +@@ -666,6 +662,10 @@ char path[MS_MAXPATHLEN]; + return(-1); + } + ++ include_stack[include_stack_ptr] = YY_CURRENT_BUFFER; /* save state */ ++ include_lineno[include_stack_ptr] = msyylineno; ++ include_stack_ptr++; ++ + msyy_switch_to_buffer( msyy_create_buffer(msyyin, YY_BUF_SIZE) ); + msyylineno = 1; + diff -Nru --exclude 9999-Update-maplexer.c.patch mapserver-8.0.0/debian/patches/CVE-2025-59431.patch mapserver-8.0.0/debian/patches/CVE-2025-59431.patch --- mapserver-8.0.0/debian/patches/CVE-2025-59431.patch 1970-01-01 01:00:00.000000000 +0100 +++ mapserver-8.0.0/debian/patches/CVE-2025-59431.patch 2026-03-23 15:02:59.000000000 +0100 @@ -0,0 +1,255 @@ +From: Even Rouault <[email protected]> +Date: Thu, 18 Sep 2025 20:22:23 +0200 +Subject: Add missing column name escaping in FLTGetCommonExpression() + +and use msLayerEscapePropertyName() insead of msOGRGetQuotedItem() in +OGR backend + +Origin: https://github.com/MapServer/MapServer/commit/1c73acaa2d7a8b1d3955f076186e57fc8c06e0c6 +Bug: https://github.com/MapServer/MapServer/security/advisories/GHSA-256m-rx4h-r55w +Bug: https://github.com/MapServer/MapServer/pull/7349 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2025-59431 +--- + maplexer.l | 14 ++++++++------ + mapogcfiltercommon.cpp | 27 ++++++++++++++++++++++----- + mapogr.cpp | 25 ++++++++++++++----------- + mapserver.h | 1 + + mapstring.cpp | 21 +++++++++++++++++++++ + 5 files changed, 66 insertions(+), 22 deletions(-) + +diff --git a/maplexer.l b/maplexer.l +index bc37858..3653fea 100644 +--- a/maplexer.l ++++ b/maplexer.l +@@ -503,31 +503,33 @@ char path[MS_MAXPATHLEN]; + /* attribute binding - data cellsize */ + return(MS_TOKEN_BINDING_DATA_CELLSIZE); + } +-<EXPRESSION_STRING>\[[^\]]*\] { ++<EXPRESSION_STRING>\[(?:\]\]|[^\]])*\] { + /* attribute binding - numeric (no quotes) */ + msyytext++; + msyytext[msyyleng-1-1] = '\0'; + MS_LEXER_STRING_REALLOC(msyystring_buffer, msyyleng, + msyystring_buffer_size); + strcpy(msyystring_buffer, msyytext); ++ msStringUnescape(msyystring_buffer, ']'); + return(MS_TOKEN_BINDING_DOUBLE); + } +-<EXPRESSION_STRING>\"\[[^\"]*\]\"|\'\[[^\']*\]\' { ++<EXPRESSION_STRING>\"\[(?:\"\"|[^\"])*\]\"|\'\[(?:\'\'|[^\'])*\]\' { + /* attribute binding - string (single or double quotes) */ +- msyytext+=2; +- msyytext[msyyleng-2-2] = '\0'; ++ msyytext[msyyleng-2] = '\0'; + MS_LEXER_STRING_REALLOC(msyystring_buffer, msyyleng, + msyystring_buffer_size); +- strcpy(msyystring_buffer, msyytext); ++ strcpy(msyystring_buffer, msyytext + 2); ++ msStringUnescape(msyystring_buffer, msyytext[0]); + return(MS_TOKEN_BINDING_STRING); + } +-<EXPRESSION_STRING>\`\[[^\`]*\]\` { ++<EXPRESSION_STRING>\`\[(?:\`\`|[^\`])*\]\` { + /* attribute binding - time */ + msyytext+=2; + msyytext[msyyleng-2-2] = '\0'; + MS_LEXER_STRING_REALLOC(msyystring_buffer, msyyleng, + msyystring_buffer_size); + strcpy(msyystring_buffer, msyytext); ++ msStringUnescape(msyystring_buffer, '`'); + return(MS_TOKEN_BINDING_TIME); + } + +diff --git a/mapogcfiltercommon.cpp b/mapogcfiltercommon.cpp +index f73d47b..c85ab8d 100644 +--- a/mapogcfiltercommon.cpp ++++ b/mapogcfiltercommon.cpp +@@ -34,6 +34,20 @@ + + #include <string> + ++static std::string FLTEscapePropertyName(const char *pszStr, ++ char chEscapeChar) { ++ std::string ret; ++ for (; *pszStr; ++pszStr) { ++ if (*pszStr == chEscapeChar) { ++ ret += chEscapeChar; ++ ret += chEscapeChar; ++ } else { ++ ret += *pszStr; ++ } ++ } ++ return ret; ++} ++ + static std::string FLTGetIsLikeComparisonCommonExpression(FilterEncodingNode *psFilterNode) + { + /* From http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap09.html#tag_09_04 */ +@@ -58,7 +72,7 @@ static std::string FLTGetIsLikeComparisonCommonExpression(FilterEncodingNode *ps + std::string expr("(\"["); + + /* attribute */ +- expr += psFilterNode->psLeftNode->pszValue; ++ expr += FLTEscapePropertyName(psFilterNode->psLeftNode->pszValue, '"'); + + /* #3521 */ + if (bCaseInsensitive ) +@@ -171,7 +185,8 @@ static std::string FLTGetIsBetweenComparisonCommonExpresssion(FilterEncodingNode + else + expr += "(["; + +- expr += psFilterNode->psLeftNode->pszValue; ++ expr += FLTEscapePropertyName(psFilterNode->psLeftNode->pszValue, ++ bString ? '"' : ']'); + + if (bString) + expr += "]\" "; +@@ -264,7 +279,9 @@ std::string FLTGetBinaryComparisonCommonExpression(FilterEncodingNode *psFilterN + expr = "(\"["; + else + expr = "(["; +- expr += psFilterNode->psLeftNode->pszValue; ++ ++ expr += FLTEscapePropertyName(psFilterNode->psLeftNode->pszValue, ++ bString ? '"' : ']'); + + if (bString) + expr += "]\" "; +@@ -542,13 +559,13 @@ static std::string FLTGetFeatureIdCommonExpression(FilterEncodingNode *psFilterN + + if (bString) { + expr += "(\"["; +- expr += pszAttribute; ++ expr += FLTEscapePropertyName(pszAttribute, '"'); + expr += "]\" == \""; + expr += pszId; + expr += "\")"; + } else { + expr += "(["; +- expr += pszAttribute; ++ expr += FLTEscapePropertyName(pszAttribute, ']'); + expr += "] == "; + expr += pszId; + expr += ")"; +diff --git a/mapogr.cpp b/mapogr.cpp +index 1b66219..e7b7833 100644 +--- a/mapogr.cpp ++++ b/mapogr.cpp +@@ -2042,7 +2042,7 @@ char *msOGRGetToken(layerObj* layer, tokenListNodeObjPtr *node) { + break; + } + case MS_TOKEN_BINDING_INTEGER: { +- char *stresc = msOGRGetQuotedItem(layer, n->tokenval.bindval.item); ++ char *stresc = msLayerEscapePropertyName(layer, n->tokenval.bindval.item); + nOutSize = strlen(stresc)+ 20; + out = (char *)msSmallMalloc(nOutSize); + +@@ -2056,17 +2056,17 @@ char *msOGRGetToken(layerObj* layer, tokenListNodeObjPtr *node) { + EQUAL(type, "Long") || + EQUAL(type, "Real")) ) + { +- snprintf(out, nOutSize, "%s", stresc); ++ snprintf(out, nOutSize, "\"%s\"", stresc); + } + else + { +- snprintf(out, nOutSize, "CAST(%s AS integer)", stresc); ++ snprintf(out, nOutSize, "CAST(\"%s\" AS integer)", stresc); + } + msFree(stresc); + break; + } + case MS_TOKEN_BINDING_STRING: { +- char *stresc = msOGRGetQuotedItem(layer, n->tokenval.bindval.item); ++ char *stresc = msLayerEscapePropertyName(layer, n->tokenval.bindval.item); + nOutSize = strlen(stresc) + 30; + out = (char *)msSmallMalloc(nOutSize); + +@@ -2078,26 +2078,26 @@ char *msOGRGetToken(layerObj* layer, tokenListNodeObjPtr *node) { + // prevent using database indexes, such as for SQlite + if( type != NULL && EQUAL(type, "Character") ) + { +- snprintf(out, nOutSize, "%s", stresc); ++ snprintf(out, nOutSize, "\"%s\"", stresc); + } + else + { +- snprintf(out, nOutSize, "CAST(%s AS text)", stresc); ++ snprintf(out, nOutSize, "CAST(\"%s\" AS text)", stresc); + } + msFree(stresc); + break; + } + case MS_TOKEN_BINDING_TIME: { + // won't get here unless col is parsed as time and they are not +- char *stresc = msOGRGetQuotedItem(layer, n->tokenval.bindval.item); ++ char *stresc = msLayerEscapePropertyName(layer, n->tokenval.bindval.item); + nOutSize = strlen(stresc)+ 10; + out = (char *)msSmallMalloc(nOutSize); +- snprintf(out, nOutSize, "%s", stresc); ++ snprintf(out, nOutSize, "\"%s\"", stresc); + msFree(stresc); + break; + } + case MS_TOKEN_BINDING_SHAPE: { +- char *stresc = msOGRGetQuotedItem(layer, OGR_L_GetGeometryColumn(info->hLayer)); // which geom field?? ++ char *stresc = msLayerEscapePropertyName(layer, OGR_L_GetGeometryColumn(info->hLayer)); // which geom field?? + nOutSize = strlen(stresc)+ 10; + out = (char *)msSmallMalloc(nOutSize); + snprintf(out, nOutSize, "%s", stresc); +@@ -3783,8 +3783,11 @@ static std::string msOGRTranslatePartialInternal(layerObj* layer, + case MS_TOKEN_BINDING_STRING: + case MS_TOKEN_BINDING_TIME: + { +- char* pszTmp = msOGRGetQuotedItem(layer, expr->m_osVal.c_str()); +- std::string osRet(pszTmp); ++ char *pszTmp = msLayerEscapePropertyName(layer, expr->m_osVal.c_str()); ++ std::string osRet; ++ osRet += '"'; ++ osRet += pszTmp; ++ osRet += '"'; + msFree(pszTmp); + return osRet; + } +diff --git a/mapserver.h b/mapserver.h +index e811735..6c2dde7 100755 +--- a/mapserver.h ++++ b/mapserver.h +@@ -2358,6 +2358,7 @@ void msPopulateTextSymbolForLabelAndString(textSymbolObj *ts, labelObj *l, char + MS_DLL_EXPORT int msUTF8ToUniChar(const char *str, unsigned int *chPtr); /* maptclutf.c */ + MS_DLL_EXPORT char* msStringEscape( const char * pszString ); + MS_DLL_EXPORT int msStringInArray( const char * pszString, char **array, int numelements); ++ void msStringUnescape(char *pszString, char chEscapeChar); + + typedef struct msStringBuffer msStringBuffer; + MS_DLL_EXPORT msStringBuffer* msStringBufferAlloc(void); +diff --git a/mapstring.cpp b/mapstring.cpp +index 64a7ca8..f4d339a 100644 +--- a/mapstring.cpp ++++ b/mapstring.cpp +@@ -2509,3 +2509,24 @@ int msStringBufferAppend(msStringBuffer* sb, const char* pszAppendedString) + sb->length += nAppendLen; + return MS_SUCCESS; + } ++ ++/************************************************************************/ ++/* msStringUnescape() */ ++/************************************************************************/ ++ ++/** Modify in place pszString such that a sequence of two consecutive ++ * chEscapeChar is replaced by a single one. ++ * Does the reverse of FLTEscapePropertyName() ++ */ ++void msStringUnescape(char *pszString, char chEscapeChar) { ++ char *pszDest = pszString; ++ for (; *pszString; ++pszString, ++pszDest) { ++ if (pszString[0] == chEscapeChar && pszString[1] == chEscapeChar) { ++ *pszDest = chEscapeChar; ++ ++pszString; ++ } else { ++ *pszDest = *pszString; ++ } ++ } ++ *pszDest = 0; ++} diff -Nru --exclude 9999-Update-maplexer.c.patch mapserver-8.0.0/debian/patches/series mapserver-8.0.0/debian/patches/series --- mapserver-8.0.0/debian/patches/series 2022-11-03 19:47:05.000000000 +0100 +++ mapserver-8.0.0/debian/patches/series 2026-03-23 15:02:59.000000000 +0100 @@ -2,3 +2,8 @@ java-hardening.patch interpreter-path.path setuptools.patch +0005-maplexer.l-avoid-non-null-terminated-msyystring_buff.patch +0006-maplexer.l-fix-heap-buffer-overflow-issues-with-NUL-.patch +0007-mapfile-parser-fix-double-free-when-included-file-do.patch +CVE-2025-59431.patch +9999-Update-maplexer.c.patch diff -Nru --exclude 9999-Update-maplexer.c.patch mapserver-8.0.0/debian/salsa-ci.yml mapserver-8.0.0/debian/salsa-ci.yml --- mapserver-8.0.0/debian/salsa-ci.yml 1970-01-01 01:00:00.000000000 +0100 +++ mapserver-8.0.0/debian/salsa-ci.yml 2026-03-23 15:02:59.000000000 +0100 @@ -0,0 +1,9 @@ +--- +include: + - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/recipes/debian.yml + +variables: + RELEASE: 'bookworm' + SALSA_CI_DISABLE_LINTIAN: 1 + SALSA_CI_DISABLE_REPROTEST: 1 + SALSA_CI_DISABLE_BLHC: 1
9999-Update-maplexer.c.patch.gz
Description: application/gzip
signature.asc
Description: PGP signature

