From 1c8805a780aee4c35c962059980ea06176055260 Mon Sep 17 00:00:00 2001 From: Paolo Borelli Date: Sun, 9 Apr 2017 10:51:35 +0200 Subject: [PATCH 1/2] Fix "is zeroish" evaluation for proto3 In proto3 the default value is zero (NULL for pointers and 0 for scalars). However when checking we still need to test by type because poinetr types have an extra indirection. --- protobuf-c/protobuf-c.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/protobuf-c/protobuf-c.c b/protobuf-c/protobuf-c.c index 39819b4..c092d34 100644 --- a/protobuf-c/protobuf-c.c +++ b/protobuf-c/protobuf-c.c @@ -523,6 +523,20 @@ optional_field_get_packed_size(const ProtobufCFieldDescriptor *field, return required_field_get_packed_size(field, member); } +static protobuf_c_boolean +field_is_zeroish(const ProtobufCFieldDescriptor *field, + const void *member) +{ + if (field->type == PROTOBUF_C_TYPE_MESSAGE || + field->type == PROTOBUF_C_TYPE_STRING) + { + const void *ptr = *(const void * const *) member; + if (ptr == NULL) + return TRUE; + } + return member == NULL; +} + /** * Calculate the serialized size of a single unlabeled message field, including * the space needed by the preceding tag. Returns 0 if the field isn't set or @@ -540,10 +554,8 @@ static size_t unlabeled_field_get_packed_size(const ProtobufCFieldDescriptor *field, const void *member) { - const void *ptr = *(const void * const *) member; - if (ptr == NULL) { + if (field_is_zeroish(field, member)) return 0; - } return required_field_get_packed_size(field, member); } @@ -1168,10 +1180,8 @@ static size_t unlabeled_field_pack(const ProtobufCFieldDescriptor *field, const void *member, uint8_t *out) { - const void *ptr = *(const void * const *) member; - if (ptr == NULL) { + if (field_is_zeroish(field, member)) return 0; - } return required_field_pack(field, member, out); } @@ -1673,10 +1683,8 @@ static size_t unlabeled_field_pack_to_buffer(const ProtobufCFieldDescriptor *field, const void *member, ProtobufCBuffer *buffer) { - const void *ptr = *(const void *const *) member; - if (ptr == NULL) { + if (field_is_zeroish(field, member)) return 0; - } return required_field_pack_to_buffer(field, member, buffer); } From 13b6e1fd0031606a2ff69da55ebee7e40d2b60f1 Mon Sep 17 00:00:00 2001 From: Paolo Borelli Date: Sat, 8 Apr 2017 14:27:37 +0200 Subject: [PATCH 2/2] Improve proto3 unit test Make sure we actually include the proto3 generated header and test nested submessages --- Makefile.am | 3 +++ t/generated-code/test-generated-code.c | 31 +++++++++++++++++++++++++- t/test-proto3.proto | 5 +++++ t/test.proto | 5 +++++ 4 files changed, 43 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 9f078f6..b59768e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -193,6 +193,9 @@ check_PROGRAMS += \ TESTS += \ t/generated-code3/test-generated-code3 +t_generated_code3_test_generated_code3_CPPFLAGS = \ + -DPROTO3 + t_generated_code3_test_generated_code3_LDADD = \ protobuf-c/libprotobuf-c.la diff --git a/t/generated-code/test-generated-code.c b/t/generated-code/test-generated-code.c index 1d62094..7443a09 100644 --- a/t/generated-code/test-generated-code.c +++ b/t/generated-code/test-generated-code.c @@ -1,10 +1,17 @@ +#ifdef PROTO3 +#include "t/test-proto3.pb-c.h" +#else #include "t/test.pb-c.h" +#endif #include #include #include -int main() +int main(void) { + Foo__Person__PhoneNumber__Comment comment = FOO__PERSON__PHONE_NUMBER__COMMENT__INIT; + Foo__Person__PhoneNumber phone = FOO__PERSON__PHONE_NUMBER__INIT; + Foo__Person__PhoneNumber *phone_numbers[1]; Foo__Person person = FOO__PERSON__INIT; Foo__Person *person2; unsigned char simple_pad[8]; @@ -12,21 +19,43 @@ int main() unsigned char *packed; ProtobufCBufferSimple bs = PROTOBUF_C_BUFFER_SIMPLE_INIT (simple_pad); + comment.comment = "protobuf-c guy"; + + phone.number = "1234"; +#ifndef PROTO3 + phone.has_type = 1; +#endif + phone.type = FOO__PERSON__PHONE_TYPE__WORK; + phone.comment = &comment; + + phone_numbers[0] = ☎ + person.name = "dave b"; person.id = 42; + person.n_phone = 1; + person.phone = phone_numbers; + size = foo__person__get_packed_size (&person); packed = malloc (size); assert (packed); + size2 = foo__person__pack (&person, packed); + assert (size == size2); foo__person__pack_to_buffer (&person, &bs.base); assert (bs.len == size); assert (memcmp (bs.data, packed, size) == 0); + PROTOBUF_C_BUFFER_SIMPLE_CLEAR (&bs); + person2 = foo__person__unpack (NULL, size, packed); assert (person2 != NULL); assert (person2->id == 42); assert (strcmp (person2->name, "dave b") == 0); + assert (person2->n_phone == 1); + assert (strcmp (person2->phone[0]->number, "1234") == 0); + assert (person2->phone[0]->type == FOO__PERSON__PHONE_TYPE__WORK); + assert (strcmp (person2->phone[0]->comment->comment, "protobuf-c guy") == 0); foo__person__free_unpacked (person2, NULL); free (packed); diff --git a/t/test-proto3.proto b/t/test-proto3.proto index 41da791..83fdf2a 100644 --- a/t/test-proto3.proto +++ b/t/test-proto3.proto @@ -14,8 +14,13 @@ message Person { } message PhoneNumber { + message Comment { + string comment = 1; + } + string number = 1; PhoneType type = 2; + Comment comment = 3; } repeated PhoneNumber phone = 4; diff --git a/t/test.proto b/t/test.proto index bc94f13..bda724e 100644 --- a/t/test.proto +++ b/t/test.proto @@ -12,8 +12,13 @@ message Person { } message PhoneNumber { + message Comment { + required string comment = 1; + } + required string number = 1; optional PhoneType type = 2 [default = HOME]; + optional Comment comment = 3; } repeated PhoneNumber phone = 4;