diff -Nru mapserver-7.6.2/ci/travis/after_success.sh mapserver-7.6.4/ci/travis/after_success.sh --- mapserver-7.6.2/ci/travis/after_success.sh 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/ci/travis/after_success.sh 2021-07-12 20:16:21.000000000 +0000 @@ -1,11 +1,11 @@ #!/bin/sh set -eu -if [ "$BUILD_NAME" != "PHP_7.2_WITH_ASAN" ]; then - # Only run coverage when it is safe to do so (not on pull requests), and only on master branch +if [ "$BUILD_NAME" != "PHP_7.3_WITH_ASAN" ]; then + # Only run coverage when it is safe to do so (not on pull requests), and only on main branch echo "$TRAVIS_SECURE_ENV_VARS" echo "$TRAVIS_BRANCH" - sh -c 'if test "$TRAVIS_SECURE_ENV_VARS" = "true" -a "$TRAVIS_BRANCH" = "master"; then echo "run coverage"; ./run_code_coverage_upload.sh; fi' + sh -c 'if test "$TRAVIS_SECURE_ENV_VARS" = "true" -a "$TRAVIS_BRANCH" = "main"; then echo "run coverage"; ./run_code_coverage_upload.sh; fi' ln -s ../../../mapparser.y build/CMakeFiles/mapserver.dir/ ln -s ../../../maplexer.l build/CMakeFiles/mapserver.dir/ coveralls --exclude renderers --exclude mapscript --exclude apache --exclude build/mapscript/mapscriptJAVA_wrap.c --exclude build/mapscript/mapscriptPYTHON_wrap.c --exclude shp2img.c --exclude legend.c --exclude scalebar.c --exclude msencrypt.c --exclude sortshp.c --exclude shptreevis.c --exclude shptree.c --exclude testexpr.c --exclude sym2img.c --exclude testcopy.c --exclude shptreetst.c --exclude tile4ms.c --exclude proj --exclude swig-3.0.12 --extension .c --extension .cpp diff -Nru mapserver-7.6.2/ci/travis/before_install.sh mapserver-7.6.4/ci/travis/before_install.sh --- mapserver-7.6.2/ci/travis/before_install.sh 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/ci/travis/before_install.sh 2021-07-12 20:16:21.000000000 +0000 @@ -1,31 +1,38 @@ #!/bin/sh set -eu -sudo mv /etc/apt/sources.list.d/pgdg* /tmp -dpkg -l | grep postgresql -dpkg -l | grep postgis -sudo apt-get remove postgresql* -sudo add-apt-repository -y ppa:ubuntugis/ppa -sudo add-apt-repository -y ppa:ubuntugis/ubuntugis-testing +# Remove pre-installed things in Travis image +if ls /etc/apt/sources.list.d/pgdg* 2>/dev/null >/dev/null; then sudo mv /etc/apt/sources.list.d/pgdg* /tmp; fi +dpkg -l | grep postgresql || /bin/true +dpkg -l | grep postgis || /bin/true +sudo apt-get remove --purge postgresql* libpq-dev libpq5 || /bin/true + +sudo add-apt-repository -y ppa:ubuntugis/ubuntugis-unstable sudo apt-get update -sudo apt-get install --allow-unauthenticated protobuf-c-compiler libprotobuf-c0-dev bison flex python-lxml libfribidi-dev cmake librsvg2-dev colordiff libpq-dev libpng12-dev libjpeg-dev libgif-dev libgeos-dev libgd2-xpm-dev libfreetype6-dev libfcgi-dev libcurl4-gnutls-dev libcairo2-dev libgdal1-dev libproj-dev libxml2-dev python-dev libexempi-dev lcov lftp postgis libharfbuzz-dev gdal-bin ccache curl pyflakes -sudo apt-get install --allow-unauthenticated libmono-system-drawing4.0-cil mono-mcs -sudo apt-get install --allow-unauthenticated php5-dev || sudo apt-get install --allow-unauthenticated php7-dev -sudo apt-get install --allow-unauthenticated libperl-dev -sudo pip install cpp-coveralls +sudo apt-get install -y --allow-unauthenticated protobuf-c-compiler libprotobuf-c0-dev bison flex libfribidi-dev cmake librsvg2-dev colordiff libpq-dev libpng-dev libjpeg-dev libgif-dev libgeos-dev libfreetype6-dev libfcgi-dev libcurl4-gnutls-dev libcairo2-dev libgdal-dev libproj-dev libxml2-dev libexempi-dev lcov lftp postgis libharfbuzz-dev gdal-bin ccache curl postgresql-server-dev-10 postgresql-10-postgis-3 postgresql-10-postgis-3-scripts swig g++ +# following are already installed on Travis CI +#sudo apt-get install --allow-unauthenticated php-dev python-dev python3-dev +sudo apt-get install -y --allow-unauthenticated libmono-system-drawing4.0-cil mono-mcs +sudo apt-get install -y --allow-unauthenticated libperl-dev +sudo apt-get install -y --allow-unauthenticated openjdk-8-jdk + +pip install cpp-coveralls pyflakes lxml sudo pip install -U -r msautotest/requirements.txt -# install swig 3.0.12 (defaults to 2.0.11 on trusty) -wget http://prdownloads.sourceforge.net/swig/swig-3.0.12.tar.gz + export CC="ccache gcc" export CXX="ccache g++" -tar xf swig-3.0.12.tar.gz -cd swig-3.0.12 && ./configure --prefix=/usr && make -j2 && sudo make install -swig -version -cd .. + +sudo sed -i 's/md5/trust/' /etc/postgresql/10/main/pg_hba.conf +sudo sed -i 's/peer/trust/' /etc/postgresql/10/main/pg_hba.conf +sudo service postgresql restart 10 + cd msautotest -pyflakes . +python -m pyflakes . ./create_postgis_test_data.sh -python -m SimpleHTTPServer &> /dev/null & + +# py3 +python -m http.server &> /dev/null & + cd .. touch maplexer.l touch mapparser.y diff -Nru mapserver-7.6.2/ci/travis/script.sh mapserver-7.6.4/ci/travis/script.sh --- mapserver-7.6.2/ci/travis/script.sh 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/ci/travis/script.sh 2021-07-12 20:16:21.000000000 +0000 @@ -1,13 +1,13 @@ #!/bin/sh set -eu -if [ "$BUILD_NAME" = "PHP_7.2_WITH_ASAN" ]; then - export CC="ccache clang" - export CXX="ccache clang++" -else +#if [ "$BUILD_NAME" = "PHP_7.3_WITH_ASAN" ]; then +# export CC="ccache clang" +# export CXX="ccache clang++" +#else export CC="ccache gcc" export CXX="ccache g++" -fi +#fi curl http://download.osgeo.org/proj/proj-6.1.1.tar.gz > proj-6.1.1.tar.gz tar xzf proj-6.1.1.tar.gz @@ -16,7 +16,7 @@ (cd proj; CFLAGS='-O2 -DPROJ_RENAME_SYMBOLS' CXXFLAGS='-O2 -DPROJ_RENAME_SYMBOLS' ./configure --disable-static --prefix=/usr/local && CCACHE_CPP2=yes make -j2 && sudo make -j3 install) sudo rm -f /usr/include/proj_api.h -if [ "$BUILD_NAME" = "PHP_7.2_WITH_ASAN" ]; then +if [ "$BUILD_NAME" = "PHP_7.3_WITH_ASAN" ]; then # Force use of PROJ 4 API sudo rm /usr/local/include/proj.h # -DNDEBUG to avoid issues with cairo cleanup @@ -24,7 +24,7 @@ export AUTOTEST_OPTS="--strict --run_under_asan" # Only run tests that only involve mapserv/shp2img binaries. mspython, etc would require LD_PREOLOAD'ing the asan shared object make -j4 asan_compatible_tests -elif [ "$BUILD_NAME" = "PHP_7.3_WITH_PROJ6" ]; then +elif [ "$BUILD_NAME" = "PHP_7.4_WITH_PROJ6" ]; then # Avoid any use of PROJ 4 API sudo rm -f /usr/include/proj_api.h make cmakebuild MFLAGS="-j2" CMAKE_C_FLAGS="-O2 -DPROJ_RENAME_SYMBOLS" CMAKE_CXX_FLAGS="-O2 -DPROJ_RENAME_SYMBOLS" EXTRA_CMAKEFLAGS="-DPROJ_INCLUDE_DIR=/usr/local/include -DPROJ_LIBRARY=/usr/local/lib/libproj.so.15" diff -Nru mapserver-7.6.2/cmake/FindProj.cmake mapserver-7.6.4/cmake/FindProj.cmake --- mapserver-7.6.2/cmake/FindProj.cmake 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/cmake/FindProj.cmake 2021-07-12 20:16:21.000000000 +0000 @@ -6,7 +6,7 @@ # PROJ_LIBRARY -FIND_PATH(PROJ_INCLUDE_DIR proj_api.h) +FIND_PATH(PROJ_INCLUDE_DIR NAMES proj.h proj_api.h) FIND_LIBRARY(PROJ_LIBRARY NAMES proj proj_i) diff -Nru mapserver-7.6.2/CMakeLists.txt mapserver-7.6.4/CMakeLists.txt --- mapserver-7.6.2/CMakeLists.txt 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/CMakeLists.txt 2021-07-12 20:16:21.000000000 +0000 @@ -17,7 +17,7 @@ set (MapServer_VERSION_MAJOR 7) set (MapServer_VERSION_MINOR 6) -set (MapServer_VERSION_REVISION 2) +set (MapServer_VERSION_REVISION 4) set (MapServer_VERSION_SUFFIX "") # Set C++ version diff -Nru mapserver-7.6.2/CONTRIBUTING.md mapserver-7.6.4/CONTRIBUTING.md --- mapserver-7.6.2/CONTRIBUTING.md 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/CONTRIBUTING.md 2021-07-12 20:16:21.000000000 +0000 @@ -5,28 +5,33 @@ ## Bugs and Help -GitHub issues should only be created to log bugs. For general help and support the MapServer [mailing lists](http://mapserver.org/community/lists.html) +GitHub issues should only be created to log bugs. For general help and support the MapServer [mailing lists](https://mapserver.org/community/lists.html) should be used. If you are unsure if you have discovered a bug, or may need help with configuring MapServer please -post to the [mapserver-users list](http://lists.osgeo.org/mailman/listinfo/mapserver-users). There is also -a [MapServer FAQ](http://www.mapserver.org/faq.html) which may have a solution to your problem. +post to the [mapserver-users list](https://lists.osgeo.org/mailman/listinfo/mapserver-users). There is also +a [MapServer FAQ](https://mapserver.org/faq.html) which may have a solution to your problem. -If you have discovered a bug, please refer to the [Bug Submission page](http://mapserver.org/development/bugs.html) for +If you have discovered a bug, please refer to the [Bug Submission page](https://mapserver.org/development/bugs.html) for guidelines on creating an issue on GitHub. Please also search the existing issues to see if the bug has already been reported, and add any further details to the existing issue. -For professional support please see the [MapServer Service Providers page](http://mapserver.org/community/service_providers.html). +For professional support please see the [MapServer Service Providers page](https://mapserver.org/community/service_providers.html). ## Development -A separate [mapserver-dev mailing list](http://lists.osgeo.org/mailman/listinfo/mapserver-dev) is available for developers -working on the MapServer code. - -Details on using GitHub can be found on the [MapServer GitHub page](http://mapserver.org/development/git.html) +A separate [mapserver-dev mailing list](https://lists.osgeo.org/mailman/listinfo/mapserver-dev) is available for developers +working on the MapServer code. Send a short message there to introduce yourself +to the community, and mention what you are interested in working on. + +Details on using GitHub can be found on the [MapServer GitHub page](https://mapserver.org/development/git.html). + +Request for Comments (RFCs), where upcoming major changes to the source +code are proposed, and a description of the various software tests & release +plans, can be found on the [MapServer Development page](https://mapserver.org/development/). Additional developer notes can be found in the [MapServer wiki](https://github.com/mapserver/mapserver/wiki#developer-notes), including coding style and guidelines, memory management, and working with Git. ## Documentation -The MapServer documentation is stored in a [separate repository](https://github.com/mapserver/docs). Please submit any documentation -issues or changes there. See the [Documentation Development Guide](http://mapserver.org/development/documentation.html) for further details. +The MapServer documentation is stored in a [separate repository](https://github.com/MapServer/MapServer-documentation). Please submit any documentation +issues or changes there. See the [Documentation Development Guide](https://mapserver.org/development/documentation.html) for further details. diff -Nru mapserver-7.6.2/debian/changelog mapserver-7.6.4/debian/changelog --- mapserver-7.6.2/debian/changelog 2021-01-22 14:00:00.000000000 +0000 +++ mapserver-7.6.4/debian/changelog 2021-01-22 14:00:00.000000000 +0000 @@ -1,3 +1,9 @@ +mapserver (7.6.4-0~bionic0) bionic; urgency=medium + + * New upstream release. + + -- Angelos Tzotsos Fri, 22 Jan 2021 16:00:00 +0200 + mapserver (7.6.2-1~bionic1) bionic; urgency=medium * patch 6216 added: PROJ >= 6 reprojection: fix use of freed memory when input and output projections are the same. diff -Nru mapserver-7.6.2/debian/patches/6216.patch mapserver-7.6.4/debian/patches/6216.patch --- mapserver-7.6.2/debian/patches/6216.patch 2021-01-22 13:58:05.000000000 +0000 +++ mapserver-7.6.4/debian/patches/6216.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -From 306164a5d8cb0abf0abaa96d026193a2da7a9ca6 Mon Sep 17 00:00:00 2001 -From: Even Rouault -Date: Fri, 22 Jan 2021 12:31:08 +0100 -Subject: [PATCH] PROJ >= 6 reprojection: fix use of freed memory when input - and output projections are the same - ---- - mapproject.c | 16 ++++++++++++++-- - 1 file changed, 14 insertions(+), 2 deletions(-) - -diff --git a/mapproject.c b/mapproject.c -index e432ae1ef..1ccc50592 100644 ---- a/mapproject.c -+++ b/mapproject.c -@@ -119,11 +119,23 @@ static int msProjectHasLonWrapOrOver(projectionObj *in) { - /* Return to be freed with proj_destroy() if *pbFreePJ = TRUE */ - static PJ* createNormalizedPJ(projectionObj *in, projectionObj *out, int* pbFreePJ) - { -+ if( in->proj == out->proj ) -+ { -+ /* Special case to avoid out_str below to cause in_str to become invalid */ -+ *pbFreePJ = TRUE; -+#if PROJ_VERSION_MAJOR == 6 && PROJ_VERSION_MINOR == 0 -+ /* 6.0 didn't support proj=noop */ -+ return proj_create(in->proj_ctx->proj_ctx, "+proj=affine"); -+#else -+ return proj_create(in->proj_ctx->proj_ctx, "+proj=noop"); -+#endif -+ } -+ - const char* const wkt_options[] = { "MULTILINE=NO", NULL }; -- const char* in_str = (in && msProjectHasLonWrapOrOver(in)) ? -+ const char* in_str = msProjectHasLonWrapOrOver(in) ? - proj_as_proj_string(in->proj_ctx->proj_ctx, in->proj, PJ_PROJ_4, NULL) : - proj_as_wkt(in->proj_ctx->proj_ctx, in->proj, PJ_WKT2_2018, wkt_options); -- const char* out_str = (out && msProjectHasLonWrapOrOver(out)) ? -+ const char* out_str = msProjectHasLonWrapOrOver(out) ? - proj_as_proj_string(out->proj_ctx->proj_ctx, out->proj, PJ_PROJ_4, NULL) : - proj_as_wkt(out->proj_ctx->proj_ctx, out->proj, PJ_WKT2_2018, wkt_options); - PJ* pj_raw; diff -Nru mapserver-7.6.2/debian/patches/series mapserver-7.6.4/debian/patches/series --- mapserver-7.6.2/debian/patches/series 2021-01-22 13:59:42.000000000 +0000 +++ mapserver-7.6.4/debian/patches/series 2021-01-22 14:00:00.000000000 +0000 @@ -1,4 +1,3 @@ perl-mapscript-install.patch java-hardening.patch interpreter-path.path -6216.patch diff -Nru mapserver-7.6.2/fontcache.c mapserver-7.6.4/fontcache.c --- mapserver-7.6.2/fontcache.c 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/fontcache.c 2021-07-12 20:16:21.000000000 +0000 @@ -287,8 +287,14 @@ FT_Set_Pixel_Sizes(face->face,0,MS_NINT(size * 96/72.0)); } error = FT_Load_Glyph(face->face,key.codepoint,FT_LOAD_DEFAULT|FT_LOAD_NO_BITMAP|FT_LOAD_NO_HINTING|FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); + if (error) { + msDebug("Unable to load glyph %u for font \"%s\". Using ? as fallback.\n", key.codepoint, face->font); + // If we can't find a glyph then try to fallback to a question mark. + unsigned int fallbackCodepoint = msGetGlyphIndex(face, 0x3F); + error = FT_Load_Glyph(face->face,fallbackCodepoint,FT_LOAD_DEFAULT|FT_LOAD_NO_BITMAP|FT_LOAD_NO_HINTING|FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); + } if(error) { - msSetError(MS_MISCERR, "unable to load glyph %ud for font \"%s\"", "msGetGlyphByIndex()",key.codepoint, face->font); + msSetError(MS_MISCERR, "unable to load glyph %u for font \"%s\"", "msGetGlyphByIndex()",key.codepoint, face->font); free(gc); #ifdef USE_THREAD if (use_global_ft_cache) @@ -335,8 +341,14 @@ pen.x = pen.y = 0; FT_Set_Transform(face->face, &matrix, &pen); error = FT_Load_Glyph(face->face,glyph->key.codepoint,FT_LOAD_DEFAULT|FT_LOAD_NO_BITMAP/*|FT_LOAD_IGNORE_TRANSFORM*/|FT_LOAD_NO_HINTING|FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); + if (error) { + msDebug("Unable to load glyph %u for font \"%s\". Using ? as fallback.\n", glyph->key.codepoint, face->font); + // If we can't find a glyph then try to fallback to a question mark. + unsigned int fallbackCodepoint = msGetGlyphIndex(face, 0x3F); + error = FT_Load_Glyph(face->face,fallbackCodepoint,FT_LOAD_DEFAULT|FT_LOAD_NO_BITMAP/*|FT_LOAD_IGNORE_TRANSFORM*/|FT_LOAD_NO_HINTING|FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); + } if(error) { - msSetError(MS_MISCERR, "unable to load glyph %ud for font \"%s\"", "msGetGlyphByIndex()",glyph->key.codepoint, face->font); + msSetError(MS_MISCERR, "unable to load glyph %u for font \"%s\"", "msGetGlyphOutline()",glyph->key.codepoint, face->font); #ifdef USE_THREAD if (use_global_ft_cache) msReleaseLock(TLOCK_TTF); diff -Nru mapserver-7.6.2/HISTORY.TXT mapserver-7.6.4/HISTORY.TXT --- mapserver-7.6.2/HISTORY.TXT 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/HISTORY.TXT 2021-07-12 20:16:21.000000000 +0000 @@ -10,7 +10,29 @@ For a complete change history, please see the Git log comments. For more details about recent point releases, please see the online changelog at: -http://mapserver.org/development/changelog/ +https://mapserver.org/development/changelog/ + +7.6.4 release (2021-07-12) +-------------------------- + +- improved performance of GPKG and SpatiaLite queries (#6361) + +- WFS: fix paging with GPKG/Spatialite datasources and non-point geometries (#6325) + +- PostGIS: use ST_Intersects instead of && for bounding box (#6348) + +see detailed changelog for other fixes + +7.6.3 release (2021-04-30) +------------------------- + +- fix security flaw for processing the MAP parameter (#6313) + +- fix code defects through Coverity Scan warnings (#6307) + +- add support for PROJ 8 (#6249) + +see detailed changelog for other fixes 7.6.2 release (2020-12-07) ------------------------- diff -Nru mapserver-7.6.2/mapcontext.c mapserver-7.6.4/mapcontext.c --- mapserver-7.6.2/mapcontext.c 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/mapcontext.c 2021-07-12 20:16:21.000000000 +0000 @@ -811,7 +811,6 @@ int msLoadMapContextLayer(mapObj *map, CPLXMLNode *psLayer, int nVersion, char *filename, int unique_layer_names) { - char *pszProj=NULL; char *pszValue; const char *pszHash; char *pszName=NULL; @@ -970,7 +969,7 @@ pszHash = msLookupHashTable(&(layer->metadata), "wms_srs"); if(((pszHash == NULL) || (strcasecmp(pszHash, "") == 0)) && map->projection.numargs != 0) { - pszProj = map->projection.args[map->projection.numargs-1]; + char* pszProj = map->projection.args[map->projection.numargs-1]; if(pszProj != NULL) { if(strncasecmp(pszProj, "AUTO:", 5) == 0) { @@ -987,6 +986,7 @@ pszProj); } } + msFree(pszProj); } } diff -Nru mapserver-7.6.2/mapcpl.c mapserver-7.6.4/mapcpl.c --- mapserver-7.6.2/mapcpl.c 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/mapcpl.c 2021-07-12 20:16:21.000000000 +0000 @@ -195,6 +195,8 @@ return NULL; } + /* We accept leakage of pLibrary */ + /* coverity[leaked_storage] */ return( pSymbol ); } diff -Nru mapserver-7.6.2/mapdraw.c mapserver-7.6.4/mapdraw.c --- mapserver-7.6.2/mapdraw.c 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/mapdraw.c 2021-07-12 20:16:21.000000000 +0000 @@ -542,6 +542,13 @@ if(map->legend.status == MS_EMBED && map->legend.postlabelcache) if(UNLIKELY(MS_FAILURE == msEmbedLegend(map, image))) { msFreeImage( image ); +#if defined(USE_WMS_LYR) || defined(USE_WFS_LYR) + /* Cleanup WMS/WFS Request stuff */ + if (pasOWSReqInfo) { + msHTTPFreeRequestObj(pasOWSReqInfo, numOWSRequests); + msFree(pasOWSReqInfo); + } +#endif return NULL; } @@ -552,7 +559,6 @@ if(map->gt.need_geotransform) msMapRestoreRealExtent(map); - if(MS_SUCCESS != msEmbedScalebar(map, image)) { msFreeImage( image ); #if defined(USE_WMS_LYR) || defined(USE_WFS_LYR) @@ -1301,7 +1307,7 @@ { int i, status; char annotate=MS_TRUE, cache=MS_FALSE; - int drawmode = MS_DRAWMODE_FEATURES|MS_DRAWMODE_QUERY; + int drawmode = MS_DRAWMODE_FEATURES; shapeObj shape; int maxnumstyles=1; @@ -1350,13 +1356,16 @@ /* if MS_HILITE, alter the one style (always at least 1 style), and set a MINDISTANCE for the labelObj to avoid duplicates */ if(map->querymap.style == MS_HILITE) { + + drawmode |= MS_DRAWMODE_QUERY; + if (layer->numclasses > 0) { colorbuffer = (colorObj*)msSmallMalloc(layer->numclasses*sizeof(colorObj)); mindistancebuffer = (int*)msSmallMalloc(layer->numclasses*sizeof(int)); } for(i=0; inumclasses; i++) { - if(layer->type == MS_LAYER_POLYGON) { /* alter BOTTOM style since that's almost always the fill */ + if(layer->type == MS_LAYER_POLYGON && layer->class[i]->numstyles > 0) { /* alter BOTTOM style since that's almost always the fill */ if (layer->class[i]->styles == NULL) { msSetError(MS_MISCERR, "Don't know how to draw class %s of layer %s without a style definition.", "msDrawQueryLayer()", layer->class[i]->name, layer->name); msFree(colorbuffer); @@ -1515,7 +1524,7 @@ /* if MS_HILITE, restore color and mindistance values */ if(map->querymap.style == MS_HILITE) { for(i=0; inumclasses; i++) { - if(layer->type == MS_LAYER_POLYGON) { + if(layer->type == MS_LAYER_POLYGON && layer->class[i]->numstyles > 0) { if(MS_VALID_COLOR(layer->class[i]->styles[0]->color)) layer->class[i]->styles[0]->color = colorbuffer[i]; else if(MS_VALID_COLOR(layer->class[i]->styles[0]->outlinecolor)) @@ -1947,7 +1956,7 @@ { int c = shape->classindex; - pointObj annopnt; + pointObj annopnt = {0,0,0,0}; // initialize int i; if(MS_DRAW_FEATURES(drawmode)) { @@ -2831,7 +2840,7 @@ double aox,aoy; symbolObj *symbol = map->symbolset.symbol[style->symbol]; if(msGetMarkerSize(map, style, &sx, &sy, ts->scalefactor) != MS_SUCCESS) - return MS_FALSE; + return -1; /* real error, different from MS_FALSE, return -1 so we can trap it */ if(style->angle) { pointObj *point = poly->poly->point; point[0].x = sx / 2.0; @@ -3119,6 +3128,7 @@ break; /* the marker collided, break from multi-label loop */ } } + if(have_label_marker == -1) return MS_FAILURE; /* error occured (symbol not found, etc...) */ if(textSymbolPtr->annotext) { /* diff -Nru mapserver-7.6.2/mapfile.c mapserver-7.6.4/mapfile.c --- mapserver-7.6.2/mapfile.c 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/mapfile.c 2021-07-12 20:16:21.000000000 +0000 @@ -97,6 +97,16 @@ return(MS_FAILURE); } +int msIsValidRegex(const char* e) { + ms_regex_t re; + if(ms_regcomp(&re, e, MS_REG_EXTENDED|MS_REG_NOSUB) != 0) { + msSetError(MS_REGEXERR, "Failed to compile expression (%s).", "msEvalRegex()", e); + return(MS_FALSE); + } + ms_regfree(&re); + return MS_TRUE; +} + int msEvalRegex(const char *e, const char *s) { ms_regex_t re; @@ -117,6 +127,26 @@ return(MS_TRUE); } +int msCaseEvalRegex(const char *e, const char *s) +{ + ms_regex_t re; + + if(!e || !s) return(MS_FALSE); + + if(ms_regcomp(&re, e, MS_REG_EXTENDED|MS_REG_ICASE|MS_REG_NOSUB) != 0) { + msSetError(MS_REGEXERR, "Failed to compile expression (%s).", "msEvalRegex()", e); + return(MS_FALSE); + } + + if(ms_regexec(&re, s, 0, NULL, 0) != 0) { /* no match */ + ms_regfree(&re); + return(MS_FALSE); + } + ms_regfree(&re); + + return(MS_TRUE); +} + #ifdef USE_MSFREE void msFree(void *p) { @@ -1933,12 +1963,8 @@ void msInitExpression(expressionObj *exp) { + memset(exp, 0, sizeof(*exp)); exp->type = MS_STRING; - exp->string = NULL; - exp->native_string = NULL; - exp->compiled = MS_FALSE; - exp->flags = 0; - exp->tokens = exp->curtoken = NULL; } void msFreeExpressionTokens(expressionObj *exp) @@ -1993,7 +2019,7 @@ int loadExpression(expressionObj *exp) { - /* TODO: should we fall msFreeExpression if exp->string != NULL? We do some checking to avoid a leak but is it enough... */ + /* TODO: should we call msFreeExpression if exp->string != NULL? We do some checking to avoid a leak but is it enough... */ msyystring_icase = MS_TRUE; if((exp->type = getSymbol(6, MS_STRING,MS_EXPRESSION,MS_REGEX,MS_ISTRING,MS_IREGEX,MS_LIST)) == -1) return(-1); @@ -2002,6 +2028,7 @@ msFree(exp->native_string); } exp->string = msStrdup(msyystring_buffer); + exp->native_string = NULL; if(exp->type == MS_ISTRING) { exp->flags = exp->flags | MS_EXP_INSENSITIVE; @@ -2729,7 +2756,7 @@ msIO_fprintf(stream, "GEOMTRANSFORM (%s)\n", style->_geomtransform.string); } else if(style->_geomtransform.type != MS_GEOMTRANSFORM_NONE) { - writeKeyword(stream, indent, "GEOMTRANSFORM", style->_geomtransform.type, 7, + writeKeyword(stream, indent, "GEOMTRANSFORM", style->_geomtransform.type, 8, MS_GEOMTRANSFORM_BBOX, "\"bbox\"", MS_GEOMTRANSFORM_END, "\"end\"", MS_GEOMTRANSFORM_LABELPOINT, "\"labelpnt\"", @@ -3374,12 +3401,15 @@ static int classResolveSymbolNames(classObj *class) { int i,j; + int try_addimage_if_notfound = MS_TRUE; + + if(msyysource == MS_URL_TOKENS) try_addimage_if_notfound = MS_FALSE; /* step through styles and labels to resolve symbol names */ /* class styles */ for(i=0; inumstyles; i++) { if(class->styles[i]->symbolname) { - if((class->styles[i]->symbol = msGetSymbolIndex(&(class->layer->map->symbolset), class->styles[i]->symbolname, MS_TRUE)) == -1) { + if((class->styles[i]->symbol = msGetSymbolIndex(&(class->layer->map->symbolset), class->styles[i]->symbolname, try_addimage_if_notfound)) == -1) { msSetError(MS_MISCERR, "Undefined symbol \"%s\" in class, style %d of layer %s.", "classResolveSymbolNames()", class->styles[i]->symbolname, i, class->layer->name); return MS_FAILURE; } @@ -3390,7 +3420,7 @@ for(i=0; inumlabels; i++) { for(j=0; jlabels[i]->numstyles; j++) { if(class->labels[i]->styles[j]->symbolname) { - if((class->labels[i]->styles[j]->symbol = msGetSymbolIndex(&(class->layer->map->symbolset), class->labels[i]->styles[j]->symbolname, MS_TRUE)) == -1) { + if((class->labels[i]->styles[j]->symbol = msGetSymbolIndex(&(class->layer->map->symbolset), class->labels[i]->styles[j]->symbolname, try_addimage_if_notfound)) == -1) { msSetError(MS_MISCERR, "Undefined symbol \"%s\" in class, label style %d of layer %s.", "classResolveSymbolNames()", class->labels[i]->styles[j]->symbolname, j, class->layer->name); return MS_FAILURE; } @@ -6443,7 +6473,7 @@ MS_CHECK_ALLOC(map, sizeof(mapObj), NULL); if(initMap(map) == -1) { /* initialize this map */ - msFree(map); + msFreeMap(map); return(NULL); } @@ -6535,7 +6565,7 @@ MS_CHECK_ALLOC(map, sizeof(mapObj), NULL); if(initMap(map) == -1) { /* initialize this map */ - msFree(map); + msFreeMap(map); return(NULL); } @@ -6636,17 +6666,6 @@ switch(msyylex()) { case(MAP): switch(msyylex()) { - case(CONFIG): { - char *key=NULL, *value=NULL; - if((getString(&key) != MS_FAILURE) && (getString(&value) != MS_FAILURE)) { - msSetConfigOption( map, key, value ); - free( key ); - key=NULL; - free( value ); - value=NULL; - } - } - break; case(EXTENT): msyystate = MS_TOKENIZE_URL_STRING; msyystring = string; @@ -6748,22 +6767,9 @@ if(msUpdateLayerFromString((GET_LAYER(map, i)), string, MS_TRUE) != MS_SUCCESS) return MS_FAILURE; } - /* make sure any symbol names for this layer have been resolved (bug #2700) */ - for(j=0; jnumclasses; j++) { - for(k=0; kclass[j]->numstyles; k++) { - if(GET_LAYER(map, i)->class[j]->styles[k]->symbolname && GET_LAYER(map, i)->class[j]->styles[k]->symbol == 0) { - if((GET_LAYER(map, i)->class[j]->styles[k]->symbol = msGetSymbolIndex(&(map->symbolset), GET_LAYER(map, i)->class[j]->styles[k]->symbolname, MS_TRUE)) == -1) { - msSetError(MS_MISCERR, "Undefined symbol \"%s\" in class %d, style %d of layer %s.", "msUpdateMapFromURL()", GET_LAYER(map, i)->class[j]->styles[k]->symbolname, j, k, GET_LAYER(map, i)->name); - return MS_FAILURE; - } - } - if(!MS_IS_VALID_ARRAY_INDEX(GET_LAYER(map, i)->class[j]->styles[k]->symbol, map->symbolset.numsymbols)) { - msSetError(MS_MISCERR, "Invalid symbol index in class %d, style %d of layer %s.", "msUpdateMapFromURL()", j, k, GET_LAYER(map, i)->name); - return MS_FAILURE; - } - } - } - + // make sure symbols are resolved + if (resolveSymbolNames(map) == MS_FAILURE) return MS_FAILURE; + break; case(LEGEND): if(msyylex() == LABEL) { diff -Nru mapserver-7.6.2/mapgml.c mapserver-7.6.4/mapgml.c --- mapserver-7.6.2/mapgml.c 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/mapgml.c 2021-07-12 20:16:21.000000000 +0000 @@ -34,7 +34,7 @@ #include "maptime.h" -/* Use only mapgml.c if WMS or WFS is available (with minor exceptions at end)*/ +/* Use only mapgml.c if WMS or WFS is available (with minor exceptions at end) */ #if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) @@ -1485,23 +1485,25 @@ if(pszOutputSRS == pszMapSRS && msProjectionsDiffer(&(lp->projection), &(map->projection))) { reprojector = msProjectCreateReprojector(&(lp->projection), &(map->projection)); if( reprojector == NULL ) { - msGMLFreeGroups(groupList); - msGMLFreeConstants(constantList); - msGMLFreeItems(itemList); - msGMLFreeGeometries(geometryList); - return MS_FAILURE; + msGMLFreeGroups(groupList); + msGMLFreeConstants(constantList); + msGMLFreeItems(itemList); + msGMLFreeGeometries(geometryList); + msFree(pszOutputSRS); + return MS_FAILURE; } } for(j=0; jresultcache->numresults; j++) { status = msLayerGetShape(lp, &shape, &(lp->resultcache->results[j])); if(status != MS_SUCCESS) { - msGMLFreeGroups(groupList); - msGMLFreeConstants(constantList); - msGMLFreeItems(itemList); - msGMLFreeGeometries(geometryList); - msProjectDestroyReprojector(reprojector); - return(status); + msGMLFreeGroups(groupList); + msGMLFreeConstants(constantList); + msGMLFreeItems(itemList); + msGMLFreeGeometries(geometryList); + msProjectDestroyReprojector(reprojector); + msFree(pszOutputSRS); + return MS_FAILURE; } /* project the shape into the map projection (if necessary), note that this projects the bounds as well */ diff -Nru mapserver-7.6.2/maphttp.c mapserver-7.6.4/maphttp.c --- mapserver-7.6.2/maphttp.c 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/maphttp.c 2021-07-12 20:16:21.000000000 +0000 @@ -39,7 +39,7 @@ #include "mapthread.h" #include "mapows.h" - +#include "cpl_conv.h" #include #ifndef _WIN32 @@ -471,7 +471,7 @@ * If set then the value is the full path to the ca-bundle.crt file * e.g. CURL_CA_BUNDLE=/usr/local/share/curl/curl-ca-bundle.crt */ - pszCurlCABundle = getenv("CURL_CA_BUNDLE"); + pszCurlCABundle = CPLGetConfigOption("CURL_CA_BUNDLE", NULL); if (debug) { msDebug("HTTP: Starting to prepare HTTP requests.\n"); diff -Nru mapserver-7.6.2/maplabel.c mapserver-7.6.4/maplabel.c --- mapserver-7.6.2/maplabel.c 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/maplabel.c 2021-07-12 20:16:21.000000000 +0000 @@ -881,7 +881,7 @@ pointObj get_metrics(pointObj *p, int position, textPathObj *tp, int ox, int oy, double rotation, int buffer, label_bounds *bounds) { - pointObj q; + pointObj q = {0,0,0,0}; // initialize double x1=0, y1=0, x2=0, y2=0; double sin_a,cos_a; double w, h, x, y; diff -Nru mapserver-7.6.2/maplegend.c mapserver-7.6.4/maplegend.c --- mapserver-7.6.2/maplegend.c 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/maplegend.c 2021-07-12 20:16:21.000000000 +0000 @@ -189,6 +189,12 @@ /* ** now draw the appropriate color/symbol/size combination */ + + /* Scalefactor will be infinity when SIZEUNITS is set in LAYER */ + if(lp->sizeunits != MS_PIXELS) { + lp->scalefactor = 1.0; + } + switch(type) { case MS_LAYER_POINT: marker.x = dstX + MS_NINT(width / 2.0); diff -Nru mapserver-7.6.2/mapobject.c mapserver-7.6.4/mapobject.c --- mapserver-7.6.2/mapobject.c 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/mapobject.c 2021-07-12 20:16:21.000000000 +0000 @@ -47,7 +47,7 @@ mapObj *msNewMapObj() { - mapObj *map; + mapObj *map = NULL; /* create an empty map, no layers etc... */ map = (mapObj *)calloc(sizeof(mapObj),1); @@ -57,11 +57,15 @@ return NULL; } - if( initMap( map ) == -1 ) + if( initMap( map ) == -1 ) { + msFreeMap(map); return NULL; + } - if( msPostMapParseOutputFormatSetup( map ) == MS_FAILURE ) + if( msPostMapParseOutputFormatSetup( map ) == MS_FAILURE ) { + msFreeMap(map); return NULL; + } return map; } diff -Nru mapserver-7.6.2/mapogcsld.c mapserver-7.6.4/mapogcsld.c --- mapserver-7.6.2/mapogcsld.c 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/mapogcsld.c 2021-07-12 20:16:21.000000000 +0000 @@ -4716,8 +4716,8 @@ } else pszAttributeName[iValue++] = pszExpression[i]; } - pszAttributeName[iValue] = '\0'; } + pszAttributeName[iValue] = '\0'; } msFreeCharArray(aszValues, nTokens); } else if (bOneCharCompare == 0) { @@ -4744,8 +4744,8 @@ } else pszAttributeName[iValue++] = pszExpression[i]; } - pszAttributeName[iValue] = '\0'; } + pszAttributeName[iValue] = '\0'; } /* -------------------------------------------------------------------- */ diff -Nru mapserver-7.6.2/mapogcsos.c mapserver-7.6.4/mapogcsos.c --- mapserver-7.6.2/mapogcsos.c 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/mapogcsos.c 2021-07-12 20:16:21.000000000 +0000 @@ -2931,16 +2931,22 @@ if (psXPathTmp) sosparams->pszRequest = msStrdup("GetCapabilities"); + xmlXPathFreeObject(psXPathTmp); + psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:DescribeSensor"); if (psXPathTmp) sosparams->pszRequest = msStrdup("DescribeSensor"); + xmlXPathFreeObject(psXPathTmp); + psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:GetObservation"); if (psXPathTmp) sosparams->pszRequest = msStrdup("GetObservation"); + xmlXPathFreeObject(psXPathTmp); + psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:DescribeObservationType"); if (psXPathTmp) diff -Nru mapserver-7.6.2/mapogr.cpp mapserver-7.6.4/mapogr.cpp --- mapserver-7.6.2/mapogr.cpp 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/mapogr.cpp 2021-07-12 20:16:21.000000000 +0000 @@ -2272,66 +2272,6 @@ bool bSpatialiteOrGPKGAddOrderByFID = false; - if( psInfo->dialect && psInfo->pszMainTableName != NULL && - ( (EQUAL(psInfo->dialect, "Spatialite") && psInfo->bHasSpatialIndex) - || EQUAL(psInfo->dialect, "GPKG") ) && - bIsValidRect ) - { - select = msStringConcatenate(select, " JOIN "); - - char szSpatialIndexName[256]; - snprintf( szSpatialIndexName, sizeof(szSpatialIndexName), - "%s_%s_%s", - EQUAL(psInfo->dialect, "Spatialite") ? "idx" : "rtree", - psInfo->pszSpatialFilterTableName, - psInfo->pszSpatialFilterGeometryColumn ); - char* pszEscapedSpatialIndexName = msLayerEscapePropertyName( - layer, szSpatialIndexName); - select = msStringConcatenate(select, "\""); - select = msStringConcatenate(select, pszEscapedSpatialIndexName); - msFree(pszEscapedSpatialIndexName); - select = msStringConcatenate(select, "\" ms_spat_idx ON \""); - char* pszEscapedMainTableName = msLayerEscapePropertyName( - layer, psInfo->pszMainTableName); - select = msStringConcatenate(select, pszEscapedMainTableName); - msFree(pszEscapedMainTableName); - select = msStringConcatenate(select, "\"."); - if( psInfo->pszRowId ) - { - char* pszEscapedRowId = msLayerEscapePropertyName( - layer, psInfo->pszRowId); - select = msStringConcatenate(select, "\""); - select = msStringConcatenate(select, pszEscapedRowId); - select = msStringConcatenate(select, "\""); - msFree(pszEscapedRowId); - } - else - select = msStringConcatenate(select, "ROWID"); - if( EQUAL(psInfo->dialect, "Spatialite") ) - select = msStringConcatenate(select, " = ms_spat_idx.pkid AND "); - else - select = msStringConcatenate(select, " = ms_spat_idx.id AND "); - - char szCond[256]; - if( EQUAL(psInfo->dialect, "Spatialite") ) - { - snprintf(szCond, sizeof(szCond), - "ms_spat_idx.xmin <= %.15g AND ms_spat_idx.xmax >= %.15g AND " - "ms_spat_idx.ymin <= %.15g AND ms_spat_idx.ymax >= %.15g", - rect.maxx, rect.minx, rect.maxy, rect.miny); - } - else - { - snprintf(szCond, sizeof(szCond), - "ms_spat_idx.minx <= %.15g AND ms_spat_idx.maxx >= %.15g AND " - "ms_spat_idx.miny <= %.15g AND ms_spat_idx.maxy >= %.15g", - rect.maxx, rect.minx, rect.maxy, rect.miny); - } - select = msStringConcatenate(select, szCond); - - bSpatialiteOrGPKGAddOrderByFID = true; - } - const char *sql = layer->filter.native_string; if (psInfo->dialect && sql && *sql != '\0' && (EQUAL(psInfo->dialect, "Spatialite") || @@ -2368,16 +2308,102 @@ msFree(points); filter = msStringConcatenate(filter, "))"); } - else if( psInfo->dialect && EQUAL(psInfo->dialect, "Spatialite") && - psInfo->pszMainTableName != NULL && !psInfo->bHasSpatialIndex ) + else if( psInfo->dialect && + (EQUAL(psInfo->dialect, "Spatialite") || + EQUAL(psInfo->dialect, "GPKG")) && + psInfo->pszMainTableName != NULL ) { + if( (EQUAL(psInfo->dialect, "Spatialite") && psInfo->bHasSpatialIndex) + || EQUAL(psInfo->dialect, "GPKG") ) + { + if (filter) filter = msStringConcatenate(filter, " AND "); + char* pszEscapedMainTableName = msLayerEscapePropertyName( + layer, psInfo->pszMainTableName); + filter = msStringConcatenate(filter, "\""); + filter = msStringConcatenate(filter, pszEscapedMainTableName); + msFree(pszEscapedMainTableName); + filter = msStringConcatenate(filter, "\"."); + if( psInfo->pszRowId ) + { + char* pszEscapedRowId = msLayerEscapePropertyName( + layer, psInfo->pszRowId); + filter = msStringConcatenate(filter, "\""); + filter = msStringConcatenate(filter, pszEscapedRowId); + filter = msStringConcatenate(filter, "\""); + msFree(pszEscapedRowId); + } + else + filter = msStringConcatenate(filter, "ROWID"); + + filter = msStringConcatenate(filter, " IN "); + filter = msStringConcatenate(filter, "("); + filter = msStringConcatenate(filter, "SELECT "); + + if( EQUAL(psInfo->dialect, "Spatialite") ) + filter = msStringConcatenate(filter, "ms_spat_idx.pkid"); + else + filter = msStringConcatenate(filter, "ms_spat_idx.id"); + + filter = msStringConcatenate(filter, " FROM "); + + char szSpatialIndexName[256]; + snprintf( szSpatialIndexName, sizeof(szSpatialIndexName), + "%s_%s_%s", + EQUAL(psInfo->dialect, "Spatialite") ? "idx" : "rtree", + psInfo->pszSpatialFilterTableName, + psInfo->pszSpatialFilterGeometryColumn ); + char* pszEscapedSpatialIndexName = msLayerEscapePropertyName( + layer, szSpatialIndexName); + + filter = msStringConcatenate(filter, "\""); + filter = msStringConcatenate(filter, pszEscapedSpatialIndexName); + msFree(pszEscapedSpatialIndexName); + + filter = msStringConcatenate(filter, "\" ms_spat_idx WHERE "); + + char szCond[256]; + if( EQUAL(psInfo->dialect, "Spatialite") ) + { + snprintf(szCond, sizeof(szCond), + "ms_spat_idx.xmin <= %.15g AND ms_spat_idx.xmax >= %.15g AND " + "ms_spat_idx.ymin <= %.15g AND ms_spat_idx.ymax >= %.15g", + rect.maxx, rect.minx, rect.maxy, rect.miny); + } + else + { + snprintf(szCond, sizeof(szCond), + "ms_spat_idx.minx <= %.15g AND ms_spat_idx.maxx >= %.15g AND " + "ms_spat_idx.miny <= %.15g AND ms_spat_idx.maxy >= %.15g", + rect.maxx, rect.minx, rect.maxy, rect.miny); + } + filter = msStringConcatenate(filter, szCond); + + filter = msStringConcatenate(filter, ")"); + + bSpatialiteOrGPKGAddOrderByFID = true; + } + + const bool isGPKG = EQUAL(psInfo->dialect, "GPKG"); if (filter) filter = msStringConcatenate(filter, " AND"); const char *col = OGR_L_GetGeometryColumn(psInfo->hLayer); // which geom field?? - filter = msStringConcatenate(filter, " MbrIntersects(\""); + filter = msStringConcatenate(filter, " Intersects("); + if( isGPKG ) + { + // Casting GeoPackage geometries to spatialie ones is done + // automatically normally, since GDAL enables the + // "amphibious" mode, but without it + // explicilty specified, spatialite 4.3.0a does an + // out-of-bounds access. + filter = msStringConcatenate(filter, "GeomFromGPB("); + } + filter = msStringConcatenate(filter, "\""); char* escaped = msLayerEscapePropertyName(layer, col); filter = msStringConcatenate(filter, escaped); msFree(escaped); - filter = msStringConcatenate(filter, "\", BuildMbr("); + filter = msStringConcatenate(filter, "\""); + if( isGPKG ) + filter = msStringConcatenate(filter, ")"); + filter = msStringConcatenate(filter, ", BuildMbr("); char *points = (char *)msSmallMalloc(30*2*5); snprintf(points, 30*4, "%lf,%lf,%lf,%lf", rect.minx, rect.miny, rect.maxx, rect.maxy); filter = msStringConcatenate(filter, points); @@ -3080,7 +3106,10 @@ #ifndef IGNORE_MISSING_DATA if( psTileInfo == NULL && targetTile == -1 ) + { + msFree(pszSRS); goto NextFile; + } #endif if( psTileInfo == NULL ) diff -Nru mapserver-7.6.2/mapows.c mapserver-7.6.4/mapows.c --- mapserver-7.6.2/mapows.c 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/mapows.c 2021-07-12 20:16:21.000000000 +0000 @@ -2587,13 +2587,14 @@ char **tokens; int numtokens, i; size_t bufferSize = 0; - char *oldStyle; + char *oldStyle = NULL; - msOWSGetEPSGProj( proj, metadata, namespaces, - bReturnOnlyFirstOne, &oldStyle ); + msOWSGetEPSGProj( proj, metadata, namespaces, bReturnOnlyFirstOne, &oldStyle ); - if( oldStyle == NULL || strncmp(oldStyle,"EPSG:",5) != 0 ) + if( oldStyle == NULL || strncmp(oldStyle,"EPSG:",5) != 0 ) { + msFree(oldStyle); return NULL; + } result = msStrdup(""); @@ -2647,13 +2648,14 @@ char *result; char **tokens; int numtokens, i; - char *oldStyle; + char *oldStyle = NULL; - msOWSGetEPSGProj( proj, metadata, namespaces, - bReturnOnlyFirstOne, &oldStyle); + msOWSGetEPSGProj( proj, metadata, namespaces, bReturnOnlyFirstOne, &oldStyle); - if( oldStyle == NULL || !EQUALN(oldStyle,"EPSG:",5) ) + if( oldStyle == NULL || !EQUALN(oldStyle,"EPSG:",5) ) { + msFree(oldStyle); // avoid leak return NULL; + } result = msStrdup(""); diff -Nru mapserver-7.6.2/mappostgis.c mapserver-7.6.4/mappostgis.c --- mapserver-7.6.2/mappostgis.c 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/mappostgis.c 2021-07-12 20:16:21.000000000 +0000 @@ -752,7 +752,7 @@ int arcCircleCenter(const pointObj *p1, const pointObj *p2, const pointObj *p3, pointObj *center, double *radius) { - pointObj c; + pointObj c = {0,0,0,0}; // initialize double dx21, dy21, dx31, dy31, h21, h31, d, r; /* Circle is closed, so p2 must be opposite p1 & p3. */ @@ -1666,37 +1666,44 @@ char *strBox = NULL; size_t sz; + const int bIsPoint = rect->minx == rect->maxx && rect->miny == rect->maxy; if (layer->debug) { msDebug("msPostGISBuildSQLBox called.\n"); } if ( strSRID ) { - static char *strBoxTemplate = "ST_GeomFromText('POLYGON((%.15g %.15g,%.15g %.15g,%.15g %.15g,%.15g %.15g,%.15g %.15g))',%s)"; + static const char *strBoxTemplate = "ST_GeomFromText('POLYGON((%.15g %.15g,%.15g %.15g,%.15g %.15g,%.15g %.15g,%.15g %.15g))',%s)"; + static const char *strBoxTemplatePoint = "ST_GeomFromText('POINT(%.15g %.15g)',%s)"; /* 10 doubles + 1 integer + template characters */ sz = 10 * 22 + strlen(strSRID) + strlen(strBoxTemplate); strBox = (char*)msSmallMalloc(sz+1); /* add space for terminating NULL */ - if ( sz <= snprintf(strBox, sz, strBoxTemplate, + if ( (bIsPoint && sz <= (size_t)(snprintf(strBox, sz, strBoxTemplatePoint, + rect->minx, rect->miny, strSRID))) || + (!bIsPoint && sz <= (size_t)(snprintf(strBox, sz, strBoxTemplate, rect->minx, rect->miny, rect->minx, rect->maxy, rect->maxx, rect->maxy, rect->maxx, rect->miny, rect->minx, rect->miny, - strSRID)) { + strSRID))) ) { msSetError(MS_MISCERR,"Bounding box digits truncated.","msPostGISBuildSQLBox"); return NULL; } } else { - static char *strBoxTemplate = "ST_GeomFromText('POLYGON((%.15g %.15g,%.15g %.15g,%.15g %.15g,%.15g %.15g,%.15g %.15g))')"; + static const char *strBoxTemplate = "ST_GeomFromText('POLYGON((%.15g %.15g,%.15g %.15g,%.15g %.15g,%.15g %.15g,%.15g %.15g))')"; + static const char *strBoxTemplatePoint = "ST_GeomFromText('POINT(%.15g %.15g)')"; /* 10 doubles + template characters */ sz = 10 * 22 + strlen(strBoxTemplate); strBox = (char*)msSmallMalloc(sz+1); /* add space for terminating NULL */ - if ( sz <= snprintf(strBox, sz, strBoxTemplate, + if ( (bIsPoint && sz <= (size_t)(snprintf(strBox, sz, strBoxTemplatePoint, + rect->minx, rect->miny))) || + (!bIsPoint && sz <= (size_t)(snprintf(strBox, sz, strBoxTemplate, rect->minx, rect->miny, rect->minx, rect->maxy, rect->maxx, rect->maxy, rect->maxx, rect->miny, - rect->minx, rect->miny) ) { + rect->minx, rect->miny))) ) { msSetError(MS_MISCERR,"Bounding box digits truncated.","msPostGISBuildSQLBox"); return NULL; } @@ -2055,7 +2062,6 @@ char *strBox = 0; char *strSRID = 0; size_t strBoxLength = 0; - static const char *strRectTemplate = "\"%s\" && %s"; /* We see to set the SRID on the box, but to what SRID? */ strSRID = msPostGISBuildSQLSRID(layer); @@ -2066,27 +2072,53 @@ } strBox = msPostGISBuildSQLBox(layer, rect, strSRID); - msFree(strSRID); if ( strBox ) { strBoxLength = strlen(strBox); } else { msSetError(MS_MISCERR, "Unable to build box SQL.", "msPostGISBuildSQLWhere()"); free( strLimit ); free( strOffset ); + msFree(strSRID); return NULL; } - strRect = (char*)msSmallMalloc(strlen(strRectTemplate) + strBoxLength + strlen(layerinfo->geomcolumn) +1 ); - sprintf(strRect, strRectTemplate, layerinfo->geomcolumn, strBox); + if( strstr(strSRID, "find_srid(") == NULL ) + { + // If the SRID is known, we can safely use ST_Intersects() + // otherwise if find_srid() would return 0, ST_Intersects() would not + // work at all, which breaks the msautotest/query/query_postgis.map + // tests, releated to bdry_counpy2 layer that has no SRID + if( layerinfo->version >= 20500 ) + { + static const char *strRectTemplate = "ST_Intersects(\"%s\", %s)"; + strRect = (char*)msSmallMalloc(strlen(strRectTemplate) + strBoxLength + strlen(layerinfo->geomcolumn) +1 ); + sprintf(strRect, strRectTemplate, layerinfo->geomcolumn, strBox); + } + else + { + // ST_Intersects() before PostGIS 2.5 doesn't support collections + // See https://github.com/MapServer/MapServer/pull/6355#issuecomment-877355007 + static const char *strRectTemplate = "(\"%s\" && %s) AND ST_Distance(\"%s\", %s) = 0"; + strRect = (char*)msSmallMalloc(strlen(strRectTemplate) + 2 * (strBoxLength + strlen(layerinfo->geomcolumn)) +1 ); + sprintf(strRect, strRectTemplate, layerinfo->geomcolumn, strBox, layerinfo->geomcolumn, strBox); + } + } + else + { + static const char *strRectTemplate = "\"%s\" && %s"; + strRect = (char*)msSmallMalloc(strlen(strRectTemplate) + strBoxLength + strlen(layerinfo->geomcolumn) +1 ); + sprintf(strRect, strRectTemplate, layerinfo->geomcolumn, strBox); + } strRectLength = strlen(strRect); free(strBox); + msFree(strSRID); /* Combine with other rectangle expressed in another SRS */ /* (generally equivalent to the above in current code paths) */ if( rectInOtherSRID != NULL && otherSRID > 0 ) { char* strRectOtherSRID; - static const char *strRectOtherSRIDTemplate = "NOT ST_Disjoint(ST_Transform(%s,%d),%s)"; + static const char *strRectOtherSRIDTemplate = "ST_Intersects(ST_Transform(%s,%d),%s)"; char szSRID[32]; char* strTmp = NULL; @@ -2121,7 +2153,7 @@ { char* strSRID; char* strRectOtherSRID; - static const char *strRectOtherSRIDTemplate = "NOT ST_Disjoint(%s,%s)"; + static const char *strRectOtherSRIDTemplate = "ST_Intersects(%s,%s)"; char* strTmp = NULL; strSRID = msPostGISBuildSQLSRID(layer); diff -Nru mapserver-7.6.2/mapprimitive.c mapserver-7.6.4/mapprimitive.c --- mapserver-7.6.2/mapprimitive.c 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/mapprimitive.c 2021-07-12 20:16:21.000000000 +0000 @@ -1133,7 +1133,7 @@ */ static pointObj generateLineIntersection(pointObj a, pointObj b, pointObj c, pointObj d) { - pointObj p; + pointObj p = {0,0,0,0}; // initialize double r; double denominator, numerator; diff -Nru mapserver-7.6.2/mapproject.c mapserver-7.6.4/mapproject.c --- mapserver-7.6.2/mapproject.c 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/mapproject.c 2021-07-12 20:16:21.000000000 +0000 @@ -119,11 +119,23 @@ /* Return to be freed with proj_destroy() if *pbFreePJ = TRUE */ static PJ* createNormalizedPJ(projectionObj *in, projectionObj *out, int* pbFreePJ) { + if( in->proj == out->proj ) + { + /* Special case to avoid out_str below to cause in_str to become invalid */ + *pbFreePJ = TRUE; +#if PROJ_VERSION_MAJOR == 6 && PROJ_VERSION_MINOR == 0 + /* 6.0 didn't support proj=noop */ + return proj_create(in->proj_ctx->proj_ctx, "+proj=affine"); +#else + return proj_create(in->proj_ctx->proj_ctx, "+proj=noop"); +#endif + } + const char* const wkt_options[] = { "MULTILINE=NO", NULL }; - const char* in_str = (in && msProjectHasLonWrapOrOver(in)) ? + const char* in_str = msProjectHasLonWrapOrOver(in) ? proj_as_proj_string(in->proj_ctx->proj_ctx, in->proj, PJ_PROJ_4, NULL) : proj_as_wkt(in->proj_ctx->proj_ctx, in->proj, PJ_WKT2_2018, wkt_options); - const char* out_str = (out && msProjectHasLonWrapOrOver(out)) ? + const char* out_str = msProjectHasLonWrapOrOver(out) ? proj_as_proj_string(out->proj_ctx->proj_ctx, out->proj, PJ_PROJ_4, NULL) : proj_as_wkt(out->proj_ctx->proj_ctx, out->proj, PJ_WKT2_2018, wkt_options); PJ* pj_raw; @@ -1199,7 +1211,7 @@ return MS_FALSE; } - pointObj p; + pointObj p = {0,0,0,0}; // initialize double invgt0 = out->gt.need_geotransform ? out->gt.invgeotransform[0] : 0.0; double invgt1 = out->gt.need_geotransform ? out->gt.invgeotransform[1] : 1.0; double invgt3 = out->gt.need_geotransform ? out->gt.invgeotransform[3] : 0.0; diff -Nru mapserver-7.6.2/mapquery.c mapserver-7.6.4/mapquery.c --- mapserver-7.6.2/mapquery.c 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/mapquery.c 2021-07-12 20:16:21.000000000 +0000 @@ -1617,7 +1617,7 @@ } /* next selection shape */ - if(lp->resultcache->numresults == 0) msLayerClose(lp); /* no need to keep the layer open */ + if(lp->resultcache == NULL || lp->resultcache->numresults == 0) msLayerClose(lp); /* no need to keep the layer open */ } /* next layer */ /* was anything found? */ diff -Nru mapserver-7.6.2/mapraster.c mapserver-7.6.4/mapraster.c --- mapserver-7.6.2/mapraster.c 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/mapraster.c 2021-07-12 20:16:21.000000000 +0000 @@ -984,16 +984,22 @@ char szPath[MS_MAXPATHLEN]; int status = MS_SUCCESS; - imageObj *image = NULL; + imageObj *image = NULL; styleObj style; + /* check to see if we have enough information to actually proceed */ + if(!map->reference.image || map->reference.height == 0 || map->reference.width == 0) { + msSetError(MS_MISCERR, "Reference map configuration error.", "msDrawReferenceMap()"); + return NULL; + } rendererVTableObj *renderer = MS_MAP_RENDERER(map); rasterBufferObj *refImage = (rasterBufferObj*)calloc(1,sizeof(rasterBufferObj)); MS_CHECK_ALLOC(refImage, sizeof(rasterBufferObj), NULL); if(MS_SUCCESS != renderer->loadImageFromFile(msBuildPath(szPath, map->mappath, map->reference.image),refImage)) { - msSetError(MS_MISCERR,"error loading reference image %s","msDrawREferenceMap()",szPath); + msSetError(MS_MISCERR,"Error loading reference image %s.","msDrawReferenceMap()",szPath); + free(refImage); return NULL; } diff -Nru mapserver-7.6.2/mapscript/python/README.rst mapserver-7.6.4/mapscript/python/README.rst --- mapserver-7.6.2/mapscript/python/README.rst 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/mapscript/python/README.rst 2021-07-12 20:16:21.000000000 +0000 @@ -2,7 +2,7 @@ ===================================== :Author: MapServer Team -:Last Updated: 2020-03-02 +:Last Updated: 2021-01-16 Introduction ------------ @@ -35,7 +35,7 @@ + mapscript can be easily added to a Python `Virtual Environment `_ + Python2 or Python3 versions of mapscript can be installed and work with a single installation of MapServer -Wheels are built based on the `Appveyor build environments `_. +Wheels are built based on the `Appveyor build environments `_. These are as follows at the time of writing: + Python 2.7 x32 @@ -68,6 +68,10 @@ To ensure compatibility with the wheels, please use identical release packages, e.g. ``release-1911-x64-gdal-2-3-mapserver-7-4`` for mapscript 7.4. +.. NOTE:: + `MS4W `_ (MapServer for Windows) is a full installer that contains Python & Python + MapScript already configured out-of-the-box, as well as default OGC web services and over 60 working mapfiles. + When using these packages the MapServer path will be similar to ``C:\release-1911-x64-gdal-2-3-mapserver-7-2\bin``. Prior to installing mapscript it is recommended to update pip to the latest version with the following command: diff -Nru mapserver-7.6.2/mapserv.c mapserver-7.6.4/mapserv.c --- mapserver-7.6.2/mapserv.c 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/mapserv.c 2021-07-12 20:16:21.000000000 +0000 @@ -43,6 +43,8 @@ #include "mapio.h" #include "maptime.h" +#include "cpl_conv.h" + #ifndef WIN32 #include #endif @@ -162,6 +164,16 @@ if(msGetGlobalDebugLevel() >= MS_DEBUGLEVEL_TUNING) msGettimeofday(&execstarttime, NULL); + /* push high-value ENV vars into the CPL global config - primarily for IIS/FastCGI */ + const char* const apszEnvVars[] = { + "CURL_CA_BUNDLE", "MS_MAPFILE", "MS_MAP_NO_PATH", "MS_MAP_PATTERN", "MS_MAP_ENV_PATTERN", + "MS_MAP_BAD_PATTERN", "MS_MAP_ENV_BAD_PATTERN", + NULL /* guard */ }; + for( int i = 0; apszEnvVars[i] != NULL; ++i ) { + const char* value = getenv(apszEnvVars[i]); + if(value) CPLSetConfigOption(apszEnvVars[i], value); + } + /* -------------------------------------------------------------------- */ /* Process arguments. In normal use as a cgi-bin there are no */ /* commandline switches, but we provide a few for test/debug */ diff -Nru mapserver-7.6.2/mapserver.h mapserver-7.6.4/mapserver.h --- mapserver-7.6.2/mapserver.h 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/mapserver.h 2021-07-12 20:16:21.000000000 +0000 @@ -2159,7 +2159,9 @@ MS_DLL_EXPORT char *msWriteReferenceMapToString(referenceMapObj *ref); MS_DLL_EXPORT char *msWriteLegendToString(legendObj *legend); MS_DLL_EXPORT char *msWriteClusterToString(clusterObj *cluster); + MS_DLL_EXPORT int msIsValidRegex(const char* e); MS_DLL_EXPORT int msEvalRegex(const char *e, const char *s); + MS_DLL_EXPORT int msCaseEvalRegex(const char *e, const char *s); #ifdef USE_MSFREE MS_DLL_EXPORT void msFree(void *p); #else diff -Nru mapserver-7.6.2/mapserv.h mapserver-7.6.4/mapserv.h --- mapserver-7.6.2/mapserv.h 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/mapserv.h 2021-07-12 20:16:21.000000000 +0000 @@ -41,6 +41,7 @@ #include "maptile.h" #include "cgiutil.h" + /* ** Defines */ diff -Nru mapserver-7.6.2/mapservutil.c mapserver-7.6.4/mapservutil.c --- mapserver-7.6.2/mapservutil.c 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/mapservutil.c 2021-07-12 20:16:21.000000000 +0000 @@ -33,6 +33,8 @@ #include "maptime.h" #include "mapows.h" +#include "cpl_conv.h" + /* ** Enumerated types, keep the query modes in sequence and at the end of the enumeration (mode enumeration is in maptemplate.h). */ @@ -197,38 +199,67 @@ int i, j; mapObj *map = NULL; + const char *ms_map_bad_pattern_default = "[/\\]{2}|[/\\]?\\.+[/\\]|,"; + const char *ms_map_env_bad_pattern_default = "^(AUTH_.*|CERT_.*|CONTENT_(LENGTH|TYPE)|DOCUMENT_(ROOT|URI)|GATEWAY_INTERFACE|HTTP.*|QUERY_STRING|PATH_(INFO|TRANSLATED)|REMOTE_.*|REQUEST_(METHOD|URI)|SCRIPT_(FILENAME|NAME)|SERVER_.*)"; + + int ms_mapfile_tainted = MS_TRUE; + const char *ms_mapfile = CPLGetConfigOption("MS_MAPFILE", NULL); + + const char *ms_map_no_path = CPLGetConfigOption("MS_MAP_NO_PATH", NULL); + const char *ms_map_pattern = CPLGetConfigOption("MS_MAP_PATTERN", NULL); + const char *ms_map_env_pattern = CPLGetConfigOption("MS_MAP_ENV_PATTERN", NULL); + + const char *ms_map_bad_pattern = CPLGetConfigOption("MS_MAP_BAD_PATTERN", NULL); + if(ms_map_bad_pattern == NULL) ms_map_bad_pattern = ms_map_bad_pattern_default; + + const char *ms_map_env_bad_pattern = CPLGetConfigOption("MS_MAP_ENV_BAD_PATTERN", NULL); + if(ms_map_env_bad_pattern == NULL) ms_map_env_bad_pattern = ms_map_env_bad_pattern_default; + for(i=0; irequest->NumParams; i++) /* find the mapfile parameter first */ if(strcasecmp(mapserv->request->ParamNames[i], "map") == 0) break; if(i == mapserv->request->NumParams) { - char *ms_mapfile = getenv("MS_MAPFILE"); - if(ms_mapfile) { - map = msLoadMap(ms_mapfile,NULL); - } else { + if(ms_mapfile == NULL) { msSetError(MS_WEBERR, "CGI variable \"map\" is not set.", "msCGILoadMap()"); /* no default, outta here */ return NULL; } + ms_mapfile_tainted = MS_FALSE; } else { - if(getenv(mapserv->request->ParamValues[i])) /* an environment variable references the actual file to use */ - map = msLoadMap(getenv(mapserv->request->ParamValues[i]), NULL); - else { - /* by here we know the request isn't for something in an environment variable */ - if(getenv("MS_MAP_NO_PATH")) { - msSetError(MS_WEBERR, "Mapfile not found in environment variables and this server is not configured for full paths.", "msCGILoadMap()"); + if(getenv(mapserv->request->ParamValues[i])) { /* an environment variable references the actual file to use */ + /* validate env variable name */ + if(msIsValidRegex(ms_map_env_bad_pattern) == MS_FALSE || msCaseEvalRegex(ms_map_env_bad_pattern, mapserv->request->ParamValues[i]) == MS_TRUE) { + msSetError(MS_WEBERR, "CGI variable \"map\" fails to validate.", "msCGILoadMap()"); return NULL; } - - if(getenv("MS_MAP_PATTERN") && msEvalRegex(getenv("MS_MAP_PATTERN"), mapserv->request->ParamValues[i]) != MS_TRUE) { - msSetError(MS_WEBERR, "Parameter 'map' value fails to validate.", "msCGILoadMap()"); + if(ms_map_env_pattern != NULL && msEvalRegex(ms_map_env_pattern, mapserv->request->ParamValues[i]) != MS_TRUE) { + msSetError(MS_WEBERR, "CGI variable \"map\" fails to validate.", "msCGILoadMap()"); return NULL; } + ms_mapfile = getenv(mapserv->request->ParamValues[i]); + } else { + /* by now we know the request isn't for something in an environment variable */ + if(ms_map_no_path != NULL) { + msSetError(MS_WEBERR, "CGI variable \"map\" not found in environment and this server is not configured for full paths.", "msCGILoadMap()"); + return NULL; + } + ms_mapfile = mapserv->request->ParamValues[i]; + } + } - /* ok to try to load now */ - map = msLoadMap(mapserv->request->ParamValues[i], NULL); + /* validate ms_mapfile if tainted */ + if(ms_mapfile_tainted == MS_TRUE) { + if(msIsValidRegex(ms_map_bad_pattern) == MS_FALSE || msEvalRegex(ms_map_bad_pattern, ms_mapfile) == MS_TRUE) { + msSetError(MS_WEBERR, "CGI variable \"map\" fails to validate.", "msCGILoadMap()"); + return NULL; + } + if(ms_map_pattern != NULL && msEvalRegex(ms_map_pattern, ms_mapfile) != MS_TRUE) { + msSetError(MS_WEBERR, "CGI variable \"map\" fails to validate.", "msCGILoadMap()"); + return NULL; } } - + /* ok to try to load now */ + map = msLoadMap(ms_mapfile, NULL); if(!map) return NULL; if(!msLookupHashTable(&(map->web.validation), "immutable")) { @@ -1620,7 +1651,7 @@ if(numtokens == 2) { /* check the class index */ classindex = atoi(tokens[1]); - if(classindex >= GET_LAYER(mapserv->map, layerindex)->numclasses) { + if(classindex < 0 || classindex >= GET_LAYER(mapserv->map, layerindex)->numclasses) { msSetError(MS_WEBERR, "Icon class=%d not found in layer=%s.", "mapserv()", classindex, GET_LAYER(mapserv->map, layerindex)->name); status = MS_FAILURE; goto li_cleanup; diff -Nru mapserver-7.6.2/mapshape.c mapserver-7.6.4/mapshape.c --- mapserver-7.6.2/mapshape.c 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/mapshape.c 2021-07-12 20:16:21.000000000 +0000 @@ -1726,11 +1726,18 @@ /* load some information about this shapefile */ msSHPGetInfo( shpfile->hSHP, &shpfile->numshapes, &shpfile->type); + + if( shpfile->numshapes < 0 || shpfile->numshapes > 256000000 ) { + msSetError(MS_SHPERR, "Corrupted .shp file : numshapes = %d.", + "msShapefileOpen()", shpfile->numshapes); + msSHPClose(shpfile->hSHP); + return -1; + } + msSHPReadBounds( shpfile->hSHP, -1, &(shpfile->bounds)); bufferSize = strlen(filename)+5; dbfFilename = (char *)msSmallMalloc(bufferSize); - dbfFilename[0] = '\0'; strcpy(dbfFilename, filename); /* clean off any extention the filename might have */ @@ -1749,6 +1756,7 @@ if( log_failures ) msSetError(MS_IOERR, "(%s)", "msShapefileOpen()", dbfFilename); free(dbfFilename); + msSHPClose(shpfile->hSHP); return(-1); } free(dbfFilename); diff -Nru mapserver-7.6.2/mapsmoothing.c mapserver-7.6.4/mapsmoothing.c --- mapserver-7.6.2/mapsmoothing.c 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/mapsmoothing.c 2021-07-12 20:16:21.000000000 +0000 @@ -142,7 +142,7 @@ while ((res = nextLineWindow(&lw)) != MS_DONE) { double ratio = 0; - pointObj point; + pointObj point = {0,0,0,0}; // initialize if (lw.lineIsRing && lw.pos==lw.line->numpoints-1) { point = newShape->line[i].point[0]; @@ -261,8 +261,8 @@ while ((res = nextLineWindow(&lw)) != MS_DONE) { double sum_x=0, sum_y=0, sum = 0; - pointObj point; - int k = 0; + pointObj point = {0,0,0,0}; // initialize + int k = 0; if (res == MS_FALSE) { /* invalid window */ msAddPointToLine(&newShape->line[j], diff -Nru mapserver-7.6.2/mapstring.c mapserver-7.6.4/mapstring.c --- mapserver-7.6.2/mapstring.c 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/mapstring.c 2021-07-12 20:16:21.000000000 +0000 @@ -2184,7 +2184,7 @@ iconv_t cd = NULL; const char *inp; char *outp, *out = NULL; - size_t len, bufsize, bufleft, iconv_status; + size_t len, bufsize, bufleft; int i; if( !layer->encoding || !*layer->encoding || !strcasecmp(layer->encoding, "UTF-8")) @@ -2198,6 +2198,7 @@ } for(i=0;i numvalues; i++) { + int failedIconv = FALSE; if(!shape->values[i] || (len = strlen(shape->values[i]))==0) { continue; /* Nothing to do */ } @@ -2210,15 +2211,18 @@ outp = out; bufleft = bufsize; - iconv_status = -1; while (len > 0) { - iconv_status = iconv(cd, (char**)&inp, &len, &outp, &bufleft); - if(iconv_status == -1) { - msFree(out); - continue; /* silently ignore failed conversions */ + const size_t iconv_status = iconv(cd, (char**)&inp, &len, &outp, &bufleft); + if(iconv_status == (size_t)(-1)) { + failedIconv = TRUE; + break; } } + if( failedIconv ) { + msFree(out); + continue; /* silently ignore failed conversions */ + } out[bufsize - bufleft] = '\0'; msFree(shape->values[i]); shape->values[i] = out; diff -Nru mapserver-7.6.2/maptemplate.c mapserver-7.6.4/maptemplate.c --- mapserver-7.6.2/maptemplate.c 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/maptemplate.c 2021-07-12 20:16:21.000000000 +0000 @@ -1728,8 +1728,8 @@ } if(labelposvalid == MS_TRUE) { - pointObj p1; - pointObj p2; + pointObj p1 = {0,0,0,0}; // initialize + pointObj p2 = {0,0,0,0}; int label_offset_x, label_offset_y; labelObj *label=NULL; label_bounds lbounds; @@ -3636,12 +3636,15 @@ while(fgets(line, MS_BUFFER_LENGTH, stream) != NULL) outbuf = msStringConcatenate(outbuf, line); fclose(stream); + stream = NULL; } /* clear any data associated with the join */ msFreeCharArray(join->values, join->numitems); join->values = NULL; + if(stream) fclose(stream); + return(outbuf); } @@ -4219,8 +4222,10 @@ if(strchr(line, '[') != NULL) { tmpline = processLine(mapserv, line, stream, mode); - if(!tmpline) + if(!tmpline) { + fclose(stream); return MS_FAILURE; + } if(papszBuffer) { if(nBufferSize <= (int)(nCurrentSize + strlen(tmpline) + 1)) { diff -Nru mapserver-7.6.2/mapwcs20.c mapserver-7.6.4/mapwcs20.c --- mapserver-7.6.2/mapwcs20.c 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/mapwcs20.c 2021-07-12 20:16:21.000000000 +0000 @@ -3602,6 +3602,7 @@ status = msWCSGetCapabilities20_CoverageSummary( map, params, psDoc, psNode, layer ); if(status != MS_SUCCESS) { + msFree(validated_language); xmlFreeDoc(psDoc); xmlCleanupParser(); return msWCSException(map, "Internal", "mapserv", params->version); diff -Nru mapserver-7.6.2/mapwcs.c mapserver-7.6.4/mapwcs.c --- mapserver-7.6.2/mapwcs.c 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/mapwcs.c 2021-07-12 20:16:21.000000000 +0000 @@ -1514,8 +1514,10 @@ /* -------------------------------------------------------------------- */ char *layer_proj = msGetProjectionString( &(layer->projection) ); - if (msLoadProjectionString(&(map->projection), layer_proj) != 0) + if (msLoadProjectionString(&(map->projection), layer_proj) != 0) { + msFree(layer_proj); return msWCSException( map, NULL, NULL, params->version ); + } free( layer_proj ); layer_proj = NULL; diff -Nru mapserver-7.6.2/mapwfs.c mapserver-7.6.4/mapwfs.c --- mapserver-7.6.2/mapwfs.c 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/mapwfs.c 2021-07-12 20:16:21.000000000 +0000 @@ -2202,15 +2202,12 @@ status = msLoadProjectionString(&(map->projection), pszMapSRS); if (status != 0) { - msSetError(MS_WFSERR, "msLoadProjectionString() failed: %s", - "msWFSGetFeature()", pszMapSRS); + msSetError(MS_WFSERR, "msLoadProjectionString() failed: %s", "msWFSGetFeature()", pszMapSRS); msFree(pszMapSRS); - return msWFSException(map, "mapserv", MS_OWS_ERROR_NO_APPLICABLE_CODE, - paramsObj->pszVersion); + return msWFSException(map, "mapserv", MS_OWS_ERROR_NO_APPLICABLE_CODE, paramsObj->pszVersion); } - msFree(pszMapSRS); - } + msFree(pszMapSRS); /*make sure that the layer projection is loaded. It could come from a ows/wfs_srs metadata*/ @@ -5182,10 +5179,12 @@ } /* these are unsupported requests. Just set the */ /* request value and return; */ - else if (msWFSGetIndexUnsupportedOperation(psOperation->pszValue) >= 0) { + else { int idx = msWFSGetIndexUnsupportedOperation(psOperation->pszValue); - wfsparams->pszRequest = msStrdup(wfsUnsupportedOperations[idx]); - break; + if( idx >= 0 ) { + wfsparams->pszRequest = msStrdup(wfsUnsupportedOperations[idx]); + break; + } } } } diff -Nru mapserver-7.6.2/mapwmslayer.c mapserver-7.6.4/mapwmslayer.c --- mapserver-7.6.2/mapwmslayer.c 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/mapwmslayer.c 2021-07-12 20:16:21.000000000 +0000 @@ -430,7 +430,7 @@ int bFlipAxisOrder = MS_FALSE; const char *pszTmp; int bIsEssential = MS_FALSE; - + if (lp->connectiontype != MS_WMS) { msSetError(MS_WMSCONNERR, "Call supported only for CONNECTIONTYPE WMS", "msBuildWMSLayerURL()"); @@ -619,24 +619,30 @@ char* pszEPSGCodeFromLayer = NULL; msOWSGetEPSGProj(&(lp->projection), NULL, "MO", MS_TRUE, &pszEPSGCodeFromLayer); if (pszEPSGCodeFromLayer == NULL || strcasecmp(pszEPSG, pszEPSGCodeFromLayer) != 0) { - char *ows_srs; - msOWSGetEPSGProj(NULL,&(lp->metadata), "MO", MS_FALSE, &ows_srs); + char *ows_srs = NULL; + msOWSGetEPSGProj(NULL, &(lp->metadata), "MO", MS_FALSE, &ows_srs); /* no need to set lp->proj if it is already set and there is only one item in the _srs metadata for this layer - we will assume the projection block matches the _srs metadata (the search for ' ' in ows_srs is a test to see if there are multiple EPSG: codes) */ if( lp->projection.numargs == 0 || ows_srs == NULL || (strchr(ows_srs,' ') != NULL) ) { - msFree(ows_srs); if (strncasecmp(pszEPSG, "EPSG:", 5) == 0) { char szProj[20]; snprintf(szProj, sizeof(szProj), "init=epsg:%s", pszEPSG+5); - if (msLoadProjectionString(&(lp->projection), szProj) != 0) + if (msLoadProjectionString(&(lp->projection), szProj) != 0) { + msFree(pszEPSGCodeFromLayer); + msFree(ows_srs); return MS_FAILURE; + } } else { - if (msLoadProjectionString(&(lp->projection), pszEPSG) != 0) + if (msLoadProjectionString(&(lp->projection), pszEPSG) != 0) { + msFree(pszEPSGCodeFromLayer); + msFree(ows_srs); return MS_FAILURE; + } } } + msFree(ows_srs); } msFree(pszEPSGCodeFromLayer); } @@ -734,8 +740,8 @@ msRectIntersect( &bbox, &layer_rect ); - bbox_width = ceil((bbox.maxx - bbox.minx) / cellsize); - bbox_height = ceil((bbox.maxy - bbox.miny) / cellsize); + bbox_width = round((bbox.maxx - bbox.minx) / cellsize); + bbox_height = round((bbox.maxy - bbox.miny) / cellsize); /* Force going through the resampler if we're going to receive a clipped BBOX (#4931) */ if(msLayerGetProcessingKey(lp, "RESAMPLE") == NULL) { diff -Nru mapserver-7.6.2/mapxbase.c mapserver-7.6.4/mapxbase.c --- mapserver-7.6.2/mapxbase.c 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/mapxbase.c 2021-07-12 20:16:21.000000000 +0000 @@ -192,6 +192,7 @@ pabyBuf = (uchar *) msSmallMalloc(500); if( VSIFReadL( pabyBuf, 32, 1, psDBF->fp ) != 1 ) { + VSIFCloseL( psDBF->fp ); msFree(psDBF); msFree(pabyBuf); return( NULL ); @@ -203,6 +204,13 @@ psDBF->nHeaderLength = nHeadLen = pabyBuf[8] + pabyBuf[9]*256; psDBF->nRecordLength = nRecLen = pabyBuf[10] + pabyBuf[11]*256; + if (nHeadLen <= 32) { + VSIFCloseL( psDBF->fp ); + msFree(psDBF); + msFree(pabyBuf); + return( NULL ); + } + psDBF->nFields = nFields = (nHeadLen - 32) / 32; psDBF->pszCurrentRecord = (char *) msSmallMalloc(nRecLen); @@ -217,6 +225,7 @@ if( VSIFReadL( pabyBuf, nHeadLen - 32, 1, psDBF->fp ) != 1 ) { msFree(psDBF->pszCurrentRecord); + VSIFCloseL( psDBF->fp ); msFree(psDBF); msFree(pabyBuf); return( NULL ); diff -Nru mapserver-7.6.2/MIGRATION_GUIDE.txt mapserver-7.6.4/MIGRATION_GUIDE.txt --- mapserver-7.6.2/MIGRATION_GUIDE.txt 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/MIGRATION_GUIDE.txt 2021-07-12 20:16:21.000000000 +0000 @@ -8,7 +8,7 @@ For developers: -The master copy of the MIGRATION_GUIDE is now located in the root of the +The main copy of the MIGRATION_GUIDE is now located in the root of the /MapServer/MapServer-documentation source tree ( https://github.com/MapServer/MapServer-documentation ). Developers are welcome and encouraged to edit/update the guide in the documentation tree directly. diff -Nru mapserver-7.6.2/README.rst mapserver-7.6.4/README.rst --- mapserver-7.6.2/README.rst 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/README.rst 2021-07-12 20:16:21.000000000 +0000 @@ -69,7 +69,7 @@ :: - Copyright (c) 2008-2020 Open Source Geospatial Foundation. + Copyright (c) 2008-2021 Open Source Geospatial Foundation. Copyright (c) 1996-2008 Regents of the University of Minnesota. Permission is hereby granted, free of charge, to any person obtaining a copy @@ -91,7 +91,7 @@ SOFTWARE. -.. |Build Status| image:: https://travis-ci.com/MapServer/MapServer.svg?branch=master +.. |Build Status| image:: https://travis-ci.com/MapServer/MapServer.svg?branch=main :target: https://travis-ci.com/MapServer/MapServer .. |Appveyor Build Status| image:: https://ci.appveyor.com/api/projects/status/vw1n07095a8bg23u?svg=true diff -Nru mapserver-7.6.2/renderers/agg/include/agg_rendering_buffer.h mapserver-7.6.4/renderers/agg/include/agg_rendering_buffer.h --- mapserver-7.6.2/renderers/agg/include/agg_rendering_buffer.h 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/renderers/agg/include/agg_rendering_buffer.h 2021-07-12 20:16:21.000000000 +0000 @@ -128,7 +128,7 @@ private: //-------------------------------------------------------------------- - T* m_buf; // Pointer to renrdering buffer + T* m_buf; // Pointer to rendering buffer T* m_start; // Pointer to first pixel depending on stride unsigned m_width; // Width in pixels unsigned m_height; // Height in pixels @@ -258,7 +258,7 @@ private: //-------------------------------------------------------------------- - T* m_buf; // Pointer to renrdering buffer + T* m_buf; // Pointer to rendering buffer pod_array m_rows; // Pointers to each row of the buffer unsigned m_width; // Width in pixels unsigned m_height; // Height in pixels diff -Nru mapserver-7.6.2/scripts/vagrant/packages.sh mapserver-7.6.4/scripts/vagrant/packages.sh --- mapserver-7.6.2/scripts/vagrant/packages.sh 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/scripts/vagrant/packages.sh 2021-07-12 20:16:21.000000000 +0000 @@ -22,6 +22,6 @@ libprotobuf-dev libprotobuf-c0-dev protobuf-c-compiler libharfbuzz-dev gdal-bin \ curl sqlite3 -curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py +curl https://bootstrap.pypa.io/pip/2.7/get-pip.py -o get-pip.py python get-pip.py pip install -U -r /vagrant/msautotest/requirements.txt diff -Nru mapserver-7.6.2/textlayout.c mapserver-7.6.4/textlayout.c --- mapserver-7.6.2/textlayout.c 2020-12-07 20:09:40.000000000 +0000 +++ mapserver-7.6.4/textlayout.c 2021-07-12 20:16:21.000000000 +0000 @@ -214,7 +214,7 @@ } #endif -int WARN_UNUSED check_single_font(fontSetObj *fontset, char *fontkey, text_run *run, TextInfo *glyphs, int ignore_missing) { +static int check_single_font(fontSetObj *fontset, char *fontkey, text_run *run, TextInfo *glyphs, int ignore_missing) { int i; face_element *fcache = NULL; if(fontset && fontkey) { @@ -228,16 +228,23 @@ run->face = fcache; if(UNLIKELY(!fcache)) return MS_FAILURE; for(i=0; ilength; i++) { - int codepoint = msGetGlyphIndex(fcache, glyphs->unicodes[run->offset+i]); + unsigned int codepoint = msGetGlyphIndex(fcache, glyphs->unicodes[run->offset+i]); if(codepoint || ignore_missing) + { + if( codepoint == 0 ) + { + msDebug("Unable to find glyph for codepoint %u. Using ? as fallback.\n", glyphs->unicodes[run->offset+i]); + codepoint = msGetGlyphIndex(fcache, '?'); + } glyphs->codepoints[run->offset+i] = codepoint; + } else return MS_FAILURE; } return MS_SUCCESS; } -int WARN_UNUSED get_face_for_run(fontSetObj *fontset, char *fontlist, text_run *run, TextInfo *glyphs) { +static int get_face_for_run(fontSetObj *fontset, char *fontlist, text_run *run, TextInfo *glyphs) { char *startfont, *endfont; int ok; #if defined(USE_HARFBUZZ) && defined(USE_FRIBIDI)