Bug#1109386: unblock: protozero/1.8.1-1 (pre-approval)

Bas Couwenberg sebastic at xs4all.nl
Wed Jul 16 11:57:07 BST 2025


Package: release.debian.org
Severity: normal
X-Debbugs-Cc: protozero at packages.debian.org
Control: affects -1 + src:protozero
User: release.debian.org at packages.debian.org
Usertags: unblock

Please unblock package protozero

The new upstream release has been uploaded to experimental for now, but I'd like to move it to unstable and have it migrate to testing too.

[ Reason ]
Fixes a buffer overrun security issue.

[ Impact ]
Unfixed security issue.

[ Tests ]
Upstream test suite.

[ Risks ]
Low, only three rdeps (libosmium, mapnik, qtlocation-opensource-src).

[ Checklist ]
  [x] all changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in testing

[ Other info ]
Upstream reported the issue on the debian-gis list:

 https://lists.debian.org/debian-gis/2025/07/msg00002.html

unblock protozero/1.8.1-1
-------------- next part --------------
diff -Nru protozero-1.8.0/CHANGELOG.md protozero-1.8.1/CHANGELOG.md
--- protozero-1.8.0/CHANGELOG.md	2025-01-13 10:42:19.000000000 +0100
+++ protozero-1.8.1/CHANGELOG.md	2025-07-15 19:28:17.000000000 +0200
@@ -14,7 +14,15 @@
 ### Fixed
 
 
-## [1.8.0] - 2024-01-13
+## [1.8.1] - 2025-07-15
+
+### Fixed
+
+- Fix buffer overrun in `get_bool()`
+- Fix test that checks that protozero also works with `std::string_view`
+
+
+## [1.8.0] - 2025-01-13
 
 ### Changed
 
diff -Nru protozero-1.8.0/CMakeLists.txt protozero-1.8.1/CMakeLists.txt
--- protozero-1.8.0/CMakeLists.txt	2025-01-13 10:42:19.000000000 +0100
+++ protozero-1.8.1/CMakeLists.txt	2025-07-15 19:28:17.000000000 +0200
@@ -10,7 +10,7 @@
 
 #-----------------------------------------------------------------------------
 
-project(protozero VERSION 1.8.0 LANGUAGES CXX C)
+project(protozero VERSION 1.8.1 LANGUAGES CXX C)
 
 set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
 
@@ -40,9 +40,13 @@
 
 include_directories("${CMAKE_SOURCE_DIR}/include")
 
+# Used for testing
 set(PROTOZERO_DATA_VIEW "" CACHE STRING "Type used for protozero::data_view")
 if(NOT PROTOZERO_DATA_VIEW STREQUAL "")
-    add_definitions(-DPROTOZERO_DATA_VIEW=${PROTOZERO_DATA_VIEW})
+    message(STATUS "Using ${PROTOZERO_DATA_VIEW} as data_view")
+    add_definitions(-DPROTOZERO_USE_VIEW=${PROTOZERO_DATA_VIEW})
+else()
+    message(STATUS "Using built-in data_view")
 endif()
 
 
diff -Nru protozero-1.8.0/debian/changelog protozero-1.8.1/debian/changelog
--- protozero-1.8.0/debian/changelog	2025-01-14 05:33:36.000000000 +0100
+++ protozero-1.8.1/debian/changelog	2025-07-16 12:48:27.000000000 +0200
@@ -1,3 +1,17 @@
+protozero (1.8.1-1) unstable; urgency=medium
+
+  * Move from experimental to unstable.
+
+ -- Bas Couwenberg <sebastic at debian.org>  Wed, 16 Jul 2025 12:48:27 +0200
+
+protozero (1.8.1-1~exp1) experimental; urgency=medium
+
+  * New upstream release.
+  * Bump Standards-Version to 4.7.2, no changes.
+  * Fix old FSF address in copyright file.
+
+ -- Bas Couwenberg <sebastic at debian.org>  Wed, 16 Jul 2025 12:44:43 +0200
+
 protozero (1.8.0-1) unstable; urgency=medium
 
   * New upstream release.
