Import of the watch repository from Pebble

This commit is contained in:
Matthieu Jeanson 2024-12-12 16:43:03 -08:00 committed by Katharine Berry
commit 3b92768480
10334 changed files with 2564465 additions and 0 deletions

View file

@ -0,0 +1,13 @@
# Regression test for security issue GHSA-gcx3-7m76-287p
# "Out-of-memory condition on repeated field can result in invalid free()"
Import("malloc_env")
malloc_env.NanopbProto("test")
test = malloc_env.Program(["test.c", "test.pb.c",
"$COMMON/pb_decode_with_malloc.o",
"$COMMON/pb_common_with_malloc.o",
"$COMMON/malloc_wrappers.o"])
malloc_env.RunTest([test, 'test_input.pb'])

View file

@ -0,0 +1,39 @@
#include <pb_decode.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "test_helpers.h"
#include "test.pb.h"
bool stream_callback(pb_istream_t *stream, uint8_t *buf, size_t count)
{
FILE *file = (FILE*)stream->state;
size_t len = fread(buf, 1, count, file);
if (len == count)
{
return true;
}
else
{
stream->bytes_left = 0;
return false;
}
}
int main()
{
pb_istream_t stream = {&stream_callback, NULL, SIZE_MAX};
MyMessage msg = MyMessage_init_default;
bool status;
stream.state = stdin;
SET_BINARY_MODE(stdin);
set_max_alloc_bytes(512);
status = pb_decode(&stream, MyMessage_fields, &msg);
assert(!status);
assert(strcmp(stream.errmsg, "realloc failed") == 0);
return 0;
}

View file

@ -0,0 +1,7 @@
syntax = "proto2";
import "nanopb.proto";
message MyMessage {
repeated string values = 1 [(nanopb).type = FT_POINTER];
}

View file

@ -0,0 +1,12 @@
# Regression test for Issue 118: Short enum names in imported proto files are not honoured
Import("env")
env = env.Clone()
env.Append(PROTOCPATH = "#regression/issue_118")
env.NanopbProto("enumdef")
env.Object('enumdef.pb.c')
env.NanopbProto(["enumuse", "enumdef.proto"])
env.Object('enumuse.pb.c')

View file

@ -0,0 +1,8 @@
syntax = "proto2";
import 'nanopb.proto';
enum MyEnum {
option (nanopb_enumopt).long_names = false;
FOOBAR = 1;
}

View file

@ -0,0 +1,7 @@
syntax = "proto2";
import 'enumdef.proto';
message MyMessage {
required MyEnum myenum = 1 [default = FOOBAR];
}

View file

@ -0,0 +1,9 @@
# Regression test for Issue 125: Wrong identifier name for extension fields
Import("env")
env.NanopbProto(["extensionbug", "extensionbug.options"])
env.Object('extensionbug.pb.c')
env.Match(['extensionbug.pb.h', 'extensionbug.expected'])

View file

@ -0,0 +1,3 @@
pb_extension_type_t Message2_extras
uint32_t field2

View file

@ -0,0 +1,4 @@
* type:FT_IGNORE
Message2.extras type:FT_STATIC
Message2.field2 type:FT_STATIC

View file

@ -0,0 +1,18 @@
syntax = "proto2";
message Message1
{
optional uint32 fieldA = 1;
extensions 30 to max;
}
message Message2
{
extend Message1
{
optional Message2 extras = 30;
}
optional uint32 field1 = 1;
optional uint32 field2 = 2;
}

View file

@ -0,0 +1,8 @@
# Regression test for issue 141: wrong encoded size #define for oneof messages
Import("env")
env.NanopbProto("testproto")
env.Object('testproto.pb.c')
env.Match(['testproto.pb.h', 'testproto.expected'])

View file

@ -0,0 +1,7 @@
define SubMessage_size \s* 88
define OneOfMessage_size \s* 113
define topMessage_size \s* 70
define MyMessage1_size \s* 46
define MyMessage2_size \s* 8
define MyMessage3_size \s* 5
define MyMessage4_size \s* 18

View file

@ -0,0 +1,52 @@
syntax = "proto2";
import 'nanopb.proto';
message SubMessage
{
repeated int32 array = 1 [(nanopb).max_count = 8];
}
message OneOfMessage
{
required int32 prefix = 1;
oneof values
{
int32 first = 5;
string second = 6 [(nanopb).max_length = 8];
SubMessage third = 7;
}
required int32 suffix = 99;
}
message topMessage {
required int32 start = 1;
oneof msg {
MyMessage1 msg1 = 2;
MyMessage2 msg2 = 3;
}
required int32 end = 4;
}
message MyMessage1 {
required uint32 n1 = 1;
required uint32 n2 = 2;
required string s = 3 [(nanopb).max_length = 32];
}
message MyMessage2 {
required uint32 num = 1;
required bool b = 2;
}
message MyMessage3 {
required bool bbb = 1;
required string ss = 2 [(nanopb).max_length = 1];
}
message MyMessage4 {
required bool bbbb = 1;
required string sss = 2 [(nanopb).max_length = 2];
required uint32 num = 3;
required uint32 num2 = 4;
}

View file

@ -0,0 +1,9 @@
# Regression test for Issue 145: Allow /* */ and // comments in .options files
Import("env")
env.NanopbProto(["comments", "comments.options"])
env.Object('comments.pb.c')
env.Match(['comments.pb.h', 'comments.expected'])

View file

@ -0,0 +1,3 @@
char foo\[5\];
char bar\[16\];

