Commit e30ec5f7 authored by lahiker42's avatar lahiker42

protobuf_c_unpack_message():

Insist that required fields be represented in the packed message.


git-svn-id: https://protobuf-c.googlecode.com/svn/trunk@242 00440858-1255-0410-a3e6-75ea37f81c3a
parent 45d9ee46
...@@ -5,7 +5,9 @@ ...@@ -5,7 +5,9 @@
- bug in dsk_dispatch_close_fd(), which usually only - bug in dsk_dispatch_close_fd(), which usually only
showed up in later function calls. showed up in later function calls.
- support for deprecated fields -- enable a GCC warning - support for deprecated fields -- enable a GCC warning
if a field has the "deprecated" option enabled. (Andrey Nigmatulin) if a field has the "deprecated" option enabled. (Andrei Nigmatulin)
- fix for protobuf_c_message_unpack() to issue error if any "required" field
is missing in input stream. (Andrei Nigmatulin)
0.13: 0.13:
- Fix for when the number of connections gets too great in RPC. - Fix for when the number of connections gets too great in RPC.
......
...@@ -2103,11 +2103,20 @@ protobuf_c_message_unpack (const ProtobufCMessageDescriptor *desc, ...@@ -2103,11 +2103,20 @@ protobuf_c_message_unpack (const ProtobufCMessageDescriptor *desc,
size_t n_unknown = 0; size_t n_unknown = 0;
unsigned f; unsigned f;
unsigned i_slab; unsigned i_slab;
unsigned last_field_index = 0;
unsigned long *required_fields_bitmap;
unsigned required_fields_bitmap_len;
static const unsigned word_bits = sizeof(long) * 8;
ASSERT_IS_MESSAGE_DESCRIPTOR (desc); ASSERT_IS_MESSAGE_DESCRIPTOR (desc);
if (allocator == NULL) if (allocator == NULL)
allocator = &protobuf_c_default_allocator; allocator = &protobuf_c_default_allocator;
required_fields_bitmap_len = (desc->n_fields + word_bits - 1) / word_bits;
required_fields_bitmap = alloca(required_fields_bitmap_len * sizeof(long));
memset(required_fields_bitmap, 0, required_fields_bitmap_len * sizeof(long));
DO_ALLOC (rv, allocator, desc->sizeof_message, return NULL); DO_ALLOC (rv, allocator, desc->sizeof_message, return NULL);
scanned_member_slabs[0] = first_member_slab; scanned_member_slabs[0] = first_member_slab;
...@@ -2150,11 +2159,15 @@ protobuf_c_message_unpack (const ProtobufCMessageDescriptor *desc, ...@@ -2150,11 +2159,15 @@ protobuf_c_message_unpack (const ProtobufCMessageDescriptor *desc,
{ {
field = desc->fields + field_index; field = desc->fields + field_index;
last_field = field; last_field = field;
last_field_index = field_index;
} }
} }
else else
field = last_field; field = last_field;
if (field != NULL && field->label == PROTOBUF_C_LABEL_REQUIRED)
required_fields_bitmap[last_field_index / word_bits] |= (1UL << (last_field_index % word_bits));
at += used; at += used;
rem -= used; rem -= used;
tmp.tag = tag; tmp.tag = tag;
...@@ -2258,11 +2271,12 @@ protobuf_c_message_unpack (const ProtobufCMessageDescriptor *desc, ...@@ -2258,11 +2271,12 @@ protobuf_c_message_unpack (const ProtobufCMessageDescriptor *desc,
rem -= tmp.len; rem -= tmp.len;
} }
/* allocate space for repeated fields */ /* allocate space for repeated fields, also check that all required fields have been set */
for (f = 0; f < desc->n_fields; f++) for (f = 0; f < desc->n_fields; f++)
if (desc->fields[f].label == PROTOBUF_C_LABEL_REPEATED) {
{ const ProtobufCFieldDescriptor *field = desc->fields + f;
const ProtobufCFieldDescriptor *field = desc->fields + f; if (field->label == PROTOBUF_C_LABEL_REPEATED)
{
size_t siz = sizeof_elt_in_repeated_array (field->type); size_t siz = sizeof_elt_in_repeated_array (field->type);
size_t *n_ptr = STRUCT_MEMBER_PTR (size_t, rv, field->quantifier_offset); size_t *n_ptr = STRUCT_MEMBER_PTR (size_t, rv, field->quantifier_offset);
if (*n_ptr != 0) if (*n_ptr != 0)
...@@ -2282,7 +2296,16 @@ protobuf_c_message_unpack (const ProtobufCMessageDescriptor *desc, ...@@ -2282,7 +2296,16 @@ protobuf_c_message_unpack (const ProtobufCMessageDescriptor *desc,
CLEAR_REMAINING_N_PTRS (); goto error_cleanup); CLEAR_REMAINING_N_PTRS (); goto error_cleanup);
#undef CLEAR_REMAINING_N_PTRS #undef CLEAR_REMAINING_N_PTRS
} }
}
else if (field->label == PROTOBUF_C_LABEL_REQUIRED)
{
if (field->default_value == NULL && 0 == (required_fields_bitmap[f / word_bits] & (1UL << (f % word_bits))))
{
UNPACK_ERROR (("message '%s': missing required field '%s'", desc->name, field->name));
goto error_cleanup;
} }
}
}
/* allocate space for unknown fields */ /* allocate space for unknown fields */
if (n_unknown) if (n_unknown)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment