[Git][debian-gis-team/lerc][upstream] New upstream version 4.1.1+ds

Antonio Valentino (@antonio.valentino) gitlab at salsa.debian.org
Sat Jul 4 21:08:08 BST 2026



Antonio Valentino pushed to branch upstream at Debian GIS Project / lerc


Commits:
4cc04dcd by Antonio Valentino at 2026-07-04T19:53:28+00:00
New upstream version 4.1.1+ds
- - - - -


19 changed files:

- .github/workflows/build_wheels.yml
- CHANGELOG.md
- CMakeLists.txt
- HOWTO-RELEASE.md
- OtherLanguages/Python/lerc/__init__.py
- + OtherLanguages/Python/pyproject.toml
- OtherLanguages/Python/setup.py
- README.md
- src/LercLib/BitMask.cpp
- src/LercLib/BitMask.h
- src/LercLib/Lerc.cpp
- src/LercLib/Lerc.h
- src/LercLib/Lerc1Decode/CntZImage.cpp
- src/LercLib/Lerc1Decode/CntZImage.h
- src/LercLib/Lerc2.cpp
- src/LercLib/Lerc2.h
- src/LercLib/fpl_EsriHuffman.cpp
- src/LercLib/include/Lerc_c_api.h
- src/LercTest/main.cpp


Changes:

=====================================
.github/workflows/build_wheels.yml
=====================================
@@ -7,18 +7,14 @@ on:
       - 'OtherLanguages/Python/**'
       - 'src/**'
       - '.github/workflows/build_wheels.yml'
-    
     tags:
       - 'v*'
-
   pull_request:
     paths:
       - 'OtherLanguages/Python/**'
       - '.github/workflows/build_wheels.yml'
-  
   workflow_dispatch:
 
-
 jobs:
   build_wheels:
     name: Build on ${{ matrix.os }}
@@ -61,7 +57,7 @@ jobs:
         run: |
           python -m pip install --upgrade pip setuptools wheel build
           cd OtherLanguages/Python
-          python -m build
+          python -m build --wheel
 
       - name: Upload Artifacts
         uses: actions/upload-artifact at v4


=====================================
CHANGELOG.md
=====================================
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
 
 ## [Unreleased][unreleased]
 
+## [4.1.1](https://github.com/Esri/lerc/releases/tag/v4.1.1) - 2026-07-02
+
+### Fixed
+
+* Fixed two security issues and some minor bugs.
+
 ## [4.1.0](https://github.com/Esri/lerc/releases/tag/v4.1.0) - 2026-03-09
 
 ### Fixed


=====================================
CMakeLists.txt
=====================================
@@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.12)
 project(Lerc
         DESCRIPTION "Limited Error Raster Compression"
         HOMEPAGE_URL "https://github.com/Esri/lerc"
-        VERSION 4.1.0) # Keep in sync with Lerc_c_api.h
+        VERSION 4.1.1) # Keep in sync with Lerc_c_api.h
 
 include(GNUInstallDirs)
 


=====================================
HOWTO-RELEASE.md
=====================================
@@ -4,12 +4,12 @@ Update version numbers in src/LercLib/include/Lerc_c_api.h and CMakeLists.txt
 
 ### npm release
 
-- Config build environment. For 4.0 release: Node.js v16 LTS, npm 8.11
+- Config build environment. For 4.1.2 release: Node.js v24.11.1 LTS, npm 11.6.2
 - Update the following files in OtherLanguages/js
   - Run npm version xxx to update version numbers in package.json
   - Update CHANGELOG.md
