[Git][debian-gis-team/shapelib][upstream] New upstream version 1.6.2

Bas Couwenberg (@sebastic) gitlab at salsa.debian.org
Wed Sep 24 00:12:37 BST 2025



Bas Couwenberg pushed to branch upstream at Debian GIS Project / shapelib


Commits:
789bb79c by Bas Couwenberg at 2025-09-23T15:49:56-07:00
New upstream version 1.6.2
- - - - -


20 changed files:

- CMakeLists.txt
- Makefile.am
- Makefile.in
- configure
- configure.ac
- dbfadd.c
- dbfcreate.c
- dbfdump.c
- dbfopen.c
- safileio.c
- sbnsearch.c
- shapefil.h
- shpopen.c
- shptree.c
- tests/CMakeLists.txt
- tests/dbf_test.cc
- tests/expect3.out
- + tests/shp_bench.cc
- tests/test3.sh
- web/release.html


Changes:

=====================================
CMakeLists.txt
=====================================
@@ -7,6 +7,11 @@
 #
 # See README.CMake
 
+set(PACKAGE shp)
+if (TARGET ${PACKAGE})
+  return ()
+endif ()
+
 # Version 3.11 or above of cmake is currently required for all platforms.
 cmake_minimum_required(VERSION 3.11)
 project(shapelib C CXX)
@@ -16,8 +21,8 @@ message(STATUS "CMAKE_SYSTEM_NAME = ${CMAKE_SYSTEM_NAME}")
 
 set(PROJECT_VERSION_MAJOR 1)
 set(PROJECT_VERSION_MINOR 6)
