From 9983fbbb83b50bde0fa4dae71b10aed2f703ddad Mon Sep 17 00:00:00 2001 From: jmjatlanta Date: Fri, 9 Dec 2016 14:13:59 -0500 Subject: [PATCH] Fixed protobuf bugs and added 3rd example of a complex object --- protobuf.c | 9 +++++++-- test/Test1_protobuf.c | 1 + test/Test3_protobuf.c | 18 +++++++++++++++--- test/test_protobuf.h | 11 ++++++++++- varint.c | 1 + 5 files changed, 34 insertions(+), 6 deletions(-) diff --git a/protobuf.c b/protobuf.c index 24a48a0..efc9525 100644 --- a/protobuf.c +++ b/protobuf.c @@ -48,6 +48,7 @@ int protobuf_encode_string(int field_number, enum WireType field_type, const cha */ int protobuf_encode_varint(int field_number, enum WireType field_type, unsigned long long incoming, unsigned char* buffer, size_t max_buffer_length, size_t* bytes_written) { + *bytes_written = 0; // push the field number and wire type together unsigned int field_no = field_number << 3; unsigned long long field = field_no | field_type; @@ -72,17 +73,20 @@ int protobuf_encode_varint(int field_number, enum WireType field_type, unsigned */ int protobuf_decode_string(const unsigned char* buffer, size_t buffer_length, char** results, size_t* bytes_read) { size_t pos = 0; + *bytes_read = 0; // grab the field size int length = varint_decode(&buffer[pos], buffer_length - pos, bytes_read); pos += *bytes_read; // allocate memory - *results = malloc(sizeof(char) * length); + *results = malloc(sizeof(char) * length + 1); if ((*results) == NULL) return 0; // copy the string memcpy((*results), &buffer[pos], length); + // don't forget the null + (*results)[length] = 0; pos += length; *bytes_read = pos; @@ -98,9 +102,10 @@ int protobuf_decode_string(const unsigned char* buffer, size_t buffer_length, ch * @param bytes_read the number of bytes read from the buffer */ int protobuf_decode_field_and_type(const unsigned char* buffer, int buffer_length, int *field_no, enum WireType *field_type, size_t* bytes_read) { + *bytes_read = 0; unsigned long long field = varint_decode(buffer, buffer_length, bytes_read); *field_no = field >> 3; - *field_type = field | *field_no; + *field_type = field & *field_no; return 1; } diff --git a/test/Test1_protobuf.c b/test/Test1_protobuf.c index ad083dc..dbc21f0 100644 --- a/test/Test1_protobuf.c +++ b/test/Test1_protobuf.c @@ -38,6 +38,7 @@ int Test1_protobuf_decode(unsigned char* buffer, size_t buffer_length, struct Te Test1_free(*output); return 0; } + pos += bytes_read; switch (field_no) { case (1): (*output)->a = varint_decode(&buffer[pos], buffer_length - pos, &bytes_read); diff --git a/test/Test3_protobuf.c b/test/Test3_protobuf.c index 3acfac4..efef130 100644 --- a/test/Test3_protobuf.c +++ b/test/Test3_protobuf.c @@ -33,7 +33,16 @@ int Test3_protobuf_encode(struct Test3* incoming, unsigned char* buffer, size_t *bytes_written += bytes_used; protobuf_encode_varint(2, Test3_message_fields[1], incoming->an_int, &buffer[*bytes_written], max_buffer_length - *bytes_written, &bytes_used); *bytes_written += bytes_used; - return Test2_protobuf_encode(incoming->test2, &buffer[*bytes_written], max_buffer_length - *bytes_written, &bytes_used); + // write Test2 to safe area + int pos = *bytes_written + 11; + size_t test2_size = 0; + int retVal = Test2_protobuf_encode(incoming->test2, &buffer[pos], max_buffer_length - pos, &test2_size); + protobuf_encode_varint(3, Test3_message_fields[2], test2_size, &buffer[*bytes_written], max_buffer_length - *bytes_written, &bytes_used); + *bytes_written += bytes_used; + // now move the encoded Test2 to the correct area + memcpy(&buffer[*bytes_written], &buffer[pos], test2_size); + *bytes_written += test2_size; + return retVal; } int Test3_protobuf_decode(unsigned char* buffer, size_t buffer_length, struct Test3** output) { @@ -59,10 +68,13 @@ int Test3_protobuf_decode(unsigned char* buffer, size_t buffer_length, struct Te (*output)->an_int = varint_decode(&buffer[pos], buffer_length - pos, &bytes_read); pos += bytes_read; break; - case(3): - Test2_protobuf_decode(&buffer[pos], buffer_length - pos, &((*output)->test2)); + case(3): { + size_t test2_size = varint_decode(&buffer[pos], buffer_length - pos, &bytes_read); pos += bytes_read; + Test2_protobuf_decode(&buffer[pos], buffer_length - pos, &((*output)->test2)); + pos += test2_size; break; + } } } return 1; diff --git a/test/test_protobuf.h b/test/test_protobuf.h index 599e58c..2393390 100644 --- a/test/test_protobuf.h +++ b/test/test_protobuf.h @@ -65,7 +65,7 @@ int test_complex_protobuf() { return 0; } - if (strcmp(results->test2->a, test3->test2->a) == 0) { + if (strcmp(results->test2->a, test3->test2->a) != 0) { printf("String a does not match: %s vs %s\n", test3->test2->a, results->test2->a); Test3_free(test3); Test3_free(results); @@ -145,6 +145,15 @@ int test_write_simple() { return 0; } + struct Test1* results; + retVal = Test1_protobuf_decode(buffer, bytes_written, &results); + + if (results->a != test1.a) { + printf("Incorrect results after decode"); + Test1_free(results); + return 0; + } + return 1; } diff --git a/varint.c b/varint.c index 3294515..fc7e128 100644 --- a/varint.c +++ b/varint.c @@ -61,6 +61,7 @@ unsigned char* varint_encode(const unsigned long long n, unsigned char* buf, int */ unsigned long long varint_decode(const unsigned char* buf, int len, size_t* bytes) { unsigned long long result = 0; + if (bytes != NULL) *bytes = 0; int bits = 0; const unsigned char* ptr = buf; unsigned long long ll;