View file

@ -0,0 +1,6 @@
/* Block comment */
# Line comment
// Line comment
DummyMessage.foo /* Block comment */ max_size:5
DummyMessage.bar max_size:16 # Line comment ###

View file

@ -0,0 +1,7 @@
syntax = "proto2";
message DummyMessage {
required string foo = 1;
required string bar = 2;
}

View file

@ -0,0 +1,13 @@
# Verify that the maximum encoded size is calculated properly
# for enums.
Import('env')
env.NanopbProto('enums')
p = env.Program(["enum_encoded_size.c",
"enums.pb.c",
"$COMMON/pb_encode.o",
"$COMMON/pb_common.o"])
env.RunTest(p)

View file

@ -0,0 +1,43 @@
#include <stdio.h>
#include <string.h>
#include <pb_encode.h>
#include "unittests.h"
#include "enums.pb.h"
int main()
{
int status = 0;
uint8_t buf[256];
SignedMsg msg1;
UnsignedMsg msg2;
pb_ostream_t s;
{
COMMENT("Test negative value of signed enum");
/* Negative value should take up the maximum size */
msg1.value = SignedEnum_SE_MIN;
s = pb_ostream_from_buffer(buf, sizeof(buf));
TEST(pb_encode(&s, SignedMsg_fields, &msg1));
TEST(s.bytes_written == SignedMsg_size);
COMMENT("Test positive value of signed enum");
/* Positive value should be smaller */
msg1.value = SignedEnum_SE_MAX;
s = pb_ostream_from_buffer(buf, sizeof(buf));
TEST(pb_encode(&s, SignedMsg_fields, &msg1));
TEST(s.bytes_written < SignedMsg_size);
}
{
COMMENT("Test positive value of unsigned enum");
/* This should take up the maximum size */
msg2.value = UnsignedEnum_UE_MAX;
s = pb_ostream_from_buffer(buf, sizeof(buf));
TEST(pb_encode(&s, UnsignedMsg_fields, &msg2));
TEST(s.bytes_written == UnsignedMsg_size);
}
return status;
}

View file

@ -0,0 +1,18 @@
syntax = "proto2";
enum SignedEnum {
SE_MIN = -1;
SE_MAX = 255;
}
enum UnsignedEnum {
UE_MAX = 65536;
}
message SignedMsg {
required SignedEnum value = 1;
}
message UnsignedMsg {
required UnsignedEnum value = 1;
}

View file

@ -0,0 +1,18 @@
# Verify that _size define is generated for messages that have
# includes from another directory.
Import('env')
incpath = env.Clone()
incpath.Append(PROTOCPATH="#regression/issue_172/submessage")
incpath.Append(CPPPATH="$BUILD/regression/issue_172/submessage")
incpath.Append(CPPPATH="$BUILD/regression/issue_172/")
incpath.NanopbProto('test')
incpath.NanopbProto(['submessage/submessage', 'submessage/submessage.options'])
p = incpath.Program(["msg_size.c",
"test.pb.c",
"submessage/submessage.pb.c",
'$COMMON/pb_common.o'])

View file

@ -0,0 +1,9 @@
#include "test.pb.h"
PB_STATIC_ASSERT(testmessage_size >= 1+1+1+1+16, TESTMESSAGE_SIZE_IS_WRONG)
int main()
{
return 0;
}

View file

@ -0,0 +1 @@
submessage.data max_size: 16

View file

@ -0,0 +1,4 @@
syntax = "proto2";
message submessage {
required bytes data = 1;
}

View file

@ -0,0 +1,6 @@
syntax = "proto2";
import "submessage.proto";
message testmessage {
optional submessage sub = 1;
}

View file

@ -0,0 +1,6 @@
# Regression test for issue with Enums inside OneOf.
Import('env')
env.NanopbProto('oneof')

View file

@ -0,0 +1,29 @@
syntax = "proto2";
message MessageOne
{
required uint32 one = 1;
required uint32 two = 2;
required uint32 three = 3;
required int32 four = 4;
}
enum EnumTwo
{
SOME_ENUM_1 = 1;
SOME_ENUM_2 = 5;
SOME_ENUM_3 = 6;
SOME_ENUM_4 = 9;
SOME_ENUM_5 = 10;
SOME_ENUM_6 = 12;
SOME_ENUM_7 = 39;
SOME_ENUM_8 = 401;
}
message OneofMessage
{
oneof payload {
MessageOne message = 1;
EnumTwo enum = 2;
}
}

View file

@ -0,0 +1,10 @@
# Regression test for Issue 195: Message size not calculated if a submessage includes
# bytes. Basically a non-working #define being generated.
Import("env")
env.NanopbProto(["test"])
env.Object('test.pb.c')
env.Match(['test.pb.h', 'test.expected'])

View file

@ -0,0 +1 @@
/\* TestMessage_size depends

View file

@ -0,0 +1,8 @@
message TestMessage {
required uint32 id = 1;
required bytes payload = 2;
}
message EncapsulatedMessage {
required uint32 id = 1;
required TestMessage test = 2;
}

View file

@ -0,0 +1,10 @@
# Regression test for issue with multiple files generated at once
Import('env')
env = env.Clone()
env.Replace(NANOPBFLAGS = "--strip-path")
env.Command(['file1.pb.c', 'file1.pb.h', 'file2.pb.c', 'file2.pb.h'], ['file1.proto', 'file2.proto'],
env['NANOPB_PROTO_CMD'])
env.Object('file1.pb.c')
env.Object('file2.pb.c')

