Fix crashes on corrupt data. (Issue 16)

git-svn-id: https://protobuf-c.googlecode.com/svn/trunk@181 00440858-1255-0410-a3e6-75ea37f81c3a
This commit is contained in:
lahiker42 2009-04-04 22:53:39 +00:00
parent cb95ca9c64
commit df4ccc669d
2 changed files with 30 additions and 9 deletions

View File

@ -1,6 +1,8 @@
0.10: (NOT YET RELEASED) 0.10: (NOT YET RELEASED)
- build issue on platforms which don't compute library dependencies - build issue on platforms which don't compute library dependencies
automatically. automatically.
- fix for certain types of corrupt messages (Landon Fuller)
0.9: 0.9:
- build issue: needed $(EXEEXT) in dependency lists for cygwin - build issue: needed $(EXEEXT) in dependency lists for cygwin
- bug fix: protobuf_c_service_get_method_by_name() was not correct b/c - bug fix: protobuf_c_service_get_method_by_name() was not correct b/c

View File

@ -1248,9 +1248,9 @@ parse_required_member (ScannedMember *scanned_member,
subm = protobuf_c_message_unpack (scanned_member->field->descriptor, subm = protobuf_c_message_unpack (scanned_member->field->descriptor,
allocator, allocator,
len - pref_len, data + pref_len); len - pref_len, data + pref_len);
*pmessage = subm; /* since we freed the message we must clear the field, even if NULL */
if (subm == NULL) if (subm == NULL)
return 0; return 0;
*pmessage = subm;
return 1; return 1;
} }
} }
@ -1413,7 +1413,7 @@ protobuf_c_message_unpack (const ProtobufCMessageDescriptor *desc,
{ {
UNPACK_ERROR (("error parsing tag/wiretype at offset %u", UNPACK_ERROR (("error parsing tag/wiretype at offset %u",
(unsigned)(at-data))); (unsigned)(at-data)));
goto error_cleanup; goto error_cleanup_during_scan;
} }
/* XXX: consider optimizing for field[1].id == tag, if field[1] exists! */ /* XXX: consider optimizing for field[1].id == tag, if field[1] exists! */
if (last_field->id != tag) if (last_field->id != tag)
@ -1455,7 +1455,7 @@ protobuf_c_message_unpack (const ProtobufCMessageDescriptor *desc,
{ {
UNPACK_ERROR (("unterminated varint at offset %u", UNPACK_ERROR (("unterminated varint at offset %u",
(unsigned)(at-data))); (unsigned)(at-data)));
goto error_cleanup; goto error_cleanup_during_scan;
} }
tmp.len = i + 1; tmp.len = i + 1;
} }
@ -1465,7 +1465,7 @@ protobuf_c_message_unpack (const ProtobufCMessageDescriptor *desc,
{ {
UNPACK_ERROR (("too short after 64bit wiretype at offset %u", UNPACK_ERROR (("too short after 64bit wiretype at offset %u",
(unsigned)(at-data))); (unsigned)(at-data)));
goto error_cleanup; goto error_cleanup_during_scan;
} }
tmp.len = 8; tmp.len = 8;
break; break;
@ -1476,7 +1476,7 @@ protobuf_c_message_unpack (const ProtobufCMessageDescriptor *desc,
if (tmp.len == 0) if (tmp.len == 0)
{ {
/* NOTE: scan_length_prefixed_data calls UNPACK_ERROR */ /* NOTE: scan_length_prefixed_data calls UNPACK_ERROR */
goto error_cleanup; goto error_cleanup_during_scan;
} }
tmp.length_prefix_len = pref_len; tmp.length_prefix_len = pref_len;
break; break;
@ -1484,13 +1484,13 @@ protobuf_c_message_unpack (const ProtobufCMessageDescriptor *desc,
case PROTOBUF_C_WIRE_TYPE_START_GROUP: case PROTOBUF_C_WIRE_TYPE_START_GROUP:
case PROTOBUF_C_WIRE_TYPE_END_GROUP: case PROTOBUF_C_WIRE_TYPE_END_GROUP:
UNPACK_ERROR (("unsupported group tag at offset %u", (unsigned)(at-data))); UNPACK_ERROR (("unsupported group tag at offset %u", (unsigned)(at-data)));
goto error_cleanup; goto error_cleanup_during_scan;
case PROTOBUF_C_WIRE_TYPE_32BIT: case PROTOBUF_C_WIRE_TYPE_32BIT:
if (rem < 4) if (rem < 4)
{ {
UNPACK_ERROR (("too short after 32bit wiretype at offset %u", UNPACK_ERROR (("too short after 32bit wiretype at offset %u",
(unsigned)(at-data))); (unsigned)(at-data)));
goto error_cleanup; goto error_cleanup_during_scan;
} }
tmp.len = 4; tmp.len = 4;
break; break;
@ -1505,7 +1505,7 @@ protobuf_c_message_unpack (const ProtobufCMessageDescriptor *desc,
if (allocator->tmp_alloc != NULL) if (allocator->tmp_alloc != NULL)
scanned_member_slabs[which_slab] = TMPALLOC(allocator, size); scanned_member_slabs[which_slab] = TMPALLOC(allocator, size);
else else
DO_ALLOC (scanned_member_slabs[which_slab], allocator, size, goto error_cleanup); DO_ALLOC (scanned_member_slabs[which_slab], allocator, size, goto error_cleanup_during_scan);
} }
scanned_member_slabs[which_slab][in_slab_index++] = tmp; scanned_member_slabs[which_slab][in_slab_index++] = tmp;
@ -1530,8 +1530,17 @@ protobuf_c_message_unpack (const ProtobufCMessageDescriptor *desc,
{ {
unsigned n = *n_ptr; unsigned n = *n_ptr;
*n_ptr = 0; *n_ptr = 0;
assert(rv->descriptor != NULL);
DO_ALLOC (STRUCT_MEMBER (void *, rv, field->offset), DO_ALLOC (STRUCT_MEMBER (void *, rv, field->offset),
allocator, siz * n, allocator, siz * n,
for(f++;f < desc->n_fields; f++) {
field = desc->fields + f;
if (field->label == PROTOBUF_C_LABEL_REPEATED)
{
n_ptr = STRUCT_MEMBER_PTR (size_t, rv, field->quantifier_offset);
*n_ptr = 0;
}
}
goto error_cleanup); goto error_cleanup);
} }
} }
@ -1555,7 +1564,7 @@ protobuf_c_message_unpack (const ProtobufCMessageDescriptor *desc,
if (!parse_member (slab + j, rv, allocator)) if (!parse_member (slab + j, rv, allocator))
{ {
UNPACK_ERROR (("error parsing member %s of %s", UNPACK_ERROR (("error parsing member %s of %s",
slab->field->name, desc->name)); slab->field ? slab->field->name : "*unknown-field*", desc->name));
goto error_cleanup; goto error_cleanup;
} }
} }
@ -1580,6 +1589,16 @@ error_cleanup:
FREE (allocator, scanned_member_slabs[j]); FREE (allocator, scanned_member_slabs[j]);
} }
return NULL; return NULL;
error_cleanup_during_scan:
FREE (allocator, rv);
if (allocator->tmp_alloc == NULL)
{
unsigned j;
for (j = 1; j <= which_slab; j++)
FREE (allocator, scanned_member_slabs[j]);
}
return NULL;
} }
/* === free_unpacked === */ /* === free_unpacked === */