Compare commits

...

13 Commits

Author SHA1 Message Date
Jochen Topf 30db69822d Github action: Modernize/fix CI 2026-07-26 16:49:46 +02:00
Jochen Topf 0265ab5f3d Release version 1.7.0 2026-07-26 16:42:30 +02:00
Jochen Topf 5b5ae13a4a Move osmpbf-outline tool from "tools" into "demo" directory
This isn't really a useful tool for normal users. It is a demo/example
program for developers to see how the library can be used.
2026-07-26 16:38:45 +02:00
Jochen Topf c33d74be06 Avoid global variables 2026-07-24 15:53:49 +02:00
Jochen Topf 01f1a3f0be Detect lz4 or zstd compressed data 2026-07-24 15:53:49 +02:00
Jochen Topf 719a26d4af Various code modernizations/fixes 2026-07-24 15:53:45 +02:00
Jochen Topf 5b6d2afa9c Use C++ versions of headers 2026-07-24 14:53:28 +02:00
Jochen Topf 830df177b5 Mark err() function as noreturn 2026-07-24 14:52:20 +02:00
Jochen Topf eda1580ce9 CMake config: Enable generation of compile_commands.json 2026-07-24 14:51:49 +02:00
Jochen Topf 9eddf3d1f8
Merge pull request #95 from simon04/fix-94
Fix BSS buffer overflow in osmpbf-outline zlib decompression
2026-07-24 14:51:08 +02:00
Simon Legner 8857d08d80 Fix BSS buffer overflow in osmpbf-outline zlib decompression
Fixes #94.
2026-07-22 22:16:52 +02:00
Leonard Ehrenfried 28f76c6bf0
Merge pull request #93 from sebastic/java-version
Set Java version to 1.8 to match Maven build.
2026-03-11 10:21:39 +01:00
Bas Couwenberg 5bb6bbfc62 Set Java version to 1.8 to match Maven build. 2026-03-10 19:38:12 +01:00
13 changed files with 170 additions and 85 deletions

View File

@ -19,6 +19,6 @@ runs:
working-directory: build
- name: Run outline
run: build/tools/osmpbf-outline resources/sample.pbf
run: build/demo/osmpbf-outline resources/sample.pbf
shell: bash

View File

@ -11,7 +11,7 @@ jobs:
CXXFLAGS: -Werror -Wall -pedantic
BUILD_TYPE: Debug
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7
- uses: ./.github/actions/install-ubuntu
- uses: ./.github/actions/build
@ -23,7 +23,19 @@ jobs:
CXXFLAGS: -Werror -Wall -pedantic
BUILD_TYPE: Debug
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7
- uses: ./.github/actions/install-ubuntu
- uses: ./.github/actions/build
ubuntu26:
runs-on: ubuntu-26.04
env:
CC: gcc
CXX: g++
CXXFLAGS: -Werror -Wall -pedantic
BUILD_TYPE: Debug
steps:
- uses: actions/checkout@v7
- uses: ./.github/actions/install-ubuntu
- uses: ./.github/actions/build
@ -35,7 +47,7 @@ jobs:
CXXFLAGS: -Werror -Wall -pedantic
BUILD_TYPE: Debug
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7
- uses: ./.github/actions/install-ubuntu
- uses: ./.github/actions/build
@ -48,7 +60,7 @@ jobs:
CXXFLAGS: -Werror -Wall -pedantic -Wno-array-bounds
BUILD_TYPE: Release
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7
- uses: ./.github/actions/install-ubuntu
- uses: ./.github/actions/build
@ -60,14 +72,14 @@ jobs:
CXXFLAGS: -Werror -Wall -pedantic -Wno-nullability-extension
BUILD_TYPE: Debug
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7
- uses: ./.github/actions/install-macos
- uses: ./.github/actions/build
windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7
- uses: ./.github/actions/install-windows
- uses: ./.github/actions/build-windows

View File