View file

@ -0,0 +1,10 @@
syntax = "proto2";
message SubMessage1 {
required int32 foo = 1;
}
message Message1 {
required SubMessage1 bar = 1;
}

View file

@ -0,0 +1,10 @@
syntax = "proto2";
message SubMessage2 {
required int32 foo = 1;
}
message Message2 {
required SubMessage2 bar = 1;
}

View file

@ -0,0 +1,14 @@
# Check that pb_release() correctly handles corrupted size fields of
# static arrays.
Import('env', 'malloc_env')
env.NanopbProto('size_corruption')
p = malloc_env.Program(["size_corruption.c",
"size_corruption.pb.c",
"$COMMON/pb_decode_with_malloc.o",
"$COMMON/pb_common_with_malloc.o",
"$COMMON/malloc_wrappers.o"])
env.RunTest(p)

View file

@ -0,0 +1,12 @@
#include "size_corruption.pb.h"
#include <pb_decode.h>
int main()
{
MainMessage msg = MainMessage_init_zero;
msg.bar_count = (pb_size_t)-1;
pb_release(MainMessage_fields, &msg);
return 0;
}

View file

@ -0,0 +1,11 @@
syntax = "proto2";
import 'nanopb.proto';
message SubMessage {
repeated int32 foo = 1 [(nanopb).type = FT_POINTER];
}
message MainMessage {
repeated SubMessage bar = 1 [(nanopb).max_count = 5];
}

View file

@ -0,0 +1,14 @@
# Regression test for Issue 227:Using proto3 type fields can cause unaligned access
# NOTE: This test will only detect problems when run with clang sanitizer (which
# is done regularly by a jenkins run).
Import('env')
env.NanopbProto('unaligned_uint64')
p = env.Program(["unaligned_uint64.c",
"unaligned_uint64.pb.c",
"$COMMON/pb_encode.o",
"$COMMON/pb_common.o"])
env.RunTest(p)

View file

@ -0,0 +1,14 @@
#include "unaligned_uint64.pb.h"
#include <pb_encode.h>
int main()
{
uint8_t buf[128];
pb_ostream_t stream = pb_ostream_from_buffer(buf, sizeof(buf));
MainMessage msg = MainMessage_init_zero;
msg.bar[0] = 'A';
pb_encode(&stream, MainMessage_fields, &msg);
return 0;
}

View file

@ -0,0 +1,8 @@
syntax = "proto3";
import 'nanopb.proto';
message MainMessage {
string foo = 1 [(nanopb).max_size = 3];
string bar = 2 [(nanopb).max_size = 8];
}

View file

@ -0,0 +1,13 @@
# Regression test for Issue 229: problem encoding message that has
# multiple oneof fields
Import('env')
env.NanopbProto('multiple_oneof')
p = env.Program(["multiple_oneof.c",
"multiple_oneof.pb.c",
"$COMMON/pb_decode.o",
"$COMMON/pb_encode.o",
"$COMMON/pb_common.o"])
env.RunTest(p)

View file

@ -0,0 +1,35 @@
#include "multiple_oneof.pb.h"
#include <unittests.h>
#include <pb_encode.h>
#include <pb_decode.h>
int main()
{
int status = 0;
uint8_t buf[128];
size_t msglen;
{
pb_ostream_t stream = pb_ostream_from_buffer(buf, sizeof(buf));
MainMessage msg = MainMessage_init_zero;
msg.which_oneof1 = MainMessage_oneof1_uint32_tag;
msg.oneof1.oneof1_uint32 = 1234;
msg.which_oneof2 = MainMessage_oneof2_uint32_tag;
msg.oneof2.oneof2_uint32 = 5678;
TEST(pb_encode(&stream, MainMessage_fields, &msg));
msglen = stream.bytes_written;
}
{
pb_istream_t stream = pb_istream_from_buffer(buf, msglen);
MainMessage msg = MainMessage_init_zero;
TEST(pb_decode(&stream, MainMessage_fields, &msg));
TEST(msg.which_oneof1 == MainMessage_oneof1_uint32_tag);
TEST(msg.oneof1.oneof1_uint32 == 1234);
TEST(msg.which_oneof2 == MainMessage_oneof2_uint32_tag);
TEST(msg.oneof2.oneof2_uint32 == 5678);
}
return status;
}

View file

@ -0,0 +1,11 @@
syntax = "proto2";
message MainMessage {
oneof oneof1 {
uint32 oneof1_uint32 = 1;
}
oneof oneof2 {
uint32 oneof2_uint32 = 2;
}
}

View file

@ -0,0 +1,13 @@
# Regression test for Issue 242: pb_encode does not encode tag for
# extension fields that is all zeros
Import('env')
env.NanopbProto('zero_value')
p = env.Program(["zero_value.c",
"zero_value.pb.c",
"$COMMON/pb_decode.o",
"$COMMON/pb_encode.o",
"$COMMON/pb_common.o"])
env.RunTest(p)

View file

