Package: release.debian.org
Severity: normal
X-Debbugs-Cc: protoz...@packages.debian.org
Control: affects -1 + src:protozero
User: release.debian....@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
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 <sebas...@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 <sebas...@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@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;
+}

Reply via email to