-set(PROJECT_VERSION_PATCH 1)
-set(shp_LIB_VERSIONINFO "5:0:1")
+set(PROJECT_VERSION_PATCH 2)
+set(shp_LIB_VERSIONINFO "6:0:2")
 set(PROJECT_VERSION
   "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
 
@@ -49,7 +54,6 @@ if(BUILD_SHARED_LIBS AND (WIN32 OR CYGWIN))
   set(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/dll)
 endif()
 
-set(PACKAGE shp)
 
 # Set up install locations.
 set(
@@ -202,8 +206,9 @@ endif()
 
 find_program(BASH_EXECUTABLE bash)
 if(BASH_EXECUTABLE)
-  set(BUILD_TESTING ON CACHE BOOL "")
+  option(BUILD_TESTING "Build tests"  ON)
 else()
+  set(BUILD_TESTING OFF CACHE BOOL "Disable tests")
   message(STATUS "WARNING: bash not available so disabling testing")
 endif()
 
@@ -292,8 +297,6 @@ if(BUILD_TESTING)
   )
   declare_test_executable(test3 "dbfadd;dbfcreate;dbfdump;shpadd;shpcreate;shpdump")
 
-  include(CTest)
-
   add_subdirectory(tests)
 endif()
 


=====================================
Makefile.am
=====================================
@@ -21,6 +21,7 @@ EXTRA_DIST = makefile.vc CMakeLists.txt autogen.sh \
 		tests/CMakeLists.txt \
 		tests/dbf_test.cc \
 		tests/sbn_test.cc \
+		tests/shp_bench.cc \
 		tests/shp_test.cc \
 		tests/test1.sh tests/test2.sh tests/test3.sh \
 		tests/expect1.out tests/expect2.out tests/expect3.out \


=====================================
Makefile.in
=====================================
@@ -640,6 +640,7 @@ EXTRA_DIST = makefile.vc CMakeLists.txt autogen.sh \
 		tests/CMakeLists.txt \
 		tests/dbf_test.cc \
 		tests/sbn_test.cc \
+		tests/shp_bench.cc \
 		tests/shp_test.cc \
 		tests/test1.sh tests/test2.sh tests/test3.sh \
 		tests/expect1.out tests/expect2.out tests/expect3.out \


=====================================
configure
=====================================
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for shapelib 1.6.1.
+# Generated by GNU Autoconf 2.69 for shapelib 1.6.2.
 #
 #
 # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -587,8 +587,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='shapelib'
 PACKAGE_TARNAME='shapelib'
-PACKAGE_VERSION='1.6.1'
-PACKAGE_STRING='shapelib 1.6.1'
+PACKAGE_VERSION='1.6.2'
+PACKAGE_STRING='shapelib 1.6.2'
 PACKAGE_BUGREPORT=''
 PACKAGE_URL=''
 
@@ -1336,7 +1336,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures shapelib 1.6.1 to adapt to many kinds of systems.
+\`configure' configures shapelib 1.6.2 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1407,7 +1407,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of shapelib 1.6.1:";;
+     short | recursive ) echo "Configuration of shapelib 1.6.2:";;
    esac
   cat <<\_ACEOF
 
@@ -1520,7 +1520,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-shapelib configure 1.6.1
+shapelib configure 1.6.2
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1919,7 +1919,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by shapelib $as_me 1.6.1, which was
+It was created by shapelib $as_me 1.6.2, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -4328,7 +4328,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='shapelib'
- VERSION='1.6.1'
+ VERSION='1.6.2'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -4762,7 +4762,7 @@ unknown)
 esac
 
 
-SHAPELIB_SO_VERSION=5:0:1
+SHAPELIB_SO_VERSION=6:0:2
 
 
 ac_ext=c
@@ -17429,7 +17429,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by shapelib $as_me 1.6.1, which was
+This file was extended by shapelib $as_me 1.6.2, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -17486,7 +17486,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-shapelib config.status 1.6.1
+shapelib config.status 1.6.2
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 


=====================================
configure.ac
=====================================
@@ -2,7 +2,7 @@ dnl Process this file with autoconf to produce a configure script.
 
 m4_define(shapelib_version_major, 1)
 m4_define(shapelib_version_minor, 6)
-m4_define(shapelib_version_micro, 1)
+m4_define(shapelib_version_micro, 2)
 
 AC_PREREQ(2.62)
 AC_INIT(shapelib, shapelib_version_major.shapelib_version_minor.shapelib_version_micro)
@@ -28,7 +28,7 @@ AM_SILENT_RULES([yes])
 m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
 
 dnl See http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
-AC_SUBST([SHAPELIB_SO_VERSION], [5:0:1])
+AC_SUBST([SHAPELIB_SO_VERSION], [6:0:2])
 
 AC_PROG_CC
 AC_PROG_CXX


=====================================
dbfadd.c
=====================================
@@ -44,6 +44,9 @@ int main(int argc, char **argv)
 
     const int iRecord = DBFGetRecordCount(hDBF);
 
+    SHPDate date;
+    char bool;
+
     // Loop assigning the new field values.
     for (int i = 0; i < DBFGetFieldCount(hDBF); i++)
     {
@@ -51,7 +54,23 @@ int main(int argc, char **argv)
             DBFWriteNULLAttribute(hDBF, iRecord, i);
         else if (DBFGetFieldInfo(hDBF, i, NULL, NULL, NULL) == FTString)
             DBFWriteStringAttribute(hDBF, iRecord, i, argv[i + 2]);
+        else if (DBFGetFieldInfo(hDBF, i, NULL, NULL, NULL) == FTDate)
+        {
+            if (3 == sscanf(argv[i + 2], "%4d%2d%2d", &date.year, &date.month,
+                            &date.day))
+            {
+                DBFWriteDateAttribute(hDBF, iRecord, i, &date);
+            }
+        }
+        else if (DBFGetFieldInfo(hDBF, i, NULL, NULL, NULL) == FTLogical)
+        {
+            if (1 == sscanf(argv[i + 2], "%c", &bool))
+            {
+                DBFWriteLogicalAttribute(hDBF, iRecord, i, bool);
+            }
+        }
         else
+
             DBFWriteDoubleAttribute(hDBF, iRecord, i, atof(argv[i + 2]));
     }
 


=====================================
dbfcreate.c
=====================================
@@ -23,7 +23,9 @@ int main(int argc, char **argv)
     if (argc < 2)
     {
         printf("dbfcreate xbase_file [[-s field_name width], "
-               "[-n field_name width decimals]]...\n");
+               "[-n field_name width decimals], "
+               "[-d field_name], "
+               "[-l field_name]]...\n");
         return 1;
     }
 
@@ -65,6 +67,33 @@ int main(int argc, char **argv)
             }
             i += 3;
         }
+        else if (i < argc - 1 && strcmp(argv[i], "-d") == 0)
+        {
+            const char *field = argv[i + 1];
+            const int width = 8;
+            const int decimals = 0;
+            if (DBFAddField(hDBF, field, FTDate, width, decimals) == -1)
+            {
+                printf("DBFAddField(%s,FTDate,%d,0) failed.\n", field, width);
+                DBFClose(hDBF);
+                return 4;
+            }
+            i += 1;
+        }
+        else if (i < argc - 1 && strcmp(argv[i], "-l") == 0)
+        {
+            const char *field = argv[i + 1];
+            const int width = 1;
+            const int decimals = 0;
+            if (DBFAddField(hDBF, field, FTLogical, width, decimals) == -1)
+            {
+                printf("DBFAddField(%s,FTLogical,%d,0) failed.\n", field,
+                       width);
+                DBFClose(hDBF);
+                return 4;
+            }
+            i += 1;
+        }
         else
         {
             printf("Argument incomplete, or unrecognised: %s\n", argv[i]);


=====================================
dbfdump.c
=====================================
@@ -59,7 +59,7 @@ int main(int argc, char **argv)
     DBFHandle hDBF = DBFOpen(pszFilename, "rb");
     if (hDBF == NULL)
     {
-        printf("DBFOpen(%s,\"r\") failed.\n", argv[1]);
+        printf("DBFOpen(%s,\"r\") failed.\n", pszFilename);
         exit(2);
     }
 


=====================================
dbfopen.c
=====================================
@@ -13,6 +13,8 @@
 
 #include "shapefil_private.h"
 
+#include <assert.h>
+#include <errno.h>
 #include <math.h>
 #include <stdbool.h>
 #include <stdio.h>
@@ -24,6 +26,7 @@
 #include "cpl_string.h"
 #else
 
+#ifndef STRCASECMP
 #if defined(_MSC_VER)
 #define STRCASECMP(a, b) (_stricmp(a, b))
 #elif defined(_WIN32)
@@ -32,6 +35,7 @@
 #include <strings.h>
 #define STRCASECMP(a, b) (strcasecmp(a, b))
 #endif
+#endif
 
 #if defined(_MSC_VER)
 #if _MSC_VER < 1900
@@ -353,10 +357,19 @@ DBFHandle SHPAPI_CALL DBFOpenLL(const char *pszFilename, const char *pszAccess,
     /* -------------------------------------------------------------------- */
     const int nLenWithoutExtension = DBFGetLenWithoutExtension(pszFilename);
     char *pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
+    if (!pszFullname)
+    {
+        return SHPLIB_NULLPTR;
+    }
     memcpy(pszFullname, pszFilename, nLenWithoutExtension);
     memcpy(pszFullname + nLenWithoutExtension, ".dbf", 5);
 
     DBFHandle psDBF = STATIC_CAST(DBFHandle, calloc(1, sizeof(DBFInfo)));
+    if (!psDBF)
+    {
+        free(pszFullname);
+        return SHPLIB_NULLPTR;
+    }
     psDBF->fp = psHooks->FOpen(pszFullname, pszAccess, psHooks->pvUserData);
     memcpy(&(psDBF->sHooks), psHooks, sizeof(SAHooks));
 
@@ -394,6 +407,14 @@ DBFHandle SHPAPI_CALL DBFOpenLL(const char *pszFilename, const char *pszAccess,
     /* -------------------------------------------------------------------- */
     const int nBufSize = 500;
     unsigned char *pabyBuf = STATIC_CAST(unsigned char *, malloc(nBufSize));
+    if (!pabyBuf)
+    {
+        psDBF->sHooks.FClose(psDBF->fp);
+        if (pfCPG)
+            psHooks->FClose(pfCPG);
+        free(psDBF);
+        return SHPLIB_NULLPTR;
+    }
     if (psDBF->sHooks.FRead(pabyBuf, XBASE_FILEHDR_SZ, 1, psDBF->fp) != 1)
     {
         psDBF->sHooks.FClose(psDBF->fp);
@@ -427,8 +448,17 @@ DBFHandle SHPAPI_CALL DBFOpenLL(const char *pszFilename, const char *pszAccess,
     const int nFields = (nHeadLen - XBASE_FILEHDR_SZ) / XBASE_FLDHDR_SZ;
     psDBF->nFields = nFields;
 
-    /* coverity[tainted_data] */
+    assert(psDBF->nRecordLength < 65536);
     psDBF->pszCurrentRecord = STATIC_CAST(char *, malloc(psDBF->nRecordLength));
+    if (!psDBF->pszCurrentRecord)
+    {
+        psDBF->sHooks.FClose(psDBF->fp);
+        if (pfCPG)
+            psDBF->sHooks.FClose(pfCPG);
+        free(pabyBuf);
+        free(psDBF);
+        return SHPLIB_NULLPTR;
+    }
 
     /* -------------------------------------------------------------------- */
     /*  Figure out the code page from the LDID and CPG                      */
@@ -443,7 +473,8 @@ DBFHandle SHPAPI_CALL DBFOpenLL(const char *pszFilename, const char *pszAccess,
         {
             pabyBuf[n] = '\0';
             psDBF->pszCodePage = STATIC_CAST(char *, malloc(n + 1));
-            memcpy(psDBF->pszCodePage, pabyBuf, n + 1);
+            if (psDBF->pszCodePage)
+                memcpy(psDBF->pszCodePage, pabyBuf, n + 1);
         }
         psDBF->sHooks.FClose(pfCPG);
     }
@@ -453,13 +484,28 @@ DBFHandle SHPAPI_CALL DBFOpenLL(const char *pszFilename, const char *pszAccess,
                  psDBF->iLanguageDriver);
         psDBF->pszCodePage = STATIC_CAST(
             char *, malloc(strlen(REINTERPRET_CAST(char *, pabyBuf)) + 1));
-        strcpy(psDBF->pszCodePage, REINTERPRET_CAST(char *, pabyBuf));
+        if (psDBF->pszCodePage)
+            strcpy(psDBF->pszCodePage, REINTERPRET_CAST(char *, pabyBuf));
     }
 
     /* -------------------------------------------------------------------- */
     /*  Read in Field Definitions                                           */
     /* -------------------------------------------------------------------- */
-    pabyBuf = STATIC_CAST(unsigned char *, realloc(pabyBuf, nHeadLen));
+
+    // To please Coverity Scan
+    assert(nHeadLen < 65536);
+    unsigned char *pabyBufNew =
+        STATIC_CAST(unsigned char *, realloc(pabyBuf, nHeadLen));
+    if (!pabyBufNew)
+    {
+        psDBF->sHooks.FClose(psDBF->fp);
+        free(pabyBuf);
+        free(psDBF->pszCurrentRecord);
+        free(psDBF->pszCodePage);
+        free(psDBF);
+        return SHPLIB_NULLPTR;
+    }
+    pabyBuf = pabyBufNew;
     psDBF->pszHeader = REINTERPRET_CAST(char *, pabyBuf);
 
     psDBF->sHooks.FSeek(psDBF->fp, XBASE_FILEHDR_SZ, 0);
@@ -478,6 +524,12 @@ DBFHandle SHPAPI_CALL DBFOpenLL(const char *pszFilename, const char *pszAccess,
     psDBF->panFieldSize = STATIC_CAST(int *, malloc(sizeof(int) * nFields));
     psDBF->panFieldDecimals = STATIC_CAST(int *, malloc(sizeof(int) * nFields));
     psDBF->pachFieldType = STATIC_CAST(char *, malloc(sizeof(char) * nFields));
+    if (!psDBF->panFieldOffset || !psDBF->panFieldSize ||
+        !psDBF->panFieldDecimals || !psDBF->pachFieldType)
+    {
+        DBFClose(psDBF);
+        return SHPLIB_NULLPTR;
+    }
 
     for (int iField = 0; iField < nFields; iField++)
     {
@@ -625,6 +677,8 @@ DBFHandle SHPAPI_CALL DBFCreateLL(const char *pszFilename,
     /* -------------------------------------------------------------------- */
     const int nLenWithoutExtension = DBFGetLenWithoutExtension(pszFilename);
     char *pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
+    if (!pszFullname)
+        return SHPLIB_NULLPTR;
     memcpy(pszFullname, pszFilename, nLenWithoutExtension);
     memcpy(pszFullname + nLenWithoutExtension, ".dbf", 5);
 
@@ -634,6 +688,16 @@ DBFHandle SHPAPI_CALL DBFCreateLL(const char *pszFilename,
     SAFile fp = psHooks->FOpen(pszFullname, "wb+", psHooks->pvUserData);
     if (fp == SHPLIB_NULLPTR)
     {
+        const size_t nMessageLen = strlen(pszFullname) + 256;
+        char *pszMessage = STATIC_CAST(char *, malloc(nMessageLen));
+        if (pszMessage)
+        {
+            snprintf(pszMessage, nMessageLen, "Failed to create file %s: %s",
+                     pszFullname, strerror(errno));
+            psHooks->Error(pszMessage);
+            free(pszMessage);
+        }
+
         free(pszFullname);
         return SHPLIB_NULLPTR;
     }
@@ -670,6 +734,10 @@ DBFHandle SHPAPI_CALL DBFCreateLL(const char *pszFilename,
     /*      Create the info structure.                                      */
     /* -------------------------------------------------------------------- */
     DBFHandle psDBF = STATIC_CAST(DBFHandle, calloc(1, sizeof(DBFInfo)));
+    if (!psDBF)
+    {
+        return SHPLIB_NULLPTR;
+    }
 
     memcpy(&(psDBF->sHooks), psHooks, sizeof(SAHooks));
     psDBF->fp = fp;
@@ -697,7 +765,8 @@ DBFHandle SHPAPI_CALL DBFCreateLL(const char *pszFilename,
     {
         psDBF->pszCodePage =
             STATIC_CAST(char *, malloc(strlen(pszCodePage) + 1));
-        strcpy(psDBF->pszCodePage, pszCodePage);
+        if (psDBF->pszCodePage)
+            strcpy(psDBF->pszCodePage, pszCodePage);
     }
     DBFSetLastModifiedDate(psDBF, 95, 7, 26); /* dummy date */
 
@@ -804,19 +873,67 @@ int SHPAPI_CALL DBFAddNativeFieldType(DBFHandle psDBF, const char *pszFieldName,
     /*      realloc all the arrays larger to hold the additional field      */
     /*      information.                                                    */
     /* -------------------------------------------------------------------- */
-    psDBF->nFields++;
 
-    psDBF->panFieldOffset = STATIC_CAST(
-        int *, realloc(psDBF->panFieldOffset, sizeof(int) * psDBF->nFields));
+    int *panFieldOffsetNew =
+        STATIC_CAST(int *, realloc(psDBF->panFieldOffset,
+                                   sizeof(int) * (psDBF->nFields + 1)));
 
-    psDBF->panFieldSize = STATIC_CAST(
-        int *, realloc(psDBF->panFieldSize, sizeof(int) * psDBF->nFields));
+    int *panFieldSizeNew =
+        STATIC_CAST(int *, realloc(psDBF->panFieldSize,
+                                   sizeof(int) * (psDBF->nFields + 1)));
 
-    psDBF->panFieldDecimals = STATIC_CAST(
-        int *, realloc(psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields));
+    int *panFieldDecimalsNew =
+        STATIC_CAST(int *, realloc(psDBF->panFieldDecimals,
+                                   sizeof(int) * (psDBF->nFields + 1)));
 
-    psDBF->pachFieldType = STATIC_CAST(
-        char *, realloc(psDBF->pachFieldType, sizeof(char) * psDBF->nFields));
+    char *pachFieldTypeNew =
+        STATIC_CAST(char *, realloc(psDBF->pachFieldType,
+                                    sizeof(char) * (psDBF->nFields + 1)));
+
+    char *pszHeaderNew =
+        STATIC_CAST(char *, realloc(psDBF->pszHeader,
+                                    (psDBF->nFields + 1) * XBASE_FLDHDR_SZ));
+
+    /* -------------------------------------------------------------------- */
+    /*      Make the current record buffer appropriately larger.            */
+    /* -------------------------------------------------------------------- */
+    char *pszCurrentRecordNew =
+        STATIC_CAST(char *, realloc(psDBF->pszCurrentRecord,
+                                    psDBF->nRecordLength + nWidth));
+
+    if (panFieldOffsetNew)
+        psDBF->panFieldOffset = panFieldOffsetNew;
+    if (panFieldSizeNew)
+        psDBF->panFieldSize = panFieldSizeNew;
+    if (panFieldDecimalsNew)
+        psDBF->panFieldDecimals = panFieldDecimalsNew;
+    if (pachFieldTypeNew)
+        psDBF->pachFieldType = pachFieldTypeNew;
+    if (pszHeaderNew)
+        psDBF->pszHeader = pszHeaderNew;
+    if (pszCurrentRecordNew)
+        psDBF->pszCurrentRecord = pszCurrentRecordNew;
+
+    if (!panFieldOffsetNew || !panFieldSizeNew || !panFieldDecimalsNew ||
+        !pachFieldTypeNew || !pszHeaderNew || !pszCurrentRecordNew)
+    {
+        psDBF->sHooks.Error("Out of memory");
+        return -1;
+    }
+
+    /* alloc record */
+    char *pszRecord = SHPLIB_NULLPTR;
+    if (!psDBF->bNoHeader)
+    {
+        pszRecord = STATIC_CAST(char *, malloc(psDBF->nRecordLength + nWidth));
+        if (!pszRecord)
+        {
+            psDBF->sHooks.Error("Out of memory");
+            return -1;
+        }
+    }
+
+    psDBF->nFields++;
 
     /* -------------------------------------------------------------------- */
     /*      Assign the new field information fields.                        */
@@ -833,9 +950,6 @@ int SHPAPI_CALL DBFAddNativeFieldType(DBFHandle psDBF, const char *pszFieldName,
     psDBF->nHeaderLength += XBASE_FLDHDR_SZ;
     psDBF->bUpdated = FALSE;
 
-    psDBF->pszHeader = STATIC_CAST(
-        char *, realloc(psDBF->pszHeader, psDBF->nFields * XBASE_FLDHDR_SZ));
-
     char *pszFInfo = psDBF->pszHeader + XBASE_FLDHDR_SZ * (psDBF->nFields - 1);
 
     for (int i = 0; i < XBASE_FLDHDR_SZ; i++)
@@ -856,12 +970,6 @@ int SHPAPI_CALL DBFAddNativeFieldType(DBFHandle psDBF, const char *pszFieldName,
         pszFInfo[17] = STATIC_CAST(unsigned char, nDecimals);
     }
 
-    /* -------------------------------------------------------------------- */
-    /*      Make the current record buffer appropriately larger.            */
-    /* -------------------------------------------------------------------- */
-    psDBF->pszCurrentRecord = STATIC_CAST(
-        char *, realloc(psDBF->pszCurrentRecord, psDBF->nRecordLength));
-
     /* we're done if dealing with new .dbf */
     if (psDBF->bNoHeader)
         return (psDBF->nFields - 1);
@@ -870,10 +978,6 @@ int SHPAPI_CALL DBFAddNativeFieldType(DBFHandle psDBF, const char *pszFieldName,
     /*      For existing .dbf file, shift records                           */
     /* -------------------------------------------------------------------- */
 
-    /* alloc record */
-    char *pszRecord =
-        STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
-
     const char chFieldFill = DBFGetNullCharacter(chType);
 
     SAOffset nRecordOffset;
@@ -1346,14 +1450,14 @@ static bool DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
             char szFormat[20];
             snprintf(szFormat, sizeof(szFormat), "%%%d.%df", nWidth,
                      psDBF->panFieldDecimals[iField]);
-            CPLsnprintf(szSField, sizeof(szSField), szFormat,
-                        *STATIC_CAST(double *, pValue));
+            const double value = *STATIC_CAST(double *, pValue);
+            CPLsnprintf(szSField, sizeof(szSField), szFormat, value);
             szSField[sizeof(szSField) - 1] = '\0';
             if (STATIC_CAST(int, strlen(szSField)) >
                 psDBF->panFieldSize[iField])
             {
                 szSField[psDBF->panFieldSize[iField]] = '\0';
-                nRetResult = false;
+                nRetResult = psDBF->sHooks.Atof(szSField) == value;
             }
             memcpy(REINTERPRET_CAST(char *,
                                     pabyRec + psDBF->panFieldOffset[iField]),
@@ -1781,11 +1885,7 @@ int SHPAPI_CALL DBFMarkRecordDeleted(DBFHandle psDBF, int iShape,
     /* -------------------------------------------------------------------- */
     /*      Assign value, marking record as dirty if it changes.            */
     /* -------------------------------------------------------------------- */
-    char chNewFlag;
-    if (bIsDeleted)
-        chNewFlag = '*';
-    else
-        chNewFlag = ' ';
+    const char chNewFlag = bIsDeleted ? '*' : ' ';
 
     if (psDBF->pszCurrentRecord[0] != chNewFlag)
     {
@@ -1963,6 +2063,31 @@ int SHPAPI_CALL DBFReorderFields(DBFHandle psDBF, const int *panMap)
         STATIC_CAST(char *, calloc(psDBF->nFields, sizeof(char)));
     char *pszHeaderNew = STATIC_CAST(
         char *, malloc(sizeof(char) * XBASE_FLDHDR_SZ * psDBF->nFields));
+    char *pszRecord = SHPLIB_NULLPTR;
+    char *pszRecordNew = SHPLIB_NULLPTR;
+    if (!(psDBF->bNoHeader && psDBF->nRecords == 0))
+    {
+        /* alloc record */
+        pszRecord =
+            STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
+        pszRecordNew =
+            STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
+    }
+    if (!panFieldOffsetNew || !panFieldSizeNew || !panFieldDecimalsNew ||
+        !pachFieldTypeNew || !pszHeaderNew ||
+        (!(psDBF->bNoHeader && psDBF->nRecords == 0) &&
+         (!pszRecord || !pszRecordNew)))
+    {
+        free(panFieldOffsetNew);
+        free(panFieldSizeNew);
+        free(panFieldDecimalsNew);
+        free(pachFieldTypeNew);
+        free(pszHeaderNew);
+        free(pszRecord);
+        free(pszRecordNew);
+        psDBF->sHooks.Error("Out of memory");
+        return FALSE;
+    }
 
     /* shuffle fields definitions */
     for (int i = 0; i < psDBF->nFields; i++)
@@ -1992,12 +2117,6 @@ int SHPAPI_CALL DBFReorderFields(DBFHandle psDBF, const int *panMap)
         psDBF->bNoHeader = TRUE;
         DBFUpdateHeader(psDBF);
 
-        /* alloc record */
-        char *pszRecord =
-            STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
-        char *pszRecordNew =
-            STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
-
         /* shuffle fields in records */
         for (int iRecord = 0; iRecord < psDBF->nRecords; iRecord++)
         {
@@ -2028,12 +2147,12 @@ int SHPAPI_CALL DBFReorderFields(DBFHandle psDBF, const int *panMap)
             psDBF->sHooks.FWrite(pszRecordNew, psDBF->nRecordLength, 1,
                                  psDBF->fp);
         }
-
-        /* free record */
-        free(pszRecord);
-        free(pszRecordNew);
     }
 
+    /* free record */
+    free(pszRecord);
+    free(pszRecordNew);
+
     if (errorAbort)
     {
         free(panFieldOffsetNew);
@@ -2096,6 +2215,31 @@ int SHPAPI_CALL DBFAlterFieldDefn(DBFHandle psDBF, int iField,
     if (nWidth > XBASE_FLD_MAX_WIDTH)
         nWidth = XBASE_FLD_MAX_WIDTH;
 
+    char *pszRecord = STATIC_CAST(
+        char *, malloc(nOldRecordLength +
+                       ((nWidth > nOldWidth) ? nWidth - nOldWidth : 0)));
+    char *pszOldField = STATIC_CAST(char *, malloc(nOldWidth + 1));
+    if (!pszRecord || !pszOldField)
+    {
+        free(pszRecord);
+        free(pszOldField);
+        return FALSE;
+    }
+
+    if (nWidth != nOldWidth)
+    {
+        char *pszCurrentRecordNew = STATIC_CAST(
+            char *, realloc(psDBF->pszCurrentRecord,
+                            psDBF->nRecordLength + nWidth - nOldWidth));
+        if (!pszCurrentRecordNew)
+        {
+            free(pszRecord);
+            free(pszOldField);
+            return FALSE;
+        }
+        psDBF->pszCurrentRecord = pszCurrentRecordNew;
+    }
+
     /* -------------------------------------------------------------------- */
     /*      Assign the new field information fields.                        */
     /* -------------------------------------------------------------------- */
@@ -2134,14 +2278,15 @@ int SHPAPI_CALL DBFAlterFieldDefn(DBFHandle psDBF, int iField,
         for (int i = iField + 1; i < psDBF->nFields; i++)
             psDBF->panFieldOffset[i] += nWidth - nOldWidth;
         psDBF->nRecordLength += nWidth - nOldWidth;
-
-        psDBF->pszCurrentRecord = STATIC_CAST(
-            char *, realloc(psDBF->pszCurrentRecord, psDBF->nRecordLength));
     }
 
     /* we're done if we're dealing with not yet created .dbf */
     if (psDBF->bNoHeader && psDBF->nRecords == 0)
+    {
+        free(pszRecord);
+        free(pszOldField);
         return TRUE;
+    }
 
     /* force update of header with new header and record length */
     psDBF->bNoHeader = TRUE;
@@ -2151,11 +2296,6 @@ int SHPAPI_CALL DBFAlterFieldDefn(DBFHandle psDBF, int iField,
 
     if (nWidth < nOldWidth || (nWidth == nOldWidth && chType != chOldType))
     {
-        char *pszRecord =
-            STATIC_CAST(char *, malloc(sizeof(char) * nOldRecordLength));
-        char *pszOldField =
-            STATIC_CAST(char *, malloc(sizeof(char) * (nOldWidth + 1)));
-
         pszOldField[nOldWidth] = 0;
 
         /* move records to their new positions */
@@ -2223,17 +2363,9 @@ int SHPAPI_CALL DBFAlterFieldDefn(DBFHandle psDBF, int iField,
             psDBF->sHooks.FWrite(&ch, 1, 1, psDBF->fp);
         }
         /* TODO: truncate file */
-
-        free(pszRecord);
-        free(pszOldField);
     }
     else if (nWidth > nOldWidth)
     {
-        char *pszRecord =
-            STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
-        char *pszOldField =
-            STATIC_CAST(char *, malloc(sizeof(char) * (nOldWidth + 1)));
-
         pszOldField[nOldWidth] = 0;
 
         /* move records to their new positions */
@@ -2296,7 +2428,7 @@ int SHPAPI_CALL DBFAlterFieldDefn(DBFHandle psDBF, int iField,
 
         if (!errorAbort && psDBF->bWriteEndOfFileChar)
         {
-            char ch = END_OF_FILE_CHARACTER;
+            const char ch = END_OF_FILE_CHARACTER;
 
             SAOffset nRecordOffset =
                 psDBF->nRecordLength * STATIC_CAST(SAOffset, psDBF->nRecords) +
@@ -2305,11 +2437,11 @@ int SHPAPI_CALL DBFAlterFieldDefn(DBFHandle psDBF, int iField,
             psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, 0);
             psDBF->sHooks.FWrite(&ch, 1, 1, psDBF->fp);
         }
-
-        free(pszRecord);
-        free(pszOldField);
     }
 
+    free(pszRecord);
+    free(pszOldField);
+
     if (errorAbort)
     {
         psDBF->nCurrentRecord = -1;


=====================================
safileio.c
=====================================
@@ -13,7 +13,7 @@
  *
  */
 
-#include "shapefil.h"
+#include "shapefil_private.h"
 
 #include <assert.h>
 #include <math.h>
@@ -101,7 +101,7 @@ void SASetupDefaultHooks(SAHooks *psHooks)
 
     psHooks->Error = SADError;
     psHooks->Atof = atof;
-    psHooks->pvUserData = NULL;
+    psHooks->pvUserData = SHPLIB_NULLPTR;
 }
 
 #ifdef SHPAPI_WINDOWS
@@ -182,5 +182,6 @@ void SASetupUtf8Hooks(SAHooks *psHooks)
 
     psHooks->Error = SADError;
     psHooks->Atof = atof;
+    psHooks->pvUserData = SHPLIB_NULLPTR;
 }
 #endif


=====================================
sbnsearch.c
=====================================
@@ -38,6 +38,7 @@
                       ((ptr)[1] << 16) | ((ptr)[2] << 8) | (ptr)[3]))
 
 typedef int coord;
+
 /*typedef unsigned char coord;*/
 
 typedef struct
@@ -127,6 +128,8 @@ SBNSearchHandle SBNOpenDiskTree(const char *pszSBNFilename,
     /* -------------------------------------------------------------------- */
     SBNSearchHandle hSBN =
         STATIC_CAST(SBNSearchHandle, calloc(1, sizeof(struct SBNSearchInfo)));
+    if (!hSBN)
+        return SHPLIB_NULLPTR;
 
     if (psHooks == SHPLIB_NULLPTR)
         SASetupDefaultHooks(&(hSBN->sHooks));


=====================================
shapefil.h
=====================================
@@ -33,7 +33,7 @@ extern "C"
 
 #define SHAPELIB_VERSION_MAJOR 1
 #define SHAPELIB_VERSION_MINOR 6
-#define SHAPELIB_VERSION_MICRO 1
+#define SHAPELIB_VERSION_MICRO 2
 
 #define SHAPELIB_MAKE_VERSION_NUMBER(major, minor, micro)                      \
     ((major) * 10000 + (minor) * 100 + (micro))
@@ -419,7 +419,7 @@ extern "C"
     /************************************************************************/
     /*                             DBF Support.                             */
     /************************************************************************/
-    typedef struct
+    typedef struct DBFInfo
     {
         SAHooks sHooks;
 
@@ -467,7 +467,7 @@ extern "C"
         int bRequireNextWriteSeek;
     } DBFInfo;
 
-    typedef DBFInfo *DBFHandle;
+    typedef struct DBFInfo *DBFHandle;
 
     typedef enum
     {


=====================================
shpopen.c
=====================================
@@ -183,7 +183,7 @@ void SHPAPI_CALL SHPWriteHeader(SHPHandle psSHP)
         STATIC_CAST(uint32_t *, malloc(sizeof(uint32_t) * 2 * psSHP->nRecords));
     if (panSHX == SHPLIB_NULLPTR)
     {
-        psSHP->sHooks.Error("Failure allocatin panSHX");
+        psSHP->sHooks.Error("Failure allocating panSHX");
         return;
     }
 
@@ -280,6 +280,8 @@ SHPHandle SHPAPI_CALL SHPOpenLL(const char *pszLayer, const char *pszAccess,
     /*  Initialize the info structure.                  */
     /* -------------------------------------------------------------------- */
     SHPHandle psSHP = STATIC_CAST(SHPHandle, calloc(1, sizeof(SHPInfo)));
+    if (!psSHP)
+        return SHPLIB_NULLPTR;
 
     psSHP->bUpdated = FALSE;
     memcpy(&(psSHP->sHooks), psHooks, sizeof(SAHooks));
@@ -290,6 +292,11 @@ SHPHandle SHPAPI_CALL SHPOpenLL(const char *pszLayer, const char *pszAccess,
     /* -------------------------------------------------------------------- */
     const int nLenWithoutExtension = SHPGetLenWithoutExtension(pszLayer);
     char *pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
+    if (!pszFullname)
+    {
+        free(psSHP);
+        return SHPLIB_NULLPTR;
+    }
     memcpy(pszFullname, pszLayer, nLenWithoutExtension);
     memcpy(pszFullname + nLenWithoutExtension, ".shp", 5);
     psSHP->fpSHP =
@@ -305,12 +312,15 @@ SHPHandle SHPAPI_CALL SHPOpenLL(const char *pszLayer, const char *pszAccess,
     {
         const size_t nMessageLen = strlen(pszFullname) * 2 + 256;
         char *pszMessage = STATIC_CAST(char *, malloc(nMessageLen));
-        pszFullname[nLenWithoutExtension] = 0;
-        snprintf(pszMessage, nMessageLen,
-                 "Unable to open %s.shp or %s.SHP in %s mode.", pszFullname,
-                 pszFullname, pszAccess);
-        psHooks->Error(pszMessage);
-        free(pszMessage);
+        if (pszMessage)
+        {
+            pszFullname[nLenWithoutExtension] = 0;
+            snprintf(pszMessage, nMessageLen,
+                     "Unable to open %s.shp or %s.SHP in %s mode.", pszFullname,
+                     pszFullname, pszAccess);
+            psHooks->Error(pszMessage);
+            free(pszMessage);
+        }
 
         free(psSHP);
         free(pszFullname);
@@ -333,13 +343,16 @@ SHPHandle SHPAPI_CALL SHPOpenLL(const char *pszLayer, const char *pszAccess,
         const size_t nMessageLen =
             64 + strlen(pszFullname) * 2 + strlen(SHP_RESTORE_SHX_HINT_MESSAGE);
         char *pszMessage = STATIC_CAST(char *, malloc(nMessageLen));
-        pszFullname[nLenWithoutExtension] = 0;
-        snprintf(
-            pszMessage, nMessageLen,
-            "Unable to open %s.shx or %s.SHX." SHP_RESTORE_SHX_HINT_MESSAGE,
-            pszFullname, pszFullname);
-        psHooks->Error(pszMessage);
-        free(pszMessage);
+        if (pszMessage)
+        {
+            pszFullname[nLenWithoutExtension] = 0;
+            snprintf(
+                pszMessage, nMessageLen,
+                "Unable to open %s.shx or %s.SHX." SHP_RESTORE_SHX_HINT_MESSAGE,
+                pszFullname, pszFullname);
+            psHooks->Error(pszMessage);
+            free(pszMessage);
+        }
 
         psSHP->sHooks.FClose(psSHP->fpSHP);
         free(psSHP);
@@ -353,7 +366,7 @@ SHPHandle SHPAPI_CALL SHPOpenLL(const char *pszLayer, const char *pszAccess,
     /*  Read the file size from the SHP file.               */
     /* -------------------------------------------------------------------- */
     unsigned char *pabyBuf = STATIC_CAST(unsigned char *, malloc(100));
-    if (psSHP->sHooks.FRead(pabyBuf, 100, 1, psSHP->fpSHP) != 1)
+    if (!pabyBuf || psSHP->sHooks.FRead(pabyBuf, 100, 1, psSHP->fpSHP) != 1)
     {
         psSHP->sHooks.Error(".shp file is unreadable, or corrupt.");
         psSHP->sHooks.FClose(psSHP->fpSHP);
@@ -661,6 +674,8 @@ int SHPAPI_CALL SHPRestoreSHX(const char *pszLayer, const char *pszAccess,
     /* -------------------------------------------------------------------- */
     const int nLenWithoutExtension = SHPGetLenWithoutExtension(pszLayer);
     char *pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
+    if (!pszFullname)
+        return 0;
     memcpy(pszFullname, pszLayer, nLenWithoutExtension);
     memcpy(pszFullname + nLenWithoutExtension, ".shp", 5);
     SAFile fpSHP = psHooks->FOpen(pszFullname, pszAccess, psHooks->pvUserData);
@@ -674,12 +689,15 @@ int SHPAPI_CALL SHPRestoreSHX(const char *pszLayer, const char *pszAccess,
     {
         const size_t nMessageLen = strlen(pszFullname) * 2 + 256;
         char *pszMessage = STATIC_CAST(char *, malloc(nMessageLen));
-
-        pszFullname[nLenWithoutExtension] = 0;
-        snprintf(pszMessage, nMessageLen, "Unable to open %s.shp or %s.SHP.",
-                 pszFullname, pszFullname);
-        psHooks->Error(pszMessage);
-        free(pszMessage);
+        if (pszMessage)
+        {
+            pszFullname[nLenWithoutExtension] = 0;
+            snprintf(pszMessage, nMessageLen,
+                     "Unable to open %s.shp or %s.SHP.", pszFullname,
+                     pszFullname);
+            psHooks->Error(pszMessage);
+            free(pszMessage);
+        }
 
         free(pszFullname);
 
@@ -717,11 +735,14 @@ int SHPAPI_CALL SHPRestoreSHX(const char *pszLayer, const char *pszAccess,
     {
         size_t nMessageLen = strlen(pszFullname) * 2 + 256;
         char *pszMessage = STATIC_CAST(char *, malloc(nMessageLen));
-        pszFullname[nLenWithoutExtension] = 0;
-        snprintf(pszMessage, nMessageLen,
-                 "Error opening file %s.shx for writing", pszFullname);
-        psHooks->Error(pszMessage);
-        free(pszMessage);
+        if (pszMessage)
+        {
+            pszFullname[nLenWithoutExtension] = 0;
+            snprintf(pszMessage, nMessageLen,
+                     "Error opening file %s.shx for writing", pszFullname);
+            psHooks->Error(pszMessage);
+            free(pszMessage);
+        }
 
         psHooks->FClose(fpSHP);
 
@@ -736,6 +757,15 @@ int SHPAPI_CALL SHPRestoreSHX(const char *pszLayer, const char *pszAccess,
     /* -------------------------------------------------------------------- */
     psHooks->FSeek(fpSHP, 100, 0);
     char *pabySHXHeader = STATIC_CAST(char *, malloc(100));
+    if (!pabySHXHeader)
+    {
+        psHooks->FClose(fpSHP);
+
+        free(pabyBuf);
+        free(pszFullname);
+
+        return (0);
+    }
     memcpy(pabySHXHeader, pabyBuf, 100);
     psHooks->FWrite(pabySHXHeader, 100, 1, fpSHX);
     free(pabyBuf);
@@ -978,22 +1008,37 @@ SHPHandle SHPAPI_CALL SHPCreate(const char *pszLayer, int nShapeType)
 SHPHandle SHPAPI_CALL SHPCreateLL(const char *pszLayer, int nShapeType,
                                   const SAHooks *psHooks)
 {
+
+    SHPHandle psSHP = STATIC_CAST(SHPHandle, calloc(1, sizeof(SHPInfo)));
+    if (!psSHP)
+        return SHPLIB_NULLPTR;
+
     /* -------------------------------------------------------------------- */
     /*      Open the two files so we can write their headers.               */
     /* -------------------------------------------------------------------- */
     const int nLenWithoutExtension = SHPGetLenWithoutExtension(pszLayer);
     char *pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
+    if (!pszFullname)
+    {
+        free(psSHP);
+        return SHPLIB_NULLPTR;
+    }
     memcpy(pszFullname, pszLayer, nLenWithoutExtension);
     memcpy(pszFullname + nLenWithoutExtension, ".shp", 5);
     SAFile fpSHP = psHooks->FOpen(pszFullname, "w+b", psHooks->pvUserData);
     if (fpSHP == SHPLIB_NULLPTR)
     {
-        char szErrorMsg[200];
-        snprintf(szErrorMsg, sizeof(szErrorMsg), "Failed to create file %s: %s",
-                 pszFullname, strerror(errno));
-        psHooks->Error(szErrorMsg);
-
+        const size_t nMessageLen = strlen(pszFullname) + 256;
+        char *pszMessage = STATIC_CAST(char *, malloc(nMessageLen));
+        if (pszMessage)
+        {
+            snprintf(pszMessage, nMessageLen, "Failed to create file %s: %s",
+                     pszFullname, strerror(errno));
+            psHooks->Error(pszMessage);
+            free(pszMessage);
+        }
         free(pszFullname);
+        free(psSHP);
         return SHPLIB_NULLPTR;
     }
 
@@ -1001,13 +1046,19 @@ SHPHandle SHPAPI_CALL SHPCreateLL(const char *pszLayer, int nShapeType,
     SAFile fpSHX = psHooks->FOpen(pszFullname, "w+b", psHooks->pvUserData);
     if (fpSHX == SHPLIB_NULLPTR)
     {
-        char szErrorMsg[200];
-        snprintf(szErrorMsg, sizeof(szErrorMsg), "Failed to create file %s: %s",
-                 pszFullname, strerror(errno));
-        psHooks->Error(szErrorMsg);
+        const size_t nMessageLen = strlen(pszFullname) + 256;
+        char *pszMessage = STATIC_CAST(char *, malloc(nMessageLen));
+        if (pszMessage)
+        {
+            snprintf(pszMessage, nMessageLen, "Failed to create file %s: %s",
+                     pszFullname, strerror(errno));
+            psHooks->Error(pszMessage);
+            free(pszMessage);
+        }
 
         free(pszFullname);
         psHooks->FClose(fpSHP);
+        free(psSHP);
         return SHPLIB_NULLPTR;
     }
 
@@ -1062,6 +1113,7 @@ SHPHandle SHPAPI_CALL SHPCreateLL(const char *pszLayer, int nShapeType,
         free(pszFullname);
         psHooks->FClose(fpSHP);
         psHooks->FClose(fpSHX);
+        free(psSHP);
         return SHPLIB_NULLPTR;
     }
 
@@ -1086,11 +1138,10 @@ SHPHandle SHPAPI_CALL SHPCreateLL(const char *pszLayer, int nShapeType,
         free(pszFullname);
         psHooks->FClose(fpSHP);
         psHooks->FClose(fpSHX);
+        free(psSHP);
         return SHPLIB_NULLPTR;
     }
 
-    SHPHandle psSHP = STATIC_CAST(SHPHandle, calloc(1, sizeof(SHPInfo)));
-
     psSHP->bUpdated = FALSE;
     memcpy(&(psSHP->sHooks), psHooks, sizeof(SAHooks));
 
@@ -1191,6 +1242,8 @@ SHPObject SHPAPI_CALL1(*)
 {
     SHPObject *psObject =
         STATIC_CAST(SHPObject *, calloc(1, sizeof(SHPObject)));
+    if (!psObject)
+        return SHPLIB_NULLPTR;
     psObject->nSHPType = nSHPType;
     psObject->nShapeId = nShapeId;
     psObject->bMeasureIsUsed = FALSE;
@@ -1235,6 +1288,13 @@ SHPObject SHPAPI_CALL1(*)
             STATIC_CAST(int *, calloc(psObject->nParts, sizeof(int)));
         psObject->panPartType =
             STATIC_CAST(int *, malloc(sizeof(int) * psObject->nParts));
+        if (!psObject->panPartStart || !psObject->panPartType)
+        {
+            free(psObject->panPartStart);
+            free(psObject->panPartType);
+            free(psObject);
+            return SHPLIB_NULLPTR;
+        }
 
         psObject->panPartStart[0] = 0;
         psObject->panPartType[0] = SHPP_RING;
@@ -1271,6 +1331,18 @@ SHPObject SHPAPI_CALL1(*)
         psObject->padfM = STATIC_CAST(
             double *,
             padfM &&bHasM ? malloc(nSize) : calloc(nVertices, sizeof(double)));
+        if (!psObject->padfX || !psObject->padfY || !psObject->padfZ ||
+            !psObject->padfM)
+        {
+            free(psObject->panPartStart);
+            free(psObject->panPartType);
+            free(psObject->padfX);
+            free(psObject->padfY);
+            free(psObject->padfZ);
+            free(psObject->padfM);
+            free(psObject);
+            return SHPLIB_NULLPTR;
+        }
         if (padfX != SHPLIB_NULLPTR)
             memcpy(psObject->padfX, padfX, nSize);
         if (padfY != SHPLIB_NULLPTR)
@@ -2123,6 +2195,11 @@ SHPObject SHPAPI_CALL1(*) SHPReadObject(const SHPHandle psSHP, int hEntity)
     else
     {
         psShape = STATIC_CAST(SHPObject *, calloc(1, sizeof(SHPObject)));
+        if (!psShape)
+        {
+            psSHP->sHooks.Error("Out of memory.");
+            return SHPLIB_NULLPTR;
+        }
     }
     psShape->nShapeId = hEntity;
     psShape->nSHPType = nSHPType;


=====================================
shptree.c
=====================================
@@ -678,6 +678,8 @@ SHPTreeDiskHandle SHPOpenDiskTree(const char *pszQIXFilename,
 
     hDiskTree = STATIC_CAST(SHPTreeDiskHandle,
                             calloc(1, sizeof(struct SHPDiskTreeInfo)));
+    if (!hDiskTree)
+        return SHPLIB_NULLPTR;
 
     if (psHooks == SHPLIB_NULLPTR)
         SASetupDefaultHooks(&(hDiskTree->sHooks));


=====================================
tests/CMakeLists.txt
=====================================
@@ -1,16 +1,31 @@
-# CMake configuration for SHP C++ unit tests
+# CMake configuration for C++ unit tests
 
 project(${CMAKE_PROJECT_NAME}Tests CXX)
 
-# Set up GoogleTest
+# Set up GoogleTest and Benchmark
 include(FetchContent)
 
+FetchContent_Declare(
+  benchmark
+  GIT_REPOSITORY https://github.com/google/benchmark.git
+  GIT_TAG v1.9.4
+  GIT_SHALLOW TRUE
+)
+
 FetchContent_Declare(
   googletest
   GIT_REPOSITORY https://github.com/google/googletest.git
-  GIT_TAG v1.15.2
+  GIT_TAG v1.17.0
+  GIT_SHALLOW TRUE
 )
 
+set(BENCHMARK_DOWNLOAD_DEPENDENCIES OFF CACHE BOOL "" FORCE)
+set(BENCHMARK_ENABLE_INSTALL OFF CACHE BOOL "" FORCE)
+set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "" FORCE)
+set(BENCHMARK_INSTALL_DOCS OFF CACHE BOOL "" FORCE)
+
+FetchContent_MakeAvailable(benchmark)
+
 # For Windows: Prevent overriding the parent project's compiler/linker settings
 set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
 
@@ -22,16 +37,23 @@ set(INSTALL_GTEST OFF CACHE BOOL "" FORCE)
 
 FetchContent_MakeAvailable(googletest)
 
-foreach(executable dbf_test sbn_test shp_test)
+set_target_properties(gtest gtest_main benchmark benchmark_main PROPERTIES FOLDER "tests/third-party")
+
+foreach(executable dbf_test sbn_test shp_test shp_bench)
   add_executable(${executable} ${PROJECT_SOURCE_DIR}/${executable}.cc)
-  target_link_libraries(${executable} PRIVATE ${PACKAGE} gtest)
+  target_link_libraries(${executable} PRIVATE ${PACKAGE} gtest benchmark)
   add_test(
     NAME ${executable}
     COMMAND ${executable}
     WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
   )
   target_compile_features(${executable} PUBLIC cxx_std_17)
-  set_target_properties(${executable} PROPERTIES FOLDER "tests" CXX_EXTENSIONS OFF)
+  if("${executable}" MATCHES ".*_bench$")
+    set(exec_folder "tests/bench")
+  else()
+    set(exec_folder "tests")
+  endif()  
+  set_target_properties(${executable} PROPERTIES FOLDER ${exec_folder} CXX_EXTENSIONS OFF)
   if (BUILD_SHARED_LIBS AND ${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.21" AND (WIN32 OR CYGWIN))
     add_custom_command(
       TARGET ${executable} POST_BUILD


=====================================
tests/dbf_test.cc
=====================================
@@ -309,7 +309,7 @@ TEST(DBFFieldTest, SetAndGetLogicalFalse)
     fs::remove(filename);
 }
 
-TEST(DBFFieldTest, SetAndGetLogicalInvalid)
+TEST(DBFFieldTest, SetLogicalInvalid)
 {
     const auto filename =
         fs::temp_directory_path() / GenerateUniqueFilename(".dbf");
@@ -318,6 +318,80 @@ TEST(DBFFieldTest, SetAndGetLogicalInvalid)
     fs::remove(filename);
 }
 
+TEST(DBFFieldTest, SetAndGetDouble)
+{
+    const auto filename =
+        fs::temp_directory_path() / GenerateUniqueFilename(".dbf");
+    constexpr const double value = 1623819823.809;
+    {
+        const auto handle = DBFCreate(filename.string().c_str());
+        EXPECT_NE(nullptr, handle);
+        const auto fid = DBFAddField(handle, "double", FTDouble, 14, 4);
+        EXPECT_GE(fid, 0);
+        const auto success = DBFWriteDoubleAttribute(handle, 0, 0, value);
+        EXPECT_TRUE(success);
+        DBFClose(handle);
+    }
+    {
+        const auto handle = DBFOpen(filename.string().c_str(), "r");
+        EXPECT_NE(nullptr, handle);
+        EXPECT_EQ(value, DBFReadDoubleAttribute(handle, 0, 0));
+        DBFClose(handle);
+    }
+    fs::remove(filename);
+}
+
+static auto WriteDuplicateFields(const fs::path &filename) -> auto
+{
+    const auto handle = DBFCreate(filename.string().c_str());
+    EXPECT_NE(nullptr, handle);
+    const auto fid1 = DBFAddField(handle, "field", FTDate, 8, 0);
+    EXPECT_GE(fid1, 0);
+    const auto fid2 = DBFAddField(handle, "field", FTDate, 8, 0);
+    EXPECT_GE(fid2, 0);
+    const auto fid3 = DBFAddField(handle, "field", FTDouble, 8, 5);
+    EXPECT_GE(fid3, 0);
+    const auto fid4 = DBFAddField(handle, "field", FTDouble, 8, 10);
+    EXPECT_GE(fid4, 0);
+    const auto fid5 = DBFAddField(handle, "field", FTInteger, 8, 0);
+    EXPECT_GE(fid5, 0);
+    const auto fid6 = DBFAddField(handle, "field", FTInteger, 8, 0);
+    EXPECT_GE(fid6, 0);
+    const auto fid7 = DBFAddField(handle, "field", FTLogical, 1, 0);
+    EXPECT_GE(fid7, 0);
+    const auto fid8 = DBFAddField(handle, "field", FTLogical, 1, 0);
+    EXPECT_GE(fid8, 0);
+    const auto fid9 = DBFAddField(handle, "field", FTString, 5, 0);
+    EXPECT_GE(fid9, 0);
+    const auto fid0 = DBFAddField(handle, "field", FTString, 10, 0);
+    EXPECT_GE(fid0, 0);
+    const auto nFields = DBFGetFieldCount(handle);
+    EXPECT_EQ(nFields, 10);
+    DBFClose(handle);
+}
+
+static auto ReadDuplicateFields(const fs::path &filename) -> auto
+{
+    const auto handle = DBFOpen(filename.string().c_str(), "r");
+    EXPECT_NE(nullptr, handle);
+    const auto nFields = DBFGetFieldCount(handle);
+    EXPECT_EQ(nFields, 10);
+    const auto fid = DBFGetFieldIndex(handle, "field");
+    EXPECT_EQ(fid, 0);
+    DBFClose(handle);
+}
+
+TEST(DBFFieldTest, AddDuplicateField)
+{
+    const auto filename =
+        fs::temp_directory_path() / GenerateUniqueFilename(".dbf");
+    WriteDuplicateFields(filename);
+    const auto size = fs::file_size(filename);
+    EXPECT_EQ(354, size);
+    ReadDuplicateFields(filename);
+    fs::remove(filename);
+}
+
 }  // namespace
 
 int main(int argc, char **argv)


=====================================
tests/expect3.out
=====================================
@@ -31,7 +31,7 @@ Shape:2 (Polygon)  nVertices=4, nParts=1
      (160,150, 0)  
      (180,170, 0)  
      (150,150, 0)  
-Descriptio                     TestInt       TestDouble 
-Square with triangle missing        1           2.50000 
-Smaller triangle                  100        1000.25000 
-(NULL)                         (NULL)            (NULL) 
+Descriptio                     TestInt       TestDouble TestDate TestBool 
+Square with triangle missing        1           2.50000 20241102 T        
+Smaller triangle                  100        1000.25000 20241102 F        
+(NULL)                         (NULL)            (NULL)   (NULL) (NULL)        


=====================================
tests/shp_bench.cc
=====================================
@@ -0,0 +1,46 @@
+#include <array>
+#include <filesystem>
+
+#include <benchmark/benchmark.h>
+#include "shapefil.h"
+
+namespace fs = std::filesystem;
+namespace bm = benchmark;
+
+namespace
+{
+
+static const auto kTestData = fs::path{"shape_eg_data"};
+
+constexpr static auto filenames = std::array<const char *, 11>{
+    "3dpoints.shp", "anno.shp",     "brklinz.shp", "CoHI_GCS12.shp",
+    "csah.shp",     "masspntz.shp", "mpatch3.shp", "multipatch.shp",
+    "multipnt.shp", "pline.shp",    "polygon.shp"};
+
+static void Benchmark_ReadAll(bm::State &state)
+{
+    const auto filename = kTestData / filenames[state.range(1)];
+    const auto handle = SHPOpen(filename.string().c_str(), "rb");
+    SHPSetFastModeReadObject(handle, static_cast<int>(state.range(0)));
+    int nEntities;
+    SHPGetInfo(handle, &nEntities, nullptr, nullptr, nullptr);
+    for (auto _ : state)
+    {
+        for (int i = 0; i < nEntities; ++i)
+        {
+            auto obj = SHPReadObject(handle, i);
+            SHPDestroyObject(obj);
+        }
+    }
+    state.SetItemsProcessed(state.iterations() * nEntities);
+    SHPClose(handle);
+}
+
+BENCHMARK(Benchmark_ReadAll)
+    ->ArgsProduct({{0, 1}, bm::CreateDenseRange(0, filenames.size() - 1, 1)})
+    ->ArgNames({"fastMode", "fileId"})
+    ->Unit(bm::kMicrosecond);
+
+}  // namespace
+
+BENCHMARK_MAIN();


=====================================
tests/test3.sh
=====================================
@@ -12,16 +12,16 @@ readonly EXPECT="${1:-$SCRIPTDIR/expect3.out}"
 
 {
 "${SHPCREATE:-./shpcreate}" test polygon
-"${DBFCREATE:-./dbfcreate}" test.dbf -s Description 30 -n TestInt 6 0 -n TestDouble 16 5
+"${DBFCREATE:-./dbfcreate}" test.dbf -s Description 30 -n TestInt 6 0 -n TestDouble 16 5 -d TestDate -l TestBool
 
 "${SHPADD:-./shpadd}" test 0 0 100 0 100 100 0 100 0 0 + 20 20 20 30 30 30 20 20
-"${DBFADD:-./dbfadd}" test.dbf "Square with triangle missing" 1.4 2.5
+"${DBFADD:-./dbfadd}" test.dbf "Square with triangle missing" 1.4 2.5 20241102 T
 
 "${SHPADD:-./shpadd}" test 150 150 160 150 180 170 150 150
-"${DBFADD:-./dbfadd}" test.dbf "Smaller triangle" 100 1000.25
+"${DBFADD:-./dbfadd}" test.dbf "Smaller triangle" 100 1000.25 20241102 F
 
 "${SHPADD:-./shpadd}" test 150 150 160 150 180 170 150 150
-"${DBFADD:-./dbfadd}" test.dbf "" "" ""
+"${DBFADD:-./dbfadd}" test.dbf "" "" "" "" ""
 
 "${SHPDUMP:-./shpdump}" test.shp
 "${DBFDUMP:-./dbfdump}" test.dbf


=====================================
web/release.html
=====================================
@@ -10,6 +10,19 @@
 To get notification of new releases of Shapelib <i>subscribe</i> to
 the project mailing list at https://lists.osgeo.org/pipermail/shapelib/.<p>
 
+<b>Release 1.6.2</b>:
+<ul>
+<li>Nullify userdata also in SASetupUtf8Hooks</li>
+<li>Test suite enhancements</li>
+<li>CMake: no longer use CTest and add manual BUILD_TESTING option instead (default to OFF)</li>
+<li>Prefer tagged version of Google Benchmark</li>
+<li>dbfcreate: allow creation of Date and Logical fields #167 (#168)</li>
+<li>Fix cppcheck nullPointerOutOfMemory warnings</li>
+<li>DBFWriteAttribute(): return true when no precision loss occured when writing a double</li>
+<li>SHPCreateLL()/DBFCreate(): make error message contains full filename (in case it is very long)</li>
+</ul>
+
+
 <b>Release 1.6.1</b>:
 <ul>
 <li>DBFIsValueNULL(): accept empty string as NULL Date (https://github.com/OSGeo/gdal/issues/10405)</li>



View it on GitLab: https://salsa.debian.org/debian-gis-team/shapelib/-/commit/789bb79c5a275653c5b516f82c97b8ea718a4c09

-- 
View it on GitLab: https://salsa.debian.org/debian-gis-team/shapelib/-/commit/789bb79c5a275653c5b516f82c97b8ea718a4c09
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20250923/b72d3bfd/attachment-0001.htm>


More information about the Pkg-grass-devel mailing list