@ -0,0 +1,51 @@
#include <unittests.h>
#include <pb_encode.h>
#include <pb_decode.h>
#include <string.h>
#include "zero_value.pb.h"
int main()
{
int status = 0;
COMMENT("Test extension fields with zero values");
{
uint8_t buffer[256] = {0};
pb_ostream_t ostream;
int32_t value = 0;
Extendable source = {0};
pb_extension_t source_ext = {0};
source_ext.type = &opt_int32;
source_ext.dest = &value;
source.extensions = &source_ext;
ostream = pb_ostream_from_buffer(buffer, sizeof(buffer));
TEST(pb_encode(&ostream, Extendable_fields, &source));
TEST(ostream.bytes_written == 2);
TEST(memcmp(buffer, "\x58\x00", 2) == 0);
}
/* Note: There never was a bug here, but this check is included
* in the regression test because the logic is closely related.
*/
COMMENT("Test pointer fields with zero values");
{
uint8_t buffer[256] = {0};
pb_ostream_t ostream;
int32_t value = 0;
PointerMessage source = {0};
source.opt_int32 = &value;
ostream = pb_ostream_from_buffer(buffer, sizeof(buffer));
TEST(pb_encode(&ostream, PointerMessage_fields, &source));
TEST(ostream.bytes_written == 2);
TEST(memcmp(buffer, "\x58\x00", 2) == 0);
}
return status;
}

View file

@ -0,0 +1,15 @@
syntax = "proto2";
import "nanopb.proto";
message Extendable {
extensions 10 to 100;
}
extend Extendable {
optional int32 opt_int32 = 11;
}
message PointerMessage {
optional int32 opt_int32 = 11 [(nanopb).type = FT_POINTER];
}

View file

@ -0,0 +1,14 @@
# Test that pb_check_proto3_default_value() correctly skips padding
# bytes in submessage structures.
Import("env")
env.NanopbProto("padding")
p = env.Program(["padding.c",
"padding.pb.c",
"$COMMON/pb_encode.o",
"$COMMON/pb_common.o"])
env.RunTest(p)

View file

@ -0,0 +1,32 @@
#include <pb_encode.h>
#include <unittests.h>
#include <string.h>
#include "padding.pb.h"
int main()
{
int status = 0;
TestMessage msg;
/* Set padding bytes to garbage */
memset(&msg, 0xAA, sizeof(msg));
/* Set all meaningful fields to 0 */
msg.submsg.boolfield = false;
msg.submsg.intfield = 0;
/* Test encoding */
{
pb_byte_t buf[128] = {0};
pb_ostream_t stream = pb_ostream_from_buffer(buf, sizeof(buf));
TEST(pb_encode(&stream, TestMessage_fields, &msg));
/* Because all fields have zero values, proto3 encoder
* shouldn't write out anything. */
TEST(stream.bytes_written == 0);
}
return status;
}

View file

@ -0,0 +1,12 @@
syntax = "proto3";
import "nanopb.proto";
message SubMessage {
bool boolfield = 1;
int64 intfield = 2;
}
message TestMessage {
SubMessage submsg = 1 [(nanopb).proto3_singular_msgs = true];
}

View file

@ -0,0 +1,12 @@
# Regression test for Issue 249: proto3 mode pb_decode() corrupts callback fields
Import('env')
env.NanopbProto('test')
p = env.Program(["test.c",
"test.pb.c",
"$COMMON/pb_decode.o",
"$COMMON/pb_encode.o",
"$COMMON/pb_common.o"])
env.RunTest(p)

View file

