[Git][debian-gis-team/protozero][upstream] New upstream version 1.8.1
Bas Couwenberg (@sebastic)
gitlab at salsa.debian.org
Wed Jul 16 11:47:47 BST 2025
Bas Couwenberg pushed to branch upstream at Debian GIS Project / protozero
Commits:
a01158b4 by Bas Couwenberg at 2025-07-16T12:32:09+02:00
New upstream version 1.8.1
- - - - -
12 changed files:
- .github/actions/install-ubuntu/action.yml
- .github/workflows/ci.yml
- CHANGELOG.md
- CMakeLists.txt
- FUZZING.md
- doc/CMakeLists.txt
- include/protozero/pbf_reader.hpp
- include/protozero/version.hpp
- test/t/bool/reader_test_cases.cpp
- test/unit/test_data_view.cpp
- tools/pbf-decoder.cpp
- + tools/pbf-fuzzer.cpp
Changes:
=====================================
.github/actions/install-ubuntu/action.yml
=====================================
@@ -7,6 +7,8 @@ runs:
run: |
sudo apt-get update -qq
sudo apt-get install -yq \
+ doxygen \
+ graphviz \
libprotobuf-dev \
protobuf-compiler
shell: bash
=====================================
.github/workflows/ci.yml
=====================================
@@ -51,6 +51,7 @@ jobs:
- 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 @@ jobs:
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 @@ jobs:
fail-fast: false
matrix:
os:
- - windows-2019
- windows-2022
+ - windows-2025
steps:
- run: |
vcpkg install \
=====================================
CHANGELOG.md
=====================================
@@ -14,7 +14,15 @@ This project adheres to [Semantic Versioning](https://semver.org/).
### 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
=====================================
CMakeLists.txt
=====================================
@@ -10,7 +10,7 @@ cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR)
#-----------------------------------------------------------------------------
-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 @@ endif()
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()
=====================================
FUZZING.md
=====================================
@@ -18,5 +18,16 @@ Then do the actual fuzzing:
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!
=====================================
doc/CMakeLists.txt
=====================================
@@ -11,7 +11,7 @@ message(STATUS "Configuring documentation")
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)
=====================================
include/protozero/pbf_reader.hpp
=====================================
@@ -494,9 +494,9 @@ public:
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;
}
/**
=====================================
include/protozero/version.hpp
=====================================
@@ -23,12 +23,12 @@ documentation.
#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
=====================================
test/t/bool/reader_test_cases.cpp
=====================================
@@ -139,3 +139,11 @@ TEST_CASE("write bool field using moved pbf_builder") {
}
}
+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);
+}
=====================================
test/unit/test_data_view.cpp
=====================================
@@ -53,7 +53,9 @@ TEST_CASE("convert data_view to std::string") {
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 @@ TEST_CASE("swapping data_view") {
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") {
=====================================
tools/pbf-decoder.cpp
=====================================
@@ -32,6 +32,7 @@ Call with --help/-h to see more options.
#include <sstream>
#include <stdexcept>
#include <string>
+#include <vector>
namespace {
@@ -194,15 +195,15 @@ void print_help() {
<< " -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 @@ int main(int argc, char* argv[]) {
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()) {
=====================================
tools/pbf-fuzzer.cpp
=====================================
@@ -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;
+}
View it on GitLab: https://salsa.debian.org/debian-gis-team/protozero/-/commit/a01158b4228e392765ffdedaf96c8afdff95b56a
--
View it on GitLab: https://salsa.debian.org/debian-gis-team/protozero/-/commit/a01158b4228e392765ffdedaf96c8afdff95b56a
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/20250716/9361ce67/attachment-0001.htm>
More information about the Pkg-grass-devel
mailing list