[gdal] 02/07: New upstream version 2.2.1~rc1+dfsg

Bas Couwenberg sebastic at debian.org
Fri Jun 23 16:12:52 UTC 2017


This is an automated email from the git hooks/post-receive script.

sebastic pushed a commit to branch experimental-2.2
in repository gdal.

commit 1dd219ffea422e0c6504b6c2b740c4abf5668f3a
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Fri Jun 23 14:47:47 2017 +0200

    New upstream version 2.2.1~rc1+dfsg
---
 GDALmake.opt.in                                    |   4 +-
 NEWS                                               | 177 +++++
 VERSION                                            |   2 +-
 alg/gdal_rpc.cpp                                   |  18 +-
 alg/llrasterize.cpp                                |   8 +-
 apps/gdal_rasterize_lib.cpp                        |  17 +-
 apps/ogr2ogr_lib.cpp                               |  43 +-
 ci/travis/gcc48_stdcpp11/before_install.sh         |   5 +-
 ci/travis/gcc48_stdcpp11/install.sh                |   3 +-
 .../gcc52_stdcpp14_sanitize/before_install.sh      |   5 +-
 ci/travis/gcc52_stdcpp14_sanitize/install.sh       |   3 +-
 ci/travis/precise_clang/before_install.sh          |   5 +-
 ci/travis/precise_clang/install.sh                 |   3 +-
 ci/travis/python3/before_install.sh                |   5 +-
 ci/travis/python3/install.sh                       |   3 +-
 configure                                          |  70 +-
 configure.ac                                       |  18 +-
 frmts/adrg/srpdataset.cpp                          |   8 +-
 frmts/aigrid/gridlib.c                             |  30 +-
 frmts/ceos/ceosopen.c                              |  14 +-
 frmts/cosar/cosar_dataset.cpp                      |  13 +-
 frmts/e00grid/GNUmakefile                          |   2 +
 frmts/e00grid/e00read.c                            |  34 +-
 frmts/envisat/envisatdataset.cpp                   |  11 +-
 frmts/georaster/georaster_dataset.cpp              |  32 +-
 frmts/georaster/georaster_priv.h                   |   4 +-
 frmts/georaster/georaster_wrapper.cpp              |  15 +-
 frmts/gtiff/geotiff.cpp                            |  15 +-
 frmts/gtiff/gt_citation.cpp                        |  40 +-
 frmts/gtiff/libtiff/tif_dirread.c                  |   5 +
 frmts/gtiff/tif_float.c                            |   6 +-
 frmts/gxf/gxfopen.c                                |  28 +-
 frmts/iris/irisdataset.cpp                         |   4 +-
 frmts/iso8211/ddfsubfielddefn.cpp                  |   8 +-
 frmts/netcdf/netcdfdataset.cpp                     |  71 +-
 frmts/northwood/grcdataset.cpp                     |   8 +-
 frmts/northwood/northwood.cpp                      |   7 +-
 frmts/pds/nasakeywordhandler.cpp                   |   4 +-
 frmts/pds/vicarkeywordhandler.cpp                  |  47 +-
 frmts/raw/fastdataset.cpp                          |  67 +-
 frmts/vrt/pixelfunctions.cpp                       |   8 +-
 frmts/vrt/vrtdataset.cpp                           |  19 +-
 frmts/webp/webpdataset.cpp                         |  11 +-
 frmts/xyz/xyzdataset.cpp                           |   3 +-
 gcore/gdal_version.h                               |   8 +-
 gcore/gdaldataset.cpp                              |   4 +-
 gcore/gdaljp2structure.cpp                         |  25 +-
 gcore/gdalrasterband.cpp                           |   4 +-
 m4/acinclude.m4                                    |  26 +-
 man/man1/gdal-config.1                             |   2 +-
 man/man1/gdal2tiles.1                              |   2 +-
 man/man1/gdal_calc.1                               |   2 +-
 man/man1/gdal_contour.1                            |   2 +-
 man/man1/gdal_edit.1                               |   2 +-
 man/man1/gdal_fillnodata.1                         |   2 +-
 man/man1/gdal_grid.1                               |   2 +-
 man/man1/gdal_merge.1                              |   2 +-
 man/man1/gdal_pansharpen.1                         |   2 +-
 man/man1/gdal_polygonize.1                         |   2 +-
 man/man1/gdal_proximity.1                          |   2 +-
 man/man1/gdal_rasterize.1                          |   2 +-
 man/man1/gdal_retile.1                             |   2 +-
 man/man1/gdal_sieve.1                              |   2 +-
 man/man1/gdal_translate.1                          |   2 +-
 man/man1/gdal_utilities.1                          |   2 +-
 man/man1/gdaladdo.1                                |   2 +-
 man/man1/gdalbuildvrt.1                            |   2 +-
 man/man1/gdalcompare.1                             |   2 +-
 man/man1/gdaldem.1                                 |   2 +-
 man/man1/gdalinfo.1                                |   2 +-
 man/man1/gdallocationinfo.1                        |   2 +-
 man/man1/gdalmanage.1                              |   2 +-
 man/man1/gdalmove.1                                |   2 +-
 man/man1/gdalsrsinfo.1                             |   2 +-
 man/man1/gdaltindex.1                              |   2 +-
 man/man1/gdaltransform.1                           |   2 +-
 man/man1/gdalwarp.1                                |   2 +-
 man/man1/gnm_utilities.1                           |   2 +-
 man/man1/gnmanalyse.1                              |   2 +-
 man/man1/gnmmanage.1                               |   2 +-
 man/man1/nearblack.1                               |   2 +-
 man/man1/ogr2ogr.1                                 |   2 +-
 man/man1/ogr_utilities.1                           |   2 +-
 man/man1/ogrinfo.1                                 |   2 +-
 man/man1/ogrlineref.1                              |   2 +-
 man/man1/ogrmerge.1                                |   2 +-
 man/man1/ogrtindex.1                               |   2 +-
 man/man1/pct2rgb.1                                 |   2 +-
 man/man1/rgb2pct.1                                 |   2 +-
 ogr/ogr_srs_esri.cpp                               |  12 +-
 ogr/ogrcurvecollection.cpp                         |  28 +-
 ogr/ogrgeometry.cpp                                |   8 +-
 ogr/ogrgeometryfactory.cpp                         |   3 +-
 ogr/ogrmultisurface.cpp                            |   7 +-
 ogr/ogrpgeogeometry.cpp                            |  13 +-
 ogr/ogrpolygon.cpp                                 |   3 +-
 ogr/ogrsf_frmts/dgn/dgnread.cpp                    |  11 +-
 ogr/ogrsf_frmts/dxf/ogr_autocad_services.cpp       |   6 +-
 ogr/ogrsf_frmts/dxf/ogrdxf_blockmap.cpp            |  12 +-
 ogr/ogrsf_frmts/dxf/ogrdxflayer.cpp                |  23 +-
 ogr/ogrsf_frmts/geojson/libjson/json_object.c      |   4 +-
 ogr/ogrsf_frmts/geojson/ogresrijsonreader.cpp      |  10 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsondriver.cpp       |  24 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsonutils.cpp        |  19 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.cpp       |  34 +-
 ogr/ogrsf_frmts/georss/ogrgeorsslayer.cpp          |   6 +-
 ogr/ogrsf_frmts/gml/gmlreader.cpp                  |   7 +-
 ogr/ogrsf_frmts/gml/gmlreader.h                    |   4 +-
 ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp   |  69 +-
 ogr/ogrsf_frmts/gpkg/ogrgeopackagetablelayer.cpp   |  84 +--
 ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.cpp      |   6 +-
 ogr/ogrsf_frmts/gtm/gtm.cpp                        |   8 +-
 ogr/ogrsf_frmts/ili/ili1reader.cpp                 |  63 +-
 ogr/ogrsf_frmts/ili/ili2reader.cpp                 |  92 ++-
 ogr/ogrsf_frmts/ili/ogrili1datasource.cpp          |  11 +-
 ogr/ogrsf_frmts/ili/ogrili2datasource.cpp          |  11 +-
 ogr/ogrsf_frmts/jml/ogrjmllayer.cpp                |   6 +-
 ogr/ogrsf_frmts/kml/kml.cpp                        |  11 +-
 ogr/ogrsf_frmts/kml/kmlnode.cpp                    |  14 +-
 ogr/ogrsf_frmts/kml/kmlnode.h                      |   4 +-
 ogr/ogrsf_frmts/mitab/mitab_coordsys.cpp           |   4 +-
 ogr/ogrsf_frmts/mitab/mitab_feature.cpp            |  10 +-
 ogr/ogrsf_frmts/mitab/mitab_feature_mif.cpp        |  10 +-
 ogr/ogrsf_frmts/mitab/mitab_mapcoordblock.cpp      |   2 +-
 ogr/ogrsf_frmts/mitab/mitab_miffile.cpp            |  15 +-
 ogr/ogrsf_frmts/mitab/mitab_spatialref.cpp         |   4 +-
 ogr/ogrsf_frmts/mitab/mitab_tabfile.cpp            |   4 +-
 ogr/ogrsf_frmts/mongodb/mongocxx_headers.h         |   2 +-
 ogr/ogrsf_frmts/mysql/ogr_mysql.h                  |   6 +-
 ogr/ogrsf_frmts/nas/nasreader.cpp                  |   7 +-
 ogr/ogrsf_frmts/ntf/ntf.h                          |  14 +-
 ogr/ogrsf_frmts/ntf/ntf_codelist.cpp               |  15 +-
 ogr/ogrsf_frmts/ntf/ntf_estlayers.cpp              |  11 +-
 ogr/ogrsf_frmts/ntf/ntf_generic.cpp                |  52 +-
 ogr/ogrsf_frmts/ntf/ntf_raster.cpp                 |  60 +-
 ogr/ogrsf_frmts/ntf/ntffilereader.cpp              | 210 ++++--
 ogr/ogrsf_frmts/ntf/ogrntfdatasource.cpp           |  11 +-
 ogr/ogrsf_frmts/openair/ogropenairdriver.cpp       |   3 +-
 ogr/ogrsf_frmts/pds/ogrpdsdatasource.cpp           |  16 +-
 ogr/ogrsf_frmts/pg/ogrpgdatasource.cpp             |   4 +-
 ogr/ogrsf_frmts/plscenes/GNUmakefile               |   2 +-
 ogr/ogrsf_frmts/plscenes/drv_plscenes.html         |   8 +-
 ogr/ogrsf_frmts/plscenes/drv_plscenes_v0.html      | 202 ------
 ogr/ogrsf_frmts/plscenes/makefile.vc               |   2 +-
 ogr/ogrsf_frmts/plscenes/ogr_plscenes.h            |  98 +--
 ogr/ogrsf_frmts/plscenes/ogrplscenesdataset.cpp    | 578 ----------------
 ogr/ogrsf_frmts/plscenes/ogrplscenesdriver.cpp     |  12 +-
 ogr/ogrsf_frmts/plscenes/ogrplsceneslayer.cpp      | 766 ---------------------
 ogr/ogrsf_frmts/rec/ll_recio.cpp                   |   4 +-
 ogr/ogrsf_frmts/rec/ogrrecdatasource.cpp           |   7 +-
 ogr/ogrsf_frmts/segukooa/ogrsegukooalayer.cpp      |   6 +-
 ogr/ogrsf_frmts/selafin/io_selafin.cpp             |   5 +-
 ogr/ogrsf_frmts/selafin/ogrselafindatasource.cpp   |   5 +-
 ogr/ogrsf_frmts/shape/shape2ogr.cpp                |   5 +-
 ogr/ogrsf_frmts/tiger/ogr_tiger.h                  |   4 +-
 ogr/ogrsf_frmts/tiger/ogrtigerdatasource.cpp       |  11 +-
 ogr/ogrsf_frmts/tiger/tigeraltname.cpp             |   4 +-
 ogr/ogrsf_frmts/tiger/tigercompletechain.cpp       |  11 +-
 ogr/ogrsf_frmts/tiger/tigerfilebase.cpp            |   4 +-
 ogr/ogrsf_frmts/tiger/tigerpoint.cpp               |   4 +-
 ogr/ogrsf_frmts/tiger/tigerpolygon.cpp             |  15 +-
 ogr/ogrsf_frmts/vfk/vfkdatablock.cpp               |   4 +-
 ogr/ogrsf_frmts/vfk/vfkreader.cpp                  |   3 +-
 port/cpl_config.h.in                               |   5 +-
 port/cpl_error.cpp                                 |  10 +-
 port/cpl_minixml.cpp                               | 115 ++--
 port/cpl_port.h                                    |   7 +-
 port/cpl_string.cpp                                |   7 +-
 port/cpl_time.cpp                                  |  17 +-
 port/cpl_vsi.h                                     |   3 +-
 port/cpl_vsil.cpp                                  |   5 +-
 port/cpl_vsil_abstract_archive.cpp                 |   4 +-
 port/cpl_vsil_curl.cpp                             | 141 +++-
 port/cpl_vsil_curl_streaming.cpp                   |   8 +-
 port/cpl_vsil_gzip.cpp                             |   8 +-
 port/cpl_vsil_sparsefile.cpp                       |   5 +-
 port/cpl_vsil_subfile.cpp                          |  13 +-
 port/cpl_vsil_unix_stdio_64.cpp                    |   3 +-
 swig/csharp/gdal/Gdal.cs                           |   5 +
 swig/csharp/gdal/GdalPINVOKE.cs                    |   3 +
 swig/csharp/gdal/gdal_wrap.cpp                     |  26 +
 swig/include/cpl.i                                 |   4 +-
 swig/include/perl/band.i                           |  31 +-
 swig/include/perl/gdal_perl.i                      |   4 +-
 swig/include/perl/ogr_perl.i                       |   2 +-
 swig/include/python/gdal_python.i                  |  10 +-
 swig/include/python/typemaps_python.i              |  13 +-
 swig/perl/Makefile.PL                              |  25 +
 swig/perl/gdal_wrap.cpp                            |  74 +-
 swig/perl/lib/Geo/GDAL.pm                          |   5 +-
 swig/perl/lib/Geo/OGR.pm                           |   2 +-
 swig/python/extensions/gdal_array_wrap.cpp         |  22 +
 swig/python/extensions/gdal_wrap.cpp               | 405 +++++++++++
 swig/python/extensions/ogr_wrap.cpp                |  77 +++
 swig/python/osgeo/gdal.py                          |  12 +-
 swig/python/samples/validate_gpkg.py               |   8 +-
 swig/python/scripts/ogrmerge.py                    |  18 +-
 swig/python/setup.py                               |   2 +-
 198 files changed, 2499 insertions(+), 2483 deletions(-)

diff --git a/GDALmake.opt.in b/GDALmake.opt.in
index 46a10a8..4af4653 100644
--- a/GDALmake.opt.in
+++ b/GDALmake.opt.in
@@ -119,9 +119,9 @@ GDAL_INCLUDE	=	-I$(GDAL_ROOT)/port -I$(GDAL_ROOT)/gcore \
 
 # libtool targets and help variables
 LIBGDAL	:=		libgdal.la
-LIBGDAL_CURRENT	:=	22
+LIBGDAL_CURRENT	:=	23
 LIBGDAL_REVISION	:=	0
-LIBGDAL_AGE	:=	2
+LIBGDAL_AGE	:=	3
 
 # native build targets and variables
 GDAL_VER	=	@GDAL_VER@
diff --git a/NEWS b/NEWS
index 8258afd..dcae136 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,180 @@
+= GDAL/OGR 2.2.1 Release Notes = 
+
+The 2.2.1 release is a bug fix release.
+
+== Build ==
+ * fix compilation without BIGTIFF_SUPPORT (#6890)
+ * configure: detect if std::isnan() is available. Helps compilation on some MacOSX setups, combined together --without-cpp11. Refs https://github.com/macports/macports-ports/pull/480
+ * fix compilation against ancient Linux kernel headers (#6909)
+ * fix detection of 64bit file API with clang 5 (#6912)
+ * configure: use .exe extension when building with mingw64* toolchains (fixes #6919)
+ * mongoDB: compilation fix on Windows
+
+== Port ==
+
+* /vsicurl/: fix occasional inappropriate failures in Read() with some combinations of initial offset, file size and read request size (#6901)
+* Add a VSICurlClearCache() function (bound to SWIG as gdal.VSICurlClearCache()) to be able to clear /vsicurl/ related caches (#6937)
+
+== Algorithms ==
+
+* GDALRasterize(): avoid hang in some cases with all_touched option (#5580)
+* gdal_rasterize: fix segfault when rasterizing onto a raster with RPC (#6922)
+
+== GDAL utilities ==
+
+* ogr_merge.py: fix '-single -o out.shp in.shp' case (#6888)
+
+== GDAL drivers ==
+
+AIGRID driver:
+  * fix handling on raw 32-bit AIG blocks
+
+ENVISAT driver:
+* fix 2.2 regression in initialization of members of MerisL2FlagBand. (#6929)
+
+GeoRaster driver:
+ * Fix memory allocation failure (#6884)
+ * add support for JP2-F in BLOB compression (corrections on geo-reference) (#6861)
+
+GPKG driver:
+ * avoid corruption of gpkg_tile_matrix when building overviews, down to a level where they are smaller than the tile size (#6932)
+
+GTIFF driver:
+* Internal libtiff: fix libtiff 4.0.8 regression regarding creating of single strip uncompressed TIFF files (#6924)
+
+netCDF driver:
+ * add support for radian and microradian units for geostationnary projection (https://github.com/OSGeo/gdal/pull/220)
+
+NWT_GRC driver:
+ * Fix handling of alpha values in GRC color table (#6905)
+ * Handle case of 0-len GRC class names (#6907)
+
+VRT driver:
+ * speed-up SerializeToXML() in case of big number of bands
+
+XYZ driver:
+ * fix 2.2 regression where the driver hangs on some dataset with missing samples (#6934)
+
+== OGR utilities ==
+
+* ogr2ogr/GDALVectorTranslate(): fix crash when using -f PDF -a_srs (#6920)
+
+== OGR drivers ==
+
+GeoJSON driver:
+ * ESRIJson: avoid endless looping on servers that don't support resultOffset (#6895)
+ * ESRIJson: use 'latestWkid' in priority over 'wkid' when reading 'spatialReference' (https://github.com/OSGeo/gdal/pull/218)
+ * GeoJSON writer: accept writing ZM or M geometry by dropping the M component (#6935)
+
+GPKG driver:
+ * make driver robust to difference of cases between table_name in gpkg_contents/gpkg_geometry_columns and name in sqlite_master (#6916)
+ 
+MITAB driver:
+ * recognize Reseau_National_Belge_1972 / EPSG:31370 on writing (#6903)
+ 
+MySQL driver:
+ * fix compilation issue with Arch Linux and mariadb 10.1.23 (fixes #6899)
+
+PG driver:
+ * do not be confused by a 'geometry' table in a non-PostGIS enabled detabase (#6896)
+
+PLScenes:
+ * remove support for V0. Deprecate V1 API. Only Data V1 is supported ( #6933)
+ 
+== Perl bindings ==
+
+* Backport the fix to #6142 Install man page according to GDALmake.opt if INSTALL_BASE is set.
+* always return something from non-void functions (#6898)
+
+== Python bindings ==
+
+* Accept callback = 0 since SWIG generates it as the default argument of BandRasterIONumPy(). Fixes https://github.com/OSGeo/gdal/pull/219
+* Fix 2.2 regression preventing use of callback function in Band.ComputeStatistics() (#6927)
+ 
+== Security oriented fixes ==
+
+Note: this is only a very partial backport of more extensive fixes done in GDAL trunk. Credit to OSS-Fuzz for all of them (some have been found locally, so no related ticket)
+
+* Fix CPLErrorSetState to ensure it does not write beyond DEFAULT_LAST_ERR_MSG_SIZE and correctly null-terminates last message. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1529.
+* Open() and Stat() methods of a number of virtual file systems: check that the filename starts with the full prefix. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1543.
+* VRT pixel functions: fix crash with 'complex' when source count is < 2. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1549
+* OpenAIR: fix potential out-of-buffer read if we need to ingest 30000 bytes
+* Several fixes in importFromWkb() and importFromWkt()
+* GDALDataset and GDALRasterBand::ReportError(): fix crash if dataset name has a % character
+* NASAKeywordHandler::SkipWhite(): fix out of bounds read
+* MITAB: ParseTABFileFields(): fix out of bounds read.
+* MITAB: ParseMIFHeader(): fix memory leak and out-of-bounds read on corrupted file
+* MITAB: ParseMIFHeader(): fix memory leaks on corrupted files
+* MITAB: avoid potentially veryyyy long loop when stroking arcs. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1644
+* MITAB: avoid heap-buffer-overflow in MITABCoordSys2TABProjInfo(). Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1653
+* OSARDataset::Open(): fix crash if pOpenInfo->fpL == NULL. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1565
+* OGRESRIJSONReadPolygon(): fix crash in error code path
+* DXF: prevent null ptr deref and out-of-bounds read on corrupted file
+* DXF: TranslateSPLINE(): sanitize integer values read to avoid int overflow. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1843
+* KML::unregisterLayerIfMatchingThisNode(): use memmove() instead of memcpy(). Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1580
+* KML: fix crash on weird structure with recursively empty folders. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1591
+* KML: fix null ptr dereference on corrupted file. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1634
+* OGRCurveCollection::importBodyFromWkb(): fix potential crash if the curve in the collection has not the same dimension has the collection dimension. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1584
+* OGRCompoundCurve::importFromWkb(): avoid potential stack overflow. Fixes https://oss-fuzz.com/v2/testcase-detail/5192348843638784
+* TIGER: fix potential stack buffer overflows. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1586 and 2020
+* TIGER: avoid potential infinite looping. Fixes https://oss-fuzz.com/v2/testcase-detail/4724815883665408
+* VFK: avoid out-of-bounds read. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1596 and 2074
+* CPLHexToBinary(): avoid reading outside of hex2char array on on-ASCII input. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1606
+* OGR PDS: avoid int32 overflow. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=160
+* GeoRSS: fix null pointer dereference on corrupted files. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1611.
+* VSIArchiveFilesystemHandler::SplitFilename(): improve performance. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1597
+* OGRGeometryFactory::organizePolygons(): fix crash on empty polygons. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1620
+* JML: fix null pointer dereference on invalid files. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1622
+* Shape: prevent null ptr deref on truncated MultiPointM geometry. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1638
+* /vsisubfile/: avoid Tell() to return negative values. And make VSIIngestFile() more robust to unsigned overflow. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1642
+* GTM: avoid useless recursive opening of files when provided with a gzip-compressed input. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1650
+* GTiff: fix heap-buffer-overflow. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1677
+* GTiff: avoid heap-buffer-overfow on corrupted State Plane citation. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2050
+* GTiff: avoid potential stack buffer overflow on corrupted Imagine citation. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2105
+* GTiff: prevent heap overflow and fix reading of multi-band band-interleaved 16/24-bit float datasets. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2264
+* GTiff: fix potential infinite loop when parsing some 24-bit float denormalized numbers. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2315
+* Internal libjson-c: fix stack buffer overflow. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1682
+* ILI1/ILI2: fix null pointer dereference when opening filename ','. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1689
+* ILI1: fix various crashes on corrupted files (including, but not limited to, https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1760, 1784, 1926)
+* ILI2: use proper cast operator. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1813
+* ILI2: fix null pointer dereference on corrupted files. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1993
+* ILI2: fix crash due to unhandled exception. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2191
+* morphFromESRI(): fix heap-use-after-free issue. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1690
+* morphFromESRI(): prevent potential null pointer dereference. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1783 and 1867
+* SEGUKOOA: fix inversion of leap year that caused index-out-of-bound reading on day 366 of leap years (2.2 regression). Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1698
+* CPLParseXMLString(): make it error out on invalid XML file even under CPLTurnErrorIntoWarning() mode. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1703.
+* GML / NAS: fix memory leak in error code path, and potential heap-buffer-read-overflow
+* NTF: fix various issues: heap & stack buffer-overflow, null ptr derefs, memory leaks. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1819 , 1820 , 1823, 1833, 1854, 1862, 1910, 1931, 1961, 1990, 1995, 1996, 2003, 2033, 2052, 2077, 2084, 2103, 2130, 2135, 2146, 2166, 2185, 2187, https://oss-fuzz.com/v2/testcase-detail/4696417694121984
+* OGRCreateFromMultiPatch(): avoid assertion on NaN coordinates. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1930
+* GXF: validate nGType to avoid later out-of-bound read in GXFReadRawScanlineFrom(). Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1975
+* GXF: fix int overflow and avoid excessive memory allocation. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2207
+* DGN: prevent heap-buffer-overflow read. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1988
+* COSAR: fix leak of file descriptor. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2019
+* ISO8211: prevent stack buffer oveflow. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2022
+* WEBP: prevent int32 overflow and too large memory allocation. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2059
+* IRIS: fix heap-buffer-overflow in some cases of nDataTypeCode. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2069
+* E00GRID: avoid heap and stack buffer overflows. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2090 , 2182, 2237, 2327
+* VICAR: fix null pointer dereference. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2116
+* VICAR: avoid use-after-free and heap-buffer-overflow. Fixes https://oss-fuzz.com/v2/testcase-detail/4825577427042304
+* VICAR: fix potential endless loop on broken files. Fixes https://oss-fuzz.com/v2/testcase-detail/6261508172414976
+* REC: fix nullptr deref
+* REC: fix potential stack buffer overflow. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2165
+* GDALGetJPEG2000Structure() / DumpGeoTIFFBox(): fix memory leak.
+* DumpGeoTIFFBox(): reject GeoJP2 boxes with a TIFF with band_count > 1
+* DumpJPK2CodeStream(): avoid potentially very long loop
+* GDALGetJPEG2000Structure(): avoid bad performance on corrupted JP2 boxes. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2214
+* GPKG: fix potential heap-buffer overflow in GPkgHeaderFromWKB(). Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2150
+* GPKG: fix potential null ptr deref. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2240
+* GPKG: avoid potential division by zero. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2253
+* SEGUKOOA: prevent read beyond end of buffer. (#6921)
+* SRP: avoid potential stack buffer overflow and excessive memory allocation/processing time
+* CPLUnixTimeToYMDHMS(): avoid potential infinite loop. Fixes https://oss-fuzz.com/v2/testcase-detail/4949567697059840
+* Selafin: fix double frees. Fixes https://oss-fuzz.com/v2/testcase-detail/6429713822121984
+* CEOS: fix heap buffer overflow. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2259
+* CEOS: fix memleak in error code path. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2279
+* FAST: avoid null pointer dereference. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2290
+* netCDF: avoid stack buffer overflow. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2302
+
 GDAL/OGR 2.2.0 Release Notes =
 
 == In a nutshell... ==
diff --git a/VERSION b/VERSION
index ccbccc3..c043eea 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.2.0
+2.2.1
diff --git a/alg/gdal_rpc.cpp b/alg/gdal_rpc.cpp
index 395a683..9e6777d 100644
--- a/alg/gdal_rpc.cpp
+++ b/alg/gdal_rpc.cpp
@@ -56,7 +56,7 @@
 
 // #define DEBUG_VERBOSE_EXTRACT_DEM
 
-CPL_CVSID("$Id: gdal_rpc.cpp 37169 2017-01-18 13:58:09Z rouault $");
+CPL_CVSID("$Id: gdal_rpc.cpp 39050 2017-06-10 20:18:19Z rouault $");
 
 CPL_C_START
 CPLXMLNode *GDALSerializeRPCTransformer( void *pTransformArg );
@@ -1607,6 +1607,7 @@ GDALRPCTransformWholeLineWithDEM( const GDALRPCTransformInfo *psTransform,
     for( int i = 0; i < nPointCount; i++ )
     {
         double dfDEMH = 0.0;
+        const double dfZ_i = padfZ ? padfZ[i] : 0.0;
 
         if( psTransform->eResampleAlg == DRA_Cubic )
         {
@@ -1699,7 +1700,7 @@ GDALRPCTransformWholeLineWithDEM( const GDALRPCTransformInfo *psTransform,
                     {
                         dfDEMH = adfElevData[k_valid_sample];
                         RPCTransformPoint( psTransform, padfX[i], padfY[i],
-                            padfZ[i] + (psTransform->dfHeightOffset + dfDEMH) *
+                            dfZ_i + (psTransform->dfHeightOffset + dfDEMH) *
                                         psTransform->dfHeightScale,
                             padfX + i, padfY + i );
 
@@ -1710,7 +1711,7 @@ GDALRPCTransformWholeLineWithDEM( const GDALRPCTransformInfo *psTransform,
                     {
                         dfDEMH = psTransform->dfDEMMissingValue;
                         RPCTransformPoint( psTransform, padfX[i], padfY[i],
-                            padfZ[i] + (psTransform->dfHeightOffset + dfDEMH) *
+                            dfZ_i + (psTransform->dfHeightOffset + dfDEMH) *
                                         psTransform->dfHeightScale,
                             padfX + i, padfY + i );
 
@@ -1755,7 +1756,7 @@ GDALRPCTransformWholeLineWithDEM( const GDALRPCTransformInfo *psTransform,
         }
 
         RPCTransformPoint( psTransform, padfX[i], padfY[i],
-                            padfZ[i] + (psTransform->dfHeightOffset + dfDEMH) *
+                            dfZ_i + (psTransform->dfHeightOffset + dfDEMH) *
                                         psTransform->dfHeightScale,
                             padfX + i, padfY + i );
 
@@ -2022,7 +2023,7 @@ int GDALRPCTransform( void *pTransformArg, int bDstToSrc,
             }
 
             RPCTransformPoint( psTransform, padfX[i], padfY[i],
-                                padfZ[i] + dfHeight,
+                               (padfZ ? padfZ[i] : 0.0) + dfHeight,
                                 padfX + i, padfY + i );
             panSuccess[i] = TRUE;
         }
@@ -2030,6 +2031,13 @@ int GDALRPCTransform( void *pTransformArg, int bDstToSrc,
         return TRUE;
     }
 
+    if( padfZ == NULL )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Z array should be provided for reverse RPC computation");
+        return FALSE;
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Compute the inverse (pixel/line/height to lat/long).  This      */
 /*      function uses an iterative method from an initial linear        */
diff --git a/alg/llrasterize.cpp b/alg/llrasterize.cpp
index 893ef4e..416509d 100644
--- a/alg/llrasterize.cpp
+++ b/alg/llrasterize.cpp
@@ -39,7 +39,7 @@
 
 #include "gdal_alg.h"
 
-CPL_CVSID("$Id: llrasterize.cpp 36894 2016-12-15 22:57:29Z rouault $");
+CPL_CVSID("$Id: llrasterize.cpp 38818 2017-06-02 12:08:07Z rouault $");
 
 static int llCompareInt(const void *a, const void *b)
 {
@@ -440,7 +440,7 @@ GDALdllImageLineAllTouched( int nRasterXSize, int nRasterYSize,
             }
 
             // Special case for vertical lines.
-            if( floor(dfX) == floor(dfXEnd) )
+            if( floor(dfX) == floor(dfXEnd) || fabs(dfX - dfXEnd) < .01 )
             {
                 if( dfYEnd < dfY )
                 {
@@ -448,7 +448,7 @@ GDALdllImageLineAllTouched( int nRasterXSize, int nRasterYSize,
                     std::swap(dfVariant, dfVariantEnd);
                 }
 
-                const int iX = static_cast<int>(floor(dfX));
+                const int iX = static_cast<int>(floor(dfXEnd));
                 int iY = static_cast<int>(floor(dfY));
                 int iYEnd = (int) floor(dfYEnd);
 
@@ -483,7 +483,7 @@ GDALdllImageLineAllTouched( int nRasterXSize, int nRasterYSize,
                 ( dfXEnd - dfX );  // Per unit change in iX.
 
             // Special case for horizontal lines.
-            if( floor(dfY) == floor(dfYEnd) )
+            if( floor(dfY) == floor(dfYEnd) || fabs(dfY - dfYEnd) < .01 )
             {
                 if( dfXEnd < dfX )
                 {
diff --git a/apps/gdal_rasterize_lib.cpp b/apps/gdal_rasterize_lib.cpp
index 613c305..7555df0 100644
--- a/apps/gdal_rasterize_lib.cpp
+++ b/apps/gdal_rasterize_lib.cpp
@@ -49,7 +49,7 @@
 #include "ogr_core.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: gdal_rasterize_lib.cpp 36682 2016-12-04 20:34:45Z rouault $");
+CPL_CVSID("$Id: gdal_rasterize_lib.cpp 39050 2017-06-10 20:18:19Z rouault $");
 
 /************************************************************************/
 /*                            ArgIsNumeric()                            */
@@ -151,19 +151,22 @@ static CPLErr ProcessLayer(
     if (!bSRSIsSet)
     {
         OGRSpatialReferenceH  hDstSRS = NULL;
-        if( GDALGetProjectionRef( hDstDS ) != NULL )
+        const char* pszProjection = GDALGetProjectionRef( hDstDS );
+        if( pszProjection != NULL && pszProjection[0] != '\0' )
         {
-            char *pszProjection;
-
-            pszProjection = (char *) GDALGetProjectionRef( hDstDS );
-
             hDstSRS = OSRNewSpatialReference(NULL);
-            if( OSRImportFromWkt( hDstSRS, &pszProjection ) != OGRERR_NONE )
+            char* pszProjectionTmp = const_cast<char*>(pszProjection);
+            if( OSRImportFromWkt( hDstSRS, &pszProjectionTmp ) != OGRERR_NONE )
             {
                 OSRDestroySpatialReference(hDstSRS);
                 hDstSRS = NULL;
             }
         }
+        else if( GDALGetMetadata(hDstDS, "RPC") != NULL )
+        {
+            hDstSRS = OSRNewSpatialReference(NULL);
+            OSRSetFromUserInput(hDstSRS, SRS_WKT_WGS84);
+        }
 
         OGRSpatialReferenceH hSrcSRS = OGR_L_GetSpatialRef(hSrcLayer);
         if( hDstSRS != NULL && hSrcSRS != NULL )
diff --git a/apps/ogr2ogr_lib.cpp b/apps/ogr2ogr_lib.cpp
index df845ad..b361106 100644
--- a/apps/ogr2ogr_lib.cpp
+++ b/apps/ogr2ogr_lib.cpp
@@ -61,7 +61,7 @@
 #include "ogrlayerdecorator.h"
 #include "ogrsf_frmts.h"
 
-CPL_CVSID("$Id: ogr2ogr_lib.cpp 37467 2017-02-26 02:21:33Z goatbar $");
+CPL_CVSID("$Id: ogr2ogr_lib.cpp 39040 2017-06-09 21:43:58Z rouault $");
 
 typedef enum
 {
@@ -1506,6 +1506,24 @@ void GDALVectorTranslateWrappedDataset:: ReleaseResultSet(
     delete poResultsSet;
 }
 
+/************************************************************************/
+/*                     OGR2OGRSpatialReferenceHolder                    */
+/************************************************************************/
+
+class OGR2OGRSpatialReferenceHolder
+{
+        OGRSpatialReference* m_poSRS;
+
+    public:
+        OGR2OGRSpatialReferenceHolder() : m_poSRS(NULL) {}
+       ~OGR2OGRSpatialReferenceHolder() { if( m_poSRS) m_poSRS->Release(); }
+
+       void assignNoRefIncrease(OGRSpatialReference* poSRS) {
+           CPLAssert(m_poSRS == NULL);
+           m_poSRS = poSRS;
+       }
+       OGRSpatialReference* get() { return m_poSRS; }
+};
 
 /************************************************************************/
 /*                     GDALVectorTranslateCreateCopy()                  */
@@ -1519,7 +1537,7 @@ static GDALDataset* GDALVectorTranslateCreateCopy(
 {
     const char* const szErrorMsg = "%s not supported by this output driver";
     GDALDataset* poWrkSrcDS = poDS;
-    OGRSpatialReference oOutputSRS; // Leave it in global scope
+    OGR2OGRSpatialReferenceHolder oOutputSRSHolder;
 
     if( psOptions->bSkipFailures )
     {
@@ -1710,8 +1728,9 @@ static GDALDataset* GDALVectorTranslateCreateCopy(
 
     if( psOptions->pszOutputSRSDef )
     {
-        if( oOutputSRS.SetFromUserInput( psOptions->pszOutputSRSDef ) !=
-                                                                OGRERR_NONE )
+        oOutputSRSHolder.assignNoRefIncrease(new OGRSpatialReference());
+        if( oOutputSRSHolder.get()->
+                SetFromUserInput( psOptions->pszOutputSRSDef ) != OGRERR_NONE )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Failed to process SRS definition: %s",
@@ -1719,7 +1738,7 @@ static GDALDataset* GDALVectorTranslateCreateCopy(
             return NULL;
         }
         poWrkSrcDS = GDALVectorTranslateWrappedDataset::New(
-            poDS, &oOutputSRS, psOptions->bTransform);
+            poDS, oOutputSRSHolder.get(), psOptions->bTransform);
         if( poWrkSrcDS == NULL )
             return NULL;
     }
@@ -1878,10 +1897,9 @@ GDALDatasetH GDALVectorTranslate( const char *pszDest, GDALDatasetH hDstDS, int
                                   const GDALVectorTranslateOptions *psOptionsIn, int *pbUsageError )
 
 {
-    OGRSpatialReference oOutputSRS;
+    OGR2OGRSpatialReferenceHolder oOutputSRSHolder;
     OGRSpatialReference oSourceSRS;
     OGRSpatialReference oSpatSRS;
-    OGRSpatialReference *poOutputSRS = NULL;
     OGRSpatialReference *poSourceSRS = NULL;
     OGRSpatialReference* poSpatSRS = NULL;
     bool bAppend = false;
@@ -2264,7 +2282,9 @@ GDALDatasetH GDALVectorTranslate( const char *pszDest, GDALDatasetH hDstDS, int
 /* -------------------------------------------------------------------- */
     if( psOptions->pszOutputSRSDef != NULL )
     {
-        if( oOutputSRS.SetFromUserInput( psOptions->pszOutputSRSDef ) != OGRERR_NONE )
+        oOutputSRSHolder.assignNoRefIncrease(new OGRSpatialReference());
+        if( oOutputSRSHolder.get()->
+                SetFromUserInput( psOptions->pszOutputSRSDef ) != OGRERR_NONE )
         {
             CPLError( CE_Failure, CPLE_AppDefined, "Failed to process SRS definition: %s",
                     psOptions->pszOutputSRSDef );
@@ -2272,7 +2292,6 @@ GDALDatasetH GDALVectorTranslate( const char *pszDest, GDALDatasetH hDstDS, int
             if( hDstDS == NULL ) GDALClose( poODS );
             return NULL;
         }
-        poOutputSRS = &oOutputSRS;
     }
 
 /* -------------------------------------------------------------------- */
@@ -2325,7 +2344,7 @@ GDALDatasetH GDALVectorTranslate( const char *pszDest, GDALDatasetH hDstDS, int
     {
         poGCPCoordTrans = new GCPCoordTransformation( psOptions->nGCPCount, psOptions->pasGCPs,
                                                       psOptions->nTransformOrder,
-                                                      poSourceSRS ? poSourceSRS : poOutputSRS );
+                                                      poSourceSRS ? poSourceSRS : oOutputSRSHolder.get() );
         if( !(poGCPCoordTrans->IsValid()) )
         {
             delete poGCPCoordTrans;
@@ -2340,7 +2359,7 @@ GDALDatasetH GDALVectorTranslate( const char *pszDest, GDALDatasetH hDstDS, int
     oSetup.m_poSrcDS = poDS;
     oSetup.m_poDstDS = poODS;
     oSetup.m_papszLCO = psOptions->papszLCO;
-    oSetup.m_poOutputSRS = poOutputSRS;
+    oSetup.m_poOutputSRS = oOutputSRSHolder.get();
     oSetup.m_bNullifyOutputSRS = psOptions->bNullifyOutputSRS;
     oSetup.m_papszSelFields = psOptions->papszSelFields;
     oSetup.m_bAppend = bAppend;
@@ -2372,7 +2391,7 @@ GDALDatasetH GDALVectorTranslate( const char *pszDest, GDALDatasetH hDstDS, int
     oTranslator.m_bTransform = psOptions->bTransform;
     oTranslator.m_bWrapDateline = psOptions->bWrapDateline;
     oTranslator.m_osDateLineOffset = osDateLineOffset;
-    oTranslator.m_poOutputSRS = poOutputSRS;
+    oTranslator.m_poOutputSRS = oOutputSRSHolder.get();
     oTranslator.m_bNullifyOutputSRS = psOptions->bNullifyOutputSRS;
     oTranslator.m_poUserSourceSRS = poSourceSRS;
     oTranslator.m_poGCPCoordTrans = poGCPCoordTrans;
diff --git a/ci/travis/gcc48_stdcpp11/before_install.sh b/ci/travis/gcc48_stdcpp11/before_install.sh
index ff90ed3..a362ed8 100755
--- a/ci/travis/gcc48_stdcpp11/before_install.sh
+++ b/ci/travis/gcc48_stdcpp11/before_install.sh
@@ -5,11 +5,12 @@ set -e
 sudo mv /etc/apt/sources.list.d/pgdg* /tmp
 sudo apt-get remove postgis libpq5 libpq-dev postgresql-9.1-postgis postgresql-9.1-postgis-2.2-scripts postgresql-9.2-postgis postgresql-9.3-postgis postgresql-9.1 postgresql-9.2 postgresql-9.3 libgdal1
 sudo add-apt-repository -y ppa:ubuntugis/ubuntugis-unstable
-sudo add-apt-repository -y ppa:marlam/gta
+#sudo add-apt-repository -y ppa:marlam/gta
 #http://ubuntuhandbook.org/index.php/2013/08/install-gcc-4-8-via-ppa-in-ubuntu-12-04-13-04/
 sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
 sudo apt-get update -qq
-sudo apt-get install python-numpy postgis postgresql-9.1 postgresql-client-9.1 postgresql-9.1-postgis-2.1 postgresql-9.1-postgis-2.1-scripts libpq-dev libpng12-dev libjpeg-dev libgif-dev liblzma-dev libgeos-dev libcurl4-gnutls-dev libproj-dev libxml2-dev libexpat-dev libxerces-c-dev libnetcdf-dev netcdf-bin libpoppler-dev libspatialite-dev gpsbabel swig libhdf4-alt-dev libhdf5-serial-dev libpodofo-dev poppler-utils libfreexl-dev unixodbc-dev libwebp-dev openjdk-7-jdk libepsilon-dev libgt [...]
+sudo apt-get install python-numpy postgis postgresql-9.1 postgresql-client-9.1 postgresql-9.1-postgis-2.1 postgresql-9.1-postgis-2.1-scripts libpq-dev libpng12-dev libjpeg-dev libgif-dev liblzma-dev libgeos-dev libcurl4-gnutls-dev libproj-dev libxml2-dev libexpat-dev libxerces-c-dev libnetcdf-dev netcdf-bin libpoppler-dev libspatialite-dev gpsbabel swig libhdf4-alt-dev libhdf5-serial-dev libpodofo-dev poppler-utils libfreexl-dev unixodbc-dev libwebp-dev openjdk-7-jdk libepsilon-dev liblc [...]
+# libgta-dev 
 sudo apt-get install python-lxml
 sudo apt-get install python-pip
 sudo apt-get install libogdi3.2-dev
diff --git a/ci/travis/gcc48_stdcpp11/install.sh b/ci/travis/gcc48_stdcpp11/install.sh
index ea9fe69..1d83d6c 100755
--- a/ci/travis/gcc48_stdcpp11/install.sh
+++ b/ci/travis/gcc48_stdcpp11/install.sh
@@ -7,7 +7,8 @@ export CCACHE_CPP2=yes
 
 # Disable --with-fgdb=/usr/local since it causes /usr/local/include/GeodatabaseManagement.h:56:1: error: expected constructor, destructor, or type conversion before ‘(’ token EXT_FILEGDB_API fgdbError CreateGeodatabase(const std::wstring& path, Geodatabase& geodatabase);
 # Disable --with-mongocxx=/usr/local since it should also likely be compiled with C+11, but this fails because boost itself should probably be
-CC="ccache gcc-4.8 -std=c11" CXX="ccache g++-4.8 -std=c++11 -Wzero-as-null-pointer-constant -DNULL_AS_NULLPTR" ./configure --prefix=/usr --without-libtool --with-jpeg12 --with-python --with-poppler --with-podofo --with-spatialite --with-mysql --with-liblzma --with-webp --with-java --with-mdb --with-jvm-lib-add-rpath --with-epsilon --with-gta --with-ecw=/usr/local --with-mrsid=/usr/local --with-mrsid-lidar=/usr/local  --with-libkml --with-openjpeg=/usr/local --with-pdfium=/usr/local --ena [...]
+CC="ccache gcc-4.8 -std=c11" CXX="ccache g++-4.8 -std=c++11 -Wzero-as-null-pointer-constant -DNULL_AS_NULLPTR" ./configure --prefix=/usr --without-libtool --with-jpeg12 --with-python --with-poppler --with-podofo --with-spatialite --with-mysql --with-liblzma --with-webp --with-java --with-mdb --with-jvm-lib-add-rpath --with-epsilon --with-ecw=/usr/local --with-mrsid=/usr/local --with-mrsid-lidar=/usr/local  --with-libkml --with-openjpeg=/usr/local --with-pdfium=/usr/local --enable-pdf-plugin
+# --with-gta
 make USER_DEFS="-Wextra -Werror" -j3
 cd apps
 make USER_DEFS="-Wextra -Werror" test_ogrsf
diff --git a/ci/travis/gcc52_stdcpp14_sanitize/before_install.sh b/ci/travis/gcc52_stdcpp14_sanitize/before_install.sh
index a1004ca..5370380 100755
--- a/ci/travis/gcc52_stdcpp14_sanitize/before_install.sh
+++ b/ci/travis/gcc52_stdcpp14_sanitize/before_install.sh
@@ -5,9 +5,10 @@ set -e
 sudo mv /etc/apt/sources.list.d/pgdg* /tmp
 sudo apt-get remove postgis libpq5 libpq-dev postgresql-9.1-postgis postgresql-9.1-postgis-2.2-scripts postgresql-9.2-postgis postgresql-9.3-postgis postgresql-9.1 postgresql-9.2 postgresql-9.3 libgdal1
 sudo add-apt-repository -y ppa:ubuntugis/ubuntugis-unstable
-sudo add-apt-repository -y ppa:marlam/gta
+#sudo add-apt-repository -y ppa:marlam/gta
 sudo apt-get update -qq
-sudo apt-get install python-numpy postgis postgresql-9.1 postgresql-client-9.1 postgresql-9.1-postgis-2.1 postgresql-9.1-postgis-2.1-scripts libpq-dev libpng12-dev libjpeg-dev libgif-dev liblzma-dev libgeos-dev libcurl4-gnutls-dev libproj-dev libxml2-dev libexpat-dev libxerces-c-dev libnetcdf-dev netcdf-bin libpoppler-dev libspatialite-dev gpsbabel swig libhdf4-alt-dev libhdf5-serial-dev libpodofo-dev poppler-utils libfreexl-dev unixodbc-dev libwebp-dev openjdk-7-jdk libepsilon-dev libgt [...]
+sudo apt-get install python-numpy postgis postgresql-9.1 postgresql-client-9.1 postgresql-9.1-postgis-2.1 postgresql-9.1-postgis-2.1-scripts libpq-dev libpng12-dev libjpeg-dev libgif-dev liblzma-dev libgeos-dev libcurl4-gnutls-dev libproj-dev libxml2-dev libexpat-dev libxerces-c-dev libnetcdf-dev netcdf-bin libpoppler-dev libspatialite-dev gpsbabel swig libhdf4-alt-dev libhdf5-serial-dev libpodofo-dev poppler-utils libfreexl-dev unixodbc-dev libwebp-dev openjdk-7-jdk libepsilon-dev liblc [...]
+# libgta-dev
 sudo apt-get install python-lxml
 sudo apt-get install python-pip
 sudo apt-get install libogdi3.2-dev
diff --git a/ci/travis/gcc52_stdcpp14_sanitize/install.sh b/ci/travis/gcc52_stdcpp14_sanitize/install.sh
index 6d4ba32..0a7a648 100755
--- a/ci/travis/gcc52_stdcpp14_sanitize/install.sh
+++ b/ci/travis/gcc52_stdcpp14_sanitize/install.sh
@@ -13,7 +13,8 @@ export CCACHE_CPP2=yes
 
 # Disable --with-fgdb=/usr/local since it causes /usr/local/include/GeodatabaseManagement.h:56:1: error: expected constructor, destructor, or type conversion before ‘(’ token EXT_FILEGDB_API fgdbError CreateGeodatabase(const std::wstring& path, Geodatabase& geodatabase);
 # Disable --with-mongocxx=/usr/local since it should also likely be compiled with C+11, but this fails because boost itself should probably be
-CC="ccache gcc" CXX="ccache g++ -std=c++14" CPPFLAGS="-DMAKE_SANITIZE_HAPPY -fsanitize=undefined -fsanitize=address" LDFLAGS="-fsanitize=undefined -fsanitize=address" ./configure --prefix=/usr --without-libtool --enable-debug --with-jpeg12 --with-poppler --without-podofo --with-spatialite --with-mysql --with-liblzma --with-webp --with-epsilon --with-gta --with-ecw=/usr/local --with-openjpeg=/usr/local --with-libtiff=internal --with-rename-internal-libtiff-symbols --with-hide-internal-sym [...]
+CC="ccache gcc" CXX="ccache g++ -std=c++14" CPPFLAGS="-DMAKE_SANITIZE_HAPPY -fsanitize=undefined -fsanitize=address" LDFLAGS="-fsanitize=undefined -fsanitize=address" ./configure --prefix=/usr --without-libtool --enable-debug --with-jpeg12 --with-poppler --without-podofo --with-spatialite --with-mysql --with-liblzma --with-webp --with-epsilon --with-ecw=/usr/local --with-openjpeg=/usr/local --with-libtiff=internal --with-rename-internal-libtiff-symbols --with-hide-internal-symbols --with-gnm
+#  --with-gta
 make USER_DEFS="-Werror" -j3
 cd apps
 make USER_DEFS="-Werror" test_ogrsf
diff --git a/ci/travis/precise_clang/before_install.sh b/ci/travis/precise_clang/before_install.sh
index f958b20..b6f0595 100755
--- a/ci/travis/precise_clang/before_install.sh
+++ b/ci/travis/precise_clang/before_install.sh
@@ -5,9 +5,10 @@ set -e
 sudo mv /etc/apt/sources.list.d/pgdg* /tmp
 sudo apt-get remove postgis libpq5 libpq-dev postgresql-9.1-postgis postgresql-9.1-postgis-2.2-scripts postgresql-9.2-postgis postgresql-9.3-postgis postgresql-9.1 postgresql-9.2 postgresql-9.3 libgdal1
 sudo add-apt-repository -y ppa:ubuntugis/ubuntugis-unstable
-sudo add-apt-repository -y ppa:marlam/gta
+#sudo add-apt-repository -y ppa:marlam/gta
 sudo apt-get update -qq
-sudo apt-get install ccache python-numpy postgis postgresql-9.1 postgresql-client-9.1 postgresql-9.1-postgis-2.1 postgresql-9.1-postgis-2.1-scripts libpq-dev libpng12-dev libjpeg-dev libgif-dev liblzma-dev libgeos-dev libcurl4-gnutls-dev libproj-dev libxml2-dev libexpat-dev libxerces-c-dev libnetcdf-dev netcdf-bin libpoppler-dev libspatialite-dev gpsbabel swig libhdf4-alt-dev libhdf5-serial-dev libpodofo-dev poppler-utils libfreexl-dev unixodbc-dev libwebp-dev openjdk-7-jdk libepsilon-de [...]
+sudo apt-get install ccache python-numpy postgis postgresql-9.1 postgresql-client-9.1 postgresql-9.1-postgis-2.1 postgresql-9.1-postgis-2.1-scripts libpq-dev libpng12-dev libjpeg-dev libgif-dev liblzma-dev libgeos-dev libcurl4-gnutls-dev libproj-dev libxml2-dev libexpat-dev libxerces-c-dev libnetcdf-dev netcdf-bin libpoppler-dev libspatialite-dev gpsbabel swig libhdf4-alt-dev libhdf5-serial-dev libpodofo-dev poppler-utils libfreexl-dev unixodbc-dev libwebp-dev openjdk-7-jdk libepsilon-de [...]
+#  libgta-dev
 sudo apt-get install python-lxml
 sudo apt-get install python-pip
 sudo apt-get install libogdi3.2-dev
diff --git a/ci/travis/precise_clang/install.sh b/ci/travis/precise_clang/install.sh
index 8b2583e..df2656a 100755
--- a/ci/travis/precise_clang/install.sh
+++ b/ci/travis/precise_clang/install.sh
@@ -9,7 +9,8 @@ scripts/detect_tabulations.sh
 scripts/detect_printf.sh
 scripts/detect_self_assignment.sh
 
-CC="ccache clang" CXX="ccache clang" ./configure --prefix=/usr --without-libtool --without-cpp11 --enable-debug --with-jpeg12 --with-python --with-poppler --with-podofo --with-spatialite --with-mysql --with-liblzma --with-webp --with-java --with-mdb --with-jvm-lib-add-rpath --with-epsilon --with-gta --with-ecw=/usr/local --with-mrsid=/usr/local --with-mrsid-lidar=/usr/local --with-fgdb=/usr/local --with-libkml --with-openjpeg=/usr/local --with-mongocxx=/usr/local
+CC="ccache clang" CXX="ccache clang" ./configure --prefix=/usr --without-libtool --without-cpp11 --enable-debug --with-jpeg12 --with-python --with-poppler --with-podofo --with-spatialite --with-mysql --with-liblzma --with-webp --with-java --with-mdb --with-jvm-lib-add-rpath --with-epsilon --with-ecw=/usr/local --with-mrsid=/usr/local --with-mrsid-lidar=/usr/local --with-fgdb=/usr/local --with-libkml --with-openjpeg=/usr/local --with-mongocxx=/usr/local
+#  --with-gta
 make docs >docs_log.txt 2>&1
 if cat docs_log.txt | grep -i warning | grep -v russian | grep -v brazilian; then echo "Doxygen warnings found" && cat docs_log.txt && /bin/false; else echo "No Doxygen warnings found"; fi
 make man >man_log.txt 2>&1
diff --git a/ci/travis/python3/before_install.sh b/ci/travis/python3/before_install.sh
index 9b94187..d303f7c 100755
--- a/ci/travis/python3/before_install.sh
+++ b/ci/travis/python3/before_install.sh
@@ -5,9 +5,10 @@ set -e
 sudo mv /etc/apt/sources.list.d/pgdg* /tmp
 sudo apt-get remove postgis libpq5 libpq-dev postgresql-9.1-postgis postgresql-9.1-postgis-2.2-scripts postgresql-9.2-postgis postgresql-9.3-postgis postgresql-9.1 postgresql-9.2 postgresql-9.3 libgdal1
 sudo add-apt-repository -y ppa:ubuntugis/ubuntugis-unstable
-sudo add-apt-repository -y ppa:marlam/gta
+#sudo add-apt-repository -y ppa:marlam/gta
 sudo apt-get update -qq
-sudo apt-get install ccache python3 python3-dev python3-numpy postgis postgresql-9.1 postgresql-client-9.1 postgresql-9.1-postgis-2.1 postgresql-9.1-postgis-2.1-scripts libpq-dev libpng12-dev libjpeg-dev libgif-dev liblzma-dev libgeos-dev libcurl4-gnutls-dev libproj-dev libxml2-dev libexpat-dev libxerces-c-dev libnetcdf-dev netcdf-bin libpoppler-dev libspatialite-dev gpsbabel swig libhdf4-alt-dev libhdf5-serial-dev libpodofo-dev poppler-utils libfreexl-dev unixodbc-dev libwebp-dev openjd [...]
+sudo apt-get install ccache python3 python3-dev python3-numpy postgis postgresql-9.1 postgresql-client-9.1 postgresql-9.1-postgis-2.1 postgresql-9.1-postgis-2.1-scripts libpq-dev libpng12-dev libjpeg-dev libgif-dev liblzma-dev libgeos-dev libcurl4-gnutls-dev libproj-dev libxml2-dev libexpat-dev libxerces-c-dev libnetcdf-dev netcdf-bin libpoppler-dev libspatialite-dev gpsbabel swig libhdf4-alt-dev libhdf5-serial-dev libpodofo-dev poppler-utils libfreexl-dev unixodbc-dev libwebp-dev openjd [...]
+# libgta-dev
 sudo apt-get install python3-lxml
 sudo apt-get install libogdi3.2-dev
 # Boost for Mongo
diff --git a/ci/travis/python3/install.sh b/ci/travis/python3/install.sh
index b8649f4..88ee444 100755
--- a/ci/travis/python3/install.sh
+++ b/ci/travis/python3/install.sh
@@ -5,7 +5,8 @@ set -e
 cd gdal
 export CCACHE_CPP2=yes
 
-CC="ccache gcc" CXX="ccache g++" ./configure --prefix=/usr --without-libtool --enable-debug --with-jpeg12 --with-python=/usr/bin/python3 --with-poppler --with-podofo --with-spatialite --with-mysql --with-liblzma --with-webp --with-java --with-mdb --with-jvm-lib-add-rpath --with-epsilon --with-gta --with-ecw=/usr/local --with-mrsid=/usr/local --with-mrsid-lidar=/usr/local --with-fgdb=/usr/local --with-libkml --with-openjpeg=/usr/local --with-mongocxx=/usr/local
+CC="ccache gcc" CXX="ccache g++" ./configure --prefix=/usr --without-libtool --enable-debug --with-jpeg12 --with-python=/usr/bin/python3 --with-poppler --with-podofo --with-spatialite --with-mysql --with-liblzma --with-webp --with-java --with-mdb --with-jvm-lib-add-rpath --with-epsilon --with-ecw=/usr/local --with-mrsid=/usr/local --with-mrsid-lidar=/usr/local --with-fgdb=/usr/local --with-libkml --with-openjpeg=/usr/local --with-mongocxx=/usr/local
+#  --with-gta
 make USER_DEFS="-Wextra -Werror" -j3
 cd apps
 make USER_DEFS="-Wextra -Werror" test_ogrsf
diff --git a/configure b/configure
index 7af467f..b3f2236 100755
--- a/configure
+++ b/configure
@@ -17954,6 +17954,50 @@ if test "x$CXX" = x ; then
   as_fn_error $? "\"You don't have a working C++ compiler.\"" "$LINENO" 5
 fi
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for std::isnan" >&5
+$as_echo_n "checking for std::isnan... " >&6; }
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <cmath>
+    int CPLIsNan(float f) { return std::isnan(f); }
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STD_IS_NAN 1
+_ACEOF
+
+
+else
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
 
 # Check whether --with-libtool was given.
 if test "${with_libtool+set}" = set; then :
@@ -18714,7 +18758,7 @@ $as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
 $as_echo_n "checking for 64bit integer type... " >&6; }
 
   echo 'int main() { long long off=0; }' >> conftest.c
-  if test -z "`${CC} -o conftest conftest.c 2>&1`" ; then
+  if test -z "`${CC} ${CCFLAGS} -o conftest conftest.c 2>&1`" ; then
 
 $as_echo "#define HAVE_LONG_LONG 1" >>confdefs.h
 
@@ -18746,7 +18790,7 @@ $as_echo_n "checking for 64bit file io... " >&6; }
     echo '#include <sys/types.h>' >> conftest.c
     echo '#include <sys/stat.h>' >> conftest.c
     echo 'int main() { struct __stat64 buf; _stat64( "", &buf ); return 0; }' >> conftest.c
-    if test -z "`${CC} -o conftest conftest.c 2>&1`" ; then
+    if test -z "`${CC} ${CCFLAGS} -o conftest conftest.c 2>&1`" ; then
         with_unix_stdio_64=no
 
 cat >>confdefs.h <<_ACEOF
@@ -18768,9 +18812,9 @@ _ACEOF
   fi
 
   if test x"$with_unix_stdio_64" = x"" ; then
-    echo '#include <stdio.h>' > conftest.cpp
+    echo '#include <stdio.h>' > conftest.c
     echo 'int main() { long long off=0; fseek64(NULL, off, SEEK_SET); off = ftell64(NULL); return 0; }' >> conftest.c
-    if test -z "`${CC} -o conftest conftest.c 2>&1`" ; then
+    if test -z "`${CC} ${CCFLAGS} -o conftest conftest.c 2>&1`" ; then
       with_unix_stdio_64=yes
       VSI_FTELL64=ftell64
       VSI_FSEEK64=fseek64
@@ -18780,9 +18824,9 @@ _ACEOF
 
 
   if test x"$with_unix_stdio_64" = x"" ; then
-    echo '#include <stdio.h>' > conftest.c
-    echo 'int main() { long long off=0; fseeko64(NULL, off, SEEK_SET); off = ftello64(NULL); return 0; }' >> conftest.c
-    if test -z "`${CXX} -o conftest conftest.c 2>&1`" ; then
+    echo '#include <stdio.h>' > conftest.cpp
+    echo 'int main() { long long off=0; fseeko64(NULL, off, SEEK_SET); off = ftello64(NULL); return 0; }' >> conftest.cpp
+    if test -z "`${CXX} ${CXXFLAGS} -o conftest conftest.cpp 2>&1`" ; then
       with_unix_stdio_64=yes
       VSI_FTELL64=ftello64
       VSI_FSEEK64=fseeko64
@@ -18792,10 +18836,10 @@ _ACEOF
 
 
   if test x"$with_unix_stdio_64" = x"" ; then
-    echo '#define _LARGEFILE64_SOURCE' > conftest.c
-    echo '#include <stdio.h>' >> conftest.c
-    echo 'int main() { long long off=0; fseeko64(NULL, off, SEEK_SET); off = ftello64(NULL); return 0; }' >> conftest.c
-    if test -z "`${CXX} -o conftest conftest.c 2>&1`" ; then
+    echo '#define _LARGEFILE64_SOURCE' > conftest.cpp
+    echo '#include <stdio.h>' >> conftest.cpp
+    echo 'int main() { long long off=0; fseeko64(NULL, off, SEEK_SET); off = ftello64(NULL); return 0; }' >> conftest.cpp
+    if test -z "`${CXX} ${CXXFLAGS} -o conftest conftest.cpp 2>&1`" ; then
       with_unix_stdio_64=yes
       VSI_FTELL64=ftello64
       VSI_FSEEK64=fseeko64
@@ -18821,7 +18865,7 @@ $as_echo "#define VSI_NEED_LARGEFILE64_SOURCE 1" >>confdefs.h
   if test x"$with_unix_stdio_64" = x"" ; then
     echo '#include <stdio.h>' > conftest.c
     echo 'int main() { fpos_t off=0; fseeko(NULL, off, SEEK_SET); off = ftello(NULL); return 0; }' >> conftest.c
-    if test -z "`${CC} -o conftest conftest.c 2>&1`" ; then
+    if test -z "`${CC} ${CCFLAGS} -o conftest conftest.c 2>&1`" ; then
       with_unix_stdio_64=yes
       VSI_FTELL64=ftello
       VSI_FSEEK64=fseeko
@@ -32943,7 +32987,7 @@ EXTRA_INCLUDES=$EXTRA_INCLUDES
 
 
 case "${host_os}" in
-    cygwin* | mingw32* | pw32*)
+    cygwin* | mingw* | pw32*)
       EXE_EXT=.exe
       SO_EXT=dll
       ;;
diff --git a/configure.ac b/configure.ac
index e3e83e8..0a53d88 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,5 @@
 dnl ***************************************************************************
-dnl $Id: configure.ac 38000 2017-04-14 11:50:06Z rouault $
+dnl $Id: configure.ac 39012 2017-06-09 10:08:43Z rouault $
 dnl
 dnl Project:  GDAL
 dnl Purpose:  Configure source file.
@@ -183,6 +183,20 @@ if test "x$CXX" = x ; then
   AC_MSG_ERROR("You don't have a working C++ compiler.")
 fi
 
+AC_MSG_CHECKING([for std::isnan])
+AC_LANG_PUSH([C++])
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+  [[#include <cmath>
+    int CPLIsNan(float f) { return std::isnan(f); }]])],
+  [
+    AC_MSG_RESULT([yes])
+    AC_DEFINE_UNQUOTED(HAVE_STD_IS_NAN, 1,
+          [Define to 1 if you have the `std::isnan' function.])
+  ], [
+    AC_MSG_RESULT([no])
+  ])
+AC_LANG_POP([C++])
+
 dnl switch between libtool and native build system
 AC_ARG_WITH(libtool, [  --without-libtool     Don't use libtool to build the library],,)
 
@@ -4723,7 +4737,7 @@ dnl building for Windows). This test should work for the case of
 dnl cross-compilation too.
 dnl ---------------------------------------------------------------------------
 case "${host_os}" in
-    cygwin* | mingw32* | pw32*)
+    cygwin* | mingw* | pw32*)
       EXE_EXT=.exe
       SO_EXT=dll
       ;;
diff --git a/frmts/adrg/srpdataset.cpp b/frmts/adrg/srpdataset.cpp
index 1fe0a7f..e386df6 100644
--- a/frmts/adrg/srpdataset.cpp
+++ b/frmts/adrg/srpdataset.cpp
@@ -39,7 +39,7 @@
 // Uncomment to recognize also .gen files in addition to .img files
 // #define OPEN_GEN
 
-CPL_CVSID("$Id: srpdataset.cpp 36979 2016-12-20 18:40:40Z rouault $");
+CPL_CVSID("$Id: srpdataset.cpp 39068 2017-06-11 13:30:59Z rouault $");
 
 class SRPDataset : public GDALPamDataset
 {
@@ -555,9 +555,12 @@ bool SRPDataset::GetFromRecord( const char* pszFileName, DDFRecord * record )
 
         const int nIndexValueWidth = subfieldDefn->GetWidth();
 
+        char offset[30] = {0};
         /* Should be strict comparison, but apparently a few datasets */
         /* have GetDataSize() greater than the required minimum (#3862) */
-        if (nIndexValueWidth > (INT_MAX - 1) / (NFL * NFC) ||
+        if (nIndexValueWidth <= 0 ||
+            static_cast<size_t>(nIndexValueWidth) >= sizeof(offset) ||
+            nIndexValueWidth > (INT_MAX - 1) / (NFL * NFC) ||
             field->GetDataSize() < nIndexValueWidth * NFL * NFC + 1)
         {
             return false;
@@ -572,7 +575,6 @@ bool SRPDataset::GetFromRecord( const char* pszFileName, DDFRecord * record )
             return false;
         }
         const char* ptr = field->GetData();
-        char offset[30] = {0};
         offset[nIndexValueWidth] = '\0';
 
         for( int i = 0; i < NFL * NFC; i++ )
diff --git a/frmts/aigrid/gridlib.c b/frmts/aigrid/gridlib.c
index 02296e2..ea18c93 100644
--- a/frmts/aigrid/gridlib.c
+++ b/frmts/aigrid/gridlib.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gridlib.c 35251 2016-08-30 04:28:53Z goatbar $
+ * $Id: gridlib.c 38227 2017-05-12 16:31:33Z rouault $
  *
  * Project:  Arc/Info Binary Grid Translator
  * Purpose:  Grid file reading code.
@@ -30,7 +30,7 @@
 
 #include "aigrid.h"
 
-CPL_CVSID("$Id: gridlib.c 35251 2016-08-30 04:28:53Z goatbar $");
+CPL_CVSID("$Id: gridlib.c 38227 2017-05-12 16:31:33Z rouault $");
 
 CPL_INLINE static void CPL_IGNORE_RET_VAL_INT(CPL_UNUSED int unused) {}
 
@@ -106,21 +106,16 @@ CPLErr AIGProcessIntConstBlock( GByte *pabyCur, int nDataSize, int nMin,
     return( CE_None );
 }
 
-/**********************************************************************
- *                       AIGSaturatedAdd()
- ***********************************************************************/
+/************************************************************************/
+/*                         AIGRolloverSignedAdd()                       */
+/************************************************************************/
 
-static GInt32 AIGSaturatedAdd(GInt32 nVal, GInt32 nAdd)
+static GInt32 AIGRolloverSignedAdd(GInt32 a, GInt32 b)
 {
-    if( nAdd >= 0 && nVal > INT_MAX - nAdd )
-        nVal = INT_MAX;
-    else if( nAdd == INT_MIN && nVal < 0 )
-        nVal = INT_MIN;
-    else if( nAdd != INT_MIN && nAdd < 0 && nVal < INT_MIN - nAdd )
-        nVal = INT_MIN;
-    else
-        nVal += nAdd;
-    return nVal;
+    // Not really portable as assumes complement to 2 representation
+    // but AIG assumes typical unsigned rollover on signed
+    // integer operations.
+    return (GInt32)((GUInt32)(a) + (GUInt32)(b));
 }
 
 /************************************************************************/
@@ -150,7 +145,7 @@ CPLErr AIGProcessRaw32BitBlock( GByte *pabyCur, int nDataSize, int nMin,
     {
         memcpy(panData + i, pabyCur, 4);
         panData[i] = CPL_MSBWORD32(panData[i]);
-        panData[i] = AIGSaturatedAdd(panData[i], nMin);
+        panData[i] = AIGRolloverSignedAdd(panData[i], nMin);
         pabyCur += 4;
     }
 
@@ -393,8 +388,7 @@ CPLErr AIGProcessBlock( GByte *pabyCur, int nDataSize, int nMin, int nMagic,
             nDataSize -= 4;
 
             nValue = CPL_MSBWORD32( nValue );
-
-            nValue += nMin;
+            nValue = AIGRolloverSignedAdd(nValue, nMin);
             for( i = 0; i < nMarker; i++ )
                 panData[nPixels++] = nValue;
         }
diff --git a/frmts/ceos/ceosopen.c b/frmts/ceos/ceosopen.c
index 7e6670b..c8d96a6 100644
--- a/frmts/ceos/ceosopen.c
+++ b/frmts/ceos/ceosopen.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ceosopen.c 36380 2016-11-21 10:21:20Z rouault $
+ * $Id: ceosopen.c 39139 2017-06-16 15:32:12Z rouault $
  *
  * Project:  CEOS Translator
  * Purpose:  Implementation of non-GDAL dependent CEOS support.
@@ -30,7 +30,7 @@
 
 #include "ceosopen.h"
 
-CPL_CVSID("$Id: ceosopen.c 36380 2016-11-21 10:21:20Z rouault $");
+CPL_CVSID("$Id: ceosopen.c 39139 2017-06-16 15:32:12Z rouault $");
 
 CPL_INLINE static void CPL_IGNORE_RET_VAL_INT(CPL_UNUSED int unused) {}
 
@@ -164,8 +164,11 @@ CEOSRecord * CEOSReadRecord( CEOSImage *psImage )
 void CEOSDestroyRecord( CEOSRecord * psRecord )
 
 {
-    CPLFree( psRecord->pachData );
-    CPLFree( psRecord );
+    if( psRecord )
+    {
+        CPLFree( psRecord->pachData );
+        CPLFree( psRecord );
+    }
 }
 
 /************************************************************************/
@@ -232,8 +235,9 @@ CEOSImage * CEOSOpen( const char * pszFilename, const char * pszAccess )
 /*      Try to read the header record.                                  */
 /* -------------------------------------------------------------------- */
     psRecord = CEOSReadRecord( psImage );
-    if( psRecord == NULL )
+    if( psRecord == NULL || psRecord->nLength < 288 + 4 )
     {
+        CEOSDestroyRecord( psRecord );
         CEOSClose( psImage );
         return NULL;
     }
diff --git a/frmts/cosar/cosar_dataset.cpp b/frmts/cosar/cosar_dataset.cpp
index 7d8e6fc..0445fab 100644
--- a/frmts/cosar/cosar_dataset.cpp
+++ b/frmts/cosar/cosar_dataset.cpp
@@ -29,7 +29,7 @@
 
 #include <string.h>
 
-CPL_CVSID("$Id: cosar_dataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
+CPL_CVSID("$Id: cosar_dataset.cpp 38793 2017-06-02 08:21:52Z rouault $");
 
 /* Various offsets, in bytes */
 // Commented out the unused defines.
@@ -50,6 +50,7 @@ class COSARDataset : public GDALDataset
 {
 public:
         COSARDataset() : fp(NULL) { }
+        ~COSARDataset();
         VSILFILE *fp;
 
         static GDALDataset *Open( GDALOpenInfo * );
@@ -140,10 +141,18 @@ CPLErr COSARRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff,
  * COSARDataset Implementation
  *****************************************************************************/
 
+COSARDataset::~COSARDataset()
+{
+    if( fp != NULL )
+    {
+        VSIFCloseL(fp);
+    }
+}
+
 GDALDataset *COSARDataset::Open( GDALOpenInfo * pOpenInfo ) {
     long nRTNB;
     /* Check if we're actually a COSAR data set. */
-    if( pOpenInfo->nHeaderBytes < 4 )
+    if( pOpenInfo->nHeaderBytes < 4 || pOpenInfo->fpL == NULL)
         return NULL;
 
     if (!STARTS_WITH_CI((char *)pOpenInfo->pabyHeader+MAGIC1_OFFSET, "CSAR"))
diff --git a/frmts/e00grid/GNUmakefile b/frmts/e00grid/GNUmakefile
index 056bd46..79b4f80 100644
--- a/frmts/e00grid/GNUmakefile
+++ b/frmts/e00grid/GNUmakefile
@@ -12,4 +12,6 @@ clean:
 
 all:	$(OBJ:.o=.$(OBJ_EXT))
 
+$(O_OBJ):       e00read.c
+
 install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
diff --git a/frmts/e00grid/e00read.c b/frmts/e00grid/e00read.c
index 3f1d3ce..6754042 100644
--- a/frmts/e00grid/e00read.c
+++ b/frmts/e00grid/e00read.c
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: e00read.c 34521 2016-07-02 21:26:43Z goatbar $
+ * $Id: e00read.c 39207 2017-06-20 17:57:08Z rouault $
  *
  * Name:     e00read.c
  * Project:  Compressed E00 Read/Write library
@@ -355,6 +355,7 @@ static void _ReadNextSourceLine(E00ReadPtr psInfo)
             if (pszLine)
             {
                 strncpy(psInfo->szInBuf, pszLine, E00_READ_BUF_SIZE);
+                psInfo->szInBuf[E00_READ_BUF_SIZE-1] = '\0';
             }
             else
             {
@@ -371,6 +372,7 @@ static void _ReadNextSourceLine(E00ReadPtr psInfo)
              */
             int nLen;
             nLen = (int)strlen(psInfo->szInBuf);
+            CPLAssert(nLen < E00_READ_BUF_SIZE);
             while(nLen > 0 && (psInfo->szInBuf[nLen-1] == '\n' ||
                                psInfo->szInBuf[nLen-1] == '\r'   ) )
             {
@@ -456,6 +458,19 @@ static const char *_UncompressNextLine(E00ReadPtr psInfo)
 
     while(!bEOL && (c=_GetNextSourceChar(psInfo)) != '\0')
     {
+
+        if (iOutBufPtr < 0)
+        {
+            CPLError(CE_Failure, CPLE_FileIO,
+                     "Corruption around line %d.",
+                     psInfo->nInputLineNo);
+            /* Force the program to abort by simulating a EOF
+             */
+            psInfo->bEOF = 1;
+            bEOL = 1;
+            break;
+        }
+
         if (c != '~')
         {
             /* Normal character... just copy it */
@@ -478,7 +493,7 @@ static const char *_UncompressNextLine(E00ReadPtr psInfo)
                  */
                 c = _GetNextSourceChar(psInfo);
                 n = c - ' ';
-                for(i=0; i<n; i++)
+                for(i=0; i<n && iOutBufPtr <= 80; i++)
                     psInfo->szOutBuf[iOutBufPtr++] = ' ';
                 bPreviousCodeWasNumeric = 0;
             }
@@ -552,7 +567,7 @@ static const char *_UncompressNextLine(E00ReadPtr psInfo)
                  */
                 iCurDigit = 0;
                 while((c=_GetNextSourceChar(psInfo)) != '\0' &&
-                      c != ' ' && c != '~')
+                      c != ' ' && c != '~' && iOutBufPtr <= 80 )
                 {
                     n = c - '!';
                     if (n == 92 && (c=_GetNextSourceChar(psInfo)) != '\0')
@@ -578,7 +593,20 @@ static const char *_UncompressNextLine(E00ReadPtr psInfo)
                 /* If odd number of digits, then flush the last one
                  */
                 if (bOddNumDigits)
+                {
+                    if( iOutBufPtr == 0 )
+                    {
+                        CPLError(CE_Failure, CPLE_FileIO,
+                                "Input file possibly corrupt around line %d.",
+                                psInfo->nInputLineNo);
+                        /* Force the program to abort by simulating a EOF
+                        */
+                        psInfo->bEOF = 1;
+                        bEOL = 1;
+                        break;
+                    }
                     iOutBufPtr--;
+                }
 
                 /* Insert the exponent string before the 2 last digits
                  * (we assume the exponent string is 2 chars. long)
diff --git a/frmts/envisat/envisatdataset.cpp b/frmts/envisat/envisatdataset.cpp
index 3ed5dcb..69dfdaf 100644
--- a/frmts/envisat/envisatdataset.cpp
+++ b/frmts/envisat/envisatdataset.cpp
@@ -34,7 +34,7 @@
 #include "ogr_srs_api.h"
 #include "timedelta.hpp"
 
-CPL_CVSID("$Id: envisatdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
+CPL_CVSID("$Id: envisatdataset.cpp 39169 2017-06-18 13:48:09Z rouault $");
 
 CPL_C_START
 #include "EnvisatFile.h"
@@ -73,9 +73,9 @@ MerisL2FlagBand::MerisL2FlagBand( GDALDataset *poDSIn, int nBandIn,
     nImgOffset(nImgOffsetIn),
     nPrefixBytes(nPrefixBytesIn),
     nBytePerPixel(3),
-    nRecordSize(nPrefixBytesIn + nBlockXSize * nBytePerPixel),
-    nDataSize(nBlockXSize * nBytePerPixel),
-    pReadBuf(static_cast<GByte *>(CPLMalloc(nRecordSize)))
+    nRecordSize(0),
+    nDataSize(0),
+    pReadBuf(NULL)
 {
     poDS = poDSIn;
     nBand = nBandIn;
@@ -86,6 +86,9 @@ MerisL2FlagBand::MerisL2FlagBand( GDALDataset *poDSIn, int nBandIn,
 
     nBlockXSize = poDS->GetRasterXSize();
     nBlockYSize = 1;
+    nRecordSize = nPrefixBytesIn + nBlockXSize * nBytePerPixel;
+    nDataSize = nBlockXSize * nBytePerPixel;
+    pReadBuf = static_cast<GByte *>(CPLMalloc(nRecordSize));
 }
 
 /************************************************************************/
diff --git a/frmts/georaster/georaster_dataset.cpp b/frmts/georaster/georaster_dataset.cpp
index 26b8dd7..dd978fe 100644
--- a/frmts/georaster/georaster_dataset.cpp
+++ b/frmts/georaster/georaster_dataset.cpp
@@ -40,7 +40,7 @@
 
 #include "georaster_priv.h"
 
-CPL_CVSID("$Id: georaster_dataset.cpp 38020 2017-04-14 21:40:01Z rouault $");
+CPL_CVSID("$Id: georaster_dataset.cpp 38222 2017-05-11 20:37:34Z rouault $");
 
 //  ---------------------------------------------------------------------------
 //                                                           GeoRasterDataset()
@@ -1484,8 +1484,34 @@ GDALDataset *GeoRasterDataset::CreateCopy( const char* pszFilename,
 
     poDstDS->GetRasterBand( 1 )->GetBlockSize( &nBlockXSize, &nBlockYSize );
 
-    void *pData = VSI_MALLOC_VERBOSE( nBlockXSize * nBlockYSize *
-        GDALGetDataTypeSize( eType ) / 8 );
+    // --------------------------------------------------------------------
+    //  JP2-F has one block with full image size. Use tile size instead
+    // --------------------------------------------------------------------
+
+    const char* pszFetched = CSLFetchNameValue( papszOptions, "COMPRESS" );
+
+    if( pszFetched != NULL && EQUAL( pszFetched, "JP2-F" ) )
+    {
+        nBlockXSize = DEFAULT_JP2_TILE_COLUMNS;
+        nBlockYSize = DEFAULT_JP2_TILE_ROWS;
+        pszFetched = CSLFetchNameValue( papszOptions, "JP2_BLOCKXSIZE" );
+        if( pszFetched != NULL )
+        {
+            nBlockXSize = atoi( pszFetched );
+        }
+        pszFetched = CSLFetchNameValue( papszOptions, "JP2_BLOCKYSIZE" );
+        if( pszFetched != NULL )
+        {
+            nBlockYSize = atoi( pszFetched );
+        }
+    }
+
+    // --------------------------------------------------------------------
+    //  Allocate memory buffer to read one block from one band
+    // --------------------------------------------------------------------
+
+    void *pData = VSI_MALLOC3_VERBOSE( nBlockXSize, nBlockYSize, 
+                                       GDALGetDataTypeSizeBytes(eType) );
 
     if( pData == NULL )
     {
diff --git a/frmts/georaster/georaster_priv.h b/frmts/georaster/georaster_priv.h
index eaa17cf..20192f1 100644
--- a/frmts/georaster/georaster_priv.h
+++ b/frmts/georaster/georaster_priv.h
@@ -86,6 +86,9 @@ CPL_C_END
 #define DEFAULT_BLOCK_ROWS 512
 #define DEFAULT_BLOCK_COLUMNS 512
 
+#define DEFAULT_JP2_TILE_ROWS 512
+#define DEFAULT_JP2_TILE_COLUMNS 512
+
 //  Default Model Coordinate Location (internal pixel geo-reference)
 
 #define MCL_CENTER      0
@@ -322,7 +325,6 @@ private:
     GByte*              pabyBlockBuf;
     GByte*              pabyCompressBuf;
     OWStatement*        poBlockStmt;
-    OWStatement*        poStmtWrite;
 
     int                 nCurrentLevel;
     long                nLevelOffset;
diff --git a/frmts/georaster/georaster_wrapper.cpp b/frmts/georaster/georaster_wrapper.cpp
index 2b34879..cc72cc5 100644
--- a/frmts/georaster/georaster_wrapper.cpp
+++ b/frmts/georaster/georaster_wrapper.cpp
@@ -34,7 +34,7 @@
 #include "cpl_string.h"
 #include "cpl_minixml.h"
 
-CPL_CVSID("$Id: georaster_wrapper.cpp 38020 2017-04-14 21:40:01Z rouault $");
+CPL_CVSID("$Id: georaster_wrapper.cpp 38500 2017-05-19 19:21:32Z ilucena $");
 
 //  ---------------------------------------------------------------------------
 //                                                           GeoRasterWrapper()
@@ -72,7 +72,6 @@ GeoRasterWrapper::GeoRasterWrapper() :
     pabyCompressBuf     = NULL;
     bIsReferenced       = false;
     poBlockStmt         = NULL;
-    poStmtWrite         = NULL;
     nCacheBlockId       = -1;
     nCurrentLevel       = -1;
     pahLevels           = NULL;
@@ -2385,6 +2384,12 @@ void GeoRasterWrapper::GetSpatialReference()
     //  Adjust Model Coordinate Location
     //  -------------------------------------------------------------------
     
+    if ( eModelCoordLocation == MCL_CENTER )
+    {
+       adfVal[2] -= ( adfVal[0] / 2.0 );
+       adfVal[5] -= ( adfVal[4] / 2.0 );
+    }    
+
     dfXCoefficient[0] = adfVal[0];
     dfXCoefficient[1] = adfVal[1];
     dfXCoefficient[2] = adfVal[2];
@@ -3193,11 +3198,13 @@ bool GeoRasterWrapper::FlushMetadata()
 
     if ( eModelCoordLocation == MCL_CENTER )
     {
-      nMLC = MCL_CENTER;
+        dfXCoef[2] += ( dfXCoefficient[0] / 2.0 );
+        dfYCoef[2] += ( dfYCoefficient[1] / 2.0 );
+        nMLC = MCL_CENTER;
     }
     else
     {
-      nMLC = MCL_UPPERLEFT;
+        nMLC = MCL_UPPERLEFT;
     }
 
     if( phRPC )
diff --git a/frmts/gtiff/geotiff.cpp b/frmts/gtiff/geotiff.cpp
index d6a83ca..59e0756 100644
--- a/frmts/gtiff/geotiff.cpp
+++ b/frmts/gtiff/geotiff.cpp
@@ -106,7 +106,7 @@
 #include "xtiffio.h"
 
 
-CPL_CVSID("$Id: geotiff.cpp 37723 2017-03-16 17:07:53Z rouault $");
+CPL_CVSID("$Id: geotiff.cpp 39129 2017-06-15 10:32:38Z rouault $");
 
 #if SIZEOF_VOIDP == 4
 static bool bGlobalStripIntegerOverflow = false;
@@ -6402,7 +6402,9 @@ CPLErr GTiffOddBitsBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     else if( eDataType == GDT_Float32 )
     {
         const int nWordBytes = poGDS->nBitsPerSample / 8;
-        GByte *pabyImage = poGDS->pabyBlockBuf + (nBand - 1) * nWordBytes;
+        const GByte *pabyImage = poGDS->pabyBlockBuf +
+            ( ( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE ) ? 0 :
+              (nBand - 1) * nWordBytes );
         const int iSkipBytes =
             ( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE ) ?
             nWordBytes : poGDS->nBands * nWordBytes;
@@ -6413,7 +6415,7 @@ CPLErr GTiffOddBitsBand::IReadBlock( int nBlockXOff, int nBlockYOff,
             for( int i = 0; i < nBlockPixels; ++i )
             {
                 static_cast<GUInt32 *>(pImage)[i] =
-                    HalfToFloat( *reinterpret_cast<GUInt16 *>(pabyImage) );
+                    HalfToFloat( *reinterpret_cast<const GUInt16 *>(pabyImage) );
                 pabyImage += iSkipBytes;
             }
         }
@@ -12082,8 +12084,11 @@ GDALDataset *GTiffDataset::OpenDir( GDALOpenInfo * poOpenInfo )
         pszFilename += strlen("GTIFF_RAW:");
     }
 
-    if( !STARTS_WITH_CI(pszFilename, "GTIFF_DIR:") )
+    if( !STARTS_WITH_CI(pszFilename, "GTIFF_DIR:") ||
+        pszFilename[strlen("GTIFF_DIR:")] == '\0' )
+    {
         return NULL;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Split out filename, and dir#/offset.                            */
@@ -16109,7 +16114,7 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     /*      imagery to force the jpegtables to get created.  This is,       */
     /*      likely only needed with libtiff >= 3.9.3 (#3633)                */
     /* -------------------------------------------------------------------- */
-    else if( nCompression == COMPRESSION_JPEG
+    else if( l_nCompression == COMPRESSION_JPEG
             && strstr(TIFFLIB_VERSION_STR, "Version 3.9") != NULL )
     {
         CPLDebug( "GDAL",
diff --git a/frmts/gtiff/gt_citation.cpp b/frmts/gtiff/gt_citation.cpp
index 24ad952..d18b586 100644
--- a/frmts/gtiff/gt_citation.cpp
+++ b/frmts/gtiff/gt_citation.cpp
@@ -45,7 +45,7 @@
 #include "gt_wkt_srs_priv.h"
 #include "ogr_core.h"
 
-CPL_CVSID("$Id: gt_citation.cpp 37477 2017-02-26 03:04:08Z goatbar $");
+CPL_CVSID("$Id: gt_citation.cpp 38890 2017-06-05 08:45:27Z rouault $");
 
 static const char * const apszUnitMap[] = {
     "meters", "1.0",
@@ -108,7 +108,7 @@ char* ImagineCitationTranslation( char* psCitation, geokey_t keyID )
             "NAD = ", "Datum = ", "Ellipsoid = ", "Units = ", NULL };
 
         // This is a handle IMAGING style citation.
-        char name[256] = { '\0' };
+        CPLString osName;
         char* p1 = NULL;
 
         char* p = strchr(psCitation, '$');
@@ -139,21 +139,21 @@ char* ImagineCitationTranslation( char* psCitation, geokey_t keyID )
             {
               case PCSCitationGeoKey:
                 if( strstr(psCitation, "Projection = ") )
-                    strcpy(name, "PRJ Name = ");
+                    osName = "PRJ Name = ";
                 else
-                    strcpy(name, "PCS Name = ");
+                    osName = "PCS Name = ";
                 break;
               case GTCitationGeoKey:
-                strcpy(name, "PCS Name = ");
+                osName = "PCS Name = ";
                 break;
               case GeogCitationGeoKey:
                 if( !strstr(p, "Unable to") )
-                    strcpy(name, "GCS Name = ");
+                    osName = "GCS Name = ";
                 break;
               default:
                 break;
             }
-            if( strlen(name)>0 )
+            if( !osName.empty() )
             {
                 // TODO(schwehr): What exactly is this code trying to do?
                 // Added in r15993 and modified in r21844 by warmerdam.
@@ -176,9 +176,8 @@ char* ImagineCitationTranslation( char* psCitation, geokey_t keyID )
                 }
                 if( p1 >= p )
                 {
-                    strncat(name, p, p1 - p + 1);
-                    strcat(name, "|");
-                    name[strlen(name)] = '\0';
+                    osName.append(p, p1 - p + 1);
+                    osName += '|';
                 }
             }
         }
@@ -207,9 +206,9 @@ char* ImagineCitationTranslation( char* psCitation, geokey_t keyID )
             if( p && p1 && p1>p )
             {
                 if( EQUAL(keyNames[i], "Units = ") )
-                    strcat(name, "LUnits = ");
+                    osName += "LUnits = ";
                 else
-                    strcat(name, keyNames[i]);
+                    osName += keyNames[i];
                 if( p1[0] == '\0' || p1[0] == '\n' || p1[0] == ' ' )
                     p1--;
                 char* p2 = p1 - 1;
@@ -224,14 +223,13 @@ char* ImagineCitationTranslation( char* psCitation, geokey_t keyID )
                 }
                 if( p1 >= p )
                 {
-                    strncat(name, p, p1 - p + 1);
-                    strcat(name, "|");
-                    name[strlen(name)] = '\0';
+                    osName.append(p, p1 - p + 1);
+                    osName += '|';
                 }
             }
         }
-        if( strlen(name) > 0 )
-            ret = CPLStrdup(name);
+        if( !osName.empty() )
+            ret = CPLStrdup(osName);
     }
     return ret;
 }
@@ -630,11 +628,11 @@ OGRBoolean CheckCitationKeyForStatePlaneUTM( GTIF* hGTIF, GTIFDefn* psDefn,
             const char *pStr =
                 strstr( szCTString, "Projection Name = ") +
                 strlen("Projection Name = ");
+            CPLString osCSName(pStr);
             const char* pReturn = strchr( pStr, '\n');
-            char CSName[128] = { '\0' };
-            strncpy(CSName, pStr, pReturn - pStr);
-            CSName[pReturn-pStr] = '\0';
-            if( poSRS->ImportFromESRIStatePlaneWKT(0, NULL, NULL, 32767, CSName)
+            if( pReturn )
+                osCSName.resize(pReturn - pStr);
+            if( poSRS->ImportFromESRIStatePlaneWKT(0, NULL, NULL, 32767, osCSName)
                 == OGRERR_NONE )
             {
                 // For some erdas citation keys, the state plane CS name is
diff --git a/frmts/gtiff/libtiff/tif_dirread.c b/frmts/gtiff/libtiff/tif_dirread.c
index f8628fd..52ba9f8 100644
--- a/frmts/gtiff/libtiff/tif_dirread.c
+++ b/frmts/gtiff/libtiff/tif_dirread.c
@@ -5522,6 +5522,11 @@ ChopUpSingleUncompressedStrip(TIFF* tif)
 	uint64* newoffsets;
 
 	bytecount = td->td_stripbytecount[0];
+        /* On a newly created file, just re-opened to be filled, we */
+        /* don't want strip chop to trigger as it is going to cause issues */
+        /* later ( StripOffsets and StripByteCounts improperly filled) . */
+        if( bytecount == 0 && tif->tif_mode != O_RDONLY )
+            return;
 	offset = td->td_stripoffset[0];
 	assert(td->td_planarconfig == PLANARCONFIG_CONTIG);
 	if ((td->td_photometric == PHOTOMETRIC_YCBCR)&&
diff --git a/frmts/gtiff/tif_float.c b/frmts/gtiff/tif_float.c
index a6f5808..a6cb663 100644
--- a/frmts/gtiff/tif_float.c
+++ b/frmts/gtiff/tif_float.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tif_float.c 34521 2016-07-02 21:26:43Z goatbar $
+ * $Id: tif_float.c 39191 2017-06-19 11:03:41Z rouault $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Floating point conversion functions. Convert 16- and 24-bit
@@ -149,14 +149,14 @@ GUInt32 TripleToFloat( GUInt32 iTriple )
 /*      Denormalized number -- renormalize it.                          */
 /* -------------------------------------------------------------------- */
 
-            while (!(iMantissa & 0x00002000))
+            while (!(iMantissa & 0x00010000))
             {
                 iMantissa <<= 1;
                 iExponent -= 1;
             }
 
             iExponent += 1;
-            iMantissa &= ~0x00002000U;
+            iMantissa &= ~0x00010000U;
         }
     }
     else if (iExponent == 127)
diff --git a/frmts/gxf/gxfopen.c b/frmts/gxf/gxfopen.c
index f291b5b..b65eebd 100644
--- a/frmts/gxf/gxfopen.c
+++ b/frmts/gxf/gxfopen.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gxfopen.c 36436 2016-11-22 21:41:51Z rouault $
+ * $Id: gxfopen.c 39055 2017-06-11 08:20:42Z rouault $
  *
  * Project:  GXF Reader
  * Purpose:  Majority of Geosoft GXF reading code.
@@ -34,7 +34,7 @@
 #include <ctype.h>
 #include "gxfopen.h"
 
-CPL_CVSID("$Id: gxfopen.c 36436 2016-11-22 21:41:51Z rouault $");
+CPL_CVSID("$Id: gxfopen.c 39055 2017-06-11 08:20:42Z rouault $");
 
 
 /* this is also defined in gdal.h which we avoid in this separable component */
@@ -327,6 +327,12 @@ GXFHandle GXFOpen( const char * pszFilename )
         else if( STARTS_WITH_CI(szTitle,"#GTYPE") )
         {
             psGXF->nGType = atoi(papszList[0]);
+            if( psGXF->nGType < 0 || psGXF->nGType > 20 )
+            {
+                CSLDestroy( papszList );
+                GXFClose( psGXF );
+                return NULL;
+            }
         }
 
         CSLDestroy( papszList );
@@ -352,12 +358,28 @@ GXFHandle GXFOpen( const char * pszFilename )
 /* -------------------------------------------------------------------- */
 /*      Allocate, and initialize the raw scanline offset array.         */
 /* -------------------------------------------------------------------- */
-    if( psGXF->nRawYSize <= 0 )
+    if( psGXF->nRawYSize <= 0 || psGXF->nRawYSize >= INT_MAX )
     {
         GXFClose( psGXF );
         return NULL;
     }
 
+    /* Avoid excessive memory allocation */
+    if( psGXF->nRawYSize >= 1000000 )
+    {
+        long nCurOffset;
+        long nFileSize;
+        nCurOffset = VSIFTell( psGXF->fp );
+        VSIFSeek( psGXF->fp, 0, SEEK_END );
+        nFileSize = VSIFTell( psGXF->fp );
+        VSIFSeek( psGXF->fp, nCurOffset, SEEK_SET );
+        if( psGXF->nRawYSize > nFileSize )
+        {
+            GXFClose( psGXF );
+            return NULL;
+        }
+    }
+
     psGXF->panRawLineOffset = (long *)
         VSICalloc( sizeof(long), psGXF->nRawYSize+1 );
     if( psGXF->panRawLineOffset == NULL )
diff --git a/frmts/iris/irisdataset.cpp b/frmts/iris/irisdataset.cpp
index 2dc9641..5f83f02 100644
--- a/frmts/iris/irisdataset.cpp
+++ b/frmts/iris/irisdataset.cpp
@@ -37,7 +37,7 @@
 #include <algorithm>
 #include <sstream>
 
-CPL_CVSID("$Id: irisdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
+CPL_CVSID("$Id: irisdataset.cpp 38839 2017-06-03 23:38:01Z rouault $");
 
 static double DEG2RAD = M_PI / 180.0;
 static double RAD2DEG = 180.0 / M_PI;
@@ -195,6 +195,8 @@ CPLErr IRISRasterBand::IReadBlock( int /* nBlockXOff */,
     // Every product type has its own size. TODO: Move it like dataType.
     int nDataLength = 1;
     if( poGDS->nDataTypeCode == 2 ) nDataLength = 1;
+    else if( poGDS->nDataTypeCode == 8 ) nDataLength = 2;
+    else if( poGDS->nDataTypeCode == 9 ) nDataLength = 2;
     else if( poGDS->nDataTypeCode == 37 ) nDataLength = 2;
     else if( poGDS->nDataTypeCode == 33 ) nDataLength = 2;
     else if( poGDS->nDataTypeCode == 32 ) nDataLength = 1;
diff --git a/frmts/iso8211/ddfsubfielddefn.cpp b/frmts/iso8211/ddfsubfielddefn.cpp
index fb978d1..79900d6 100644
--- a/frmts/iso8211/ddfsubfielddefn.cpp
+++ b/frmts/iso8211/ddfsubfielddefn.cpp
@@ -40,7 +40,7 @@
 #include "cpl_error.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ddfsubfielddefn.cpp 36552 2016-11-29 06:01:45Z goatbar $");
+CPL_CVSID("$Id: ddfsubfielddefn.cpp 38799 2017-06-02 08:54:26Z rouault $");
 
 /************************************************************************/
 /*                          DDFSubfieldDefn()                           */
@@ -478,6 +478,12 @@ DDFSubfieldDefn::ExtractFloatData( const char * pachSourceData,
                         pszName, pszFormatString, nMaxBytes );
               return 0;
           }
+          if( nFormatWidth > static_cast<int>(sizeof(abyData)) )
+          {
+              CPLError( CE_Failure, CPLE_AppDefined,
+                        "Format width %d too large", nFormatWidth );
+              return 0;
+          }
 
           if( pnConsumedBytes != NULL )
               *pnConsumedBytes = nFormatWidth;
diff --git a/frmts/netcdf/netcdfdataset.cpp b/frmts/netcdf/netcdfdataset.cpp
index 9493c1b..5913d8a 100644
--- a/frmts/netcdf/netcdfdataset.cpp
+++ b/frmts/netcdf/netcdfdataset.cpp
@@ -62,7 +62,7 @@
 #include "ogr_core.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: netcdfdataset.cpp 38132 2017-04-25 16:34:14Z rouault $");
+CPL_CVSID("$Id: netcdfdataset.cpp 39160 2017-06-18 10:59:08Z rouault $");
 
 // Internal function declarations.
 
@@ -2827,6 +2827,23 @@ void netCDFDataset::SetProjectionFromVar( int nVarId, bool bReadSRSOnly )
     {
         nc_inq_varid(cdfid, poDS->papszDimName[nXDimID], &nVarDimXID);
         nc_inq_varid(cdfid, poDS->papszDimName[nYDimID], &nVarDimYID);
+
+        // Check that they are 1D or 2D variables
+        if( nVarDimXID >= 0 )
+        {
+            int ndims = -1;
+            nc_inq_varndims(cdfid, nVarDimXID, &ndims);
+            if( ndims == 0 || ndims > 2 )
+                nVarDimXID = -1;
+        }
+
+        if( nVarDimYID >= 0 )
+        {
+            int ndims = -1;
+            nc_inq_varndims(cdfid, nVarDimYID, &ndims);
+            if( ndims == 0 || ndims > 2 )
+                nVarDimYID = -1;
+        }
     }
 
     if( !bReadSRSOnly && (nVarDimXID != -1) && (nVarDimYID != -1) )
@@ -3116,6 +3133,58 @@ void netCDFDataset::SetProjectionFromVar( int nVarId, bool bReadSRSOnly )
                 yMinMax[1] = dfCoordOffset + yMinMax[1] * dfCoordScale;
             }
 
+
+            // Geostationary satellites can specify units in (micro)radians
+            // So we check if they do, and if so convert to linear units (meters)
+            const char *pszProjName = oSRS.GetAttrValue( "PROJECTION" );
+            if( pszProjName != NULL )
+            {
+                if( EQUAL( pszProjName, SRS_PT_GEOSTATIONARY_SATELLITE ) )
+                {
+                    double satelliteHeight = oSRS.GetProjParm(SRS_PP_SATELLITE_HEIGHT, 1.0);
+                    size_t nAttlen = 0;
+                    char szUnits[NC_MAX_NAME+1];
+                    szUnits[0] = '\0';
+                    nc_type nAttype=NC_NAT;
+                    nc_inq_att(cdfid, nVarDimXID, "units", &nAttype, &nAttlen);
+                    if( nAttlen < sizeof(szUnits) &&
+                        nc_get_att_text( cdfid, nVarDimXID, "units",
+                        szUnits ) == NC_NOERR )
+                    {
+                        szUnits[nAttlen] = '\0';
+                        if( EQUAL( szUnits, "microradian" ) )
+                        {
+                            xMinMax[0] = xMinMax[0] * satelliteHeight * 0.000001;
+                            xMinMax[1] = xMinMax[1] * satelliteHeight * 0.000001;
+                        }
+                        else if( EQUAL( szUnits, "rad" ) )
+                        {
+                            xMinMax[0] = xMinMax[0] * satelliteHeight;
+                            xMinMax[1] = xMinMax[1] * satelliteHeight;
+                        }
+                    }
+                    szUnits[0] = '\0';
+                    nc_inq_att(cdfid, nVarDimYID, "units", &nAttype, &nAttlen);
+                    if( nAttlen < sizeof(szUnits) &&
+                       nc_get_att_text( cdfid, nVarDimYID, "units",
+                       szUnits ) == NC_NOERR )
+                    {
+                        szUnits[nAttlen] = '\0';
+                        if( EQUAL( szUnits, "microradian" ) )
+                        {
+                            yMinMax[0] = yMinMax[0] * satelliteHeight * 0.000001;
+                            yMinMax[1] = yMinMax[1] * satelliteHeight * 0.000001;
+                        }
+                        else if( EQUAL( szUnits, "rad" ) )
+                        {
+                            yMinMax[0] = yMinMax[0] * satelliteHeight;
+                            yMinMax[1] = yMinMax[1] * satelliteHeight;
+                        }
+                    }
+                }
+            }
+
+
             adfTempGeoTransform[0] = xMinMax[0];
             adfTempGeoTransform[2] = 0;
             adfTempGeoTransform[3] = yMinMax[1];
diff --git a/frmts/northwood/grcdataset.cpp b/frmts/northwood/grcdataset.cpp
index d13e82f..f6bc787 100644
--- a/frmts/northwood/grcdataset.cpp
+++ b/frmts/northwood/grcdataset.cpp
@@ -37,7 +37,7 @@
 #include "../../ogr/ogrsf_frmts/mitab/mitab.h"
 #endif
 
-CPL_CVSID("$Id: grcdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
+CPL_CVSID("$Id: grcdataset.cpp 38727 2017-05-31 17:50:31Z dmorissette $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -117,9 +117,9 @@ NWT_GRCRasterBand::NWT_GRCRasterBand( NWT_GRCDataset * poDSIn, int nBandIn )
     // load the color table and might as well to the ClassNames
     poGDS->poColorTable = new GDALColorTable();
 
-    GDALColorEntry oEntry = { 255, 255, 255, 255 };
+    GDALColorEntry oEntry = { 255, 255, 255, 0 };
     // null value = 0 is transparent
-    // alpha 255 = transparent
+    // alpha 0 = transparent
 
     poGDS->poColorTable->SetColorEntry( 0, &oEntry );
 
@@ -130,7 +130,7 @@ NWT_GRCRasterBand::NWT_GRCRasterBand( NWT_GRCDataset * poDSIn, int nBandIn )
         oEntry.c1 = poGDS->pGrd->stClassDict->stClassifedItem[i]->r;
         oEntry.c2 = poGDS->pGrd->stClassDict->stClassifedItem[i]->g;
         oEntry.c3 = poGDS->pGrd->stClassDict->stClassifedItem[i]->b;
-        oEntry.c4 = 0;            // alpha 0 = solid
+        oEntry.c4 = 255;            // alpha 255 = solid
 
         poGDS->poColorTable->SetColorEntry( poGDS->pGrd->
                                           stClassDict->stClassifedItem[i]->
diff --git a/frmts/northwood/northwood.cpp b/frmts/northwood/northwood.cpp
index 3f521d0..a19991c 100644
--- a/frmts/northwood/northwood.cpp
+++ b/frmts/northwood/northwood.cpp
@@ -34,7 +34,7 @@
 #include <algorithm>
 #include <string>
 
-CPL_CVSID("$Id: northwood.cpp 36776 2016-12-10 11:17:47Z rouault $");
+CPL_CVSID("$Id: northwood.cpp 38735 2017-05-31 20:39:50Z dmorissette $");
 
 int nwt_ParseHeader( NWT_GRID * pGrd, char *nwtHeader )
 {
@@ -264,7 +264,10 @@ int nwt_ParseHeader( NWT_GRID * pGrd, char *nwtHeader )
                 return FALSE;
             }
 
-            if( !VSIFReadL( &psItem->szClassName, psItem->usLen, 1, pGrd->fp ) )
+            // 0-len class names are possible
+            psItem->szClassName[0] = '\0';
+            if( psItem->usLen > 0 &&
+                !VSIFReadL( &psItem->szClassName, psItem->usLen, 1, pGrd->fp ) )
                 return FALSE;
         }
     }
diff --git a/frmts/pds/nasakeywordhandler.cpp b/frmts/pds/nasakeywordhandler.cpp
index 0da3374..0936f01 100644
--- a/frmts/pds/nasakeywordhandler.cpp
+++ b/frmts/pds/nasakeywordhandler.cpp
@@ -55,7 +55,7 @@
 #include "ogrgeojsonreader.h"
 #include "ogr_json_header.h"
 
-CPL_CVSID("$Id: nasakeywordhandler.cpp 37651 2017-03-08 18:26:09Z rouault $");
+CPL_CVSID("$Id: nasakeywordhandler.cpp 38306 2017-05-14 09:21:58Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -537,6 +537,8 @@ void NASAKeywordHandler::SkipWhite()
             {
                 pszHeaderNext++;
             }
+            if( *pszHeaderNext == '\0' )
+                return;
 
             pszHeaderNext += 2;
 
diff --git a/frmts/pds/vicarkeywordhandler.cpp b/frmts/pds/vicarkeywordhandler.cpp
index de7a9ce..ea1d83c 100644
--- a/frmts/pds/vicarkeywordhandler.cpp
+++ b/frmts/pds/vicarkeywordhandler.cpp
@@ -34,7 +34,7 @@
 
 #include <algorithm>
 
-CPL_CVSID("$Id: vicarkeywordhandler.cpp 36981 2016-12-20 19:46:41Z rouault $");
+CPL_CVSID("$Id: vicarkeywordhandler.cpp 39145 2017-06-16 22:20:03Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -135,23 +135,26 @@ int VICARKeywordHandler::Ingest( VSILFILE *fp, GByte *pabyHeader )
 /* -------------------------------------------------------------------- */
 
     long int nPixelOffset=0;
-    if (EQUAL( CSLFetchNameValue(papszKeywordList,"FORMAT" ), "BYTE" )) {
+    const char* pszFormat = CSLFetchNameValueDef(papszKeywordList,"FORMAT","");
+    if (EQUAL( pszFormat, "BYTE" )) {
         nPixelOffset = 1;
     }
-    else if (EQUAL( CSLFetchNameValue(papszKeywordList,"FORMAT" ), "HALF" )) {
+    else if (EQUAL( pszFormat, "HALF" )) {
         nPixelOffset = 2;
     }
-    else if (EQUAL( CSLFetchNameValue(papszKeywordList,"FORMAT" ), "FULL" )) {
+    else if (EQUAL( pszFormat, "FULL" )) {
         nPixelOffset = 4;
     }
-    else if (EQUAL( CSLFetchNameValue(papszKeywordList,"FORMAT" ), "REAL" )) {
+    else if (EQUAL( pszFormat, "REAL" )) {
         nPixelOffset = 4;
     }
+    if( nPixelOffset == 0 )
+        return FALSE;
 
-    const long int nCols = atoi( CSLFetchNameValue( papszKeywordList, "NS" ) );
-    const long int nRows = atoi( CSLFetchNameValue( papszKeywordList, "NL" ) );
-    const int nBands = atoi( CSLFetchNameValue( papszKeywordList, "NB" ) );
-    const int nBB = atoi( CSLFetchNameValue( papszKeywordList, "NBB" ) );
+    const long int nCols = atoi( CSLFetchNameValueDef( papszKeywordList, "NS", "" ) );
+    const long int nRows = atoi( CSLFetchNameValueDef( papszKeywordList, "NL", "" ) );
+    const int nBands = atoi( CSLFetchNameValueDef( papszKeywordList, "NB", "" ) );
+    const int nBB = atoi( CSLFetchNameValueDef( papszKeywordList, "NBB", "" ) );
 
     const long int nLineOffset = nPixelOffset * nCols + nBB ;
     const long int nBandOffset = nLineOffset * nRows;
@@ -172,23 +175,24 @@ int VICARKeywordHandler::Ingest( VSILFILE *fp, GByte *pabyHeader )
     if (pszLBLSIZE)
         nOffset = static_cast<int>(pszLBLSIZE - (const char *)pszEOLHeader);
     pch1 = strstr( reinterpret_cast<char *>( pszEOLHeader + nOffset ), "=" );
-    if( pch1 == NULL )
+    if( pch1 == NULL || *pch1 == '\0' )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "END-OF-DATASET LABEL NOT FOUND!");
         VSIFree(pszEOLHeader);
         return FALSE;
     }
-    VSIFree(pszEOLHeader);
     pch1 ++;
     pch2 = strstr( pch1, " " );
     if( pch2 == NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "END-OF-DATASET LABEL NOT FOUND!");
+        VSIFree(pszEOLHeader);
         return FALSE;
     }
     strncpy( keyval, pch1, std::min(static_cast<size_t>(pch2 - pch1),
                                     sizeof(keyval) - 1 ) );
     keyval[std::min( static_cast<size_t>(pch2-pch1), sizeof(keyval)-1 )] = '\0';
+    VSIFree(pszEOLHeader);
 
     int EOLabelSize = atoi( keyval );
     if( EOLabelSize <= 0 || EOLabelSize > 100 * 1024 * 1024 )
@@ -246,16 +250,19 @@ int VICARKeywordHandler::ReadPair( CPLString &osName, CPLString &osValue ) {
     osName = "";
     osValue = "";
 
-    if( !ReadWord( osName ) ) {
-    return FALSE;}
+    if( !ReadWord( osName ) )
+    {
+        // VICAR has no NULL string termination
+        if( *pszHeaderNext == '\0') {
+            osName="END";
+            return TRUE;
+        }
+        return FALSE;
+    }
 
     SkipWhite();
-
-    // VICAR has no NULL string termination
-    if( *pszHeaderNext == '\0') {
-        osName="END";
-        return TRUE;
-    }
+    if( *pszHeaderNext == '\0' )
+        return FALSE;
 
     pszHeaderNext++;
 
@@ -308,7 +315,7 @@ int VICARKeywordHandler::ReadWord( CPLString &osWord )
     SkipWhite();
 
     if( *pszHeaderNext == '\0')
-        return TRUE;
+        return FALSE;
 
     if( !( *pszHeaderNext != '='  && !isspace((unsigned char)*pszHeaderNext)) )
         return FALSE;
diff --git a/frmts/raw/fastdataset.cpp b/frmts/raw/fastdataset.cpp
index 32ae6b4..b3f2238 100644
--- a/frmts/raw/fastdataset.cpp
+++ b/frmts/raw/fastdataset.cpp
@@ -32,7 +32,7 @@
 #include "ogr_spatialref.h"
 #include "rawdataset.h"
 
-CPL_CVSID("$Id: fastdataset.cpp 36682 2016-12-04 20:34:45Z rouault $");
+CPL_CVSID("$Id: fastdataset.cpp 39148 2017-06-17 07:09:58Z rouault $");
 
 // static const int ADM_STD_HEADER_SIZE = 4608;  // Format specification says it
 static const int ADM_HEADER_SIZE = 5000;  // Should be 4608, but some vendors
@@ -990,41 +990,44 @@ GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
     // Coordinates should follow the word "PROJECTION", otherwise we can
     // be confused by other occurrences of the corner keywords.
     char *pszGeomRecord = strstr( pszHeader, "PROJECTION" );
-    // Read corner coordinates
-    pszTemp = strstr( pszGeomRecord, CORNER_UPPER_LEFT );
-    if ( pszTemp && !EQUAL( pszTemp, "" ) )
+    if( pszGeomRecord )
     {
-        pszTemp += strlen( CORNER_UPPER_LEFT ) + 28;
-        dfULX = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE );
-        pszTemp += CORNER_VALUE_SIZE + 1;
-        dfULY = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE );
-    }
+        // Read corner coordinates
+        pszTemp = strstr( pszGeomRecord, CORNER_UPPER_LEFT );
+        if ( pszTemp && !EQUAL( pszTemp, "" ) )
+        {
+            pszTemp += strlen( CORNER_UPPER_LEFT ) + 28;
+            dfULX = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE );
+            pszTemp += CORNER_VALUE_SIZE + 1;
+            dfULY = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE );
+        }
 
-    pszTemp = strstr( pszGeomRecord, CORNER_UPPER_RIGHT );
-    if ( pszTemp && !EQUAL( pszTemp, "" ) )
-    {
-        pszTemp += strlen( CORNER_UPPER_RIGHT ) + 28;
-        dfURX = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE );
-        pszTemp += CORNER_VALUE_SIZE + 1;
-        dfURY = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE );
-    }
+        pszTemp = strstr( pszGeomRecord, CORNER_UPPER_RIGHT );
+        if ( pszTemp && !EQUAL( pszTemp, "" ) )
+        {
+            pszTemp += strlen( CORNER_UPPER_RIGHT ) + 28;
+            dfURX = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE );
+            pszTemp += CORNER_VALUE_SIZE + 1;
+            dfURY = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE );
+        }
 
-    pszTemp = strstr( pszGeomRecord, CORNER_LOWER_LEFT );
-    if ( pszTemp && !EQUAL( pszTemp, "" ) )
-    {
-        pszTemp += strlen( CORNER_LOWER_LEFT ) + 28;
-        dfLLX = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE );
-        pszTemp += CORNER_VALUE_SIZE + 1;
-        dfLLY = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE );
-    }
+        pszTemp = strstr( pszGeomRecord, CORNER_LOWER_LEFT );
+        if ( pszTemp && !EQUAL( pszTemp, "" ) )
+        {
+            pszTemp += strlen( CORNER_LOWER_LEFT ) + 28;
+            dfLLX = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE );
+            pszTemp += CORNER_VALUE_SIZE + 1;
+            dfLLY = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE );
+        }
 
-    pszTemp = strstr( pszGeomRecord, CORNER_LOWER_RIGHT );
-    if ( pszTemp && !EQUAL( pszTemp, "" ) )
-    {
-        pszTemp += strlen( CORNER_LOWER_RIGHT ) + 28;
-        dfLRX = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE );
-        pszTemp += CORNER_VALUE_SIZE + 1;
-        dfLRY = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE );
+        pszTemp = strstr( pszGeomRecord, CORNER_LOWER_RIGHT );
+        if ( pszTemp && !EQUAL( pszTemp, "" ) )
+        {
+            pszTemp += strlen( CORNER_LOWER_RIGHT ) + 28;
+            dfLRX = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE );
+            pszTemp += CORNER_VALUE_SIZE + 1;
+            dfLRY = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE );
+        }
     }
 
     if ( dfULX != 0.0 && dfULY != 0.0
diff --git a/frmts/vrt/pixelfunctions.cpp b/frmts/vrt/pixelfunctions.cpp
index e98a027..bc5d742 100644
--- a/frmts/vrt/pixelfunctions.cpp
+++ b/frmts/vrt/pixelfunctions.cpp
@@ -31,7 +31,7 @@
 #include "gdal.h"
 #include "vrtdataset.h"
 
-CPL_CVSID("$Id: pixelfunctions.cpp 35897 2016-10-24 11:54:24Z goatbar $");
+CPL_CVSID("$Id: pixelfunctions.cpp 38256 2017-05-13 15:57:47Z rouault $");
 
 static CPLErr RealPixelFunc( void **papoSources, int nSources, void *pData,
                              int nXSize, int nYSize,
@@ -199,12 +199,12 @@ static CPLErr ComplexPixelFunc( void **papoSources, int nSources, void *pData,
                                 GDALDataType eSrcType, GDALDataType eBufType,
                                 int nPixelSpace, int nLineSpace )
 {
-    const void * const pReal = papoSources[0];
-    const void * const pImag = papoSources[1];
-
     /* ---- Init ---- */
     if( nSources != 2 ) return CE_Failure;
 
+    const void * const pReal = papoSources[0];
+    const void * const pImag = papoSources[1];
+
     /* ---- Set pixels ---- */
     for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
         for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
diff --git a/frmts/vrt/vrtdataset.cpp b/frmts/vrt/vrtdataset.cpp
index 15ac23c..e752246 100644
--- a/frmts/vrt/vrtdataset.cpp
+++ b/frmts/vrt/vrtdataset.cpp
@@ -39,7 +39,7 @@
 
 /*! @cond Doxygen_Suppress */
 
-CPL_CVSID("$Id: vrtdataset.cpp 37212 2017-01-26 10:01:56Z rouault $");
+CPL_CVSID("$Id: vrtdataset.cpp 38964 2017-06-08 08:09:07Z rouault $");
 
 /************************************************************************/
 /*                            VRTDataset()                             */
@@ -288,6 +288,11 @@ CPLXMLNode *VRTDataset::SerializeToXML( const char *pszVRTPathIn )
     /* -------------------------------------------------------------------- */
     /*      Serialize bands.                                                */
     /* -------------------------------------------------------------------- */
+    CPLXMLNode* psLastChild = psDSTree->psChild;
+    for( ; psLastChild != NULL && psLastChild->psNext;
+                                    psLastChild = psLastChild->psNext )
+    {
+    }
     for( int iBand = 0; iBand < nBands; iBand++ )
     {
         CPLXMLNode *psBandTree =
@@ -295,7 +300,17 @@ CPLXMLNode *VRTDataset::SerializeToXML( const char *pszVRTPathIn )
                 papoBands[iBand])->SerializeToXML( pszVRTPathIn );
 
         if( psBandTree != NULL )
-            CPLAddXMLChild( psDSTree, psBandTree );
+        {
+            if( psLastChild == NULL )
+            {
+                CPLAddXMLChild( psDSTree, psBandTree );
+            }
+            else
+            {
+                psLastChild->psNext = psBandTree;
+            }
+            psLastChild = psBandTree;
+        }
     }
 
     /* -------------------------------------------------------------------- */
diff --git a/frmts/webp/webpdataset.cpp b/frmts/webp/webpdataset.cpp
index 0281a9c..32b11f2 100644
--- a/frmts/webp/webpdataset.cpp
+++ b/frmts/webp/webpdataset.cpp
@@ -32,7 +32,7 @@
 
 #include "webp_headers.h"
 
-CPL_CVSID("$Id: webpdataset.cpp 37788 2017-03-19 11:52:40Z rouault $");
+CPL_CVSID("$Id: webpdataset.cpp 38837 2017-06-03 12:33:56Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -283,6 +283,15 @@ CPLErr WEBPDataset::Uncompress()
     bHasBeenUncompressed = TRUE;
     eUncompressErrRet = CE_Failure;
 
+    // To avoid excessive memory allocation attempts
+    // Normally WebP images are no larger than 16383x16383*4 ~= 1 GB
+    if( nRasterXSize > INT_MAX / (nRasterYSize * nBands) )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Too large image");
+        return CE_Failure;
+    }
+
     pabyUncompressed = reinterpret_cast<GByte*>(
         VSIMalloc3(nRasterXSize, nRasterYSize, nBands ) );
     if (pabyUncompressed == NULL)
diff --git a/frmts/xyz/xyzdataset.cpp b/frmts/xyz/xyzdataset.cpp
index fa7b53f..b3c58d1 100644
--- a/frmts/xyz/xyzdataset.cpp
+++ b/frmts/xyz/xyzdataset.cpp
@@ -34,7 +34,7 @@
 #include <algorithm>
 #include <vector>
 
-CPL_CVSID("$Id: xyzdataset.cpp 36822 2016-12-12 11:18:45Z rouault $");
+CPL_CVSID("$Id: xyzdataset.cpp 39210 2017-06-20 18:19:21Z rouault $");
 
 static const double RELATIVE_ERROR = 1e-3;
 
@@ -930,6 +930,7 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
                                  fabs(*oIter - static_cast<int>(*oIter / dfStepX + 0.5) * dfStepX) / dfStepX < RELATIVE_ERROR )
                         {
                             nCountStepX = -1; // disable update of mean
+                            ++ oIter;
                         }
                         else if( dfStepX > *oIter &&
                                  fabs(dfStepX - static_cast<int>(dfStepX / *oIter + 0.5) * (*oIter)) / dfStepX < RELATIVE_ERROR )
diff --git a/gcore/gdal_version.h b/gcore/gdal_version.h
index a5ba3e0..7d75746 100644
--- a/gcore/gdal_version.h
+++ b/gcore/gdal_version.h
@@ -1,4 +1,4 @@
-/* $Id: gdal_version.h 38167 2017-04-28 16:00:45Z rouault $ */
+/* $Id: gdal_version.h 39236 2017-06-23 11:26:14Z rouault $ */
 
 /* -------------------------------------------------------------------- */
 /*      GDAL Version Information.                                       */
@@ -7,7 +7,7 @@
 #ifndef GDAL_VERSION_MAJOR
 #  define GDAL_VERSION_MAJOR    2
 #  define GDAL_VERSION_MINOR    2
-#  define GDAL_VERSION_REV      0
+#  define GDAL_VERSION_REV      1
 #  define GDAL_VERSION_BUILD    0
 #endif
 
@@ -23,8 +23,8 @@
 #endif
 
 #ifndef GDAL_RELEASE_DATE
-#  define GDAL_RELEASE_DATE     20170428
+#  define GDAL_RELEASE_DATE     20170623
 #endif
 #ifndef GDAL_RELEASE_NAME
-#  define GDAL_RELEASE_NAME     "2.2.0"
+#  define GDAL_RELEASE_NAME     "2.2.1"
 #endif
diff --git a/gcore/gdaldataset.cpp b/gcore/gdaldataset.cpp
index 7e513b5..29f254b 100644
--- a/gcore/gdaldataset.cpp
+++ b/gcore/gdaldataset.cpp
@@ -71,7 +71,7 @@
 #include "../sqlite/ogrsqliteexecutesql.h"
 #endif
 
-CPL_CVSID("$Id: gdaldataset.cpp 37723 2017-03-16 17:07:53Z rouault $");
+CPL_CVSID("$Id: gdaldataset.cpp 38303 2017-05-14 09:16:00Z rouault $");
 
 CPL_C_START
 GDALAsyncReader *
@@ -3446,7 +3446,7 @@ void GDALDataset::ReportError(CPLErr eErrClass, CPLErrorNum err_no,
     const char *pszDSName = GetDescription();
     if (strlen(fmt) + strlen(pszDSName) + 3 >= sizeof(szNewFmt) - 1)
         pszDSName = CPLGetFilename(pszDSName);
-    if (pszDSName[0] != '\0' &&
+    if (pszDSName[0] != '\0' && strchr(pszDSName, '%') == NULL &&
         strlen(fmt) + strlen(pszDSName) + 3 < sizeof(szNewFmt) - 1)
     {
         snprintf(szNewFmt, sizeof(szNewFmt), "%s: %s", pszDSName, fmt);
diff --git a/gcore/gdaljp2structure.cpp b/gcore/gdaljp2structure.cpp
index 94227ec..8e59d5b 100644
--- a/gcore/gdaljp2structure.cpp
+++ b/gcore/gdaljp2structure.cpp
@@ -139,10 +139,15 @@ static void DumpGeoTIFFBox(CPLXMLNode* psBox,
     {
         CPLString osTmpFilename(CPLSPrintf("/vsimem/tmp_%p.tif", oBox.GetFILE()));
         CPL_IGNORE_RET_VAL(VSIFCloseL(VSIFileFromMemBuffer(
-            osTmpFilename, pabyBoxData, nBoxDataLength, TRUE) ));
+            osTmpFilename, pabyBoxData, nBoxDataLength, FALSE) ));
         CPLPushErrorHandler(CPLQuietErrorHandler);
         GDALDataset* poDS = (GDALDataset*) GDALOpen(osTmpFilename, GA_ReadOnly);
         CPLPopErrorHandler();
+        if( poDS && poDS->GetRasterCount() > 1 )
+        {
+            GDALClose(poDS);
+            poDS = NULL;
+        }
         if( poDS )
         {
             CPLString osTmpVRTFilename(CPLSPrintf("/vsimem/tmp_%p.vrt", oBox.GetFILE()));
@@ -180,6 +185,7 @@ static void DumpGeoTIFFBox(CPLXMLNode* psBox,
         }
         VSIUnlink(osTmpFilename);
     }
+    CPLFree(pabyBoxData);
 }
 
 static void DumpFTYPBox(CPLXMLNode* psBox, GDALJP2Box& oBox)
@@ -714,6 +720,8 @@ static void DumpRREQBox(CPLXMLNode* psBox, GDALJP2Box& oBox)
                 pabyIter += 2;
                 nRemainingLength -= 2;
             }
+            else
+                break;
             if( nRemainingLength >= ML )
             {
                 CPLString osHex("0x");
@@ -727,6 +735,8 @@ static void DumpRREQBox(CPLXMLNode* psBox, GDALJP2Box& oBox)
                             CPLSPrintf("SM%d", iNSF),
                             (int)ML, osHex.c_str());
             }
+            else
+                break;
         }
         GUInt16 NVF = 0;
         if( nRemainingLength >= 2 )
@@ -754,6 +764,8 @@ static void DumpRREQBox(CPLXMLNode* psBox, GDALJP2Box& oBox)
                             CPLSPrintf("VF%d", iNVF),
                             (int)ML, osHex.c_str());
             }
+            else
+                break;
             if( nRemainingLength >= ML )
             {
                 CPLString osHex("0x");
@@ -767,6 +779,8 @@ static void DumpRREQBox(CPLXMLNode* psBox, GDALJP2Box& oBox)
                             CPLSPrintf("VM%d", iNVF),
                             (int)ML, osHex.c_str());
             }
+            else
+                break;
         }
         if( nRemainingLength > 0 )
             CPLCreateXMLElementAndValue(
@@ -937,6 +951,7 @@ static CPLXMLNode* DumpJPK2CodeStream(CPLXMLNode* psBox,
         GByte* pabyMarkerDataIter = pabyMarkerData;
         GUInt16 nRemainingMarkerSize = nMarkerSize - 2;
         GUInt32 nLastVal = 0;
+        bool bError = false;
 
 #define READ_MARKER_FIELD_UINT8_COMMENT(name, comment) \
         do { if( nRemainingMarkerSize >= 1 ) { \
@@ -948,6 +963,7 @@ static CPLXMLNode* DumpJPK2CodeStream(CPLXMLNode* psBox,
             else { \
                 AddError(psMarker, CPLSPrintf("Cannot read field %s", name)); \
                 nLastVal = 0; \
+                bError = true; \
             } \
         } while( false )
 
@@ -967,6 +983,7 @@ static CPLXMLNode* DumpJPK2CodeStream(CPLXMLNode* psBox,
             else { \
                 AddError(psMarker, CPLSPrintf("Cannot read field %s", name)); \
                 nLastVal = 0; \
+                bError = true; \
             } \
         } while( false )
 
@@ -986,6 +1003,7 @@ static CPLXMLNode* DumpJPK2CodeStream(CPLXMLNode* psBox,
             else { \
                 AddError(psMarker, CPLSPrintf("Cannot read field %s", name)); \
                 nLastVal = 0; \
+                bError = true; \
             } \
         } while( false )
 
@@ -1023,7 +1041,8 @@ static CPLXMLNode* DumpJPK2CodeStream(CPLXMLNode* psBox,
             READ_MARKER_FIELD_UINT32("YTOSiz");
             READ_MARKER_FIELD_UINT16("Csiz");
             int CSiz = nLastVal;
-            for(int i=0;i<CSiz;i++)
+            bError = false;
+            for(int i=0;i<CSiz && !bError;i++)
             {
                 READ_MARKER_FIELD_UINT8_COMMENT(CPLSPrintf("Ssiz%d", i),
                         GetInterpretationOfBPC(static_cast<GByte>(nLastVal)));
@@ -1215,6 +1234,8 @@ static CPLXMLNode* DumpJPK2CodeStream(CPLXMLNode* psBox,
             AddError(psCSBox, "Cannot seek to next marker", nOffset + 2 + nMarkerSize);
             break;
         }
+
+        CPL_IGNORE_RET_VAL(bError);
     }
     CPLFree(pabyMarkerData);
     return psCSBox;
diff --git a/gcore/gdalrasterband.cpp b/gcore/gdalrasterband.cpp
index e218c11..f282c61 100644
--- a/gcore/gdalrasterband.cpp
+++ b/gcore/gdalrasterband.cpp
@@ -51,7 +51,7 @@
 #include "gdal.h"
 #include "gdal_rat.h"
 
-CPL_CVSID("$Id: gdalrasterband.cpp 37473 2017-02-26 02:48:38Z goatbar $");
+CPL_CVSID("$Id: gdalrasterband.cpp 38303 2017-05-14 09:16:00Z rouault $");
 
 /************************************************************************/
 /*                           GDALRasterBand()                           */
@@ -6509,7 +6509,7 @@ void GDALRasterBand::ReportError( CPLErr eErrClass, CPLErrorNum err_no,
     const char* pszDSName = poDS ? poDS->GetDescription() : "";
     if( strlen(fmt) + strlen(pszDSName) + 20 >= sizeof(szNewFmt) - 1 )
         pszDSName = CPLGetFilename(pszDSName);
-    if( pszDSName[0] != '\0' &&
+    if( pszDSName[0] != '\0' && strchr(pszDSName, '%') == NULL &&
         strlen(fmt) + strlen(pszDSName) + 20 < sizeof(szNewFmt) - 1 )
     {
         snprintf(szNewFmt, sizeof(szNewFmt), "%s, band %d: %s",
diff --git a/m4/acinclude.m4 b/m4/acinclude.m4
index 33736f2..a8b181e 100644
--- a/m4/acinclude.m4
+++ b/m4/acinclude.m4
@@ -1,5 +1,5 @@
 dnl ***************************************************************************
-dnl $Id: acinclude.m4 37079 2017-01-09 22:46:26Z rouault $
+dnl $Id: acinclude.m4 38883 2017-06-05 08:08:26Z rouault $
 dnl
 dnl Project:  GDAL
 dnl Purpose:  Configure extra local definitions.
@@ -36,7 +36,7 @@ AC_DEFUN([AC_HAVE_LONG_LONG],
   AC_MSG_CHECKING([for 64bit integer type])
 
   echo 'int main() { long long off=0; }' >> conftest.c
-  if test -z "`${CC} -o conftest conftest.c 2>&1`" ; then
+  if test -z "`${CC} ${CCFLAGS} -o conftest conftest.c 2>&1`" ; then
     AC_DEFINE(HAVE_LONG_LONG, 1, [Define to 1, if your compiler supports long long data type])
     AC_MSG_RESULT([long long])
   else
@@ -108,7 +108,7 @@ AC_DEFUN([AC_UNIX_STDIO_64],
     echo '#include <sys/types.h>' >> conftest.c
     echo '#include <sys/stat.h>' >> conftest.c
     echo 'int main() { struct __stat64 buf; _stat64( "", &buf ); return 0; }' >> conftest.c
-    if test -z "`${CC} -o conftest conftest.c 2>&1`" ; then
+    if test -z "`${CC} ${CCFLAGS} -o conftest conftest.c 2>&1`" ; then
         with_unix_stdio_64=no
         AC_DEFINE_UNQUOTED(VSI_STAT64,_stat64, [Define to name of 64bit stat function])
         AC_DEFINE_UNQUOTED(VSI_STAT64_T,__stat64, [Define to name of 64bit stat structure])
@@ -122,9 +122,9 @@ AC_DEFUN([AC_UNIX_STDIO_64],
   fi
 
   if test x"$with_unix_stdio_64" = x"" ; then
-    echo '#include <stdio.h>' > conftest.cpp
+    echo '#include <stdio.h>' > conftest.c
     echo 'int main() { long long off=0; fseek64(NULL, off, SEEK_SET); off = ftell64(NULL); return 0; }' >> conftest.c
-    if test -z "`${CC} -o conftest conftest.c 2>&1`" ; then
+    if test -z "`${CC} ${CCFLAGS} -o conftest conftest.c 2>&1`" ; then
       with_unix_stdio_64=yes
       VSI_FTELL64=ftell64
       VSI_FSEEK64=fseek64
@@ -137,9 +137,9 @@ AC_DEFUN([AC_UNIX_STDIO_64],
   dnl by stdio.h.  With CXX (C++) this becomes a fatal error.
 
   if test x"$with_unix_stdio_64" = x"" ; then
-    echo '#include <stdio.h>' > conftest.c
-    echo 'int main() { long long off=0; fseeko64(NULL, off, SEEK_SET); off = ftello64(NULL); return 0; }' >> conftest.c
-    if test -z "`${CXX} -o conftest conftest.c 2>&1`" ; then
+    echo '#include <stdio.h>' > conftest.cpp
+    echo 'int main() { long long off=0; fseeko64(NULL, off, SEEK_SET); off = ftello64(NULL); return 0; }' >> conftest.cpp
+    if test -z "`${CXX} ${CXXFLAGS} -o conftest conftest.cpp 2>&1`" ; then
       with_unix_stdio_64=yes
       VSI_FTELL64=ftello64
       VSI_FSEEK64=fseeko64
@@ -151,10 +151,10 @@ AC_DEFUN([AC_UNIX_STDIO_64],
   dnl before including stdio.h.  This should work on Linux 2.4 series systems.
 
   if test x"$with_unix_stdio_64" = x"" ; then
-    echo '#define _LARGEFILE64_SOURCE' > conftest.c
-    echo '#include <stdio.h>' >> conftest.c
-    echo 'int main() { long long off=0; fseeko64(NULL, off, SEEK_SET); off = ftello64(NULL); return 0; }' >> conftest.c
-    if test -z "`${CXX} -o conftest conftest.c 2>&1`" ; then
+    echo '#define _LARGEFILE64_SOURCE' > conftest.cpp
+    echo '#include <stdio.h>' >> conftest.cpp
+    echo 'int main() { long long off=0; fseeko64(NULL, off, SEEK_SET); off = ftello64(NULL); return 0; }' >> conftest.cpp
+    if test -z "`${CXX} ${CXXFLAGS} -o conftest conftest.cpp 2>&1`" ; then
       with_unix_stdio_64=yes
       VSI_FTELL64=ftello64
       VSI_FSEEK64=fseeko64
@@ -181,7 +181,7 @@ AC_DEFUN([AC_UNIX_STDIO_64],
   if test x"$with_unix_stdio_64" = x"" ; then
     echo '#include <stdio.h>' > conftest.c
     echo 'int main() { fpos_t off=0; fseeko(NULL, off, SEEK_SET); off = ftello(NULL); return 0; }' >> conftest.c
-    if test -z "`${CC} -o conftest conftest.c 2>&1`" ; then
+    if test -z "`${CC} ${CCFLAGS} -o conftest conftest.c 2>&1`" ; then
       with_unix_stdio_64=yes
       VSI_FTELL64=ftello
       VSI_FSEEK64=fseeko
diff --git a/man/man1/gdal-config.1 b/man/man1/gdal-config.1
index bd5d20f..161e398 100644
--- a/man/man1/gdal-config.1
+++ b/man/man1/gdal-config.1
@@ -1,4 +1,4 @@
-.TH "gdal-config" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "gdal-config" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal2tiles.1 b/man/man1/gdal2tiles.1
index 8c18403..4737a40 100644
--- a/man/man1/gdal2tiles.1
+++ b/man/man1/gdal2tiles.1
@@ -1,4 +1,4 @@
-.TH "gdal2tiles" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "gdal2tiles" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_calc.1 b/man/man1/gdal_calc.1
index bc6007e..bc6f63a 100644
--- a/man/man1/gdal_calc.1
+++ b/man/man1/gdal_calc.1
@@ -1,4 +1,4 @@
-.TH "gdal_calc" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "gdal_calc" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_contour.1 b/man/man1/gdal_contour.1
index dc094a4..e85245e 100644
--- a/man/man1/gdal_contour.1
+++ b/man/man1/gdal_contour.1
@@ -1,4 +1,4 @@
-.TH "gdal_contour" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "gdal_contour" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_edit.1 b/man/man1/gdal_edit.1
index 804543e..90c6cfb 100644
--- a/man/man1/gdal_edit.1
+++ b/man/man1/gdal_edit.1
@@ -1,4 +1,4 @@
-.TH "gdal_edit" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "gdal_edit" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_fillnodata.1 b/man/man1/gdal_fillnodata.1
index 14c04b4..5295419 100644
--- a/man/man1/gdal_fillnodata.1
+++ b/man/man1/gdal_fillnodata.1
@@ -1,4 +1,4 @@
-.TH "gdal_fillnodata" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "gdal_fillnodata" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_grid.1 b/man/man1/gdal_grid.1
index 2ffd052..0762938 100644
--- a/man/man1/gdal_grid.1
+++ b/man/man1/gdal_grid.1
@@ -1,4 +1,4 @@
-.TH "gdal_grid" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "gdal_grid" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_merge.1 b/man/man1/gdal_merge.1
index 8453289..fd46d8a 100644
--- a/man/man1/gdal_merge.1
+++ b/man/man1/gdal_merge.1
@@ -1,4 +1,4 @@
-.TH "gdal_merge" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "gdal_merge" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_pansharpen.1 b/man/man1/gdal_pansharpen.1
index 07191b3..1b04e1f 100644
--- a/man/man1/gdal_pansharpen.1
+++ b/man/man1/gdal_pansharpen.1
@@ -1,4 +1,4 @@
-.TH "gdal_pansharpen" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "gdal_pansharpen" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_polygonize.1 b/man/man1/gdal_polygonize.1
index b1e26e6..da0ea3e 100644
--- a/man/man1/gdal_polygonize.1
+++ b/man/man1/gdal_polygonize.1
@@ -1,4 +1,4 @@
-.TH "gdal_polygonize" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "gdal_polygonize" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_proximity.1 b/man/man1/gdal_proximity.1
index 45a353f..d027498 100644
--- a/man/man1/gdal_proximity.1
+++ b/man/man1/gdal_proximity.1
@@ -1,4 +1,4 @@
-.TH "gdal_proximity" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "gdal_proximity" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_rasterize.1 b/man/man1/gdal_rasterize.1
index f25540e..c5dee57 100644
--- a/man/man1/gdal_rasterize.1
+++ b/man/man1/gdal_rasterize.1
@@ -1,4 +1,4 @@
-.TH "gdal_rasterize" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "gdal_rasterize" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_retile.1 b/man/man1/gdal_retile.1
index 516139c..f5d7d00 100644
--- a/man/man1/gdal_retile.1
+++ b/man/man1/gdal_retile.1
@@ -1,4 +1,4 @@
-.TH "gdal_retile" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "gdal_retile" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_sieve.1 b/man/man1/gdal_sieve.1
index ca20acf..9b318c4 100644
--- a/man/man1/gdal_sieve.1
+++ b/man/man1/gdal_sieve.1
@@ -1,4 +1,4 @@
-.TH "gdal_sieve" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "gdal_sieve" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_translate.1 b/man/man1/gdal_translate.1
index 66a4efd..3b25126 100644
--- a/man/man1/gdal_translate.1
+++ b/man/man1/gdal_translate.1
@@ -1,4 +1,4 @@
-.TH "gdal_translate" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "gdal_translate" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_utilities.1 b/man/man1/gdal_utilities.1
index 346da27..1e6243a 100644
--- a/man/man1/gdal_utilities.1
+++ b/man/man1/gdal_utilities.1
@@ -1,4 +1,4 @@
-.TH "gdal_utilities" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "gdal_utilities" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdaladdo.1 b/man/man1/gdaladdo.1
index 79a4b8c..0857e0b 100644
--- a/man/man1/gdaladdo.1
+++ b/man/man1/gdaladdo.1
@@ -1,4 +1,4 @@
-.TH "gdaladdo" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "gdaladdo" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalbuildvrt.1 b/man/man1/gdalbuildvrt.1
index 7a2a672..3347e69 100644
--- a/man/man1/gdalbuildvrt.1
+++ b/man/man1/gdalbuildvrt.1
@@ -1,4 +1,4 @@
-.TH "gdalbuildvrt" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "gdalbuildvrt" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalcompare.1 b/man/man1/gdalcompare.1
index d5212b9..5d285ef 100644
--- a/man/man1/gdalcompare.1
+++ b/man/man1/gdalcompare.1
@@ -1,4 +1,4 @@
-.TH "gdalcompare" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "gdalcompare" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdaldem.1 b/man/man1/gdaldem.1
index b9a64dd..9a3a6e4 100644
--- a/man/man1/gdaldem.1
+++ b/man/man1/gdaldem.1
@@ -1,4 +1,4 @@
-.TH "gdaldem" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "gdaldem" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalinfo.1 b/man/man1/gdalinfo.1
index 60f85ea..2294801 100644
--- a/man/man1/gdalinfo.1
+++ b/man/man1/gdalinfo.1
@@ -1,4 +1,4 @@
-.TH "gdalinfo" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "gdalinfo" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdallocationinfo.1 b/man/man1/gdallocationinfo.1
index 6198e67..fe95694 100644
--- a/man/man1/gdallocationinfo.1
+++ b/man/man1/gdallocationinfo.1
@@ -1,4 +1,4 @@
-.TH "gdallocationinfo" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "gdallocationinfo" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalmanage.1 b/man/man1/gdalmanage.1
index 290405a..663ff57 100644
--- a/man/man1/gdalmanage.1
+++ b/man/man1/gdalmanage.1
@@ -1,4 +1,4 @@
-.TH "gdalmanage" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "gdalmanage" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalmove.1 b/man/man1/gdalmove.1
index 78263cb..2dabd47 100644
--- a/man/man1/gdalmove.1
+++ b/man/man1/gdalmove.1
@@ -1,4 +1,4 @@
-.TH "gdalmove" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "gdalmove" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalsrsinfo.1 b/man/man1/gdalsrsinfo.1
index b86a256..12d0f25 100644
--- a/man/man1/gdalsrsinfo.1
+++ b/man/man1/gdalsrsinfo.1
@@ -1,4 +1,4 @@
-.TH "gdalsrsinfo" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "gdalsrsinfo" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdaltindex.1 b/man/man1/gdaltindex.1
index 282793d..055922c 100644
--- a/man/man1/gdaltindex.1
+++ b/man/man1/gdaltindex.1
@@ -1,4 +1,4 @@
-.TH "gdaltindex" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "gdaltindex" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdaltransform.1 b/man/man1/gdaltransform.1
index ee028ac..53e1d65 100644
--- a/man/man1/gdaltransform.1
+++ b/man/man1/gdaltransform.1
@@ -1,4 +1,4 @@
-.TH "gdaltransform" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "gdaltransform" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalwarp.1 b/man/man1/gdalwarp.1
index 865c5fb..77871e4 100644
--- a/man/man1/gdalwarp.1
+++ b/man/man1/gdalwarp.1
@@ -1,4 +1,4 @@
-.TH "gdalwarp" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "gdalwarp" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gnm_utilities.1 b/man/man1/gnm_utilities.1
index 2d2baea..6d9b086 100644
--- a/man/man1/gnm_utilities.1
+++ b/man/man1/gnm_utilities.1
@@ -1,4 +1,4 @@
-.TH "gnm_utilities" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "gnm_utilities" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gnmanalyse.1 b/man/man1/gnmanalyse.1
index 5859b61..5bbf260 100644
--- a/man/man1/gnmanalyse.1
+++ b/man/man1/gnmanalyse.1
@@ -1,4 +1,4 @@
-.TH "gnmanalyse" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "gnmanalyse" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gnmmanage.1 b/man/man1/gnmmanage.1
index b330b04..edaebea 100644
--- a/man/man1/gnmmanage.1
+++ b/man/man1/gnmmanage.1
@@ -1,4 +1,4 @@
-.TH "gnmmanage" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "gnmmanage" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/nearblack.1 b/man/man1/nearblack.1
index 832f662..647cc57 100644
--- a/man/man1/nearblack.1
+++ b/man/man1/nearblack.1
@@ -1,4 +1,4 @@
-.TH "nearblack" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "nearblack" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/ogr2ogr.1 b/man/man1/ogr2ogr.1
index 2596fb0..00ff254 100644
--- a/man/man1/ogr2ogr.1
+++ b/man/man1/ogr2ogr.1
@@ -1,4 +1,4 @@
-.TH "ogr2ogr" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "ogr2ogr" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/ogr_utilities.1 b/man/man1/ogr_utilities.1
index 8836842..995383c 100644
--- a/man/man1/ogr_utilities.1
+++ b/man/man1/ogr_utilities.1
@@ -1,4 +1,4 @@
-.TH "ogr_utilities" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "ogr_utilities" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/ogrinfo.1 b/man/man1/ogrinfo.1
index a5d3925..0b08dc8 100644
--- a/man/man1/ogrinfo.1
+++ b/man/man1/ogrinfo.1
@@ -1,4 +1,4 @@
-.TH "ogrinfo" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "ogrinfo" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/ogrlineref.1 b/man/man1/ogrlineref.1
index 1d4b620..75f5b19 100644
--- a/man/man1/ogrlineref.1
+++ b/man/man1/ogrlineref.1
@@ -1,4 +1,4 @@
-.TH "ogrlineref" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "ogrlineref" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/ogrmerge.1 b/man/man1/ogrmerge.1
index 83a70ae..05e7080 100644
--- a/man/man1/ogrmerge.1
+++ b/man/man1/ogrmerge.1
@@ -1,4 +1,4 @@
-.TH "ogrmerge" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "ogrmerge" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/ogrtindex.1 b/man/man1/ogrtindex.1
index 73b701e..57b5b85 100644
--- a/man/man1/ogrtindex.1
+++ b/man/man1/ogrtindex.1
@@ -1,4 +1,4 @@
-.TH "ogrtindex" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "ogrtindex" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/pct2rgb.1 b/man/man1/pct2rgb.1
index 64a01ca..7efc979 100644
--- a/man/man1/pct2rgb.1
+++ b/man/man1/pct2rgb.1
@@ -1,4 +1,4 @@
-.TH "pct2rgb" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "pct2rgb" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/rgb2pct.1 b/man/man1/rgb2pct.1
index 7c758a1..96130fb 100644
--- a/man/man1/rgb2pct.1
+++ b/man/man1/rgb2pct.1
@@ -1,4 +1,4 @@
-.TH "rgb2pct" 1 "Fri Apr 28 2017" "GDAL" \" -*- nroff -*-
+.TH "rgb2pct" 1 "Fri Jun 23 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/ogr/ogr_srs_esri.cpp b/ogr/ogr_srs_esri.cpp
index bd03faa..486c86c 100644
--- a/ogr/ogr_srs_esri.cpp
+++ b/ogr/ogr_srs_esri.cpp
@@ -50,7 +50,7 @@
 #include "ogr_p.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ogr_srs_esri.cpp 36472 2016-11-23 16:38:20Z rouault $");
+CPL_CVSID("$Id: ogr_srs_esri.cpp 38677 2017-05-29 11:07:01Z rouault $");
 
 extern void OGREPSGDatumNameMassage( char ** ppszDatum );
 
@@ -2102,7 +2102,7 @@ OGRErr OGRSpatialReference::morphFromESRI()
                 FindProjParm( "Standard_Parallel_1", poPROJCS );
             const int iLatOrigChild =
                 FindProjParm( "Latitude_Of_Origin", poPROJCS );
-            if( iSP1Child != -1 && iLatOrigChild != 1 )
+            if( iSP1Child != -1 && iLatOrigChild != -1 )
             {
                 // Do a sanity check before removing Standard_Parallel_1.
                 if( EQUAL(poPROJCS->GetChild(iSP1Child)->GetValue(),
@@ -2132,6 +2132,12 @@ OGRErr OGRSpatialReference::morphFromESRI()
                               const_cast<char **>(papszDatumMapping+2),
                               3 );
 
+    // Refresh poDatum as the above SetNode() calls might have invalidated
+    // it.
+    poDatum = GetAttrNode( "DATUM" );
+    if( poDatum != NULL )
+        poDatum = poDatum->GetChild(0);
+
 /* -------------------------------------------------------------------- */
 /*      Special case for Peru96 related SRS that should use the         */
 /*      Peru96 DATUM, but in ESRI world, both Peru96 and SIRGAS-Chile   */
@@ -2143,7 +2149,7 @@ OGRErr OGRSpatialReference::morphFromESRI()
         const char* pszSRSName = GetAttrValue("PROJCS");
         if( pszSRSName == NULL )
             pszSRSName = GetAttrValue("GEOGCS");
-        if( strstr(pszSRSName, "Peru96") )
+        if( pszSRSName != NULL && strstr(pszSRSName, "Peru96") )
         {
             bPeru96Datum = true;
             poDatum->SetValue( "Peru96" );
diff --git a/ogr/ogrcurvecollection.cpp b/ogr/ogrcurvecollection.cpp
index 1a6cda4..1a4df66 100644
--- a/ogr/ogrcurvecollection.cpp
+++ b/ogr/ogrcurvecollection.cpp
@@ -40,7 +40,7 @@
 #include "cpl_string.h"
 #include "cpl_vsi.h"
 
-CPL_CVSID("$Id: ogrcurvecollection.cpp 37852 2017-03-27 15:31:30Z rouault $");
+CPL_CVSID("$Id: ogrcurvecollection.cpp 39065 2017-06-11 13:17:51Z rouault $");
 
 //! @cond Doxygen_Suppress
 
@@ -272,15 +272,16 @@ OGRErr OGRCurveCollection::importBodyFromWkb(
         if( nSize < 9 && nSize != -1 )
             return OGRERR_NOT_ENOUGH_DATA;
 
-        OGRwkbGeometryType eSubGeomType = wkbUnknown;
+        OGRwkbGeometryType eFlattenSubGeomType = wkbUnknown;
         if( OGRReadWKBGeometryType( pabySubData, eWkbVariant,
-                                    &eSubGeomType ) != OGRERR_NONE )
+                                    &eFlattenSubGeomType ) != OGRERR_NONE )
             return OGRERR_FAILURE;
+        eFlattenSubGeomType = wkbFlatten(eFlattenSubGeomType);
 
         OGRErr eErr = OGRERR_NONE;
-        if( (eSubGeomType != wkbCompoundCurve &&
-             OGR_GT_IsCurve(eSubGeomType)) ||
-            (bAcceptCompoundCurve && eSubGeomType == wkbCompoundCurve) )
+        if( (eFlattenSubGeomType != wkbCompoundCurve &&
+             OGR_GT_IsCurve(eFlattenSubGeomType)) ||
+            (bAcceptCompoundCurve && eFlattenSubGeomType == wkbCompoundCurve) )
         {
             eErr = OGRGeometryFactory::
                 createFromWkb( pabySubData, NULL,
@@ -291,12 +292,20 @@ OGRErr OGRCurveCollection::importBodyFromWkb(
             CPLDebug(
                 "OGR",
                 "Cannot add geometry of type (%d) to geometry of type (%d)",
-                eSubGeomType, poGeom->getGeometryType());
+                eFlattenSubGeomType, poGeom->getGeometryType());
             return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
         }
 
         if( eErr == OGRERR_NONE )
         {
+            // Do that before adding the curve to the collection, since that
+            // might change its dimensions.
+            const int nSubGeomWkbSize = poSubGeom->WkbSize();
+            if( nSize != -1 )
+                nSize -= nSubGeomWkbSize;
+
+            nDataOffset += nSubGeomWkbSize;
+
             OGRCurve *poCurve = dynamic_cast<OGRCurve *>(poSubGeom);
             if( poCurve == NULL )
             {
@@ -311,11 +320,6 @@ OGRErr OGRCurveCollection::importBodyFromWkb(
             return eErr;
         }
 
-        const int nSubGeomWkbSize = poSubGeom->WkbSize();
-        if( nSize != -1 )
-            nSize -= nSubGeomWkbSize;
-
-        nDataOffset += nSubGeomWkbSize;
     }
 
     return OGRERR_NONE;
diff --git a/ogr/ogrgeometry.cpp b/ogr/ogrgeometry.cpp
index d65f202..b6fceea 100644
--- a/ogr/ogrgeometry.cpp
+++ b/ogr/ogrgeometry.cpp
@@ -56,7 +56,7 @@
 #define UNUSED_IF_NO_GEOS
 #endif
 
-CPL_CVSID("$Id: ogrgeometry.cpp 37004 2016-12-23 14:57:46Z goatbar $");
+CPL_CVSID("$Id: ogrgeometry.cpp 38291 2017-05-14 00:40:31Z rouault $");
 
 //! @cond Doxygen_Suppress
 int OGRGeometry::bGenerate_DB2_V72_BYTE_ORDER = FALSE;
@@ -6122,7 +6122,7 @@ OGRErr OGRGeometry::importPreambuleOfCollectionFromWkb( unsigned char * pabyData
     if( OGR_SWAP( eByteOrder ) )
         nGeomCount = CPL_SWAP32(nGeomCount);
 
-    if( nGeomCount < 0 || nGeomCount > INT_MAX / 4 )
+    if( nGeomCount < 0 || nGeomCount > INT_MAX / nMinSubGeomSize )
     {
         nGeomCount = 0;
         return OGRERR_CORRUPT_DATA;
@@ -6232,8 +6232,8 @@ OGRErr OGRGeometry::importCurveCollectionFromWkt(
             poCurve = dynamic_cast<OGRCurve *>(poGeom);
             if( poCurve == NULL )
             {
-                CPLError(CE_Fatal, CPLE_AppDefined,
-                         "dynamic_cast failed.  Expected OGRCurve.");
+                delete poGeom;
+                eErr = OGRERR_CORRUPT_DATA;
             }
         }
         else
diff --git a/ogr/ogrgeometryfactory.cpp b/ogr/ogrgeometryfactory.cpp
index 4e567a2..4b25dd0 100644
--- a/ogr/ogrgeometryfactory.cpp
+++ b/ogr/ogrgeometryfactory.cpp
@@ -62,7 +62,7 @@
 #define UNUSED_IF_NO_GEOS
 #endif
 
-CPL_CVSID("$Id: ogrgeometryfactory.cpp 38117 2017-04-23 07:36:29Z rouault $");
+CPL_CVSID("$Id: ogrgeometryfactory.cpp 38398 2017-05-16 08:25:00Z rouault $");
 
 /************************************************************************/
 /*                           createFromWkb()                            */
@@ -1450,6 +1450,7 @@ OGRGeometry* OGRGeometryFactory::organizePolygons( OGRGeometry **papoPolygons,
         if( eType == wkbCurvePolygon )
             bHasCurves = true;
         if( asPolyEx[i].poPolygon != NULL
+            && !asPolyEx[i].poPolygon->IsEmpty()
             && asPolyEx[i].poPolygon->getNumInteriorRings() == 0
             && asPolyEx[i].poPolygon->
                 getExteriorRingCurve()->getNumPoints() >= 4)
diff --git a/ogr/ogrmultisurface.cpp b/ogr/ogrmultisurface.cpp
index c06b976..ec40ad0 100644
--- a/ogr/ogrmultisurface.cpp
+++ b/ogr/ogrmultisurface.cpp
@@ -37,7 +37,7 @@
 #include "ogr_core.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrmultisurface.cpp 36379 2016-11-21 09:38:41Z rouault $");
+CPL_CVSID("$Id: ogrmultisurface.cpp 38291 2017-05-14 00:40:31Z rouault $");
 
 /************************************************************************/
 /*                          OGRMultiSurface()                           */
@@ -216,8 +216,9 @@ OGRErr OGRMultiSurface::importFromWkt( char ** ppszInput )
             poSurface = dynamic_cast<OGRSurface*>(poGeom);
             if( poSurface == NULL )
             {
-                CPLError(CE_Fatal, CPLE_AppDefined,
-                         "dynamic_cast failed.  Expected OGRSurface.");
+                delete poGeom;
+                eErr = OGRERR_CORRUPT_DATA;
+                break;
             }
         }
         else
diff --git a/ogr/ogrpgeogeometry.cpp b/ogr/ogrpgeogeometry.cpp
index 1911785..458f883 100644
--- a/ogr/ogrpgeogeometry.cpp
+++ b/ogr/ogrpgeogeometry.cpp
@@ -51,7 +51,7 @@
 #include "ogr_core.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrpgeogeometry.cpp 37654 2017-03-09 07:42:07Z rouault $");
+CPL_CVSID("$Id: ogrpgeogeometry.cpp 38691 2017-05-30 14:03:26Z rouault $");
 
 static const int SHPP_TRISTRIP  = 0;
 static const int SHPP_TRIFAN    = 1;
@@ -411,7 +411,16 @@ OGRGeometry* OGRCreateFromMultiPatch       ( int nParts,
             nPartPoints == 4 &&
             padfX[nPartStart] == padfX[nPartStart + 3] &&
             padfY[nPartStart] == padfY[nPartStart + 3] &&
-            padfZ[nPartStart] == padfZ[nPartStart + 3] )
+            padfZ[nPartStart] == padfZ[nPartStart + 3] &&
+            !CPLIsNan(padfX[nPartStart]) &&
+            !CPLIsNan(padfX[nPartStart+1]) &&
+            !CPLIsNan(padfX[nPartStart+2]) &&
+            !CPLIsNan(padfY[nPartStart]) &&
+            !CPLIsNan(padfY[nPartStart+1]) &&
+            !CPLIsNan(padfY[nPartStart+2]) &&
+            !CPLIsNan(padfZ[nPartStart]) &&
+            !CPLIsNan(padfZ[nPartStart+1]) &&
+            !CPLIsNan(padfZ[nPartStart+2]) )
         {
             bool bDuplicate = false;
             if( iPart > 0 )
diff --git a/ogr/ogrpolygon.cpp b/ogr/ogrpolygon.cpp
index 6497903..b231566 100644
--- a/ogr/ogrpolygon.cpp
+++ b/ogr/ogrpolygon.cpp
@@ -42,7 +42,7 @@
 #include "ogr_sfcgal.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrpolygon.cpp 36883 2016-12-15 13:31:12Z rouault $");
+CPL_CVSID("$Id: ogrpolygon.cpp 38291 2017-05-14 00:40:31Z rouault $");
 
 /************************************************************************/
 /*                             OGRPolygon()                             */
@@ -542,6 +542,7 @@ OGRErr OGRPolygon::importFromWKTListOnly( char ** ppszInput,
                                       &nMaxPoints, &nPoints );
         if( pszInput == NULL || nPoints == 0 )
         {
+            CPLFree(padfM);
             return OGRERR_CORRUPT_DATA;
         }
         if( (flagsFromInput & OGR_G_3D) && !(flags & OGR_G_3D) )
diff --git a/ogr/ogrsf_frmts/dgn/dgnread.cpp b/ogr/ogrsf_frmts/dgn/dgnread.cpp
index 0ee414c..5a03912 100644
--- a/ogr/ogrsf_frmts/dgn/dgnread.cpp
+++ b/ogr/ogrsf_frmts/dgn/dgnread.cpp
@@ -30,7 +30,7 @@
 
 #include <algorithm>
 
-CPL_CVSID("$Id: dgnread.cpp 37472 2017-02-26 02:47:45Z goatbar $");
+CPL_CVSID("$Id: dgnread.cpp 38747 2017-05-31 22:12:52Z rouault $");
 
 static DGNElemCore *DGNParseTCB( DGNInfo * );
 static DGNElemCore *DGNParseColorTable( DGNInfo * );
@@ -465,7 +465,8 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
               psLine->vertices[1].z = DGN_INT32( psDGN->abyElem + 56 );
           }
 
-          if (deltaStart && deltaLength)
+          if (deltaStart && deltaLength &&
+              deltaStart + 1 * 4 + 2 + 2 <= psLine->core.attr_bytes)
           {
               for (int i=0; i<2; i++)
               {
@@ -542,7 +543,8 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
               if( psDGN->dimension == 3 )
                   psLine->vertices[i].z =
                       DGN_INT32( psDGN->abyElem + 46 + i*pntsize );
-              if (deltaStart && deltaLength)
+              if (deltaStart && deltaLength &&
+                  deltaStart + i * 4 + 2 + 2 <= psLine->core.attr_bytes)
               {
                 int dx = DGN_INT16(psLine->core.attr_data + deltaStart + i * 4);
                 int dy = DGN_INT16(psLine->core.attr_data + deltaStart + i * 4 + 2);
@@ -1023,7 +1025,8 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
             psBounds->vertices[i].x = DGN_INT32( psDGN->abyElem + 40 + i*8 );
             psBounds->vertices[i].y = DGN_INT32( psDGN->abyElem + 44 + i*8 );
             psBounds->vertices[i].z = 0;
-            if (deltaStart && deltaLength)
+            if (deltaStart && deltaLength &&
+                deltaStart + i * 4 + 2 + 2 <= psBounds->core.attr_bytes)
             {
                 int dx = DGN_INT16(psBounds->core.attr_data + deltaStart + i * 4);
                 int dy = DGN_INT16(psBounds->core.attr_data + deltaStart + i * 4 + 2);
diff --git a/ogr/ogrsf_frmts/dxf/ogr_autocad_services.cpp b/ogr/ogrsf_frmts/dxf/ogr_autocad_services.cpp
index 0f0d294..713b09b 100644
--- a/ogr/ogrsf_frmts/dxf/ogr_autocad_services.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogr_autocad_services.cpp
@@ -30,7 +30,7 @@
 #include "ogr_autocad_services.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogr_autocad_services.cpp 36981 2016-12-20 19:46:41Z rouault $");
+CPL_CVSID("$Id: ogr_autocad_services.cpp 38338 2017-05-14 15:21:43Z rouault $");
 
 /************************************************************************/
 /*                           ACTextUnescape()                           */
@@ -73,7 +73,7 @@ CPLString ACTextUnescape( const char *pszRawInput, const char *pszEncoding )
             pszInput++;
         }
         else if( pszInput[0] == '\\' && pszInput[1] == 'U'
-                 && pszInput[2] == '+' )
+                 && pszInput[2] == '+' && CPLStrnlen(pszInput, 7) >= 7 )
         {
             CPLString osHex;
             unsigned int iChar = 0;
@@ -107,6 +107,8 @@ CPLString ACTextUnescape( const char *pszRawInput, const char *pszEncoding )
 
             while( *pszInput != ';' && *pszInput != '\0' )
                 pszInput++;
+            if( *pszInput == '\0' )
+                break;
         }
         else if( pszInput[0] == '\\' && pszInput[1] == '\\' )
         {
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxf_blockmap.cpp b/ogr/ogrsf_frmts/dxf/ogrdxf_blockmap.cpp
index a726e9e..7048368 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxf_blockmap.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxf_blockmap.cpp
@@ -32,7 +32,7 @@
 #include "cpl_string.h"
 #include "cpl_csv.h"
 
-CPL_CVSID("$Id: ogrdxf_blockmap.cpp 36682 2016-12-04 20:34:45Z rouault $");
+CPL_CVSID("$Id: ogrdxf_blockmap.cpp 38342 2017-05-14 18:13:16Z rouault $");
 
 /************************************************************************/
 /*                          ReadBlockSection()                          */
@@ -80,6 +80,12 @@ bool OGRDXFDataSource::ReadBlocksSection()
         if (nCode >= 0)
             UnreadValue();
 
+        if( oBlockMap.find(osBlockName) != oBlockMap.end() )
+        {
+            DXF_READER_ERROR();
+            return false;
+        }
+
         // Now we will process entities till we run out at the ENDBLK code.
         // we aggregate the geometries of the features into a multi-geometry,
         // but throw away other stuff attached to the features.
@@ -98,7 +104,9 @@ bool OGRDXFDataSource::ReadBlocksSection()
             }
             else
             {
-                poColl->addGeometryDirectly( poFeature->StealGeometry() );
+                OGRGeometry* poSubGeom = poFeature->StealGeometry();
+                if( poSubGeom )
+                    poColl->addGeometryDirectly( poSubGeom );
                 delete poFeature;
             }
         }
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxflayer.cpp b/ogr/ogrsf_frmts/dxf/ogrdxflayer.cpp
index a542fec..b8a1248 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxflayer.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxflayer.cpp
@@ -34,7 +34,7 @@
 
 #include <cmath>
 
-CPL_CVSID("$Id: ogrdxflayer.cpp 37837 2017-03-23 22:13:09Z rouault $");
+CPL_CVSID("$Id: ogrdxflayer.cpp 38666 2017-05-29 10:03:12Z rouault $");
 
 /************************************************************************/
 /*                            OGRDXFLayer()                             */
@@ -1748,14 +1748,35 @@ OGRFeature *OGRDXFLayer::TranslateSPLINE()
 
           case 71:
             nDegree = atoi(szLineBuf);
+            // Arbitrary threshold
+            if( nDegree < 0 || nDegree > 100)
+            {
+                DXF_LAYER_READER_ERROR();
+                delete poFeature;
+                return NULL;
+            }
             break;
 
           case 72:
             nKnots = atoi(szLineBuf);
+            // Arbitrary threshold
+            if( nKnots < 0 || nKnots > 10000000)
+            {
+                DXF_LAYER_READER_ERROR();
+                delete poFeature;
+                return NULL;
+            }
             break;
 
           case 73:
             nControlPoints = atoi(szLineBuf);
+            // Arbitrary threshold
+            if( nControlPoints < 0 || nControlPoints > 10000000)
+            {
+                DXF_LAYER_READER_ERROR();
+                delete poFeature;
+                return NULL;
+            }
             break;
 
           default:
diff --git a/ogr/ogrsf_frmts/geojson/libjson/json_object.c b/ogr/ogrsf_frmts/geojson/libjson/json_object.c
index 26758f2..65020ec 100644
--- a/ogr/ogrsf_frmts/geojson/libjson/json_object.c
+++ b/ogr/ogrsf_frmts/geojson/libjson/json_object.c
@@ -564,7 +564,9 @@ static int json_object_double_to_json_string(struct json_object* jso,
   char buf[128], *p, *q;
   int size;
 
-  size = snprintf(buf, 128, "%f", jso->o.c_double);
+  size = snprintf(buf, sizeof(buf), "%f", jso->o.c_double);
+  if( size < 0 || size > (int)sizeof(buf) )
+      size = (int)sizeof(buf);
   p = strchr(buf, ',');
   if (p) {
     *p = '.';
diff --git a/ogr/ogrsf_frmts/geojson/ogresrijsonreader.cpp b/ogr/ogrsf_frmts/geojson/ogresrijsonreader.cpp
index bb5b899..5f6ff10 100644
--- a/ogr/ogrsf_frmts/geojson/ogresrijsonreader.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogresrijsonreader.cpp
@@ -50,7 +50,7 @@
 #include "ogrgeojsonutils.h"
 // #include "symbol_renames.h"
 
-CPL_CVSID("$Id: ogresrijsonreader.cpp 38127 2017-04-23 14:58:22Z rouault $");
+CPL_CVSID("$Id: ogresrijsonreader.cpp 38620 2017-05-23 09:32:47Z rouault $");
 
 /************************************************************************/
 /*                          OGRESRIJSONReader()                         */
@@ -771,9 +771,7 @@ OGRGeometry* OGRESRIJSONReadLineString( json_object* poObj )
             if( !OGRESRIJSONReaderParseXYZMArray (
               poObjCoords, bHasZ, bHasM, &dfX, &dfY, &dfZ, &dfM, &nNumCoords) )
             {
-                if( poRet != poLine )
-                    delete poRet;
-                delete poLine;
+                delete poRet;
                 return NULL;
             }
 
@@ -995,7 +993,9 @@ OGRSpatialReference* OGRESRIJSONReadSpatialReference( json_object* poObj )
         OGRGeoJSONFindMemberByName( poObj, "spatialReference" );
     if( NULL != poObjSrs )
     {
-        json_object* poObjWkid = OGRGeoJSONFindMemberByName( poObjSrs, "wkid" );
+        json_object* poObjWkid = OGRGeoJSONFindMemberByName( poObjSrs, "latestWkid" );
+        if( poObjWkid == NULL )
+            poObjWkid = OGRGeoJSONFindMemberByName( poObjSrs, "wkid" );
         if( poObjWkid == NULL )
         {
             json_object* poObjWkt =
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsondriver.cpp b/ogr/ogrsf_frmts/geojson/ogrgeojsondriver.cpp
index 67b1c54..3f98299 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsondriver.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsondriver.cpp
@@ -45,7 +45,7 @@
 #include "ogrgeojsonutils.h"
 #include "ogrsf_frmts.h"
 
-CPL_CVSID("$Id: ogrgeojsondriver.cpp 37374 2017-02-13 11:59:01Z goatbar $");
+CPL_CVSID("$Id: ogrgeojsondriver.cpp 38520 2017-05-20 15:08:48Z rouault $");
 
 class OGRESRIFeatureServiceDataset;
 
@@ -58,6 +58,7 @@ class OGRESRIFeatureServiceLayer: public OGRLayer
     OGRESRIFeatureServiceDataset* poDS;
     OGRFeatureDefn* poFeatureDefn;
     GIntBig         nFeaturesRead;
+    GIntBig         nFirstFID;
     GIntBig         nLastFID;
     bool            bOtherPage;
     bool            bUseSequentialFID;
@@ -116,6 +117,7 @@ OGRESRIFeatureServiceLayer::OGRESRIFeatureServiceLayer(
     OGRESRIFeatureServiceDataset* poDSIn) :
     poDS(poDSIn),
     nFeaturesRead(0),
+    nFirstFID(0),
     nLastFID(0),
     bOtherPage(false),
     bUseSequentialFID(false)
@@ -173,12 +175,22 @@ OGRFeature* OGRESRIFeatureServiceLayer::GetNextFeature()
             if( poSrcFeat == NULL )
                 return NULL;
             bOtherPage = true;
+            if( bWasInFirstPage && poSrcFeat->GetFID() != 0 &&
+                poSrcFeat->GetFID() == nFirstFID )
+            {
+                // End-less looping
+                CPLDebug("ESRIJSON", "Scrolling not working. Stopping");
+                delete poSrcFeat;
+                return NULL;
+            }
+            if( bWasInFirstPage && poSrcFeat->GetFID() == 0 &&
+                nLastFID == nFeaturesRead - 1 )
+            {
+                bUseSequentialFID = true;
+            }
         }
-        if( bOtherPage && bWasInFirstPage && poSrcFeat->GetFID() == 0 &&
-            nLastFID == nFeaturesRead - 1 )
-        {
-            bUseSequentialFID = true;
-        }
+        if( nFeaturesRead == 0 )
+            nFirstFID = poSrcFeat->GetFID();
 
         OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
         poFeature->SetFrom(poSrcFeat);
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonutils.cpp b/ogr/ogrsf_frmts/geojson/ogrgeojsonutils.cpp
index 03b9424..7e6f67d 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonutils.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonutils.cpp
@@ -33,7 +33,7 @@
 #include <ogr_geometry.h>
 #include <json.h> // JSON-C
 
-CPL_CVSID("$Id: ogrgeojsonutils.cpp 35836 2016-10-20 13:57:15Z goatbar $");
+CPL_CVSID("$Id: ogrgeojsonutils.cpp 39217 2017-06-20 20:43:30Z rouault $");
 
 /************************************************************************/
 /*                           GeoJSONIsObject()                          */
@@ -300,22 +300,21 @@ const char* OGRGeoJSONGetGeometryName( OGRGeometry const* poGeometry )
 {
     CPLAssert( NULL != poGeometry );
 
-    const OGRwkbGeometryType eType = poGeometry->getGeometryType();
+    const OGRwkbGeometryType eType = wkbFlatten(poGeometry->getGeometryType());
 
-    if( wkbPoint == eType || wkbPoint25D == eType )
+    if( wkbPoint == eType )
         return "Point";
-    else if( wkbLineString == eType || wkbLineString25D == eType )
+    else if( wkbLineString == eType )
         return "LineString";
-    else if( wkbPolygon == eType || wkbPolygon25D == eType )
+    else if( wkbPolygon == eType )
         return "Polygon";
-    else if( wkbMultiPoint == eType || wkbMultiPoint25D == eType )
+    else if( wkbMultiPoint == eType )
         return "MultiPoint";
-    else if( wkbMultiLineString == eType || wkbMultiLineString25D == eType )
+    else if( wkbMultiLineString == eType )
         return "MultiLineString";
-    else if( wkbMultiPolygon == eType || wkbMultiPolygon25D == eType )
+    else if( wkbMultiPolygon == eType )
         return "MultiPolygon";
-    else if( wkbGeometryCollection == eType ||
-             wkbGeometryCollection25D == eType )
+    else if( wkbGeometryCollection == eType )
         return "GeometryCollection";
 
     return "Unknown";
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.cpp b/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.cpp
index 2c1eddf..ef5d281 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.cpp
@@ -37,7 +37,7 @@
 #include <ogr_api.h>
 #include <ogr_p.h>
 
-CPL_CVSID("$Id: ogrgeojsonwriter.cpp 37371 2017-02-13 11:41:59Z rouault $");
+CPL_CVSID("$Id: ogrgeojsonwriter.cpp 39217 2017-06-20 20:43:30Z rouault $");
 
 
 /************************************************************************/
@@ -657,7 +657,7 @@ json_object* OGRGeoJSONWriteFeature( OGRFeature* poFeature,
             json_object_array_add(
                 poObjBBOX,
                 json_object_new_coord(sEnvelope.MinY, oOptions));
-            if( poGeometry->getCoordinateDimension() == 3 )
+            if( wkbHasZ(poGeometry->getGeometryType()) )
                 json_object_array_add(
                     poObjBBOX,
                     json_object_new_coord(sEnvelope.MinZ, oOptions));
@@ -667,7 +667,7 @@ json_object* OGRGeoJSONWriteFeature( OGRFeature* poFeature,
             json_object_array_add(
                 poObjBBOX,
                 json_object_new_coord(sEnvelope.MaxY, oOptions));
-            if( poGeometry->getCoordinateDimension() == 3 )
+            if( wkbHasZ(poGeometry->getGeometryType()) )
                 json_object_array_add(
                     poObjBBOX,
                     json_object_new_coord(sEnvelope.MaxZ, oOptions));
@@ -869,11 +869,11 @@ json_object* OGRGeoJSONWriteGeometry( OGRGeometry* poGeometry,
         return NULL;
     }
 
-    OGRwkbGeometryType eType = poGeometry->getGeometryType();
+    OGRwkbGeometryType eFType = wkbFlatten(poGeometry->getGeometryType());
     // For point empty, return a null geometry. For other empty geometry types,
     // we will generate an empty coordinate array, which is propably also
     // borderline.
-    if( (wkbPoint == eType || wkbPoint25D == eType) && poGeometry->IsEmpty() )
+    if( eFType == wkbPoint && poGeometry->IsEmpty() )
     {
         return NULL;
     }
@@ -894,7 +894,7 @@ json_object* OGRGeoJSONWriteGeometry( OGRGeometry* poGeometry,
 /* -------------------------------------------------------------------- */
     json_object* poObjGeom = NULL;
 
-    if( wkbGeometryCollection == eType || wkbGeometryCollection25D == eType )
+    if( eFType == wkbGeometryCollection  )
     {
         poObjGeom =
             OGRGeoJSONWriteGeometryCollection(
@@ -903,27 +903,27 @@ json_object* OGRGeoJSONWriteGeometry( OGRGeometry* poGeometry,
     }
     else
     {
-        if( wkbPoint == eType || wkbPoint25D == eType )
+        if( wkbPoint == eFType )
             poObjGeom =
                 OGRGeoJSONWritePoint( static_cast<OGRPoint*>(poGeometry),
                                       oOptions );
-        else if( wkbLineString == eType || wkbLineString25D == eType )
+        else if( wkbLineString == eFType )
             poObjGeom =
                 OGRGeoJSONWriteLineString(
                     static_cast<OGRLineString*>(poGeometry), oOptions );
-        else if( wkbPolygon == eType || wkbPolygon25D == eType )
+        else if( wkbPolygon == eFType )
             poObjGeom =
                 OGRGeoJSONWritePolygon( static_cast<OGRPolygon*>(poGeometry),
                                         oOptions );
-        else if( wkbMultiPoint == eType || wkbMultiPoint25D == eType )
+        else if( wkbMultiPoint == eFType )
             poObjGeom =
                 OGRGeoJSONWriteMultiPoint(
                     static_cast<OGRMultiPoint*>(poGeometry), oOptions );
-        else if( wkbMultiLineString == eType || wkbMultiLineString25D == eType )
+        else if( wkbMultiLineString == eFType )
             poObjGeom =
                 OGRGeoJSONWriteMultiLineString(
                     static_cast<OGRMultiLineString*>(poGeometry), oOptions );
-        else if( wkbMultiPolygon == eType || wkbMultiPolygon25D == eType )
+        else if( wkbMultiPolygon == eFType )
             poObjGeom =
                 OGRGeoJSONWriteMultiPolygon(
                     static_cast<OGRMultiPolygon*>(poGeometry), oOptions );
@@ -960,14 +960,14 @@ json_object* OGRGeoJSONWritePoint( OGRPoint* poPoint,
     json_object* poObj = NULL;
 
     // Generate "coordinates" object for 2D or 3D dimension.
-    if( 3 == poPoint->getCoordinateDimension() )
+    if( wkbHasZ(poPoint->getGeometryType()) )
     {
         poObj = OGRGeoJSONWriteCoords( poPoint->getX(),
                                        poPoint->getY(),
                                        poPoint->getZ(),
                                        oOptions );
     }
-    else if( 2 == poPoint->getCoordinateDimension() )
+    else if( !poPoint->IsEmpty() )
     {
         poObj = OGRGeoJSONWriteCoords( poPoint->getX(),
                                        poPoint->getY(),
@@ -1226,9 +1226,10 @@ json_object* OGRGeoJSONWriteLineCoords( OGRLineString* poLine,
     json_object* poObjCoords = json_object_new_array();
 
     const int nCount = poLine->getNumPoints();
+    const bool bHasZ = wkbHasZ(poLine->getGeometryType());
     for( int i = 0; i < nCount; ++i )
     {
-        if( poLine->getCoordinateDimension() == 2 )
+        if( !bHasZ )
             poObjPoint =
                 OGRGeoJSONWriteCoords( poLine->getX(i), poLine->getY(i),
                                        oOptions );
@@ -1264,10 +1265,11 @@ json_object* OGRGeoJSONWriteRingCoords( OGRLinearRing* poLine,
                          (!bIsExteriorRing && !poLine->isClockwise()));
 
     const int nCount = poLine->getNumPoints();
+    const bool bHasZ = wkbHasZ(poLine->getGeometryType());
     for( int i = 0; i < nCount; ++i )
     {
         const int nIdx = (bInvertOrder) ? nCount - 1 - i: i;
-        if( poLine->getCoordinateDimension() == 2 )
+        if( !bHasZ )
             poObjPoint =
                 OGRGeoJSONWriteCoords( poLine->getX(nIdx), poLine->getY(nIdx),
                                        oOptions );
diff --git a/ogr/ogrsf_frmts/georss/ogrgeorsslayer.cpp b/ogr/ogrsf_frmts/georss/ogrgeorsslayer.cpp
index ae4bd70..c485790 100644
--- a/ogr/ogrsf_frmts/georss/ogrgeorsslayer.cpp
+++ b/ogr/ogrsf_frmts/georss/ogrgeorsslayer.cpp
@@ -32,7 +32,7 @@
 #include "ogr_georss.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrgeorsslayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
+CPL_CVSID("$Id: ogrgeorsslayer.cpp 38386 2017-05-15 11:55:09Z rouault $");
 
 static const char* const apszAllowedATOMFieldNamesWithSubElements[] =
     { "author", "contributor", NULL };
@@ -605,9 +605,7 @@ void OGRGeoRSSLayer::endElementCbk(const char *pszName)
     if( pszColon )
         pszNoNSName = pszColon + 1;
 
-    if ((eFormat == GEORSS_ATOM && currentDepth == 1 && strcmp(pszNoNSName, "entry") == 0) ||
-        ((eFormat == GEORSS_RSS || eFormat == GEORSS_RSS_RDF) &&
-         (currentDepth == 1 || currentDepth == 2) && strcmp(pszNoNSName, "item") == 0))
+    if( bInFeature && currentDepth == featureDepth )
     {
         bInFeature = false;
         bInTagWithSubTag = false;
diff --git a/ogr/ogrsf_frmts/gml/gmlreader.cpp b/ogr/ogrsf_frmts/gml/gmlreader.cpp
index 0181067..acacdb6 100644
--- a/ogr/ogrsf_frmts/gml/gmlreader.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlreader.cpp
@@ -44,7 +44,7 @@
 #include "gmlutils.h"
 #include "ogr_geometry.h"
 
-CPL_CVSID("$Id: gmlreader.cpp 37914 2017-04-06 17:38:46Z rouault $");
+CPL_CVSID("$Id: gmlreader.cpp 38566 2017-05-21 16:59:47Z rouault $");
 
 /************************************************************************/
 /*                            ~IGMLReader()                             */
@@ -899,6 +899,11 @@ void GMLReader::PopState()
             m_poCompleteFeature = m_poState->m_poFeature;
             m_poState->m_poFeature = NULL;
         }
+        else if( !bUseExpatReader && m_poState->m_poFeature != NULL )
+        {
+            delete m_poState->m_poFeature;
+            m_poState->m_poFeature = NULL;
+        }
 #endif
 
 #ifdef HAVE_EXPAT
diff --git a/ogr/ogrsf_frmts/gml/gmlreader.h b/ogr/ogrsf_frmts/gml/gmlreader.h
index 168a9ed..a16f507 100644
--- a/ogr/ogrsf_frmts/gml/gmlreader.h
+++ b/ogr/ogrsf_frmts/gml/gmlreader.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gmlreader.h 37371 2017-02-13 11:41:59Z rouault $
+ * $Id: gmlreader.h 38566 2017-05-21 16:59:47Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Public Declarations for OGR free GML Reader code.
@@ -256,7 +256,7 @@ public:
 
     void            SetPropertyDirectly( int i, char *pszValue );
 
-    const GMLProperty*GetProperty( int i ) const { return (i < m_nPropertyCount) ? &m_pasProperties[i] : NULL; }
+    const GMLProperty*GetProperty( int i ) const { return (i >= 0 && i < m_nPropertyCount) ? &m_pasProperties[i] : NULL; }
 
     const char      *GetFID() const { return m_pszFID; }
     void             SetFID( const char *pszFID );
diff --git a/ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp b/ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp
index cdcd389..35bc12b 100644
--- a/ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp
+++ b/ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp
@@ -38,7 +38,7 @@
 
 #include <algorithm>
 
-CPL_CVSID("$Id: ogrgeopackagedatasource.cpp 37995 2017-04-14 09:50:49Z rouault $");
+CPL_CVSID("$Id: ogrgeopackagedatasource.cpp 39212 2017-06-20 19:00:17Z rouault $");
 
 /************************************************************************/
 /*                             Tiling schemes                           */
@@ -767,7 +767,7 @@ int GDALGeoPackageDataset::Open( GDALOpenInfo* poOpenInfo )
                     "AND name NOT LIKE 'rtree_%' AND name NOT LIKE 'sqlite_%' "
                     // Avoid reading those views from simple_sewer_features.gpkg
                     "AND name NOT IN ('st_spatial_ref_sys', 'spatial_ref_sys', 'st_geometry_columns') "
-                    "AND name NOT IN (SELECT table_name FROM gpkg_contents)";
+                    "AND lower(name) NOT IN (SELECT lower(table_name) FROM gpkg_contents)";
         }
         const int nTableLimit =
                     atoi(CPLGetConfigOption("OGR_TABLE_LIMIT", "10000"));
@@ -1335,9 +1335,9 @@ bool GDALGeoPackageDataset::OpenRaster( const char* pszTableName,
             // overflows, but that's already a insane value.
             "AND zoom_level >= 0 AND zoom_level <= 65536 "
             "AND pixel_x_size > 0 AND pixel_y_size > 0 "
-            "AND tile_width > 0 AND tile_width <= 65536 "
-            "AND tile_height > 0 AND tile_height <= 65536 "
-            "AND matrix_width > 0 AND matrix_height > 0",
+            "AND tile_width >= 1 AND tile_width <= 65536 "
+            "AND tile_height >= 1 AND tile_height <= 65536 "
+            "AND matrix_width >= 1 AND matrix_height >= 1",
             osQuotedTableName.c_str());
     CPLString osSQL(pszSQL);
     const char* pszZoomLevel =  CSLFetchNameValue(papszOpenOptionsIn, "ZOOM_LEVEL");
@@ -1517,10 +1517,14 @@ bool GDALGeoPackageDataset::OpenRaster( const char* pszTableName,
     for( int i = 1; i < oResult.nRowCount; i++ )
     {
         GDALGeoPackageDataset* poOvrDS = new GDALGeoPackageDataset();
-        poOvrDS->InitRaster(
+        if( !poOvrDS->InitRaster(
             this, pszTableName, dfMinX, dfMinY, dfMaxX, dfMaxY,
             pszContentsMinX, pszContentsMinY, pszContentsMaxX, pszContentsMaxY,
-            papszOpenOptionsIn, oResult, i);
+            papszOpenOptionsIn, oResult, i) )
+        {
+            delete poOvrDS;
+            break;
+        }
 
         m_papoOverviewDS = (GDALGeoPackageDataset**) CPLRealloc(m_papoOverviewDS,
                         sizeof(GDALGeoPackageDataset*) * (m_nOverviewCount+1));
@@ -1528,7 +1532,8 @@ bool GDALGeoPackageDataset::OpenRaster( const char* pszTableName,
 
         int nTileWidth, nTileHeight;
         poOvrDS->GetRasterBand(1)->GetBlockSize(&nTileWidth, &nTileHeight);
-        if( poOvrDS->GetRasterXSize() < nTileWidth &&
+        if( eAccess == GA_ReadOnly &&
+            poOvrDS->GetRasterXSize() < nTileWidth &&
             poOvrDS->GetRasterYSize() < nTileHeight )
         {
             break;
@@ -1604,14 +1609,14 @@ CPLErr GDALGeoPackageDataset::SetProjection( const char* pszProjection )
 
     if( m_bRecordInsertedInGPKGContent )
     {
-        char* pszSQL = sqlite3_mprintf("UPDATE gpkg_contents SET srs_id = %d WHERE table_name = '%q'",
+        char* pszSQL = sqlite3_mprintf("UPDATE gpkg_contents SET srs_id = %d WHERE lower(table_name) = lower('%q')",
                                         m_nSRID, m_osRasterTable.c_str());
         OGRErr eErr = SQLCommand(hDB, pszSQL);
         sqlite3_free(pszSQL);
         if ( eErr != OGRERR_NONE )
             return CE_Failure;
 
-        pszSQL = sqlite3_mprintf("UPDATE gpkg_tile_matrix_set SET srs_id = %d WHERE table_name = '%q'",
+        pszSQL = sqlite3_mprintf("UPDATE gpkg_tile_matrix_set SET srs_id = %d WHERE lower(table_name) = lower('%q')",
                                  m_nSRID, m_osRasterTable.c_str());
         eErr = SQLCommand(hDB, pszSQL);
         sqlite3_free(pszSQL);
@@ -1907,7 +1912,7 @@ OGRErr GDALGeoPackageDataset::UpdateGpkgContentsLastChange(
         pszSQL = sqlite3_mprintf(
                     "UPDATE gpkg_contents SET "
                     "last_change = '%q'"
-                    "WHERE table_name = '%q'",
+                    "WHERE lower(table_name) = lower('%q')",
                     pszCurrentDate,
                     pszTableName);
     }
@@ -1916,7 +1921,7 @@ OGRErr GDALGeoPackageDataset::UpdateGpkgContentsLastChange(
         pszSQL = sqlite3_mprintf(
                     "UPDATE gpkg_contents SET "
                     "last_change = strftime('%%Y-%%m-%%dT%%H:%%M:%%fZ','now')"
-                    "WHERE table_name = '%q'",
+                    "WHERE lower(table_name) = lower('%q')",
                     pszTableName);
     }
 
@@ -2125,7 +2130,7 @@ CPLErr GDALGeoPackageDataset::IBuildOverviews(
                 for(int k=0;k<=jCandidate;k++)
                 {
                     pszSQL = sqlite3_mprintf("UPDATE gpkg_tile_matrix SET zoom_level = %d "
-                        "WHERE table_name = '%q' AND zoom_level = %d",
+                        "WHERE lower(table_name) = lower('%q') AND zoom_level = %d",
                         m_nZoomLevel - k + 1,
                         m_osRasterTable.c_str(),
                         m_nZoomLevel - k);
@@ -2341,7 +2346,7 @@ char **GDALGeoPackageDataset::GetMetadata( const char *pszDomain )
             "md.md_standard_uri IS NOT NULL AND "
             "md.mime_type IS NOT NULL AND "
             "(mdr.reference_scope = 'geopackage' OR "
-            "(mdr.reference_scope = 'table' AND mdr.table_name = '%q')) ORDER BY md.id "
+            "(mdr.reference_scope = 'table' AND lower(mdr.table_name) = lower('%q'))) ORDER BY md.id "
             "LIMIT 1000", // to avoid denial of service
             m_osRasterTable.c_str());
     }
@@ -2480,7 +2485,7 @@ void GDALGeoPackageDataset::WriteMetadata(CPLXMLNode* psXMLNode, /* will be dest
             "SELECT md.id FROM gpkg_metadata md "
             "JOIN gpkg_metadata_reference mdr ON (md.id = mdr.md_file_id ) "
             "WHERE md.md_scope = 'dataset' AND md.md_standard_uri='http://gdal.org' "
-            "AND md.mime_type='text/xml' AND mdr.reference_scope = 'table' AND mdr.table_name = '%q'",
+            "AND md.mime_type='text/xml' AND mdr.reference_scope = 'table' AND lower(mdr.table_name) = lower('%q')",
             pszTableName);
     }
     else
@@ -2750,7 +2755,7 @@ CPLErr GDALGeoPackageDataset::FlushMetadata()
         {
             m_osIdentifier = pszIdentifier;
             char* pszSQL = sqlite3_mprintf(
-                "UPDATE gpkg_contents SET identifier = '%q' WHERE table_name = '%q'",
+                "UPDATE gpkg_contents SET identifier = '%q' WHERE lower(table_name) = lower('%q')",
                 pszIdentifier, m_osRasterTable.c_str());
             SQLCommand(hDB, pszSQL);
             sqlite3_free(pszSQL);
@@ -2760,7 +2765,7 @@ CPLErr GDALGeoPackageDataset::FlushMetadata()
         {
             m_osDescription = pszDescription;
             char* pszSQL = sqlite3_mprintf(
-                "UPDATE gpkg_contents SET description = '%q' WHERE table_name = '%q'",
+                "UPDATE gpkg_contents SET description = '%q' WHERE lower(table_name) = lower('%q')",
                 pszDescription, m_osRasterTable.c_str());
             SQLCommand(hDB, pszSQL);
             sqlite3_free(pszSQL);
@@ -2829,7 +2834,7 @@ CPLErr GDALGeoPackageDataset::FlushMetadata()
         if( pszIdentifier != NULL )
         {
             char* pszSQL = sqlite3_mprintf(
-                "UPDATE gpkg_contents SET identifier = '%q' WHERE table_name = '%q'",
+                "UPDATE gpkg_contents SET identifier = '%q' WHERE lower(table_name) = lower('%q')",
                 pszIdentifier, m_papoLayers[i]->GetName());
             SQLCommand(hDB, pszSQL);
             sqlite3_free(pszSQL);
@@ -2837,7 +2842,7 @@ CPLErr GDALGeoPackageDataset::FlushMetadata()
         if( pszDescription != NULL )
         {
             char* pszSQL = sqlite3_mprintf(
-                "UPDATE gpkg_contents SET description = '%q' WHERE table_name = '%q'",
+                "UPDATE gpkg_contents SET description = '%q' WHERE lower(table_name) = lower('%q')",
                 pszDescription, m_papoLayers[i]->GetName());
             SQLCommand(hDB, pszSQL);
             sqlite3_free(pszSQL);
@@ -3333,13 +3338,13 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
         "BEFORE INSERT ON \"%w\" "
         "FOR EACH ROW BEGIN "
         "SELECT RAISE(ABORT, 'insert on table ''%q'' violates constraint: zoom_level not specified for table in gpkg_tile_matrix') "
-        "WHERE NOT (NEW.zoom_level IN (SELECT zoom_level FROM gpkg_tile_matrix WHERE table_name = '%q')) ; "
+        "WHERE NOT (NEW.zoom_level IN (SELECT zoom_level FROM gpkg_tile_matrix WHERE lower(table_name) = lower('%q'))) ; "
         "END; "
         "CREATE TRIGGER \"%w_zoom_update\" "
         "BEFORE UPDATE OF zoom_level ON \"%w\" "
         "FOR EACH ROW BEGIN "
         "SELECT RAISE(ABORT, 'update on table ''%q'' violates constraint: zoom_level not specified for table in gpkg_tile_matrix') "
-        "WHERE NOT (NEW.zoom_level IN (SELECT zoom_level FROM gpkg_tile_matrix WHERE table_name = '%q')) ; "
+        "WHERE NOT (NEW.zoom_level IN (SELECT zoom_level FROM gpkg_tile_matrix WHERE lower(table_name) = lower('%q'))) ; "
         "END; "
         "CREATE TRIGGER \"%w_tile_column_insert\" "
         "BEFORE INSERT ON \"%w\" "
@@ -3347,7 +3352,7 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
         "SELECT RAISE(ABORT, 'insert on table ''%q'' violates constraint: tile_column cannot be < 0') "
         "WHERE (NEW.tile_column < 0) ; "
         "SELECT RAISE(ABORT, 'insert on table ''%q'' violates constraint: tile_column must by < matrix_width specified for table and zoom level in gpkg_tile_matrix') "
-        "WHERE NOT (NEW.tile_column < (SELECT matrix_width FROM gpkg_tile_matrix WHERE table_name = '%q' AND zoom_level = NEW.zoom_level)); "
+        "WHERE NOT (NEW.tile_column < (SELECT matrix_width FROM gpkg_tile_matrix WHERE lower(table_name) = lower('%q') AND zoom_level = NEW.zoom_level)); "
         "END; "
         "CREATE TRIGGER \"%w_tile_column_update\" "
         "BEFORE UPDATE OF tile_column ON \"%w\" "
@@ -3355,7 +3360,7 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
         "SELECT RAISE(ABORT, 'update on table ''%q'' violates constraint: tile_column cannot be < 0') "
         "WHERE (NEW.tile_column < 0) ; "
         "SELECT RAISE(ABORT, 'update on table ''%q'' violates constraint: tile_column must by < matrix_width specified for table and zoom level in gpkg_tile_matrix') "
-        "WHERE NOT (NEW.tile_column < (SELECT matrix_width FROM gpkg_tile_matrix WHERE table_name = '%q' AND zoom_level = NEW.zoom_level)); "
+        "WHERE NOT (NEW.tile_column < (SELECT matrix_width FROM gpkg_tile_matrix WHERE lower(table_name) = lower('%q') AND zoom_level = NEW.zoom_level)); "
         "END; "
         "CREATE TRIGGER \"%w_tile_row_insert\" "
         "BEFORE INSERT ON \"%w\" "
@@ -3363,7 +3368,7 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
         "SELECT RAISE(ABORT, 'insert on table ''%q'' violates constraint: tile_row cannot be < 0') "
         "WHERE (NEW.tile_row < 0) ; "
         "SELECT RAISE(ABORT, 'insert on table ''%q'' violates constraint: tile_row must by < matrix_height specified for table and zoom level in gpkg_tile_matrix') "
-        "WHERE NOT (NEW.tile_row < (SELECT matrix_height FROM gpkg_tile_matrix WHERE table_name = '%q' AND zoom_level = NEW.zoom_level)); "
+        "WHERE NOT (NEW.tile_row < (SELECT matrix_height FROM gpkg_tile_matrix WHERE lower(table_name) = lower('%q') AND zoom_level = NEW.zoom_level)); "
         "END; "
         "CREATE TRIGGER \"%w_tile_row_update\" "
         "BEFORE UPDATE OF tile_row ON \"%w\" "
@@ -3371,7 +3376,7 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
         "SELECT RAISE(ABORT, 'update on table ''%q'' violates constraint: tile_row cannot be < 0') "
         "WHERE (NEW.tile_row < 0) ; "
         "SELECT RAISE(ABORT, 'update on table ''%q'' violates constraint: tile_row must by < matrix_height specified for table and zoom level in gpkg_tile_matrix') "
-        "WHERE NOT (NEW.tile_row < (SELECT matrix_height FROM gpkg_tile_matrix WHERE table_name = '%q' AND zoom_level = NEW.zoom_level)); "
+        "WHERE NOT (NEW.tile_row < (SELECT matrix_height FROM gpkg_tile_matrix WHERE lower(table_name) = lower('%q') AND zoom_level = NEW.zoom_level)); "
         "END; ",
         m_osRasterTable.c_str(),
         m_osRasterTable.c_str(),
@@ -4463,7 +4468,7 @@ OGRErr GDALGeoPackageDataset::DeleteLayer( int iLayer )
         m_papoLayers[iLayer]->DropSpatialIndex();
 
     char* pszSQL = sqlite3_mprintf(
-            "DELETE FROM gpkg_geometry_columns WHERE table_name = '%q'",
+            "DELETE FROM gpkg_geometry_columns WHERE lower(table_name) = lower('%q')",
              osLayerName.c_str());
     OGRErr eErr = SQLCommand(hDB, pszSQL);
     sqlite3_free(pszSQL);
@@ -4471,7 +4476,7 @@ OGRErr GDALGeoPackageDataset::DeleteLayer( int iLayer )
     if( eErr == OGRERR_NONE )
     {
         pszSQL = sqlite3_mprintf(
-                "DELETE FROM gpkg_contents WHERE table_name = '%q'",
+                "DELETE FROM gpkg_contents WHERE lower(table_name) = lower('%q')",
                 osLayerName.c_str());
         eErr = SQLCommand(hDB, pszSQL);
         sqlite3_free(pszSQL);
@@ -4480,7 +4485,7 @@ OGRErr GDALGeoPackageDataset::DeleteLayer( int iLayer )
     if( eErr == OGRERR_NONE && HasExtensionsTable() )
     {
         pszSQL = sqlite3_mprintf(
-                "DELETE FROM gpkg_extensions WHERE table_name = '%q'",
+                "DELETE FROM gpkg_extensions WHERE lower(table_name) = lower('%q')",
                 osLayerName.c_str());
         eErr = SQLCommand(hDB, pszSQL);
         sqlite3_free(pszSQL);
@@ -4489,7 +4494,7 @@ OGRErr GDALGeoPackageDataset::DeleteLayer( int iLayer )
     if( eErr == OGRERR_NONE && HasMetadataTables() )
     {
         pszSQL = sqlite3_mprintf(
-                "DELETE FROM gpkg_metadata_reference WHERE table_name = '%q'",
+                "DELETE FROM gpkg_metadata_reference WHERE lower(table_name) = lower('%q')",
                 osLayerName.c_str());
         eErr = SQLCommand(hDB, pszSQL);
         sqlite3_free(pszSQL);
@@ -4498,7 +4503,7 @@ OGRErr GDALGeoPackageDataset::DeleteLayer( int iLayer )
     if( eErr == OGRERR_NONE && HasDataColumnsTable() )
     {
         pszSQL = sqlite3_mprintf(
-                "DELETE FROM gpkg_data_columns WHERE table_name = '%q'",
+                "DELETE FROM gpkg_data_columns WHERE lower(table_name) = lower('%q')",
                 osLayerName.c_str());
         eErr = SQLCommand(hDB, pszSQL);
         sqlite3_free(pszSQL);
@@ -4508,7 +4513,7 @@ OGRErr GDALGeoPackageDataset::DeleteLayer( int iLayer )
     if( eErr == OGRERR_NONE && m_bHasGPKGOGRContents )
     {
         pszSQL = sqlite3_mprintf(
-                "DELETE FROM gpkg_ogr_contents WHERE table_name = '%q'",
+                "DELETE FROM gpkg_ogr_contents WHERE lower(table_name) = lower('%q')",
                 osLayerName.c_str());
         eErr = SQLCommand(hDB, pszSQL);
         sqlite3_free(pszSQL);
@@ -4941,7 +4946,7 @@ void GDALGeoPackageDataset::CheckUnknownExtensions(bool bCheckRasterTable)
     else
         pszSQL = sqlite3_mprintf(
             "SELECT extension_name, definition, scope FROM gpkg_extensions "
-            "WHERE (table_name = '%q' "
+            "WHERE (lower(table_name) = lower('%q') "
             "AND extension_name IS NOT NULL "
             "AND definition IS NOT NULL "
             "AND scope IS NOT NULL "
diff --git a/ogr/ogrsf_frmts/gpkg/ogrgeopackagetablelayer.cpp b/ogr/ogrsf_frmts/gpkg/ogrgeopackagetablelayer.cpp
index 054efe2..ba3677a 100644
--- a/ogr/ogrsf_frmts/gpkg/ogrgeopackagetablelayer.cpp
+++ b/ogr/ogrsf_frmts/gpkg/ogrgeopackagetablelayer.cpp
@@ -33,7 +33,7 @@
 #include "cpl_time.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrgeopackagetablelayer.cpp 38036 2017-04-16 12:35:59Z rouault $");
+CPL_CVSID("$Id: ogrgeopackagetablelayer.cpp 38922 2017-06-06 20:38:20Z rouault $");
 
 static const char UNSUPPORTED_OP_READ_ONLY[] =
   "%s : unsupported operation on a read-only datasource.";
@@ -57,7 +57,7 @@ OGRErr OGRGeoPackageTableLayer::SaveExtent()
                 "UPDATE gpkg_contents SET "
                 "min_x = %g, min_y = %g, "
                 "max_x = %g, max_y = %g "
-                "WHERE table_name = '%q' AND "
+                "WHERE lower(table_name) = lower('%q') AND "
                 "Lower(data_type) = 'features'",
                 m_poExtent->MinX, m_poExtent->MinY,
                 m_poExtent->MaxX, m_poExtent->MaxY,
@@ -99,7 +99,7 @@ OGRErr OGRGeoPackageTableLayer::SaveTimestamp()
         char* pszSQL = sqlite3_mprintf(
                     "UPDATE gpkg_ogr_contents SET "
                     "feature_count = %s "
-                    "WHERE table_name = '%q'",
+                    "WHERE lower(table_name) = lower('%q')",
                     osFeatureCount.c_str(),
                     m_pszTableName);
         err = SQLCommand(m_poDS->GetDB(), pszSQL);
@@ -576,7 +576,7 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(bool bIsSpatial, bool bIsGpk
     {
         SQLResult oResult;
         char* pszSQL = sqlite3_mprintf(
-            "SELECT type FROM sqlite_master WHERE name = '%q' AND type "
+            "SELECT type FROM sqlite_master WHERE lower(name) = lower('%q') AND type "
             "IN ('view', 'table')",
             m_pszTableName);
         err = SQLQuery(poDb, pszSQL, &oResult);
@@ -604,7 +604,7 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(bool bIsSpatial, bool bIsGpk
             "SELECT table_name, data_type, identifier, "
             "description, min_x, min_y, max_x, max_y "
             "FROM gpkg_contents "
-            "WHERE (table_name = '%q')"
+            "WHERE (lower(table_name) = lower('%q'))"
 #ifdef WORKAROUND_SQLITE3_BUGS
             " OR 0"
 #endif
@@ -643,7 +643,7 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(bool bIsSpatial, bool bIsGpk
             pszSQL = sqlite3_mprintf(
                 "SELECT feature_count "
                 "FROM gpkg_ogr_contents "
-                "WHERE table_name = '%q'"
+                "WHERE lower(table_name) = lower('%q')"
 #ifdef WORKAROUND_SQLITE3_BUGS
                 " OR 0"
 #endif
@@ -707,7 +707,7 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(bool bIsSpatial, bool bIsGpk
                         "SELECT table_name, column_name, "
                         "geometry_type_name, srs_id, z, m "
                         "FROM gpkg_geometry_columns "
-                        "WHERE table_name = '%q'"
+                        "WHERE lower(table_name) = lower('%q')"
 #ifdef WORKAROUND_SQLITE3_BUGS
                         " OR 0"
 #endif
@@ -1297,7 +1297,7 @@ OGRErr OGRGeoPackageTableLayer::CreateGeomField( OGRGeomFieldDefn *poGeomFieldIn
             "ALTER TABLE \"%w\" ADD COLUMN \"%w\" %s%s"
             ";"
             "UPDATE gpkg_contents SET data_type = 'features' "
-            "WHERE table_name = '%q'",
+            "WHERE lower(table_name) = lower('%q')",
             m_pszTableName, oGeomField.GetNameRef(),
             m_poDS->GetGeometryTypeString(oGeomField.GetType()),
             !oGeomField.IsNullable() ? " NOT NULL DEFAULT ''" : "",
@@ -1358,7 +1358,7 @@ void OGRGeoPackageTableLayer::DisableFeatureCount(bool bInMemoryOnly)
     {
         char* pszSQL = sqlite3_mprintf(
             "UPDATE gpkg_ogr_contents SET feature_count = NULL WHERE "
-            "table_name = '%q'",
+            "lower(table_name )= lower('%q')",
             m_pszTableName);
         SQLCommand(m_poDS->GetDB(), pszSQL);
         sqlite3_free(pszSQL);
@@ -1385,7 +1385,7 @@ void OGRGeoPackageTableLayer::CreateTriggers(const char* pszTableName)
             "CREATE TRIGGER \"trigger_insert_feature_count_%w\" "
             "AFTER INSERT ON \"%w\" "
             "BEGIN UPDATE gpkg_ogr_contents SET feature_count = "
-            "feature_count + 1 WHERE table_name = '%q'; END;",
+            "feature_count + 1 WHERE lower(table_name) = lower('%q'); END;",
             pszTableName, pszTableName, pszTableName);
         SQLCommand(m_poDS->GetDB(), pszSQL);
         sqlite3_free(pszSQL);
@@ -1394,7 +1394,7 @@ void OGRGeoPackageTableLayer::CreateTriggers(const char* pszTableName)
             "CREATE TRIGGER \"trigger_delete_feature_count_%w\" "
             "AFTER DELETE ON \"%w\" "
             "BEGIN UPDATE gpkg_ogr_contents SET feature_count = "
-            "feature_count - 1 WHERE table_name = '%q'; END;",
+            "feature_count - 1 WHERE lower(table_name) = lower('%q'); END;",
             pszTableName, pszTableName, pszTableName);
         SQLCommand(m_poDS->GetDB(), pszSQL);
         sqlite3_free(pszSQL);
@@ -1432,7 +1432,7 @@ void OGRGeoPackageTableLayer::DisableTriggers(bool bNullifyFeatureCount)
         {
             pszSQL = sqlite3_mprintf(
                 "UPDATE gpkg_ogr_contents SET feature_count = NULL WHERE "
-                "table_name = '%q'",
+                "lower(table_name )= lower('%q')",
                 m_pszTableName);
             SQLCommand(m_poDS->GetDB(), pszSQL);
             sqlite3_free(pszSQL);
@@ -2065,7 +2065,7 @@ GIntBig OGRGeoPackageTableLayer::GetFeatureCount( int /*bForce*/ )
         {
             char* pszSQL = sqlite3_mprintf(
                 "SELECT feature_count FROM gpkg_ogr_contents WHERE "
-                "table_name = '%q' LIMIT 2",
+                "lower(table_name) = lower('%q') LIMIT 2",
                 m_pszTableName);
             SQLResult oResult;
             OGRErr err = SQLQuery( m_poDS->GetDB(), pszSQL, &oResult);
@@ -2144,7 +2144,7 @@ GIntBig OGRGeoPackageTableLayer::GetFeatureCount( int /*bForce*/ )
                                                   m_nTotalFeatureCount);
                 char* pszSQL = sqlite3_mprintf(
                     "UPDATE gpkg_ogr_contents SET feature_count = %s WHERE "
-                    "table_name = '%q'", pszCount, m_pszTableName);
+                    "lower(table_name )= lower('%q')", pszCount, m_pszTableName);
                 SQLCommand(m_poDS->GetDB(), pszSQL);
                 sqlite3_free(pszSQL);
             }
@@ -2208,7 +2208,7 @@ OGRErr OGRGeoPackageTableLayer::GetExtent(OGREnvelope *psExtent, int bForce)
                 "UPDATE gpkg_contents SET "
                 "min_x = NULL, min_y = NULL, "
                 "max_x = NULL, max_y = NULL "
-                "WHERE table_name = '%q' AND "
+                "WHERE lower(table_name) = lower('%q') AND "
                 "Lower(data_type) = 'features'",
                 m_pszTableName);
             SQLCommand( m_poDS->GetDB(), pszSQL);
@@ -2670,7 +2670,7 @@ void OGRGeoPackageTableLayer::CheckUnknownExtensions()
     {
         pszSQL = sqlite3_mprintf(
                     "SELECT extension_name, definition, scope "
-                    "FROM gpkg_extensions WHERE (table_name='%q' "
+                    "FROM gpkg_extensions WHERE (lower(table_name)=lower('%q') "
                     "AND extension_name IS NOT NULL "
                     "AND definition IS NOT NULL "
                     "AND scope IS NOT NULL) "
@@ -2684,11 +2684,11 @@ void OGRGeoPackageTableLayer::CheckUnknownExtensions()
     {
         pszSQL = sqlite3_mprintf(
                     "SELECT extension_name, definition, scope "
-                    "FROM gpkg_extensions WHERE (table_name='%q' "
+                    "FROM gpkg_extensions WHERE (lower(table_name)=lower('%q') "
                     "AND extension_name IS NOT NULL "
                     "AND definition IS NOT NULL "
                     "AND scope IS NOT NULL "
-                    "AND column_name='%q' AND extension_name NOT IN ('gpkg_geom_CIRCULARSTRING', "
+                    "AND lower(column_name)=lower('%q') AND extension_name NOT IN ('gpkg_geom_CIRCULARSTRING', "
                     "'gpkg_geom_COMPOUNDCURVE', 'gpkg_geom_CURVEPOLYGON', 'gpkg_geom_MULTICURVE', "
                     "'gpkg_geom_MULTISURFACE', 'gpkg_geom_CURVE', 'gpkg_geom_SURFACE', "
                     "'gpkg_geom_POLYHEDRALSURFACE', 'gpkg_geom_TIN', 'gpkg_geom_TRIANGLE', "
@@ -2790,8 +2790,8 @@ bool OGRGeoPackageTableLayer::CreateGeometryExtensionIfNecessary(OGRwkbGeometryT
 
     // Check first if the extension isn't registered
     char* pszSQL = sqlite3_mprintf(
-        "SELECT 1 FROM gpkg_extensions WHERE table_name = '%q' AND "
-        "column_name = '%q' AND extension_name = 'gpkg_geom_%s'",
+        "SELECT 1 FROM gpkg_extensions WHERE lower(table_name) = lower('%q') AND "
+        "lower(column_name) = lower('%q') AND extension_name = 'gpkg_geom_%s'",
          pszT, pszC, pszGeometryType);
     const bool bExists = SQLGetInteger(m_poDS->GetDB(), pszSQL, NULL) == 1;
     sqlite3_free(pszSQL);
@@ -2842,8 +2842,8 @@ bool OGRGeoPackageTableLayer::HasSpatialIndex()
 
     /* Check into gpkg_extensions */
     char* pszSQL = sqlite3_mprintf(
-                 "SELECT * FROM gpkg_extensions WHERE (table_name='%q' "
-                 "AND column_name='%q' AND extension_name='gpkg_rtree_index')"
+                 "SELECT * FROM gpkg_extensions WHERE (lower(table_name)=lower('%q') "
+                 "AND lower(column_name)=lower('%q') AND extension_name='gpkg_rtree_index')"
 #ifdef WORKAROUND_SQLITE3_BUGS
                 " OR 0"
 #endif
@@ -2884,8 +2884,8 @@ bool OGRGeoPackageTableLayer::DropSpatialIndex(bool bCalledFromSQLFunction)
     const char* pszT = m_pszTableName;
     const char* pszC = m_poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef();
     char* pszSQL = sqlite3_mprintf(
-        "DELETE FROM gpkg_extensions WHERE table_name='%q' "
-        "AND column_name='%q' AND extension_name='gpkg_rtree_index'",
+        "DELETE FROM gpkg_extensions WHERE lower(table_name)=lower('%q') "
+        "AND lower(column_name)=lower('%q') AND extension_name='gpkg_rtree_index'",
         pszT, pszC );
     SQLCommand(m_poDS->GetDB(), pszSQL);
     sqlite3_free(pszSQL);
@@ -2949,7 +2949,7 @@ void OGRGeoPackageTableLayer::RenameTo(const char* pszDstTableName)
     SyncToDisk();
 
     char* pszSQL = sqlite3_mprintf(
-        "SELECT 1 FROM sqlite_master WHERE name = '%q' "
+        "SELECT 1 FROM sqlite_master WHERE lower(name) = lower('%q') "
         "AND type IN ('table', 'view')",
          pszDstTableName);
     const bool bAlreadyExists =
@@ -2978,7 +2978,7 @@ void OGRGeoPackageTableLayer::RenameTo(const char* pszDstTableName)
 
     pszSQL = sqlite3_mprintf(
         "UPDATE gpkg_geometry_columns SET table_name = '%q' WHERE "
-        "table_name = '%q'",
+        "lower(table_name )= lower('%q')",
         pszDstTableName, m_pszTableName);
     OGRErr eErr = SQLCommand(m_poDS->GetDB(), pszSQL);
     sqlite3_free(pszSQL);
@@ -2988,7 +2988,7 @@ void OGRGeoPackageTableLayer::RenameTo(const char* pszDstTableName)
         // Rename the identifier if it defaulted to the table name
         pszSQL = sqlite3_mprintf(
                 "UPDATE gpkg_contents SET identifier = '%q' WHERE "
-                "table_name = '%q' AND identifier = '%q'",
+                "lower(table_name) = lower('%q') AND identifier = '%q'",
                 pszDstTableName, m_pszTableName, m_pszTableName);
         eErr = SQLCommand(m_poDS->GetDB(), pszSQL);
         sqlite3_free(pszSQL);
@@ -2998,7 +2998,7 @@ void OGRGeoPackageTableLayer::RenameTo(const char* pszDstTableName)
     {
         pszSQL = sqlite3_mprintf(
                 "UPDATE gpkg_contents SET table_name = '%q' WHERE "
-                "table_name = '%q'",
+                "lower(table_name )= lower('%q')",
                 pszDstTableName, m_pszTableName);
         eErr = SQLCommand(m_poDS->GetDB(), pszSQL);
         sqlite3_free(pszSQL);
@@ -3008,7 +3008,7 @@ void OGRGeoPackageTableLayer::RenameTo(const char* pszDstTableName)
     {
         pszSQL = sqlite3_mprintf(
             "UPDATE gpkg_extensions SET table_name = '%q' WHERE "
-            "table_name = '%q'",
+            "lower(table_name )= lower('%q')",
             pszDstTableName, m_pszTableName);
         eErr = SQLCommand(m_poDS->GetDB(), pszSQL);
         sqlite3_free(pszSQL);
@@ -3018,7 +3018,7 @@ void OGRGeoPackageTableLayer::RenameTo(const char* pszDstTableName)
     {
         pszSQL = sqlite3_mprintf(
             "UPDATE gpkg_metadata_reference SET table_name = '%q' WHERE "
-            "table_name = '%q'",
+            "lower(table_name )= lower('%q')",
             pszDstTableName, m_pszTableName);
         eErr = SQLCommand(m_poDS->GetDB(), pszSQL);
         sqlite3_free(pszSQL);
@@ -3028,7 +3028,7 @@ void OGRGeoPackageTableLayer::RenameTo(const char* pszDstTableName)
     {
         pszSQL = sqlite3_mprintf(
             "UPDATE gpkg_data_columns SET table_name = '%q' WHERE "
-            "table_name = '%q'",
+            "lower(table_name )= lower('%q')",
             pszDstTableName, m_pszTableName);
         eErr = SQLCommand(m_poDS->GetDB(), pszSQL);
         sqlite3_free(pszSQL);
@@ -3039,7 +3039,7 @@ void OGRGeoPackageTableLayer::RenameTo(const char* pszDstTableName)
     {
         pszSQL = sqlite3_mprintf(
             "UPDATE gpkg_ogr_contents SET table_name = '%q' WHERE "
-            "table_name = '%q'",
+            "lower(table_name )= lower('%q')",
             pszDstTableName, m_pszTableName);
         eErr = SQLCommand(m_poDS->GetDB(), pszSQL);
         sqlite3_free(pszSQL);
@@ -3466,7 +3466,7 @@ OGRErr OGRGeoPackageTableLayer::RunDeferredCreationIfNecessary()
         if( m_poDS->m_bHasGPKGOGRContents )
         {
             pszSQL = sqlite3_mprintf(
-                "DELETE FROM gpkg_ogr_contents WHERE table_name = '%q'",
+                "DELETE FROM gpkg_ogr_contents WHERE lower(table_name) = lower('%q')",
                 pszLayerName);
             SQLCommand(m_poDS->GetDB(), pszSQL);
             sqlite3_free(pszSQL);
@@ -3546,7 +3546,7 @@ char **OGRGeoPackageTableLayer::GetMetadata( const char *pszDomain )
         "WHERE md.metadata IS NOT NULL AND "
         "md.md_standard_uri IS NOT NULL AND "
         "md.mime_type IS NOT NULL AND "
-        "mdr.table_name = '%q' ORDER BY md.id "
+        "lower(mdr.table_name) = lower('%q') ORDER BY md.id "
         "LIMIT 1000", // to avoid denial of service
         m_pszTableName);
 
@@ -3703,7 +3703,7 @@ OGRErr OGRGeoPackageTableLayer::RecreateTable(const CPLString& osColumnsForCreat
 
     char* pszSQL = sqlite3_mprintf(
         "SELECT sql FROM sqlite_master WHERE type IN ('trigger','index') "
-        "AND tbl_name='%q' LIMIT 10000",
+        "AND lower(tbl_name)=lower('%q') LIMIT 10000",
         m_pszTableName );
     SQLResult oTriggers;
     OGRErr eErr = SQLQuery(hDB, pszSQL, &oTriggers);
@@ -3873,8 +3873,8 @@ OGRErr OGRGeoPackageTableLayer::DeleteField( int iFieldToDelete )
     if( m_poDS->HasExtensionsTable() )
     {
         char* pszSQL = sqlite3_mprintf(
-            "DELETE FROM gpkg_extensions WHERE table_name = '%q' AND "
-            "column_name = '%q'",
+            "DELETE FROM gpkg_extensions WHERE lower(table_name) = lower('%q') AND "
+            "lower(column_name) = lower('%q')",
             m_pszTableName,
             m_poFeatureDefn->GetFieldDefn(iFieldToDelete)->GetNameRef() );
         eErr = SQLCommand( m_poDS->GetDB(), pszSQL );
@@ -3887,8 +3887,8 @@ OGRErr OGRGeoPackageTableLayer::DeleteField( int iFieldToDelete )
     if( m_poDS->HasDataColumnsTable() )
     {
         char* pszSQL = sqlite3_mprintf(
-            "DELETE FROM gpkg_data_columns WHERE table_name = '%q' AND "
-            "column_name = '%q'",
+            "DELETE FROM gpkg_data_columns WHERE lower(table_name) = lower('%q') AND "
+            "lower(column_name) = lower('%q')",
             m_pszTableName,
             m_poFeatureDefn->GetFieldDefn(iFieldToDelete)->GetNameRef() );
         eErr = SQLCommand( m_poDS->GetDB(), pszSQL );
@@ -4046,7 +4046,7 @@ OGRErr OGRGeoPackageTableLayer::AlterFieldDefn( int iFieldToAlter,
         char* pszSQL = sqlite3_mprintf(
             "SELECT name, type, sql FROM sqlite_master WHERE "
             "type IN ('trigger','index') "
-            "AND tbl_name='%q' AND sql LIKE '%%%q%%' LIMIT 10000",
+            "AND lower(tbl_name)=lower('%q') AND sql LIKE '%%%q%%' LIMIT 10000",
             m_pszTableName,
             SQLEscapeName(osOldColName).c_str() );
         eErr = SQLQuery(hDB, pszSQL, &oTriggers);
@@ -4141,7 +4141,7 @@ OGRErr OGRGeoPackageTableLayer::AlterFieldDefn( int iFieldToAlter,
     {
         char* pszSQL = sqlite3_mprintf(
             "UPDATE gpkg_extensions SET column_name = '%q' WHERE "
-            "table_name = '%q' AND column_name = '%q'",
+            "lower(table_name) = lower('%q') AND lower(column_name) = lower('%q')",
             poNewFieldDefn->GetNameRef(),
             m_pszTableName,
             osOldColName.c_str() );
@@ -4156,7 +4156,7 @@ OGRErr OGRGeoPackageTableLayer::AlterFieldDefn( int iFieldToAlter,
     {
         char* pszSQL = sqlite3_mprintf(
             "UPDATE gpkg_data_columns SET column_name = '%q' WHERE "
-            "table_name = '%q' AND column_name = '%q'",
+            "lower(table_name) = lower('%q') AND lower(column_name) = lower('%q')",
             poNewFieldDefn->GetNameRef(),
             m_pszTableName,
             osOldColName.c_str() );
diff --git a/ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.cpp b/ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.cpp
index 0cbc315..f59b8aa 100644
--- a/ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.cpp
+++ b/ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.cpp
@@ -29,7 +29,7 @@
 #include "ogrgeopackageutility.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrgeopackageutility.cpp 37806 2017-03-20 14:59:36Z rouault $");
+CPL_CVSID("$Id: ogrgeopackageutility.cpp 38970 2017-06-08 08:32:05Z rouault $");
 
 /* Requirement 20: A GeoPackage SHALL store feature table geometries */
 /* with the basic simple feature geometry types (Geometry, Point, */
@@ -367,6 +367,10 @@ OGRErr GPkgHeaderFromWKB(const GByte *pabyGpkg, size_t nGpkgLen, GPkgHeader *poH
 #endif
             nEnvelopeDim = 4; /* 2D+ZM envelope */
         }
+        else
+        {
+            return OGRERR_FAILURE;
+        }
     }
 
     /* SrsId */
diff --git a/ogr/ogrsf_frmts/gtm/gtm.cpp b/ogr/ogrsf_frmts/gtm/gtm.cpp
index 6594856..2bf9964 100644
--- a/ogr/ogrsf_frmts/gtm/gtm.cpp
+++ b/ogr/ogrsf_frmts/gtm/gtm.cpp
@@ -29,7 +29,7 @@
 
 #include "gtm.h"
 
-CPL_CVSID("$Id: gtm.cpp 36948 2016-12-18 13:32:14Z rouault $");
+CPL_CVSID("$Id: gtm.cpp 38444 2017-05-17 08:54:05Z rouault $");
 
 /************************************************************************/
 /*        Methods for dealing with write on files and buffers           */
@@ -339,7 +339,11 @@ bool GTM::isValid()
         {
             VSILFILE* pGTMFileOri = pGTMFile;
             pGTMFile = fp;
-            if (isValid())
+            char* pszFilenameOri = pszFilename;
+            pszFilename = pszGZIPFileName;
+            const bool bRet = isValid();
+            pszFilename = pszFilenameOri;
+            if (bRet)
             {
                 VSIFCloseL(pGTMFileOri);
                 CPLFree(pszGZIPFileName);
diff --git a/ogr/ogrsf_frmts/ili/ili1reader.cpp b/ogr/ogrsf_frmts/ili/ili1reader.cpp
index 8064213..6e8b6f6 100644
--- a/ogr/ogrsf_frmts/ili/ili1reader.cpp
+++ b/ogr/ogrsf_frmts/ili/ili1reader.cpp
@@ -48,7 +48,7 @@
 #  endif
 #endif
 
-CPL_CVSID("$Id: ili1reader.cpp 35911 2016-10-24 15:03:26Z goatbar $");
+CPL_CVSID("$Id: ili1reader.cpp 38687 2017-05-30 11:11:12Z rouault $");
 
 //
 // ILI1Reader
@@ -259,7 +259,7 @@ int ILI1Reader::ReadTable(CPL_UNUSED const char *layername) {
       const char *firsttok = CSLGetField(tokens, 0);
       if (EQUAL(firsttok, "OBJE"))
       {
-        if (featureDef->GetFieldCount() == 0)
+        if (featureDef->GetFieldCount() == 0 && curLayer->GetFeatureCount() == 0)
         {
           CPLError( CE_Warning, CPLE_AppDefined,
                     "No field definition found for table: %s",
@@ -375,7 +375,8 @@ int ILI1Reader::ReadTable(CPL_UNUSED const char *layername) {
         OGRwkbGeometryType geomType
             = (geomIdx < featureDef->GetGeomFieldCount()) ?
                featureDef->GetGeomFieldDefn(geomIdx)->GetType() : wkbNone;
-        ReadGeom(tokens, geomIdx, geomType, feature);
+        if( CSLCount(tokens) >= 3 )
+            ReadGeom(tokens, geomIdx, geomType, feature);
       }
       else if (EQUAL(firsttok, "ELIN"))
       {
@@ -390,7 +391,8 @@ int ILI1Reader::ReadTable(CPL_UNUSED const char *layername) {
             geomIdx++;
         } while (geomIdx < featureDef->GetGeomFieldCount() &&
                  featureDef->GetGeomFieldDefn(geomIdx)->GetType() == wkbPoint);
-        ReadGeom(tokens, geomIdx, wkbMultiLineString, feature);
+        if( CSLCount(tokens) >= 3 )
+            ReadGeom(tokens, geomIdx, wkbMultiLineString, feature);
       }
       else if (EQUAL(firsttok, "PERI"))
       {
@@ -462,27 +464,38 @@ void ILI1Reader::ReadGeom( char **stgeom, int geomIdx, OGRwkbGeometryType eType,
     while (!end && (tokens = ReadParseLine()) != NULL)
     {
       const char *firsttok = CSLGetField(tokens, 0);
-      if (EQUAL(firsttok, "LIPT"))
+      if( firsttok == NULL )
+      {
+          // do nothing
+      }
+      else if (EQUAL(firsttok, "LIPT") && CSLCount(tokens) >= 3)
       {
         ogrPoint.setX(CPLAtof(tokens[1])); ogrPoint.setY(CPLAtof(tokens[2]));
         if (arc) {
           arc->addPoint(&ogrPoint);
           OGRErr error =  ogrCurve->addCurveDirectly(arc);
           if (error != OGRERR_NONE) {
-            CPLError(CE_Warning, CPLE_AppDefined, "Added geometry: %s", arc->exportToJson() );
+            char* pszJSon = arc->exportToJson();
+            CPLError(CE_Warning, CPLE_AppDefined, "Could not add geometry: %s",
+                     pszJSon ? pszJSon : "(null)" );
+            CPLFree(pszJSon);
             delete arc;
           }
           arc = NULL;
         }
         ogrLine->addPoint(&ogrPoint);
       }
-      else if (EQUAL(firsttok, "ARCP"))
+      else if (EQUAL(firsttok, "ARCP") && CSLCount(tokens) >= 3)
       {
         //Finish line and start arc
         if (ogrLine->getNumPoints() > 1) {
           OGRErr error = ogrCurve->addCurveDirectly(ogrLine);
           if (error != OGRERR_NONE) {
-            CPLError(CE_Warning, CPLE_AppDefined, "Added geometry: %s", ogrLine->exportToJson() );
+            char* pszJSon = ogrLine->exportToJson();
+            CPLError(CE_Warning, CPLE_AppDefined, "Could not add geometry: %s",
+                     pszJSon ? pszJSon : "(null)" );
+            CPLFree(pszJSon);
+            delete ogrLine;
           }
           ogrLine = new OGRLineString();
         } else {
@@ -499,7 +512,11 @@ void ILI1Reader::ReadGeom( char **stgeom, int geomIdx, OGRwkbGeometryType eType,
         if (ogrLine->getNumPoints() > 1) { // Ignore single LIPT after ARCP
           OGRErr error = ogrCurve->addCurveDirectly(ogrLine);
           if (error != OGRERR_NONE) {
-            CPLError(CE_Warning, CPLE_AppDefined, "Added geometry: %s", ogrLine->exportToJson() );
+            char* pszJSon = ogrLine->exportToJson();
+            CPLError(CE_Warning, CPLE_AppDefined, "Could not add geometry: %s",
+                     pszJSon ? pszJSon : "(null)" );
+            CPLFree(pszJSon);
+            delete ogrLine;
           }
           ogrLine = NULL;
         }
@@ -508,7 +525,11 @@ void ILI1Reader::ReadGeom( char **stgeom, int geomIdx, OGRwkbGeometryType eType,
           {
             OGRErr error = ogrMultiLine->addGeometryDirectly(ogrCurve);
             if (error != OGRERR_NONE) {
-              CPLError(CE_Warning, CPLE_AppDefined, "Added geometry: %s", ogrCurve->exportToJson() );
+              char* pszJSon = ogrCurve->exportToJson();
+              CPLError(CE_Warning, CPLE_AppDefined, "Could not add geometry: %s",
+                       pszJSon ? pszJSon : "(null)" );
+              CPLFree(pszJSon);
+              delete ogrCurve;
             }
             ogrCurve = NULL;
           }
@@ -516,7 +537,11 @@ void ILI1Reader::ReadGeom( char **stgeom, int geomIdx, OGRwkbGeometryType eType,
           {
             OGRErr error = ogrPoly->addRingDirectly(ogrCurve);
             if (error != OGRERR_NONE) {
-              CPLError(CE_Warning, CPLE_AppDefined, "Added geometry: %s", ogrCurve->exportToJson() );
+              char* pszJSon = ogrCurve->exportToJson();
+              CPLError(CE_Warning, CPLE_AppDefined, "Could not add geometry: %s",
+                       pszJSon ? pszJSon : "(null)" );
+              CPLFree(pszJSon);
+              delete ogrCurve;
             }
             ogrCurve = NULL;
           }
@@ -648,7 +673,13 @@ char ** ILI1Reader::ReadParseLine()
     if (strlen(pszLine) == 0) return NULL;
 
     char **tokens = CSLTokenizeString2( pszLine, " ", CSLT_PRESERVEESCAPES );
-    char *token = tokens[CSLCount(tokens)-1];
+    int nCount = CSLCount(tokens);
+    if( nCount == 0 )
+    {
+        CSLDestroy(tokens);
+        return NULL;
+    }
+    const char *token = tokens[nCount-1];
 
     //Append CONT lines
     while (strlen(pszLine) && token[0] == codeContinue && token[1] == '\0')
@@ -663,7 +694,8 @@ char ** ILI1Reader::ReadParseLine()
           break;
       }
       char **conttok = CSLTokenizeString2( pszLine, " ", CSLT_PRESERVEESCAPES );
-      if (!conttok || !EQUAL(conttok[0], "CONT"))
+      if (!conttok || conttok[0] == NULL || !EQUAL(conttok[0], "CONT") ||
+          conttok[1] == NULL)
       {
           CSLDestroy(conttok);
           break;
@@ -675,6 +707,11 @@ char ** ILI1Reader::ReadParseLine()
 
       CSLDestroy(conttok);
     }
+    if( tokens[0] == NULL )
+    {
+        CSLDestroy(tokens);
+        tokens = NULL;
+    }
     return tokens;
 }
 
diff --git a/ogr/ogrsf_frmts/ili/ili2reader.cpp b/ogr/ogrsf_frmts/ili/ili2reader.cpp
index fe8a222..bd5fbe1 100644
--- a/ogr/ogrsf_frmts/ili/ili2reader.cpp
+++ b/ogr/ogrsf_frmts/ili/ili2reader.cpp
@@ -36,7 +36,7 @@
 
 using namespace std;
 
-CPL_CVSID("$Id: ili2reader.cpp 37743 2017-03-17 13:14:00Z rouault $");
+CPL_CVSID("$Id: ili2reader.cpp 39035 2017-06-09 18:10:22Z rouault $");
 
 //
 // constants
@@ -144,12 +144,15 @@ static OGRPoint *getPoint(DOMElement *elem) {
   while (coordElem != NULL) {
     char* pszTagName = XMLString::transcode(coordElem->getTagName());
     char* pszObjValue = getObjValue(coordElem);
-    if (cmpStr("C1", pszTagName) == 0)
-      pt->setX(CPLAtof(pszObjValue));
-    else if (cmpStr("C2", pszTagName) == 0)
-      pt->setY(CPLAtof(pszObjValue));
-    else if (cmpStr("C3", pszTagName) == 0)
-      pt->setZ(CPLAtof(pszObjValue));
+    if( pszObjValue )
+    {
+        if (cmpStr("C1", pszTagName) == 0)
+        pt->setX(CPLAtof(pszObjValue));
+        else if (cmpStr("C2", pszTagName) == 0)
+        pt->setY(CPLAtof(pszObjValue));
+        else if (cmpStr("C3", pszTagName) == 0)
+        pt->setZ(CPLAtof(pszObjValue));
+    }
     CPLFree(pszObjValue);
     XMLString::release(&pszTagName);
     coordElem = (DOMElement *)coordElem->getNextSibling();
@@ -173,20 +176,23 @@ OGRCircularString *ILI2Reader::getArc(DOMElement *elem) {
   while (arcElem != NULL) {
     char* pszTagName = XMLString::transcode(arcElem->getTagName());
     char* pszObjValue = getObjValue(arcElem);
-    if (cmpStr("C1", pszTagName) == 0)
-      ptEnd->setX(CPLAtof(pszObjValue));
-    else if (cmpStr("C2", pszTagName) == 0)
-      ptEnd->setY(CPLAtof(pszObjValue));
-    else if (cmpStr("C3", pszTagName) == 0)
-      ptEnd->setZ(CPLAtof(pszObjValue));
-    else if (cmpStr("A1", pszTagName) == 0)
-      ptOnArc->setX(CPLAtof(pszObjValue));
-    else if (cmpStr("A2", pszTagName) == 0)
-      ptOnArc->setY(CPLAtof(pszObjValue));
-    else if (cmpStr("A3", pszTagName) == 0)
-      ptOnArc->setZ(CPLAtof(pszObjValue));
-    else if (cmpStr("R", pszTagName) == 0) {
-      // radius = CPLAtof(pszObjValue);
+    if( pszObjValue )
+    {
+        if (cmpStr("C1", pszTagName) == 0)
+        ptEnd->setX(CPLAtof(pszObjValue));
+        else if (cmpStr("C2", pszTagName) == 0)
+        ptEnd->setY(CPLAtof(pszObjValue));
+        else if (cmpStr("C3", pszTagName) == 0)
+        ptEnd->setZ(CPLAtof(pszObjValue));
+        else if (cmpStr("A1", pszTagName) == 0)
+        ptOnArc->setX(CPLAtof(pszObjValue));
+        else if (cmpStr("A2", pszTagName) == 0)
+        ptOnArc->setY(CPLAtof(pszObjValue));
+        else if (cmpStr("A3", pszTagName) == 0)
+        ptOnArc->setZ(CPLAtof(pszObjValue));
+        else if (cmpStr("R", pszTagName) == 0) {
+        // radius = CPLAtof(pszObjValue);
+        }
     }
     CPLFree(pszObjValue);
     XMLString::release(&pszTagName);
@@ -235,20 +241,23 @@ static OGRCompoundCurve *getPolyline(DOMElement *elem) {
       while (arcElem != NULL) {
         char* pszTagName2 = XMLString::transcode(arcElem->getTagName());
         char* pszObjValue = getObjValue(arcElem);
-        if (cmpStr("C1", pszTagName2) == 0)
-          ptEnd->setX(CPLAtof(pszObjValue));
-        else if (cmpStr("C2", pszTagName2) == 0)
-          ptEnd->setY(CPLAtof(pszObjValue));
-        else if (cmpStr("C3", pszTagName2) == 0)
-          ptEnd->setZ(CPLAtof(pszObjValue));
-        else if (cmpStr("A1", pszTagName2) == 0)
-          ptOnArc->setX(CPLAtof(pszObjValue));
-        else if (cmpStr("A2", pszTagName2) == 0)
-          ptOnArc->setY(CPLAtof(pszObjValue));
-        else if (cmpStr("A3", pszTagName2) == 0)
-          ptOnArc->setZ(CPLAtof(pszObjValue));
-        else if (cmpStr("R", pszTagName2) == 0) {
-          // radius = CPLAtof(pszObjValue);
+        if( pszObjValue )
+        {
+            if (cmpStr("C1", pszTagName2) == 0)
+            ptEnd->setX(CPLAtof(pszObjValue));
+            else if (cmpStr("C2", pszTagName2) == 0)
+            ptEnd->setY(CPLAtof(pszObjValue));
+            else if (cmpStr("C3", pszTagName2) == 0)
+            ptEnd->setZ(CPLAtof(pszObjValue));
+            else if (cmpStr("A1", pszTagName2) == 0)
+            ptOnArc->setX(CPLAtof(pszObjValue));
+            else if (cmpStr("A2", pszTagName2) == 0)
+            ptOnArc->setY(CPLAtof(pszObjValue));
+            else if (cmpStr("A3", pszTagName2) == 0)
+            ptOnArc->setZ(CPLAtof(pszObjValue));
+            else if (cmpStr("R", pszTagName2) == 0) {
+            // radius = CPLAtof(pszObjValue);
+            }
         }
         CPLFree(pszObjValue);
         XMLString::release(&pszTagName2);
@@ -301,13 +310,13 @@ static OGRCompoundCurve *getBoundary(DOMElement *elem) {
 static OGRCurvePolygon *getPolygon(DOMElement *elem) {
   OGRCurvePolygon *pg = new OGRCurvePolygon();
 
-  DOMElement *boundaryElem = (DOMElement *)elem->getFirstChild(); // outer boundary
+  DOMElement *boundaryElem = dynamic_cast<DOMElement *>(elem->getFirstChild()); // outer boundary
   while (boundaryElem != NULL) {
     char* pszTagName = XMLString::transcode(boundaryElem->getTagName());
     if (cmpStr(ILI2_BOUNDARY, pszTagName) == 0)
       pg->addRingDirectly(getBoundary(boundaryElem));
     XMLString::release(&pszTagName);
-    boundaryElem = (DOMElement *)boundaryElem->getNextSibling(); // inner boundaries
+    boundaryElem = dynamic_cast<DOMElement *>(boundaryElem->getNextSibling()); // inner boundaries
   }
 
   return pg;
@@ -588,12 +597,19 @@ int ILI2Reader::SaveClasses( const char *pszFile = NULL ) {
         CPLDebug( "OGR_ILI", "Parsing %s", pszFile);
         m_poSAXReader->parse(pszFile);
     }
+    catch (const DOMException& toCatch)
+    {
+        // Can happen with createElement() in ILI2Handler::startElement()
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "DOMException: %s\n",
+                  transcode(toCatch.getMessage()).c_str());
+        return FALSE;
+    }
     catch (const SAXException& toCatch)
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Parsing failed: %s\n",
                   transcode(toCatch.getMessage()).c_str());
-
         return FALSE;
     }
 
diff --git a/ogr/ogrsf_frmts/ili/ogrili1datasource.cpp b/ogr/ogrsf_frmts/ili/ogrili1datasource.cpp
index 5fd2fea..0334293 100644
--- a/ogr/ogrsf_frmts/ili/ogrili1datasource.cpp
+++ b/ogr/ogrsf_frmts/ili/ogrili1datasource.cpp
@@ -35,7 +35,7 @@
 
 #include <string>
 
-CPL_CVSID("$Id: ogrili1datasource.cpp 34819 2016-07-28 22:32:18Z goatbar $");
+CPL_CVSID("$Id: ogrili1datasource.cpp 38486 2017-05-19 10:12:42Z rouault $");
 
 /************************************************************************/
 /*                         OGRILI1DataSource()                         */
@@ -101,10 +101,15 @@ int OGRILI1DataSource::Open( const char * pszNewName,
     else
     {
         char **filenames = CSLTokenizeString2( pszNewName, ",", 0 );
-
+        int nCount = CSLCount(filenames);
+        if( nCount == 0 )
+        {
+            CSLDestroy(filenames);
+            return FALSE;
+        }
         osBasename = filenames[0];
 
-        if( CSLCount(filenames) > 1 )
+        if( nCount > 1 )
             osModelFilename = filenames[1];
 
         CSLDestroy( filenames );
diff --git a/ogr/ogrsf_frmts/ili/ogrili2datasource.cpp b/ogr/ogrsf_frmts/ili/ogrili2datasource.cpp
index 6083e2c..bea9779 100644
--- a/ogr/ogrsf_frmts/ili/ogrili2datasource.cpp
+++ b/ogr/ogrsf_frmts/ili/ogrili2datasource.cpp
@@ -36,7 +36,7 @@
 
 using namespace std;
 
-CPL_CVSID("$Id: ogrili2datasource.cpp 37745 2017-03-17 13:43:46Z rouault $");
+CPL_CVSID("$Id: ogrili2datasource.cpp 38486 2017-05-19 10:12:42Z rouault $");
 
 /************************************************************************/
 /*                         OGRILI2DataSource()                         */
@@ -96,10 +96,15 @@ int OGRILI2DataSource::Open( const char * pszNewName,
     else
     {
         char **filenames = CSLTokenizeString2( pszNewName, ",", 0 );
-
+        int nCount = CSLCount(filenames);
+        if( nCount == 0 )
+        {
+            CSLDestroy(filenames);
+            return FALSE;
+        }
         osBasename = filenames[0];
 
-        if( CSLCount(filenames) > 1 )
+        if( nCount > 1 )
             osModelFilename = filenames[1];
 
         CSLDestroy( filenames );
diff --git a/ogr/ogrsf_frmts/jml/ogrjmllayer.cpp b/ogr/ogrsf_frmts/jml/ogrjmllayer.cpp
index 0b42fa7..f0cc33e 100644
--- a/ogr/ogrsf_frmts/jml/ogrjmllayer.cpp
+++ b/ogr/ogrsf_frmts/jml/ogrjmllayer.cpp
@@ -29,7 +29,7 @@
 #include "ogr_jml.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrjmllayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
+CPL_CVSID("$Id: ogrjmllayer.cpp 38401 2017-05-16 08:29:26Z rouault $");
 
 #ifdef HAVE_EXPAT
 
@@ -193,6 +193,8 @@ void OGRJMLLayer::startElementCbk(const char *pszName, const char **ppszAttr)
             {
                 if( !oColumn.osAttributeName.empty() &&
                     ppszAttr != NULL &&
+                    ppszAttr[0] != NULL &&
+                    ppszAttr[1] != NULL &&
                     oColumn.osAttributeName.compare(ppszAttr[0]) == 0 &&
                     oColumn.osAttributeValue.compare(ppszAttr[1]) == 0 )
                 {
@@ -215,6 +217,8 @@ void OGRJMLLayer::startElementCbk(const char *pszName, const char **ppszAttr)
             }
             else if( !oColumn.osAttributeName.empty() &&
                       ppszAttr != NULL &&
+                      ppszAttr[0] != NULL &&
+                      ppszAttr[1] != NULL &&
                       oColumn.osAttributeName.compare(ppszAttr[0]) == 0 )
             {
                 /* <osElementName osAttributeName="value"></osElementName> */
diff --git a/ogr/ogrsf_frmts/kml/kml.cpp b/ogr/ogrsf_frmts/kml/kml.cpp
index 71d8f96..4b4a53e 100644
--- a/ogr/ogrsf_frmts/kml/kml.cpp
+++ b/ogr/ogrsf_frmts/kml/kml.cpp
@@ -37,7 +37,7 @@
 #include <iostream>
 #include <string>
 
-CPL_CVSID("$Id: kml.cpp 35775 2016-10-17 00:43:44Z goatbar $");
+CPL_CVSID("$Id: kml.cpp 38409 2017-05-16 09:58:58Z rouault $");
 
 KML::KML() :
     poTrunk_(NULL),
@@ -213,7 +213,8 @@ void XMLCALL KML::startElement( void* pUserData, const char* pszName,
     poKML->nWithoutEventCounter = 0;
 
     if(poKML->poTrunk_ == NULL
-    || (poKML->poCurrent_->getName()).compare("description") != 0)
+    || (poKML->poCurrent_ != NULL &&
+        poKML->poCurrent_->getName().compare("description") != 0))
     {
         if (poKML->nDepth_ == 1024)
         {
@@ -244,7 +245,7 @@ void XMLCALL KML::startElement( void* pUserData, const char* pszName,
 
         poKML->nDepth_++;
     }
-    else
+    else if( poKML->poCurrent_ != NULL )
     {
         std::string sNewContent = "<";
         sNewContent += pszName;
@@ -635,11 +636,11 @@ void KML::unregisterLayerIfMatchingThisNode(KMLNode* poNode)
         {
             if( i < nNumLayers_ - 1 )
             {
-                memcpy( papoLayers_ + i, papoLayers_ + i + 1,
+                memmove( papoLayers_ + i, papoLayers_ + i + 1,
                         (nNumLayers_ - 1 - i) * sizeof(KMLNode*) );
             }
             nNumLayers_ --;
-            continue;
+            break;
         }
         i++;
     }
diff --git a/ogr/ogrsf_frmts/kml/kmlnode.cpp b/ogr/ogrsf_frmts/kml/kmlnode.cpp
index 8b476d4..b01e77c 100644
--- a/ogr/ogrsf_frmts/kml/kmlnode.cpp
+++ b/ogr/ogrsf_frmts/kml/kmlnode.cpp
@@ -32,7 +32,7 @@
 #include <string>
 #include <vector>
 
-CPL_CVSID("$Id: kmlnode.cpp 36981 2016-12-20 19:46:41Z rouault $");
+CPL_CVSID("$Id: kmlnode.cpp 38371 2017-05-15 10:59:39Z rouault $");
 
 /************************************************************************/
 /*                           Help functions                             */
@@ -331,6 +331,16 @@ int KMLNode::classify(KML* poKML, int nRecLevel)
     return TRUE;
 }
 
+
+void KMLNode::unregisterLayerIfMatchingThisNode(KML* poKML)
+{
+    for(std::size_t z = 0; z < countChildren(); z++)
+    {
+        getChild(z)->unregisterLayerIfMatchingThisNode(poKML);
+    }
+    poKML->unregisterLayerIfMatchingThisNode(this);
+}
+
 void KMLNode::eliminateEmpty(KML* poKML)
 {
     for(kml_nodes_t::size_type z = 0; z < pvpoChildren_->size(); z++)
@@ -339,7 +349,7 @@ void KMLNode::eliminateEmpty(KML* poKML)
            && (poKML->isContainer((*pvpoChildren_)[z]->sName_)
                || poKML->isFeatureContainer((*pvpoChildren_)[z]->sName_)))
         {
-            poKML->unregisterLayerIfMatchingThisNode((*pvpoChildren_)[z]);
+            (*pvpoChildren_)[z]->unregisterLayerIfMatchingThisNode(poKML);
             delete (*pvpoChildren_)[z];
             pvpoChildren_->erase(pvpoChildren_->begin() + z);
             z--;
diff --git a/ogr/ogrsf_frmts/kml/kmlnode.h b/ogr/ogrsf_frmts/kml/kmlnode.h
index c185edc..fde6ca1 100644
--- a/ogr/ogrsf_frmts/kml/kmlnode.h
+++ b/ogr/ogrsf_frmts/kml/kmlnode.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: kmlnode.h 36411 2016-11-21 22:03:48Z rouault $
+ * $Id: kmlnode.h 38371 2017-05-15 10:59:39Z rouault $
  *
  * Project:  KML Driver
  * Purpose:  Class for building up the node structure of the kml file.
@@ -110,6 +110,8 @@ private:
 
     int nLayerNumber_;
     int nNumFeatures_;
+
+    void unregisterLayerIfMatchingThisNode(KML* poKML);
 };
 
 #endif /* KMLNODE_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/mitab/mitab_coordsys.cpp b/ogr/ogrsf_frmts/mitab/mitab_coordsys.cpp
index 53edc12..ba39ade 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_coordsys.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_coordsys.cpp
@@ -44,7 +44,7 @@
 #include "mitab_priv.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: mitab_coordsys.cpp 37428 2017-02-19 23:32:58Z goatbar $");
+CPL_CVSID("$Id: mitab_coordsys.cpp 38441 2017-05-17 08:38:50Z rouault $");
 
 extern const MapInfoDatumInfo asDatumInfoList[];
 extern const MapInfoSpheroidInfo asSpheroidInfoList[];
@@ -252,7 +252,7 @@ int MITABCoordSys2TABProjInfo(const char * pszCoordSys, TABProjInfo *psProj)
     // Parse the passed string into words.
     while(*pszCoordSys == ' ')
         pszCoordSys++;  // Eat leading spaces.
-    if( STARTS_WITH_CI(pszCoordSys, "CoordSys") )
+    if( STARTS_WITH_CI(pszCoordSys, "CoordSys") && pszCoordSys[8] != '\0' )
         pszCoordSys += 9;
 
     char **papszFields =
diff --git a/ogr/ogrsf_frmts/mitab/mitab_feature.cpp b/ogr/ogrsf_frmts/mitab/mitab_feature.cpp
index 81e19b7..54dc3cb 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_feature.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_feature.cpp
@@ -54,7 +54,7 @@
 #include "ogr_featurestyle.h"
 #include "ogr_geometry.h"
 
-CPL_CVSID("$Id: mitab_feature.cpp 37434 2017-02-22 07:35:34Z goatbar $");
+CPL_CVSID("$Id: mitab_feature.cpp 38426 2017-05-16 19:38:58Z rouault $");
 
 /*=====================================================================
  *                      class TABFeature
@@ -4882,6 +4882,14 @@ int TABArc::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
             (540.0-m_dEndAngle);
     }
 
+    if( fabs(m_dEndAngle - m_dStartAngle) >= 721 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Wrong start and end angles: %f %f",
+                 m_dStartAngle, m_dEndAngle);
+        return -1;
+    }
+
     if (poMapFile->GetHeaderBlock()->m_nCoordOriginQuadrant==3 ||
         poMapFile->GetHeaderBlock()->m_nCoordOriginQuadrant==4 ||
         poMapFile->GetHeaderBlock()->m_nCoordOriginQuadrant==0 )
diff --git a/ogr/ogrsf_frmts/mitab/mitab_feature_mif.cpp b/ogr/ogrsf_frmts/mitab/mitab_feature_mif.cpp
index 079048e..da266a0 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_feature_mif.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_feature_mif.cpp
@@ -49,7 +49,7 @@
 #include "ogr_feature.h"
 #include "ogr_geometry.h"
 
-CPL_CVSID("$Id: mitab_feature_mif.cpp 37371 2017-02-13 11:41:59Z rouault $");
+CPL_CVSID("$Id: mitab_feature_mif.cpp 38426 2017-05-16 19:38:58Z rouault $");
 
 /*=====================================================================
  *                      class TABFeature
@@ -1602,6 +1602,14 @@ int TABArc::ReadGeometryFromMIFFile(MIDDATAFile *fp)
     CSLDestroy(papszToken);
     papszToken = NULL;
 
+    if( fabs(m_dEndAngle - m_dStartAngle) >= 721 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Wrong start and end angles: %f %f",
+                 m_dStartAngle, m_dEndAngle);
+        return -1;
+    }
+
     /*-------------------------------------------------------------
      * Start/End angles
      * Since the angles are specified for integer coordinates, and
diff --git a/ogr/ogrsf_frmts/mitab/mitab_mapcoordblock.cpp b/ogr/ogrsf_frmts/mitab/mitab_mapcoordblock.cpp
index 5bc89c7..c4aaaff 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_mapcoordblock.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_mapcoordblock.cpp
@@ -43,7 +43,7 @@
 #include "cpl_error.h"
 #include "cpl_vsi.h"
 
-CPL_CVSID("$Id: mitab_mapcoordblock.cpp 37347 2017-02-12 03:10:54Z goatbar $");
+CPL_CVSID("$Id: mitab_mapcoordblock.cpp 38360 2017-05-14 22:20:17Z rouault $");
 
 /*=====================================================================
  *                      class TABMAPCoordBlock
diff --git a/ogr/ogrsf_frmts/mitab/mitab_miffile.cpp b/ogr/ogrsf_frmts/mitab/mitab_miffile.cpp
index cf37e67..f632290 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_miffile.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_miffile.cpp
@@ -51,7 +51,7 @@
 #include "ogr_spatialref.h"
 #include "ogrsf_frmts.h"
 
-CPL_CVSID("$Id: mitab_miffile.cpp 37458 2017-02-25 18:58:53Z rouault $");
+CPL_CVSID("$Id: mitab_miffile.cpp 38321 2017-05-14 11:12:47Z rouault $");
 
 /*=====================================================================
  *                      class MIFFile
@@ -433,19 +433,23 @@ int MIFFile::ParseMIFHeader(int* pbIsEmpty)
            }
           CSLDestroy(papszToken);
         }
-        else if (STARTS_WITH_CI(pszLine, "UNIQUE"))
+        else if (m_pszUnique == NULL &&
+                 STARTS_WITH_CI(pszLine, "UNIQUE"))
         {
             bColumns = FALSE; bCoordSys = FALSE;
 
             m_pszUnique = CPLStrdup(pszLine + 6);
         }
-        else if (STARTS_WITH_CI(pszLine, "INDEX"))
+        else if (m_pszIndex == NULL &&
+                 STARTS_WITH_CI(pszLine, "INDEX"))
         {
             bColumns = FALSE; bCoordSys = FALSE;
 
             m_pszIndex = CPLStrdup(pszLine + 5);
         }
-        else if (STARTS_WITH_CI(pszLine, "COORDSYS") )
+        else if (m_pszCoordSys == NULL &&
+                 STARTS_WITH_CI(pszLine, "COORDSYS") &&
+                 CPLStrnlen(pszLine, 9) >= 9)
         {
             bCoordSys = TRUE;
             m_pszCoordSys = CPLStrdup(pszLine + 9);
@@ -1062,6 +1066,9 @@ int MIFFile::Close()
     CPLFree(m_pszDelimiter);
     m_pszDelimiter = NULL;
 
+    CPLFree(m_pszUnique);
+    m_pszUnique = NULL;
+
     CPLFree(m_pszFname);
     m_pszFname = NULL;
 
diff --git a/ogr/ogrsf_frmts/mitab/mitab_spatialref.cpp b/ogr/ogrsf_frmts/mitab/mitab_spatialref.cpp
index 7504052..b7e6e66 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_spatialref.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_spatialref.cpp
@@ -45,7 +45,7 @@
 #include "ogr_spatialref.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: mitab_spatialref.cpp 37449 2017-02-25 15:23:08Z rouault $");
+CPL_CVSID("$Id: mitab_spatialref.cpp 38702 2017-05-30 21:46:38Z rouault $");
 
 /* -------------------------------------------------------------------- */
 /*      This table was automatically generated by doing translations    */
@@ -241,7 +241,7 @@ const MapInfoDatumInfo asDatumInfoList[] =
 { 0,    1016,"Finnish_KKJ",                4, -96.062, -82.428, -121.754, -4.801, -0.345, 1.376, 1.496, 0},
 { 6610, 1017,"Xian 1980",                  53, 24, -123, -94, -0.02, -0.25, 0.13, 1.1, 0},
 { 0,    1018,"Lithuanian Pulkovo 1942",    4, -40.59527, -18.54979, -69.33956, -2.508, -1.8319, 2.6114, -4.2991, 0},
-{ 0,    1019,"Belgian 1972 7 Parameter",   4, -99.059, 53.322, -112.486, -0.419, 0.83, -1.885, 0.999999, 0},
+{ 6313, 1019,"Belgian 1972 7 Parameter",   4, -99.059, 53.322, -112.486, -0.419, 0.83, -1.885, 0.999999, 0},
 { 6818, 1020,"S-JTSK with Ferro prime meridian", 10, 589, 76, 480, 0, 0, 0, 0, -17.666666666667},
 
 { -1,   -1, NULL,                          0, 0, 0, 0, 0, 0, 0, 0, 0}
diff --git a/ogr/ogrsf_frmts/mitab/mitab_tabfile.cpp b/ogr/ogrsf_frmts/mitab/mitab_tabfile.cpp
index 52b0e5b..ce32c42 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_tabfile.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_tabfile.cpp
@@ -55,7 +55,7 @@
 #include "ogr_spatialref.h"
 #include "ogrsf_frmts.h"
 
-CPL_CVSID("$Id: mitab_tabfile.cpp 37351 2017-02-12 05:22:20Z goatbar $");
+CPL_CVSID("$Id: mitab_tabfile.cpp 38309 2017-05-14 09:26:54Z rouault $");
 
 static const char UNSUPPORTED_OP_READ_ONLY[] =
   "%s : unsupported operation on a read-only datasource.";
@@ -659,7 +659,7 @@ int TABFile::ParseTABFileFields()
         while(*pszStr != '\0' && isspace((unsigned char)*pszStr))
             pszStr++;
 
-        if (STARTS_WITH_CI(pszStr, "Fields"))
+        if (STARTS_WITH_CI(pszStr, "Fields") && CPLStrnlen(pszStr, 7) >= 7)
         {
             /*---------------------------------------------------------
              * We found the list of table fields
diff --git a/ogr/ogrsf_frmts/mongodb/mongocxx_headers.h b/ogr/ogrsf_frmts/mongodb/mongocxx_headers.h
index 6f0831b..a6ee3b2 100644
--- a/ogr/ogrsf_frmts/mongodb/mongocxx_headers.h
+++ b/ogr/ogrsf_frmts/mongodb/mongocxx_headers.h
@@ -42,7 +42,7 @@
 #pragma warning( disable : 4244 )
 #endif
 
-#ifdef WIN32
+#ifdef _WIN32
 #include <winsock2.h>
 #undef min
 #undef max
diff --git a/ogr/ogrsf_frmts/mysql/ogr_mysql.h b/ogr/ogrsf_frmts/mysql/ogr_mysql.h
index 07a6827..76a6762 100644
--- a/ogr/ogrsf_frmts/mysql/ogr_mysql.h
+++ b/ogr/ogrsf_frmts/mysql/ogr_mysql.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_mysql.h 36501 2016-11-25 14:09:24Z rouault $
+ * $Id: ogr_mysql.h 38631 2017-05-23 20:07:01Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Declarations for MySQL OGR Driver Classes.
@@ -32,6 +32,10 @@
 #ifndef OGR_MYSQL_H_INCLUDED
 #define OGR_MYSQL_H_INCLUDED
 
+// Include cpl_port.h before mysql stuff to avoid issues with CPLIsFinite()
+// See https://trac.osgeo.org/gdal/ticket/6899
+#include "cpl_port.h"
+
 #ifdef _MSC_VER
 #pragma warning( push )
 #pragma warning( disable : 4324 ) /* 'my_alignment_imp<0x02>' : structure was padded due to __declspec(align()) */
diff --git a/ogr/ogrsf_frmts/nas/nasreader.cpp b/ogr/ogrsf_frmts/nas/nasreader.cpp
index b8fd047..37a5291 100644
--- a/ogr/ogrsf_frmts/nas/nasreader.cpp
+++ b/ogr/ogrsf_frmts/nas/nasreader.cpp
@@ -38,7 +38,7 @@
 
 #include <algorithm>
 
-CPL_CVSID("$Id: nasreader.cpp 36300 2016-11-19 15:05:34Z jef $");
+CPL_CVSID("$Id: nasreader.cpp 38566 2017-05-21 16:59:47Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -406,6 +406,11 @@ void NASReader::PopState()
             m_poCompleteFeature = m_poState->m_poFeature;
             m_poState->m_poFeature = NULL;
         }
+        else if( m_poState->m_poFeature != NULL )
+        {
+            delete m_poState->m_poFeature;
+            m_poState->m_poFeature = NULL;
+        }
 
         GMLReadState *poParent = m_poState->m_poParentState;
 
diff --git a/ogr/ogrsf_frmts/ntf/ntf.h b/ogr/ogrsf_frmts/ntf/ntf.h
index c4c3fa9..9f3b129 100644
--- a/ogr/ogrsf_frmts/ntf/ntf.h
+++ b/ogr/ogrsf_frmts/ntf/ntf.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ntf.h 36501 2016-11-25 14:09:24Z rouault $
+ * $Id: ntf.h 39074 2017-06-11 19:04:21Z rouault $
  *
  * Project:  NTF Translator
  * Purpose:  Main declarations for NTF translator.
@@ -278,6 +278,8 @@ class NTFFileReader
     int               bCacheLines;
     int               nLineCacheSize;
     OGRGeometry     **papoLineCache;
+    
+    void              AddToIndexGroup( NTFRecord * poRecord );
 
   public:
     explicit           NTFFileReader( OGRNTFDataSource * );
@@ -306,9 +308,9 @@ class NTFFileReader
 
     int               ProcessAttValue( const char *pszValType,
                                        const char *pszRawValue,
-                                       char **ppszAttName,
-                                       char **ppszAttValue,
-                                       char **ppszCodeDesc );
+                                       const char **ppszAttName,
+                                       const char **ppszAttValue,
+                                       const char **ppszCodeDesc );
 
     int               TestForLayer( OGRNTFLayer * );
     OGRFeature       *ReadOGRFeature( OGRNTFLayer * = NULL );
@@ -421,7 +423,7 @@ class OGRNTFFeatureClassLayer : public OGRLayer
 
     OGRNTFDataSource   *poDS;
 
-    int                 iCurrentFC;
+    GIntBig            iCurrentFC;
 
   public:
     explicit             OGRNTFFeatureClassLayer( OGRNTFDataSource * poDS );
@@ -458,7 +460,7 @@ class OGRNTFRasterLayer : public OGRLayer
     float              *pafColumn;
     int                 iColumnOffset;
 
-    int                 iCurrentFC;
+    GIntBig             iCurrentFC;
 
     int                 nDEMSample;
     int                 nFeatureCount;
diff --git a/ogr/ogrsf_frmts/ntf/ntf_codelist.cpp b/ogr/ogrsf_frmts/ntf/ntf_codelist.cpp
index bdd8d51..8425d69 100644
--- a/ogr/ogrsf_frmts/ntf/ntf_codelist.cpp
+++ b/ogr/ogrsf_frmts/ntf/ntf_codelist.cpp
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ntf_codelist.cpp 35191 2016-08-24 01:33:06Z goatbar $");
+CPL_CVSID("$Id: ntf_codelist.cpp 38652 2017-05-29 07:37:00Z rouault $");
 
 /************************************************************************/
 /*                             NTFCodeList                              */
@@ -48,16 +48,20 @@ NTFCodeList::NTFCodeList( NTFRecord * poRecord ) :
     snprintf( szValType, sizeof(szValType), "%s", poRecord->GetField(13,14) );
     snprintf( szFInter, sizeof(szFInter), "%s", poRecord->GetField(15,19) );
 
+    const int nRecordLen = poRecord->GetLength();
     const char *pszText = poRecord->GetData() + 22;
     int iThisField = 0;
     for( ;
-         *pszText != '\0' && iThisField < nNumCode;
+         nRecordLen > 22 && *pszText != '\0' && iThisField < nNumCode;
          iThisField++ )
     {
         char szVal[128] = {};
         int iLen = 0;
-        while( *pszText != '\\' && *pszText != '\0' )
+        while( iLen < static_cast<int>(sizeof(szVal)) - 1 &&
+               *pszText != '\\' && *pszText != '\0' )
+        {
             szVal[iLen++] = *(pszText++);
+        }
         szVal[iLen] = '\0';
 
         if( *pszText == '\\' )
@@ -65,8 +69,11 @@ NTFCodeList::NTFCodeList( NTFRecord * poRecord ) :
 
         iLen = 0;
         char szDes[128] = {};
-        while( *pszText != '\\' && *pszText != '\0' )
+        while( iLen < static_cast<int>(sizeof(szDes)) - 1 &&
+               *pszText != '\\' && *pszText != '\0' )
+        {
             szDes[iLen++] = *(pszText++);
+        }
         szDes[iLen] = '\0';
 
         if( *pszText == '\\' )
diff --git a/ogr/ogrsf_frmts/ntf/ntf_estlayers.cpp b/ogr/ogrsf_frmts/ntf/ntf_estlayers.cpp
index 5407c57..fb455e8 100644
--- a/ogr/ogrsf_frmts/ntf/ntf_estlayers.cpp
+++ b/ogr/ogrsf_frmts/ntf/ntf_estlayers.cpp
@@ -32,7 +32,7 @@
 #include "ntf.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ntf_estlayers.cpp 35911 2016-10-24 15:03:26Z goatbar $");
+CPL_CVSID("$Id: ntf_estlayers.cpp 39029 2017-06-09 14:40:19Z rouault $");
 
 static const int MAX_LINK = 5000;
 
@@ -1435,7 +1435,7 @@ static OGRFeature *TranslateProfilePoint( NTFFileReader *poReader,
                                     NULL );
 
     // Set HEIGHT/elevation
-    OGRPoint    *poPoint = (OGRPoint *) poFeature->GetGeometryRef();
+    OGRPoint    *poPoint = dynamic_cast<OGRPoint *>(poFeature->GetGeometryRef());
 
     if( poPoint != NULL && poPoint->getCoordinateDimension() == 3 )
     {
@@ -1482,7 +1482,7 @@ static OGRFeature *TranslateProfileLine( NTFFileReader *poReader,
                                     NULL );
 
     // Set HEIGHT/elevation
-    OGRLineString *poLine = (OGRLineString *) poFeature->GetGeometryRef();
+    OGRLineString *poLine = dynamic_cast<OGRLineString*>(poFeature->GetGeometryRef());
 
     poFeature->SetField( 2, poFeature->GetFieldAsDouble(2) * 0.01 );
     if( poLine != NULL && poLine->getCoordinateDimension() == 2 )
@@ -1743,9 +1743,10 @@ void NTFFileReader::EstablishLayer( const char * pszLayerName,
                 {
                     oFieldDefn.SetType( OFTReal );
                     oFieldDefn.SetWidth( poClass->panAttrMaxWidth[iGAtt]+1 );
-                    if( pszFormat[2] == ',' )
+                    const size_t nFormatLen = strlen(pszFormat);
+                    if( nFormatLen >= 4 && pszFormat[2] == ',' )
                         oFieldDefn.SetPrecision(atoi(pszFormat+3));
-                    else if( pszFormat[3] == ',' )
+                    else if( nFormatLen >= 5 && pszFormat[3] == ',' )
                         oFieldDefn.SetPrecision(atoi(pszFormat+4));
                 }
 
diff --git a/ogr/ogrsf_frmts/ntf/ntf_generic.cpp b/ogr/ogrsf_frmts/ntf/ntf_generic.cpp
index 49053da..08958b7 100644
--- a/ogr/ogrsf_frmts/ntf/ntf_generic.cpp
+++ b/ogr/ogrsf_frmts/ntf/ntf_generic.cpp
@@ -30,7 +30,7 @@
 #include "ntf.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ntf_generic.cpp 37371 2017-02-13 11:41:59Z rouault $");
+CPL_CVSID("$Id: ntf_generic.cpp 38953 2017-06-07 22:10:29Z rouault $");
 
 static const int MAX_LINK = 5000;
 
@@ -172,7 +172,9 @@ void OGRNTFDataSource::WorkupGeneric( NTFFileReader * poReader )
         else
             papoGroup = poReader->ReadRecordGroup();
 
-        if( papoGroup == NULL || papoGroup[0]->GetType() == 99 )
+        if( papoGroup == NULL ||
+            papoGroup[0]->GetType() < 0 ||
+            papoGroup[0]->GetType() >= 99 )
             break;
 
 /* -------------------------------------------------------------------- */
@@ -199,11 +201,12 @@ void OGRNTFDataSource::WorkupGeneric( NTFFileReader * poReader )
                   poReader->ProcessAttRec( poRecord, NULL,
                                            &papszTypes, &papszValues );
 
-                  for( int iAtt = 0; papszTypes[iAtt] != NULL; iAtt++ )
+                  for( int iAtt = 0; papszTypes != NULL &&
+                                     papszTypes[iAtt] != NULL; iAtt++ )
                   {
                       NTFAttDesc *poAttDesc =
                           poReader->GetAttDesc( papszTypes[iAtt] );
-                      if( poAttDesc != NULL )
+                      if( poAttDesc != NULL && papszValues[iAtt] != NULL )
                       {
                           poClass->CheckAddAttr( poAttDesc->val_type,
                                                  poAttDesc->finter,
@@ -325,9 +328,9 @@ static void AddGenericAttributes( NTFFileReader * poReader,
 /* -------------------------------------------------------------------- */
         if( iListField != -1 )
         {
-            char *pszAttLongName = NULL;
-            char *pszAttValue = NULL;
-            char *pszCodeDesc = NULL;
+            const char *pszAttLongName = NULL;
+            const char *pszAttValue = NULL;
+            const char *pszCodeDesc = NULL;
 
             poReader->ProcessAttValue( papszTypes[iAtt], papszValues[iAtt],
                                        &pszAttLongName, &pszAttValue,
@@ -384,7 +387,10 @@ static OGRFeature *TranslateGenericNode( NTFFileReader *poReader,
     if( papoGroup[0]->GetLength() > 18 )
     {
         nLinkCount = atoi(papoGroup[0]->GetField(15,18));
-        panLinks = (int *) CPLCalloc(sizeof(int),nLinkCount);
+        if( nLinkCount > 0 )
+        {
+            panLinks = static_cast<int *>(CPLCalloc(sizeof(int), nLinkCount));
+        }
     }
 
     poFeature->SetField( "NUM_LINKS", nLinkCount );
@@ -434,10 +440,18 @@ static OGRFeature *TranslateGenericCollection( NTFFileReader *poReader,
     int         nPartCount=0;
     int         *panParts = NULL;
 
-    if( papoGroup[0]->GetLength() > 18 )
+    if( papoGroup[0]->GetLength() >= 20 )
     {
         nPartCount = atoi(papoGroup[0]->GetField(9,12));
-        panParts = (int *) CPLCalloc(sizeof(int),nPartCount);
+        if( nPartCount > 0 &&
+            nPartCount-1 <= (papoGroup[0]->GetLength() - 20) / 8 )
+        {
+            panParts = static_cast<int *>(CPLCalloc(sizeof(int), nPartCount));
+        }
+        else
+        {
+            nPartCount = 0;
+        }
     }
 
     poFeature->SetField( "NUM_PARTS", nPartCount );
@@ -548,7 +562,8 @@ static OGRFeature *TranslateGenericName( NTFFileReader *poReader,
     // TEXT
     int nNumChar = atoi(papoGroup[0]->GetField(13,14));
 
-    poFeature->SetField( "TEXT", papoGroup[0]->GetField( 15, 15+nNumChar-1));
+    if( nNumChar > 0 && papoGroup[0]->GetLength() >= 15+nNumChar-1 )
+        poFeature->SetField( "TEXT", papoGroup[0]->GetField( 15, 15+nNumChar-1));
 
     // Geometry
     for( int iRec = 0; papoGroup[iRec] != NULL; iRec++ )
@@ -627,7 +642,7 @@ static OGRFeature *TranslateGenericPoint( NTFFileReader *poReader,
         snprintf( szValType, sizeof(szValType), "%s", papoGroup[0]->GetField(9,10) );
         if( !EQUAL(szValType,"  ") )
         {
-            char *pszProcessedValue = NULL;
+            const char *pszProcessedValue = NULL;
 
             if( poReader->ProcessAttValue(szValType,
                                           papoGroup[0]->GetField(11,16),
@@ -679,7 +694,7 @@ static OGRFeature *TranslateGenericLine( NTFFileReader *poReader,
         snprintf( szValType, sizeof(szValType), "%s", papoGroup[0]->GetField(9,10) );
         if( !EQUAL(szValType,"  ") )
         {
-            char *pszProcessedValue = NULL;
+            const char *pszProcessedValue = NULL;
 
             if( poReader->ProcessAttValue(szValType,
                                           papoGroup[0]->GetField(11,16),
@@ -720,7 +735,7 @@ static OGRFeature *TranslateGenericPoly( NTFFileReader *poReader,
         // NUM_PARTS
         int             nNumLinks = atoi(papoGroup[1]->GetField( 9, 12 ));
 
-        if( nNumLinks > MAX_LINK )
+        if( nNumLinks < 0 || nNumLinks > MAX_LINK )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "MAX_LINK exceeded in ntf_generic.cpp." );
@@ -786,7 +801,7 @@ static OGRFeature *TranslateGenericCPoly( NTFFileReader *poReader,
          && papoGroup[1]->GetType() != NRT_GEOMETRY3D) )
         return NULL;
 
-    if( papoGroup[1] != NULL
+    if( papoGroup[2] != NULL
         && papoGroup[2]->GetType() != NRT_ATTREC )
         return NULL;
 
@@ -822,6 +837,13 @@ static OGRFeature *TranslateGenericCPoly( NTFFileReader *poReader,
     int         anPolyId[MAX_LINK*2];
 
     nNumLink = atoi(papoGroup[0]->GetField(9,12));
+    if( nNumLink < 0 || nNumLink > MAX_LINK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                    "MAX_LINK exceeded in ntf_generic.cpp." );
+        return poFeature;
+    }
+
     for( int iLink = 0; iLink < nNumLink; iLink++ )
     {
         anPolyId[iLink] = atoi(papoGroup[0]->GetField(13 + iLink*7,
diff --git a/ogr/ogrsf_frmts/ntf/ntf_raster.cpp b/ogr/ogrsf_frmts/ntf/ntf_raster.cpp
index b9b0ec1..6c2ba40 100644
--- a/ogr/ogrsf_frmts/ntf/ntf_raster.cpp
+++ b/ogr/ogrsf_frmts/ntf/ntf_raster.cpp
@@ -32,7 +32,7 @@
 
 #include <algorithm>
 
-CPL_CVSID("$Id: ntf_raster.cpp 36332 2016-11-20 15:19:39Z rouault $");
+CPL_CVSID("$Id: ntf_raster.cpp 39070 2017-06-11 17:46:53Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -127,6 +127,9 @@ void NTFFileReader::EstablishRasterAccess()
 /* -------------------------------------------------------------------- */
     delete poRecord;
 
+    if( !GDALCheckDatasetDimensions(nRasterXSize, nRasterYSize) )
+        return;
+
     panColumnOffset = (long *) CPLCalloc(sizeof(long),nRasterXSize);
 
     GetFPPos( panColumnOffset+0, NULL );
@@ -178,6 +181,8 @@ CPLErr NTFFileReader::ReadRasterColumn( int iColumn, float *pafElev )
 /* -------------------------------------------------------------------- */
     SetFPPos( panColumnOffset[iColumn], iColumn );
     NTFRecord *poRecord = ReadRecord();
+    if( poRecord == NULL )
+        return CE_Failure;
 
     if( iColumn < nRasterXSize-1 )
     {
@@ -192,7 +197,7 @@ CPLErr NTFFileReader::ReadRasterColumn( int iColumn, float *pafElev )
         const double dfVOffset = atoi(poRecord->GetField(56,65));
         const double dfVScale = atoi(poRecord->GetField(66,75)) * 0.001;
 
-        for( int iPixel = 0; iPixel < nRasterXSize; iPixel++ )
+        for( int iPixel = 0; iPixel < nRasterYSize; iPixel++ )
         {
             pafElev[iPixel] = (float) (dfVOffset + dfVScale *
                 atoi(poRecord->GetField(84+iPixel*4,87+iPixel*4)));
@@ -204,7 +209,7 @@ CPLErr NTFFileReader::ReadRasterColumn( int iColumn, float *pafElev )
 /* -------------------------------------------------------------------- */
     else if( pafElev != NULL && GetProductId() == NPC_LANDFORM_PROFILE_DTM )
     {
-        for( int iPixel = 0; iPixel < nRasterXSize; iPixel++ )
+        for( int iPixel = 0; iPixel < nRasterYSize; iPixel++ )
         {
             pafElev[iPixel] = (float)
            (atoi(poRecord->GetField(19+iPixel*5,23+iPixel*5)) * GetZMult());
@@ -234,7 +239,7 @@ OGRNTFRasterLayer::OGRNTFRasterLayer( OGRNTFDataSource *poDSIn,
     pafColumn(static_cast<float *>(
         CPLCalloc(sizeof(float), poReaderIn->GetRasterYSize()))),
     iColumnOffset(-1),
-    iCurrentFC(0),
+    iCurrentFC(1),
     // Check for DEM subsampling.
     nDEMSample(poDSIn->GetOption( "DEM_SAMPLE" ) == NULL ?
                1 : std::max(1, atoi(poDSIn->GetOption("DEM_SAMPLE")))),
@@ -295,7 +300,7 @@ void OGRNTFRasterLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
 void OGRNTFRasterLayer::ResetReading()
 
 {
-    iCurrentFC = 0;
+    iCurrentFC = 1;
 }
 
 /************************************************************************/
@@ -305,30 +310,33 @@ void OGRNTFRasterLayer::ResetReading()
 OGRFeature *OGRNTFRasterLayer::GetNextFeature()
 
 {
-    if( iCurrentFC == 0 )
-        iCurrentFC = 1;
-    else
+    if( iCurrentFC > static_cast<GIntBig>(poReader->GetRasterXSize())*
+                                          poReader->GetRasterYSize() )
     {
-        int     iReqColumn, iReqRow;
+        return NULL;
+    }
 
-        iReqColumn = (iCurrentFC - 1) / poReader->GetRasterYSize();
-        iReqRow = iCurrentFC - iReqColumn * poReader->GetRasterXSize() - 1;
+    OGRFeature* poFeature = GetFeature( iCurrentFC );
 
-        if( iReqRow + nDEMSample > poReader->GetRasterYSize() )
-        {
-            iReqRow = 0;
-            iReqColumn += nDEMSample;
-        }
-        else
-        {
-            iReqRow += nDEMSample;
-        }
+    int     iReqColumn, iReqRow;
 
-        iCurrentFC = iReqColumn * poReader->GetRasterYSize()
-            + iReqRow + 1;
+    iReqColumn = static_cast<int>((iCurrentFC - 1) / poReader->GetRasterYSize());
+    iReqRow = static_cast<int>(iCurrentFC - iReqColumn * poReader->GetRasterYSize() - 1);
+
+    if( iReqRow + nDEMSample > poReader->GetRasterYSize() )
+    {
+        iReqRow = 0;
+        iReqColumn += nDEMSample;
+    }
+    else
+    {
+        iReqRow += nDEMSample;
     }
 
-    return GetFeature( (long) iCurrentFC );
+    iCurrentFC = static_cast<GIntBig>(iReqColumn) * poReader->GetRasterYSize()
+        + iReqRow + 1;
+
+    return poFeature;
 }
 
 /************************************************************************/
@@ -352,8 +360,8 @@ OGRFeature *OGRNTFRasterLayer::GetFeature( GIntBig nFeatureId )
 /* -------------------------------------------------------------------- */
 /*      Do we need to load a different column.                          */
 /* -------------------------------------------------------------------- */
-    iReqColumn = ((int)nFeatureId - 1) / poReader->GetRasterYSize();
-    iReqRow = (int)nFeatureId - iReqColumn * poReader->GetRasterXSize() - 1;
+    iReqColumn = static_cast<int>((nFeatureId - 1) / poReader->GetRasterYSize());
+    iReqRow = static_cast<int>(nFeatureId - iReqColumn * poReader->GetRasterYSize() - 1);
 
     if( iReqColumn != iColumnOffset )
     {
@@ -361,6 +369,8 @@ OGRFeature *OGRNTFRasterLayer::GetFeature( GIntBig nFeatureId )
         if( poReader->ReadRasterColumn( iReqColumn, pafColumn ) != CE_None )
             return NULL;
     }
+    if( iReqRow < 0 || iReqRow >= poReader->GetRasterYSize() )
+        return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding feature.                                 */
diff --git a/ogr/ogrsf_frmts/ntf/ntffilereader.cpp b/ogr/ogrsf_frmts/ntf/ntffilereader.cpp
index 1342e5f..303b877 100644
--- a/ogr/ogrsf_frmts/ntf/ntffilereader.cpp
+++ b/ogr/ogrsf_frmts/ntf/ntffilereader.cpp
@@ -35,7 +35,7 @@
 
 #include <algorithm>
 
-CPL_CVSID("$Id: ntffilereader.cpp 36776 2016-12-10 11:17:47Z rouault $");
+CPL_CVSID("$Id: ntffilereader.cpp 39006 2017-06-09 07:55:52Z rouault $");
 
 static int DefaultNTFRecordGrouper( NTFFileReader *, NTFRecord **,
                                     NTFRecord * );
@@ -88,6 +88,8 @@ NTFFileReader::NTFFileReader( OGRNTFDataSource * poDataSource ) :
     papoLineCache(NULL)
 {
     apoCGroup[0] = NULL;
+    apoCGroup[1] = NULL;
+    apoCGroup[MAX_REC_GROUP] = NULL;
     memset( adfGeoTransform, 0, sizeof(adfGeoTransform) );
     memset( apoTypeTranslation, 0, sizeof(apoTypeTranslation) );
     for( int i = 0; i < 100; i++ )
@@ -278,7 +280,7 @@ int NTFFileReader::Open( const char * pszFilenameIn )
 /* -------------------------------------------------------------------- */
 /*      Handle feature class name records.                              */
 /* -------------------------------------------------------------------- */
-        if( poRecord->GetType() == NRT_FCR )
+        if( poRecord->GetType() == NRT_FCR && poRecord->GetLength() >= 37 )
         {
             nFCCount++;
 
@@ -345,6 +347,11 @@ int NTFFileReader::Open( const char * pszFilenameIn )
                           poCodeList->szValType );
                 delete poCodeList;
             }
+            else if( psAttDesc->poCodeList != NULL )
+            {
+                // Should not happen on sane files.
+                delete poCodeList;
+            }
             else
             {
                 psAttDesc->poCodeList = poCodeList;
@@ -395,7 +402,8 @@ int NTFFileReader::Open( const char * pszFilenameIn )
 /* -------------------------------------------------------------------- */
 /*      Classify the product type.                                      */
 /* -------------------------------------------------------------------- */
-    if( STARTS_WITH_CI(pszProduct, "LAND-LINE") && CPLAtof(pszPVName+5) < 1.3 )
+    if( STARTS_WITH_CI(pszProduct, "LAND-LINE") && strlen(pszPVName) > 5 &&
+        CPLAtof(pszPVName+5) < 1.3 )
         nProduct = NPC_LANDLINE;
     else if( STARTS_WITH_CI(pszProduct, "LAND-LINE") )
         nProduct = NPC_LANDLINE99;
@@ -456,15 +464,19 @@ int NTFFileReader::Open( const char * pszFilenameIn )
     nStartPos = VSIFTell(fp);
 
     pszTileName = CPLStrdup(poRecord->GetField(3,12));        // SECT_REF
-    while( pszTileName[strlen(pszTileName)-1] == ' ' )
-        pszTileName[strlen(pszTileName)-1] = '\0';
+    size_t nTileNameLen = strlen(pszTileName);
+    while( nTileNameLen > 0 && pszTileName[nTileNameLen-1] == ' ' )
+    {
+        pszTileName[nTileNameLen-1] = '\0';
+        nTileNameLen --;
+    }
 
     nCoordWidth = atoi(poRecord->GetField(15,19));            // XYLEN
-    if( nCoordWidth == 0 )
+    if( nCoordWidth <= 0 )
         nCoordWidth = 10;
 
     nZWidth = atoi(poRecord->GetField(31,35));                // ZLEN
-    if( nZWidth == 0 )
+    if( nZWidth <= 0 )
         nZWidth = 10;
 
     dfXYMult = atoi(poRecord->GetField(21,30)) / 1000.0;      // XY_MULT
@@ -676,8 +688,7 @@ OGRGeometry *NTFFileReader::ProcessGeometry( NTFRecord * poRecord,
     else
     {
         CPLError(CE_Failure, CPLE_AppDefined,
-                 "GType = %d", nGType );
-        CPLAssert( false );
+                 "Unhandled GType = %d", nGType );
     }
 
     if( poGeometry != NULL )
@@ -774,10 +785,10 @@ OGRGeometry *NTFFileReader::ProcessGeometry3D( NTFRecord * poRecord,
 int NTFFileReader::ProcessAttDesc( NTFRecord * poRecord, NTFAttDesc* psAD )
 
 {
-    if( poRecord->GetType() != NRT_ADR )
+    psAD->poCodeList = NULL;
+    if( poRecord->GetType() != NRT_ADR || poRecord->GetLength() < 13 )
         return FALSE;
 
-    psAD->poCodeList = NULL;
     snprintf( psAD->val_type, sizeof(psAD->val_type), "%s", poRecord->GetField( 3, 4 ));
     snprintf( psAD->fwidth, sizeof(psAD->fwidth), "%s", poRecord->GetField( 5, 7 ));
     snprintf( psAD->finter, sizeof(psAD->finter), "%s", poRecord->GetField( 8, 12 ));
@@ -817,7 +828,13 @@ int NTFFileReader::ProcessAttRecGroup( NTFRecord **papoRecords,
         char **papszValues1 = NULL;
         if( !ProcessAttRec( papoRecords[iRec], NULL,
                             &papszTypes1, &papszValues1 ) )
+        {
+            CSLDestroy(*ppapszTypes);
+            CSLDestroy(*ppapszValues);
+            *ppapszTypes = NULL;
+            *ppapszValues = NULL;
             return FALSE;
+        }
 
         if( *ppapszTypes == NULL )
         {
@@ -849,7 +866,12 @@ int NTFFileReader::ProcessAttRec( NTFRecord * poRecord,
                                   char *** ppapszValues )
 
 {
-    if( poRecord->GetType() != NRT_ATTREC )
+    if( pnAttId != NULL )
+        *pnAttId = 0;
+    *ppapszTypes = NULL;
+    *ppapszValues = NULL;
+
+    if( poRecord->GetType() != NRT_ATTREC || poRecord->GetLength() < 8 )
         return FALSE;
 
 /* -------------------------------------------------------------------- */
@@ -862,13 +884,12 @@ int NTFFileReader::ProcessAttRec( NTFRecord * poRecord,
 /*      Loop handling attribute till we get a '0' indicating the end    */
 /*      of the record.                                                  */
 /* ==================================================================== */
-    *ppapszTypes = NULL;
-    *ppapszValues = NULL;
 
     int iOffset = 8;
     const char *pszData = poRecord->GetData();
+    bool bError = false;
 
-    while( pszData[iOffset] != '0' && pszData[iOffset] != '\0' )
+    while( iOffset < poRecord->GetLength() && pszData[iOffset] != '0' )
     {
 /* -------------------------------------------------------------------- */
 /*      Extract the two letter code name for the attribute, and use     */
@@ -879,7 +900,8 @@ int NTFFileReader::ProcessAttRec( NTFRecord * poRecord,
         {
             CPLDebug( "NTF", "Couldn't translate attrec type `%2.2s'.",
                       pszData + iOffset );
-            return FALSE;
+            bError = true;
+            break;
         }
 
         *ppapszTypes =
@@ -891,11 +913,20 @@ int NTFFileReader::ProcessAttRec( NTFRecord * poRecord,
 /*      terminated by a backslash.                                      */
 /* -------------------------------------------------------------------- */
         const int nFWidth = atoi(psAttDesc->fwidth);
+        if( nFWidth < 0 )
+        {
+            bError = true;
+            break;
+        }
         int nEnd = 0;
         if( nFWidth == 0 )
         {
             const char * pszData2 = poRecord->GetData();
-
+            if( iOffset + 2 >= poRecord->GetLength() )
+            {
+                bError = true;
+                break;
+            }
             for( nEnd = iOffset + 2;
                  pszData2[nEnd] != '\\' && pszData2[nEnd] != '\0';
                  nEnd++ ) {}
@@ -918,14 +949,27 @@ int NTFFileReader::ProcessAttRec( NTFRecord * poRecord,
         if( nFWidth == 0 )
         {
             iOffset = nEnd;
+            if( iOffset >= poRecord->GetLength() )
+            {
+                bError = true;
+                break;
+            }
             if( pszData[iOffset] == '\\' )
                 iOffset++;
         }
         else
-            iOffset += 2 + atoi(psAttDesc->fwidth);
+            iOffset += 2 + nFWidth;
     }
 
-    return TRUE;
+    if( bError )
+    {
+        CSLDestroy(*ppapszTypes);
+        CSLDestroy(*ppapszValues);
+        *ppapszTypes = NULL;
+        *ppapszValues = NULL;
+    }
+
+    return( *ppapszTypes != NULL );
 }
 
 /************************************************************************/
@@ -954,13 +998,16 @@ NTFAttDesc * NTFFileReader::GetAttDesc( const char * pszType )
 /*      the long user name.  The value will be transformed from         */
 /*      fixed point (with the decimal implicit) to fixed point with     */
 /*      an explicit decimal point if it has a "R" format.               */
+/*      Note: the returned *ppszAttValue has a very short lifetime      */
+/*      and should immediately be used. Further calls to                */
+/*      ProcessAttValue or CPLSPrintf() will invalidate it.             */
 /************************************************************************/
 
 int NTFFileReader::ProcessAttValue( const char *pszValType,
                                     const char *pszRawValue,
-                                    char **ppszAttName,
-                                    char **ppszAttValue,
-                                    char **ppszCodeDesc )
+                                    const char **ppszAttName,
+                                    const char **ppszAttValue,
+                                    const char **ppszCodeDesc )
 
 {
 /* -------------------------------------------------------------------- */
@@ -985,18 +1032,28 @@ int NTFFileReader::ProcessAttValue( const char *pszValType,
         for( pszDecimalPortion = psAttDesc->finter;
              *pszDecimalPortion != ',' && *pszDecimalPortion != '\0';
              pszDecimalPortion++ ) {}
+        if( *pszDecimalPortion == '\0' )
+        {
+            *ppszAttValue = "";
+        }
+        else
+        {
+            const int nWidth = static_cast<int>(strlen(pszRawValue));
+            const int nPrecision = atoi(pszDecimalPortion+1);
+            if( nPrecision < 0 || nPrecision >= nWidth )
+            {
+                *ppszAttValue = "";
+            }
+            else
+            {
+                CPLString osResult(pszRawValue);
+                osResult.resize(nWidth - nPrecision);
+                osResult += ".";
+                osResult += pszRawValue+nWidth-nPrecision;
 
-        const int nWidth = static_cast<int>(strlen(pszRawValue));
-        const int nPrecision = atoi(pszDecimalPortion+1);
-
-        // TODO(schwehr): Why static?
-        static char szRealString[30] = {};
-        strncpy( szRealString, pszRawValue, nWidth - nPrecision );
-        szRealString[nWidth-nPrecision] = '.';
-        strcpy( szRealString+nWidth-nPrecision+1,
-                pszRawValue+nWidth-nPrecision );
-
-        *ppszAttValue = szRealString;
+                *ppszAttValue = CPLSPrintf("%s", osResult.c_str());
+            }
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -1005,12 +1062,7 @@ int NTFFileReader::ProcessAttValue( const char *pszValType,
 /* -------------------------------------------------------------------- */
     else if( psAttDesc->finter[0] == 'I' )
     {
-        // TODO(schwehr): Why static?
-        static char szIntString[30]; // FIXME thread unsafe
-
-        snprintf( szIntString, sizeof(szIntString), "%d", atoi(pszRawValue) );
-
-        *ppszAttValue = szIntString;
+        *ppszAttValue = CPLSPrintf("%d", atoi(pszRawValue) );
     }
 
 /* -------------------------------------------------------------------- */
@@ -1018,7 +1070,7 @@ int NTFFileReader::ProcessAttValue( const char *pszValType,
 /* -------------------------------------------------------------------- */
     else
     {
-        *ppszAttValue = (char *) pszRawValue;
+        *ppszAttValue = pszRawValue;
     }
 
 /* -------------------------------------------------------------------- */
@@ -1030,7 +1082,7 @@ int NTFFileReader::ProcessAttValue( const char *pszValType,
     }
     else if( psAttDesc->poCodeList != NULL )
     {
-        *ppszCodeDesc = (char *)psAttDesc->poCodeList->Lookup( *ppszAttValue );
+        *ppszCodeDesc = psAttDesc->poCodeList->Lookup( *ppszAttValue );
     }
     else
     {
@@ -1112,9 +1164,9 @@ int NTFFileReader::ApplyAttributeValue( OGRFeature * poFeature, int iField,
 /*      Process the attribute value ... this really only has a          */
 /*      useful effect for real numbers.                                 */
 /* -------------------------------------------------------------------- */
-    char *pszAttLongName = NULL;
-    char *pszAttValue = NULL;
-    char *pszCodeDesc = NULL;
+    const char *pszAttLongName = NULL;
+    const char *pszAttValue = NULL;
+    const char *pszCodeDesc = NULL;
 
     if( !ProcessAttValue( pszAttName, papszValues[iValue],
                           &pszAttLongName, &pszAttValue, &pszCodeDesc ) )
@@ -1365,7 +1417,6 @@ NTFRecord **NTFFileReader::ReadRecordGroup()
    NTFRecord *poRecord = NULL;
    while( (poRecord = ReadRecord()) != NULL && poRecord->GetType() != NRT_VTR )
    {
-       CPLAssert( nRecordCount < MAX_REC_GROUP);
        if( nRecordCount >= MAX_REC_GROUP )
        {
            CPLError( CE_Failure, CPLE_AppDefined,
@@ -1505,8 +1556,10 @@ OGRFeature * NTFFileReader::ReadOGRFeature( OGRNTFLayer * poTargetLayer )
 /* -------------------------------------------------------------------- */
     else
     {
-        CPLAssert( nFeatureCount == -1
-                   || nFeatureCount == nSavedFeatureId - nBaseFeatureId );
+        // This assertion was triggered by https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1982
+        // it doesn't look critical enough to be enabled.
+        //CPLAssert( nFeatureCount == -1
+        //           || nFeatureCount == nSavedFeatureId - nBaseFeatureId );
         nFeatureCount = nSavedFeatureId - nBaseFeatureId;
     }
 
@@ -1581,6 +1634,14 @@ void NTFFileReader::IndexFile()
             delete poRecord;
             continue;
         }
+        if( iId < 0 )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Illegal id %d record, skipping.",
+                      iId );
+            delete poRecord;
+            continue;
+        }
 
 /* -------------------------------------------------------------------- */
 /*      Grow type specific subindex if needed.                          */
@@ -1666,14 +1727,29 @@ NTFRecord * NTFFileReader::GetIndexedRecord( int iType, int iId )
 /*                          AddToIndexGroup()                           */
 /************************************************************************/
 
-static void AddToIndexGroup( NTFRecord **papoGroup, NTFRecord * poRecord )
+void NTFFileReader::AddToIndexGroup( NTFRecord * poRecord )
 
 {
     int i = 1;  // Used after for.
-    for( ; papoGroup[i] != NULL; i++ ) {}
+    for( ; apoCGroup[i] != NULL; i++ )
+    {
+        if( apoCGroup[i] == poRecord )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                    "Record already inserted in group");
+            return;
+        }
+    }
+    if( i == MAX_REC_GROUP )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Maximum number of records in group reached");
+        delete poRecord;
+        return;
+    }
 
-    papoGroup[i] = poRecord;
-    papoGroup[i+1] = NULL;
+    apoCGroup[i] = poRecord;
+    apoCGroup[i+1] = NULL;
 }
 
 /************************************************************************/
@@ -1699,6 +1775,8 @@ NTFRecord **NTFFileReader::GetNextIndexedRecordGroup( NTFRecord **
     {
         nPrevType = papoPrevGroup[0]->GetType();
         nPrevId = atoi(papoPrevGroup[0]->GetField(3,8));
+        if( nPrevId < 0 )
+            return NULL;
     }
 
 /* -------------------------------------------------------------------- */
@@ -1754,8 +1832,7 @@ NTFRecord **NTFFileReader::GetNextIndexedRecordGroup( NTFRecord **
     {
         int             l_nAttCount = 0;
 
-        AddToIndexGroup( apoCGroup,
-                         GetIndexedRecord( NRT_GEOMETRY,
+        AddToIndexGroup( GetIndexedRecord( NRT_GEOMETRY,
                                            atoi(poAnchor->GetField(9,14)) ) );
 
         if( poAnchor->GetLength() >= 16 )
@@ -1764,7 +1841,6 @@ NTFRecord **NTFFileReader::GetNextIndexedRecordGroup( NTFRecord **
         for( int iAtt = 0; iAtt < l_nAttCount; iAtt++ )
         {
             AddToIndexGroup(
-                apoCGroup,
                 GetIndexedRecord( NRT_ATTREC,
                                   atoi(poAnchor->GetField(17+6*iAtt,
                                                           22+6*iAtt)) ) );
@@ -1781,13 +1857,14 @@ NTFRecord **NTFFileReader::GetNextIndexedRecordGroup( NTFRecord **
 
         // Add all the text position records.
         nSelCount = atoi(poAnchor->GetField(9,10));
+        if( nSelCount < 0 )
+            return NULL;
 
         for( int iSel = 0; iSel < nSelCount; iSel++ )
         {
             int iStart = 11 + 12*iSel + 6;
 
             AddToIndexGroup(
-                apoCGroup,
                 GetIndexedRecord( NRT_TEXTPOS,
                                   atoi(poAnchor->GetField(iStart,iStart+5)) ));
         }
@@ -1805,12 +1882,10 @@ NTFRecord **NTFFileReader::GetNextIndexedRecordGroup( NTFRecord **
             for( int iTEXR = 0; iTEXR < nNumTEXR; iTEXR++ )
             {
                 AddToIndexGroup(
-                    apoCGroup,
                     GetIndexedRecord( NRT_TEXTREP,
                                       atoi(poRecord->GetField(11+iTEXR*12,
                                                               16+iTEXR*12))));
                 AddToIndexGroup(
-                    apoCGroup,
                     GetIndexedRecord( NRT_GEOMETRY,
                                       atoi(poRecord->GetField(17+iTEXR*12,
                                                               22+iTEXR*12))));
@@ -1827,7 +1902,6 @@ NTFRecord **NTFFileReader::GetNextIndexedRecordGroup( NTFRecord **
             int iStart = 13 + nSelCount*12 + 6 * iAtt;
 
             AddToIndexGroup(
-                apoCGroup,
                 GetIndexedRecord( NRT_ATTREC,
                                   atoi(poAnchor->GetField(iStart,iStart+5)) ));
         }
@@ -1838,8 +1912,7 @@ NTFRecord **NTFFileReader::GetNextIndexedRecordGroup( NTFRecord **
 /* -------------------------------------------------------------------- */
     else if( poAnchor->GetType() == NRT_NODEREC )
     {
-        AddToIndexGroup( apoCGroup,
-                         GetIndexedRecord( NRT_GEOMETRY,
+        AddToIndexGroup( GetIndexedRecord( NRT_GEOMETRY,
                                            atoi(poAnchor->GetField(9,14)) ) );
     }
 
@@ -1849,6 +1922,8 @@ NTFRecord **NTFFileReader::GetNextIndexedRecordGroup( NTFRecord **
     else if( poAnchor->GetType() == NRT_COLLECT )
     {
         const int nParts = atoi(poAnchor->GetField(9,12));
+        if( nParts < 0 )
+            return NULL;
         const int nAttOffset = 13 + nParts * 8;
         int l_nAttCount = 0;
 
@@ -1860,7 +1935,6 @@ NTFRecord **NTFFileReader::GetNextIndexedRecordGroup( NTFRecord **
             const int iStart = nAttOffset + 2 + iAtt * 6;
 
             AddToIndexGroup(
-                apoCGroup,
                 GetIndexedRecord( NRT_ATTREC,
                                   atoi(poAnchor->GetField(iStart,iStart+5)) ));
         }
@@ -1871,12 +1945,11 @@ NTFRecord **NTFFileReader::GetNextIndexedRecordGroup( NTFRecord **
 /* -------------------------------------------------------------------- */
     else if( poAnchor->GetType() == NRT_POLYGON )
     {
-        AddToIndexGroup( apoCGroup,
-                         GetIndexedRecord( NRT_CHAIN,
+        AddToIndexGroup( GetIndexedRecord( NRT_CHAIN,
                                            atoi(poAnchor->GetField(9,14)) ) );
 
         if( poAnchor->GetLength() >= 20 )
-            AddToIndexGroup( apoCGroup,
+            AddToIndexGroup(
                         GetIndexedRecord( NRT_GEOMETRY,
                                           atoi(poAnchor->GetField(15,20)) ) );
 
@@ -1889,7 +1962,6 @@ NTFRecord **NTFFileReader::GetNextIndexedRecordGroup( NTFRecord **
         for( int iAtt = 0; iAtt < l_nAttCount; iAtt++ )
         {
             AddToIndexGroup(
-                apoCGroup,
                 GetIndexedRecord( NRT_ATTREC,
                                   atoi(poAnchor->GetField(23+6*iAtt,
                                                           28+6*iAtt)) ) );
@@ -1901,14 +1973,15 @@ NTFRecord **NTFFileReader::GetNextIndexedRecordGroup( NTFRecord **
     else if( poAnchor->GetType() == NRT_CPOLY )
     {
         int nPolyCount = atoi(poAnchor->GetField(9,12));
+        if( nPolyCount < 0 )
+            return NULL;
         int nPostPoly = nPolyCount*7 + 12;
 
         if( poAnchor->GetLength() >= nPostPoly + 6 )
         {
             int  nGeomId = atoi(poAnchor->GetField(nPostPoly+1,nPostPoly+6));
 
-            AddToIndexGroup( apoCGroup,
-                             GetIndexedRecord( NRT_GEOMETRY, nGeomId) );
+            AddToIndexGroup( GetIndexedRecord( NRT_GEOMETRY, nGeomId) );
         }
 
         if( poAnchor->GetLength() >= nPostPoly + 8 )
@@ -1919,8 +1992,7 @@ NTFRecord **NTFFileReader::GetNextIndexedRecordGroup( NTFRecord **
             {
                 int nAttId = atoi(poAnchor->GetField(nPostPoly+9+iAtt*6,
                                                      nPostPoly+14+iAtt*6));
-                AddToIndexGroup( apoCGroup,
-                                 GetIndexedRecord( NRT_ATTREC, nAttId) );
+                AddToIndexGroup( GetIndexedRecord( NRT_ATTREC, nAttId) );
             }
         }
     }
diff --git a/ogr/ogrsf_frmts/ntf/ogrntfdatasource.cpp b/ogr/ogrsf_frmts/ntf/ogrntfdatasource.cpp
index 9bf64ea..02a0aef 100644
--- a/ogr/ogrsf_frmts/ntf/ogrntfdatasource.cpp
+++ b/ogr/ogrsf_frmts/ntf/ogrntfdatasource.cpp
@@ -30,7 +30,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrntfdatasource.cpp 36677 2016-12-04 13:42:55Z rouault $");
+CPL_CVSID("$Id: ogrntfdatasource.cpp 38675 2017-05-29 11:02:44Z rouault $");
 
 /************************************************************************/
 /*                          OGRNTFDataSource()                          */
@@ -293,7 +293,7 @@ int OGRNTFDataSource::Open( const char * pszFilename, int bTestOpen,
                     break;
             }
 
-            if( j == 80 || szHeader[j-1] != '%' )
+            if( j == 80 || (j > 0 && szHeader[j-1] != '%') )
                 continue;
         }
 
@@ -537,9 +537,12 @@ void OGRNTFDataSource::EnsureTileNameUnique( NTFFileReader *poNewReader )
 
         for( int iReader = 0; iReader < nNTFFileCount && bIsUnique; iReader++ )
         {
-            if( strcmp( szCandidateName,
-                        GetFileReader( iReader )->GetTileName() ) == 0 )
+            const char* pszTileName = GetFileReader( iReader )->GetTileName();
+            if( pszTileName != NULL &&
+                strcmp( szCandidateName, pszTileName ) == 0 )
+            {
                 bIsUnique = FALSE;
+            }
         }
     } while( !bIsUnique );
 
diff --git a/ogr/ogrsf_frmts/openair/ogropenairdriver.cpp b/ogr/ogrsf_frmts/openair/ogropenairdriver.cpp
index f653322..dd242e0 100644
--- a/ogr/ogrsf_frmts/openair/ogropenairdriver.cpp
+++ b/ogr/ogrsf_frmts/openair/ogropenairdriver.cpp
@@ -30,7 +30,7 @@
 #include "ogr_openair.h"
 #include "ogrsf_frmts.h"
 
-CPL_CVSID("$Id: ogropenairdriver.cpp 34819 2016-07-28 22:32:18Z goatbar $");
+CPL_CVSID("$Id: ogropenairdriver.cpp 38286 2017-05-14 00:10:56Z rouault $");
 
 /************************************************************************/
 /*                                Open()                                */
@@ -82,6 +82,7 @@ static GDALDataset *OGROpenAirDriverOpen( GDALOpenInfo* poOpenInfo )
             return NULL;
         if( !poOpenInfo->TryToIngest(30000) )
             return NULL;
+        pabyHeader = reinterpret_cast<char *>(poOpenInfo->pabyHeader);
         bIsOpenAir =
             strstr(pabyHeader, "\nAC ") != NULL &&
             strstr(pabyHeader, "\nAN ") != NULL &&
diff --git a/ogr/ogrsf_frmts/pds/ogrpdsdatasource.cpp b/ogr/ogrsf_frmts/pds/ogrpdsdatasource.cpp
index a292cf1..ee270fd 100644
--- a/ogr/ogrsf_frmts/pds/ogrpdsdatasource.cpp
+++ b/ogr/ogrsf_frmts/pds/ogrpdsdatasource.cpp
@@ -30,7 +30,7 @@
 #include "cpl_string.h"
 #include "ogr_pds.h"
 
-CPL_CVSID("$Id: ogrpdsdatasource.cpp 36682 2016-12-04 20:34:45Z rouault $");
+CPL_CVSID("$Id: ogrpdsdatasource.cpp 38382 2017-05-15 11:30:15Z rouault $");
 
 using namespace OGRPDS;
 
@@ -183,8 +183,22 @@ bool OGRPDSDataSource::LoadTable( const char* pszFilename,
             osTableFilename[0] <= '9')
         {
             nStartBytes = atoi(osTableFilename.c_str()) - 1;
+            if( nStartBytes < 0)
+            {
+                CPLError(CE_Failure, CPLE_NotSupported,
+                        "Cannot parse %s line", osTableFilename.c_str());
+                return false;
+            }
             if (strstr(osTableFilename.c_str(), "<BYTES>") == NULL)
+            {
+                if( nRecordSize > 0 && nStartBytes > INT_MAX / nRecordSize )
+                {
+                    CPLError(CE_Failure, CPLE_NotSupported,
+                             "Too big StartBytes value");
+                    return false;
+                }
                 nStartBytes *= nRecordSize;
+            }
             osTableFilename = pszFilename;
         }
         else
diff --git a/ogr/ogrsf_frmts/pg/ogrpgdatasource.cpp b/ogr/ogrsf_frmts/pg/ogrpgdatasource.cpp
index 161b456..639ed15 100644
--- a/ogr/ogrsf_frmts/pg/ogrpgdatasource.cpp
+++ b/ogr/ogrsf_frmts/pg/ogrpgdatasource.cpp
@@ -36,7 +36,7 @@
 
 #define PQexec this_is_an_error
 
-CPL_CVSID("$Id: ogrpgdatasource.cpp 36981 2016-12-20 19:46:41Z rouault $");
+CPL_CVSID("$Id: ogrpgdatasource.cpp 38594 2017-05-22 09:53:07Z rouault $");
 
 static void OGRPGNoticeProcessor( void *arg, const char * pszMessage );
 
@@ -710,7 +710,7 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
 /*      so we will get the value of the gist indexes.                   */
 /* -------------------------------------------------------------------- */
     hResult = OGRPG_PQexec(hPGConn,
-                        "SELECT oid, typname FROM pg_type WHERE typname IN ('geometry', 'geography')" );
+                        "SELECT oid, typname FROM pg_type WHERE typname IN ('geometry', 'geography') AND typtype='b'" );
 
     if( hResult && PQresultStatus(hResult) == PGRES_TUPLES_OK
         && PQntuples(hResult) > 0  && CPLTestBool(CPLGetConfigOption("PG_USE_POSTGIS", "YES")))
diff --git a/ogr/ogrsf_frmts/plscenes/GNUmakefile b/ogr/ogrsf_frmts/plscenes/GNUmakefile
index b5923b5..cd1f6c5 100644
--- a/ogr/ogrsf_frmts/plscenes/GNUmakefile
+++ b/ogr/ogrsf_frmts/plscenes/GNUmakefile
@@ -2,7 +2,7 @@
 
 include ../../../GDALmake.opt
 
-OBJ	=	ogrplscenesdriver.o ogrplscenesdataset.o ogrplscenesv1dataset.o ogrplsceneslayer.o ogrplscenesv1layer.o \
+OBJ	=	ogrplscenesdriver.o ogrplscenesv1dataset.o ogrplscenesv1layer.o \
 		ogrplscenesdatav1layer.o ogrplscenesdatav1dataset.o
 
 CPPFLAGS	:=	$(JSON_INCLUDE) -I.. -I../.. -I../geojson  $(CPPFLAGS)
diff --git a/ogr/ogrsf_frmts/plscenes/drv_plscenes.html b/ogr/ogrsf_frmts/plscenes/drv_plscenes.html
index 13f3cb4..59e34e0 100644
--- a/ogr/ogrsf_frmts/plscenes/drv_plscenes.html
+++ b/ogr/ogrsf_frmts/plscenes/drv_plscenes.html
@@ -7,23 +7,21 @@
 
 <h1>PLScenes (Planet Labs Scenes/Catalog API)</h1>
 
-(GDAL/OGR >= 2.0 for V0 API,  GDAL/OGR >= 2.1 for V1 API,  GDAL/OGR >= 2.2 for Data V1 API)<p>
+(GDAL/OGR >= 2.2 for Data V1 API)<p>
 
-This driver can connect to Planet Labs Scenes v0/Catalog v1/Data V1 API.
+This driver can connect to Planet Labs Data V1 API.
 GDAL/OGR must be built with Curl support in order for the
 PLScenes driver to be compiled.<p>
 
 Please consult the dedicated pages for each version of the API:
 <ul>
-<li><a href="drv_plscenes_v0.html">V0 API</a> (deprecated)</li>
-<li><a href="drv_plscenes_v1.html">V1 API</a> (deprecated)</li>
+<li><a href="drv_plscenes_v1.html">V1 API</a> (deprecated, will be removed in the future)</li>
 <li><a href="drv_plscenes_data_v1.html">Data V1 API</a> (current)</li>
 </ul>
 
 <h2>See Also</h2>
 
 <ul>
-<li> <a href="https://www.planet.com/docs/reference/v0/">Documentation of Planet Scenes API V0</a><p>
 <li> <a href="https://www.planet.com/docs/reference/data-api/">Documentation of Planet Scenes Data API V1</a><p>
 <li> <a href="frmt_plmosaic.html">Raster PLMosaic / Planet Mosaics API driver</a><p>
 </ul>
diff --git a/ogr/ogrsf_frmts/plscenes/drv_plscenes_v0.html b/ogr/ogrsf_frmts/plscenes/drv_plscenes_v0.html
deleted file mode 100644
index 2e9b9dd..0000000
--- a/ogr/ogrsf_frmts/plscenes/drv_plscenes_v0.html
+++ /dev/null
@@ -1,202 +0,0 @@
-<html>
-<head>
-<title>PLScenes (Planet Labs Scenes/Catalog API), V0 API</title>
-</head>
-
-<body bgcolor="#ffffff">
-
-<h1>PLScenes (Planet Labs Scenes/Catalog API), V0 API</h1>
-
-GDAL/OGR >= 2.0<p>
-
-Note: this version of the API is deprecated. Please migrate to the
-<a href="drv_plscenes_data_v1.html">Data V1 API</a>.<p>
-
-The driver supports read-only operations to list scenes and their metadata
-as a vector layer per scene type, "ortho" for example.
-It can also access raster scenes.<p>
-
-<h2>Dataset name syntax</h2>
-
-The minimal syntax to open a datasource is : <pre>PLScenes:[options]</pre><p>
-
-Additional optional parameters can be specified after the ':' sign.
-Currently the following one is supported :<p>
-
-<ul>
-<li> <b>version</b>=v0: To specify the API version to request. Defaults to data_v1 starting with GDAL 2.2 (v0 for older versions).</li>
-<li> <b>api_key</b>=value: To specify the Planet API KEY. It is mandatory, unless
-it is supplied through the open option API_KEY, or the configuration option PL_API_KEY.</li>
-<li> <b>scene</b>=scene_id: To specify the scene ID, when accessing raster data.
-Optional for vector layer access.</li>
-<li> <b>catalog</b>=name: To specify the item types name.
-Optional for vector layer access.</li>
-<li> <b>product_type</b>=value: To specify the asset type
-(for raster fetching). Default is "visual". Optional for vector layer access.</li>
-</ul>
-
-If several parameters are specified, they must be separated by a comma.<p>
-
-<h2>Open options</h2>
-
-The following open options are available :
-<ul>
-<li><b>VERSION</b>=v0: To specify the API version to request. Defaults to data_v1 starting with GDAL 2.2 (v0 for older versions).</li>
-<li><b>API_KEY</b>=value: To specify the Planet API KEY.</li>
-<li><b>SCENE</b>=scene_id: To specify the scene ID, when accessing raster data.
-Optional for vector layer access.</li>
-<li><b>CATALOG</b>=name: To specify the item types name.
-Optional for vector layer access.</li>
-<li><b>PRODUCT_TYPE</b>=value: To specify the asset type
-(for raster fetching). Default is "visual". Optional for vector layer access.</li>
-<li><b>RANDOM_ACCESS</b>=YES/NO: Whether raster should be accessed in random access mode
-(but with potentially not optimal throughput). If NO, in-memory ingestion is done.
-Default is YES.</li>
-</ul>
-
-<h2>Configuration options</h2>
-
-The following configuration options are available :
-<ul>
-<li><b>PL_API_KEY</b>=value: To specify the Planet API KEY.</li>
-</ul>
-
-<h2>Attributes</h2>
-
-The <a href="https://www.planet.com/docs/v0/scenes/#metadata">scene metadata</a>
-are retrieved into the following feature fields for the "ortho" layer :<p>
-
-<table border="1">
-<tr><th>Name</th><th>Type</th><th>Description</th></tr>
-
-<tr><td>id</td><td>String</td><td>Scene unique identifier.</td></tr>
-<tr><td>acquired</td><td>DateTime</td><td>The time that image was taken in UTC.</td></tr>
-<tr><td>camera.bit_depth</td><td>Integer</td><td>Bit depth with which the image was taken onboard the satellite. Currently 8 or 12.</td></tr>
-<tr><td>camera.color_mode</td><td>String</td><td>The color mode of the image as taken by the satellite. Currently "RGB" or "Monochromatic".</td></tr>
-<tr><td>camera.exposure_time</td><td>Integer</td><td>The exposure time in microseconds.</td></tr>
-<tr><td>camera.gain</td><td>Integer</td><td>The analog gain with which the image was taken.</td></tr>
-<tr><td>camera.tdi_pulses</td><td>Integer</td><td>The number of pulses used for time delay and integration on the CCD. Currently 0 (if TDI was not used), 4, 6, or 12.</td></tr>
-<tr><td>cloud_cover.estimated</td><td>Real</td><td>The estimated percentage of the image covered by clouds. Decimal 0-100.</td></tr>
-<tr><td>data.products.analytic.full</td><td>String</td><td>URL to download scene GeoTIFF of the "analytic" product.</td></tr>
-<tr><td>data.products.visual.full</td><td>String</td><td>URL to download scene GeoTIFF of the "visual" product.</td></tr>
-<tr><td>file_size</td><td>Integer</td><td>The size of the full image in bytes.</td></tr>
-<tr><td>image_statistics.gsd</td><td>Real</td><td>The ground sample distance (distance between pixel centers measured on the ground) of the image in meters.</td></tr>
-<tr><td>image_statistics.image_quality</td><td>String</td><td>Image quality category for scene. One of 'test', 'standard', or 'target'.</td></tr>
-<tr><td>image_statistics.snr</td><td>Real</td><td>The estimated signal to noise ratio. Decimal > 0. Values greater than or equal to 50 are considered excellent quality. Values less than 50 and greater than or equal to 20 are considered adequate quality. Values less than 20 are considered poor quality.</td></tr>
-<tr><td>links.full</td><td>String</td><td>URL to download scene GeoTIFF (same content as data.products.visual.full currently)</td></tr>
-<tr><td>links.self</td><td>String</td><td>URL to scene information</td></tr>
-<tr><td>links.square_thumbnail</td><td>String</td><td>URL to image thumbnail</td></tr>
-<tr><td>links.thumbnail</td><td>String</td><td>Link to image square thumbnail</td></tr>
-<tr><td>sat.alt</td><td>Real</td><td>The altitude of the satellite when the image was taken in kilometers.</td></tr>
-<tr><td>sat.id</td><td>String</td><td>A unique identifier for the satellite that captured this image.</td></tr>
-<tr><td>sat.lat</td><td>Real</td><td>The latitude of the satellite when the image was taken in degrees.</td></tr>
-<tr><td>sat.lng</td><td>Real</td><td>The longitude of the satellite when the image was taken in degrees.</td></tr>
-<tr><td>sat.off_nadir</td><td>Real</td><td>The angle off nadir in degrees at which the image was taken.</td></tr>
-<tr><td>strip_id</td><td>Real</td><td>A unique float identifier for the set of images taken sequentially be the same satellite.</td></tr>
-<tr><td>sun.altitude</td><td>Real</td><td>The altitude (angle above horizon) of the sun from the imaged location at the time of capture in degrees.</td></tr>
-<tr><td>sun.azimuth</td><td>Real</td><td>The azimuth (angle clockwise from north) of the sun from the imaged location at the time of capture in degrees.</td></tr>
-<tr><td>sun.local_time_of_day</td><td>Real</td><td>The local sun time at the imaged location at the time of capture (0-24).</td></tr>
-</table>
-
-For other layers / scene types, additional attributes may be retrieved.<p>
-
-<h3>Geometry</h3>
-
-The footprint of each scene is reported as a MultiPolygon with a longitude/latitude
-WGS84 coordinate system (EPSG:4326).
-
-<h3>Filtering</h3>
-
-The driver will forward any spatial filter set with SetSpatialFilter() to
-the server. It also makes the same for simple attribute filters set with
-SetAttributeFilter(). Note that not all attributes support all comparison
-operators. Refer to comparator column in <a href="https://www.planet.com/docs/v0/scenes/#metadata">Metadata properties</a> <p>
-
-<h3>Paging</h3>
-
-Features are retrieved from the server by chunks of 1000 by default (and this
-is the maximum value accepted by the server).
-This number can be altered with the PLSCENES_PAGE_SIZE
-configuration option.<p>
-
-<h3>Vector layer (scene metadata) examples</h3>
-
-<li>
-Listing all scenes available (with the rights of the account) :
-<pre>
-ogrinfo -ro -al "PLScenes:" -oo API_KEY=some_value
-</pre>
-or
-<pre>
-ogrinfo -ro -al "PLScenes:api_key=some_value"
-</pre>
-or
-<pre>
-ogrinfo -ro -al "PLScenes:" --config PL_API_KEY some_value
-</pre>
-<p>
-
-<li>
-Listing all scenes available under a point of (lat,lon)=(40,-100) :
-<pre>
-ogrinfo -ro -al "PLScenes:" -oo API_KEY=some_value -spat -100,40,-100,40
-</pre>
-<p>
-
-<li>
-Listing all scenes available within a bounding box (lat,lon)=(40,-100) to (lat,lon)=(39,-99)
-<pre>
-ogrinfo -ro -al "PLScenes:" -oo API_KEY=some_value -spat -100,40,-99,39
-</pre>
-<p>
-
-<li>
-Listing all scenes available matching criteria :
-<pre>
-ogrinfo -ro -al "PLScenes:" -oo API_KEY=some_value -where "acquired >= '2015/03/26 00:00:00' AND \"cloud_cover.estimated\" < 10"
-</pre>
-<p>
-
-<h2>Raster access</h2>
-
-<p>Scenes and their thumbnails can be accessed as raster datasets, provided
-that the scene ID is specified with the 'scene' parameter / SCENE open option.
-The product type (visual, analytic or thumb) can be specified with the
-'product_type' parameter / PRODUCT_TYPE open option. The scene id is the
-content of the value of the 'id' field of the features of the 'ortho' vector layer.</p>
-
-<p>This functionality is a convenience wrapper of the
-<a href="https://www.planet.com/docs/reference/v0/scenes/#api-endpoints">API for fetching the scene GeoTIFF</a>
-</p>
-
-<h3>Raster access examples</h3>
-
-<li>
-Displaying raster metadata :
-
-<pre>
-gdalinfo "PLScenes:scene=scene_id,product_type=analytic" -oo API_KEY=some_value
-</pre>
-or
-<pre>
-gdalinfo "PLScenes:" -oo API_KEY=some_value -oo SCENE=scene_id -oo PRODUCT_TYPE=analytic
-</pre>
-
-<li>
-Converting/downloading a whole file:
-
-<pre>
-gdal_translate "PLScenes:" -oo API_KEY=some_value -oo SCENE=scene_id \
-                -oo PRODUCT_TYPE=analytic -oo RANDOM_ACCESS=NO out.tif
-</pre>
-
-<h2>See Also</h2>
-
-<ul>
-<li> <a href="drv_plscenes.html">General documentation page for PLScenes driver</a><p>
-<li> <a href="https://www.planet.com/docs/reference/v0/">Documentation of Planet Scenes API v0</a><p>
-<li> <a href="frmt_plmosaic.html">Raster PLMosaic / Planet Mosaics API driver</a><p>
-</ul>
-
-</body>
-</html>
diff --git a/ogr/ogrsf_frmts/plscenes/makefile.vc b/ogr/ogrsf_frmts/plscenes/makefile.vc
index 03c40e0..63e8b55 100644
--- a/ogr/ogrsf_frmts/plscenes/makefile.vc
+++ b/ogr/ogrsf_frmts/plscenes/makefile.vc
@@ -1,5 +1,5 @@
 
-OBJ	=	ogrplscenesdriver.obj ogrplscenesdataset.obj ogrplscenesv1dataset.obj ogrplsceneslayer.obj ogrplscenesv1layer.obj \
+OBJ	=	ogrplscenesdriver.obj ogrplscenesv1dataset.obj ogrplscenesv1layer.obj \
 		ogrplscenesdatav1layer.obj ogrplscenesdatav1dataset.obj
 
 EXTRAFLAGS =	-I.. -I..\..  -I..\geojson -I..\geojson\libjson
diff --git a/ogr/ogrsf_frmts/plscenes/ogr_plscenes.h b/ogr/ogrsf_frmts/plscenes/ogr_plscenes.h
index 4fabc7b..df06d6d 100644
--- a/ogr/ogrsf_frmts/plscenes/ogr_plscenes.h
+++ b/ogr/ogrsf_frmts/plscenes/ogr_plscenes.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_plscenes.h 37271 2017-02-02 13:34:26Z rouault $
+ * $Id: ogr_plscenes.h 39215 2017-06-20 19:09:46Z rouault $
  *
  * Project:  PlanetLabs scene driver
  * Purpose:  PLScenes driver interface
@@ -41,102 +41,6 @@
 #include <set>
 #include <vector>
 
-class OGRPLScenesLayer;
-
-class OGRPLScenesDataset: public GDALDataset
-{
-        bool            bMustCleanPersistent;
-        CPLString       osBaseURL;
-        CPLString       osAPIKey;
-
-        int             nLayers;
-        OGRPLScenesLayer  **papoLayers;
-        std::map<OGRLayer*, OGRPLScenesLayer*> oMapResultSetToSourceLayer;
-
-        char             **GetBaseHTTPOptions();
-        GDALDataset       *OpenRasterScene(GDALOpenInfo* poOpenInfo,
-                                           CPLString osScene,
-                                           char** papszOptions);
-
-    public:
-                            OGRPLScenesDataset();
-                           virtual ~OGRPLScenesDataset();
-
-        virtual int         GetLayerCount() override { return nLayers; }
-        virtual OGRLayer   *GetLayer(int idx) override;
-        virtual OGRLayer   *GetLayerByName(const char* pszName) override;
-        virtual OGRLayer   *ExecuteSQL( const char *pszSQLCommand,
-                                        OGRGeometry *poSpatialFilter,
-                                        const char *pszDialect ) override;
-        virtual void        ReleaseResultSet( OGRLayer * poLayer ) override;
-
-        json_object        *RunRequest(const char* pszURL,
-                                       int bQuiet404Error = FALSE);
-
-        static GDALDataset* Open(GDALOpenInfo* poOpenInfo);
-};
-
-class OGRPLScenesLayer: public OGRLayer
-{
-            friend class OGRPLScenesDataset;
-
-            OGRPLScenesDataset* poDS;
-            CPLString       osBaseURL;
-            OGRFeatureDefn* poFeatureDefn;
-            OGRSpatialReference* poSRS;
-            bool            bEOF;
-            GIntBig         nNextFID;
-            GIntBig         nFeatureCount;
-            CPLString       osNextURL;
-            CPLString       osRequestURL;
-            CPLString       osQuery;
-
-            OGRGeoJSONDataSource *poGeoJSONDS;
-            OGRLayer             *poGeoJSONLayer;
-
-            OGRGeometry    *poMainFilter;
-
-            int             nPageSize;
-            bool            bStillInFirstPage;
-            int             bAcquiredAscending;
-
-            bool            bFilterMustBeClientSideEvaluated;
-            CPLString       osFilterURLPart;
-
-            OGRFeature     *GetNextRawFeature();
-            CPLString       BuildURL(int nFeatures);
-            int             GetNextPage();
-            CPLString       BuildFilter(swq_expr_node* poNode);
-
-    public:
-                            OGRPLScenesLayer(OGRPLScenesDataset* poDS,
-                                             const char* pszName,
-                                             const char* pszBaseURL,
-                                             json_object* poObjCount10 = NULL);
-                           virtual ~OGRPLScenesLayer();
-
-        virtual void            ResetReading() override;
-        virtual GIntBig         GetFeatureCount(int bForce = FALSE) override;
-        virtual OGRFeature     *GetNextFeature() override;
-        virtual int             TestCapability(const char*) override;
-        virtual OGRFeatureDefn *GetLayerDefn() override { return poFeatureDefn; }
-
-        virtual void        SetSpatialFilter( OGRGeometry *poGeom ) override;
-        virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override
-                { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
-
-        virtual OGRErr      SetAttributeFilter( const char * ) override;
-
-        virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce ) override;
-        virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
-                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
-
-        void                SetMainFilterRect(double dfMinX, double dfMinY,
-                                              double dfMaxX, double dfMaxY);
-        void                SetAcquiredOrderingFlag(int bAcquiredAscendingIn)
-                                { bAcquiredAscending = bAcquiredAscendingIn; }
-};
-
 class OGRPLScenesV1Layer;
 class OGRPLScenesV1Dataset: public GDALDataset
 {
diff --git a/ogr/ogrsf_frmts/plscenes/ogrplscenesdataset.cpp b/ogr/ogrsf_frmts/plscenes/ogrplscenesdataset.cpp
deleted file mode 100644
index b7309d0..0000000
--- a/ogr/ogrsf_frmts/plscenes/ogrplscenesdataset.cpp
+++ /dev/null
@@ -1,578 +0,0 @@
-/******************************************************************************
- *
- * Project:  PlanetLabs scene driver
- * Purpose:  Implements OGRPLScenesDataset
- * Author:   Even Rouault, even dot rouault at spatialys.com
- *
- ******************************************************************************
- * Copyright (c) 2015, Planet Labs
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "ogr_plscenes.h"
-#include "ogrgeojsonreader.h"
-
-CPL_CVSID("$Id: ogrplscenesdataset.cpp 38115 2017-04-23 07:24:41Z rouault $");
-
-/************************************************************************/
-/*                         OGRPLScenesDataset()                         */
-/************************************************************************/
-
-OGRPLScenesDataset::OGRPLScenesDataset() :
-    bMustCleanPersistent(false),
-    nLayers(0),
-    papoLayers(NULL)
-{}
-
-/************************************************************************/
-/*                         ~OGRPLScenesDataset()                        */
-/************************************************************************/
-
-OGRPLScenesDataset::~OGRPLScenesDataset()
-{
-    for( int i = 0; i < nLayers; i++ )
-        delete papoLayers[i];
-    CPLFree(papoLayers);
-
-    if( bMustCleanPersistent )
-    {
-        char **papszOptions =
-            CSLSetNameValue(NULL, "CLOSE_PERSISTENT",
-                            CPLSPrintf("PLSCENES:%p", this));
-        CPLHTTPDestroyResult(CPLHTTPFetch(osBaseURL, papszOptions));
-        CSLDestroy(papszOptions);
-    }
-}
-
-/************************************************************************/
-/*                              GetLayer()                              */
-/************************************************************************/
-
-OGRLayer *OGRPLScenesDataset::GetLayer( int idx )
-{
-    if( idx < 0 || idx >= nLayers )
-        return NULL;
-    return papoLayers[idx];
-}
-
-/************************************************************************/
-/*                          GetLayerByName()                            */
-/************************************************************************/
-
-OGRLayer *OGRPLScenesDataset::GetLayerByName(const char* pszName)
-{
-    OGRLayer* poLayer = GDALDataset::GetLayerByName(pszName);
-    if( poLayer != NULL )
-        return poLayer;
-
-    CPLString osURL;
-    osURL = osBaseURL;
-    osURL += pszName;
-    osURL += "/";
-    json_object* poObj = RunRequest( (osURL + CPLString("?count=10")).c_str() );
-    if( poObj == NULL )
-        return NULL;
-
-    OGRPLScenesLayer* poPLLayer = new OGRPLScenesLayer(this, pszName, osURL, poObj);
-    papoLayers = (OGRPLScenesLayer**) CPLRealloc(papoLayers,
-                                sizeof(OGRPLScenesLayer*) * (nLayers + 1));
-    papoLayers[nLayers ++] = poPLLayer;
-
-    json_object_put(poObj);
-
-    return poPLLayer;
-}
-
-/***********************************************************************/
-/*                            ExecuteSQL()                             */
-/***********************************************************************/
-
-OGRLayer* OGRPLScenesDataset::ExecuteSQL( const char *pszSQLCommand,
-                                          OGRGeometry *poSpatialFilter,
-                                          const char *pszDialect )
-{
-    if( STARTS_WITH_CI(pszSQLCommand, "SELECT ") )
-    {
-        swq_select oSelect;
-        CPLString osSQLCommand(pszSQLCommand);
-        size_t nLimitPos = osSQLCommand.ifind(" limit ");
-        if( nLimitPos != std::string::npos )
-            osSQLCommand.resize(nLimitPos);
-
-        CPLPushErrorHandler(CPLQuietErrorHandler);
-        CPLErr eErr = oSelect.preparse(osSQLCommand);
-        CPLPopErrorHandler();
-        if( eErr != CE_None )
-            return GDALDataset::ExecuteSQL(pszSQLCommand, poSpatialFilter, pszDialect);
-
-/* -------------------------------------------------------------------- */
-/*      ORDER BY optimization on acquired field                         */
-/* -------------------------------------------------------------------- */
-        if( oSelect.join_count == 0 && oSelect.poOtherSelect == NULL &&
-            oSelect.table_count == 1 && oSelect.order_specs == 1 &&
-            strcmp(oSelect.order_defs[0].field_name, "acquired") == 0 )
-        {
-            OGRPLScenesLayer* poLayer = NULL;
-            for( int idx = 0; idx < nLayers; idx++ )
-            {
-                if( strcmp( papoLayers[idx]->GetName(),
-                            oSelect.table_defs[0].table_name) == 0 )
-                {
-                    poLayer = papoLayers[idx];
-                    break;
-                }
-            }
-            if( poLayer != NULL )
-            {
-                poLayer->SetAcquiredOrderingFlag(
-                                        oSelect.order_defs[0].ascending_flag);
-                OGRLayer* poRet = GDALDataset::ExecuteSQL(pszSQLCommand, poSpatialFilter, pszDialect);
-                if( poRet )
-                    oMapResultSetToSourceLayer[poRet] = poLayer;
-                return poRet;
-            }
-        }
-    }
-    return GDALDataset::ExecuteSQL(pszSQLCommand, poSpatialFilter, pszDialect);
-}
-
-/***********************************************************************/
-/*                           ReleaseResultSet()                        */
-/***********************************************************************/
-
-void OGRPLScenesDataset::ReleaseResultSet( OGRLayer * poResultsSet )
-{
-    if( poResultsSet )
-    {
-        OGRPLScenesLayer* poSrcLayer = oMapResultSetToSourceLayer[poResultsSet];
-        // Reset the acquired ordering to its default
-        if( poSrcLayer )
-        {
-            poSrcLayer->SetAcquiredOrderingFlag(-1);
-            oMapResultSetToSourceLayer.erase(poResultsSet);
-        }
-        delete poResultsSet;
-    }
-}
-
-/************************************************************************/
-/*                          GetBaseHTTPOptions()                         */
-/************************************************************************/
-
-char** OGRPLScenesDataset::GetBaseHTTPOptions()
-{
-    bMustCleanPersistent = true;
-
-    char** papszOptions = NULL;
-    papszOptions =
-        CSLAddString(papszOptions, CPLSPrintf("PERSISTENT=PLSCENES:%p", this));
-    papszOptions =
-        CSLAddString(papszOptions,
-                     CPLSPrintf("HEADERS=Authorization: api-key %s",
-                                osAPIKey.c_str()));
-    return papszOptions;
-}
-
-/************************************************************************/
-/*                               RunRequest()                           */
-/************************************************************************/
-
-json_object* OGRPLScenesDataset::RunRequest(const char* pszURL,
-                                            int bQuiet404Error)
-{
-    char** papszOptions = CSLAddString(GetBaseHTTPOptions(), NULL);
-    papszOptions = CSLSetNameValue(papszOptions, "MAX_RETRY", "3");
-    CPLHTTPResult * psResult;
-    if( STARTS_WITH(osBaseURL, "/vsimem/") &&
-        STARTS_WITH(pszURL, "/vsimem/") )
-    {
-        CPLDebug("PLSCENES", "Fetching %s", pszURL);
-        psResult = (CPLHTTPResult*) CPLCalloc(1, sizeof(CPLHTTPResult));
-        vsi_l_offset nDataLengthLarge = 0;
-        CPLString osURL(pszURL);
-        if( osURL[osURL.size()-1 ] == '/' )
-            osURL.resize(osURL.size()-1);
-        GByte* pabyBuf = VSIGetMemFileBuffer(osURL, &nDataLengthLarge, FALSE);
-        size_t nDataLength = static_cast<size_t>(nDataLengthLarge);
-        if( pabyBuf )
-        {
-            psResult->pabyData = (GByte*) VSI_MALLOC_VERBOSE(1 + nDataLength);
-            if( psResult->pabyData )
-            {
-                memcpy(psResult->pabyData, pabyBuf, nDataLength);
-                psResult->pabyData[nDataLength] = 0;
-            }
-        }
-        else
-        {
-            psResult->pszErrBuf =
-                CPLStrdup(CPLSPrintf("Error 404. Cannot find %s", pszURL));
-        }
-    }
-    else
-    {
-        if( bQuiet404Error )
-            CPLPushErrorHandler(CPLQuietErrorHandler);
-        psResult = CPLHTTPFetch( pszURL, papszOptions);
-        if( bQuiet404Error )
-            CPLPopErrorHandler();
-    }
-    CSLDestroy(papszOptions);
-
-    if( psResult->pszErrBuf != NULL )
-    {
-        if( !(bQuiet404Error && strstr(psResult->pszErrBuf, "404")) )
-        {
-            CPLError(CE_Failure, CPLE_AppDefined, "%s",
-                    psResult->pabyData ? (const char*) psResult->pabyData :
-                    psResult->pszErrBuf);
-        }
-        CPLHTTPDestroyResult(psResult);
-        return NULL;
-    }
-
-    if( psResult->pabyData == NULL )
-    {
-        CPLError(CE_Failure, CPLE_AppDefined, "Empty content returned by server");
-        CPLHTTPDestroyResult(psResult);
-        return NULL;
-    }
-
-    json_object* poObj = NULL;
-    const char* pszText = reinterpret_cast<const char*>(psResult->pabyData);
-    if( !OGRJSonParse(pszText, &poObj, true) )
-    {
-        CPLHTTPDestroyResult(psResult);
-        return NULL;
-    }
-
-    CPLHTTPDestroyResult(psResult);
-
-    if( json_object_get_type(poObj) != json_type_object )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined, "Return is not a JSON dictionary");
-        json_object_put(poObj);
-        poObj = NULL;
-    }
-
-    return poObj;
-}
-
-/************************************************************************/
-/*                            OpenRasterScene()                         */
-/************************************************************************/
-
-GDALDataset* OGRPLScenesDataset::OpenRasterScene(GDALOpenInfo* poOpenInfo,
-                                                 CPLString osScene,
-                                                 char** papszOptions)
-{
-    if( !(poOpenInfo->nOpenFlags & GDAL_OF_RASTER) )
-    {
-        return NULL;
-    }
-
-    for( char** papszIter = papszOptions; papszIter && *papszIter; papszIter ++ )
-    {
-        char* pszKey = NULL;
-        const char* pszValue = CPLParseNameValue(*papszIter, &pszKey);
-        if( pszValue != NULL )
-        {
-            if( !EQUAL(pszKey, "api_key") &&
-                !EQUAL(pszKey, "scene") &&
-                !EQUAL(pszKey, "product_type") &&
-                !EQUAL(pszKey, "version") )
-            {
-                CPLError(CE_Failure, CPLE_NotSupported, "Unsupported option %s", pszKey);
-                CPLFree(pszKey);
-                return NULL;
-            }
-            CPLFree(pszKey);
-        }
-    }
-
-    const char* pszProductType = CSLFetchNameValueDef(papszOptions, "product_type",
-                CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "PRODUCT_TYPE", "visual"));
-
-    CPLString osRasterURL;
-    osRasterURL = osBaseURL;
-    osRasterURL += CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "CATALOG", "ortho");
-    osRasterURL += "/";
-    osRasterURL += osScene;
-    json_object* poObj = RunRequest( osRasterURL );
-    if( poObj == NULL )
-        return NULL;
-    json_object* poProperties = CPL_json_object_object_get(poObj, "properties");
-    if( poProperties == NULL || json_object_get_type(poProperties) != json_type_object )
-    {
-        CPLError(CE_Failure, CPLE_AppDefined, "Cannot find properties object");
-        json_object_put(poObj);
-        return NULL;
-    }
-
-    const char* pszLink = NULL;
-    if( EQUAL(pszProductType, "thumb") )
-    {
-        json_object* poLinks = CPL_json_object_object_get(poProperties, "links");
-        if( poLinks != NULL && json_object_get_type(poLinks) == json_type_object )
-        {
-            json_object* poThumbnail = CPL_json_object_object_get(poLinks, "thumbnail");
-            if( poThumbnail && json_object_get_type(poThumbnail) == json_type_string )
-                pszLink = json_object_get_string(poThumbnail);
-        }
-    }
-    else
-    {
-        json_object* poData = CPL_json_object_object_get(poProperties, "data");
-        if( poData != NULL && json_object_get_type(poData) == json_type_object )
-        {
-            json_object* poProducts = CPL_json_object_object_get(poData, "products");
-            if( poProducts != NULL && json_object_get_type(poProducts) == json_type_object )
-            {
-                json_object* poProduct = CPL_json_object_object_get(poProducts, pszProductType);
-                if( poProduct != NULL && json_object_get_type(poProduct) == json_type_object )
-                {
-                    json_object* poFull = CPL_json_object_object_get(poProduct, "full");
-                    if( poFull && json_object_get_type(poFull) == json_type_string )
-                        pszLink = json_object_get_string(poFull);
-                }
-            }
-        }
-    }
-    osRasterURL = pszLink ? pszLink : "";
-    json_object_put(poObj);
-    if( osRasterURL.empty() )
-    {
-        CPLError(CE_Failure, CPLE_AppDefined, "Cannot find link to scene %s",
-                 osScene.c_str());
-        return NULL;
-    }
-
-    if( STARTS_WITH(osRasterURL, "http://") )
-    {
-        osRasterURL = "http://" + osAPIKey + ":@" + osRasterURL.substr(strlen("http://"));
-    }
-    else if( STARTS_WITH(osRasterURL, "https://") )
-    {
-        osRasterURL = "https://" + osAPIKey + ":@" + osRasterURL.substr(strlen("https://"));
-    }
-
-    CPLString osOldHead(CPLGetConfigOption("CPL_VSIL_CURL_USE_HEAD", ""));
-    CPLString osOldAllowedFilename(CPLGetConfigOption("CPL_VSIL_CURL_ALLOWED_FILENAME", ""));
-
-    const bool bUseVSICURL =
-        CPLFetchBool(poOpenInfo->papszOpenOptions, "RANDOM_ACCESS", true);
-    if( bUseVSICURL && !(STARTS_WITH(osBaseURL, "/vsimem/")) )
-    {
-        CPLSetThreadLocalConfigOption("CPL_VSIL_CURL_USE_HEAD", "NO");
-        CPLSetThreadLocalConfigOption("CPL_VSIL_CURL_ALLOWED_FILENAME",
-                                      ("/vsicurl/" + osRasterURL).c_str());
-
-        VSIStatBufL sStat;
-        if( VSIStatL(("/vsicurl/" + osRasterURL).c_str(), &sStat) == 0 &&
-            sStat.st_size > 0 )
-        {
-            osRasterURL = "/vsicurl/" + osRasterURL;
-        }
-        else
-        {
-            CPLDebug("PLSCENES", "Cannot use random access for that file");
-        }
-    }
-
-    char** papszAllowedDrivers = NULL;
-    papszAllowedDrivers = CSLAddString(papszAllowedDrivers, "HTTP");
-    papszAllowedDrivers = CSLAddString(papszAllowedDrivers, "GTiff");
-    papszAllowedDrivers = CSLAddString(papszAllowedDrivers, "PNG");
-    papszAllowedDrivers = CSLAddString(papszAllowedDrivers, "JPEG");
-    GDALDataset* poOutDS = (GDALDataset*) GDALOpenEx(osRasterURL, GDAL_OF_RASTER,
-                                                     papszAllowedDrivers, NULL, NULL);
-    CSLDestroy(papszAllowedDrivers);
-    if( poOutDS )
-    {
-        if( !EQUAL(pszProductType, "thumb") )
-        {
-            OGRPLScenesLayer* poLayer = new OGRPLScenesLayer(this, "ortho",
-                                            (osBaseURL + "ortho/").c_str());
-            papoLayers = (OGRPLScenesLayer**) CPLRealloc(papoLayers,
-                                        sizeof(OGRPLScenesLayer*) * (nLayers + 1));
-            papoLayers[nLayers ++] = poLayer;
-
-            // Set a dummy name so that PAM goes here
-            CPLPushErrorHandler(CPLQuietErrorHandler);
-            poOutDS->SetDescription("/vsimem/tmp/ogrplscenesv0");
-
-            /* Attach scene metadata. */
-            poLayer->SetAttributeFilter(CPLSPrintf("id = '%s'", osScene.c_str()));
-            OGRFeature* poFeat = poLayer->GetNextFeature();
-            if( poFeat )
-            {
-                for(int i=0;i<poFeat->GetFieldCount();i++)
-                {
-                    if( poFeat->IsFieldSetAndNotNull(i) )
-                    {
-                        const char* pszKey = poFeat->GetFieldDefnRef(i)->GetNameRef();
-                        const char* pszVal = poFeat->GetFieldAsString(i);
-                        if( strstr(pszKey, "file_size") == NULL &&
-                            strstr(pszVal, "https://") == NULL )
-                        {
-                            poOutDS->SetMetadataItem(pszKey, pszVal);
-                        }
-                    }
-                }
-            }
-            delete poFeat;
-
-            poOutDS->FlushCache();
-            VSIUnlink("/vsimem/tmp/ogrplscenesv0");
-            VSIUnlink("/vsimem/tmp/ogrplscenesv0.aux.xml");
-            CPLPopErrorHandler();
-        }
-
-        CPLErrorReset();
-        poOutDS->SetDescription(poOpenInfo->pszFilename);
-        CSLDestroy(poOutDS->GetFileList()); /* so as to probe all auxiliary files before resetting the allowed extensions */
-    }
-
-    if( bUseVSICURL )
-    {
-        CPLSetThreadLocalConfigOption("CPL_VSIL_CURL_USE_HEAD",
-                                    !osOldHead.empty() ? osOldHead.c_str(): NULL);
-        CPLSetThreadLocalConfigOption("CPL_VSIL_CURL_ALLOWED_FILENAME",
-                                    !osOldAllowedFilename.empty() ? osOldAllowedFilename.c_str(): NULL);
-    }
-
-    return poOutDS;
-}
-
-/************************************************************************/
-/*                                Open()                                */
-/************************************************************************/
-
-GDALDataset* OGRPLScenesDataset::Open(GDALOpenInfo* poOpenInfo)
-{
-    OGRPLScenesDataset* poDS = new OGRPLScenesDataset();
-
-    poDS->osBaseURL = CPLGetConfigOption("PL_URL", "https://api.planet.com/v0/scenes/");
-
-    char** papszOptions = CSLTokenizeStringComplex(
-        poOpenInfo->pszFilename+strlen("PLScenes:"), ",", TRUE, FALSE );
-
-    poDS->osAPIKey = CSLFetchNameValueDef(papszOptions, "api_key",
-        CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "API_KEY",
-                                CPLGetConfigOption("PL_API_KEY","")) );
-    if( poDS->osAPIKey.empty() )
-    {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Missing PL_API_KEY configuration option or API_KEY open option");
-        delete poDS;
-        CSLDestroy(papszOptions);
-        return NULL;
-    }
-
-    const char* pszScene = CSLFetchNameValueDef(papszOptions, "scene",
-                CSLFetchNameValue(poOpenInfo->papszOpenOptions, "SCENE"));
-    if( pszScene )
-    {
-        GDALDataset* poRasterDS = poDS->OpenRasterScene(poOpenInfo, pszScene,
-                                                        papszOptions);
-        delete poDS;
-        CSLDestroy(papszOptions);
-        return poRasterDS;
-    }
-
-    for( char** papszIter = papszOptions; papszIter && *papszIter; papszIter ++ )
-    {
-        char* pszKey = NULL;
-        const char* pszValue = CPLParseNameValue(*papszIter, &pszKey);
-        if( pszValue != NULL )
-        {
-            if( !EQUAL(pszKey, "api_key") &&
-                !EQUAL(pszKey, "spat") &&
-                !EQUAL(pszKey, "version") )
-            {
-                CPLError(CE_Failure, CPLE_NotSupported, "Unsupported option '%s'", pszKey);
-                CPLFree(pszKey);
-                delete poDS;
-                CSLDestroy(papszOptions);
-                return NULL;
-            }
-            CPLFree(pszKey);
-        }
-    }
-
-    json_object* poObj = poDS->RunRequest(poDS->osBaseURL);
-    if( poObj == NULL )
-    {
-        delete poDS;
-        CSLDestroy(papszOptions);
-        return NULL;
-    }
-
-    json_object_iter it;
-    it.key = NULL;
-    it.val = NULL;
-    it.entry = NULL;
-    json_object_object_foreachC( poObj, it )
-    {
-        if( it.val != NULL && json_object_get_type(it.val) == json_type_string )
-        {
-            const char* pszSceneType = it.key;
-            const char* pszSceneTypeURL = json_object_get_string(it.val);
-            json_object* poObj2 = NULL;
-            if( !EQUAL(pszSceneType, "ortho") )
-                poObj2 = poDS->RunRequest( (CPLString(pszSceneTypeURL) + CPLString("?count=10")).c_str() );
-
-            OGRPLScenesLayer* poLayer = new OGRPLScenesLayer(poDS, pszSceneType, pszSceneTypeURL, poObj2);
-
-            if( poObj2 )
-                json_object_put(poObj2);
-
-            poDS->papoLayers = (OGRPLScenesLayer**) CPLRealloc(poDS->papoLayers,
-                                        sizeof(OGRPLScenesLayer*) * (poDS->nLayers + 1));
-            poDS->papoLayers[poDS->nLayers ++] = poLayer;
-
-            const char* pszSpat = CSLFetchNameValue(papszOptions, "spat");
-            if( pszSpat )
-            {
-                char** papszTokens = CSLTokenizeString2(pszSpat, " ", 0);
-                if( CSLCount(papszTokens) >= 4 )
-                {
-                    poLayer->SetMainFilterRect(CPLAtof(papszTokens[0]),
-                                               CPLAtof(papszTokens[1]),
-                                               CPLAtof(papszTokens[2]),
-                                               CPLAtof(papszTokens[3]));
-                }
-                CSLDestroy(papszTokens);
-            }
-        }
-    }
-
-    json_object_put(poObj);
-
-    CSLDestroy(papszOptions);
-
-    if( !(poOpenInfo->nOpenFlags & GDAL_OF_VECTOR) )
-    {
-        delete poDS;
-        return NULL;
-    }
-
-    return poDS;
-}
diff --git a/ogr/ogrsf_frmts/plscenes/ogrplscenesdriver.cpp b/ogr/ogrsf_frmts/plscenes/ogrplscenesdriver.cpp
index c6217d8..7407aa4 100644
--- a/ogr/ogrsf_frmts/plscenes/ogrplscenesdriver.cpp
+++ b/ogr/ogrsf_frmts/plscenes/ogrplscenesdriver.cpp
@@ -28,7 +28,7 @@
 
 #include "ogr_plscenes.h"
 
-CPL_CVSID("$Id: ogrplscenesdriver.cpp 37289 2017-02-03 18:42:21Z rouault $");
+CPL_CVSID("$Id: ogrplscenesdriver.cpp 39215 2017-06-20 19:09:46Z rouault $");
 
 /************************************************************************/
 /*                         OGRPLScenesIdentify()                        */
@@ -54,7 +54,12 @@ static GDALDataset* OGRPLScenesOpen(GDALOpenInfo* poOpenInfo)
                 CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "VERSION", ""));
     CSLDestroy(papszOptions);
     if( EQUAL(osVersion, "v0"))
-        return OGRPLScenesDataset::Open(poOpenInfo);
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "This API version has been removed. "
+                 "Please use DATA_V1 API instead");
+        return NULL;
+    }
     if( EQUAL(osVersion, "v1") )
         return OGRPLScenesV1Dataset::Open(poOpenInfo);
     if( EQUAL(osVersion, "data_v1") || EQUAL(osVersion, "")  )
@@ -85,7 +90,6 @@ void RegisterOGRPLSCENES()
     poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
 "<OpenOptionList>"
 "  <Option name='VERSION' type='string-select' description='API version' default='DATA_V1'>"
-"    <Value>V0</Value>"
 "    <Value>V1</Value>"
 "    <Value>DATA_V1</Value>"
 "  </Option>"
@@ -93,7 +97,7 @@ void RegisterOGRPLSCENES()
 "  <Option name='FOLLOW_LINKS' type='boolean' description='Whether assets links should be followed for each scene (API v1 / data v1 only)' default='NO'/>"
 "  <Option name='SCENE' type='string' description='Scene id (for raster fetching)'/>"
 "  <Option name='ITEMTYPES' alias='CATALOG' type='string' description='Catalog id (API v1 / data v1 only, mandatory for raster fetching)'/>"
-"  <Option name='ASSET' alias='PRODUCT_TYPE' type='string' description='Asset category/Product type. For v0 API: visual, analytic or thumb (for raster fetching)' default='visual'/>"
+"  <Option name='ASSET' alias='PRODUCT_TYPE' type='string' description='Asset category/Product type.' default='visual'/>"
 "  <Option name='RANDOM_ACCESS' type='boolean' description='Whether raster should be accessed in random access mode (but with potentially not optimal throughput). If no, in-memory ingestion is done' default='YES'/>"
 "  <Option name='ACTIVATION_TIMEOUT' type='int' description='Number of seconds during which to wait for asset activation (API v1 / data v1 only, raster)' default='3600'/>"
 "  <Option name='FILTER' type='string' description='Custom filter (API v1 / data v1 only)'/>"
diff --git a/ogr/ogrsf_frmts/plscenes/ogrplsceneslayer.cpp b/ogr/ogrsf_frmts/plscenes/ogrplsceneslayer.cpp
deleted file mode 100644
index 021b596..0000000
--- a/ogr/ogrsf_frmts/plscenes/ogrplsceneslayer.cpp
+++ /dev/null
@@ -1,766 +0,0 @@
-/******************************************************************************
- *
- * Project:  PlanetLabs scene driver
- * Purpose:  Implements OGRPLScenesLayer
- * Author:   Even Rouault, even dot rouault at spatialys.com
- *
- ******************************************************************************
- * Copyright (c) 2015, Planet Labs
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "ogr_plscenes.h"
-#include "ogrgeojsonreader.h"
-#include <algorithm>
-
-CPL_CVSID("$Id: ogrplsceneslayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
-
-typedef struct
-{
-    const char* pszName;
-    OGRFieldType eType;
-} PLAttribute;
-
-static const PLAttribute apsAttrs[] = {
-    { "id",                     OFTString },
-    { "acquired",               OFTDateTime },
-    { "camera.bit_depth",       OFTInteger },
-    { "camera.color_mode",      OFTString },
-    { "camera.exposure_time",   OFTInteger },
-    { "camera.gain",            OFTInteger },
-    { "camera.tdi_pulses",      OFTInteger },
-    { "cloud_cover.estimated",  OFTReal },
-    { "data.products.analytic.full",      OFTString },
-    { "data.products.visual.full",        OFTString },
-    { "file_size",                        OFTInteger },
-    { "image_statistics.gsd",             OFTReal },
-    { "image_statistics.image_quality",   OFTString },
-    { "image_statistics.snr",             OFTReal },
-    { "links.full",                       OFTString },
-    { "links.self",                       OFTString },
-    { "links.square_thumbnail",           OFTString },
-    { "links.thumbnail",                  OFTString },
-    { "sat.alt",                          OFTReal },
-    { "sat.id",                           OFTString },
-    { "sat.lat",                          OFTReal },
-    { "sat.lng",                          OFTReal },
-    { "sat.off_nadir",                    OFTReal },
-    { "strip_id",                         OFTReal },
-    { "sun.altitude",                     OFTReal },
-    { "sun.azimuth",                      OFTReal },
-    { "sun.local_time_of_day",            OFTReal },
-};
-
-static bool OGRPLScenesLayerFieldNameComparator(const CPLString& osFirst,
-                                                const CPLString& osSecond)
-{
-    const char* pszUnderscore1 = strrchr(osFirst.c_str(), '_');
-    const char* pszUnderscore2 = strrchr(osSecond.c_str(), '_');
-    int val1 = 0, val2 = 0;
-    if( pszUnderscore1 && pszUnderscore2 &&
-        (CPLString(osFirst).substr(0, pszUnderscore1-osFirst.c_str()) ==
-         CPLString(osSecond).substr(0, pszUnderscore2-osSecond.c_str())) &&
-        sscanf(pszUnderscore1 + 1, "%d", &val1) == 1 &&
-        sscanf(pszUnderscore2 + 1, "%d", &val2) == 1 )
-    {
-        return val1 < val2;
-    }
-    return osFirst < osSecond;
-}
-
-/************************************************************************/
-/*                           OGRPLScenesLayer()                         */
-/************************************************************************/
-
-OGRPLScenesLayer::OGRPLScenesLayer( OGRPLScenesDataset* poDSIn,
-                                    const char* pszName,
-                                    const char* pszBaseURL,
-                                    json_object* poObjCount10 ) :
-    poDS(poDSIn),
-    osBaseURL(pszBaseURL),
-    poFeatureDefn(new OGRFeatureDefn(pszName)),
-    poSRS(new OGRSpatialReference(SRS_WKT_WGS84)),
-    bEOF(false),
-    nNextFID(1),
-    nFeatureCount(-1),
-    poGeoJSONDS(NULL),
-    poGeoJSONLayer(NULL),
-    poMainFilter(NULL),
-    nPageSize(atoi(CPLGetConfigOption("PLSCENES_PAGE_SIZE", "1000"))),
-    bStillInFirstPage(false),
-    bAcquiredAscending(-1),
-    bFilterMustBeClientSideEvaluated(false)
-{
-    SetDescription(pszName);
-    poFeatureDefn->SetGeomType(wkbMultiPolygon);
-    for( int i = 0;
-         i < static_cast<int>(sizeof(apsAttrs)) /
-             static_cast<int>(sizeof(apsAttrs[0]));
-         i++ )
-    {
-        OGRFieldDefn oField(apsAttrs[i].pszName, apsAttrs[i].eType);
-        poFeatureDefn->AddFieldDefn(&oField);
-    }
-    poFeatureDefn->Reference();
-    poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
-    ResetReading();
-
-    if( poObjCount10 != NULL )
-    {
-        json_object* poCount = CPL_json_object_object_get(poObjCount10, "count");
-        if( poCount != NULL )
-          nFeatureCount = std::max(static_cast<int64_t>(0),
-                                   json_object_get_int64(poCount));
-
-        OGRGeoJSONDataSource* poTmpDS = new OGRGeoJSONDataSource();
-        OGRGeoJSONReader oReader;
-        oReader.SetFlattenNestedAttributes(true, '.');
-        oReader.ReadLayer( poTmpDS, "layer", poObjCount10 );
-        OGRLayer* poTmpLayer = poTmpDS->GetLayer(0);
-        if( poTmpLayer )
-        {
-            OGRFeatureDefn* poTmpFDefn = poTmpLayer->GetLayerDefn();
-            std::vector<CPLString> aosNewFields;
-            for(int i=0;i<poTmpFDefn->GetFieldCount();i++)
-            {
-                if( poFeatureDefn->GetFieldIndex(poTmpFDefn->GetFieldDefn(i)->GetNameRef()) < 0 )
-                    aosNewFields.push_back(poTmpFDefn->GetFieldDefn(i)->GetNameRef());
-            }
-            std::sort(aosNewFields.begin(), aosNewFields.end(), OGRPLScenesLayerFieldNameComparator);
-            for(int i=0;i<(int)aosNewFields.size();i++)
-            {
-                OGRFieldDefn oField(poTmpFDefn->GetFieldDefn(poTmpFDefn->GetFieldIndex(aosNewFields[i])));
-                poFeatureDefn->AddFieldDefn(&oField);
-            }
-        }
-        delete poTmpDS;
-    }
-}
-
-/************************************************************************/
-/*                           ~OGRPLScenesLayer()                        */
-/************************************************************************/
-
-OGRPLScenesLayer::~OGRPLScenesLayer()
-{
-    poFeatureDefn->Release();
-    poSRS->Release();
-    delete poGeoJSONDS;
-    delete poMainFilter;
-}
-
-/************************************************************************/
-/*                             BuildFilter()                            */
-/************************************************************************/
-
-CPLString OGRPLScenesLayer::BuildFilter(swq_expr_node* poNode)
-{
-    if( poNode->eNodeType == SNT_OPERATION )
-    {
-        if( poNode->nOperation == SWQ_AND && poNode->nSubExprCount == 2 )
-        {
-            // For AND, we can deal with a failure in one of the branch
-            // since client-side will do that extra filtering
-            CPLString osFilter1 = BuildFilter(poNode->papoSubExpr[0]);
-            CPLString osFilter2 = BuildFilter(poNode->papoSubExpr[1]);
-            if( !osFilter1.empty() && !osFilter2.empty() )
-                return osFilter1 + "&" + osFilter2;
-            else if( !osFilter1.empty() )
-                return osFilter1;
-            else
-                return osFilter2;
-        }
-        else if( (poNode->nOperation == SWQ_EQ ||
-                  poNode->nOperation == SWQ_NE ||
-                  poNode->nOperation == SWQ_LT ||
-                  poNode->nOperation == SWQ_LE ||
-                  poNode->nOperation == SWQ_GT ||
-                  poNode->nOperation == SWQ_GE) && poNode->nSubExprCount == 2 &&
-                  poNode->papoSubExpr[0]->eNodeType == SNT_COLUMN &&
-                  poNode->papoSubExpr[1]->eNodeType == SNT_CONSTANT &&
-                  poNode->papoSubExpr[0]->field_index != poFeatureDefn->GetFieldIndex("id") &&
-                  poNode->papoSubExpr[0]->field_index < poFeatureDefn->GetFieldCount() )
-        {
-            OGRFieldDefn *poFieldDefn =
-                poFeatureDefn->GetFieldDefn(poNode->papoSubExpr[0]->field_index);
-
-            int nOperation = poNode->nOperation;
-
-            // image_quality supports only gte filters
-            // (https://www.planet.com/docs-v0/v0/scenes/planetscope/#metadata)
-            if( poNode->papoSubExpr[0]->field_index ==
-                    poFeatureDefn->GetFieldIndex("image_statistics.image_quality") &&
-                nOperation != SWQ_GE )
-            {
-                // == target can be safely turned as >= target
-                if( poNode->nOperation == SWQ_EQ &&
-                    poNode->papoSubExpr[1]->field_type == SWQ_STRING &&
-                    strcmp(poNode->papoSubExpr[1]->string_value, "target") == 0 )
-                {
-                    nOperation = SWQ_GE;
-                }
-                else
-                {
-                    if( !bFilterMustBeClientSideEvaluated )
-                    {
-                        bFilterMustBeClientSideEvaluated = true;
-                        CPLDebug("PLSCENES",
-                                 "Part or full filter will have to be "
-                                 "evaluated on client side.");
-                    }
-                    return "";
-                }
-            }
-
-            CPLString osFilter(poFieldDefn->GetNameRef());
-
-            bool bDateTimeParsed = false;
-            int nYear = 0;
-            int nMonth = 0;
-            int nDay = 0;
-            int nHour = 0;
-            int nMinute = 0;
-            int nSecond = 0;
-            if( poNode->papoSubExpr[1]->field_type == SWQ_TIMESTAMP )
-            {
-                if( sscanf(poNode->papoSubExpr[1]->string_value,"%04d/%02d/%02d %02d:%02d:%02d",
-                           &nYear, &nMonth, &nDay, &nHour, &nMinute, &nSecond) >= 3 ||
-                    sscanf(poNode->papoSubExpr[1]->string_value,"%04d-%02d-%02dT%02d:%02d:%02d",
-                           &nYear, &nMonth, &nDay, &nHour, &nMinute, &nSecond) >= 3 )
-                    bDateTimeParsed = true;
-            }
-
-            osFilter += ".";
-
-            if( nOperation == SWQ_EQ )
-            {
-                if( bDateTimeParsed )
-                    osFilter += "gte";
-                else
-                    osFilter += "eq";
-            }
-            else if( nOperation == SWQ_NE )
-                osFilter += "neq";
-            else if( nOperation == SWQ_LT )
-                osFilter += "lt";
-            else if( nOperation == SWQ_LE )
-                osFilter += "lte";
-            else if( nOperation == SWQ_GT )
-                osFilter += "gt";
-            else if( nOperation == SWQ_GE )
-                osFilter += "gte";
-            osFilter += "=";
-
-            if (poNode->papoSubExpr[1]->field_type == SWQ_FLOAT)
-                osFilter += CPLSPrintf("%.8f", poNode->papoSubExpr[1]->float_value);
-            else if (poNode->papoSubExpr[1]->field_type == SWQ_INTEGER)
-                osFilter += CPLSPrintf(CPL_FRMT_GIB, poNode->papoSubExpr[1]->int_value);
-            else if (poNode->papoSubExpr[1]->field_type == SWQ_STRING)
-                osFilter += poNode->papoSubExpr[1]->string_value;
-            else if (poNode->papoSubExpr[1]->field_type == SWQ_TIMESTAMP)
-            {
-                if( bDateTimeParsed )
-                {
-                    osFilter += CPLSPrintf("%04d-%02d-%02dT%02d:%02d:%02d",
-                                           nYear, nMonth, nDay, nHour, nMinute, nSecond);
-                    if( nOperation == SWQ_EQ )
-                    {
-                        osFilter += "&";
-                        osFilter += poFieldDefn->GetNameRef();
-                        osFilter += ".lt=";
-                        nSecond ++;
-                        if( nSecond == 60 ) { nSecond = 0; nMinute ++; }
-                        if( nMinute == 60 ) { nMinute = 0; nHour ++; }
-                        if( nHour == 24 ) { nHour = 0; nDay ++; }
-                        osFilter += CPLSPrintf("%04d-%02d-%02dT%02d:%02d:%02d",
-                                               nYear, nMonth, nDay, nHour, nMinute, nSecond);
-                    }
-                }
-                else
-                    osFilter += poNode->papoSubExpr[1]->string_value;
-            }
-            return osFilter;
-        }
-    }
-    if( !bFilterMustBeClientSideEvaluated )
-    {
-        bFilterMustBeClientSideEvaluated = true;
-        CPLDebug("PLSCENES",
-                 "Part or full filter will have to be evaluated on client side.");
-    }
-    return "";
-}
-
-/************************************************************************/
-/*                             ResetReading()                           */
-/************************************************************************/
-
-void OGRPLScenesLayer::ResetReading()
-{
-    bEOF = false;
-    if( poGeoJSONLayer && bStillInFirstPage )
-        poGeoJSONLayer->ResetReading();
-    else
-        poGeoJSONLayer = NULL;
-    nNextFID = 1;
-    bStillInFirstPage = true;
-    osRequestURL = BuildURL(nPageSize);
-}
-
-/************************************************************************/
-/*                             BuildURL()                               */
-/************************************************************************/
-
-CPLString OGRPLScenesLayer::BuildURL(int nFeatures)
-{
-    CPLString osURL = osBaseURL + CPLSPrintf("?count=%d", nFeatures);
-
-    if( bAcquiredAscending == 1 )
-        osURL += "&order_by=acquired%20asc";
-    else if( bAcquiredAscending == 0 )
-        osURL += "&order_by=acquired%20desc";
-
-    if( m_poFilterGeom != NULL || poMainFilter != NULL )
-    {
-        OGRGeometry* poIntersection = NULL;
-        OGRGeometry* poFilterGeom = m_poFilterGeom;
-        if( poFilterGeom )
-        {
-            OGREnvelope sEnvelope;
-            poFilterGeom->getEnvelope(&sEnvelope);
-            if( sEnvelope.MinX <= -180 && sEnvelope.MinY <= -90 &&
-                sEnvelope.MaxX >= 180 && sEnvelope.MaxY >= 90 )
-                poFilterGeom = NULL;
-        }
-
-        if( poFilterGeom && poMainFilter )
-            poIntersection = poFilterGeom->Intersection(poMainFilter);
-        else if( poFilterGeom )
-            poIntersection = poFilterGeom;
-        else if( poMainFilter )
-            poIntersection = poMainFilter;
-        if( poIntersection )
-        {
-            char* pszWKT = NULL;
-            OGREnvelope sEnvelope;
-            poIntersection->getEnvelope(&sEnvelope);
-            if( sEnvelope.MinX == sEnvelope.MaxX && sEnvelope.MinY == sEnvelope.MaxY )
-            {
-                pszWKT = CPLStrdup(CPLSPrintf("POINT(%.18g %.18g)",
-                                            sEnvelope.MinX, sEnvelope.MinY));
-            }
-            else
-                poIntersection->exportToWkt(&pszWKT);
-
-            osURL += "&intersects=";
-            char* pszWKTEscaped = CPLEscapeString(pszWKT, -1, CPLES_URL);
-            osURL += pszWKTEscaped;
-            CPLFree(pszWKTEscaped);
-            CPLFree(pszWKT);
-        }
-        if( poIntersection != m_poFilterGeom && poIntersection != poMainFilter  )
-            delete poIntersection;
-    }
-
-    if( !osFilterURLPart.empty() )
-    {
-        if( osFilterURLPart[0] == '&' )
-            osURL += osFilterURLPart;
-        else
-            osURL = osBaseURL + osFilterURLPart;
-    }
-
-    return osURL;
-}
-
-/************************************************************************/
-/*                              GetNextPage()                           */
-/************************************************************************/
-
-int OGRPLScenesLayer::GetNextPage()
-{
-    delete poGeoJSONDS;
-    poGeoJSONLayer = NULL;
-    poGeoJSONDS = NULL;
-
-    if( osRequestURL.empty() )
-    {
-        bEOF = true;
-        if( !bFilterMustBeClientSideEvaluated && nFeatureCount < 0 )
-            nFeatureCount = 0;
-        return FALSE;
-    }
-    // In the case of a "id = 'foo'" filter, a non existing resource
-    // will cause a 404 error, which we want to be silent
-    int bQuiet404Error = ( osRequestURL.find('?') == std::string::npos );
-    json_object* poObj = poDS->RunRequest(osRequestURL, bQuiet404Error);
-    if( poObj == NULL )
-    {
-        bEOF = true;
-        if( !bFilterMustBeClientSideEvaluated && nFeatureCount < 0 )
-            nFeatureCount = 0;
-        return FALSE;
-    }
-
-    if( !bFilterMustBeClientSideEvaluated && nFeatureCount < 0 )
-    {
-        json_object* poType = CPL_json_object_object_get(poObj, "type");
-        if( poType && json_object_get_type(poType) == json_type_string &&
-            strcmp(json_object_get_string(poType), "Feature") == 0 )
-        {
-            nFeatureCount = 1;
-        }
-        else
-        {
-            json_object* poCount = CPL_json_object_object_get(poObj, "count");
-            if( poCount == NULL )
-            {
-                json_object_put(poObj);
-                bEOF = true;
-                nFeatureCount = 0;
-                return FALSE;
-            }
-            nFeatureCount = std::max(static_cast<int64_t>(0),
-                                     json_object_get_int64(poCount));
-        }
-    }
-
-    // Parse the Feature/FeatureCollection with the GeoJSON reader
-    poGeoJSONDS = new OGRGeoJSONDataSource();
-    OGRGeoJSONReader oReader;
-    oReader.SetFlattenNestedAttributes(true, '.');
-    oReader.ReadLayer( poGeoJSONDS, "layer", poObj);
-    poGeoJSONLayer = poGeoJSONDS->GetLayer(0);
-
-    // Get URL of next page
-    osNextURL = "";
-    if( poGeoJSONLayer )
-    {
-        json_object* poLinks = CPL_json_object_object_get(poObj, "links");
-        if( poLinks && json_object_get_type(poLinks) == json_type_object )
-        {
-            json_object* poNext = CPL_json_object_object_get(poLinks, "next");
-            if( poNext && json_object_get_type(poNext) == json_type_string )
-            {
-                osNextURL = json_object_get_string(poNext);
-            }
-        }
-    }
-
-    json_object_put(poObj);
-    return poGeoJSONLayer != NULL;
-}
-
-/************************************************************************/
-/*                          SetSpatialFilter()                          */
-/************************************************************************/
-
-void OGRPLScenesLayer::SetSpatialFilter(  OGRGeometry *poGeomIn )
-{
-    nFeatureCount = -1;
-    poGeoJSONLayer = NULL;
-
-    if( poGeomIn )
-    {
-        OGREnvelope sEnvelope;
-        poGeomIn->getEnvelope(&sEnvelope);
-        if( sEnvelope.MinX == sEnvelope.MaxX && sEnvelope.MinY == sEnvelope.MaxY )
-        {
-            OGRPoint p(sEnvelope.MinX, sEnvelope.MinY);
-            InstallFilter(&p);
-        }
-        else
-            InstallFilter( poGeomIn );
-    }
-    else
-        InstallFilter( poGeomIn );
-
-    ResetReading();
-}
-
-/************************************************************************/
-/*                         SetAttributeFilter()                         */
-/************************************************************************/
-
-OGRErr OGRPLScenesLayer::SetAttributeFilter( const char *pszQuery )
-
-{
-    if( pszQuery == NULL )
-        osQuery = "";
-    else
-        osQuery = pszQuery;
-
-    nFeatureCount = -1;
-    poGeoJSONLayer = NULL;
-
-    OGRErr eErr = OGRLayer::SetAttributeFilter(pszQuery);
-
-    osFilterURLPart = "";
-    bFilterMustBeClientSideEvaluated = false;
-    if( m_poAttrQuery != NULL )
-    {
-        swq_expr_node* poNode = (swq_expr_node*) m_poAttrQuery->GetSWQExpr();
-
-        poNode->ReplaceBetweenByGEAndLERecurse();
-
-        if( poNode->eNodeType == SNT_OPERATION &&
-            poNode->nOperation == SWQ_EQ && poNode->nSubExprCount == 2 &&
-            poNode->papoSubExpr[0]->eNodeType == SNT_COLUMN &&
-            poNode->papoSubExpr[0]->field_index == poFeatureDefn->GetFieldIndex("id") &&
-            poNode->papoSubExpr[1]->eNodeType == SNT_CONSTANT &&
-            poNode->papoSubExpr[1]->field_type == SWQ_STRING )
-        {
-            osFilterURLPart = poNode->papoSubExpr[1]->string_value;
-        }
-        else
-        {
-            CPLString osFilter = BuildFilter(poNode);
-            if( !osFilter.empty() )
-            {
-                osFilterURLPart = "&";
-                osFilterURLPart += osFilter;
-            }
-        }
-    }
-
-    ResetReading();
-
-    return eErr;
-}
-
-/************************************************************************/
-/*                           GetNextFeature()                           */
-/************************************************************************/
-
-OGRFeature *OGRPLScenesLayer::GetNextFeature()
-{
-    if( !bFilterMustBeClientSideEvaluated )
-        return GetNextRawFeature();
-
-    while( true )
-    {
-        OGRFeature *poFeature = NULL;
-        poFeature = GetNextRawFeature();
-        if (poFeature == NULL)
-            return NULL;
-
-        if((m_poFilterGeom == NULL
-            || FilterGeometry( poFeature->GetGeometryRef() ) )
-        && (m_poAttrQuery == NULL
-            || m_poAttrQuery->Evaluate( poFeature )) )
-        {
-            return poFeature;
-        }
-        else
-            delete poFeature;
-    }
-}
-
-/************************************************************************/
-/*                            GetNextRawFeature()                       */
-/************************************************************************/
-
-OGRFeature* OGRPLScenesLayer::GetNextRawFeature()
-{
-    if( bEOF ||
-        (!bFilterMustBeClientSideEvaluated &&
-         nFeatureCount >= 0 &&
-         nNextFID > nFeatureCount) )
-        return NULL;
-
-    if( poGeoJSONLayer == NULL )
-    {
-        if( !GetNextPage() )
-            return NULL;
-    }
-
-#ifdef notdef
-    if( CPLTestBool(CPLGetConfigOption("OGR_LIMIT_TOO_MANY_FEATURES", "FALSE")) &&
-        nFeatureCount > nPageSize )
-    {
-        bEOF = true;
-        OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
-        const char* pszWKT = "MULTIPOLYGON(((-180 90,180 90,180 -90,-180 -90,-180 90)))";
-        OGRGeometry* poGeom = NULL;
-        OGRGeometryFactory::createFromWkt((char**)&pszWKT, poSRS, &poGeom);
-        poFeature->SetGeometryDirectly(poGeom);
-        return poFeature;
-    }
-#endif
-
-    OGRFeature* poGeoJSONFeature = poGeoJSONLayer->GetNextFeature();
-    if( poGeoJSONFeature == NULL )
-    {
-        osRequestURL = osNextURL;
-        bStillInFirstPage = false;
-        if( !GetNextPage() )
-            return NULL;
-        poGeoJSONFeature = poGeoJSONLayer->GetNextFeature();
-        if( poGeoJSONFeature == NULL )
-        {
-            bEOF = true;
-            return NULL;
-        }
-    }
-    OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
-    poFeature->SetFID(nNextFID++);
-
-    OGRGeometry* poGeom = poGeoJSONFeature->StealGeometry();
-    if( poGeom != NULL )
-    {
-        if( poGeom->getGeometryType() == wkbPolygon )
-        {
-            OGRMultiPolygon* poMP = new OGRMultiPolygon();
-            poMP->addGeometryDirectly(poGeom);
-            poGeom = poMP;
-        }
-        poGeom->assignSpatialReference(poSRS);
-        poFeature->SetGeometryDirectly(poGeom);
-    }
-
-    for(int i=0;i<poFeatureDefn->GetFieldCount();i++)
-    {
-        OGRFieldDefn* poFieldDefn = poFeatureDefn->GetFieldDefn(i);
-        OGRFieldType eType = poFieldDefn->GetType();
-        int iSrcField = poGeoJSONFeature->GetFieldIndex(poFieldDefn->GetNameRef());
-        if( iSrcField >= 0 && poGeoJSONFeature->IsFieldSetAndNotNull(iSrcField) )
-        {
-            if( eType == OFTInteger )
-                poFeature->SetField(i,
-                    poGeoJSONFeature->GetFieldAsInteger(iSrcField));
-            else if( eType == OFTReal )
-                poFeature->SetField(i,
-                    poGeoJSONFeature->GetFieldAsDouble(iSrcField));
-            else
-                poFeature->SetField(i,
-                    poGeoJSONFeature->GetFieldAsString(iSrcField));
-        }
-    }
-
-    delete poGeoJSONFeature;
-
-    return poFeature;
-}
-
-/************************************************************************/
-/*                          GetFeatureCount()                           */
-/************************************************************************/
-
-GIntBig OGRPLScenesLayer::GetFeatureCount(int bForce)
-{
-    if( nFeatureCount < 0 )
-    {
-        CPLString osURL(BuildURL(1));
-        if( bFilterMustBeClientSideEvaluated )
-        {
-            nFeatureCount = OGRLayer::GetFeatureCount(bForce);
-        }
-        else if( osURL.find('?') == std::string::npos )
-        {
-            /* Case of a "id = XXXXX" filter: we get directly a Feature, */
-            /* not a FeatureCollection */
-            GetNextPage();
-        }
-        else
-        {
-            nFeatureCount = 0;
-            json_object* poObj = poDS->RunRequest(osURL);
-            if( poObj != NULL )
-            {
-                json_object* poCount = CPL_json_object_object_get(poObj, "count");
-                if( poCount != NULL )
-                    nFeatureCount = std::max(static_cast<int64_t>(0),
-                                             json_object_get_int64(poCount));
-
-                // Small optimization, if the feature count is actually 1
-                // then we can fetch it as the full layer
-                if( nFeatureCount == 1 )
-                {
-                    delete poGeoJSONDS;
-                    // Parse the Feature/FeatureCollection with the GeoJSON reader
-                    poGeoJSONDS = new OGRGeoJSONDataSource();
-                    OGRGeoJSONReader oReader;
-                    oReader.SetFlattenNestedAttributes(true, '.');
-                    oReader.ReadLayer( poGeoJSONDS, "layer", poObj);
-                    poGeoJSONLayer = poGeoJSONDS->GetLayer(0);
-                    osNextURL = "";
-                }
-                json_object_put(poObj);
-            }
-        }
-    }
-
-    return nFeatureCount;
-}
-
-/************************************************************************/
-/*                                GetExtent()                           */
-/************************************************************************/
-
-OGRErr OGRPLScenesLayer::GetExtent( OGREnvelope *psExtent, int bForce )
-{
-    GetFeatureCount();
-    if( nFeatureCount > 0 && nFeatureCount < nPageSize )
-        return OGRLayer::GetExtentInternal(0, psExtent, bForce);
-
-    psExtent->MinX = -180;
-    psExtent->MinY = -90;
-    psExtent->MaxX = 180;
-    psExtent->MaxY = 90;
-    return OGRERR_NONE;
-}
-
-/************************************************************************/
-/*                              SetMainFilterRect()                     */
-/************************************************************************/
-
-void OGRPLScenesLayer::SetMainFilterRect( double dfMinX, double dfMinY,
-                                          double dfMaxX, double dfMaxY )
-{
-    delete poMainFilter;
-    if( dfMinX == dfMaxX && dfMinY == dfMaxY )
-        poMainFilter = new OGRPoint(dfMinX, dfMinY);
-    else
-    {
-        OGRPolygon* poPolygon = new OGRPolygon();
-        poMainFilter = poPolygon;
-        OGRLinearRing* poLR = new OGRLinearRing;
-        poPolygon->addRingDirectly(poLR);
-        poLR->addPoint(dfMinX, dfMinY);
-        poLR->addPoint(dfMinX, dfMaxY);
-        poLR->addPoint(dfMaxX, dfMaxY);
-        poLR->addPoint(dfMaxX, dfMinY);
-        poLR->addPoint(dfMinX, dfMinY);
-    }
-    ResetReading();
-}
-
-/************************************************************************/
-/*                              TestCapability()                        */
-/************************************************************************/
-
-int OGRPLScenesLayer::TestCapability(const char* pszCap)
-{
-    if( EQUAL(pszCap, OLCFastFeatureCount) )
-        return !bFilterMustBeClientSideEvaluated;
-    if( EQUAL(pszCap, OLCStringsAsUTF8) )
-        return TRUE;
-    return FALSE;
-}
diff --git a/ogr/ogrsf_frmts/rec/ll_recio.cpp b/ogr/ogrsf_frmts/rec/ll_recio.cpp
index bac1cc5..4f6b6af 100644
--- a/ogr/ogrsf_frmts/rec/ll_recio.cpp
+++ b/ogr/ogrsf_frmts/rec/ll_recio.cpp
@@ -30,7 +30,7 @@
 #include "cpl_string.h"
 #include "ogr_rec.h"
 
-CPL_CVSID("$Id: ll_recio.cpp 36547 2016-11-28 22:27:56Z goatbar $");
+CPL_CVSID("$Id: ll_recio.cpp 39002 2017-06-09 00:06:16Z rouault $");
 
 static int nNextRecLine = 0;
 
@@ -123,6 +123,8 @@ const char *RECGetField( const char *pszSrc, int nStart, int nWidth )
 {
     static char szWorkField[128] = {};
 
+    if( nWidth >= static_cast<int>(sizeof(szWorkField)) )
+        nWidth = sizeof(szWorkField)-1;
     strncpy( szWorkField, pszSrc + nStart - 1, nWidth );
     szWorkField[nWidth] = '\0';
 
diff --git a/ogr/ogrsf_frmts/rec/ogrrecdatasource.cpp b/ogr/ogrsf_frmts/rec/ogrrecdatasource.cpp
index d76495d..77d1adb 100644
--- a/ogr/ogrsf_frmts/rec/ogrrecdatasource.cpp
+++ b/ogr/ogrsf_frmts/rec/ogrrecdatasource.cpp
@@ -30,7 +30,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrrecdatasource.cpp 34819 2016-07-28 22:32:18Z goatbar $");
+CPL_CVSID("$Id: ogrrecdatasource.cpp 38951 2017-06-07 21:40:45Z rouault $");
 
 /************************************************************************/
 /*                          OGRRECDataSource()                          */
@@ -105,6 +105,11 @@ int OGRRECDataSource::Open( const char * pszFilename )
 /*      field that is a number greater than zero.                       */
 /* -------------------------------------------------------------------- */
     const char * pszLine = CPLReadLine( fp );
+    if( pszLine == NULL )
+    {
+        VSIFClose( fp );
+        return FALSE;
+    }
 
     const int nFieldCount = atoi(pszLine);
     if( nFieldCount < 1 || nFieldCount > 1000 )
diff --git a/ogr/ogrsf_frmts/segukooa/ogrsegukooalayer.cpp b/ogr/ogrsf_frmts/segukooa/ogrsegukooalayer.cpp
index c148324..9ef83ef 100644
--- a/ogr/ogrsf_frmts/segukooa/ogrsegukooalayer.cpp
+++ b/ogr/ogrsf_frmts/segukooa/ogrsegukooalayer.cpp
@@ -32,7 +32,7 @@
 #include "ogr_p.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ogrsegukooalayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
+CPL_CVSID("$Id: ogrsegukooalayer.cpp 39045 2017-06-10 09:39:08Z rouault $");
 
 /************************************************************************/
 /*                            ExtractField()                            */
@@ -420,7 +420,7 @@ OGRFeature *OGRUKOOAP190Layer::GetNextRawFeature()
                 if ((bIsLeap && nDayOfYear >= 1 && nDayOfYear <= 366) ||
                     (!bIsLeap && nDayOfYear >= 1 && nDayOfYear <= 365))
                 {
-                    static const int leap_offset = bIsLeap ? 0 : 1;
+                    static const int leap_offset = bIsLeap ? 1 : 0;
                     while( nDayOfYear >
                            nDays +
                            mon_lengths[leap_offset][nMonth] )
@@ -605,7 +605,7 @@ OGRFeature *OGRSEGP1Layer::GetNextRawFeature()
         }
 
         /* Normal layout -> extract other fields */
-        if (nLatitudeCol == 27)
+        if (nLatitudeCol == 27 && nLineLen >= 26-1+1)
         {
             char szLineName[16 + 1];
             ExtractField(szLineName, pszLine, 2-1, 16);
diff --git a/ogr/ogrsf_frmts/selafin/io_selafin.cpp b/ogr/ogrsf_frmts/selafin/io_selafin.cpp
index 55f66de..abb28eb 100644
--- a/ogr/ogrsf_frmts/selafin/io_selafin.cpp
+++ b/ogr/ogrsf_frmts/selafin/io_selafin.cpp
@@ -32,7 +32,7 @@
 #include "cpl_error.h"
 #include "cpl_quad_tree.h"
 
-CPL_CVSID("$Id: io_selafin.cpp 36347 2016-11-20 20:43:39Z rouault $");
+CPL_CVSID("$Id: io_selafin.cpp 39100 2017-06-13 08:53:49Z rouault $");
 
 namespace Selafin {
 
@@ -369,6 +369,7 @@ namespace Selafin {
     int read_intarray(VSILFILE *fp,int *&panData,bool bDiscard) {
         int nLength=0;
         read_integer(fp,nLength);
+        panData = NULL;
         if (nLength<0 || nLength+1<=0) {
             CPLError(CE_Failure,CPLE_FileIO,"%s",SELAFIN_ERROR_MESSAGE);
             return -1;
@@ -386,11 +387,13 @@ namespace Selafin {
             }
             for (int i=0;i<nLength/4;++i) if (read_integer(fp,panData[i])==0) {
                 CPLFree(panData);
+                panData = NULL;
                 CPLError(CE_Failure,CPLE_FileIO,"%s",SELAFIN_ERROR_MESSAGE);
                 return -1;
             }
             if (VSIFSeekL(fp,4,SEEK_CUR)!=0) {
                 CPLFree(panData);
+                panData = NULL;
                 CPLError(CE_Failure,CPLE_FileIO,"%s",SELAFIN_ERROR_MESSAGE);
                 return -1;
             }
diff --git a/ogr/ogrsf_frmts/selafin/ogrselafindatasource.cpp b/ogr/ogrsf_frmts/selafin/ogrselafindatasource.cpp
index 30714a4..126cb92 100644
--- a/ogr/ogrsf_frmts/selafin/ogrselafindatasource.cpp
+++ b/ogr/ogrsf_frmts/selafin/ogrselafindatasource.cpp
@@ -34,7 +34,7 @@
 
 #include <ctime>
 
-CPL_CVSID("$Id: ogrselafindatasource.cpp 35562 2016-09-30 19:16:16Z goatbar $");
+CPL_CVSID("$Id: ogrselafindatasource.cpp 39100 2017-06-13 08:53:49Z rouault $");
 
 /************************************************************************/
 /*                          Range                                       */
@@ -442,9 +442,9 @@ int OGRSelafinDataSource::OpenTable(const char * pszFilename) {
     }
 
     // Read header of file to get common information for all layers
+    // poHeader now owns fp
     poHeader=Selafin::read_header(fp,pszFilename);
     if (poHeader==NULL) {
-        VSIFCloseL(fp);
         CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open %s, wrong format.\n", pszFilename);
         return FALSE;
     }
@@ -472,7 +472,6 @@ int OGRSelafinDataSource::OpenTable(const char * pszFilename) {
                 if( VSIFSeekL(fp, poHeader->getPosition(i)+4, SEEK_SET)!=0 ||
                     Selafin::read_float(fp, dfTime)==0 )
                 {
-                    VSIFCloseL(fp);
                     CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open %s, wrong format.\n", pszFilename);
                     return FALSE;
                 }
diff --git a/ogr/ogrsf_frmts/shape/shape2ogr.cpp b/ogr/ogrsf_frmts/shape/shape2ogr.cpp
index 5f97d90..7db217f 100644
--- a/ogr/ogrsf_frmts/shape/shape2ogr.cpp
+++ b/ogr/ogrsf_frmts/shape/shape2ogr.cpp
@@ -36,7 +36,7 @@
 #include <algorithm>
 #include <limits>
 
-CPL_CVSID("$Id: shape2ogr.cpp 37371 2017-02-13 11:41:59Z rouault $");
+CPL_CVSID("$Id: shape2ogr.cpp 38412 2017-05-16 10:07:10Z rouault $");
 
 /************************************************************************/
 /*                        RingStartEnd                                  */
@@ -178,7 +178,8 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
                             psShape->padfZ[i] );
                     }
                 }
-                else if( psShape->nSHPType == SHPT_MULTIPOINTM )
+                else if( psShape->nSHPType == SHPT_MULTIPOINTM &&
+                         psShape->padfM )
                 {
                     poPoint = new OGRPoint(psShape->padfX[i], psShape->padfY[i],
                                            0.0, psShape->padfM[i]);
diff --git a/ogr/ogrsf_frmts/tiger/ogr_tiger.h b/ogr/ogrsf_frmts/tiger/ogr_tiger.h
index cb6b9bb..fb29303 100644
--- a/ogr/ogrsf_frmts/tiger/ogr_tiger.h
+++ b/ogr/ogrsf_frmts/tiger/ogr_tiger.h
@@ -1,6 +1,6 @@
 /*-*-C++-*-*/
 /******************************************************************************
- * $Id: ogr_tiger.h 36501 2016-11-25 14:09:24Z rouault $
+ * $Id: ogr_tiger.h 38802 2017-06-02 09:04:34Z rouault $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Main declarations for Tiger translator.
@@ -120,6 +120,8 @@ typedef struct TigerRecordInfo {
 // than is really necessary won't affect the amount of memory required
 // in a substantial way.
 // mbp Fri Dec 20 19:19:59 2002
+// Note: OGR_TIGER_RECBUF_LEN should also be larger than 255, since
+// TigerRecordInfo::nRecordLength fits on unsigned char.
 #define OGR_TIGER_RECBUF_LEN 500
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/tiger/ogrtigerdatasource.cpp b/ogr/ogrsf_frmts/tiger/ogrtigerdatasource.cpp
index 1414146..963540c 100644
--- a/ogr/ogrsf_frmts/tiger/ogrtigerdatasource.cpp
+++ b/ogr/ogrsf_frmts/tiger/ogrtigerdatasource.cpp
@@ -33,7 +33,7 @@
 #include <cctype>
 #include <algorithm>
 
-CPL_CVSID("$Id: ogrtigerdatasource.cpp 36017 2016-10-29 04:27:08Z goatbar $");
+CPL_CVSID("$Id: ogrtigerdatasource.cpp 38363 2017-05-14 22:30:05Z rouault $");
 
 /************************************************************************/
 /*                        TigerClassifyVersion()                        */
@@ -358,10 +358,11 @@ int OGRTigerDataSource::Open( const char * pszFilename, int bTestOpen,
             {
                 char       szModule[128];
 
-                strncpy( szModule, candidateFileList[i],
-                         strlen(candidateFileList[i])-1 );
-
-                szModule[strlen(candidateFileList[i])-1] = '\0';
+                snprintf( szModule, sizeof(szModule), "%s",
+                          candidateFileList[i] );
+                const size_t nLen = strlen(szModule);
+                if( nLen )
+                    szModule[nLen-1] = '\0';
 
                 papszFileList = CSLAddString(papszFileList, szModule);
             }
diff --git a/ogr/ogrsf_frmts/tiger/tigeraltname.cpp b/ogr/ogrsf_frmts/tiger/tigeraltname.cpp
index 131db0a..b5a51e7 100644
--- a/ogr/ogrsf_frmts/tiger/tigeraltname.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigeraltname.cpp
@@ -29,7 +29,7 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigeraltname.cpp 35911 2016-10-24 15:03:26Z goatbar $");
+CPL_CVSID("$Id: tigeraltname.cpp 38802 2017-06-02 09:04:34Z rouault $");
 
 static const char FILE_CODE[] = "4";
 
@@ -104,6 +104,8 @@ OGRFeature *TigerAltName::GetFeature( int nRecordId )
         return NULL;
     }
 
+    // Overflow cannot happen since psRTInfo->nRecordLength is unsigned
+    // char and sizeof(achRecord) == OGR_TIGER_RECBUF_LEN > 255
     if( VSIFReadL( achRecord, psRTInfo->nRecordLength, 1, fpPrimary ) != 1 )
     {
         CPLError( CE_Failure, CPLE_FileIO,
diff --git a/ogr/ogrsf_frmts/tiger/tigercompletechain.cpp b/ogr/ogrsf_frmts/tiger/tigercompletechain.cpp
index d5b9563..2b4405f 100644
--- a/ogr/ogrsf_frmts/tiger/tigercompletechain.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigercompletechain.cpp
@@ -30,7 +30,7 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigercompletechain.cpp 36472 2016-11-23 16:38:20Z rouault $");
+CPL_CVSID("$Id: tigercompletechain.cpp 39090 2017-06-12 20:41:44Z rouault $");
 
 static const TigerFieldInfo rt1_2002_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
@@ -401,6 +401,8 @@ OGRFeature *TigerCompleteChain::GetFeature( int nRecordId )
         return NULL;
     }
 
+    // Overflow cannot happen since psRTInfo->nRecordLength is unsigned
+    // char and sizeof(achRecord) == OGR_TIGER_RECBUF_LEN > 255
     if( VSIFReadL( achRecord, psRT1Info->nRecordLength, 1, fpPrimary ) != 1 )
     {
         CPLError( CE_Failure, CPLE_FileIO,
@@ -435,6 +437,8 @@ OGRFeature *TigerCompleteChain::GetFeature( int nRecordId )
             return NULL;
         }
 
+        // Overflow cannot happen since psRTInfo->nRecordLength is unsigned
+        // char and sizeof(achRecord) == OGR_TIGER_RECBUF_LEN > 255
         if( VSIFReadL( achRT3Rec, psRT3Info->nRecordLength, 1, fpRT3 ) != 1 )
         {
             CPLError( CE_Failure, CPLE_FileIO,
@@ -621,6 +625,11 @@ int TigerCompleteChain::GetShapeRecordId( int nChainId, int nTLID )
     char        achShapeRec[OGR_TIGER_RECBUF_LEN];
     int         nShapeRecLen = psRT2Info->nRecordLength + nRecordLength - psRT1Info->nRecordLength;
 
+    if( nShapeRecLen <= 0 )
+    {
+        return -2;
+    }
+
     while( nChainsRead < nMaxChainToRead )
     {
         if( VSIFSeekL( fpShape, (nWorkingRecId-1) * nShapeRecLen,
diff --git a/ogr/ogrsf_frmts/tiger/tigerfilebase.cpp b/ogr/ogrsf_frmts/tiger/tigerfilebase.cpp
index 9cc501a..9544f05 100644
--- a/ogr/ogrsf_frmts/tiger/tigerfilebase.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerfilebase.cpp
@@ -33,7 +33,7 @@
 #include "cpl_error.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: tigerfilebase.cpp 37987 2017-04-14 07:42:50Z rouault $");
+CPL_CVSID("$Id: tigerfilebase.cpp 38802 2017-06-02 09:04:34Z rouault $");
 
 /************************************************************************/
 /*                           TigerFileBase()                            */
@@ -573,6 +573,8 @@ OGRFeature *TigerFileBase::GetFeature( int nRecordId )
         return NULL;
     }
 
+    // Overflow cannot happen since psRTInfo->nRecordLength is unsigned
+    // char and sizeof(achRecord) == OGR_TIGER_RECBUF_LEN > 255
     if( VSIFReadL( achRecord, psRTInfo->nRecordLength, 1, fpPrimary ) != 1 )
     {
         CPLError( CE_Failure, CPLE_FileIO,
diff --git a/ogr/ogrsf_frmts/tiger/tigerpoint.cpp b/ogr/ogrsf_frmts/tiger/tigerpoint.cpp
index 57e6f09..0f0fa62 100644
--- a/ogr/ogrsf_frmts/tiger/tigerpoint.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerpoint.cpp
@@ -29,7 +29,7 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerpoint.cpp 35609 2016-10-04 14:16:24Z goatbar $");
+CPL_CVSID("$Id: tigerpoint.cpp 38802 2017-06-02 09:04:34Z rouault $");
 
 /************************************************************************/
 /*                             TigerPoint()                             */
@@ -70,6 +70,8 @@ OGRFeature *TigerPoint::GetFeature( int nRecordId,
         return NULL;
     }
 
+    // Overflow cannot happen since psRTInfo->nRecordLength is unsigned
+    // char and sizeof(achRecord) == OGR_TIGER_RECBUF_LEN > 255
     if( VSIFReadL( achRecord, psRTInfo->nRecordLength, 1, fpPrimary ) != 1 ) {
         CPLError( CE_Failure, CPLE_FileIO,
                   "Failed to read record %d of %sP",
diff --git a/ogr/ogrsf_frmts/tiger/tigerpolygon.cpp b/ogr/ogrsf_frmts/tiger/tigerpolygon.cpp
index 265cb90..516ab9e 100644
--- a/ogr/ogrsf_frmts/tiger/tigerpolygon.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerpolygon.cpp
@@ -30,7 +30,7 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerpolygon.cpp 35933 2016-10-25 16:46:26Z goatbar $");
+CPL_CVSID("$Id: tigerpolygon.cpp 38802 2017-06-02 09:04:34Z rouault $");
 
 static const TigerFieldInfo rtA_2002_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
@@ -474,7 +474,7 @@ bool TigerPolygon::SetModule( const char * pszModuleIn )
 OGRFeature *TigerPolygon::GetFeature( int nRecordId )
 
 {
-  char        achRecord[OGR_TIGER_RECBUF_LEN];
+    char        achRecord[OGR_TIGER_RECBUF_LEN];
 
     if( nRecordId < 0 || nRecordId >= nFeatures )
     {
@@ -490,6 +490,13 @@ OGRFeature *TigerPolygon::GetFeature( int nRecordId )
     if( fpPrimary == NULL )
         return NULL;
 
+    if( nRecordLength > static_cast<int>(sizeof(achRecord)) )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Record length too large" );
+        return NULL;
+    }
+
     if( VSIFSeekL( fpPrimary, nRecordId * nRecordLength, SEEK_SET ) != 0 )
     {
         CPLError( CE_Failure, CPLE_FileIO,
@@ -527,14 +534,18 @@ OGRFeature *TigerPolygon::GetFeature( int nRecordId )
             CPLError( CE_Failure, CPLE_FileIO,
                       "Failed to seek to %d of %sS",
                       nRecordId * nRTSRecLen, pszModule );
+            delete poFeature;
             return NULL;
         }
 
+        // Overflow cannot happen since psRTInfo->nRecordLength is unsigned
+        // char and sizeof(achRecord) == OGR_TIGER_RECBUF_LEN > 255
         if( VSIFReadL( achRTSRec, psRTSInfo->nRecordLength, 1, fpRTS ) != 1 )
         {
             CPLError( CE_Failure, CPLE_FileIO,
                       "Failed to read record %d of %sS",
                       nRecordId, pszModule );
+            delete poFeature;
             return NULL;
         }
 
diff --git a/ogr/ogrsf_frmts/vfk/vfkdatablock.cpp b/ogr/ogrsf_frmts/vfk/vfkdatablock.cpp
index 8e4bd80..6f09ea9 100644
--- a/ogr/ogrsf_frmts/vfk/vfkdatablock.cpp
+++ b/ogr/ogrsf_frmts/vfk/vfkdatablock.cpp
@@ -37,7 +37,7 @@
 #include "cpl_conv.h"
 #include "cpl_error.h"
 
-CPL_CVSID("$Id: vfkdatablock.cpp 36682 2016-12-04 20:34:45Z rouault $");
+CPL_CVSID("$Id: vfkdatablock.cpp 38846 2017-06-04 09:00:01Z rouault $");
 
 /*!
   \brief VFK Data Block constructor
@@ -108,7 +108,7 @@ void IVFKDataBlock::SetProperties(const char *poLine)
     const char *poChar = NULL;
 
     /* skip data block name */
-    for (poChar = poLine; *poChar != '0' && *poChar != ';'; poChar++)
+    for (poChar = poLine; *poChar != '\0' && *poChar != ';'; poChar++)
         ;
     if (*poChar == '\0')
         return;
diff --git a/ogr/ogrsf_frmts/vfk/vfkreader.cpp b/ogr/ogrsf_frmts/vfk/vfkreader.cpp
index f6376d6..1e3f6cd 100644
--- a/ogr/ogrsf_frmts/vfk/vfkreader.cpp
+++ b/ogr/ogrsf_frmts/vfk/vfkreader.cpp
@@ -40,7 +40,7 @@
 
 #include "ogr_geometry.h"
 
-CPL_CVSID("$Id: vfkreader.cpp 35911 2016-10-24 15:03:26Z goatbar $");
+CPL_CVSID("$Id: vfkreader.cpp 38376 2017-05-15 11:16:16Z rouault $");
 
 static char *GetDataBlockName(const char *);
 
@@ -293,6 +293,7 @@ int VFKReader::ReadDataRecords(IVFKDataBlock *poDataBlock)
                     CPLFree(pszLine);
 
                     while ((pszLine = ReadLine()) != NULL &&
+                           pszLine[0] != '\0' &&
                            pszLine[strlen(pszLine) - 1] == '\244') {
                         /* append line */
                         osMultiLine += pszLine;
diff --git a/port/cpl_config.h.in b/port/cpl_config.h.in
index 383fde1..0ddde8e 100644
--- a/port/cpl_config.h.in
+++ b/port/cpl_config.h.in
@@ -1,5 +1,5 @@
 /* port/cpl_config.h.in.  Generated from configure.in by autoheader.  */
-/* $Id: cpl_config.h.in 36873 2016-12-15 01:53:11Z rouault $ */
+/* $Id: cpl_config.h.in 38508 2017-05-20 09:35:37Z rouault $ */
 
 /* Define if you want to use pthreads based multiprocessing support */
 #undef CPL_MULTIPROC_PTHREAD
@@ -258,3 +258,6 @@
 
 /* Define to 1 if you have the `uselocale' function. */
 #undef HAVE_USELOCALE
+
+/* Define to 1 if you have the `std::isnan' function. */
+#undef HAVE_STD_IS_NAN
diff --git a/port/cpl_error.cpp b/port/cpl_error.cpp
index 2182bb8..68bed85 100644
--- a/port/cpl_error.cpp
+++ b/port/cpl_error.cpp
@@ -46,7 +46,7 @@
 #define TIMESTAMP_DEBUG
 // #define MEMORY_DEBUG
 
-CPL_CVSID("$Id: cpl_error.cpp 37003 2016-12-23 14:54:07Z goatbar $");
+CPL_CVSID("$Id: cpl_error.cpp 38237 2017-05-13 10:04:44Z rouault $");
 
 static CPLMutex *hErrorMutex = NULL;
 static void *pErrorHandlerUserData = NULL;
@@ -711,10 +711,10 @@ void CPL_DLL CPLErrorSetState( CPLErr eErrClass, CPLErrorNum err_no,
     }
 
     psCtx->nLastErrNo = err_no;
-    strncpy(psCtx->szLastErrMsg, pszMsg, psCtx->nLastErrMsgMax);
-    psCtx->szLastErrMsg[
-        std::max(psCtx->nLastErrMsgMax-1,
-                 static_cast<int>( strlen(pszMsg) ))] = '\0';
+    const size_t size = std::min(
+        static_cast<size_t>(psCtx->nLastErrMsgMax-1), strlen(pszMsg) );
+    strncpy( psCtx->szLastErrMsg, pszMsg, size );
+    psCtx->szLastErrMsg[size] = '\0';
     psCtx->eLastErrType = eErrClass;
 }
 
diff --git a/port/cpl_minixml.cpp b/port/cpl_minixml.cpp
index b078f3d..a208769 100644
--- a/port/cpl_minixml.cpp
+++ b/port/cpl_minixml.cpp
@@ -53,7 +53,7 @@
 #include "cpl_string.h"
 #include "cpl_vsi.h"
 
-CPL_CVSID("$Id: cpl_minixml.cpp 37918 2017-04-07 17:05:53Z rouault $");
+CPL_CVSID("$Id: cpl_minixml.cpp 38510 2017-05-20 10:10:29Z rouault $");
 
 typedef enum {
     TNone,
@@ -190,7 +190,7 @@ static CPL_INLINE bool _AddToToken( ParseContext *psContext, char chNewChar )
 /*                             ReadToken()                              */
 /************************************************************************/
 
-static XMLTokenType ReadToken( ParseContext *psContext )
+static XMLTokenType ReadToken( ParseContext *psContext, CPLErr& eLastErrorType )
 
 {
     psContext->nTokenSize = 0;
@@ -238,7 +238,8 @@ static XMLTokenType ReadToken( ParseContext *psContext )
             chNext = ReadChar(psContext);
             if( chNext == '\0' )
             {
-                CPLError( CE_Failure, CPLE_AppDefined,
+                eLastErrorType = CE_Failure;
+                CPLError( eLastErrorType, CPLE_AppDefined,
                           "Parse error in DOCTYPE on or before line %d, "
                           "reached end of file without '>'.",
                           psContext->nInputLine );
@@ -270,7 +271,8 @@ static XMLTokenType ReadToken( ParseContext *psContext )
 
                 if( chNext == '\0' )
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined,
+                    eLastErrorType = CE_Failure;
+                    CPLError( eLastErrorType, CPLE_AppDefined,
                               "Parse error in DOCTYPE on or before line %d, "
                               "reached end of file without ']'.",
                           psContext->nInputLine );
@@ -388,8 +390,8 @@ static XMLTokenType ReadToken( ParseContext *psContext )
         if( chNext != '"' )
         {
             psContext->eTokenType = TNone;
-            CPLError(
-                CE_Failure, CPLE_AppDefined,
+            eLastErrorType = CE_Failure;
+            CPLError( eLastErrorType, CPLE_AppDefined,
                 "Parse error on line %d, reached EOF before closing quote.",
                 psContext->nInputLine);
         }
@@ -416,8 +418,8 @@ static XMLTokenType ReadToken( ParseContext *psContext )
         if( chNext != '\'' )
         {
             psContext->eTokenType = TNone;
-            CPLError(
-                CE_Failure, CPLE_AppDefined,
+            eLastErrorType = CE_Failure;
+            CPLError( eLastErrorType, CPLE_AppDefined,
                 "Parse error on line %d, reached EOF before closing quote.",
                 psContext->nInputLine);
         }
@@ -497,7 +499,8 @@ fail:
 /*                              PushNode()                              */
 /************************************************************************/
 
-static bool PushNode( ParseContext *psContext, CPLXMLNode *psNode )
+static bool PushNode( ParseContext *psContext, CPLXMLNode *psNode,
+                      CPLErr& eLastErrorType )
 
 {
     if( psContext->nStackMaxSize <= psContext->nStackSize )
@@ -505,6 +508,7 @@ static bool PushNode( ParseContext *psContext, CPLXMLNode *psNode )
         // Somewhat arbitrary number.
         if( psContext->nStackMaxSize >= 10000 )
         {
+            eLastErrorType = CE_Failure;
             CPLError(CE_Failure, CPLE_NotSupported,
                      "XML element depth beyond 10000. Giving up");
             VSIFree(psContext->papsStack);
@@ -518,6 +522,7 @@ static bool PushNode( ParseContext *psContext, CPLXMLNode *psNode )
                        sizeof(StackContext) * psContext->nStackMaxSize));
         if( papsStack == NULL )
         {
+            eLastErrorType = CE_Failure;
             CPLError(CE_Failure, CPLE_OutOfMemory,
                      "Out of memory allocating %d bytes",
                      static_cast<int>(sizeof(StackContext)) *
@@ -659,19 +664,25 @@ CPLXMLNode *CPLParseXMLString( const char *pszString )
     sContext.psFirstNode = NULL;
     sContext.psLastNode = NULL;
 
+#ifdef DEBUG
+    bool bRecoverableError = true;
+#endif
+    CPLErr eLastErrorType = CE_None;
+
 /* ==================================================================== */
 /*      Loop reading tokens.                                            */
 /* ==================================================================== */
-    while( ReadToken( &sContext ) != TNone )
+    while( ReadToken( &sContext, eLastErrorType ) != TNone )
     {
 /* -------------------------------------------------------------------- */
 /*      Create a new element.                                           */
 /* -------------------------------------------------------------------- */
         if( sContext.eTokenType == TOpen )
         {
-            if( ReadToken(&sContext) != TToken )
+            if( ReadToken(&sContext, eLastErrorType) != TToken )
             {
-                CPLError( CE_Failure, CPLE_AppDefined,
+                eLastErrorType = CE_Failure;
+                CPLError( eLastErrorType, CPLE_AppDefined,
                           "Line %d: Didn't find element token after "
                           "open angle bracket.",
                           sContext.nInputLine );
@@ -685,7 +696,7 @@ CPLXMLNode *CPLParseXMLString( const char *pszString )
                                               sContext.pszToken );
                 if( !psElement ) break;
                 AttachNode( &sContext, psElement );
-                if( !PushNode( &sContext, psElement ) )
+                if( !PushNode( &sContext, psElement, eLastErrorType ) )
                     break;
             }
             else
@@ -701,8 +712,9 @@ CPLXMLNode *CPLParseXMLString( const char *pszString )
                     if( CPLTestBool(CPLGetConfigOption("CPL_MINIXML_RELAXED",
                                                        "FALSE")) )
                     {
+                        eLastErrorType = CE_Warning;
                         CPLError(
-                            CE_Warning, CPLE_AppDefined,
+                            eLastErrorType, CPLE_AppDefined,
                             "Line %d: <%.500s> doesn't have matching <%.500s>.",
                             sContext.nInputLine,
                             sContext.pszToken, sContext.pszToken + 1 );
@@ -713,8 +725,9 @@ CPLXMLNode *CPLParseXMLString( const char *pszString )
                     else
 #endif
                     {
+                        eLastErrorType = CE_Failure;
                         CPLError(
-                            CE_Failure, CPLE_AppDefined,
+                            eLastErrorType, CPLE_AppDefined,
                             "Line %d: <%.500s> doesn't have matching <%.500s>.",
                             sContext.nInputLine,
                             sContext.pszToken, sContext.pszToken + 1 );
@@ -729,8 +742,9 @@ CPLXMLNode *CPLParseXMLString( const char *pszString )
                     {
                         // TODO: At some point we could just error out like any
                         // other sane XML parser would do.
+                        eLastErrorType = CE_Warning;
                         CPLError(
-                            CE_Warning, CPLE_AppDefined,
+                            eLastErrorType, CPLE_AppDefined,
                             "Line %d: <%.500s> matches <%.500s>, but the case "
                             "isn't the same.  Going on, but this is invalid "
                             "XML that might be rejected in future versions.",
@@ -742,9 +756,10 @@ CPLXMLNode *CPLParseXMLString( const char *pszString )
 #ifdef DEBUG
 end_processing_close:
 #endif
-                    if( ReadToken(&sContext) != TClose )
+                    if( ReadToken(&sContext, eLastErrorType) != TClose )
                     {
-                        CPLError( CE_Failure, CPLE_AppDefined,
+                        eLastErrorType = CE_Failure;
+                        CPLError( eLastErrorType, CPLE_AppDefined,
                                   "Line %d: Missing close angle bracket "
                                   "after <%.500s.",
                                   sContext.nInputLine,
@@ -768,7 +783,7 @@ end_processing_close:
             if( !psAttr ) break;
             AttachNode( &sContext, psAttr );
 
-            if( ReadToken(&sContext) != TEqual )
+            if( ReadToken(&sContext, eLastErrorType) != TEqual )
             {
                 // Parse stuff like <?valbuddy_schematron
                 // ../wmtsSimpleGetCapabilities.sch?>
@@ -800,18 +815,25 @@ end_processing_close:
                     continue;
                 }
 
-                CPLError( CE_Failure, CPLE_AppDefined,
+                eLastErrorType = CE_Failure;
+                CPLError( eLastErrorType, CPLE_AppDefined,
                           "Line %d: Didn't find expected '=' for value of "
                           "attribute '%.500s'.",
                           sContext.nInputLine, psAttr->pszValue );
+#ifdef DEBUG
+                // Accepting an attribute without child text
+                // would break too much assumptions in driver code
+                bRecoverableError = false;
+#endif
                 break;
             }
 
-            if( ReadToken(&sContext) == TToken )
+            if( ReadToken(&sContext, eLastErrorType) == TToken )
             {
                 /* TODO: at some point we could just error out like any other */
                 /* sane XML parser would do */
-                CPLError( CE_Warning, CPLE_AppDefined,
+                eLastErrorType = CE_Warning;
+                CPLError( eLastErrorType, CPLE_AppDefined,
                           "Line %d: Attribute value should be single or double "
                           "quoted.  Going on, but this is invalid XML that "
                           "might be rejected in future versions.",
@@ -819,9 +841,15 @@ end_processing_close:
             }
             else if( sContext.eTokenType != TString )
             {
-                CPLError( CE_Failure, CPLE_AppDefined,
+                eLastErrorType = CE_Failure;
+                CPLError( eLastErrorType, CPLE_AppDefined,
                           "Line %d: Didn't find expected attribute value.",
                           sContext.nInputLine );
+#ifdef DEBUG
+                // Accepting an attribute without child text
+                // would break too much assumptions in driver code
+                bRecoverableError = false;
+#endif
                 break;
             }
 
@@ -836,7 +864,8 @@ end_processing_close:
         {
             if( sContext.nStackSize == 0 )
             {
-                CPLError( CE_Failure, CPLE_AppDefined,
+                eLastErrorType = CE_Failure;
+                CPLError( eLastErrorType, CPLE_AppDefined,
                           "Line %d: Found unbalanced '>'.",
                           sContext.nInputLine );
                 break;
@@ -851,7 +880,8 @@ end_processing_close:
         {
             if( sContext.nStackSize == 0 )
             {
-                CPLError( CE_Failure, CPLE_AppDefined,
+                eLastErrorType = CE_Failure;
+                CPLError( eLastErrorType, CPLE_AppDefined,
                           "Line %d: Found unbalanced '/>'.",
                           sContext.nInputLine );
                 break;
@@ -867,7 +897,8 @@ end_processing_close:
         {
             if( sContext.nStackSize == 0 )
             {
-                CPLError( CE_Failure, CPLE_AppDefined,
+                eLastErrorType = CE_Failure;
+                CPLError( eLastErrorType, CPLE_AppDefined,
                           "Line %d: Found unbalanced '?>'.",
                           sContext.nInputLine );
                 break;
@@ -875,7 +906,8 @@ end_processing_close:
             else if( sContext.papsStack[sContext.nStackSize-1].
                          psFirstNode->pszValue[0] != '?' )
             {
-                CPLError( CE_Failure, CPLE_AppDefined,
+                eLastErrorType = CE_Failure;
+                CPLError( eLastErrorType, CPLE_AppDefined,
                           "Line %d: Found '?>' without matching '<?'.",
                           sContext.nInputLine );
                 break;
@@ -920,7 +952,8 @@ end_processing_close:
 /* -------------------------------------------------------------------- */
         else
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
+            eLastErrorType = CE_Failure;
+            CPLError( eLastErrorType, CPLE_AppDefined,
                       "Parse error at line %d, unexpected token:%.500s",
                       sContext.nInputLine, sContext.pszToken );
             break;
@@ -936,23 +969,21 @@ end_processing_close:
 #ifdef DEBUG
         // Makes life of fuzzers easier if we accept somewhat corrupted XML
         // like <x> ...
-        if( CPLTestBool(CPLGetConfigOption("CPL_MINIXML_RELAXED", "FALSE")) )
+        if( bRecoverableError &&
+            CPLTestBool(CPLGetConfigOption("CPL_MINIXML_RELAXED", "FALSE")) )
         {
-            CPLError(CE_Warning, CPLE_AppDefined,
-                     "Parse error at EOF, not all elements have been closed, "
-                     "starting with %.500s",
-                     sContext.papsStack[sContext.nStackSize-1].
-                         psFirstNode->pszValue );
+            eLastErrorType = CE_Warning;
         }
         else
 #endif
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Parse error at EOF, not all elements have been closed, "
-                      "starting with %.500s",
-                      sContext.papsStack[sContext.nStackSize-1].
-                          psFirstNode->pszValue );
+            eLastErrorType = CE_Failure;
         }
+        CPLError( eLastErrorType, CPLE_AppDefined,
+                    "Parse error at EOF, not all elements have been closed, "
+                    "starting with %.500s",
+                    sContext.papsStack[sContext.nStackSize-1].
+                        psFirstNode->pszValue );
     }
 
 /* -------------------------------------------------------------------- */
@@ -962,14 +993,16 @@ end_processing_close:
     if( sContext.papsStack != NULL )
         CPLFree( sContext.papsStack );
 
-    if( CPLGetLastErrorType() == CE_Failure )
+    // We do not trust CPLGetLastErrorType() as if CPLTurnFailureIntoWarning()
+    // has been set we would never get failures
+    if( eLastErrorType == CE_Failure )
     {
         CPLDestroyXMLNode( sContext.psFirstNode );
         sContext.psFirstNode = NULL;
         sContext.psLastNode = NULL;
     }
 
-    if( CPLGetLastErrorType() == CE_None )
+    if( eLastErrorType == CE_None )
     {
         // Restore initial error state.
         CPLErrorSetState(eErrClass, nErrNum, osErrMsg);
diff --git a/port/cpl_port.h b/port/cpl_port.h
index f4f910f..ec9c496 100644
--- a/port/cpl_port.h
+++ b/port/cpl_port.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_port.h 37456 2017-02-25 18:35:03Z rouault $
+ * $Id: cpl_port.h 38517 2017-05-20 11:35:37Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Author:   Frank Warmerdam, warmerdam at pobox.com
@@ -653,10 +653,11 @@ static inline char* CPL_afl_friendly_strstr(const char* haystack, const char* ne
 #  define CPLIsNan(x) _isnan(x)
 #  define CPLIsInf(x) (!_isnan(x) && !_finite(x))
 #  define CPLIsFinite(x) _finite(x)
-#elif defined(__cplusplus) && defined(__MINGW32__) &&  __GNUC__ == 4 && __GNUC_MINOR__ == 2
-/* Hack for compatibility with ancient i586-mingw32msvc toolchain */
+#elif defined(__cplusplus) && defined(HAVE_STD_IS_NAN) && HAVE_STD_IS_NAN
 extern "C++" {
+#ifndef DOXYGEN_SKIP
 #include <cmath>
+#endif
 static inline int CPLIsNan(float f) { return std::isnan(f); }
 static inline int CPLIsNan(double f) { return std::isnan(f); }
 static inline int CPLIsInf(float f) { return std::isinf(f); }
diff --git a/port/cpl_string.cpp b/port/cpl_string.cpp
index aee5c88..cf386b1 100644
--- a/port/cpl_string.cpp
+++ b/port/cpl_string.cpp
@@ -59,7 +59,7 @@
 #include "cpl_multiproc.h"
 #include "cpl_vsi.h"
 
-CPL_CVSID("$Id: cpl_string.cpp 37457 2017-02-25 18:57:53Z rouault $");
+CPL_CVSID("$Id: cpl_string.cpp 38379 2017-05-15 11:25:22Z rouault $");
 
 /*=====================================================================
                     StringList manipulation functions.
@@ -2497,14 +2497,15 @@ static const unsigned char hex2char[256] = {
 
 GByte *CPLHexToBinary( const char *pszHex, int *pnBytes )
 {
+    const GByte* pabyHex = reinterpret_cast<const GByte*>(pszHex);
     const size_t nHexLen = strlen(pszHex);
 
     GByte *pabyWKB = static_cast<GByte *>( CPLMalloc(nHexLen / 2 + 2) );
 
     for( size_t i = 0; i < nHexLen/2; ++i )
     {
-        const unsigned char h1 = hex2char[static_cast<int>( pszHex[2*i] )];
-        const unsigned char h2 = hex2char[static_cast<int>( pszHex[2*i+1] )];
+        const unsigned char h1 = hex2char[pabyHex[2*i]];
+        const unsigned char h2 = hex2char[pabyHex[2*i+1]];
 
         // First character is high bits, second is low bits.
         pabyWKB[i] = static_cast<GByte>( (h1 << 4) | h2 );
diff --git a/port/cpl_time.cpp b/port/cpl_time.cpp
index b3b10ee..c9753dc 100644
--- a/port/cpl_time.cpp
+++ b/port/cpl_time.cpp
@@ -27,7 +27,7 @@
 
 #include "cpl_error.h"
 
-CPL_CVSID("$Id: cpl_time.cpp 36928 2016-12-17 06:12:35Z goatbar $");
+CPL_CVSID("$Id: cpl_time.cpp 39087 2017-06-12 20:17:14Z rouault $");
 
 static const int SECSPERMIN = 60;
 static const int MINSPERHOUR = 60;
@@ -111,8 +111,10 @@ struct tm * CPLUnixTimeToYMDHMS(GIntBig unixTime, struct tm* pRet)
 
     int y = EPOCH_YEAR;
     int yleap = 0;
-    while( days < 0
-           || days >= static_cast<GIntBig>( year_lengths[yleap = isleap(y)] ) )
+    int iters = 0;
+    while( iters < 1000 &&
+           (days < 0
+           || days >= static_cast<GIntBig>( year_lengths[yleap = isleap(y)] )) )
     {
         int newy = y + static_cast<int>( days / DAYSPERNYEAR );
         if( days < 0 )
@@ -121,6 +123,15 @@ struct tm * CPLUnixTimeToYMDHMS(GIntBig unixTime, struct tm* pRet)
             LEAPS_THROUGH_END_OF(newy - 1) -
             LEAPS_THROUGH_END_OF(y - 1);
         y = newy;
+        iters ++;
+    }
+    if( iters == 1000 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Invalid unixTime = " CPL_FRMT_GIB,
+                 unixTime);
+        memset(pRet, 0, sizeof(*pRet));
+        return pRet;
     }
 
     pRet->tm_year = static_cast<int>( y - TM_YEAR_BASE );
diff --git a/port/cpl_vsi.h b/port/cpl_vsi.h
index 94e5e64..e8a4e3b 100644
--- a/port/cpl_vsi.h
+++ b/port/cpl_vsi.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_vsi.h 37640 2017-03-07 15:20:35Z rouault $
+ * $Id: cpl_vsi.h 39224 2017-06-21 08:50:19Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Author:   Frank Warmerdam, warmerdam at pobox.com
@@ -306,6 +306,7 @@ void CPL_DLL VSIInstallLargeFileHandler(void);
 /*! @endcond */
 void CPL_DLL VSIInstallSubFileHandler(void);
 void VSIInstallCurlFileHandler(void);
+void CPL_DLL VSICurlClearCache(void);
 void VSIInstallCurlStreamingFileHandler(void);
 void VSIInstallS3FileHandler(void);
 void VSIInstallS3StreamingFileHandler(void);
diff --git a/port/cpl_vsil.cpp b/port/cpl_vsil.cpp
index 8d1e2c6..35d026c 100644
--- a/port/cpl_vsil.cpp
+++ b/port/cpl_vsil.cpp
@@ -53,7 +53,7 @@
 #include "cpl_vsi_virtual.h"
 
 
-CPL_CVSID("$Id: cpl_vsil.cpp 37640 2017-03-07 15:20:35Z rouault $");
+CPL_CVSID("$Id: cpl_vsil.cpp 38421 2017-05-16 17:09:42Z rouault $");
 
 /************************************************************************/
 /*                             VSIReadDir()                             */
@@ -1388,7 +1388,8 @@ int VSIIngestFile( VSILFILE* fp,
 
         // With "large" VSI I/O API we can read data chunks larger than
         // VSIMalloc could allocate. Catch it here.
-        if( nDataLen > static_cast<vsi_l_offset>(static_cast<size_t>(nDataLen))
+        if( nDataLen != static_cast<vsi_l_offset>(static_cast<size_t>(nDataLen))
+            || nDataLen + 1 < nDataLen
             || (nMaxSize >= 0 &&
                 nDataLen > static_cast<vsi_l_offset>(nMaxSize)) )
         {
diff --git a/port/cpl_vsil_abstract_archive.cpp b/port/cpl_vsil_abstract_archive.cpp
index 96fdbbd..c74c40f 100644
--- a/port/cpl_vsil_abstract_archive.cpp
+++ b/port/cpl_vsil_abstract_archive.cpp
@@ -48,7 +48,7 @@
 
 //! @cond Doxygen_Suppress
 
-CPL_CVSID("$Id: cpl_vsil_abstract_archive.cpp 37597 2017-03-04 17:27:00Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_abstract_archive.cpp 38389 2017-05-15 12:23:59Z rouault $");
 
 static bool IsEitherSlash( char c )
 {
@@ -457,9 +457,9 @@ char* VSIArchiveFilesystemHandler::SplitFilename( const char *pszFilename,
     else
         pszFilename += strlen(GetPrefix()) + 1;
 
+    const std::vector<CPLString> oExtensions = GetExtensions();
     while( pszFilename[i] )
     {
-        const std::vector<CPLString> oExtensions = GetExtensions();
         int nToSkip = 0;
 
         for( std::vector<CPLString>::const_iterator iter = oExtensions.begin();
diff --git a/port/cpl_vsil_curl.cpp b/port/cpl_vsil_curl.cpp
index 2b4ebb0..922543b 100644
--- a/port/cpl_vsil_curl.cpp
+++ b/port/cpl_vsil_curl.cpp
@@ -42,7 +42,7 @@
 #include "cpl_vsi_virtual.h"
 #include "cpl_http.h"
 
-CPL_CVSID("$Id: cpl_vsil_curl.cpp 37987 2017-04-14 07:42:50Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_curl.cpp 39224 2017-06-21 08:50:19Z rouault $");
 
 #ifndef HAVE_CURL
 
@@ -61,6 +61,11 @@ void VSIInstallGSFileHandler( void )
     // Not supported.
 }
 
+void VSICurlClearCache( void )
+{
+    // Not supported.
+}
+
 /************************************************************************/
 /*                      VSICurlInstallReadCbk()                         */
 /************************************************************************/
@@ -329,6 +334,8 @@ public:
                                                 vsi_l_offset nFileOffsetStart );
 
     CURL               *GetCurlHandleFor( CPLString osURL );
+
+    void                ClearCache();
 };
 
 /************************************************************************/
@@ -1373,6 +1380,19 @@ size_t VSICurlHandle::Read( void * const pBufferIn, size_t const nSize,
     vsi_l_offset iterOffset = curOffset;
     while( nBufferRequestSize )
     {
+        // Don't try to read after end of file.
+        CachedFileProp* cachedFileProp = poFS->GetCachedFileProp(m_pszURL);
+        if( cachedFileProp->bHasComputedFileSize &&
+            iterOffset >= cachedFileProp->fileSize )
+        {
+            if( iterOffset == curOffset )
+            {
+                CPLDebug("VSICURL", "Request at offset " CPL_FRMT_GUIB
+                         ", after end of file", iterOffset);
+            }
+            break;
+        }
+
         const CachedRegion* psRegion = poFS->GetRegion(m_pszURL, iterOffset);
         if( psRegion == NULL )
         {
@@ -1901,40 +1921,7 @@ VSICurlFilesystemHandler::VSICurlFilesystemHandler()
 
 VSICurlFilesystemHandler::~VSICurlFilesystemHandler()
 {
-    for( int i=0; i < nRegions; i++ )
-    {
-        CPLFree(papsRegions[i]->pData);
-        CPLFree(papsRegions[i]);
-    }
-    CPLFree(papsRegions);
-
-    std::map<CPLString, CachedFileProp*>::const_iterator iterCacheFileSize;
-
-    for( iterCacheFileSize = cacheFileSize.begin();
-         iterCacheFileSize != cacheFileSize.end();
-         ++iterCacheFileSize )
-    {
-        delete iterCacheFileSize->second;
-    }
-
-    std::map<CPLString, CachedDirList*>::const_iterator iterCacheDirList;
-
-    for( iterCacheDirList = cacheDirList.begin();
-         iterCacheDirList != cacheDirList.end();
-         ++iterCacheDirList )
-    {
-        CSLDestroy(iterCacheDirList->second->papszFileList);
-        CPLFree(iterCacheDirList->second);
-    }
-
-    std::map<GIntBig, CachedConnection*>::const_iterator iterConnections;
-    for( iterConnections = mapConnections.begin();
-         iterConnections != mapConnections.end();
-         ++iterConnections )
-    {
-        curl_easy_cleanup(iterConnections->second->hCurlHandle);
-        delete iterConnections->second;
-    }
+    ClearCache();
 
     if( hMutex != NULL )
         CPLDestroyMutex( hMutex );
@@ -2222,6 +2209,53 @@ void VSICurlFilesystemHandler::InvalidateCachedFileProp( const char* pszURL )
 }
 
 /************************************************************************/
+/*                            ClearCache()                              */
+/************************************************************************/
+
+void VSICurlFilesystemHandler::ClearCache()
+{
+    CPLMutexHolder oHolder( &hMutex );
+
+    for( int i=0; i < nRegions; i++ )
+    {
+        CPLFree(papsRegions[i]->pData);
+        CPLFree(papsRegions[i]);
+    }
+    CPLFree(papsRegions);
+    nRegions = 0;
+    papsRegions = NULL;
+
+    std::map<CPLString, CachedFileProp*>::const_iterator iterCacheFileSize;
+    for( iterCacheFileSize = cacheFileSize.begin();
+         iterCacheFileSize != cacheFileSize.end();
+         ++iterCacheFileSize )
+    {
+        delete iterCacheFileSize->second;
+    }
+    cacheFileSize.clear();
+
+    std::map<CPLString, CachedDirList*>::const_iterator iterCacheDirList;
+    for( iterCacheDirList = cacheDirList.begin();
+         iterCacheDirList != cacheDirList.end();
+         ++iterCacheDirList )
+    {
+        CSLDestroy(iterCacheDirList->second->papszFileList);
+        CPLFree(iterCacheDirList->second);
+    }
+    cacheDirList.clear();
+
+    std::map<GIntBig, CachedConnection*>::const_iterator iterConnections;
+    for( iterConnections = mapConnections.begin();
+         iterConnections != mapConnections.end();
+         ++iterConnections )
+    {
+        curl_easy_cleanup(iterConnections->second->hCurlHandle);
+        delete iterConnections->second;
+    }
+    mapConnections.clear();
+}
+
+/************************************************************************/
 /*                          CreateFileHandle()                          */
 /************************************************************************/
 
@@ -2295,6 +2329,9 @@ VSIVirtualHandle* VSICurlFilesystemHandler::Open( const char *pszFilename,
                                                   const char *pszAccess,
                                                   bool bSetError )
 {
+    if( !STARTS_WITH_CI(pszFilename, GetFSPrefix()) )
+        return NULL;
+
     if( strchr(pszAccess, 'w') != NULL ||
         strchr(pszAccess, '+') != NULL )
     {
@@ -3291,6 +3328,9 @@ int VSICurlFilesystemHandler::Stat( const char *pszFilename,
                                     VSIStatBufL *pStatBuf,
                                     int nFlags )
 {
+    if( !STARTS_WITH_CI(pszFilename, GetFSPrefix()) )
+        return -1;
+
     const CPLString osFilename(pszFilename);
 
     memset(pStatBuf, 0, sizeof(VSIStatBufL));
@@ -4172,6 +4212,9 @@ VSIVirtualHandle* VSIS3FSHandler::Open( const char *pszFilename,
                                         const char *pszAccess,
                                         bool bSetError)
 {
+    if( !STARTS_WITH_CI(pszFilename, GetFSPrefix()) )
+        return NULL;
+
     if( strchr(pszAccess, 'w') != NULL || strchr(pszAccess, 'a') != NULL )
     {
         /*if( strchr(pszAccess, '+') != NULL)
@@ -4207,6 +4250,9 @@ VSIVirtualHandle* VSIS3FSHandler::Open( const char *pszFilename,
 int VSIS3FSHandler::Stat( const char *pszFilename, VSIStatBufL *pStatBuf,
                           int nFlags )
 {
+    if( !STARTS_WITH_CI(pszFilename, GetFSPrefix()) )
+        return -1;
+
     CPLString osFilename(pszFilename);
     if( osFilename.find('/', GetFSPrefix().size()) == std::string::npos )
         osFilename += "/";
@@ -5015,4 +5061,29 @@ void VSIInstallGSFileHandler( void )
     VSIFileManager::InstallHandler( "/vsigs/", new VSIGSFSHandler );
 }
 
+/************************************************************************/
+/*                         VSICurlClearCache()                          */
+/************************************************************************/
+
+/**
+ * \brief Clean local cache associated with /vsicurl/ (and related file systems)
+ *
+ * /vsicurl (and related file systems like /vsis3/ , /vsigs/) cache a number of
+ * metadata and data for faster execution in read-only scenarios. But when the
+ * content on the server-side may change during the same process, those
+ * mechanisms can prevent opening new files, or give an outdated version of them.
+ *
+ * @since GDAL 2.2.1
+ */
+
+void VSICurlClearCache( void )
+{
+    VSICurlFilesystemHandler *poFSHandler =
+        dynamic_cast<VSICurlFilesystemHandler*>(
+            VSIFileManager::GetHandler( "/vsis3/" ));
+
+    if( poFSHandler )
+        poFSHandler->ClearCache();
+}
+
 #endif /* HAVE_CURL */
diff --git a/port/cpl_vsil_curl_streaming.cpp b/port/cpl_vsil_curl_streaming.cpp
index 3dc3e28..1b2e6d6 100644
--- a/port/cpl_vsil_curl_streaming.cpp
+++ b/port/cpl_vsil_curl_streaming.cpp
@@ -41,7 +41,7 @@
 #include "cpl_string.h"
 #include "cpl_time.h"
 
-CPL_CVSID("$Id: cpl_vsil_curl_streaming.cpp 37645 2017-03-08 00:15:33Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_curl_streaming.cpp 38248 2017-05-13 12:58:34Z rouault $");
 
 #if !defined(HAVE_CURL) || defined(CPL_MULTIPROC_STUB)
 
@@ -1588,6 +1588,9 @@ VSIVirtualHandle* VSICurlStreamingFSHandler::Open( const char *pszFilename,
                                                    const char *pszAccess,
                                                    bool /* bSetError */ )
 {
+    if( !STARTS_WITH_CI(pszFilename, GetFSPrefix()) )
+        return NULL;
+
     if( strchr(pszAccess, 'w') != NULL ||
         strchr(pszAccess, '+') != NULL )
     {
@@ -1620,6 +1623,9 @@ int VSICurlStreamingFSHandler::Stat( const char *pszFilename,
                                      VSIStatBufL *pStatBuf,
                                      int nFlags )
 {
+    if( !STARTS_WITH_CI(pszFilename, GetFSPrefix()) )
+        return -1;
+
     CPLString osFilename(pszFilename);
 
     memset(pStatBuf, 0, sizeof(VSIStatBufL));
diff --git a/port/cpl_vsil_gzip.cpp b/port/cpl_vsil_gzip.cpp
index 2889842..a39f173 100644
--- a/port/cpl_vsil_gzip.cpp
+++ b/port/cpl_vsil_gzip.cpp
@@ -108,7 +108,7 @@
 #include "cpl_vsi_virtual.h"
 
 
-CPL_CVSID("$Id: cpl_vsil_gzip.cpp 36990 2016-12-21 19:42:05Z goatbar $");
+CPL_CVSID("$Id: cpl_vsil_gzip.cpp 38248 2017-05-13 12:58:34Z rouault $");
 
 static const int Z_BUFSIZE = 65536;  // Original size is 16384
 static const int gz_magic[2] = {0x1f, 0x8b};  // gzip magic header
@@ -1531,6 +1531,9 @@ VSIVirtualHandle* VSIGZipFilesystemHandler::Open( const char *pszFilename,
                                                   const char *pszAccess,
                                                   bool /* bSetError */ )
 {
+    if( !STARTS_WITH_CI(pszFilename, "/vsigzip/") )
+        return NULL;
+
     VSIFilesystemHandler *poFSHandler =
         VSIFileManager::GetHandler( pszFilename + strlen("/vsigzip/"));
 
@@ -1635,6 +1638,9 @@ int VSIGZipFilesystemHandler::Stat( const char *pszFilename,
                                     VSIStatBufL *pStatBuf,
                                     int nFlags )
 {
+    if( !STARTS_WITH_CI(pszFilename, "/vsigzip/") )
+        return -1;
+
     CPLMutexHolder oHolder(&hMutex);
 
     memset(pStatBuf, 0, sizeof(VSIStatBufL));
diff --git a/port/cpl_vsil_sparsefile.cpp b/port/cpl_vsil_sparsefile.cpp
index d996f20..0cb6e85 100644
--- a/port/cpl_vsil_sparsefile.cpp
+++ b/port/cpl_vsil_sparsefile.cpp
@@ -51,7 +51,7 @@
 #include "cpl_string.h"
 #include "cpl_vsi_virtual.h"
 
-CPL_CVSID("$Id: cpl_vsil_sparsefile.cpp 36990 2016-12-21 19:42:05Z goatbar $");
+CPL_CVSID("$Id: cpl_vsil_sparsefile.cpp 38248 2017-05-13 12:58:34Z rouault $");
 
 class SFRegion {
 public:
@@ -358,7 +358,8 @@ VSISparseFileFilesystemHandler::Open( const char *pszFilename,
                                       bool /* bSetError */ )
 
 {
-    CPLAssert( STARTS_WITH_CI(pszFilename, "/vsisparse/") );
+    if( !STARTS_WITH_CI(pszFilename, "/vsisparse/") )
+        return NULL;
 
     if( !EQUAL(pszAccess, "r") && !EQUAL(pszAccess, "rb") )
     {
diff --git a/port/cpl_vsil_subfile.cpp b/port/cpl_vsil_subfile.cpp
index 4da0aa2..a37a41a 100644
--- a/port/cpl_vsil_subfile.cpp
+++ b/port/cpl_vsil_subfile.cpp
@@ -42,7 +42,7 @@
 #include "cpl_string.h"
 #include "cpl_vsi_virtual.h"
 
-CPL_CVSID("$Id: cpl_vsil_subfile.cpp 36990 2016-12-21 19:42:05Z goatbar $");
+CPL_CVSID("$Id: cpl_vsil_subfile.cpp 38421 2017-05-16 17:09:42Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -157,7 +157,10 @@ int VSISubFileHandle::Seek( vsi_l_offset nOffset, int nWhence )
 vsi_l_offset VSISubFileHandle::Tell()
 
 {
-    return VSIFTellL( fp ) - nSubregionOffset;
+    vsi_l_offset nBasePos = VSIFTellL( fp );
+    if( nBasePos >= nSubregionOffset )
+        return nBasePos - nSubregionOffset;
+    return 0;
 }
 
 /************************************************************************/
@@ -332,6 +335,9 @@ VSISubFileFilesystemHandler::Open( const char *pszFilename,
                                    bool /* bSetError */ )
 
 {
+    if( !STARTS_WITH_CI(pszFilename, "/vsisubfile/") )
+        return NULL;
+
     CPLString osSubFilePath;
     vsi_l_offset nOff = 0;
     vsi_l_offset nSize = 0;
@@ -384,6 +390,9 @@ int VSISubFileFilesystemHandler::Stat( const char * pszFilename,
                                        int nFlags )
 
 {
+    if( !STARTS_WITH_CI(pszFilename, "/vsisubfile/") )
+        return -1;
+
     CPLString osSubFilePath;
     vsi_l_offset nOff = 0;
     vsi_l_offset nSize = 0;
diff --git a/port/cpl_vsil_unix_stdio_64.cpp b/port/cpl_vsil_unix_stdio_64.cpp
index 05a6b02..5f06275 100644
--- a/port/cpl_vsil_unix_stdio_64.cpp
+++ b/port/cpl_vsil_unix_stdio_64.cpp
@@ -81,7 +81,7 @@
 #include "cpl_string.h"
 #include "cpl_vsi_error.h"
 
-CPL_CVSID("$Id: cpl_vsil_unix_stdio_64.cpp 36990 2016-12-21 19:42:05Z goatbar $");
+CPL_CVSID("$Id: cpl_vsil_unix_stdio_64.cpp 38821 2017-06-02 12:42:27Z rouault $");
 
 #if defined(UNIX_STDIO_64)
 
@@ -503,6 +503,7 @@ int VSIUnixStdioHandle::Truncate( vsi_l_offset nNewSize )
 #ifdef __linux
 #include <linux/fs.h> /* FS_IOC_FIEMAP */
 #ifdef FS_IOC_FIEMAP
+#include <linux/types.h> // for types used in linux/fiemap;h
 #include <linux/fiemap.h> /* struct fiemap */
 #endif
 #include <sys/ioctl.h>
diff --git a/swig/csharp/gdal/Gdal.cs b/swig/csharp/gdal/Gdal.cs
index 30f3924..7bdc551 100644
--- a/swig/csharp/gdal/Gdal.cs
+++ b/swig/csharp/gdal/Gdal.cs
@@ -350,6 +350,11 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
     return ret;
   }
 
+  public static void VSICurlClearCache() {
+    GdalPINVOKE.VSICurlClearCache();
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+  }
+
   public static string[] ParseCommandLine(string utf8_path) {
         /* %typemap(csout) char** CSL */
         IntPtr cPtr = GdalPINVOKE.ParseCommandLine(Gdal.StringToUtf8Bytes(utf8_path));
diff --git a/swig/csharp/gdal/GdalPINVOKE.cs b/swig/csharp/gdal/GdalPINVOKE.cs
index 6e854e3..fffc6e9 100644
--- a/swig/csharp/gdal/GdalPINVOKE.cs
+++ b/swig/csharp/gdal/GdalPINVOKE.cs
@@ -337,6 +337,9 @@ class GdalPINVOKE {
   [DllImport("gdal_wrap", EntryPoint="CSharp_VSIFWriteL")]
   public static extern int VSIFWriteL(string jarg1, int jarg2, int jarg3, IntPtr jarg4);
 
+  [DllImport("gdal_wrap", EntryPoint="CSharp_VSICurlClearCache")]
+  public static extern void VSICurlClearCache();
+
   [DllImport("gdal_wrap", EntryPoint="CSharp_ParseCommandLine")]
   public static extern IntPtr ParseCommandLine(byte[] jarg1);
 
diff --git a/swig/csharp/gdal/gdal_wrap.cpp b/swig/csharp/gdal/gdal_wrap.cpp
index 42f0722..c63d63b 100644
--- a/swig/csharp/gdal/gdal_wrap.cpp
+++ b/swig/csharp/gdal/gdal_wrap.cpp
@@ -3662,6 +3662,32 @@ SWIGEXPORT int SWIGSTDCALL CSharp_VSIFWriteL(char * jarg1, int jarg2, int jarg3,
 }
 
 
+SWIGEXPORT void SWIGSTDCALL CSharp_VSICurlClearCache() {
+  {
+    CPLErrorReset();
+    VSICurlClearCache();
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+}
+
+
 SWIGEXPORT void * SWIGSTDCALL CSharp_ParseCommandLine(char * jarg1) {
   void * jresult ;
   char *arg1 = (char *) 0 ;
diff --git a/swig/include/cpl.i b/swig/include/cpl.i
index 53959a8..bf33704 100644
--- a/swig/include/cpl.i
+++ b/swig/include/cpl.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl.i 37544 2017-03-01 18:36:56Z rouault $
+ * $Id: cpl.i 39224 2017-06-21 08:50:19Z rouault $
  *
  * Name:     cpl.i
  * Project:  GDAL Python Interface
@@ -583,6 +583,8 @@ void VSIStdoutUnsetRedirection()
 }
 #endif
 
+void VSICurlClearCache();
+
 #endif /* !defined(SWIGJAVA) */
 
 %apply (char **CSL) {char **};
diff --git a/swig/include/perl/band.i b/swig/include/perl/band.i
index b0eacf7..8ff96ea 100644
--- a/swig/include/perl/band.i
+++ b/swig/include/perl/band.i
@@ -3,7 +3,7 @@
 %header %{
   double NVClassify(int comparison, double nv, AV* classifier, const char **error) {
      /* recursive, return nv < classifier[0] ? classifier[1] : classifier[2]
-        returns error if there are not three values in the classifier,
+        sets error if there are not three values in the classifier,
         first is not a number, or second or third are not a number of arrayref
      */
      SV** f = av_fetch(classifier, 0, 0);
@@ -32,18 +32,15 @@
              return SvNV(*t);
          else if (t && SvROK(*t) && (SvTYPE(SvRV(*t)) == SVt_PVAV))
              return NVClassify(comparison, nv, (AV*)(SvRV(*t)), error);
-         else {
+         else
              *error = "The decision in a classifier must be a number or a reference to a classifier.";
-             return 0;
-         }
-     } else {
+     } else
          *error = "The first value in a classifier must be a number.";
-         return 0;
-     }
+     return 0;
   }
   void NVClass(int comparison, double nv, AV* classifier, int *klass, const char **error) {
-     /* recursive, return nv < classifier[0] ? classifier[1] : classifier[2]
-        returns NULL if there are not three values in the classifier,
+     /* recursive, return in klass nv < classifier[0] ? classifier[1] : classifier[2]
+        sets NULL if there are not three values in the classifier,
         first is not a number, or second or third are not a number of arrayref
      */
      SV** f = av_fetch(classifier, 0, 0);
@@ -77,14 +74,10 @@
              return;
          else if (t && SvROK(*t) && (SvTYPE(SvRV(*t)) == SVt_PVAV))
              NVClass(comparison, nv, (AV*)(SvRV(*t)), klass, error);
-         else {
+         else
              *error = "The decision in a classifier must be a number or a reference to a classifier.";
-             return;
-         }
-     } else {
+     } else
          *error = "The first value in a classifier must be a number.";
-         return;
-     }
   }
   AV* to_array_classifier(SV* classifier, int* comparison, const char **error) {
       if (SvROK(classifier) && (SvTYPE(SvRV(classifier)) == SVt_PVAV)) {
@@ -100,16 +93,18 @@
                   *comparison = 2;
               else if (strcmp(c, ">=") == 0)
                   *comparison = 3;
-              else
+              else {
                   *error = "The first element in classifier object must be a comparison.";
+                  return NULL;
+              }
           }
           if (s && SvROK(*s) && (SvTYPE(SvRV(*s)) == SVt_PVAV))
               return (AV*)SvRV(*s);
           else
               *error = "The second element in classifier object must be an array reference.";
-      } else {
+      } else
           *error = NEED_ARRAY_REF;
-      }
+      return NULL;
   }
 %}
 
diff --git a/swig/include/perl/gdal_perl.i b/swig/include/perl/gdal_perl.i
index bfb6e2c..8873f93 100644
--- a/swig/include/perl/gdal_perl.i
+++ b/swig/include/perl/gdal_perl.i
@@ -143,8 +143,8 @@ use Geo::GDAL::Const;
 # Note that the 1/100000 digits may be used to create more than one
 # CPAN release from one GDAL release.
 
-our $VERSION = '2.0200';
-our $GDAL_VERSION = '2.2.0';
+our $VERSION = '2.0201';
+our $GDAL_VERSION = '2.2.1';
 
 =pod
 
diff --git a/swig/include/perl/ogr_perl.i b/swig/include/perl/ogr_perl.i
index 3a07284..2b10317 100644
--- a/swig/include/perl/ogr_perl.i
+++ b/swig/include/perl/ogr_perl.i
@@ -126,7 +126,7 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 %perlcode %{
 
 package Geo::OGR;
-our $VERSION = '2.0200'; # this needs to be the same as that in gdal_perl.i
+our $VERSION = '2.0201'; # this needs to be the same as that in gdal_perl.i
 
 Geo::GDAL->import(qw(:INTERNAL));
 
diff --git a/swig/include/python/gdal_python.i b/swig/include/python/gdal_python.i
index 1c44e19..4e92f1b 100644
--- a/swig/include/python/gdal_python.i
+++ b/swig/include/python/gdal_python.i
@@ -1,5 +1,5 @@
 /*
- * $Id: gdal_python.i 37485 2017-02-27 15:34:30Z rouault $
+ * $Id: gdal_python.i 39126 2017-06-15 09:35:41Z rouault $
  *
  * python specific code for gdal bindings.
  */
@@ -314,17 +314,21 @@ unsigned int wrapper_VSIFReadL( void **buf, unsigned int nMembSize, unsigned int
 
 %pythoncode %{
 
-  def ComputeStatistics(self, approx_ok):
+  def ComputeStatistics(self, *args):
     """ComputeStatistics(Band self, bool approx_ok, GDALProgressFunc callback=0, void * callback_data=None) -> CPLErr"""
 
     # For backward compatibility. New SWIG has stricter typing and really
     # enforces bool
+    approx_ok = args[0]
     if approx_ok == 0:
         approx_ok = False
     elif approx_ok == 1:
         approx_ok = True
+    new_args = [ approx_ok ]
+    for arg in args[1:]:
+        new_args.append( arg )
 
-    return _gdal.Band_ComputeStatistics(self, approx_ok)
+    return _gdal.Band_ComputeStatistics(self, *new_args)
 
 
   def ReadRaster(self, xoff = 0, yoff = 0, xsize = None, ysize = None,
diff --git a/swig/include/python/typemaps_python.i b/swig/include/python/typemaps_python.i
index 1600a58..4b76f64 100644
--- a/swig/include/python/typemaps_python.i
+++ b/swig/include/python/typemaps_python.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: typemaps_python.i 37499 2017-02-28 01:00:01Z rouault $
+ * $Id: typemaps_python.i 38771 2017-06-01 11:24:27Z rouault $
  *
  * Name:     typemaps_python.i
  * Project:  GDAL Python Interface
@@ -1293,6 +1293,17 @@ static PyObject *XMLTreeToPyList( CPLXMLNode *psTree )
 {
     /* %typemap(in) (GDALProgressFunc callback = NULL) */
     /* callback_func typemap */
+
+    /* In some cases 0 is passed instead of None. */
+    /* See https://github.com/OSGeo/gdal/pull/219 */
+    if ( PyLong_Check($input) || PyInt_Check($input) )
+    {
+        if( PyLong_AsLong($input) == 0 )
+        {
+            $input = Py_None;
+        }
+    }
+
     if ($input && $input != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( $input,
diff --git a/swig/perl/Makefile.PL b/swig/perl/Makefile.PL
index 08d32b5..65ac354 100644
--- a/swig/perl/Makefile.PL
+++ b/swig/perl/Makefile.PL
@@ -20,6 +20,31 @@ unless (-r $config) {
         "You have to first say \"cd $source_tree; make\".";
 }
 
+# logic to set INSTALLSITEMAN3DIR if INSTALL_BASE and INST_MAN are set
+# INSTALL_BASE is used in the standard case when this script is called
+# as a part of overall build with --with-perl
+# INST_MAN may be set by --mandir=DIR option to configure
+if ($ARGV[0] =~ /INSTALL_BASE=(.*)/) {
+    my $INSTALL_BASE = $1;
+    my $opt = "$source_tree/GDALmake.opt";
+    open(my $fh, "<", $opt) or die "Can't open < $opt: $!";
+    while (<$fh>) {
+        if (/(\w+)\s+=\s+(.*)/) {
+            my $key = $1;
+            my $val = $2;
+            $val =~ s/\s+$//;
+            if ($key eq 'prefix') {
+                die 'prefix in GDALmake.opt is set different to \$INSTALL_BASE' unless $INSTALL_BASE eq $val;
+            } elsif ($key eq 'INST_MAN') {
+                $val =~ s/\$\{prefix\}/$INSTALL_BASE/;
+                push @ARGV, "INSTALLSITEMAN1DIR=$val/man1";
+                push @ARGV, "INSTALLSITEMAN3DIR=$val/man3";
+            }
+        }
+    }
+    close $fh;
+}
+
 my ($INC, $LIB, $objects) = get_config($config);
 
 for my $module (sort keys %$objects) {
diff --git a/swig/perl/gdal_wrap.cpp b/swig/perl/gdal_wrap.cpp
index 9b69b56..0121674 100644
--- a/swig/perl/gdal_wrap.cpp
+++ b/swig/perl/gdal_wrap.cpp
@@ -1742,7 +1742,7 @@ void DontUseExceptions() {
 
   double NVClassify(int comparison, double nv, AV* classifier, const char **error) {
      /* recursive, return nv < classifier[0] ? classifier[1] : classifier[2]
-        returns error if there are not three values in the classifier,
+        sets error if there are not three values in the classifier,
         first is not a number, or second or third are not a number of arrayref
      */
      SV** f = av_fetch(classifier, 0, 0);
@@ -1771,18 +1771,15 @@ void DontUseExceptions() {
              return SvNV(*t);
          else if (t && SvROK(*t) && (SvTYPE(SvRV(*t)) == SVt_PVAV))
              return NVClassify(comparison, nv, (AV*)(SvRV(*t)), error);
-         else {
+         else
              *error = "The decision in a classifier must be a number or a reference to a classifier.";
-             return 0;
-         }
-     } else {
+     } else
          *error = "The first value in a classifier must be a number.";
-         return 0;
-     }
+     return 0;
   }
   void NVClass(int comparison, double nv, AV* classifier, int *klass, const char **error) {
-     /* recursive, return nv < classifier[0] ? classifier[1] : classifier[2]
-        returns NULL if there are not three values in the classifier,
+     /* recursive, return in klass nv < classifier[0] ? classifier[1] : classifier[2]
+        sets NULL if there are not three values in the classifier,
         first is not a number, or second or third are not a number of arrayref
      */
      SV** f = av_fetch(classifier, 0, 0);
@@ -1816,14 +1813,10 @@ void DontUseExceptions() {
              return;
          else if (t && SvROK(*t) && (SvTYPE(SvRV(*t)) == SVt_PVAV))
              NVClass(comparison, nv, (AV*)(SvRV(*t)), klass, error);
-         else {
+         else
              *error = "The decision in a classifier must be a number or a reference to a classifier.";
-             return;
-         }
-     } else {
+     } else
          *error = "The first value in a classifier must be a number.";
-         return;
-     }
   }
   AV* to_array_classifier(SV* classifier, int* comparison, const char **error) {
       if (SvROK(classifier) && (SvTYPE(SvRV(classifier)) == SVt_PVAV)) {
@@ -1839,16 +1832,18 @@ void DontUseExceptions() {
                   *comparison = 2;
               else if (strcmp(c, ">=") == 0)
                   *comparison = 3;
-              else
+              else {
                   *error = "The first element in classifier object must be a comparison.";
+                  return NULL;
+              }
           }
           if (s && SvROK(*s) && (SvTYPE(SvRV(*s)) == SVt_PVAV))
               return (AV*)SvRV(*s);
           else
               *error = "The second element in classifier object must be an array reference.";
-      } else {
+      } else
           *error = NEED_ARRAY_REF;
-      }
+      return NULL;
   }
 
 
@@ -7598,6 +7593,48 @@ XS(_wrap_VSIStdoutUnsetRedirection) {
 }
 
 
+XS(_wrap_VSICurlClearCache) {
+  {
+    int argvi = 0;
+    dXSARGS;
+    
+    if ((items < 0) || (items > 0)) {
+      SWIG_croak("Usage: VSICurlClearCache();");
+    }
+    {
+      CPLErrorReset();
+      VSICurlClearCache();
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    {
+      /* %typemap(out) void */
+    }
+    XSRETURN(argvi);
+  fail:
+    SWIG_croak_null();
+  }
+}
+
+
 XS(_wrap_ParseCommandLine) {
   {
     char *arg1 = (char *) 0 ;
@@ -29894,6 +29931,7 @@ static swig_command_info swig_commands[] = {
 {"Geo::GDALc::VSIFReadL", _wrap_VSIFReadL},
 {"Geo::GDALc::VSIStdoutSetRedirection", _wrap_VSIStdoutSetRedirection},
 {"Geo::GDALc::VSIStdoutUnsetRedirection", _wrap_VSIStdoutUnsetRedirection},
+{"Geo::GDALc::VSICurlClearCache", _wrap_VSICurlClearCache},
 {"Geo::GDALc::ParseCommandLine", _wrap_ParseCommandLine},
 {"Geo::GDALc::MajorObject_GetDescription", _wrap_MajorObject_GetDescription},
 {"Geo::GDALc::MajorObject_SetDescription", _wrap_MajorObject_SetDescription},
diff --git a/swig/perl/lib/Geo/GDAL.pm b/swig/perl/lib/Geo/GDAL.pm
index 548b063..1110af6 100644
--- a/swig/perl/lib/Geo/GDAL.pm
+++ b/swig/perl/lib/Geo/GDAL.pm
@@ -95,6 +95,7 @@ package Geo::GDAL;
 *VSIFReadL = *Geo::GDALc::VSIFReadL;
 *VSIStdoutSetRedirection = *Geo::GDALc::VSIStdoutSetRedirection;
 *VSIStdoutUnsetRedirection = *Geo::GDALc::VSIStdoutUnsetRedirection;
+*VSICurlClearCache = *Geo::GDALc::VSICurlClearCache;
 *ParseCommandLine = *Geo::GDALc::ParseCommandLine;
 *GDAL_GCP_GCPX_get = *Geo::GDALc::GDAL_GCP_GCPX_get;
 *GDAL_GCP_GCPX_set = *Geo::GDALc::GDAL_GCP_GCPX_set;
@@ -1055,8 +1056,8 @@ use Geo::GDAL::Const;
 # Note that the 1/100000 digits may be used to create more than one
 # CPAN release from one GDAL release.
 
-our $VERSION = '2.0200';
-our $GDAL_VERSION = '2.2.0';
+our $VERSION = '2.0201';
+our $GDAL_VERSION = '2.2.1';
 
 =pod
 
diff --git a/swig/perl/lib/Geo/OGR.pm b/swig/perl/lib/Geo/OGR.pm
index 549f19d..b0c200c 100644
--- a/swig/perl/lib/Geo/OGR.pm
+++ b/swig/perl/lib/Geo/OGR.pm
@@ -960,7 +960,7 @@ package Geo::OGR;
 
 
 package Geo::OGR;
-our $VERSION = '2.0200'; # this needs to be the same as that in gdal_perl.i
+our $VERSION = '2.0201'; # this needs to be the same as that in gdal_perl.i
 
 Geo::GDAL->import(qw(:INTERNAL));
 
diff --git a/swig/python/extensions/gdal_array_wrap.cpp b/swig/python/extensions/gdal_array_wrap.cpp
index bdcb361..005b5a2 100644
--- a/swig/python/extensions/gdal_array_wrap.cpp
+++ b/swig/python/extensions/gdal_array_wrap.cpp
@@ -5020,6 +5020,17 @@ SWIGINTERN PyObject *_wrap_BandRasterIONumPy(PyObject *SWIGUNUSEDPARM(self), PyO
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj9) || PyInt_Check(obj9) )
+      {
+        if( PyLong_AsLong(obj9) == 0 )
+        {
+          obj9 = Py_None;
+        }
+      }
+      
       if (obj9 && obj9 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj9,
@@ -5182,6 +5193,17 @@ SWIGINTERN PyObject *_wrap_DatasetIONumPy(PyObject *SWIGUNUSEDPARM(self), PyObje
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj9) || PyInt_Check(obj9) )
+      {
+        if( PyLong_AsLong(obj9) == 0 )
+        {
+          obj9 = Py_None;
+        }
+      }
+      
       if (obj9 && obj9 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj9,
diff --git a/swig/python/extensions/gdal_wrap.cpp b/swig/python/extensions/gdal_wrap.cpp
index cca0a30..ffcfe51 100644
--- a/swig/python/extensions/gdal_wrap.cpp
+++ b/swig/python/extensions/gdal_wrap.cpp
@@ -9292,6 +9292,36 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_VSICurlClearCache(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  
+  if (!PyArg_ParseTuple(args,(char *)":VSICurlClearCache")) SWIG_fail;
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      VSICurlClearCache();
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_ParseCommandLine(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
@@ -10487,6 +10517,17 @@ SWIGINTERN PyObject *_wrap_Driver_CreateCopy(PyObject *SWIGUNUSEDPARM(self), PyO
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj5) || PyInt_Check(obj5) )
+      {
+        if( PyLong_AsLong(obj5) == 0 )
+        {
+          obj5 = Py_None;
+        }
+      }
+      
       if (obj5 && obj5 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj5,
@@ -13958,6 +13999,17 @@ SWIGINTERN PyObject *_wrap_Dataset_BuildOverviews(PyObject *SWIGUNUSEDPARM(self)
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj3) || PyInt_Check(obj3) )
+      {
+        if( PyLong_AsLong(obj3) == 0 )
+        {
+          obj3 = Py_None;
+        }
+      }
+      
       if (obj3 && obj3 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj3,
@@ -16200,6 +16252,17 @@ SWIGINTERN PyObject *_wrap_Dataset_GetNextFeature(PyObject *SWIGUNUSEDPARM(self)
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj3) || PyInt_Check(obj3) )
+      {
+        if( PyLong_AsLong(obj3) == 0 )
+        {
+          obj3 = Py_None;
+        }
+      }
+      
       if (obj3 && obj3 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj3,
@@ -16979,6 +17042,17 @@ SWIGINTERN PyObject *_wrap_Dataset_ReadRaster1(PyObject *SWIGUNUSEDPARM(self), P
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj13) || PyInt_Check(obj13) )
+      {
+        if( PyLong_AsLong(obj13) == 0 )
+        {
+          obj13 = Py_None;
+        }
+      }
+      
       if (obj13 && obj13 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj13,
@@ -18489,6 +18563,17 @@ SWIGINTERN PyObject *_wrap_Band_ComputeStatistics(PyObject *SWIGUNUSEDPARM(self)
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj2) || PyInt_Check(obj2) )
+      {
+        if( PyLong_AsLong(obj2) == 0 )
+        {
+          obj2 = Py_None;
+        }
+      }
+      
       if (obj2 && obj2 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj2,
@@ -19796,6 +19881,17 @@ SWIGINTERN PyObject *_wrap_Band_GetHistogram(PyObject *SWIGUNUSEDPARM(self), PyO
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj6) || PyInt_Check(obj6) )
+      {
+        if( PyLong_AsLong(obj6) == 0 )
+        {
+          obj6 = Py_None;
+        }
+      }
+      
       if (obj6 && obj6 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj6,
@@ -19992,6 +20088,17 @@ SWIGINTERN PyObject *_wrap_Band_GetDefaultHistogram(PyObject *SWIGUNUSEDPARM(sel
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj6) || PyInt_Check(obj6) )
+      {
+        if( PyLong_AsLong(obj6) == 0 )
+        {
+          obj6 = Py_None;
+        }
+      }
+      
       if (obj6 && obj6 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj6,
@@ -21135,6 +21242,17 @@ SWIGINTERN PyObject *_wrap_Band_ReadRaster1(PyObject *SWIGUNUSEDPARM(self), PyOb
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj11) || PyInt_Check(obj11) )
+      {
+        if( PyLong_AsLong(obj11) == 0 )
+        {
+          obj11 = Py_None;
+        }
+      }
+      
       if (obj11 && obj11 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj11,
@@ -23117,6 +23235,17 @@ SWIGINTERN PyObject *_wrap_ComputeMedianCutPCT(PyObject *SWIGUNUSEDPARM(self), P
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj5) || PyInt_Check(obj5) )
+      {
+        if( PyLong_AsLong(obj5) == 0 )
+        {
+          obj5 = Py_None;
+        }
+      }
+      
       if (obj5 && obj5 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj5,
@@ -23272,6 +23401,17 @@ SWIGINTERN PyObject *_wrap_DitherRGB2PCT(PyObject *SWIGUNUSEDPARM(self), PyObjec
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj5) || PyInt_Check(obj5) )
+      {
+        if( PyLong_AsLong(obj5) == 0 )
+        {
+          obj5 = Py_None;
+        }
+      }
+      
       if (obj5 && obj5 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj5,
@@ -23464,6 +23604,17 @@ SWIGINTERN PyObject *_wrap_ReprojectImage(PyObject *SWIGUNUSEDPARM(self), PyObje
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj7) || PyInt_Check(obj7) )
+      {
+        if( PyLong_AsLong(obj7) == 0 )
+        {
+          obj7 = Py_None;
+        }
+      }
+      
       if (obj7 && obj7 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj7,
@@ -23696,6 +23847,17 @@ SWIGINTERN PyObject *_wrap_ComputeProximity(PyObject *SWIGUNUSEDPARM(self), PyOb
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj3) || PyInt_Check(obj3) )
+      {
+        if( PyLong_AsLong(obj3) == 0 )
+        {
+          obj3 = Py_None;
+        }
+      }
+      
       if (obj3 && obj3 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj3,
@@ -23948,6 +24110,17 @@ SWIGINTERN PyObject *_wrap_RasterizeLayer(PyObject *SWIGUNUSEDPARM(self), PyObje
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj7) || PyInt_Check(obj7) )
+      {
+        if( PyLong_AsLong(obj7) == 0 )
+        {
+          obj7 = Py_None;
+        }
+      }
+      
       if (obj7 && obj7 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj7,
@@ -24168,6 +24341,17 @@ SWIGINTERN PyObject *_wrap_Polygonize(PyObject *SWIGUNUSEDPARM(self), PyObject *
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj5) || PyInt_Check(obj5) )
+      {
+        if( PyLong_AsLong(obj5) == 0 )
+        {
+          obj5 = Py_None;
+        }
+      }
+      
       if (obj5 && obj5 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj5,
@@ -24364,6 +24548,17 @@ SWIGINTERN PyObject *_wrap_FPolygonize(PyObject *SWIGUNUSEDPARM(self), PyObject
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj5) || PyInt_Check(obj5) )
+      {
+        if( PyLong_AsLong(obj5) == 0 )
+        {
+          obj5 = Py_None;
+        }
+      }
+      
       if (obj5 && obj5 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj5,
@@ -24560,6 +24755,17 @@ SWIGINTERN PyObject *_wrap_FillNodata(PyObject *SWIGUNUSEDPARM(self), PyObject *
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj5) || PyInt_Check(obj5) )
+      {
+        if( PyLong_AsLong(obj5) == 0 )
+        {
+          obj5 = Py_None;
+        }
+      }
+      
       if (obj5 && obj5 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj5,
@@ -24762,6 +24968,17 @@ SWIGINTERN PyObject *_wrap_SieveFilter(PyObject *SWIGUNUSEDPARM(self), PyObject
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj6) || PyInt_Check(obj6) )
+      {
+        if( PyLong_AsLong(obj6) == 0 )
+        {
+          obj6 = Py_None;
+        }
+      }
+      
       if (obj6 && obj6 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj6,
@@ -24926,6 +25143,17 @@ SWIGINTERN PyObject *_wrap_RegenerateOverviews(PyObject *SWIGUNUSEDPARM(self), P
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj3) || PyInt_Check(obj3) )
+      {
+        if( PyLong_AsLong(obj3) == 0 )
+        {
+          obj3 = Py_None;
+        }
+      }
+      
       if (obj3 && obj3 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj3,
@@ -25061,6 +25289,17 @@ SWIGINTERN PyObject *_wrap_RegenerateOverview(PyObject *SWIGUNUSEDPARM(self), Py
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj3) || PyInt_Check(obj3) )
+      {
+        if( PyLong_AsLong(obj3) == 0 )
+        {
+          obj3 = Py_None;
+        }
+      }
+      
       if (obj3 && obj3 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj3,
@@ -25262,6 +25501,17 @@ SWIGINTERN PyObject *_wrap_ContourGenerate(PyObject *SWIGUNUSEDPARM(self), PyObj
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj9) || PyInt_Check(obj9) )
+      {
+        if( PyLong_AsLong(obj9) == 0 )
+        {
+          obj9 = Py_None;
+        }
+      }
+      
       if (obj9 && obj9 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj9,
@@ -26116,6 +26366,17 @@ SWIGINTERN PyObject *_wrap_Transformer_TransformGeolocations(PyObject *SWIGUNUSE
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj4) || PyInt_Check(obj4) )
+      {
+        if( PyLong_AsLong(obj4) == 0 )
+        {
+          obj4 = Py_None;
+        }
+      }
+      
       if (obj4 && obj4 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj4,
@@ -28878,6 +29139,17 @@ SWIGINTERN PyObject *_wrap_TranslateInternal(PyObject *SWIGUNUSEDPARM(self), PyO
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj3) || PyInt_Check(obj3) )
+      {
+        if( PyLong_AsLong(obj3) == 0 )
+        {
+          obj3 = Py_None;
+        }
+      }
+      
       if (obj3 && obj3 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj3,
@@ -29171,6 +29443,17 @@ SWIGINTERN PyObject *_wrap_wrapper_GDALWarpDestDS(PyObject *SWIGUNUSEDPARM(self)
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj3) || PyInt_Check(obj3) )
+      {
+        if( PyLong_AsLong(obj3) == 0 )
+        {
+          obj3 = Py_None;
+        }
+      }
+      
       if (obj3 && obj3 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj3,
@@ -29322,6 +29605,17 @@ SWIGINTERN PyObject *_wrap_wrapper_GDALWarpDestName(PyObject *SWIGUNUSEDPARM(sel
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj3) || PyInt_Check(obj3) )
+      {
+        if( PyLong_AsLong(obj3) == 0 )
+        {
+          obj3 = Py_None;
+        }
+      }
+      
       if (obj3 && obj3 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj3,
@@ -29592,6 +29886,17 @@ SWIGINTERN PyObject *_wrap_wrapper_GDALVectorTranslateDestDS(PyObject *SWIGUNUSE
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj3) || PyInt_Check(obj3) )
+      {
+        if( PyLong_AsLong(obj3) == 0 )
+        {
+          obj3 = Py_None;
+        }
+      }
+      
       if (obj3 && obj3 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj3,
@@ -29709,6 +30014,17 @@ SWIGINTERN PyObject *_wrap_wrapper_GDALVectorTranslateDestName(PyObject *SWIGUNU
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj3) || PyInt_Check(obj3) )
+      {
+        if( PyLong_AsLong(obj3) == 0 )
+        {
+          obj3 = Py_None;
+        }
+      }
+      
       if (obj3 && obj3 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj3,
@@ -29994,6 +30310,17 @@ SWIGINTERN PyObject *_wrap_DEMProcessingInternal(PyObject *SWIGUNUSEDPARM(self),
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj5) || PyInt_Check(obj5) )
+      {
+        if( PyLong_AsLong(obj5) == 0 )
+        {
+          obj5 = Py_None;
+        }
+      }
+      
       if (obj5 && obj5 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj5,
@@ -30270,6 +30597,17 @@ SWIGINTERN PyObject *_wrap_wrapper_GDALNearblackDestDS(PyObject *SWIGUNUSEDPARM(
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj3) || PyInt_Check(obj3) )
+      {
+        if( PyLong_AsLong(obj3) == 0 )
+        {
+          obj3 = Py_None;
+        }
+      }
+      
       if (obj3 && obj3 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj3,
@@ -30387,6 +30725,17 @@ SWIGINTERN PyObject *_wrap_wrapper_GDALNearblackDestName(PyObject *SWIGUNUSEDPAR
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj3) || PyInt_Check(obj3) )
+      {
+        if( PyLong_AsLong(obj3) == 0 )
+        {
+          obj3 = Py_None;
+        }
+      }
+      
       if (obj3 && obj3 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj3,
@@ -30652,6 +31001,17 @@ SWIGINTERN PyObject *_wrap_GridInternal(PyObject *SWIGUNUSEDPARM(self), PyObject
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj3) || PyInt_Check(obj3) )
+      {
+        if( PyLong_AsLong(obj3) == 0 )
+        {
+          obj3 = Py_None;
+        }
+      }
+      
       if (obj3 && obj3 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj3,
@@ -30919,6 +31279,17 @@ SWIGINTERN PyObject *_wrap_wrapper_GDALRasterizeDestDS(PyObject *SWIGUNUSEDPARM(
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj3) || PyInt_Check(obj3) )
+      {
+        if( PyLong_AsLong(obj3) == 0 )
+        {
+          obj3 = Py_None;
+        }
+      }
+      
       if (obj3 && obj3 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj3,
@@ -31036,6 +31407,17 @@ SWIGINTERN PyObject *_wrap_wrapper_GDALRasterizeDestName(PyObject *SWIGUNUSEDPAR
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj3) || PyInt_Check(obj3) )
+      {
+        if( PyLong_AsLong(obj3) == 0 )
+        {
+          obj3 = Py_None;
+        }
+      }
+      
       if (obj3 && obj3 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj3,
@@ -31327,6 +31709,17 @@ SWIGINTERN PyObject *_wrap_BuildVRTInternalObjects(PyObject *SWIGUNUSEDPARM(self
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj3) || PyInt_Check(obj3) )
+      {
+        if( PyLong_AsLong(obj3) == 0 )
+        {
+          obj3 = Py_None;
+        }
+      }
+      
       if (obj3 && obj3 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj3,
@@ -31506,6 +31899,17 @@ SWIGINTERN PyObject *_wrap_BuildVRTInternalNames(PyObject *SWIGUNUSEDPARM(self),
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj3) || PyInt_Check(obj3) )
+      {
+        if( PyLong_AsLong(obj3) == 0 )
+        {
+          obj3 = Py_None;
+        }
+      }
+      
       if (obj3 && obj3 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj3,
@@ -31654,6 +32058,7 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"VSI_RANGE_STATUS_HOLE_swigconstant", VSI_RANGE_STATUS_HOLE_swigconstant, METH_VARARGS, NULL},
 	 { (char *)"VSIFGetRangeStatusL", _wrap_VSIFGetRangeStatusL, METH_VARARGS, (char *)"VSIFGetRangeStatusL(VSILFILE * fp, GIntBig offset, GIntBig length) -> int"},
 	 { (char *)"VSIFWriteL", _wrap_VSIFWriteL, METH_VARARGS, (char *)"VSIFWriteL(int nLen, int size, int memb, VSILFILE * fp) -> int"},
+	 { (char *)"VSICurlClearCache", _wrap_VSICurlClearCache, METH_VARARGS, (char *)"VSICurlClearCache()"},
 	 { (char *)"ParseCommandLine", _wrap_ParseCommandLine, METH_VARARGS, (char *)"ParseCommandLine(char const * utf8_path) -> char **"},
 	 { (char *)"MajorObject_GetDescription", _wrap_MajorObject_GetDescription, METH_VARARGS, (char *)"MajorObject_GetDescription(MajorObject self) -> char const *"},
 	 { (char *)"MajorObject_SetDescription", _wrap_MajorObject_SetDescription, METH_VARARGS, (char *)"MajorObject_SetDescription(MajorObject self, char const * pszNewDesc)"},
diff --git a/swig/python/extensions/ogr_wrap.cpp b/swig/python/extensions/ogr_wrap.cpp
index e6aa07e..f8f4fc8 100644
--- a/swig/python/extensions/ogr_wrap.cpp
+++ b/swig/python/extensions/ogr_wrap.cpp
@@ -12519,6 +12519,17 @@ SWIGINTERN PyObject *_wrap_Layer_Intersection(PyObject *SWIGUNUSEDPARM(self), Py
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj4) || PyInt_Check(obj4) )
+      {
+        if( PyLong_AsLong(obj4) == 0 )
+        {
+          obj4 = Py_None;
+        }
+      }
+      
       if (obj4 && obj4 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj4,
@@ -12712,6 +12723,17 @@ SWIGINTERN PyObject *_wrap_Layer_Union(PyObject *SWIGUNUSEDPARM(self), PyObject
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj4) || PyInt_Check(obj4) )
+      {
+        if( PyLong_AsLong(obj4) == 0 )
+        {
+          obj4 = Py_None;
+        }
+      }
+      
       if (obj4 && obj4 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj4,
@@ -12905,6 +12927,17 @@ SWIGINTERN PyObject *_wrap_Layer_SymDifference(PyObject *SWIGUNUSEDPARM(self), P
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj4) || PyInt_Check(obj4) )
+      {
+        if( PyLong_AsLong(obj4) == 0 )
+        {
+          obj4 = Py_None;
+        }
+      }
+      
       if (obj4 && obj4 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj4,
@@ -13098,6 +13131,17 @@ SWIGINTERN PyObject *_wrap_Layer_Identity(PyObject *SWIGUNUSEDPARM(self), PyObje
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj4) || PyInt_Check(obj4) )
+      {
+        if( PyLong_AsLong(obj4) == 0 )
+        {
+          obj4 = Py_None;
+        }
+      }
+      
       if (obj4 && obj4 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj4,
@@ -13291,6 +13335,17 @@ SWIGINTERN PyObject *_wrap_Layer_Update(PyObject *SWIGUNUSEDPARM(self), PyObject
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj4) || PyInt_Check(obj4) )
+      {
+        if( PyLong_AsLong(obj4) == 0 )
+        {
+          obj4 = Py_None;
+        }
+      }
+      
       if (obj4 && obj4 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj4,
@@ -13484,6 +13539,17 @@ SWIGINTERN PyObject *_wrap_Layer_Clip(PyObject *SWIGUNUSEDPARM(self), PyObject *
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj4) || PyInt_Check(obj4) )
+      {
+        if( PyLong_AsLong(obj4) == 0 )
+        {
+          obj4 = Py_None;
+        }
+      }
+      
       if (obj4 && obj4 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj4,
@@ -13677,6 +13743,17 @@ SWIGINTERN PyObject *_wrap_Layer_Erase(PyObject *SWIGUNUSEDPARM(self), PyObject
     {
       /* %typemap(in) (GDALProgressFunc callback = NULL) */
       /* callback_func typemap */
+      
+      /* In some cases 0 is passed instead of None. */
+      /* See https://github.com/OSGeo/gdal/pull/219 */
+      if ( PyLong_Check(obj4) || PyInt_Check(obj4) )
+      {
+        if( PyLong_AsLong(obj4) == 0 )
+        {
+          obj4 = Py_None;
+        }
+      }
+      
       if (obj4 && obj4 != Py_None ) {
         void* cbfunction = NULL;
         CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj4,
diff --git a/swig/python/osgeo/gdal.py b/swig/python/osgeo/gdal.py
index 28c3822..81d22b8 100644
--- a/swig/python/osgeo/gdal.py
+++ b/swig/python/osgeo/gdal.py
@@ -1433,6 +1433,10 @@ def VSIFWriteL(*args):
     """VSIFWriteL(int nLen, int size, int memb, VSILFILE * fp) -> int"""
     return _gdal.VSIFWriteL(*args)
 
+def VSICurlClearCache(*args):
+    """VSICurlClearCache()"""
+    return _gdal.VSICurlClearCache(*args)
+
 def ParseCommandLine(*args):
     """ParseCommandLine(char const * utf8_path) -> char **"""
     return _gdal.ParseCommandLine(*args)
@@ -2487,17 +2491,21 @@ class Band(MajorObject):
 
 
 
-    def ComputeStatistics(self, approx_ok):
+    def ComputeStatistics(self, *args):
       """ComputeStatistics(Band self, bool approx_ok, GDALProgressFunc callback=0, void * callback_data=None) -> CPLErr"""
 
     # For backward compatibility. New SWIG has stricter typing and really
     # enforces bool
+      approx_ok = args[0]
       if approx_ok == 0:
           approx_ok = False
       elif approx_ok == 1:
           approx_ok = True
+      new_args = [ approx_ok ]
+      for arg in args[1:]:
+          new_args.append( arg )
 
-      return _gdal.Band_ComputeStatistics(self, approx_ok)
+      return _gdal.Band_ComputeStatistics(self, *new_args)
 
 
     def ReadRaster(self, xoff = 0, yoff = 0, xsize = None, ysize = None,
diff --git a/swig/python/samples/validate_gpkg.py b/swig/python/samples/validate_gpkg.py
index caa20c8..cbaadd0 100644
--- a/swig/python/samples/validate_gpkg.py
+++ b/swig/python/samples/validate_gpkg.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 ###############################################################################
-# $Id: validate_gpkg.py 38103 2017-04-22 18:06:20Z rouault $
+# $Id: validate_gpkg.py 38922 2017-06-06 20:38:20Z rouault $
 #
 # Project:  GDAL/OGR
 # Purpose:  Test compliance of GeoPackage database w.r.t GeoPackage spec
@@ -268,7 +268,7 @@ class GPKGChecker:
         rows = c.fetchall()
         for (table_name, last_change, srs_id) in rows:
             c.execute("SELECT 1 FROM sqlite_master WHERE "
-                      "name = ? AND type IN ('table', 'view')", (table_name,))
+                      "lower(name) = lower(?) AND type IN ('table', 'view')", (table_name,))
             self._assert(c.fetchone() is not None, 14,
                          ('table_name=%s in gpkg_contents is not a ' +
                           'table or view') % table_name)
@@ -315,7 +315,7 @@ class GPKGChecker:
         found_geom = False
         count_pkid = 0
         for (_, name, type, notnull, default, pk) in cols:
-            if name == geom_column_name:
+            if name.lower() == geom_column_name.lower():
                 found_geom = True
                 self._assert(
                     type in base_geom_types or
@@ -1260,7 +1260,7 @@ class GPKGChecker:
                   "WHERE extension_name = 'gpkg_rtree_index' ")
         rows = c.fetchall()
         for (table_name, scope) in rows:
-            c.execute("SELECT 1 FROM gpkg_contents WHERE table_name = ? "
+            c.execute("SELECT 1 FROM gpkg_contents WHERE lower(table_name) = lower(?) "
                       "AND data_type = 'features'", (table_name,))
             self._assert(c.fetchone() is not None, 75,
                          ('gpkg_extensions declares gpkg_rtree_index for %s,' +
diff --git a/swig/python/scripts/ogrmerge.py b/swig/python/scripts/ogrmerge.py
index d12a048..1edb054 100755
--- a/swig/python/scripts/ogrmerge.py
+++ b/swig/python/scripts/ogrmerge.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 ###############################################################################
-# $Id: ogrmerge.py 37620 2017-03-06 09:19:57Z rouault $
+# $Id: ogrmerge.py 38240 2017-05-13 11:37:40Z rouault $
 #
 # Project:  GDAL/OGR samples
 # Purpose:  Merge the content of several vector datasets into a single one.
@@ -388,11 +388,11 @@ def process(argv, progress=None, progress_arg=None):
                 writer.open_element('OGRVRTLayer',
                                     attrs={'name': layer_name})
                 attrs = None
-                if os.path.exists(src_dsname) and \
-                   src_dsname.find('/') < 0 and \
-                   src_ds.name.find('\\') < 0 and \
+                if EQUAL(output_format, 'VRT') and \
                    os.path.exists(src_dsname) and \
-                   not os.path.isabs(src_dsname):
+                   not os.path.isabs(src_dsname) and \
+                   vrt_filename.find('/') < 0 and \
+                   vrt_filename.find('\\') < 0:
                     attrs = {'relativeToVRT': '1'}
                 writer.write_element_value('SrcDataSource', src_dsname,
                                            attrs=attrs)
@@ -479,11 +479,11 @@ def process(argv, progress=None, progress_arg=None):
                 writer.open_element('OGRVRTLayer',
                                     attrs={'name': layer_name})
                 attrs = None
-                if os.path.exists(src_dsname) and \
-                   src_dsname.find('/') < 0 and \
-                   src_ds.name.find('\\') < 0 and \
+                if EQUAL(output_format, 'VRT') and \
                    os.path.exists(src_dsname) and \
-                   not os.path.isabs(src_dsname):
+                   not os.path.isabs(src_dsname) and \
+                   vrt_filename.find('/') < 0 and \
+                   vrt_filename.find('\\') < 0:
                     attrs = {'relativeToVRT': '1'}
                 writer.write_element_value('SrcDataSource', src_dsname,
                                            attrs=attrs)
diff --git a/swig/python/setup.py b/swig/python/setup.py
index da199aa..8ac2f8e 100644
--- a/swig/python/setup.py
+++ b/swig/python/setup.py
@@ -7,7 +7,7 @@
 # Howard Butler hobu.inc at gmail.com
 
 
-gdal_version = '2.2.0'
+gdal_version = '2.2.1'
 
 import sys
 import os

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/gdal.git



More information about the Pkg-grass-devel mailing list