@ -0,0 +1,59 @@
#include "test.pb.h"
#include <unittests.h>
#include <pb_encode.h>
#include <pb_decode.h>
static bool write_array(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
{
int i;
for (i = 0; i < 5; i++)
{
if (!pb_encode_tag_for_field(stream, field))
return false;
if (!pb_encode_varint(stream, 1000 + i))
return false;
}
return true;
}
static bool read_array(pb_istream_t *stream, const pb_field_t *field, void **arg)
{
uint32_t i;
int *sum = *arg;
if (!pb_decode_varint32(stream, &i))
return false;
*sum += i;
return true;
}
int main()
{
int status = 0;
pb_byte_t buf[128] = {0};
pb_size_t msglen;
{
MainMessage msg = MainMessage_init_zero;
pb_ostream_t stream = pb_ostream_from_buffer(buf, sizeof(buf));
msg.submsg.foo.funcs.encode = &write_array;
TEST(pb_encode(&stream, MainMessage_fields, &msg));
msglen = stream.bytes_written;
}
{
MainMessage msg = MainMessage_init_zero;
pb_istream_t stream = pb_istream_from_buffer(buf, msglen);
int sum = 0;
msg.submsg.foo.funcs.decode = &read_array;
msg.submsg.foo.arg = &sum;
TEST(pb_decode(&stream, MainMessage_fields, &msg));
TEST(sum == 1000 + 1001 + 1002 + 1003 + 1004);
}
return status;
}

View file

@ -0,0 +1,11 @@
syntax = "proto3";
import "nanopb.proto";
message SubMessage {
repeated int32 foo = 1;
}
message MainMessage {
SubMessage submsg = 1 [(nanopb).proto3_singular_msgs = true];
}

View file

@ -0,0 +1,15 @@
# Regression test for Issue 253: Wrong calculated message maximum size
Import('env')
env.NanopbProto('short_array')
p = env.Program(['short_array.c',
'short_array.pb.c',
"$COMMON/pb_decode.o",
"$COMMON/pb_encode.o",
"$COMMON/pb_common.o"])
env.RunTest(p)

View file

@ -0,0 +1,24 @@
#include <unittests.h>
#include <pb_encode.h>
#include "short_array.pb.h"
int main()
{
int status = 0;
COMMENT("Test message length calculation for short arrays");
{
uint8_t buffer[TestMessage_size] = {0};
pb_ostream_t ostream = pb_ostream_from_buffer(buffer, TestMessage_size);
TestMessage msg = TestMessage_init_zero;
msg.rep_uint32_count = 1;
msg.rep_uint32[0] = ((uint32_t)1 << 31);
TEST(pb_encode(&ostream, TestMessage_fields, &msg));
TEST(ostream.bytes_written == TestMessage_size);
}
return status;
}

View file

@ -0,0 +1,7 @@
syntax = "proto2";
import "nanopb.proto";
message TestMessage {
repeated uint32 rep_uint32 = 1 [(nanopb).max_count = 1];
}

View file

@ -0,0 +1,16 @@
# Regression test for Issue 256: Proto3 mode skips submessages even when
# later array fields have non-zero value
Import('env')
env.NanopbProto('submsg_array')
p = env.Program(['submsg_array.c',
'submsg_array.pb.c',
"$COMMON/pb_decode.o",
"$COMMON/pb_encode.o",
"$COMMON/pb_common.o"])
env.RunTest(p)

View file

@ -0,0 +1,38 @@
#include <unittests.h>
#include <pb_encode.h>
#include <pb_decode.h>
#include "submsg_array.pb.h"
int main()
{
int status = 0;
COMMENT("Test encoding for submessage with array");
{
uint8_t buffer[TestMessage_size] = {0};
pb_ostream_t ostream = pb_ostream_from_buffer(buffer, TestMessage_size);
TestMessage msg = TestMessage_init_zero;
msg.submsg.rep_uint32_count = 3;
msg.submsg.rep_uint32[0] = 0;
msg.submsg.rep_uint32[1] = 1;
msg.submsg.rep_uint32[2] = 2;
TEST(pb_encode(&ostream, TestMessage_fields, &msg));
TEST(ostream.bytes_written > 0);
{
pb_istream_t istream = pb_istream_from_buffer(buffer, ostream.bytes_written);
TestMessage msg2 = TestMessage_init_zero;
TEST(pb_decode(&istream, TestMessage_fields, &msg2));
TEST(msg2.submsg.rep_uint32_count == 3);
TEST(msg2.submsg.rep_uint32[0] == 0);
TEST(msg2.submsg.rep_uint32[1] == 1);
TEST(msg2.submsg.rep_uint32[2] == 2);
}
}
return status;
}

View file

@ -0,0 +1,11 @@
syntax = "proto3";
import "nanopb.proto";
message SubMessage {
repeated uint32 rep_uint32 = 1 [(nanopb).max_count = 3];
}
message TestMessage {
SubMessage submsg = 1 [(nanopb).proto3_singular_msgs = true];
}

View file

@ -0,0 +1,21 @@
# Check that callback fields inside malloc()ed messages
# are correctly initialized.
Import('env', 'malloc_env')
env.NanopbProto('callback_pointer')
p = malloc_env.Program(["callback_pointer.c",
"callback_pointer.pb.c",
"$COMMON/pb_decode_with_malloc.o",
"$COMMON/pb_common_with_malloc.o",
"$COMMON/malloc_wrappers.o"])
# Run test under valgrind if available
kwargs = {}
if env.get("VALGRIND"):
kwargs['COMMAND'] = env['VALGRIND']
kwargs['ARGS'] = ["-q", "--error-exitcode=99", p[0].abspath]
env.RunTest(p, **kwargs)

View file

@ -0,0 +1,30 @@
#include "callback_pointer.pb.h"
#include <unittests.h>
#include <pb_decode.h>
int main()
{
int status = 0;
const uint8_t msgdata[] = {0x0A, 0x02, 0x08, 0x7F};
MainMessage msg = MainMessage_init_zero;
{
pb_istream_t stream = pb_istream_from_buffer(msgdata, sizeof(msgdata));
COMMENT("Running first decode");
TEST(pb_decode(&stream, MainMessage_fields, &msg));
pb_release(MainMessage_fields, &msg);
}
{
pb_istream_t stream = pb_istream_from_buffer(msgdata, sizeof(msgdata));
COMMENT("Running second decode");
TEST(pb_decode(&stream, MainMessage_fields, &msg));
pb_release(MainMessage_fields, &msg);
}
TEST(get_alloc_count() == 0);
return status;
}

View file

@ -0,0 +1,11 @@
syntax = "proto2";
import 'nanopb.proto';
message SubMessage {
optional int32 foo = 1 [(nanopb).type = FT_CALLBACK];
}
message MainMessage {
optional SubMessage bar = 1 [(nanopb).type = FT_POINTER];
}

View file

@ -0,0 +1,7 @@
# Check that generator gives a warning about large extension field number.
Import('env')
env.NanopbProto('large_extension')
env.Match(['large_extension.pb.c', 'large_extension.expected'])

View file

@ -0,0 +1 @@
PB_BIND\(foo_ext_extmsg, foo_ext_extmsg, 4\)

View file

@ -0,0 +1,10 @@
syntax = "proto2";
message Foo {
extensions 1 to max;
}
extend Foo {
optional int32 foo_ext = 99999;
}

View file

@ -0,0 +1,14 @@
# Check that default values with special characters are
# correctly handled.
Import('env')
env.NanopbProto('defaults')
p = env.Program(["defaults.c",
"defaults.pb.c",
"$COMMON/pb_decode.o",
"$COMMON/pb_common.o"])
env.RunTest(p)

View file

@ -0,0 +1,44 @@
#include "defaults.pb.h"
#include <unittests.h>
#include <pb_decode.h>
int check_defaults(const DefaultsMsg *msg)
{
int status = 0;
TEST(msg->b1[0] == 0xDE && msg->b1[1] == 0xAD && msg->b1[2] == 0x00 &&
msg->b1[3] == 0xBE && msg->b1[4] == 0xEF);
TEST(msg->b2.bytes[0] == 0xDE && msg->b2.bytes[1] == 0xAD &&
msg->b2.bytes[2] == 0x00 && msg->b2.bytes[3] == 0xBE &&
msg->b2.bytes[4] == 0xEF && msg->b2.size == 5);
TEST(msg->b3.bytes[0] == 0xDE && msg->b3.bytes[1] == 0xAD &&
msg->b3.bytes[2] == 0x00 && msg->b3.bytes[3] == 0xBE &&
msg->b3.bytes[4] == 0xEF && msg->b2.size == 5);
TEST(msg->s1[0] == (char)0xC3 && msg->s1[1] == (char)0xA4 &&
msg->s1[2] == (char)0xC3 && msg->s1[3] == (char)0xB6 &&
msg->s1[4] == '\0');
return status;
}
int main()
{
int status = 0;
{
DefaultsMsg msg = DefaultsMsg_init_default;
COMMENT("Checking defaults from static initializer");
status += check_defaults(&msg);
}
{
DefaultsMsg msg = DefaultsMsg_init_zero;
pb_istream_t empty = {0,0,0};
pb_decode(&empty, DefaultsMsg_fields, &msg);
COMMENT("Checking defaults set at runtime");
status += check_defaults(&msg);
}
return status;
}

View file

@ -0,0 +1,11 @@
syntax = "proto2";
import 'nanopb.proto';
message DefaultsMsg {
optional bytes b1 = 1 [default = "\xDE\xAD\x00\xBE\xEF", (nanopb).max_size = 5, (nanopb).fixed_length=true];
optional bytes b2 = 2 [default = "\xDE\xAD\x00\xBE\xEF", (nanopb).max_size = 5];
optional bytes b3 = 3 [default = "\xDE\xAD\000\xBE\xEF", (nanopb).max_size = 15];
optional string s1 = 4 [default = "äö", (nanopb).max_size = 8];
}

View file

@ -0,0 +1,7 @@
# Check that generator doesn't exceed memory limits
Import('env')
env.NanopbProto('bigvalue')

View file

@ -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;
}

