mirror of
https://github.com/protobuf-c/protobuf-c.git
synced 2024-12-27 13:31:02 +08:00
protobuf-c.c: fix packed repeated bool parsing
From https://developers.google.com/protocol-buffers/docs/proto3#updating: int32, uint32, int64, uint64, and bool are all compatible – this means you can change a field from one of these types to another without breaking forwards- or backwards-compatibility. If a number is parsed from the wire which doesn't fit in the corresponding type, you will get the same effect as if you had cast the number to that type in C++ (e.g. if a 64-bit number is read as an int32, it will be truncated to 32 bits). Until this fix, protobuf-c did not conform to the rule above when it came to deserializing non-boolean packed repeated data into a protobuf_c_boolean array. Fully scan the varint and use parse_boolean to truncate the resulting value. Fixes #440
This commit is contained in:
parent
38af0d26ab
commit
733ae77e23
16
Makefile.am
16
Makefile.am
@ -274,6 +274,22 @@ BUILT_SOURCES += \
|
|||||||
t/issue389/issue389.pb-c.c t/issue389/issue389.pb-c.h
|
t/issue389/issue389.pb-c.c t/issue389/issue389.pb-c.h
|
||||||
EXTRA_DIST += \
|
EXTRA_DIST += \
|
||||||
t/issue389/issue389.proto
|
t/issue389/issue389.proto
|
||||||
|
|
||||||
|
check_PROGRAMS += \
|
||||||
|
t/issue440/issue440
|
||||||
|
TESTS += \
|
||||||
|
t/issue440/issue440
|
||||||
|
t_issue440_issue440_SOURCES = \
|
||||||
|
t/issue440/issue440.c \
|
||||||
|
t/issue440/issue440.pb-c.c
|
||||||
|
t_issue440_issue440_LDADD = \
|
||||||
|
protobuf-c/libprotobuf-c.la
|
||||||
|
t/issue440/issue440.pb-c.c t/issue440/issue440.pb-c.h: $(top_builddir)/protoc-c/protoc-gen-c$(EXEEXT) $(top_srcdir)/t/issue440/issue440.proto
|
||||||
|
$(AM_V_GEN)@PROTOC@ --plugin=protoc-gen-c=$(top_builddir)/protoc-c/protoc-gen-c$(EXEEXT) -I$(top_srcdir) --c_out=$(top_builddir) $(top_srcdir)/t/issue440/issue440.proto
|
||||||
|
BUILT_SOURCES += \
|
||||||
|
t/issue440/issue440.pb-c.c t/issue440/issue440.pb-c.h
|
||||||
|
EXTRA_DIST += \
|
||||||
|
t/issue440/issue440.proto
|
||||||
endif # BUILD_PROTO3
|
endif # BUILD_PROTO3
|
||||||
EXTRA_DIST += \
|
EXTRA_DIST += \
|
||||||
t/issue330/issue330.proto
|
t/issue330/issue330.proto
|
||||||
|
@ -2748,7 +2748,9 @@ parse_packed_repeated_member(ScannedMember *scanned_member,
|
|||||||
const uint8_t *at = scanned_member->data + scanned_member->length_prefix_len;
|
const uint8_t *at = scanned_member->data + scanned_member->length_prefix_len;
|
||||||
size_t rem = scanned_member->len - scanned_member->length_prefix_len;
|
size_t rem = scanned_member->len - scanned_member->length_prefix_len;
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
|
#if defined(WORDS_BIGENDIAN)
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
#endif
|
||||||
|
|
||||||
switch (field->type) {
|
switch (field->type) {
|
||||||
case PROTOBUF_C_TYPE_SFIXED32:
|
case PROTOBUF_C_TYPE_SFIXED32:
|
||||||
@ -2841,13 +2843,15 @@ parse_packed_repeated_member(ScannedMember *scanned_member,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PROTOBUF_C_TYPE_BOOL:
|
case PROTOBUF_C_TYPE_BOOL:
|
||||||
count = rem;
|
while (rem > 0) {
|
||||||
for (i = 0; i < count; i++) {
|
unsigned s = scan_varint(rem, at);
|
||||||
if (at[i] > 1) {
|
if (s == 0) {
|
||||||
PROTOBUF_C_UNPACK_ERROR("bad packed-repeated boolean value");
|
PROTOBUF_C_UNPACK_ERROR("bad packed-repeated boolean value");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
((protobuf_c_boolean *) array)[i] = at[i];
|
((protobuf_c_boolean *) array)[count++] = parse_boolean(s, at);
|
||||||
|
at += s;
|
||||||
|
rem -= s;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
1
t/issue440/.gitignore
vendored
Normal file
1
t/issue440/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
issue440
|
30
t/issue440/issue440.c
Normal file
30
t/issue440/issue440.c
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "t/issue440/issue440.pb-c.h"
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
/* Output of $ echo "int: 1 int: -142342 int: 0 int: 423423222" | \
|
||||||
|
* protoc issue440.proto --encode=Int | xxd -i:
|
||||||
|
* 0x0a, 0x11, 0x01, 0xfa, 0xa7, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
* 0x01, 0x00, 0xf6, 0xd9, 0xf3, 0xc9, 0x01
|
||||||
|
*
|
||||||
|
* Output of $ echo "int: 1 int: -142342 int: 0 int: 423423222" | \
|
||||||
|
* protoc issue440.proto --encode=Int | protoc issue440.proto \
|
||||||
|
* --decode=Boolean: boolean: true boolean: true boolean: false boolean: true
|
||||||
|
*/
|
||||||
|
uint8_t protoc[] = {0x0a, 0x11, 0x01, 0xfa, 0xa7, 0xf7, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0xf6, 0xd9, 0xf3, 0xc9,
|
||||||
|
0x01};
|
||||||
|
Boolean *msg = boolean__unpack (NULL, sizeof protoc, protoc);
|
||||||
|
assert(msg);
|
||||||
|
assert(msg->n_boolean == 4);
|
||||||
|
assert(msg->boolean[0] == 1);
|
||||||
|
assert(msg->boolean[1] == 1);
|
||||||
|
assert(msg->boolean[2] == 0);
|
||||||
|
assert(msg->boolean[3] == 1);
|
||||||
|
boolean__free_unpacked (msg, NULL);
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
9
t/issue440/issue440.proto
Normal file
9
t/issue440/issue440.proto
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
message Int {
|
||||||
|
repeated int32 int = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Boolean {
|
||||||
|
repeated bool boolean = 1;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user