@ -6,10 +6,10 @@ jobs:
maven-ubuntu22:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7
- run: sudo apt-get install protobuf-compiler
- name: Set up JDK 8
uses: actions/setup-java@v4
uses: actions/setup-java@v5
with:
distribution: zulu
java-version: 8
@ -19,10 +19,23 @@ jobs:
maven-ubuntu24:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7
- run: sudo apt-get install protobuf-compiler
- name: Set up JDK 8
uses: actions/setup-java@v4
uses: actions/setup-java@v5
with:
distribution: zulu
java-version: 8
- name: Build with Maven
run: mvn -B package --file pom.xml
maven-ubuntu26:
runs-on: ubuntu-26.04
steps:
- uses: actions/checkout@v7
- run: sudo apt-get install protobuf-compiler
- name: Set up JDK 8
uses: actions/setup-java@v5
with:
distribution: zulu
java-version: 8
@ -32,10 +45,10 @@ jobs:
ant-ubuntu22:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7
- run: sudo apt-get install protobuf-compiler libprotobuf-java
- name: Set up JDK 8
uses: actions/setup-java@v4
uses: actions/setup-java@v5
with:
distribution: zulu
java-version: 8
@ -45,10 +58,23 @@ jobs:
ant-ubuntu24:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7
- run: sudo apt-get install protobuf-compiler libprotobuf-java
- name: Set up JDK 8
uses: actions/setup-java@v4
uses: actions/setup-java@v5
with:
distribution: zulu
java-version: 8
- name: Build with Ant
run: ant
ant-ubuntu26:
runs-on: ubuntu-26.04
steps:
- uses: actions/checkout@v7
- run: sudo apt-get install protobuf-compiler libprotobuf-java
- name: Set up JDK 8
uses: actions/setup-java@v5
with:
distribution: zulu
java-version: 8

View File

