From 6a213568c13bed113ea31c6d19af2390fe0ebc64 Mon Sep 17 00:00:00 2001 From: Petteri Aimonen Date: Thu, 31 May 2018 22:16:53 +0300 Subject: Add --no-strip-path command line option (#326) --- generator/nanopb_generator.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/generator/nanopb_generator.py b/generator/nanopb_generator.py index f77f8c4..6f38688 100755 --- a/generator/nanopb_generator.py +++ b/generator/nanopb_generator.py @@ -1512,6 +1512,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 +1593,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. -- cgit v1.2.3 From 66eba33227d75bec02b7163874d40989b7b919b2 Mon Sep 17 00:00:00 2001 From: Petteri Aimonen Date: Sat, 21 Jul 2018 11:58:47 +0300 Subject: Fix dates in changelog (#329) --- CHANGELOG.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index f7811a4..5a17be0 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,4 +1,4 @@ -nanopb-0.3.9.1 (2017-04-xx) +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) -- cgit v1.2.3 From 41a8c3b968ca4d703004d4c5faaf954dc2d78a8d Mon Sep 17 00:00:00 2001 From: matejcik Date: Mon, 27 Aug 2018 18:57:27 +0200 Subject: slight improvement to Names class to support new usecases --- generator/nanopb_generator.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/generator/nanopb_generator.py b/generator/nanopb_generator.py index 6f38688..e3f8dae 100755 --- a/generator/nanopb_generator.py +++ b/generator/nanopb_generator.py @@ -95,11 +95,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 +111,8 @@ class Names: def __add__(self, other): if isinstance(other, strtypes): return Names(self.parts + (other,)) + elif isinstance(other, Name): + return Names(self.parts + other.parts) elif isinstance(other, tuple): return Names(self.parts + other) else: -- cgit v1.2.3 From 37cdb0df67b2adc1c70b3b5e6bc26657f844c1dd Mon Sep 17 00:00:00 2001 From: matejcik Date: Mon, 27 Aug 2018 18:57:53 +0200 Subject: add typename mangling Three options for what to do with long type names: M_NONE - original, default. Do nothing special. M_STRIP_PACKAGE - Strip local package name. Useful when you want to use package names, but don't want to deal with `com_mycompany_supersoftware_proto_` prefixes on every symbol. Not useful when your packages cross-reference each other, because it only strips the _current_ package name, so references to other packages actually become invalid. M_FLATTEN - Always use only the last part of a dotted name. Useful when you have packages and/or deeply nested structs that don't actually have colliding names. Then you get shorter C symbols for no additional cost. Not useful when the names can collide. --- generator/nanopb_generator.py | 77 ++++++++++++++++++++++++++++++++----------- generator/proto/nanopb.proto | 9 +++++ 2 files changed, 66 insertions(+), 20 deletions(-) diff --git a/generator/nanopb_generator.py b/generator/nanopb_generator.py index e3f8dae..9420919 100755 --- a/generator/nanopb_generator.py +++ b/generator/nanopb_generator.py @@ -188,12 +188,12 @@ class Enum: '''desc is EnumDescriptorProto''' self.options = enum_options - self.names = names + desc.name + self.names = names 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 = [(desc.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 @@ -724,8 +724,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) @@ -1026,7 +1026,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 @@ -1035,19 +1035,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 @@ -1109,30 +1112,64 @@ 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: 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 -- cgit v1.2.3 From 8e60f24bda65a2c047c7f13dea1cc90475969944 Mon Sep 17 00:00:00 2001 From: matejcik Date: Tue, 28 Aug 2018 17:56:43 +0200 Subject: fix test failures --- generator/nanopb_generator.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/generator/nanopb_generator.py b/generator/nanopb_generator.py index 9420919..5f335ee 100755 --- a/generator/nanopb_generator.py +++ b/generator/nanopb_generator.py @@ -111,7 +111,7 @@ class Names: def __add__(self, other): if isinstance(other, strtypes): return Names(self.parts + (other,)) - elif isinstance(other, Name): + elif isinstance(other, Names): return Names(self.parts + other.parts) elif isinstance(other, tuple): return Names(self.parts + other) @@ -190,10 +190,13 @@ class Enum: self.options = enum_options self.names = names + # by definition, `names` include this enum's name + base_name = Names(names.parts[:-1]) + if enum_options.long_names: self.values = [(names + x.name, x.number) for x in desc.value] else: - self.values = [(desc.name + x.name, x.number) for x in desc.value] + 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 -- cgit v1.2.3 From 28b2ea151c0bbf4bfdebd678c3ef044c909ad7c4 Mon Sep 17 00:00:00 2001 From: matejcik Date: Fri, 31 Aug 2018 14:46:59 +0200 Subject: unit test for typename mangling feature --- tests/typename_mangling/SConscript | 20 +++++++++++++++ tests/typename_mangling/test_flatten.c | 22 ++++++++++++++++ tests/typename_mangling/test_strip_package.c | 19 ++++++++++++++ tests/typename_mangling/with_package.options | 5 ++++ tests/typename_mangling/with_package.proto | 38 ++++++++++++++++++++++++++++ 5 files changed, 104 insertions(+) create mode 100644 tests/typename_mangling/SConscript create mode 100644 tests/typename_mangling/test_flatten.c create mode 100644 tests/typename_mangling/test_strip_package.c create mode 100644 tests/typename_mangling/with_package.options create mode 100644 tests/typename_mangling/with_package.proto 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 +#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 +#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; + } +} -- cgit v1.2.3 From 0358e2312f11f9351516266050f868d5d6477f26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20M=C3=BCller?= Date: Sat, 1 Sep 2018 11:11:20 +0200 Subject: Pass protoc-gen-nanopb.bat to protoc when on Windows --- extra/FindNanopb.cmake | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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 -- cgit v1.2.3 From be12f7c22d8418df3a920a320e56de5063e18200 Mon Sep 17 00:00:00 2001 From: Petteri Aimonen Date: Thu, 13 Sep 2018 19:47:06 +0300 Subject: Add testcase for issue #338 --- tests/SConstruct | 8 ++ tests/multiple_files/subdir/multifile2.proto | 5 + tests/multiple_files/test_multiple_files.c | 3 +- tests/regression/issue_338/SConscript | 7 + tests/regression/issue_338/bigvalue.proto | 204 +++++++++++++++++++++++++++ 5 files changed, 226 insertions(+), 1 deletion(-) create mode 100644 tests/regression/issue_338/SConscript create mode 100644 tests/regression/issue_338/bigvalue.proto diff --git a/tests/SConstruct b/tests/SConstruct index f998024..06e4dba 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']) 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; +} -- cgit v1.2.3 From c946dd2a7b911b68e8ce99679751a8db8949cd31 Mon Sep 17 00:00:00 2001 From: Petteri Aimonen Date: Thu, 13 Sep 2018 20:04:17 +0300 Subject: Fix large generator memory usage with oneof fields (#338) Instead of 2**n ternary operator construct, uses a sizeof(union{}) construct with linear length increase. --- generator/nanopb_generator.py | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/generator/nanopb_generator.py b/generator/nanopb_generator.py index 5f335ee..cf05f54 100755 --- a/generator/nanopb_generator.py +++ b/generator/nanopb_generator.py @@ -853,24 +853,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) -- cgit v1.2.3 From 3db85603e7f094e09b31b234b694348f48deddf5 Mon Sep 17 00:00:00 2001 From: Petteri Aimonen Date: Thu, 13 Sep 2018 20:05:46 +0300 Subject: Don't generate useless _size values that cannot be resolved at runtime (#338) Previously the generator assumed that any submessage could be found in a different file. Now it knows that if the submessage is in current file, it won't be in a different file. --- generator/nanopb_generator.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/generator/nanopb_generator.py b/generator/nanopb_generator.py index cf05f54..787f33c 100755 --- a/generator/nanopb_generator.py +++ b/generator/nanopb_generator.py @@ -648,6 +648,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. @@ -1186,9 +1193,11 @@ class ProtoFile: 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: -- cgit v1.2.3 From cf99a1d5eb3209d632da23ba7a01749b3eb170a0 Mon Sep 17 00:00:00 2001 From: Petteri Aimonen Date: Wed, 3 Oct 2018 19:35:22 +0300 Subject: Add testcase for #342 --- tests/regression/issue_342/SConscript | 21 +++++++++++ tests/regression/issue_342/extensions.proto | 11 ++++++ tests/regression/issue_342/test_extensions.c | 52 ++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 tests/regression/issue_342/SConscript create mode 100644 tests/regression/issue_342/extensions.proto create mode 100644 tests/regression/issue_342/test_extensions.c 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..abfa915 --- /dev/null +++ b/tests/regression/issue_342/test_extensions.c @@ -0,0 +1,52 @@ +#include +#include +#include +#include +#include +#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; +} + -- cgit v1.2.3 From 7e68eef1f001461ff4c8351237e2c9e34a10d645 Mon Sep 17 00:00:00 2001 From: Petteri Aimonen Date: Wed, 3 Oct 2018 19:35:59 +0300 Subject: Fix possible null-pointer dereference in decode_callback_field (#342) This bug can only occur when all of the following apply: 1) Message contains extension fields and 2) the extension field is of callback type and 3) the pb_extension_t structure is defined, but the pointer to pb_callback_t is left as NULL. The correct behaviour in this case is that the field will be skipped. Further, for most compilers atleast and probably for all compilers, the bug will only occur if PB_OLD_CALLBACK_STYLE compilation option is specified. --- pb_decode.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/pb_decode.c b/pb_decode.c index 4b80e81..a792744 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) { -- cgit v1.2.3 From 77cf92aacdd20da9318063562aea3c9255e4427f Mon Sep 17 00:00:00 2001 From: Petteri Aimonen Date: Wed, 3 Oct 2018 20:42:33 +0300 Subject: Fix compiler warning --- tests/regression/issue_342/test_extensions.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression/issue_342/test_extensions.c b/tests/regression/issue_342/test_extensions.c index abfa915..1a48855 100644 --- a/tests/regression/issue_342/test_extensions.c +++ b/tests/regression/issue_342/test_extensions.c @@ -20,7 +20,7 @@ int main(int argc, char **argv) { pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); - pb_callback_t callback_def = {0}; + pb_callback_t callback_def = {{0}}; pb_extension_t ext = {0}; BaseMessage msg = {0}; -- cgit v1.2.3 From 7369de399c6b1f7ad31d8f3b56ea34493190b11a Mon Sep 17 00:00:00 2001 From: Jari Vetoniemi Date: Thu, 11 Oct 2018 09:57:10 +0300 Subject: Test mem_release with garbage input --- tests/mem_release/mem_release.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/tests/mem_release/mem_release.c b/tests/mem_release/mem_release.c index dc6f87d..eb62cad 100644 --- a/tests/mem_release/mem_release.c +++ b/tests/mem_release/mem_release.c @@ -177,9 +177,30 @@ static bool test_OneofMessage() return true; } +/* 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)); + } + + return true; +} + int main() { - if (test_TestMessage() && test_OneofMessage()) + if (test_TestMessage() && test_OneofMessage() && test_Garbage()) return 0; else return 1; -- cgit v1.2.3 From b84b723320c9e55ee26a52566cbe3a92fdf41eca Mon Sep 17 00:00:00 2001 From: Jari Vetoniemi Date: Thu, 11 Oct 2018 09:52:23 +0300 Subject: Don't release fields of a callback If submessage array is a callback, there's nothing to release. --- pb_decode.c | 2 +- tests/mem_release/mem_release.c | 13 +++++++++++++ tests/mem_release/mem_release.proto | 6 ++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/pb_decode.c b/pb_decode.c index a792744..2c652f1 100644 --- a/pb_decode.c +++ b/pb_decode.c @@ -1158,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/tests/mem_release/mem_release.c b/tests/mem_release/mem_release.c index eb62cad..6e06da5 100644 --- a/tests/mem_release/mem_release.c +++ b/tests/mem_release/mem_release.c @@ -177,6 +177,11 @@ 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() { @@ -195,6 +200,14 @@ static bool test_Garbage() 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; } 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; +} -- cgit v1.2.3 From fb6570b3ce4fc4c9e0e3a1e746c4e004242a1f9b Mon Sep 17 00:00:00 2001 From: Petteri Aimonen Date: Thu, 11 Oct 2018 10:39:31 +0300 Subject: Update changelog & authors --- AUTHORS.txt | 5 ++++- CHANGELOG.txt | 9 +++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/AUTHORS.txt b/AUTHORS.txt index 0034abf..6c17124 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -42,4 +42,7 @@ Edward Z. Yang Robbie Shade Andrew Ballinger Hamina, Juha-Pekka - +Jason Bishop +matejcik +Tobias Müller +Jari Vetoniemi diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 5a17be0..3bf097e 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,12 @@ +nanopb-0.3.9.2 (2018-10-xx) + 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) + Add --no-strip-path command line option (#326) + Option for flattening nested protobuf names (#333) + Fix dates in changelog (#329) + 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) -- cgit v1.2.3 From 302792f207486a15a745ed74c6809c71902c97c1 Mon Sep 17 00:00:00 2001 From: Petteri Aimonen Date: Thu, 11 Oct 2018 11:15:22 +0300 Subject: Fix test failure on Windows --- tests/SConstruct | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/SConstruct b/tests/SConstruct index 06e4dba..dc43966 100644 --- a/tests/SConstruct +++ b/tests/SConstruct @@ -149,6 +149,12 @@ elif 'g++' in env['CXX'] or 'gcc' in env['CXX']: elif 'cl' in env['CXX']: env.Append(CXXFLAGS = '/Zi /W2 /WX') + # 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(CXXFLAGS = '/wd4116') + # Now include the SConscript files from all subdirectories import os.path env['VARIANT_DIR'] = 'build' -- cgit v1.2.3 From aee518b2b23922c52dfc9d6cd05eef31ed4af88a Mon Sep 17 00:00:00 2001 From: Petteri Aimonen Date: Thu, 11 Oct 2018 11:51:45 +0300 Subject: Further test fail fix for Windows --- tests/SConstruct | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/SConstruct b/tests/SConstruct index dc43966..d2dfeec 100644 --- a/tests/SConstruct +++ b/tests/SConstruct @@ -136,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') @@ -147,13 +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') - - # 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(CXXFLAGS = '/wd4116') + env.Append(CXXFLAGS = '/Zi /W2 /WX /wd4116') # Now include the SConscript files from all subdirectories import os.path -- cgit v1.2.3 From 1023743d1e07e2db038d69097b9cdde0ca784abf Mon Sep 17 00:00:00 2001 From: Gabriel Staples Date: Wed, 17 Oct 2018 13:34:54 -0700 Subject: Update README.md Add minor formatting marks to make more readable. Ex: `` for `code` and ** for *italics*. --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) 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 -- cgit v1.2.3 From 2fe9068437f29e9eff80ca387b0faa3b4f77e72a Mon Sep 17 00:00:00 2001 From: Amarnath Date: Sat, 20 Oct 2018 18:48:22 +0530 Subject: Made some changes for Error Output. Sometimes python protobuf version can't be found out by the above listed command. So added one more command to find python protobuf version which utilises pip freeze command. --- generator/nanopb_generator.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/generator/nanopb_generator.py b/generator/nanopb_generator.py index 787f33c..66114f8 100755 --- a/generator/nanopb_generator.py +++ b/generator/nanopb_generator.py @@ -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 -- cgit v1.2.3 From 4c7093266ebc794853e8ce71885a950ce3f0daee Mon Sep 17 00:00:00 2001 From: Michal Rostecki Date: Wed, 24 Oct 2018 13:51:28 +0200 Subject: cmake: Allow to build a shared library Introduce options BUILD_SHARED_LIBS and BUILD_STATIC_LIBS to allow building both types of libraries. By default only BUILD_STATIC_LIBS is enabled. --- CMakeLists.txt | 55 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index deb9eec..56eed64 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,9 +3,13 @@ cmake_minimum_required(VERSION 2.8.12) project(nanopb C) set(nanopb_VERSION_STRING nanopb-0.4.0-dev) +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) @@ -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 - $ - ) + 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 + $ + ) + 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 + $ + ) + 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::) -- cgit v1.2.3 From fa16f72f4354eba27c8e182a033608298b8e60e5 Mon Sep 17 00:00:00 2001 From: Michal Rostecki Date: Wed, 24 Oct 2018 14:27:52 +0200 Subject: cmake: Include CMAKE_INSTALL_LIBDIR in CMAKE_INSTALL_CMAKEDIR If user defines non-standard directory in CMAKE_INSTALL_LIBDIR option (i.e. /usr/lib64), then CMAKE_INSTALL_CMAKEDIR should use it as a prefix. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index deb9eec..fd4ade4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,7 +31,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) -- cgit v1.2.3 From 6a0df68944b90995406b7d5ba8262ecfac76e022 Mon Sep 17 00:00:00 2001 From: Pei Wang Date: Thu, 1 Nov 2018 13:03:23 -0700 Subject: Clarify the usage of callback fields inside oneof sections in the docs --- docs/concepts.rst | 5 +++++ 1 file changed, 5 insertions(+) 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 -- cgit v1.2.3 From 6655ea52ee0449b562c06b5f2e90a8fac7230fe4 Mon Sep 17 00:00:00 2001 From: Petteri Aimonen Date: Fri, 2 Nov 2018 09:09:30 +0200 Subject: Fix splint test error (#359) --- pb_encode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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; -- cgit v1.2.3 From 9426c11840c979dd46d917827cecfdfbd36cf739 Mon Sep 17 00:00:00 2001 From: Petteri Aimonen Date: Sun, 4 Nov 2018 20:02:29 +0200 Subject: Update changelog & authors --- AUTHORS.txt | 4 ++++ CHANGELOG.txt | 7 +++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/AUTHORS.txt b/AUTHORS.txt index 6c17124..2d63fed 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -46,3 +46,7 @@ Jason Bishop matejcik Tobias Müller Jari Vetoniemi +Gabriel Staples +Amarnath +Michal Rostecki +Pei Wang diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 3bf097e..559e941 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,11 +1,14 @@ -nanopb-0.3.9.2 (2018-10-xx) +nanopb-0.3.9.2 (2018-11-xx) 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) - Fix dates in changelog (#329) + 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) -- cgit v1.2.3 From 3626b5c40e2457629ac60a563dde523be7c10bb4 Mon Sep 17 00:00:00 2001 From: Petteri Aimonen Date: Sat, 10 Nov 2018 13:10:04 +0200 Subject: Publishing nanopb-0.3.9.2 --- CHANGELOG.txt | 2 +- CMakeLists.txt | 2 +- generator/nanopb_generator.py | 2 +- library.json | 2 +- pb.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 559e941..4c6ab7f 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,4 +1,4 @@ -nanopb-0.3.9.2 (2018-11-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) diff --git a/CMakeLists.txt b/CMakeLists.txt index db0903d..642c68d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 2.8.12) project(nanopb C) -set(nanopb_VERSION_STRING nanopb-0.4.0-dev) +set(nanopb_VERSION_STRING nanopb-0.3.9.2) set(nanopb_SOVERSION 0) string(REPLACE "nanopb-" "" nanopb_VERSION ${nanopb_VERSION_STRING}) diff --git a/generator/nanopb_generator.py b/generator/nanopb_generator.py index 66114f8..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.4.0-dev" +nanopb_version = "nanopb-0.3.9.2" import sys import re diff --git a/library.json b/library.json index 0a3e17c..0a6e5ba 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "Nanopb", - "version": "0.3.9", + "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 a0dd323..a10f012 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.4.0-dev +#define NANOPB_VERSION nanopb-0.3.9.2 /* Include all the system headers needed by nanopb. You will need the * definitions of the following: -- cgit v1.2.3