-  - Update copyright year in Gruntfile.js, README.md and README.hbs
-  - If applicable, update usage in README.md and README.hbs
+  - Update copyright year in Gruntfile.js, README.md
+  - If applicable, update usage in README.md
 - Build and publish to npm
 
 ```


=====================================
OtherLanguages/Python/lerc/__init__.py
=====================================
@@ -1,3 +1,3 @@
-__version__ = "4.1"
+__version__ = "4.1.1"
 
 from ._lerc import *


=====================================
OtherLanguages/Python/pyproject.toml
=====================================
@@ -0,0 +1,3 @@
+[build-system]
+requires = ["setuptools", "wheel"]
+build-backend = "setuptools.build_meta"


=====================================
OtherLanguages/Python/setup.py
=====================================
@@ -26,8 +26,7 @@ try:
 except Exception:
     long_description = "Limited Error Raster Compression"
 
-# Using MANIFEST.in doesn't respect relative paths above the package root.
-# Instead, inspect the location and copy in the binaries if newer.
+# Stage binaries from repo root into package root
 BINARY_TYPES = ["*.dll", "*.lib", "*.so*", "*.dylib"]
 PLATFORMS = ["Linux", "MacOS", "windows"]
 for platform in PLATFORMS:
@@ -41,7 +40,7 @@ for platform in PLATFORMS:
 
 setuptools.setup(
     name="pylerc",
-    version="4.1",
+    version="4.1.1",
     author="esri",
     author_email="python at esri.com",
     description="Limited Error Raster Compression",
@@ -56,6 +55,7 @@ setuptools.setup(
         "Programming Language :: Python :: 3.11",
         "Programming Language :: Python :: 3.12",
         "Programming Language :: Python :: 3.13",
+        "Programming Language :: Python :: 3.14",
         "License :: OSI Approved :: Apache Software License",
     ],
     package_data={"lerc": BINARY_TYPES},


=====================================
README.md
=====================================
@@ -123,7 +123,7 @@ The codecs Lerc2 and Lerc1 have been in use for years, bugs in those low level m
 
 ## Licensing
 
-Copyright 2015-2022 Esri
+Copyright 2015-2026 Esri
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.


=====================================
src/LercLib/BitMask.cpp
=====================================
@@ -102,7 +102,7 @@ int BitMask::CountValidBits() const
   const Byte numBitsHB[16] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
   const Byte* ptr = m_pBits;
   int sum = 0;
-  int i = Size();
+  size_t i = Size();
   while (i--)
   {
     sum += numBitsHB[*ptr & 15] + numBitsHB[*ptr >> 4];


=====================================
src/LercLib/BitMask.h
=====================================
@@ -25,6 +25,7 @@ Contributors:  Thomas Maurer
 #define BITMASK_H
 
 #include "Defines.h"
+#include <cstddef>
 
 NAMESPACE_LERC_START
 
@@ -59,7 +60,7 @@ public:
 
   int GetWidth() const                      { return m_nCols; }
   int GetHeight() const                     { return m_nRows; }
-  int Size() const                          { return (m_nCols * m_nRows + 7) >> 3; }
+  size_t Size() const                       { return ((size_t)m_nCols * m_nRows + 7) >> 3; }
   const Byte* Bits() const                  { return m_pBits; }
   Byte* Bits()                              { return m_pBits; }
   static Byte Bit(int k)                    { return (1 << 7) >> (k & 7); }


=====================================
src/LercLib/Lerc.cpp
=====================================
@@ -188,7 +188,7 @@ ErrCode Lerc::GetLercInfo(const Byte* pLercBlob, unsigned int numBytesBlob, stru
   lercInfo.zMax = -FLT_MAX;
 
   CntZImage cntZImg;
-  if (numBytesHeaderBand0 <= numBytesBlob && cntZImg.read(&pByte, 1e12, true))    // read just the header
+  if (numBytesHeaderBand0 <= numBytesBlob && cntZImg.read(&pByte, pLercBlob + numBytesBlob, 1e12, true))    // read just the header
   {
     size_t nBytesRead = pByte - pLercBlob;
     size_t nBytesNeeded = 10 + 4 * sizeof(int) + 1 * sizeof(double);
@@ -205,7 +205,7 @@ ErrCode Lerc::GetLercInfo(const Byte* pLercBlob, unsigned int numBytesBlob, stru
     double maxZErrorInFile(0);
     memcpy(&maxZErrorInFile, ptr, sizeof(double));
 
-    if (height > 20000 || width > 20000)    // guard against bogus numbers; size limitation for old Lerc1
+    if (height < 0 || width < 0 || height > 40000 || width > 40000)  // guard against bogus numbers; size limitation for old Lerc1
       return ErrCode::Failed;
 
     lercInfo.nDepth = 1;
@@ -219,7 +219,7 @@ ErrCode Lerc::GetLercInfo(const Byte* pLercBlob, unsigned int numBytesBlob, stru
 
     while (lercInfo.blobSize + numBytesHeaderBand1 < numBytesBlob)    // means there could be another band
     {
-      if (!cntZImg.read(&pByte, 1e12, false, onlyZPart))
+      if (!cntZImg.read(&pByte, pLercBlob + numBytesBlob, 1e12, false, onlyZPart))
         return (lercInfo.nBands > 0) ? ErrCode::Ok : ErrCode::Failed;    // no other band, we are done
 
       onlyZPart = true;
@@ -479,11 +479,11 @@ ErrCode Lerc::DecodeTempl(T* pData, const Byte* pLercBlob, unsigned int numBytes
     for (int iBand = 0; iBand < nBands; iBand++)
     {
       unsigned int numBytesHeader = iBand == 0 ? numBytesHeaderBand0 : numBytesHeaderBand1;
-      if ((size_t)(pByte - pLercBlob) + numBytesHeader > numBytesBlob)
+      if ((size_t)(pByte1 - pLercBlob) + numBytesHeader > numBytesBlob)
         return ErrCode::BufferTooSmall;
 
       bool onlyZPart = iBand > 0;
-      if (!zImg.read(&pByte1, 1e12, false, onlyZPart))
+      if (!zImg.read(&pByte1, pLercBlob + numBytesBlob, 1e12, false, onlyZPart))
         return ErrCode::Failed;
 
       if (zImg.getWidth() != nCols || zImg.getHeight() != nRows)
@@ -675,14 +675,18 @@ ErrCode Lerc::EncodeInternal(const T* pData, int version, int nDepth, int nCols,
     bool bNeedNoData = false;    // can only turn true for nDepth > 1, and mix of valid and invalid values at the same pixel (special case)
     errCode = ErrCode::Ok;
 
+    double minVal(+1), maxVal(-1);
+    lerc2.ClearMinMax();
+
     if (bIsFltOrDbl)    // if flt type, filter out NaN and / or noData values and update the mask if possible
     {
       errCode = FilterNoDataAndNaN(dataBuffer, maskBuffer, nDepth, nCols, nRows, maxZErrL, bPassNoDataValue, noDataL,
-        bModifiedMask, bNeedNoData, bIsFltDblAllInt);
+        bModifiedMask, bNeedNoData, bIsFltDblAllInt, minVal, maxVal);
     }
     else if (bPassNoDataValue)    // if int type (no NaN), and no noData value specified, nothing to do
     {
-      errCode = FilterNoData(dataBuffer, maskBuffer, nDepth, nCols, nRows, maxZErrL, bPassNoDataValue, noDataL, bModifiedMask, bNeedNoData);
+      errCode = FilterNoData(dataBuffer, maskBuffer, nDepth, nCols, nRows, maxZErrL, bPassNoDataValue, noDataL,
+        bModifiedMask, bNeedNoData, minVal, maxVal);
     }
 
     if (errCode != ErrCode::Ok)
@@ -723,6 +727,10 @@ ErrCode Lerc::EncodeInternal(const T* pData, int version, int nDepth, int nCols,
       || !lerc2.SetIsAllInt(bIsFltDblAllInt))
       return ErrCode::Failed;
 
+    if (nDepth == 1 && (maxVal >= minVal)
+      && !lerc2.SetMinMax(nDepth, minVal, maxVal))
+      return ErrCode::Failed;
+
     unsigned int nBytes = lerc2.ComputeNumBytesNeededToWrite(arrL, maxZErrL, bEncMsk);
     if (nBytes <= 0)
       return ErrCode::Failed;
@@ -1210,7 +1218,8 @@ bool Lerc::GetTypeRange(const T, std::pair<double, double>& range)
 
 template<class T>
 ErrCode Lerc::FilterNoData(std::vector<T>& dataBuffer, std::vector<Byte>& maskBuffer, int nDepth, int nCols, int nRows,
-  double& maxZError, bool bPassNoDataValue, double& noDataValue, bool& bModifiedMask, bool& bNeedNoData)
+  double& maxZError, bool bPassNoDataValue, double& noDataValue, bool& bModifiedMask, bool& bNeedNoData,
+  double& minValA, double& maxValA)
 {
   if (nDepth <= 0 || nCols <= 0 || nRows <= 0 || maxZError < 0)
     return ErrCode::WrongParam;
@@ -1252,10 +1261,13 @@ ErrCode Lerc::FilterNoData(std::vector<T>& dataBuffer, std::vector<Byte>& maskBu
 
           if (z == origNoData)
             cntInvalid++;
-          else if (z < minVal)
-            minVal = z;
-          else if (z > maxVal)
-            maxVal = z;
+          else
+          {
+            if (z < minVal)
+              minVal = z;
+            if (z > maxVal)
+              maxVal = z;
+          }
         }
 
         if (cntInvalid == nDepth)
@@ -1271,6 +1283,16 @@ ErrCode Lerc::FilterNoData(std::vector<T>& dataBuffer, std::vector<Byte>& maskBu
   double maxZErrL = (std::max)(0.5, floor(maxZError));    // same mapping for int types as in Lerc2.cpp
   double dist = floor(maxZErrL);
 
+  if (minVal == DBL_MAX && maxVal == -DBL_MAX)    // if the tile has no valid data
+  {
+    minValA = maxValA = 0;
+    maxZError = 0.5;
+    return ErrCode::Ok;
+  }
+
+  minValA = minVal;
+  maxValA = maxVal;
+
   // check the orig noData value is far enough away from the valid range
   if ((origNoData >= minVal - dist) && (origNoData <= maxVal + dist))
   {
@@ -1333,7 +1355,8 @@ ErrCode Lerc::FilterNoData(std::vector<T>& dataBuffer, std::vector<Byte>& maskBu
 
 template<class T>
 ErrCode Lerc::FilterNoDataAndNaN(std::vector<T>& dataBuffer, std::vector<Byte>& maskBuffer, int nDepth, int nCols, int nRows,
-  double& maxZError, bool bPassNoDataValue, double& noDataValue, bool& bModifiedMask, bool& bNeedNoData, bool& bIsFltDblAllInt)
+  double& maxZError, bool bPassNoDataValue, double& noDataValue, bool& bModifiedMask, bool& bNeedNoData, bool& bIsFltDblAllInt,
+  double& minValA, double& maxValA)
 {
   if (nDepth <= 0 || nCols <= 0 || nRows <= 0 || maxZError < 0)
     return ErrCode::WrongParam;
@@ -1371,7 +1394,6 @@ ErrCode Lerc::FilterNoDataAndNaN(std::vector<T>& dataBuffer, std::vector<Byte>&
 
   double minVal = DBL_MAX;
   double maxVal = -DBL_MAX;
-  int cntValidPixels = 0;
 
   // check for NaN or noData in valid pixels
   for (int k = 0, i = 0; i < nRows; i++)
@@ -1381,7 +1403,6 @@ ErrCode Lerc::FilterNoDataAndNaN(std::vector<T>& dataBuffer, std::vector<Byte>&
     for (int n = 0, j = 0; j < nCols; j++, k++, n += nDepth)
       if (maskBuffer[k])
       {
-        cntValidPixels++;
         int cntInvalidValues = 0;
 
         for (int m = 0; m < nDepth; m++)
@@ -1406,7 +1427,7 @@ ErrCode Lerc::FilterNoDataAndNaN(std::vector<T>& dataBuffer, std::vector<Byte>&
           {
             if (zVal < minVal)
               minVal = zVal;
-            else if (zVal > maxVal)
+            if (zVal > maxVal)
               maxVal = zVal;
 
             if (bAllInt && !IsInt(zVal))
@@ -1424,10 +1445,16 @@ ErrCode Lerc::FilterNoDataAndNaN(std::vector<T>& dataBuffer, std::vector<Byte>&
       }
   }
 
-  bNeedNoData = bHasNoDataValuesLeft;
+  if (minVal == DBL_MAX && maxVal == -DBL_MAX)    // if the tile has no valid data
+  {
+    minValA = maxValA = 0;
+    maxZError = 0;
+    return ErrCode::Ok;
+  }
 
-  if (cntValidPixels == 0)
-    bAllInt = false;
+  minValA = minVal;
+  maxValA = maxVal;
+  bNeedNoData = bHasNoDataValuesLeft;
 
   if (bHasNaN && nDepth > 1 && bHasNoDataValuesLeft && !bPassNoDataValue)
   {


=====================================
src/LercLib/Lerc.h
=====================================
@@ -272,11 +272,13 @@ NAMESPACE_LERC_START
 
     template<class T>
     static ErrCode FilterNoData(std::vector<T>& dataBuffer, std::vector<Byte>& maskBuffer, int nDepth, int nCols, int nRows,
-      double& maxZError, bool bPassNoDataValue, double& noDataValue, bool& bModifiedMask, bool& bNeedNoData);
+      double& maxZError, bool bPassNoDataValue, double& noDataValue, bool& bModifiedMask, bool& bNeedNoData,
+      double& minVal, double& maxVal);
 
     template<class T>
     static ErrCode FilterNoDataAndNaN(std::vector<T>& dataBuffer, std::vector<Byte>& maskBuffer, int nDepth, int nCols, int nRows,
-      double& maxZError, bool bPassNoDataValue, double& noDataValue, bool& bModifiedMask, bool& bNeedNoData, bool& bIsFltDblAllInt);
+      double& maxZError, bool bPassNoDataValue, double& noDataValue, bool& bModifiedMask, bool& bNeedNoData, bool& bIsFltDblAllInt,
+      double& minVal, double& maxVal);
 
     template<class T>
     static bool FindNewNoDataBelowValidMin(double minVal, double maxZErr, bool bAllInt, double lowIntLimit, T& newNoDataVal);


=====================================
src/LercLib/Lerc1Decode/CntZImage.cpp
=====================================
@@ -69,12 +69,16 @@ unsigned int CntZImage::computeNumBytesNeededToReadHeader(bool onlyZPart)
 
 // -------------------------------------------------------------------------- ;
 
-bool CntZImage::read(const Byte** ppByte, double maxZError, bool onlyHeader, bool onlyZPart)
+bool CntZImage::read(const Byte** ppByte, const Byte* bArr_end, double maxZError, bool onlyHeader, bool onlyZPart)
 {
   if (!ppByte || !*ppByte)
     return false;
 
   size_t len = getTypeString().length();
+
+  if (*ppByte + len > bArr_end)
+    return false;
+
   string typeStr(len, '0');
   memcpy(&typeStr[0], *ppByte, len);
   *ppByte += len;
@@ -87,6 +91,9 @@ bool CntZImage::read(const Byte** ppByte, double maxZError, bool onlyHeader, boo
 
   const Byte* ptr = *ppByte;
 
+  if (ptr + 4 * sizeof(int) + sizeof(double) > bArr_end)
+    return false;
+
   memcpy(&version, ptr, sizeof(int));  ptr += sizeof(int);
   memcpy(&type,    ptr, sizeof(int));  ptr += sizeof(int);
   memcpy(&height,  ptr, sizeof(int));  ptr += sizeof(int);
@@ -104,7 +111,7 @@ bool CntZImage::read(const Byte** ppByte, double maxZError, bool onlyHeader, boo
   if (version != 11 || type != type_)
     return false;
 
-  if (width > 20000 || height > 20000)
+  if (height < 0 || width < 0 || height > 40000 || width > 40000)  // guard against bogus numbers; size limitation for old Lerc1
     return false;
 
   if (maxZErrorInFile > maxZError)
@@ -130,6 +137,9 @@ bool CntZImage::read(const Byte** ppByte, double maxZError, bool onlyHeader, boo
 
     const Byte* ptr = *ppByte;
 
+    if (ptr + 3 * sizeof(int) + sizeof(float) > bArr_end)
+      return false;
+
     memcpy(&numTilesVert, ptr, sizeof(int));  ptr += sizeof(int);
     memcpy(&numTilesHori, ptr, sizeof(int));  ptr += sizeof(int);
     memcpy(&numBytes, ptr, sizeof(int));  ptr += sizeof(int);
@@ -143,6 +153,9 @@ bool CntZImage::read(const Byte** ppByte, double maxZError, bool onlyHeader, boo
     SWAP_4(numBytes);
     SWAP_4(maxValInImg);
 
+    if (numBytes < 0 || ptr + numBytes > bArr_end)
+      return false;
+
     if (!zPart && numTilesVert == 0 && numTilesHori == 0)    // no tiling for this cnt part
     {
       if (numBytes == 0)    // cnt part is const
@@ -188,7 +201,8 @@ bool CntZImage::read(const Byte** ppByte, double maxZError, bool onlyHeader, boo
 bool CntZImage::readTiles(bool zPart, double maxZErrorInFile, int numTilesVert, int numTilesHori,
   float maxValInImg, const Byte* bArr)
 {
-  if (numTilesVert <= 0 || numTilesHori <= 0)
+  if (numTilesVert <= 0 || numTilesHori <= 0
+    || numTilesVert > height_ || numTilesHori > width_)
     return false;
 
   const Byte* ptr = bArr;


=====================================
src/LercLib/Lerc1Decode/CntZImage.h
=====================================
@@ -47,7 +47,7 @@ public:
   static unsigned int computeNumBytesNeededToReadHeader(bool onlyZPart);
 
   /// read succeeds only if maxZError on file <= maxZError requested
-  bool read(const Byte** ppByte, double maxZError, bool onlyHeader = false, bool onlyZPart = false);
+  bool read(const Byte** ppByte, const Byte* bArr_end, double maxZError, bool onlyHeader = false, bool onlyZPart = false);
 
 protected:
 


=====================================
src/LercLib/Lerc2.cpp
=====================================
@@ -70,6 +70,7 @@ void Lerc2::Init()
   m_maxValToQuantize  = 0;
   m_encodeMask        = true;
   m_writeDataOneSweep = false;
+  m_minMaxSet         = false;
   m_imageEncodeMode   = IEM_Tiling;
 
   m_headerInfo.RawInit();
@@ -145,6 +146,31 @@ bool Lerc2::SetIsAllInt(bool bIsAllInt)
 
 // -------------------------------------------------------------------------- ;
 
+bool Lerc2::SetMinMax(int nDepth, double minVal, double maxVal)
+{
+  ClearMinMax();
+
+  if (nDepth != 1 || minVal > maxVal)
+    return false;
+
+  m_zMinVec.assign(1, minVal);
+  m_zMaxVec.assign(1, maxVal);
+  m_minMaxSet = true;
+
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+void Lerc2::ClearMinMax()
+{
+  m_zMinVec.clear();
+  m_zMaxVec.clear();
+  m_minMaxSet = false;
+}
+
+// -------------------------------------------------------------------------- ;
+
 template<class T>
 unsigned int Lerc2::ComputeNumBytesNeededToWrite(const T* arr, double maxZError, bool encodeMask)
 {
@@ -214,7 +240,8 @@ unsigned int Lerc2::ComputeNumBytesNeededToWrite(const T* arr, double maxZError,
   Byte* ptr = nullptr;    // only emulate the writing and just count the bytes needed
   int nBytesTiling = 0;
 
-  if (!ComputeMinMaxRanges(arr, m_zMinVec, m_zMaxVec))    // need this for diff encoding before WriteTiles()
+  if ((!m_minMaxSet || m_headerInfo.nDepth > 1)
+    && !ComputeMinMaxRanges(arr, m_zMinVec, m_zMaxVec))    // need this for diff encoding before WriteTiles()
     return 0;
 
   m_headerInfo.zMin = *std::min_element(m_zMinVec.begin(), m_zMinVec.end());
@@ -823,8 +850,11 @@ bool Lerc2::ReadHeader(const Byte** ppByte, size_t& nBytesRemainingInOut, struct
   hd.microBlockSize = intVec[i++];
   hd.blobSize       = intVec[i++];
   const int dt      = intVec[i++];
-  if (dt < DT_Char || dt > DT_Double)
+
+  if (hd.nRows <= 0 || hd.nCols <= 0 || hd.nDepth <= 0 || hd.numValidPixel < 0
+    || hd.microBlockSize <= 0 || hd.blobSize <= 0 || dt < DT_Char || dt > DT_Double)
     return false;
+
   hd.dt             = static_cast<DataType>(dt);
   hd.nBlobsMore     = (hd.version >= 6) ? intVec[i++] : 0;
 
@@ -841,8 +871,9 @@ bool Lerc2::ReadHeader(const Byte** ppByte, size_t& nBytesRemainingInOut, struct
   hd.noDataVal      = (hd.version >= 6) ? dblVec[i++] : 0;
   hd.noDataValOrig  = (hd.version >= 6) ? dblVec[i++] : 0;
 
-  if (hd.nRows <= 0 || hd.nCols <= 0 || hd.nDepth <= 0 || hd.numValidPixel < 0 || hd.microBlockSize <= 0 || hd.blobSize <= 0
-    || (hd.nRows > INT_MAX / hd.nCols) || hd.numValidPixel > hd.nRows * hd.nCols)
+  size_t numPixel = (size_t)hd.nRows * hd.nCols;
+
+  if (numPixel > (size_t)INT_MAX || (size_t)hd.numValidPixel > numPixel)
     return false;
 
   *ppByte = ptr;


=====================================
src/LercLib/Lerc2.h
=====================================
@@ -86,6 +86,9 @@ public:
   bool SetNumBlobsMoreToCome(int nBlobsMore);    // for safer decode of multi-band blobs
   bool SetIsAllInt(bool bIsAllInt);
 
+  bool SetMinMax(int nDepth, double minVal, double maxVal);    // set min / max but only for nDepth = 1
+  void ClearMinMax();
+
   template<class T>
   unsigned int ComputeNumBytesNeededToWrite(const T* arr, double maxZError, bool encodeMask);
 
@@ -146,7 +149,8 @@ private:
   HeaderInfo  m_headerInfo;
   BitStuffer2 m_bitStuffer2;
   bool        m_encodeMask,
-              m_writeDataOneSweep;
+              m_writeDataOneSweep,
+              m_minMaxSet;
   ImageEncodeMode  m_imageEncodeMode;
 
   std::vector<double> m_zMinVec, m_zMaxVec;


=====================================
src/LercLib/fpl_EsriHuffman.cpp
=====================================
@@ -53,23 +53,28 @@ bool decodePackBits (const unsigned char *ptr, const size_t size, size_t expecte
 
     for (size_t i = 0; i < size; )
     {
-        // read header byte.
-
-        int b = ptr[i];
-
-        if (b <= 127)
-        {
-            while (b >= 0) { i++; out[curr++] = ptr[i]; b--; }
-            i++;
-            continue;
-        }
-        else
-        {
-            i++;
-            while (b >= 127) { out[curr++] = ptr[i]; b--; }
-            i++;
-            continue;
-        }
+      int b = ptr[i++];  // read header byte
+
+      if (b <= 127)
+      {
+        if (curr + b >= expected)
+          return false;
+
+        int b1 = b + 1;
+        memcpy(&out[curr], &ptr[i], b1);
+        curr += b1;
+        i += b1;
+      }
+      else
+      {
+        if (curr + b - 127 >= expected)
+          return false;
+
+        int b1 = b - 127 + 1;
+        memset(&out[curr], ptr[i], b1);
+        curr += b1;
+        i++;
+      }
     }
 
     return (curr == expected);
@@ -353,6 +358,11 @@ int fpl_EsriHuffman::EncodeHuffman (const char *input, size_t input_len, unsigne
         long rle_len = getPackBitsSize ((unsigned char *)input, input_len, &limit);
         if (rle_len > 0 && (rle_len < numBytes) && (rle_len < (long)input_len))
         {
+            if ((rle_len + 1) <= 0) // rle_len is maximum long value, so adding 1 results in overflow.
+            {
+              return HUFF_UNEXPECTED; // this should not normally happen.
+            }
+
             *ppByte = (unsigned char *)malloc (rle_len + 1);
 
             if (*ppByte == NULL)


=====================================
src/LercLib/include/Lerc_c_api.h
=====================================
@@ -38,7 +38,7 @@ extern "C" {
 
 #define LERC_VERSION_MAJOR 4
 #define LERC_VERSION_MINOR 1
-#define LERC_VERSION_PATCH 0
+#define LERC_VERSION_PATCH 1
 
 /* Macro to compute a LERC version number from its components */
 #define LERC_COMPUTE_VERSION(maj,min,patch) ((maj)*10000+(min)*100+(patch))


=====================================
src/LercTest/main.cpp
=====================================
@@ -799,17 +799,23 @@ bool ReadFile(const string& fn, Byte* pBuffer, size_t bufferSize, size_t& nBytes
   }
 
   fseek(fp, 0, SEEK_END);
-  size_t fileSize = ftell(fp);    // get the file size
-  fclose(fp);
-  fp = 0;
+  int rv = ftell(fp);    // get the file size
+  if (rv <= 0)
+  {
+    fclose(fp);
+    return false;
+  }
+
+  size_t fileSize = (size_t)rv;
 
   if (fileSize > bufferSize)
   {
     printf("Lerc blob size %d > buffer size of %d\n", (uint32)fileSize, (uint32)bufferSize);
+    fclose(fp);
     return false;
   }
 
-  fp = fopen(fn.c_str(), "rb");
+  rewind(fp);
   nBytesRead = fread(pBuffer, 1, fileSize, fp);    // read Lerc blob into buffer
   fclose(fp);
   return nBytesRead == fileSize;



View it on GitLab: https://salsa.debian.org/debian-gis-team/lerc/-/commit/4cc04dcdec0f155c7c4b741d06da935a29682feb

-- 
View it on GitLab: https://salsa.debian.org/debian-gis-team/lerc/-/commit/4cc04dcdec0f155c7c4b741d06da935a29682feb
You're receiving this email because of your account on salsa.debian.org. Manage all notifications: https://salsa.debian.org/-/profile/notifications | Help: https://salsa.debian.org/help


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


More information about the Pkg-grass-devel mailing list