@ -1,5 +1,13 @@
## Unreleased
## Release notes for 1.7.0 (2026-07-26)
- C++: Fix buffer overflow in osmpbf-outline tool [#95](https://github.com/openstreetmap/OSM-binary/pull/95)
- C++: Various small code cleanups and modernizations
- C++: osmpbf-outline tool moved to demo directory, it isn't installed by default any more. This tool was never really useful for normal users, it is more a demo/example showing how to use the library
Note to packagers: You should remove the osmpbf-outline tool from packages.
## Release notes for 1.6.1 (2025-12-20)
- Java: Update to latest protoc and protobuf runtime versions [#92](https://github.com/openstreetmap/OSM-binary/pull/92)

View File

@ -1,6 +1,8 @@
cmake_minimum_required(VERSION 3.10)
project(osmpbf VERSION 1.5.0)
project(osmpbf VERSION 1.7.0)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
include(GNUInstallDirs)
@ -18,5 +20,5 @@ add_subdirectory(osmpbf)
# The osmpbf-outline tool does not compile on Windows because getopt.h is missing
if(NOT MSVC)
add_subdirectory(tools)
add_subdirectory(demo)
endif()

View File

@ -70,11 +70,11 @@ To install:
make install
```
There is a tool named osmpbf-outline that shows a debug output of the contents
of a PBF file. To run it:
There is a demo tool named osmpbf-outline that shows a debug output of some of
the contents of a PBF file. To run it:
```sh
tools/osmpbf-outline osm-file.osm.pbf
demo/osmpbf-outline osm-file.osm.pbf
```

View File

@ -21,7 +21,7 @@
<exec executable="/bin/sh">
<arg value="./build.sh"/>
</exec>
<javac includeantruntime="false" destdir="${build.dir}">
<javac includeantruntime="false" destdir="${build.dir}" source="1.8" target="1.8">
<src path="${src.dir}"/>
<src path="${src.generated.dir}"/>
<classpath>

View File

View File

@ -12,5 +12,5 @@ target_include_directories(osmpbf-outline SYSTEM PRIVATE ${ZLIB_INCLUDE_DIR})
target_link_libraries(osmpbf-outline PRIVATE osmpbf ZLIB::ZLIB protobuf::libprotobuf)
set_property(TARGET osmpbf-outline PROPERTY CXX_STANDARD 11)
install(TARGETS osmpbf-outline RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(FILES osmpbf-outline.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
#install(TARGETS osmpbf-outline RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
#install(FILES osmpbf-outline.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)

View File

@ -2,10 +2,10 @@
#include <unistd.h>
// used for va_list in debug-print methods
#include <stdarg.h>
#include <cstdarg>
// file io lib
#include <stdio.h>
#include <cstdio>
// getopt is used to check for the --color-flag
#include <getopt.h>
@ -23,47 +23,31 @@
// this is the header to pbf format
#include <osmpbf/osmpbf.h>
namespace {
// should the output use color?
bool usecolor = false;
// buffer for reading a compressed blob from file
char buffer[OSMPBF::max_uncompressed_blob_size];
// buffer for decompressing the blob
char unpack_buffer[OSMPBF::max_uncompressed_blob_size];
// pbf struct of a BlobHeader
OSMPBF::BlobHeader blobheader;
// pbf struct of a Blob
OSMPBF::Blob blob;
// pbf struct of an OSM HeaderBlock
OSMPBF::HeaderBlock headerblock;
// pbf struct of an OSM PrimitiveBlock
OSMPBF::PrimitiveBlock primblock;
// prints a formatted message to stdout, optionally color coded
void msg(const char* format, int color, va_list args) {
if (usecolor) {
fprintf(stdout, "\x1b[0;%dm", color);
std::fprintf(stdout, "\x1b[0;%dm", color);
}
vfprintf(stdout, format, args);
std::vfprintf(stdout, format, args);
if (usecolor) {
fprintf(stdout, "\x1b[0m\n");
std::fprintf(stdout, "\x1b[0m\n");
} else {
fprintf(stdout, "\n");
std::fprintf(stdout, "\n");
}
}
// prints a formatted message to stdout, color coded to red
void err(const char* format, ...) {
[[noreturn]] void err(const char* format, ...) {
va_list args;
va_start(args, format);
msg(format, 31, args);
va_end(args);
exit(1);
std::exit(1);
}
// prints a formatted message to stdout, color coded to yellow
@ -90,23 +74,25 @@ void debug(const char* format, ...) {
va_end(args);
}
} // anonymous namespace
// application main method
int main(int argc, char *argv[]) {
// check if the output is a tty so we can use colors
#ifdef WIN32
usecolor = 0;
usecolor = false;
#else
usecolor = isatty(1);
#endif
static struct option long_options[] = {
{"color", no_argument, 0, 'c'},
{0, 0, 0, 0}
option const long_options[] = {
{"color", no_argument, nullptr, 'c'},
{nullptr, 0, nullptr, 0}
};
while (1) {
int c = getopt_long(argc, argv, "c", long_options, 0);
while (true) {
int const c = getopt_long(argc, argv, "c", long_options, nullptr);
if (c == -1) {
break;
@ -117,7 +103,7 @@ int main(int argc, char *argv[]) {
usecolor = true;
break;
default:
exit(1);
return 1;
}
}
@ -127,19 +113,25 @@ int main(int argc, char *argv[]) {
}
// open specified file
FILE *fp = fopen(argv[optind], "rb");
FILE *fp = std::fopen(argv[optind], "rb");
if (!fp) {
err("can't open file '%s'", argv[optind]);
}
// buffer for reading a compressed blob from file
static char buffer[OSMPBF::max_uncompressed_blob_size];
// buffer for decompressing the blob
static char unpack_buffer[OSMPBF::max_uncompressed_blob_size];
// read while the file has not reached its end
while (!feof(fp)) {
while (!std::feof(fp)) {
// storage of size, used multiple times
int32_t sz;
std::uint32_t sz = 0;
// read the first 4 bytes of the file, this is the size of the blob-header
if (fread(&sz, sizeof(sz), 1, fp) != 1) {
if (std::fread(&sz, sizeof(sz), 1, fp) != 1) {
break; // end of file reached
}
@ -152,12 +144,15 @@ int main(int argc, char *argv[]) {
}
// read the blob-header from the file
if (fread(buffer, sz, 1, fp) != 1) {
if (std::fread(buffer, sz, 1, fp) != 1) {
err("unable to read blob-header from file");
}
// pbf struct of a BlobHeader
OSMPBF::BlobHeader blobheader;
// parse the blob-header from the read-buffer
if (!blobheader.ParseFromArray(buffer, sz)) {
if (!blobheader.ParseFromArray(buffer, static_cast<int>(sz))) {
err("unable to parse blob header");
}
@ -180,12 +175,15 @@ int main(int argc, char *argv[]) {
}
// read the blob from the file
if (fread(buffer, sz, 1, fp) != 1) {
if (std::fread(buffer, sz, 1, fp) != 1) {
err("unable to read blob from file");
}
// pbf struct of a Blob
OSMPBF::Blob blob;
// parse the blob from the read-buffer
if (!blob.ParseFromArray(buffer, sz)) {
if (!blob.ParseFromArray(buffer, static_cast<int>(sz))) {
err("unable to parse blob");
}
@ -204,15 +202,15 @@ int main(int argc, char *argv[]) {
sz = blob.raw().size();
// check that raw_size is set correctly
if (sz != blob.raw_size()) {
warn(" reports wrong raw_size: %u bytes", blob.raw_size());
if (sz != static_cast<std::uint32_t>(blob.raw_size())) {
warn(" reports wrong raw_size: %d bytes", blob.raw_size());
}
// tell about the blob-data
debug(" contains uncompressed data: %u bytes", sz);
// copy the uncompressed data over to the unpack_buffer
memcpy(unpack_buffer, buffer, sz);
std::memcpy(unpack_buffer, buffer, sz);
}
// if the blob has zlib-compressed data
@ -232,6 +230,12 @@ int main(int argc, char *argv[]) {
debug(" contains zlib-compressed data: %u bytes", sz);
debug(" uncompressed size: %u bytes", blob.raw_size());
// ensure the raw_size fits into the unpack_buffer, otherwise
// zlib would inflate past the end of the fixed-size buffer
if (blob.raw_size() < 0 || blob.raw_size() > OSMPBF::max_uncompressed_blob_size) {
err(" raw_size is bigger then allowed (%d > %u)", blob.raw_size(), OSMPBF::max_uncompressed_blob_size);
}
// zlib information
z_stream z;
@ -273,9 +277,6 @@ int main(int argc, char *argv[]) {
warn(" contains several data streams");
}
// we have at least one datastream
found_data = true;
// tell about the compressed data
debug(" contains lzma-compressed data: %u bytes", blob.lzma_data().size());
debug(" uncompressed size: %u bytes", blob.raw_size());
@ -284,6 +285,36 @@ int main(int argc, char *argv[]) {
err(" lzma-decompression is not supported");
}
// if the blob has lz4-compressed data
if (blob.has_lz4_data()) {
// issue a warning if there is more than one data steam, a blob may only contain one data stream
if (found_data) {
warn(" contains several data streams");
}
// tell about the compressed data
debug(" contains lz4-compressed data: %u bytes", blob.lz4_data().size());
debug(" uncompressed size: %u bytes", blob.raw_size());
// issue a warning, lz4 compression is not yet supported
err(" lz4-decompression is not supported");
}
// if the blob has zstd-compressed data
if (blob.has_zstd_data()) {
// issue a warning if there is more than one data steam, a blob may only contain one data stream
if (found_data) {
warn(" contains several data streams");
}
// tell about the compressed data
debug(" contains zstd-compressed data: %u bytes", blob.zstd_data().size());
debug(" uncompressed size: %u bytes", blob.raw_size());
// issue a warning, zstd compression is not yet supported
err(" zstd-decompression is not supported");
}
// check we have at least one data-stream
if (!found_data) {
err(" does not contain any known data stream");
@ -294,28 +325,31 @@ int main(int argc, char *argv[]) {
// tell about the OSMHeader blob
info(" OSMHeader");
// pbf struct of an OSM HeaderBlock
OSMPBF::HeaderBlock headerblock;
// parse the HeaderBlock from the blob
if (!headerblock.ParseFromArray(unpack_buffer, sz)) {
if (!headerblock.ParseFromArray(unpack_buffer, static_cast<int>(sz))) {
err("unable to parse header block");
}
// tell about the bbox
if (headerblock.has_bbox()) {
OSMPBF::HeaderBBox bbox = headerblock.bbox();
OSMPBF::HeaderBBox const& bbox = headerblock.bbox();
debug(" bbox: %.7f,%.7f,%.7f,%.7f",
(double)bbox.left() / OSMPBF::lonlat_resolution,
(double)bbox.bottom() / OSMPBF::lonlat_resolution,
(double)bbox.right() / OSMPBF::lonlat_resolution,
(double)bbox.top() / OSMPBF::lonlat_resolution);
static_cast<double>(bbox.left()) / OSMPBF::lonlat_resolution,
static_cast<double>(bbox.bottom()) / OSMPBF::lonlat_resolution,
static_cast<double>(bbox.right()) / OSMPBF::lonlat_resolution,
static_cast<double>(bbox.top()) / OSMPBF::lonlat_resolution);
}
// tell about the required features
for (int i = 0, l = headerblock.required_features_size(); i < l; i++) {
for (int i = 0, l = headerblock.required_features_size(); i < l; ++i) {
debug(" required_feature: %s", headerblock.required_features(i).c_str());
}
// tell about the optional features
for (int i = 0, l = headerblock.optional_features_size(); i < l; i++) {
for (int i = 0, l = headerblock.optional_features_size(); i < l; ++i) {
debug(" optional_feature: %s", headerblock.optional_features(i).c_str());
}
@ -332,8 +366,11 @@ int main(int argc, char *argv[]) {
// tell about the OSMData blob
info(" OSMData");
// pbf struct of an OSM PrimitiveBlock
OSMPBF::PrimitiveBlock primblock;
// parse the PrimitiveBlock from the blob
if (!primblock.ParseFromArray(unpack_buffer, sz)) {
if (!primblock.ParseFromArray(unpack_buffer, static_cast<int>(sz))) {
err("unable to parse primitive block");
}
@ -350,11 +387,11 @@ int main(int argc, char *argv[]) {
debug(" primitivegroups: %u groups", primblock.primitivegroup_size());
// iterate over all PrimitiveGroups
for (int i = 0, l = primblock.primitivegroup_size(); i < l; i++) {
for (int i = 0, l = primblock.primitivegroup_size(); i < l; ++i) {
// one PrimitiveGroup from the the Block
OSMPBF::PrimitiveGroup pg = primblock.primitivegroup(i);
OSMPBF::PrimitiveGroup const& pg = primblock.primitivegroup(i);
bool found_items=false;
bool found_items = false;
// tell about nodes
if (pg.nodes_size() > 0) {
@ -409,7 +446,7 @@ int main(int argc, char *argv[]) {
}
// close the file pointer
fclose(fp);
std::fclose(fp);
// clean up the protobuf lib
google::protobuf::ShutdownProtobufLibrary();

View File

@ -18,7 +18,7 @@
// this describes the high-level OSM objects
#include <osmpbf/osmformat.pb.h> // IWYU pragma: export
#define OSMPBF_VERSION "1.5.0"
#define OSMPBF_VERSION "1.7.0"
namespace OSMPBF {

View File

@ -6,7 +6,7 @@
<groupId>org.openstreetmap.pbf</groupId>
<artifactId>osmpbf</artifactId>
<packaging>jar</packaging>
<version>1.6.1</version>
<version>1.7.0</version>
<name>OSM-Binary</name>
<description>Library for the OpenStreetMap PBF format</description>
<url>https://github.com/openstreetmap/OSM-binary</url>