View file

@ -0,0 +1,11 @@
# Regression test for #342:
# Possible null-pointer dereference in pb_decode.c
Import("env")
env.NanopbProto("extensions")
testprog = env.Program(["test_extensions.c", "extensions.pb.c",
'$COMMON/pb_decode.o', '$COMMON/pb_encode.o', '$COMMON/pb_common.o'])
env.RunTest(testprog)

View file

@ -0,0 +1,11 @@
syntax = "proto2";
message BaseMessage {
extensions 100 to 200;
}
extend BaseMessage {
optional string string_extension = 100;
}

View file

@ -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, void * const *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 bug #342 */
msg.extensions = &ext;
TEST(pb_decode(&stream, BaseMessage_fields, &msg));
}
return status;
}

View file

@ -0,0 +1,14 @@
# Regression test for #363:
# Incorrect PB_STATIC_ASSERT for bytes inside oneof
Import("env")
env.NanopbProto("oneofmsg.proto")
testprog = env.Program(["test_oneofmsg.c",
"oneofmsg.pb.c",
"$COMMON/pb_encode.o",
"$COMMON/pb_decode.o",
"$COMMON/pb_common.o"])
env.RunTest(testprog)

View file

@ -0,0 +1,10 @@
syntax = "proto2";
import "nanopb.proto";
message BodyMessage {
oneof body_type {
bytes device_data_crypted = 1 [(nanopb).max_size = 252];
bytes device_config_crypted = 2 [(nanopb).max_size = 252];
}
}

View file

@ -0,0 +1,42 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pb_encode.h>
#include <pb_decode.h>
#include "oneofmsg.pb.h"
#include "unittests.h"
int main(int argc, char **argv)
{
int status = 0;
uint8_t buffer[512];
pb_size_t msglen = 0;
{
pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
BodyMessage msg = BodyMessage_init_zero;
msg.which_body_type = BodyMessage_device_data_crypted_tag;
msg.body_type.device_data_crypted.size = 252;
memset(msg.body_type.device_data_crypted.bytes, 0xAA, 252);
TEST(pb_encode(&stream, BodyMessage_fields, &msg));
msglen = stream.bytes_written;
TEST(msglen > 252);
}
{
pb_istream_t stream = pb_istream_from_buffer(buffer, msglen);
BodyMessage msg = BodyMessage_init_zero;
TEST(pb_decode(&stream, BodyMessage_fields, &msg));
TEST(msg.which_body_type == BodyMessage_device_data_crypted_tag);
TEST(msg.body_type.device_data_crypted.size == 252);
TEST(msg.body_type.device_data_crypted.bytes[251] == 0xAA);
}
return status;
}

View file

@ -0,0 +1,14 @@
# Regression test for #376:
# Problem with fixed array inside proto3 submessage
Import("env")
env.NanopbProto(["fixed_array.proto", "fixed_array.options"])
testprog = env.Program(["test_fixarray.c",
"fixed_array.pb.c",
"$COMMON/pb_encode.o",
"$COMMON/pb_decode.o",
"$COMMON/pb_common.o"])
env.RunTest(testprog)

View file

@ -0,0 +1,2 @@
SubMessage.data fixed_count:true,max_count:8
MainMessage.submsg proto3_singular_msgs:true

View file

