aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKrzysztof KosiƄski <krzysio@google.com>2021-10-28 08:54:07 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2021-10-28 08:54:07 +0000
commitc41cd8542e1d91e1ba3e3a366095376ce81c51c3 (patch)
treefe885fd8676eb3a340f7dad5e05240e4f6b551d1
parent75930fdbca54e79d07a890855a04f161a7cbdce9 (diff)
parent31d9b7d2423131b1f27dba43834edd5432efd6fa (diff)
downloadnanopb-c-c41cd8542e1d91e1ba3e3a366095376ce81c51c3.tar.gz
Upgrade nanopb to 0.3.9.2. am: 8eaf90c022 am: ce669ebda9 am: 31d9b7d242
Original change: https://android-review.googlesource.com/c/platform/external/nanopb-c/+/1869256 Change-Id: I7da2cf793f1add66c452eef0a270643b4fbc50aa
-rw-r--r--.gitignore28
-rw-r--r--.travis.yml60
-rw-r--r--AUTHORS.txt9
-rw-r--r--CHANGELOG.txt14
-rw-r--r--CMakeLists.txt59
-rw-r--r--METADATA9
-rw-r--r--MODULE_LICENSE_BSD_LIKE (renamed from MODULE_LICENSE_PUBLIC_DOMAIN)0
-rw-r--r--OWNERS3
-rw-r--r--README.android12
-rw-r--r--README.md16
-rw-r--r--README.version3
-rw-r--r--docs/concepts.rst5
-rw-r--r--examples/simple/rules.mk24
-rw-r--r--examples/simple/simple.pb.c19
-rw-r--r--examples/simple/simple.pb.h51
-rw-r--r--extra/FindNanopb.cmake6
-rw-r--r--extra/nanopb-config-version.cmake.in22
-rw-r--r--extra/nanopb-config.cmake2
-rwxr-xr-xgenerator/nanopb_generator.py138
-rw-r--r--generator/proto/nanopb.proto9
-rw-r--r--library.json2
-rw-r--r--pb.h25
-rw-r--r--pb_decode.c13
-rw-r--r--pb_encode.c2
-rw-r--r--tests/SConstruct16
-rw-r--r--tests/mem_release/mem_release.c36
-rw-r--r--tests/mem_release/mem_release.proto6
-rw-r--r--tests/multiple_files/subdir/multifile2.proto5
-rw-r--r--tests/multiple_files/test_multiple_files.c3
-rw-r--r--tests/regression/issue_338/SConscript7
-rw-r--r--tests/regression/issue_338/bigvalue.proto204
-rw-r--r--tests/regression/issue_342/SConscript21
-rw-r--r--tests/regression/issue_342/extensions.proto11
-rw-r--r--tests/regression/issue_342/test_extensions.c52
-rw-r--r--tests/typename_mangling/SConscript20
-rw-r--r--tests/typename_mangling/test_flatten.c22
-rw-r--r--tests/typename_mangling/test_strip_package.c19
-rw-r--r--tests/typename_mangling/with_package.options5
-rw-r--r--tests/typename_mangling/with_package.proto38
39 files changed, 788 insertions, 208 deletions
diff --git a/.gitignore b/.gitignore
index c9b568f..3bb09db 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,28 @@
+*.gcda
+*.gcno
+*.gcov
+*.o
+*.pb.c
+*.pb.h
+*.pb
*.pyc
-*.swp
+*_pb2.py
+*~
+*.tar.gz
+.sconsign.dblite
+config.log
+.sconf_temp
+tests/build
+julkaisu.txt
+dist
+docs/*.html
+docs/generator_flow.png
+examples/simple/simple
+examples/network_server/client
+examples/network_server/server
+examples/using_double_on_avr/decode_double
+examples/using_double_on_avr/encode_double
+examples/using_double_on_avr/test_conversions
+examples/using_union_messages/decode
+examples/using_union_messages/encode
+generator/nanopb_pb2.pyc
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..e8eca0f
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,60 @@
+# Travis CI has no ability to handle 3 langauges (c, c++, python)
+# and it overrides $CC/$CXX if language is set to c/c++ (only one, not both).
+#
+# Set language to python since at least the result of that is something useful.
+language: python
+
+python:
+ - "2.7"
+ - "3.4"
+
+# Manage the C/C++ compiler manually
+env:
+ - CC=gcc CXX=g++
+ - CC=gcc-4.8 CXX=g++-4.8
+ - CC=gcc-4.9 CXX=g++-4.9
+ - CC=gcc-5 CXX=g++-5
+ - CC=clang CXX=clang++
+
+addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ packages:
+ - gcc-4.8
+ - g++-4.8
+ - gcc-4.9
+ - g++-4.9
+ - gcc-5
+ - g++-5
+
+
+before_install:
+ - export PATH=$HOME/.local/bin:$HOME/protobuf/bin:$PATH
+ - export MAKEFLAGS=-j$(nproc)
+ - $CC --version
+ - $CXX --version
+ - python --version
+ - lsb_release -a
+
+# Seems to be issues with concurrent builds
+#cache:
+# directories:
+# - $HOME/protobuf
+
+# Rather then compile protobuf 3 from source, use the binaries now available
+# to speed up build time and reduce surprises until Ubuntu adds protobuf3
+# packages to the repository.
+install:
+ - mkdir -p $HOME/protobuf && pushd $HOME/protobuf
+ && curl -LO 'https://github.com/google/protobuf/releases/download/v3.4.0/protoc-3.4.0-linux-x86_64.zip'
+ && unzip protoc-3.4.0-linux-x86_64.zip
+ && popd
+ - curl -L 'https://github.com/google/protobuf/releases/download/v3.4.0/protobuf-python-3.4.0.tar.gz' | tar xzf -
+ && pushd protobuf-3.4.0/python
+ && python setup.py build && python setup.py install
+ && popd
+
+script:
+ - pushd generator/proto && make && popd
+ - pushd tests && scons CC=$CC CXX=$CXX && popd
diff --git a/AUTHORS.txt b/AUTHORS.txt
index 0034abf..2d63fed 100644
--- a/AUTHORS.txt
+++ b/AUTHORS.txt
@@ -42,4 +42,11 @@ Edward Z. Yang <ezyang@mit.edu>
Robbie Shade <rjshade@google.com>
Andrew Ballinger <andrewballinger@stratisopt.com>
Hamina, Juha-Pekka <Juha-Pekka.Hamina@nordicsemi.no>
-
+Jason Bishop <jason.bishop@bigassfans.com>
+matejcik <ja@matejcik.cz>
+Tobias MĂŒller <Tobias_Mueller@twam.info>
+Jari Vetoniemi <mailroxas@gmail.com>
+Gabriel Staples <ercaguy@gmail.com>
+Amarnath <amarnath.h.96@gmail.com>
+Michal Rostecki <mrostecki@suse.de>
+Pei Wang <wangpei10@baidu.com>
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index f7811a4..4c6ab7f 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -1,4 +1,16 @@
-nanopb-0.3.9.1 (2017-04-xx)
+nanopb-0.3.9.2 (2018-11-10)
+ Erroneous free() when using callbacks combined with PB_ENABLE_MALLOC (#346)
+ Fix possible null-pointer dereference in decode_callback_field (#342)
+ Fix FindNanopb.cmake on Windows (#335)
+ Fix large generator memory usage with oneof fields (#338)
+ Fix error in splint test (#359)
+ Allow cmake to build as a shared library (#352, #353)
+ Add --no-strip-path command line option (#326)
+ Option for flattening nested protobuf names (#333)
+ Documentation fixes (#329, #350, #358)
+ Better error messages (#351)
+
+nanopb-0.3.9.1 (2018-04-14)
Fix handling of special characters in string/bytes default values (issue #322)
Fix encoding of negative numbers with PB_WITHOUT_64BIT (#285)
Fix _zero initializer for enums that don't begin at 0. (#295)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2625a66..642c68d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,10 +2,14 @@ cmake_minimum_required(VERSION 2.8.12)
project(nanopb C)
-set(nanopb_VERSION_STRING nanopb-0.3.9.1)
+set(nanopb_VERSION_STRING nanopb-0.3.9.2)
+set(nanopb_SOVERSION 0)
string(REPLACE "nanopb-" "" nanopb_VERSION ${nanopb_VERSION_STRING})
+option(BUILD_SHARED_LIBS "Build shared libraries" OFF)
+option(BUILD_STATIC_LIBS "Build static libraries" ON)
+
option(nanopb_BUILD_RUNTIME "Build the headers and libraries needed at runtime" ON)
option(nanopb_BUILD_GENERATOR "Build the protoc plugin for code generation" ON)
option(nanopb_MSVC_STATIC_RUNTIME "Link static runtime libraries" ON)
@@ -31,7 +35,7 @@ if(MSVC AND nanopb_MSVC_STATIC_RUNTIME)
endif()
if(NOT DEFINED CMAKE_INSTALL_CMAKEDIR)
- set(CMAKE_INSTALL_CMAKEDIR "lib/cmake/nanopb")
+ set(CMAKE_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/nanopb")
endif()
if(nanopb_BUILD_GENERATOR)
@@ -62,25 +66,46 @@ if(nanopb_BUILD_GENERATOR)
endif()
if(nanopb_BUILD_RUNTIME)
- add_library(protobuf-nanopb STATIC
- pb.h
- pb_common.h
- pb_common.c
- pb_encode.h
- pb_encode.c
- pb_decode.h
- pb_decode.c)
-
- target_include_directories(protobuf-nanopb INTERFACE
- $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
- )
+ if(BUILD_SHARED_LIBS)
+ add_library(protobuf-nanopb SHARED
+ pb.h
+ pb_common.h
+ pb_common.c
+ pb_encode.h
+ pb_encode.c
+ pb_decode.h
+ pb_decode.c)
+ set_target_properties(protobuf-nanopb PROPERTIES
+ SOVERSION ${nanopb_SOVERSION})
+ install(TARGETS protobuf-nanopb EXPORT nanopb-targets
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
+ target_include_directories(protobuf-nanopb INTERFACE
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+ )
+ endif()
+
+ if(BUILD_STATIC_LIBS)
+ add_library(protobuf-nanopb-static STATIC
+ pb.h
+ pb_common.h
+ pb_common.c
+ pb_encode.h
+ pb_encode.c
+ pb_decode.h
+ pb_decode.c)
+ set_target_properties(protobuf-nanopb-static PROPERTIES
+ OUTPUT_NAME protobuf-nanopb)
+ install(TARGETS protobuf-nanopb-static EXPORT nanopb-targets
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
+ target_include_directories(protobuf-nanopb-static INTERFACE
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+ )
+ endif()
configure_file(extra/nanopb-config-version.cmake.in
nanopb-config-version.cmake @ONLY)
- install(TARGETS protobuf-nanopb EXPORT nanopb-targets
- ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
-
install(EXPORT nanopb-targets
DESTINATION ${CMAKE_INSTALL_CMAKEDIR}
NAMESPACE nanopb::)
diff --git a/METADATA b/METADATA
index d97975c..6e439ec 100644
--- a/METADATA
+++ b/METADATA
@@ -1,3 +1,12 @@
+name: "nanopb"
+description: "Nanopb - Protocol Buffers for Embedded Systems"
+
third_party {
+ url {
+ type: GIT
+ value: "https://github.com/nanopb/nanopb"
+ }
+ version: "0.3.9.2"
+ last_upgrade_date { year: 2021 month: 10 day: 27 }
license_type: NOTICE
}
diff --git a/MODULE_LICENSE_PUBLIC_DOMAIN b/MODULE_LICENSE_BSD_LIKE
index e69de29..e69de29 100644
--- a/MODULE_LICENSE_PUBLIC_DOMAIN
+++ b/MODULE_LICENSE_BSD_LIKE
diff --git a/OWNERS b/OWNERS
index e0fd5b8..400f949 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,5 +1,4 @@
-# Default code reviewers picked from top 3 or more developers.
-# Please update this list if you find better candidates.
shanyu@google.com
jeffbailey@google.com
rtenneti@google.com
+krzysio@google.com
diff --git a/README.android b/README.android
deleted file mode 100644
index 5ce0117..0000000
--- a/README.android
+++ /dev/null
@@ -1,12 +0,0 @@
-URL: https://jpa.kapsi.fi/nanopb/
-Version: 0.3.9.1
-License: zlib
-Description: "nanopb-c: A plugin for Google Protobuf compiler that generates C code"
-
-To use with Android modify Android.mk adding .proto files to
-LOCAL_SRC_FILES and set LOCAL_PROTOC_OPTIMIZE_TYPE:
-
- LOCAL_SRC_FILES += simple.proto
- LOCAL_PROTOC_OPTIMIZE_TYPE := nanopb-c
-
-Then look at https://jpa.kapsi.fi/nanopb/ Documentation for how to use nanopb-c.
diff --git a/README.md b/README.md
index 07860f0..1a73cdd 100644
--- a/README.md
+++ b/README.md
@@ -18,8 +18,8 @@ Using the nanopb library
------------------------
To use the nanopb library, you need to do two things:
-1. Compile your .proto files for nanopb, using protoc.
-2. Include pb_encode.c, pb_decode.c and pb_common.c in your project.
+1. Compile your .proto files for nanopb, using `protoc`.
+2. Include *pb_encode.c*, *pb_decode.c* and *pb_common.c* in your project.
The easiest way to get started is to study the project in "examples/simple".
It contains a Makefile, which should work directly under most Linux systems.
@@ -30,23 +30,23 @@ README.txt in that folder.
Using the Protocol Buffers compiler (protoc)
--------------------------------------------
-The nanopb generator is implemented as a plugin for the Google's own protoc
+The nanopb generator is implemented as a plugin for the Google's own `protoc`
compiler. This has the advantage that there is no need to reimplement the
basic parsing of .proto files. However, it does mean that you need the
Google's protobuf library in order to run the generator.
If you have downloaded a binary package for nanopb (either Windows, Linux or
-Mac OS X version), the 'protoc' binary is included in the 'generator-bin'
+Mac OS X version), the `protoc` binary is included in the 'generator-bin'
folder. In this case, you are ready to go. Simply run this command:
generator-bin/protoc --nanopb_out=. myprotocol.proto
However, if you are using a git checkout or a plain source distribution, you
-need to provide your own version of protoc and the Google's protobuf library.
-On Linux, the necessary packages are protobuf-compiler and python-protobuf.
+need to provide your own version of `protoc` and the Google's protobuf library.
+On Linux, the necessary packages are `protobuf-compiler` and `python-protobuf`.
On Windows, you can either build Google's protobuf library from source or use
one of the binary distributions of it. In either case, if you use a separate
-protoc, you need to manually give the path to nanopb generator:
+`protoc`, you need to manually give the path to nanopb generator:
protoc --plugin=protoc-gen-nanopb=nanopb/generator/protoc-gen-nanopb ...
@@ -57,7 +57,7 @@ Running the tests
If you want to perform further development of the nanopb core, or to verify
its functionality using your compiler and platform, you'll want to run the
test suite. The build rules for the test suite are implemented using Scons,
-so you need to have that installed. To run the tests:
+so you need to have that installed (ex: `sudo apt install scons` on Ubuntu). To run the tests:
cd tests
scons
diff --git a/README.version b/README.version
deleted file mode 100644
index b0e5805..0000000
--- a/README.version
+++ /dev/null
@@ -1,3 +0,0 @@
-URL: https://github.com/nanopb/nanopb/archive/0.3.9.1.tar.gz
-Version: 0.3.9.1
-BugComponent: 31808
diff --git a/docs/concepts.rst b/docs/concepts.rst
index 1f9aec1..168e564 100644
--- a/docs/concepts.rst
+++ b/docs/concepts.rst
@@ -317,6 +317,11 @@ The user is expected to set the filed manually using the correct field tag::
Notice that neither ``which_payload`` field nor the unused fileds in ``payload``
will consume any space in the resulting encoded message.
+When a C union is used to represent a ``oneof`` section, the union cannot have
+callback fields or nested callback fields. Otherwise, the decoding process may
+fail. If callbacks must be used inside a ``oneof`` section, the generator
+option *no_unions* should be set to *true* for that section.
+
.. _`oneof`: https://developers.google.com/protocol-buffers/docs/reference/proto2-spec#oneof_and_oneof_field
Extension fields
diff --git a/examples/simple/rules.mk b/examples/simple/rules.mk
deleted file mode 100644
index 1e4221d..0000000
--- a/examples/simple/rules.mk
+++ /dev/null
@@ -1,24 +0,0 @@
-NANOPB_DIR := external/nanopb-0.3.9.1-linux-x86
-
-LOCAL_DIR := $(GET_LOCAL_DIR)
-
-MODULE := $(LOCAL_DIR)
-
-MODULE_SRCS += \
- $(LOCAL_DIR)/simple.c \
- $(LOCAL_DIR)/simple.pb.c \
- $(NANOPB_DIR)/pb_encode.c \
- $(NANOPB_DIR)/pb_decode.c \
- $(NANOPB_DIR)/pb_common.c
-
-MODULE_CPPFLAGS += -std=c++11
-
-MODULE_INCLUDES += \
- $(NANOPB_DIR)
-
-$(LOCAL_DIR)/simple.pb.c: $(LOCAL_DIR)/simple.proto
- $(PROTOC) $(PROTOC_OPTS) --nanopb_out=$(LOCAL_DIR) $(LOCAL_DIR)/simple.proto
-
-include $(NANOPB_DIR)/extra/nanopb.mk
-include make/module.mk
-
diff --git a/examples/simple/simple.pb.c b/examples/simple/simple.pb.c
deleted file mode 100644
index 481aa7d..0000000
--- a/examples/simple/simple.pb.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Automatically generated nanopb constant definitions */
-/* Generated by nanopb-0.3.9.1 at Fri May 25 16:28:54 2018. */
-
-#include "simple.pb.h"
-
-/* @@protoc_insertion_point(includes) */
-#if PB_PROTO_HEADER_VERSION != 30
-#error Regenerate this file with the current version of nanopb generator.
-#endif
-
-
-
-const pb_field_t SimpleMessage_fields[2] = {
- PB_FIELD( 1, INT32 , REQUIRED, STATIC , FIRST, SimpleMessage, lucky_number, lucky_number, 0),
- PB_LAST_FIELD
-};
-
-
-/* @@protoc_insertion_point(eof) */
diff --git a/examples/simple/simple.pb.h b/examples/simple/simple.pb.h
deleted file mode 100644
index f4614db..0000000
--- a/examples/simple/simple.pb.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* Automatically generated nanopb header */
-/* Generated by nanopb-0.3.9.1 at Fri May 25 16:28:54 2018. */
-
-#ifndef PB_SIMPLE_PB_H_INCLUDED
-#define PB_SIMPLE_PB_H_INCLUDED
-#include <pb.h>
-
-/* @@protoc_insertion_point(includes) */
-#if PB_PROTO_HEADER_VERSION != 30
-#error Regenerate this file with the current version of nanopb generator.
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Struct definitions */
-typedef struct _SimpleMessage {
- int32_t lucky_number;
-/* @@protoc_insertion_point(struct:SimpleMessage) */
-} SimpleMessage;
-
-/* Default values for struct fields */
-
-/* Initializer values for message structs */
-#define SimpleMessage_init_default {0}
-#define SimpleMessage_init_zero {0}
-
-/* Field tags (for use in manual encoding/decoding) */
-#define SimpleMessage_lucky_number_tag 1
-
-/* Struct field encoding specification for nanopb */
-extern const pb_field_t SimpleMessage_fields[2];
-
-/* Maximum encoded size of messages (where known) */
-#define SimpleMessage_size 11
-
-/* Message IDs (where set with "msgid" option) */
-#ifdef PB_MSGID
-
-#define SIMPLE_MESSAGES \
-
-
-#endif
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-/* @@protoc_insertion_point(eof) */
-
-#endif
diff --git a/extra/FindNanopb.cmake b/extra/FindNanopb.cmake
index bba341d..7730251 100644
--- a/extra/FindNanopb.cmake
+++ b/extra/FindNanopb.cmake
@@ -149,7 +149,11 @@ function(NANOPB_GENERATE_CPP SRCS HDRS)
set(GENERATOR_PATH ${CMAKE_BINARY_DIR}/nanopb/generator)
set(NANOPB_GENERATOR_EXECUTABLE ${GENERATOR_PATH}/nanopb_generator.py)
- set(NANOPB_GENERATOR_PLUGIN ${GENERATOR_PATH}/protoc-gen-nanopb)
+ if (WIN32)
+ set(NANOPB_GENERATOR_PLUGIN ${GENERATOR_PATH}/protoc-gen-nanopb.bat)
+ else()
+ set(NANOPB_GENERATOR_PLUGIN ${GENERATOR_PATH}/protoc-gen-nanopb)
+ endif()
set(GENERATOR_CORE_DIR ${GENERATOR_PATH}/proto)
set(GENERATOR_CORE_SRC
diff --git a/extra/nanopb-config-version.cmake.in b/extra/nanopb-config-version.cmake.in
index 1b51027..f9292a8 100644
--- a/extra/nanopb-config-version.cmake.in
+++ b/extra/nanopb-config-version.cmake.in
@@ -1,11 +1,11 @@
-set(PACKAGE_VERSION "@nanopb_VERSION@")
-
-# Check whether the requested PACKAGE_FIND_VERSION is compatible
-if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
- set(PACKAGE_VERSION_COMPATIBLE FALSE)
-else()
- set(PACKAGE_VERSION_COMPATIBLE TRUE)
- if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
- set(PACKAGE_VERSION_EXACT TRUE)
- endif()
-endif()
+set(PACKAGE_VERSION "@nanopb_VERSION@")
+
+# Check whether the requested PACKAGE_FIND_VERSION is compatible
+if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
+ set(PACKAGE_VERSION_COMPATIBLE FALSE)
+else()
+ set(PACKAGE_VERSION_COMPATIBLE TRUE)
+ if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
+ set(PACKAGE_VERSION_EXACT TRUE)
+ endif()
+endif()
diff --git a/extra/nanopb-config.cmake b/extra/nanopb-config.cmake
index 42d977a..4f726a6 100644
--- a/extra/nanopb-config.cmake
+++ b/extra/nanopb-config.cmake
@@ -1 +1 @@
-include(${CMAKE_CURRENT_LIST_DIR}/nanopb-targets.cmake)
+include(${CMAKE_CURRENT_LIST_DIR}/nanopb-targets.cmake)
diff --git a/generator/nanopb_generator.py b/generator/nanopb_generator.py
index 5b74ca1..906a1ac 100755
--- a/generator/nanopb_generator.py
+++ b/generator/nanopb_generator.py
@@ -3,7 +3,7 @@
from __future__ import unicode_literals
'''Generate header file for nanopb from a ProtoBuf FileDescriptorSet.'''
-nanopb_version = "nanopb-0.3.9.1"
+nanopb_version = "nanopb-0.3.9.2"
import sys
import re
@@ -44,6 +44,9 @@ except TypeError:
*** which protoc ***
*** protoc --version ***
*** python -c 'import google.protobuf; print(google.protobuf.__file__)' ***
+ *** If you are not able to find the python protobuf version using the ***
+ *** above command, use this command. ***
+ *** pip freeze | grep -i protobuf ***
****************************************************************************
''' + '\n')
raise
@@ -95,11 +98,14 @@ try:
except NameError:
strtypes = (str, )
+
class Names:
'''Keeps a set of nested names and formats them to C identifier.'''
def __init__(self, parts = ()):
if isinstance(parts, Names):
parts = parts.parts
+ elif isinstance(parts, strtypes):
+ parts = (parts,)
self.parts = tuple(parts)
def __str__(self):
@@ -108,6 +114,8 @@ class Names:
def __add__(self, other):
if isinstance(other, strtypes):
return Names(self.parts + (other,))
+ elif isinstance(other, Names):
+ return Names(self.parts + other.parts)
elif isinstance(other, tuple):
return Names(self.parts + other)
else:
@@ -183,12 +191,15 @@ class Enum:
'''desc is EnumDescriptorProto'''
self.options = enum_options
- self.names = names + desc.name
+ self.names = names
+
+ # by definition, `names` include this enum's name
+ base_name = Names(names.parts[:-1])
if enum_options.long_names:
- self.values = [(self.names + x.name, x.number) for x in desc.value]
- else:
self.values = [(names + x.name, x.number) for x in desc.value]
+ else:
+ self.values = [(base_name + x.name, x.number) for x in desc.value]
self.value_longnames = [self.names + x.name for x in desc.value]
self.packed = enum_options.packed_enum
@@ -640,6 +651,13 @@ class Field:
if encsize is not None:
# Include submessage length prefix
encsize += varint_max_size(encsize.upperlimit())
+ else:
+ my_msg = dependencies.get(str(self.struct_name))
+ if my_msg and submsg.protofile == my_msg.protofile:
+ # The dependency is from the same file and size cannot be
+ # determined for it, thus we know it will not be possible
+ # in runtime either.
+ return None
if encsize is None:
# Submessage or its size cannot be found.
@@ -719,8 +737,8 @@ class ExtensionRange(Field):
return EncodedSize(0)
class ExtensionField(Field):
- def __init__(self, struct_name, desc, field_options):
- self.fullname = struct_name + desc.name
+ def __init__(self, fullname, desc, field_options):
+ self.fullname = fullname
self.extendee_name = names_from_type_name(desc.extendee)
Field.__init__(self, self.fullname + 'struct', desc, field_options)
@@ -845,24 +863,33 @@ class OneOf(Field):
def encoded_size(self, dependencies):
'''Returns the size of the largest oneof field.'''
- largest = EncodedSize(0)
- symbols = set()
+ largest = 0
+ symbols = []
for f in self.fields:
size = EncodedSize(f.encoded_size(dependencies))
- if size.value is None:
+ if size is None or size.value is None:
return None
elif size.symbols:
- symbols.add(EncodedSize(f.submsgname + 'size').symbols[0])
- elif size.value > largest.value:
- largest = size
+ symbols.append((f.tag, size.symbols[0]))
+ elif size.value > largest:
+ largest = size.value
if not symbols:
+ # Simple case, all sizes were known at generator time
return largest
- symbols = list(symbols)
- symbols.append(str(largest))
- max_size = lambda x, y: '({0} > {1} ? {0} : {1})'.format(x, y)
- return reduce(max_size, symbols)
+ if largest > 0:
+ # Some sizes were known, some were not
+ symbols.insert(0, (0, largest))
+
+ if len(symbols) == 1:
+ # Only one symbol was needed
+ return EncodedSize(5, [symbols[0][1]])
+ else:
+ # Use sizeof(union{}) construct to find the maximum size of
+ # submessages.
+ union_def = ' '.join('char f%d[%s];' % s for s in symbols)
+ return EncodedSize(5, ['sizeof(union{%s})' % union_def])
# ---------------------------------------------------------------------------
# Generation of messages (structures)
@@ -1021,7 +1048,7 @@ class Message:
# Processing of entire .proto files
# ---------------------------------------------------------------------------
-def iterate_messages(desc, names = Names()):
+def iterate_messages(desc, flatten = False, names = Names()):
'''Recursively find all messages. For each, yield name, DescriptorProto.'''
if hasattr(desc, 'message_type'):
submsgs = desc.message_type
@@ -1030,19 +1057,22 @@ def iterate_messages(desc, names = Names()):
for submsg in submsgs:
sub_names = names + submsg.name
- yield sub_names, submsg
+ if flatten:
+ yield Names(submsg.name), submsg
+ else:
+ yield sub_names, submsg
- for x in iterate_messages(submsg, sub_names):
+ for x in iterate_messages(submsg, flatten, sub_names):
yield x
-def iterate_extensions(desc, names = Names()):
+def iterate_extensions(desc, flatten = False, names = Names()):
'''Recursively find all extensions.
For each, yield name, FieldDescriptorProto.
'''
for extension in desc.extension:
yield names, extension
- for subname, subdesc in iterate_messages(desc, names):
+ for subname, subdesc in iterate_messages(desc, flatten, names):
for extension in subdesc.extension:
yield subname, extension
@@ -1104,37 +1134,73 @@ class ProtoFile:
self.messages = []
self.extensions = []
+ mangle_names = self.file_options.mangle_names
+ flatten = mangle_names == nanopb_pb2.M_FLATTEN
+ strip_prefix = None
+ if mangle_names == nanopb_pb2.M_STRIP_PACKAGE:
+ strip_prefix = "." + self.fdesc.package
+
+ def create_name(names):
+ if mangle_names == nanopb_pb2.M_NONE:
+ return base_name + names
+ elif mangle_names == nanopb_pb2.M_STRIP_PACKAGE:
+ return Names(names)
+ else:
+ single_name = names
+ if isinstance(names, Names):
+ single_name = names.parts[-1]
+ return Names(single_name)
+
+ def mangle_field_typename(typename):
+ if mangle_names == nanopb_pb2.M_FLATTEN:
+ return "." + typename.split(".")[-1]
+ elif strip_prefix is not None and typename.startswith(strip_prefix):
+ return typename[len(strip_prefix):]
+ else:
+ return typename
+
if self.fdesc.package:
base_name = Names(self.fdesc.package.split('.'))
else:
base_name = Names()
for enum in self.fdesc.enum_type:
- enum_options = get_nanopb_suboptions(enum, self.file_options, base_name + enum.name)
- self.enums.append(Enum(base_name, enum, enum_options))
+ name = create_name(enum.name)
+ enum_options = get_nanopb_suboptions(enum, self.file_options, name)
+ self.enums.append(Enum(name, enum, enum_options))
- for names, message in iterate_messages(self.fdesc, base_name):
- message_options = get_nanopb_suboptions(message, self.file_options, names)
+ for names, message in iterate_messages(self.fdesc, flatten):
+ name = create_name(names)
+ message_options = get_nanopb_suboptions(message, self.file_options, name)
if message_options.skip_message:
continue
- self.messages.append(Message(names, message, message_options))
+ for field in message.field:
+ if field.type in (FieldD.TYPE_MESSAGE, FieldD.TYPE_ENUM):
+ field.type_name = mangle_field_typename(field.type_name)
+
+
+ self.messages.append(Message(name, message, message_options))
for enum in message.enum_type:
- enum_options = get_nanopb_suboptions(enum, message_options, names + enum.name)
- self.enums.append(Enum(names, enum, enum_options))
+ name = create_name(names + enum.name)
+ enum_options = get_nanopb_suboptions(enum, message_options, name)
+ self.enums.append(Enum(name, enum, enum_options))
- for names, extension in iterate_extensions(self.fdesc, base_name):
- field_options = get_nanopb_suboptions(extension, self.file_options, names + extension.name)
+ for names, extension in iterate_extensions(self.fdesc, flatten):
+ name = create_name(names + extension.name)
+ field_options = get_nanopb_suboptions(extension, self.file_options, name)
if field_options.type != nanopb_pb2.FT_IGNORE:
- self.extensions.append(ExtensionField(names, extension, field_options))
+ self.extensions.append(ExtensionField(name, extension, field_options))
def add_dependency(self, other):
for enum in other.enums:
self.dependencies[str(enum.names)] = enum
+ enum.protofile = other
for msg in other.messages:
self.dependencies[str(msg.name)] = msg
+ msg.protofile = other
# Fix field default values where enum short names are used.
for enum in other.enums:
@@ -1512,6 +1578,10 @@ optparser.add_option("-Q", "--generated-include-format", dest="genformat",
optparser.add_option("-L", "--library-include-format", dest="libformat",
metavar="FORMAT", default='#include <%s>\n',
help="Set format string to use for including the nanopb pb.h header. [default: %default]")
+optparser.add_option("--strip-path", dest="strip_path", action="store_true", default=True,
+ help="Strip directory path from #included .pb.h file name [default: %default]")
+optparser.add_option("--no-strip-path", dest="strip_path", action="store_false",
+ help="Opposite of --strip-path")
optparser.add_option("-T", "--no-timestamp", dest="notimestamp", action="store_true", default=False,
help="Don't add timestamp to .pb.h and .pb.c preambles")
optparser.add_option("-q", "--quiet", dest="quiet", action="store_true", default=False,
@@ -1589,7 +1659,11 @@ def process_file(filename, fdesc, options, other_files = {}):
noext = os.path.splitext(filename)[0]
headername = noext + options.extension + options.header_extension
sourcename = noext + options.extension + options.source_extension
- headerbasename = os.path.basename(headername)
+
+ if options.strip_path:
+ headerbasename = os.path.basename(headername)
+ else:
+ headerbasename = headername
# List of .proto files that should not be included in the C header file
# even if they are mentioned in the source .proto.
diff --git a/generator/proto/nanopb.proto b/generator/proto/nanopb.proto
index 0c05a2b..95a57c4 100644
--- a/generator/proto/nanopb.proto
+++ b/generator/proto/nanopb.proto
@@ -27,6 +27,12 @@ enum IntSize {
IS_64 = 64;
}
+enum TypenameMangling {
+ M_NONE = 0; // Default, no typename mangling
+ M_STRIP_PACKAGE = 1; // Strip current package name
+ M_FLATTEN = 2; // Only use last path component
+}
+
// This is the inner options message, which basically defines options for
// a field. When it is used in message or file scope, it applies to all
// fields.
@@ -83,6 +89,9 @@ message NanoPBOptions {
// Generate repeated field with fixed count
optional bool fixed_count = 16 [default = false];
+
+ // Mangle long names
+ optional TypenameMangling mangle_names = 17 [default = M_NONE];
}
// Extensions to protoc 'Descriptor' type in order to define options
diff --git a/library.json b/library.json
index b070e54..0a6e5ba 100644
--- a/library.json
+++ b/library.json
@@ -1,6 +1,6 @@
{
"name": "Nanopb",
- "version": "0.3.9.1",
+ "version": "0.3.9.2",
"keywords": "protocol buffers, protobuf, google",
"description": "Nanopb is a plain-C implementation of Google's Protocol Buffers data format. It is targeted at 32 bit microcontrollers, but is also fit for other embedded systems with tight (2-10 kB ROM, <1 kB RAM) memory constraints.",
"repository": {
diff --git a/pb.h b/pb.h
index 52d24de..41c8cdc 100644
--- a/pb.h
+++ b/pb.h
@@ -46,7 +46,7 @@
/* Version of the nanopb library. Just in case you want to check it in
* your own program. */
-#define NANOPB_VERSION nanopb-0.3.9.1
+#define NANOPB_VERSION nanopb-0.3.9.2
/* Include all the system headers needed by nanopb. You will need the
* definitions of the following:
@@ -122,11 +122,6 @@
#define PB_STATIC_ASSERT_MSG(MSG, LINE, COUNTER) PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER)
#define PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER) pb_static_assertion_##MSG##LINE##COUNTER
#endif
-#ifndef STATIC_ASSERT
-#define STATIC_ASSERT PB_STATIC_ASSERT
-#define STATIC_ASSERT_MSG PB_STATIC_ASSERT_MSG
-#define STATIC_ASSERT_MSG_ PB_STATIC_ASSERT_MSG_
-#endif
#else
#define PB_STATIC_ASSERT(COND,MSG)
#endif
@@ -194,7 +189,7 @@ typedef uint_least8_t pb_type_t;
#define PB_HTYPE_MASK 0x30
/**** Field allocation types ****/
-
+
#define PB_ATYPE_STATIC 0x00
#define PB_ATYPE_POINTER 0x80
#define PB_ATYPE_CALLBACK 0x40
@@ -242,7 +237,7 @@ struct pb_field_s {
pb_ssize_t size_offset; /* Offset of array size or has-boolean, relative to data */
pb_size_t data_size; /* Data size in bytes for a single item */
pb_size_t array_size; /* Maximum number of entries in array */
-
+
/* Field definitions for submessage
* OR default value for all other non-array, non-callback types
* If null, then field will zeroed. */
@@ -308,8 +303,8 @@ struct pb_callback_s {
bool (*decode)(pb_istream_t *stream, const pb_field_t *field, void **arg);
bool (*encode)(pb_ostream_t *stream, const pb_field_t *field, void * const *arg);
} funcs;
-#endif
-
+#endif
+
/* Free arg for use by callback */
void *arg;
};
@@ -339,7 +334,7 @@ struct pb_extension_type_s {
*/
bool (*decode)(pb_istream_t *stream, pb_extension_t *extension,
uint32_t tag, pb_wire_type_t wire_type);
-
+
/* Called once after all regular fields have been encoded.
* If you have something to write, do so and return true.
* If you do not have anything to write, just return true.
@@ -347,7 +342,7 @@ struct pb_extension_type_s {
* Set to NULL for default handler.
*/
bool (*encode)(pb_ostream_t *stream, const pb_extension_t *extension);
-
+
/* Free field for use by the callback. */
const void *arg;
};
@@ -356,11 +351,11 @@ struct pb_extension_s {
/* Type describing the extension field. Usually you'll initialize
* this to a pointer to the automatically generated structure. */
const pb_extension_type_t *type;
-
+
/* Destination for the decoded data. This must match the datatype
* of the extension field. */
void *dest;
-
+
/* Pointer to the next extension handler, or NULL.
* If this extension does not match a field, the next handler is
* automatically called. */
@@ -467,7 +462,7 @@ struct pb_extension_s {
#define PB_SINGULAR_CALLBACK(tag, st, m, fd, ltype, ptr) \
{tag, PB_ATYPE_CALLBACK | PB_HTYPE_OPTIONAL | ltype, \
fd, 0, pb_membersize(st, m), 0, ptr}
-
+
#define PB_REPEATED_CALLBACK(tag, st, m, fd, ltype, ptr) \
{tag, PB_ATYPE_CALLBACK | PB_HTYPE_REPEATED | ltype, \
fd, 0, pb_membersize(st, m), 0, ptr}
diff --git a/pb_decode.c b/pb_decode.c
index 4b80e81..2c652f1 100644
--- a/pb_decode.c
+++ b/pb_decode.c
@@ -658,15 +658,20 @@ static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_
static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter)
{
pb_callback_t *pCallback = (pb_callback_t*)iter->pData;
-
#ifdef PB_OLD_CALLBACK_STYLE
- void *arg = pCallback->arg;
+ void *arg;
#else
- void **arg = &(pCallback->arg);
+ void **arg;
#endif
if (pCallback == NULL || pCallback->funcs.decode == NULL)
return pb_skip_field(stream, wire_type);
+
+#ifdef PB_OLD_CALLBACK_STYLE
+ arg = pCallback->arg;
+#else
+ arg = &(pCallback->arg);
+#endif
if (wire_type == PB_WT_STRING)
{
@@ -1153,7 +1158,7 @@ static void pb_release_single_field(const pb_field_iter_t *iter)
ext = ext->next;
}
}
- else if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE)
+ else if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE && PB_ATYPE(type) != PB_ATYPE_CALLBACK)
{
/* Release fields in submessage or submsg array */
void *pItem = iter->pData;
diff --git a/pb_encode.c b/pb_encode.c
index 089172c..d0129e6 100644
--- a/pb_encode.c
+++ b/pb_encode.c
@@ -232,7 +232,7 @@ static bool pb_check_proto3_default_value(const pb_field_t *field, const void *p
/* Oneof fields */
return *(const pb_size_t*)pSize == 0;
}
- else if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && field->size_offset)
+ else if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && field->size_offset != 0)
{
/* Proto2 optional fields inside proto3 submessage */
return *(const bool*)pSize == false;
diff --git a/tests/SConstruct b/tests/SConstruct
index f998024..d2dfeec 100644
--- a/tests/SConstruct
+++ b/tests/SConstruct
@@ -16,6 +16,14 @@ scons CC=clang CXX=clang++
import os
env = Environment(ENV = os.environ, tools = ['default', 'nanopb'])
+# Limit memory usage. This is to catch problems like issue #338
+try:
+ import resource
+ soft, hard = resource.getrlimit(resourse.RLIMIT_AS)
+ resource.setrlimit(resource.RLIMIT_AS, (100*1024*1024, hard))
+except:
+ pass
+
# Allow overriding the compiler with scons CC=???
if 'CC' in ARGUMENTS: env.Replace(CC = ARGUMENTS['CC'])
if 'CXX' in ARGUMENTS: env.Replace(CXX = ARGUMENTS['CXX'])
@@ -128,6 +136,12 @@ elif 'cl' in env['CC']:
# More strict checks on the nanopb core
env.Append(CORECFLAGS = '/W4')
+
+ # Disable warning about sizeof(union{}) construct that is used in
+ # message size macros, in e.g. multiple_files testcase. The C construct
+ # itself is valid, but quite rare, which causes Visual C++ to give a warning
+ # about it.
+ env.Append(CFLAGS = '/wd4116')
elif 'tcc' in env['CC']:
# Tiny C Compiler
env.Append(CFLAGS = '-Wall -Werror -g')
@@ -139,7 +153,7 @@ if 'clang' in env['CXX']:
elif 'g++' in env['CXX'] or 'gcc' in env['CXX']:
env.Append(CXXFLAGS = '-g -Wall -Werror -Wextra -Wno-missing-field-initializers')
elif 'cl' in env['CXX']:
- env.Append(CXXFLAGS = '/Zi /W2 /WX')
+ env.Append(CXXFLAGS = '/Zi /W2 /WX /wd4116')
# Now include the SConscript files from all subdirectories
import os.path
diff --git a/tests/mem_release/mem_release.c b/tests/mem_release/mem_release.c
index dc6f87d..6e06da5 100644
--- a/tests/mem_release/mem_release.c
+++ b/tests/mem_release/mem_release.c
@@ -177,9 +177,43 @@ static bool test_OneofMessage()
return true;
}
+static bool dummy_decode_cb(pb_istream_t *stream, const pb_field_t *field, void **arg)
+{
+ return false;
+}
+
+/* Garbage input */
+static bool test_Garbage()
+{
+ const uint8_t buffer[] = "I'm only happy when it rains";
+ const size_t msgsize = sizeof(buffer);
+
+ {
+ OneofMessage msg = OneofMessage_init_zero;
+ pb_istream_t stream = pb_istream_from_buffer(buffer, msgsize);
+ TEST(!pb_decode(&stream, OneofMessage_fields, &msg));
+ }
+
+ {
+ TestMessage msg = TestMessage_init_zero;
+ pb_istream_t stream = pb_istream_from_buffer(buffer, msgsize);
+ TEST(!pb_decode(&stream, TestMessage_fields, &msg));
+ }
+
+ {
+ RepeatedMessage msg = RepeatedMessage_init_zero;
+ pb_istream_t stream = pb_istream_from_buffer(buffer, msgsize);
+ msg.subs.arg = NULL;
+ msg.subs.funcs.decode = dummy_decode_cb;
+ TEST(!pb_decode(&stream, RepeatedMessage_fields, &msg));
+ }
+
+ return true;
+}
+
int main()
{
- if (test_TestMessage() && test_OneofMessage())
+ if (test_TestMessage() && test_OneofMessage() && test_Garbage())
return 0;
else
return 1;
diff --git a/tests/mem_release/mem_release.proto b/tests/mem_release/mem_release.proto
index 0816dc2..b0addbd 100644
--- a/tests/mem_release/mem_release.proto
+++ b/tests/mem_release/mem_release.proto
@@ -33,3 +33,9 @@ message OneofMessage
}
required int32 last = 4;
}
+
+message RepeatedMessage
+{
+ required int32 first = 1;
+ repeated SubMessage subs = 2;
+}
diff --git a/tests/multiple_files/subdir/multifile2.proto b/tests/multiple_files/subdir/multifile2.proto
index 847a929..99f094e 100644
--- a/tests/multiple_files/subdir/multifile2.proto
+++ b/tests/multiple_files/subdir/multifile2.proto
@@ -9,9 +9,14 @@ message Callback2Message {
required SubMessage submsg = 2;
}
+message SmallMessage {
+ required bool dummy = 1;
+}
+
message OneofMessage {
oneof msgs {
StaticMessage tstmsg = 1;
+ SmallMessage msg2 = 2;
}
}
diff --git a/tests/multiple_files/test_multiple_files.c b/tests/multiple_files/test_multiple_files.c
index 70a3e59..a4a600a 100644
--- a/tests/multiple_files/test_multiple_files.c
+++ b/tests/multiple_files/test_multiple_files.c
@@ -23,7 +23,8 @@ int main()
{
subdir_SubdirMessage foo = subdir_SubdirMessage_init_default;
TEST(foo.foo == 15);
- /* TEST(subdir_OneofMessage_size == 27); */ /* TODO: Issue #172 */
+ TEST(subdir_OneofMessage_size >= 27); /* Note: not perfectly accurate due to issue 172 */
+ TEST(subdir_OneofMessage_size <= 30);
}
return status;
diff --git a/tests/regression/issue_338/SConscript b/tests/regression/issue_338/SConscript
new file mode 100644
index 0000000..7b219b8
--- /dev/null
+++ b/tests/regression/issue_338/SConscript
@@ -0,0 +1,7 @@
+# Check that generator doesn't exceed memory limits
+
+Import('env')
+
+env.NanopbProto('bigvalue')
+
+
diff --git a/tests/regression/issue_338/bigvalue.proto b/tests/regression/issue_338/bigvalue.proto
new file mode 100644
index 0000000..3ff284a
--- /dev/null
+++ b/tests/regression/issue_338/bigvalue.proto
@@ -0,0 +1,204 @@
+syntax = "proto3";
+
+package enterprise;
+
+message BigData {
+ repeated BigEvent events = 1;
+}
+
+message BigEvent {
+ oneof event {
+ BigValue1 data1 = 1;
+ BigValue2 data2 = 2;
+ BigValue3 data3 = 3;
+ BigValue4 data4 = 4;
+ BigValue5 data5 = 5;
+ BigValue6 data6 = 6;
+ BigValue7 data7 = 7;
+ BigValue8 data8 = 8;
+ BigValue9 data9 = 9;
+ BigValue10 data10 = 10;
+ BigValue11 data11 = 11;
+ BigValue12 data12 = 12;
+ BigValue13 data13 = 13;
+ BigValue14 data14 = 14;
+ BigValue15 data15 = 15;
+ BigValue16 data16 = 16;
+ BigValue17 data17 = 17;
+ BigValue18 data18 = 18;
+ BigValue19 data19 = 19;
+ BigValue20 data20 = 20;
+ BigValue21 data21 = 21;
+ BigValue22 data22 = 22;
+ BigValue23 data23 = 23;
+ BigValue24 data24 = 24;
+ BigValue25 data25 = 25;
+ BigValue26 data26 = 26;
+ BigValue27 data27 = 27;
+ BigValue28 data28 = 28;
+ BigValue29 data29 = 29;
+ BigValue30 data30 = 30;
+ BigValue31 data31 = 31;
+ BigValue32 data32 = 32;
+ }
+}
+
+message BigValue1 {
+ int32 key = 1;
+ bytes value = 2;
+}
+
+message BigValue2 {
+ int32 key = 1;
+ bytes value = 2;
+}
+
+message BigValue3 {
+ int32 key = 1;
+ bytes value = 2;
+}
+
+message BigValue4 {
+ int32 key = 1;
+ bytes value = 2;
+}
+
+message BigValue5 {
+ int32 key = 1;
+ bytes value = 2;
+}
+
+message BigValue6 {
+ int32 key = 1;
+ bytes value = 2;
+}
+
+message BigValue7 {
+ int32 key = 1;
+ bytes value = 2;
+}
+
+message BigValue8 {
+ int32 key = 1;
+ bytes value = 2;
+}
+
+message BigValue9 {
+ int32 key = 1;
+ bytes value = 2;
+}
+
+message BigValue10 {
+ int32 key = 1;
+ bytes value = 2;
+}
+
+message BigValue11 {
+ int32 key = 1;
+ bytes value = 2;
+}
+
+message BigValue12 {
+ int32 key = 1;
+ bytes value = 2;
+}
+
+message BigValue13 {
+ int32 key = 1;
+ bytes value = 2;
+}
+
+message BigValue14 {
+ int32 key = 1;
+ bytes value = 2;
+}
+
+message BigValue15 {
+ int32 key = 1;
+ bytes value = 2;
+}
+
+message BigValue16 {
+ int32 key = 1;
+ bytes value = 2;
+}
+
+message BigValue17 {
+ int32 key = 1;
+ bytes value = 2;
+}
+
+message BigValue18 {
+ int32 key = 1;
+ bytes value = 2;
+}
+
+message BigValue19 {
+ int32 key = 1;
+ bytes value = 2;
+}
+
+message BigValue20 {
+ int32 key = 1;
+ bytes value = 2;
+}
+
+message BigValue21 {
+ int32 key = 1;
+ bytes value = 2;
+}
+
+message BigValue22 {
+ int32 key = 1;
+ bytes value = 2;
+}
+
+message BigValue23 {
+ int32 key = 1;
+ bytes value = 2;
+}
+
+message BigValue24 {
+ int32 key = 1;
+ bytes value = 2;
+}
+
+message BigValue25 {
+ int32 key = 1;
+ bytes value = 2;
+}
+
+message BigValue26 {
+ int32 key = 1;
+ bytes value = 2;
+}
+
+message BigValue27 {
+ int32 key = 1;
+ bytes value = 2;
+}
+
+message BigValue28 {
+ int32 key = 1;
+ bytes value = 2;
+}
+
+message BigValue29 {
+ int32 key = 1;
+ bytes value = 2;
+}
+
+message BigValue30 {
+ int32 key = 1;
+ bytes value = 2;
+}
+
+message BigValue31 {
+ int32 key = 1;
+ bytes value = 2;
+}
+
+message BigValue32 {
+ int32 key = 1;
+ bytes value = 2;
+}
diff --git a/tests/regression/issue_342/SConscript b/tests/regression/issue_342/SConscript
new file mode 100644
index 0000000..e15d022
--- /dev/null
+++ b/tests/regression/issue_342/SConscript
@@ -0,0 +1,21 @@
+# Regression test for #342:
+# Possible null-pointer dereference in pb_decode.c
+
+Import("env")
+
+# Define the compilation options
+opts = env.Clone()
+opts.Append(CPPDEFINES = {'PB_OLD_CALLBACK_STYLE': 1})
+
+# Build new version of core
+strict = opts.Clone()
+strict.Append(CFLAGS = strict['CORECFLAGS'])
+strict.Object("pb_decode_oldcallback.o", "$NANOPB/pb_decode.c")
+strict.Object("pb_encode_oldcallback.o", "$NANOPB/pb_encode.c")
+strict.Object("pb_common_oldcallback.o", "$NANOPB/pb_common.c")
+
+opts.NanopbProto("extensions")
+testprog = opts.Program(["test_extensions.c", "extensions.pb.c", "pb_encode_oldcallback.o", "pb_decode_oldcallback.o", "pb_common_oldcallback.o"])
+
+opts.RunTest(testprog)
+
diff --git a/tests/regression/issue_342/extensions.proto b/tests/regression/issue_342/extensions.proto
new file mode 100644
index 0000000..04b60ab
--- /dev/null
+++ b/tests/regression/issue_342/extensions.proto
@@ -0,0 +1,11 @@
+syntax = "proto2";
+
+message BaseMessage {
+ extensions 100 to 200;
+}
+
+extend BaseMessage {
+ optional string string_extension = 100;
+}
+
+
diff --git a/tests/regression/issue_342/test_extensions.c b/tests/regression/issue_342/test_extensions.c
new file mode 100644
index 0000000..1a48855
--- /dev/null
+++ b/tests/regression/issue_342/test_extensions.c
@@ -0,0 +1,52 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pb_encode.h>
+#include <pb_decode.h>
+#include "extensions.pb.h"
+#include "unittests.h"
+
+static bool write_string(pb_ostream_t *stream, const pb_field_t *field, const void *arg)
+{
+ return pb_encode_tag_for_field(stream, field) &&
+ pb_encode_string(stream, (const void*)"abc", 3);
+}
+
+int main(int argc, char **argv)
+{
+ int status = 0;
+ uint8_t buffer[64];
+ pb_size_t msglen = 0;
+
+ {
+ pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
+ pb_callback_t callback_def = {{0}};
+ pb_extension_t ext = {0};
+ BaseMessage msg = {0};
+
+ callback_def.funcs.encode = &write_string;
+ ext.type = &string_extension;
+ ext.dest = &callback_def;
+ msg.extensions = &ext;
+
+ TEST(pb_encode(&stream, BaseMessage_fields, &msg));
+
+ msglen = stream.bytes_written;
+ TEST(msglen > 3);
+ }
+
+ {
+ pb_istream_t stream = pb_istream_from_buffer(buffer, msglen);
+ pb_extension_t ext = {0};
+ BaseMessage msg = {0};
+
+ ext.type = &string_extension;
+ /* Note: ext.dest remains null to trigger buf #342 */
+ msg.extensions = &ext;
+
+ TEST(pb_decode(&stream, BaseMessage_fields, &msg));
+ }
+
+ return status;
+}
+
diff --git a/tests/typename_mangling/SConscript b/tests/typename_mangling/SConscript
new file mode 100644
index 0000000..219e6e2
--- /dev/null
+++ b/tests/typename_mangling/SConscript
@@ -0,0 +1,20 @@
+# Test mangle_names option
+
+Import('env')
+
+def set_mangling(type):
+ def command(target, source, env):
+ with open(str(source[0])) as src, open(str(target[0]), "w") as dst:
+ dst.write("* mangle_names:{}\n".format(type))
+ dst.write(src.read())
+ return command
+
+env.Command("strip_package.options", "with_package.options", set_mangling("M_STRIP_PACKAGE"))
+env.Command("strip_package.proto", "with_package.proto", Copy("$TARGET", "$SOURCE"))
+env.NanopbProto(["strip_package", "strip_package.options"])
+env.Program(["test_strip_package.c", "strip_package.pb.c"])
+
+env.Command("flatten.options", "with_package.options", set_mangling("M_FLATTEN"))
+env.Command("flatten.proto", "with_package.proto", Copy("$TARGET", "$SOURCE"))
+env.NanopbProto(["flatten", "flatten.options"])
+env.Program(["test_flatten.c", "flatten.pb.c"])
diff --git a/tests/typename_mangling/test_flatten.c b/tests/typename_mangling/test_flatten.c
new file mode 100644
index 0000000..dbc126e
--- /dev/null
+++ b/tests/typename_mangling/test_flatten.c
@@ -0,0 +1,22 @@
+/*
+ * Tests if expected names are generated when M_FLATTEN is used.
+ */
+
+#include <stdio.h>
+#include "unittests.h"
+#include "flatten.pb.h"
+
+int main()
+{
+ TopLevelMessage msg = {0};
+ NestedMessage nmsg = msg.nested;
+ NestedLevel2 nmsg2 = nmsg.nested;
+ NestedLevel3 nmsg3 = nmsg2.nested;
+ nmsg3.nothing = 42;
+
+ msg.short_if_none = ShortIfNone_IfNone_A;
+ msg.short_if_strip_package = ShortIfStripPackage_IfPackage_A;
+ msg.short_if_flatten = IfFlatten_A;
+
+ return nmsg3.nothing; /* this sets `nmsg3` as used, to prevent warning */
+}
diff --git a/tests/typename_mangling/test_strip_package.c b/tests/typename_mangling/test_strip_package.c
new file mode 100644
index 0000000..329de54
--- /dev/null
+++ b/tests/typename_mangling/test_strip_package.c
@@ -0,0 +1,19 @@
+/*
+ * Tests if expected names are generated when M_STRIP_PACKAGE is used.
+ */
+
+#include <stdio.h>
+#include "unittests.h"
+#include "strip_package.pb.h"
+
+int main()
+{
+ TopLevelMessage msg = {0};
+ TopLevelMessage_NestedMessage_NestedLevel2_NestedLevel3 nmsg = msg.nested.nested.nested;
+
+ msg.short_if_none = TopLevelMessage_ShortIfNone_IfNone_A;
+ msg.short_if_strip_package = TopLevelMessage_IfPackage_A;
+ msg.short_if_flatten = TopLevelMessage_ShortIfFlatten_IfFlatten_A;
+
+ return nmsg.nothing; /* marks nmsg as used */
+}
diff --git a/tests/typename_mangling/with_package.options b/tests/typename_mangling/with_package.options
new file mode 100644
index 0000000..115c94d
--- /dev/null
+++ b/tests/typename_mangling/with_package.options
@@ -0,0 +1,5 @@
+* long_names:true
+
+com.example.nanopb.TopLevelMessage.ShortIfNone long_names:false
+TopLevelMessage.ShortIfStripPackage long_names:false
+ShortIfFlatten long_names: false
diff --git a/tests/typename_mangling/with_package.proto b/tests/typename_mangling/with_package.proto
new file mode 100644
index 0000000..c5af6e1
--- /dev/null
+++ b/tests/typename_mangling/with_package.proto
@@ -0,0 +1,38 @@
+syntax = "proto2";
+
+package com.example.nanopb;
+
+message TopLevelMessage {
+ required uint32 base_field = 1;
+ required NestedMessage nested = 2;
+ optional ShortIfNone short_if_none = 3;
+ optional ShortIfStripPackage short_if_strip_package = 4;
+ optional ShortIfFlatten short_if_flatten = 5;
+
+ message NestedMessage {
+ required NestedLevel2 nested = 1;
+
+ message NestedLevel2 {
+ required NestedLevel3 nested = 1;
+
+ message NestedLevel3 {
+ required uint32 nothing = 1;
+ }
+ }
+ }
+
+ enum ShortIfNone {
+ IfNone_A = 1;
+ IfNone_B = 2;
+ }
+
+ enum ShortIfStripPackage {
+ IfPackage_A = 1;
+ IfPackage_B = 2;
+ }
+
+ enum ShortIfFlatten {
+ IfFlatten_A = 1;
+ IfFlatten_B = 2;
+ }
+}