diff -Nru protozero-1.8.0/debian/control protozero-1.8.1/debian/control
--- protozero-1.8.0/debian/control	2024-07-28 19:52:33.000000000 +0200
+++ protozero-1.8.1/debian/control	2025-07-16 12:48:08.000000000 +0200
@@ -10,7 +10,7 @@
                libprotobuf-dev <!nocheck>,
                protobuf-compiler <!nocheck>,
                pkgconf
-Standards-Version: 4.7.0
+Standards-Version: 4.7.2
 Vcs-Browser: https://salsa.debian.org/debian-gis-team/protozero/
 Vcs-Git: https://salsa.debian.org/debian-gis-team/protozero.git
 Homepage: https://github.com/mapbox/protozero
diff -Nru protozero-1.8.0/debian/copyright protozero-1.8.1/debian/copyright
--- protozero-1.8.0/debian/copyright	2025-01-14 05:32:16.000000000 +0100
+++ protozero-1.8.1/debian/copyright	2025-03-29 07:28:35.000000000 +0100
@@ -92,10 +92,6 @@
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
  .
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- .
  On Debian systems, the complete text of version 2 of the GNU General
  Public License can be found in `/usr/share/common-licenses/GPL-2'.
 
diff -Nru protozero-1.8.0/doc/CMakeLists.txt protozero-1.8.1/doc/CMakeLists.txt
--- protozero-1.8.0/doc/CMakeLists.txt	2025-01-13 10:42:19.000000000 +0100
+++ protozero-1.8.1/doc/CMakeLists.txt	2025-07-15 19:28:17.000000000 +0200
@@ -11,7 +11,7 @@
 message(STATUS "Looking for doxygen")
 find_package(Doxygen)
 
-if(DOXYGEN_FOUND)
+if(DOXYGEN_FOUND AND DOXYGEN_DOT_FOUND)
     message(STATUS "Looking for doxygen - found")
     configure_file(Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY)
 
diff -Nru protozero-1.8.0/FUZZING.md protozero-1.8.1/FUZZING.md
--- protozero-1.8.0/FUZZING.md	2025-01-13 10:42:19.000000000 +0100
+++ protozero-1.8.1/FUZZING.md	2025-07-15 19:28:17.000000000 +0200
@@ -18,5 +18,16 @@
 
 See the AFL documentation for more information.
 
+For increased speed, you can also use the dedicated pbf-fuzzer tool, which skips reading
+data from files or stdin:
+
+    clang++ -O2 -std=c++17 -g -DNDEBUG -Iinclude -fsanitize=address,fuzzer tools/pbf-fuzzer.cpp -o tools/pbf-fuzzer
+    ./tools/pbf-fuzzer
+
+or using AFL++
+
+    afl-clang-fast++ -O2 -std=c++17 -g -DNDEBUG -Iinclude -fsanitize=address,fuzzer tools/pbf-fuzzer.cpp -o tools/pbf-fuzzer
+    afl-fuzz -i testcase_dir -o findings_dir -- tools/pbf-fuzzer
+
 This only checkes the reading side of Protozero!
 
diff -Nru protozero-1.8.0/.github/actions/install-ubuntu/action.yml protozero-1.8.1/.github/actions/install-ubuntu/action.yml
--- protozero-1.8.0/.github/actions/install-ubuntu/action.yml	2025-01-13 10:42:19.000000000 +0100
+++ protozero-1.8.1/.github/actions/install-ubuntu/action.yml	2025-07-15 19:28:17.000000000 +0200
@@ -7,6 +7,8 @@
       run: |
         sudo apt-get update -qq
         sudo apt-get install -yq \
+            doxygen \
+            graphviz \
             libprotobuf-dev \
             protobuf-compiler
       shell: bash
diff -Nru protozero-1.8.0/.github/workflows/ci.yml protozero-1.8.1/.github/workflows/ci.yml
--- protozero-1.8.0/.github/workflows/ci.yml	2025-01-13 10:42:19.000000000 +0100
+++ protozero-1.8.1/.github/workflows/ci.yml	2025-07-15 19:28:17.000000000 +0200
@@ -51,6 +51,7 @@
           - image: "debian:bookworm"
             c_compiler: clang
             cpp_compiler: clang++
+            cpp_version: 17
             data_view: std::string_view
           - image: "debian:testing"
             c_compiler: clang
@@ -136,7 +137,7 @@
       CXX: clang++
       BUILD_TYPE: ${{ matrix.build_type }}
     steps:
-      - run: brew install protobuf
+      - run: brew install doxygen graphviz protobuf
       - uses: actions/checkout at v4
       - uses: ./.github/actions/cmake
       - uses: ./.github/actions/build
@@ -149,8 +150,8 @@
       fail-fast: false
       matrix:
         os:
-          - windows-2019
           - windows-2022
+          - windows-2025
     steps:
       - run: |
           vcpkg install \
diff -Nru protozero-1.8.0/include/protozero/pbf_reader.hpp protozero-1.8.1/include/protozero/pbf_reader.hpp
--- protozero-1.8.0/include/protozero/pbf_reader.hpp	2025-01-13 10:42:19.000000000 +0100
+++ protozero-1.8.1/include/protozero/pbf_reader.hpp	2025-07-15 19:28:17.000000000 +0200
@@ -494,9 +494,9 @@
     bool get_bool() {
         protozero_assert(tag() != 0 && "call next() before accessing field value");
         protozero_assert(has_wire_type(pbf_wire_type::varint) && "not a varint");
-        const bool result = m_data[0] != 0;
+        const char* value = m_data;
         skip_varint(&m_data, m_end);
-        return result;
+        return *value != 0;
     }
 
     /**
diff -Nru protozero-1.8.0/include/protozero/version.hpp protozero-1.8.1/include/protozero/version.hpp
--- protozero-1.8.0/include/protozero/version.hpp	2025-01-13 10:42:19.000000000 +0100
+++ protozero-1.8.1/include/protozero/version.hpp	2025-07-15 19:28:17.000000000 +0200
@@ -23,12 +23,12 @@
 #define PROTOZERO_VERSION_MINOR 8
 
 /// The patch number
-#define PROTOZERO_VERSION_PATCH 0
+#define PROTOZERO_VERSION_PATCH 1
 
 /// The complete version number
 #define PROTOZERO_VERSION_CODE (PROTOZERO_VERSION_MAJOR * 10000 + PROTOZERO_VERSION_MINOR * 100 + PROTOZERO_VERSION_PATCH)
 
 /// Version number as string
-#define PROTOZERO_VERSION_STRING "1.8.0"
+#define PROTOZERO_VERSION_STRING "1.8.1"
 
 #endif // PROTOZERO_VERSION_HPP
diff -Nru protozero-1.8.0/test/t/bool/reader_test_cases.cpp protozero-1.8.1/test/t/bool/reader_test_cases.cpp
--- protozero-1.8.0/test/t/bool/reader_test_cases.cpp	2025-01-13 10:42:19.000000000 +0100
+++ protozero-1.8.1/test/t/bool/reader_test_cases.cpp	2025-07-15 19:28:17.000000000 +0200
@@ -139,3 +139,11 @@
     }
 }
 
+TEST_CASE("read bool from using pbf_reader: truncated message") {
+    std::vector<char> buffer = { 0x08 };
+
+    protozero::pbf_reader item{buffer.data(), buffer.size()};
+
+    REQUIRE(item.next());
+    REQUIRE_THROWS_AS(item.get_bool(), protozero::end_of_buffer_exception);
+}
diff -Nru protozero-1.8.0/test/unit/test_data_view.cpp protozero-1.8.1/test/unit/test_data_view.cpp
--- protozero-1.8.0/test/unit/test_data_view.cpp	2025-01-13 10:42:19.000000000 +0100
+++ protozero-1.8.1/test/unit/test_data_view.cpp	2025-07-15 19:28:17.000000000 +0200
@@ -53,7 +53,9 @@
     const std::string s = std::string(view);
     REQUIRE(s == "foobar");
     REQUIRE(std::string(view) == "foobar");
+#ifndef PROTOZERO_USE_VIEW
     REQUIRE(view.to_string() == "foobar");
+#endif
 }
 
 #ifndef PROTOZERO_USE_VIEW
@@ -69,14 +71,14 @@
     protozero::data_view view1{"foo"};
     protozero::data_view view2{"bar"};
 
-    REQUIRE(view1.to_string() == "foo");
-    REQUIRE(view2.to_string() == "bar");
+    REQUIRE(std::string(view1) == "foo");
+    REQUIRE(std::string(view2) == "bar");
 
     using std::swap;
     swap(view1, view2);
 
-    REQUIRE(view2.to_string() == "foo");
-    REQUIRE(view1.to_string() == "bar");
+    REQUIRE(std::string(view2) == "foo");
+    REQUIRE(std::string(view1) == "bar");
 }
 
 TEST_CASE("comparing data_views") {
diff -Nru protozero-1.8.0/tools/pbf-decoder.cpp protozero-1.8.1/tools/pbf-decoder.cpp
--- protozero-1.8.0/tools/pbf-decoder.cpp	2025-01-13 10:42:19.000000000 +0100
+++ protozero-1.8.1/tools/pbf-decoder.cpp	2025-07-15 19:28:17.000000000 +0200
@@ -32,6 +32,7 @@
 #include <sstream>
 #include <stdexcept>
 #include <string>
+#include <vector>
 
 namespace {
 
@@ -194,15 +195,15 @@
               << "  -o, --offset=OFFSET  Start reading from OFFSET bytes\n";
 }
 
-std::string read_from_file(const char* filename) {
+std::vector<char> read_from_file(const char* filename) {
     const std::ifstream file{filename, std::ios::binary};
-    return std::string{std::istreambuf_iterator<char>(file.rdbuf()),
-                       std::istreambuf_iterator<char>()};
+    return std::vector<char>{std::istreambuf_iterator<char>(file.rdbuf()),
+                             std::istreambuf_iterator<char>()};
 }
 
-std::string read_from_stdin() {
-    return std::string{std::istreambuf_iterator<char>(std::cin.rdbuf()),
-                       std::istreambuf_iterator<char>()};
+std::vector<char> read_from_stdin() {
+    return std::vector<char>{std::istreambuf_iterator<char>(std::cin.rdbuf()),
+                             std::istreambuf_iterator<char>()};
 }
 
 } // anonymous namespace
@@ -251,15 +252,15 @@
     const std::string filename{argv[optind]};
 
     try {
-        std::string buffer{filename == "-" ? read_from_stdin() :
-                                             read_from_file(argv[optind])};
+        std::vector<char> buffer{filename == "-" ? read_from_stdin() :
+                                                   read_from_file(argv[optind])};
 
         if (offset > buffer.size()) {
             throw std::runtime_error{"offset is larger than file size"};
         }
 
         if (offset > 0) {
-            buffer.erase(0, offset);
+            buffer.erase(buffer.begin(), buffer.begin() + offset);
         }
 
         if (length < buffer.size()) {
diff -Nru protozero-1.8.0/tools/pbf-fuzzer.cpp protozero-1.8.1/tools/pbf-fuzzer.cpp
--- protozero-1.8.0/tools/pbf-fuzzer.cpp	1970-01-01 01:00:00.000000000 +0100
+++ protozero-1.8.1/tools/pbf-fuzzer.cpp	2025-07-15 19:28:17.000000000 +0200
@@ -0,0 +1,85 @@
+#include <protozero/pbf_reader.hpp>
+
+// From Google Benchmark library.
+// See https://github.com/google/benchmark/blob/main/LICENSE
+template <class Tp>
+inline __attribute__((always_inline)) void DoNotOptimize(Tp const& value) {
+    asm volatile("" : : "r,m"(value) : "memory");
+}
+
+template <typename T>
+int read_packed(protozero::iterator_range<T> range) {
+    try {
+        for (const auto& item : range) {
+            DoNotOptimize(item);
+        }
+    } catch (const protozero::exception&) {
+        // no-op. This is probably not a packed field of that type.
+    }
+    return 0;
+}
+
+template <typename Fn>
+void try_field(const protozero::pbf_reader& reader, Fn&& fn) {
+    try {
+        DoNotOptimize(fn(reader));
+    } catch (const protozero::exception&) {
+        // no-op. This is probably not a field of that type.
+    }
+}
+
+int try_message(protozero::pbf_reader reader) {
+    try {
+        while (reader.next()) {
+            if (reader.has_wire_type(protozero::pbf_wire_type::varint)) {
+                // Try to decode this field as any of the types that can be encoded as varint.
+                try_field(reader, [](protozero::pbf_reader r) { return r.get_bool(); });
+                try_field(reader, [](protozero::pbf_reader r) { return r.get_enum(); });
+                try_field(reader, [](protozero::pbf_reader r) { return r.get_int32(); });
+                try_field(reader, [](protozero::pbf_reader r) { return r.get_sint32(); });
+                try_field(reader, [](protozero::pbf_reader r) { return r.get_uint32(); });
+                try_field(reader, [](protozero::pbf_reader r) { return r.get_int64(); });
+                try_field(reader, [](protozero::pbf_reader r) { return r.get_sint64(); });
+                try_field(reader, [](protozero::pbf_reader r) { return r.get_uint64(); });
+            } else if (reader.has_wire_type(protozero::pbf_wire_type::length_delimited)) {
+                // Try to decode this field as any of the types that can be encoded as length-delimited.
+                try_field(reader, [](protozero::pbf_reader r) { return try_message(r.get_message()); });
+                try_field(reader, [](protozero::pbf_reader r) { return read_packed(r.get_packed_bool()); });
+                try_field(reader, [](protozero::pbf_reader r) { return read_packed(r.get_packed_double()); });
+                try_field(reader, [](protozero::pbf_reader r) { return read_packed(r.get_packed_enum()); });
+                try_field(reader, [](protozero::pbf_reader r) { return read_packed(r.get_packed_fixed32()); });
+                try_field(reader, [](protozero::pbf_reader r) { return read_packed(r.get_packed_fixed64()); });
+                try_field(reader, [](protozero::pbf_reader r) { return read_packed(r.get_packed_float()); });
+                try_field(reader, [](protozero::pbf_reader r) { return read_packed(r.get_packed_int32()); });
+                try_field(reader, [](protozero::pbf_reader r) { return read_packed(r.get_packed_int64()); });
+                try_field(reader, [](protozero::pbf_reader r) { return read_packed(r.get_packed_sfixed32()); });
+                try_field(reader, [](protozero::pbf_reader r) { return read_packed(r.get_packed_sfixed64()); });
+                try_field(reader, [](protozero::pbf_reader r) { return read_packed(r.get_packed_sint32()); });
+                try_field(reader, [](protozero::pbf_reader r) { return read_packed(r.get_packed_sint64()); });
+                try_field(reader, [](protozero::pbf_reader r) { return read_packed(r.get_packed_uint32()); });
+                try_field(reader, [](protozero::pbf_reader r) { return read_packed(r.get_packed_uint64()); });
+            } else if (reader.has_wire_type(protozero::pbf_wire_type::fixed64)) {
+                // Try to decode this field as any of the types that can be encoded as fixed64.
+                try_field(reader, [](protozero::pbf_reader r) { return r.get_double(); });
+                try_field(reader, [](protozero::pbf_reader r) { return r.get_fixed64(); });
+                try_field(reader, [](protozero::pbf_reader r) { return r.get_sfixed64(); });
+            } else if (reader.has_wire_type(protozero::pbf_wire_type::fixed32)) {
+                // Try to decode this field as any of the types that can be encoded as fixed32.
+                try_field(reader, [](protozero::pbf_reader r) { return r.get_float(); });
+                try_field(reader, [](protozero::pbf_reader r) { return r.get_fixed32(); });
+                try_field(reader, [](protozero::pbf_reader r) { return r.get_sfixed32(); });
+            }
+
+            reader.skip();
+        }
+    } catch (const protozero::exception&) {
+        // no-op. This is probably not a valid message.
+    }
+
+    return 0;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    try_message(protozero::pbf_reader{reinterpret_cast<const char*>(data), size});
+    return 0;
+}


More information about the Pkg-grass-devel mailing list