@ -0,0 +1,11 @@
syntax = "proto3";
message MainMessage {
SubMessage submsg = 1;
}
message SubMessage {
repeated int32 data = 1;
}

View file

@ -0,0 +1,40 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pb_encode.h>
#include <pb_decode.h>
#include "fixed_array.pb.h"
#include "unittests.h"
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));
MainMessage msg = MainMessage_init_zero;
msg.submsg.data[0] = 0;
msg.submsg.data[4] = 5;
TEST(pb_encode(&stream, MainMessage_fields, &msg));
msglen = stream.bytes_written;
TEST(msglen > 5);
}
{
pb_istream_t stream = pb_istream_from_buffer(buffer, msglen);
MainMessage msg = MainMessage_init_zero;
TEST(pb_decode(&stream, MainMessage_fields, &msg));
TEST(msg.submsg.data[0] == 0);
TEST(msg.submsg.data[4] == 5);
}
return status;
}

View file

@ -0,0 +1,9 @@
# Regression test for #380:
# mangle_names:M_STRIP_PACKAGE is broken when message name (partially)
# matches package name
Import("env")
env.NanopbProto(["manglenames.proto", "manglenames.options"])
env.Object("manglenames.pb.o", "manglenames.pb.c")

View file

@ -0,0 +1 @@
* mangle_names:M_STRIP_PACKAGE

View file

@ -0,0 +1,16 @@
syntax = "proto2";
package A;
message A {
message B {
optional uint32 val = 1;
}
optional B b = 1;
}
message AP {
message B {
optional uint32 val = 1;
}
optional B m = 1;
}

View file

@ -0,0 +1,14 @@
# Regression test for #395:
# Unexpected empty submessage in proto3 mode
Import("env")
env.NanopbProto(["test.proto", "test.options"])
testprog = env.Program(["test.c",
"test.pb.c",
"$COMMON/pb_encode.o",
"$COMMON/pb_decode.o",
"$COMMON/pb_common.o"])
env.RunTest(testprog)

View file

@ -0,0 +1,38 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pb_encode.h>
#include <pb_decode.h>
#include "test.pb.h"
#include "unittests.h"
int main(int argc, char **argv)
{
int status = 0;
uint8_t buffer[512] = {0};
int i;
pb_ostream_t ostream;
Reply reply = Reply_init_zero;
Reply_Result request_result = Reply_Result_OK;
ostream = pb_ostream_from_buffer(buffer, sizeof(buffer));
reply.result = request_result;
if (!pb_encode(&ostream, Reply_fields, &reply)) {
fprintf(stderr, "Encode failed: %s\n", PB_GET_ERROR(&ostream));
return 1;
}
printf("response payload (%d):", (int)ostream.bytes_written);
for (i = 0; i < ostream.bytes_written; i++) {
printf("%02X", buffer[i]);
}
printf("\n");
TEST(ostream.bytes_written == 2);
TEST(buffer[0] == 0x08);
TEST(buffer[1] == 0x01);
return status;
}

View file

@ -0,0 +1,3 @@
* proto3_singular_msgs:true
SubSubAMessage.somestring max_size:64
SubSubBMessage.somestring max_size:64

View file

@ -0,0 +1,37 @@
syntax = "proto3";
message Error
{
int32 code = 1;
string message = 2;
}
message SubSubAMessage
{
string somestring = 1;
}
message SubSubBMessage
{
string somestring = 1;
}
message SubMessage
{
SubSubAMessage subsubmessageA = 1;
repeated SubSubBMessage subsubmessageB = 2;
}
message Reply
{
enum Result
{
ERROR = 0;
OK = 1;
SOME_A = 2;
}
Result result = 1;
Error error = 2;
SubMessage submessage = 3;
}

View file

@ -0,0 +1,8 @@
# Regression test for issue #407: Extension fields > 255 not parsed correctly
Import("env")
env.NanopbProto("extensions")
test = env.Program(["test_extensions.c", "extensions.pb.c", "$COMMON/pb_encode.o", "$COMMON/pb_decode.o", "$COMMON/pb_common.o"])
env.RunTest(test)

View file

@ -0,0 +1,14 @@
syntax = "proto2";
message SimpleMessage {
optional uint32 number = 1;
extensions 100 to max;
}
message ExtMessage {
extend SimpleMessage {
optional ExtMessage ext_message_ext = 1100;
}
optional uint32 second_number = 1;
}

View file

@ -0,0 +1,68 @@
#include <pb_encode.h>
#include <pb_decode.h>
#include "extensions.pb.h"
#include "unittests.h"
int main()
{
uint8_t buffer[256];
int status = 0;
size_t msglen;
{
pb_ostream_t stream;
SimpleMessage msg = SimpleMessage_init_zero;
ExtMessage extmsg = ExtMessage_init_zero;
pb_extension_t ext = pb_extension_init_zero;
COMMENT("Encoding message");
msg.has_number = true;
msg.number = 1234;
extmsg.has_second_number = true;
extmsg.second_number = 5678;
msg.extensions = &ext;
ext.type = &ExtMessage_ext_message_ext;
ext.dest = &extmsg;
ext.next = NULL;
stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
TEST(pb_encode(&stream, SimpleMessage_fields, &msg));
msglen = stream.bytes_written;
TEST(msglen == 9); /* 3 for number, 3 for submsg tag+len, 3 for second_number */
TEST(buffer[0] == 0x08); /* varint 1 */
TEST(buffer[1] == 0xD2); /* number = 1234 */
TEST(buffer[2] == 0x09);
TEST(buffer[3] == 0xE2); /* submsg 1100 */
TEST(buffer[4] == 0x44);
TEST(buffer[5] == 0x03); /* length 3 */
TEST(buffer[6] == 0x08); /* varint 1 */
TEST(buffer[7] == 0xae); /* second_number = 5678 */
TEST(buffer[8] == 0x2c);
}
{
pb_istream_t stream;
SimpleMessage msg = SimpleMessage_init_zero;
ExtMessage extmsg = ExtMessage_init_zero;
pb_extension_t ext = pb_extension_init_zero;
COMMENT("Decoding message");
msg.extensions = &ext;
ext.type = &ExtMessage_ext_message_ext;
ext.dest = &extmsg;
ext.next = NULL;
ext.found = false;
stream = pb_istream_from_buffer(buffer, msglen);
TEST(pb_decode(&stream, SimpleMessage_fields, &msg));
TEST(msg.has_number);
TEST(msg.number == 1234);
TEST(ext.found);
TEST(extmsg.has_second_number);
TEST(extmsg.second_number == 5678);
}
return status;
}

View file

@ -0,0 +1,14 @@
# Regression test for #453:
# Warning for float conversion with default values.
Import("env")
env2 = env.Clone()
if 'gcc' in env['CC']:
env2.Append(CFLAGS = '-Wconversion')
env2.NanopbProto("test.proto")
testprog = env2.Program(["test.c"])
env2.RunTest(testprog)

View file

@ -0,0 +1,11 @@
#include "test.pb.h"
#include "unittests.h"
int main()
{
int status = 0;
MyMessage msg = MyMessage_init_default;
TEST(msg.myfield >= 1.23399f);
TEST(msg.myfield <= 1.23401f);
return status;
}

View file

@ -0,0 +1,7 @@
syntax = 'proto2';
message MyMessage
{
optional float myfield = 1 [default = 1.234];
}

View file

@ -0,0 +1,7 @@
# Regression test for issue #472: submsg_callback fails to compile in Atmel Studio
Import("env")
env.NanopbProto("test")
env.Object("test.pb.c")

View file

@ -0,0 +1,16 @@
syntax = "proto3";
import "nanopb.proto";
message FirmwareUpdateCommand {
string version = 1;
uint32 size = 2;
}
message CommandWrapperMessage {
option (nanopb_msgopt).submsg_callback = true;
oneof payload {
FirmwareUpdateCommand firmware_update = 1;
}
}

View file

@ -0,0 +1,11 @@
# Check that the int8_t and uint8_t types are not used in the nanopb core.
Import("env")
env.Match('pb_decode_c.matched', ["$NANOPB/pb_decode.c", 'uint8.expected'])
env.Match('pb_decode_h.matched', ["$NANOPB/pb_decode.h", 'uint8.expected'])
env.Match('pb_encode_c.matched', ["$NANOPB/pb_encode.c", 'uint8.expected'])
env.Match('pb_encode_h.matched', ["$NANOPB/pb_encode.h", 'uint8.expected'])
env.Match('pb_common_c.matched', ["$NANOPB/pb_common.c", 'uint8.expected'])
env.Match('pb_common_h.matched', ["$NANOPB/pb_common.h", 'uint8.expected'])
env.Match('pb_h.matched', ["$NANOPB/pb.h", 'uint8.expected'])

View file

@ -0,0 +1,3 @@
! ^\s*[^/* ].*uint8_t
! ^\s*[^/* ].*int8_t

View file

@ -0,0 +1,6 @@
# Regression test for #487:
# Problem in default_value() with nested messages
Import("env")
env.NanopbProto("test")
env.Object("test.pb.c")

View file

@ -0,0 +1,16 @@
syntax = "proto2";
package a.b.c;
message TopLevel {
optional uint32 field = 1 [default = 0];
optional NestedTypeA foo = 2;
message NestedTypeA {
optional NestedTypeB bar = 1;
message NestedTypeB {
optional uint32 foobar = 1;
}
}
}

View file

@ -0,0 +1,10 @@
# Regression test for #493:
# Maximum recursion depth exceeded in generator
Import("env")
env.NanopbProto("test.proto")
# Note that test.pb.c will fail compilation due to recursive static definition.
# This is to be expected.

View file

@ -0,0 +1,9 @@
syntax = "proto2";
import "nanopb.proto";
message MyMessage {
option (nanopb_msgopt).msgid = 8;
oneof configuration_flash {
MyMessage my_message_v1 = 1;
}
}

View file

@ -0,0 +1,17 @@
# Regression test for #494:
# Using sizeof on anonymous union not allowed in C++, in message_size oneof sizing fallback
Import('env')
import os, sys
# The build rules here are a bit tricky to make the normal dependency
# resolution intentionally fail. This causes the generator to use the fallback
# define which had the problem with C++.
env.Command("oneof.pb", "oneof.proto", "$PROTOC $PROTOCFLAGS -I$BUILDDIR/regression/issue_494 -o$TARGETS $SOURCES")
env.Command(["oneof.pb.c", "oneof.pb.h"], "oneof.pb", env['NANOPB_GENERATOR'] + " -D$BUILDDIR/regression/issue_494 $SOURCES")
env.NanopbProto("submessage.proto")
env.Depends("oneof.pb", "submessage.proto")
test = env.Program(["oneof_size.cc"])
env.Depends(test, "oneof.pb.h")
env.RunTest(test)

Some files were not shown because too many files have changed in this diff Show more