From 85440108e502b6f58671fcfc4b84103d1a716253 Mon Sep 17 00:00:00 2001 From: Josh Haberman Date: Tue, 11 Aug 2015 17:46:31 -0700 Subject: More decoder fixes, and slightly changed parse call semantics. Prior to this change, if an error was returned, it would be guaranteed to always return a short byte count. Now the two concepts are a bit more orthogonal. There are cases where the entire input is consumed even though an error was encountered. --- tests/pb/test_decoder.cc | 48 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) (limited to 'tests/pb/test_decoder.cc') diff --git a/tests/pb/test_decoder.cc b/tests/pb/test_decoder.cc index 78dd7dc..fd9d9ae 100644 --- a/tests/pb/test_decoder.cc +++ b/tests/pb/test_decoder.cc @@ -202,6 +202,16 @@ string submsg(uint32_t fn, const string& buf) { return cat( tag(fn, UPB_WIRE_TYPE_DELIMITED), delim(buf) ); } +// Like delim()/submsg(), but intentionally encodes an incorrect length. +// These help test when a delimited boundary doesn't land in the right place. +string badlen_delim(int err, const string& buf) { + return cat(varint(buf.size() + err), buf); +} + +string badlen_submsg(int err, uint32_t fn, const string& buf) { + return cat( tag(fn, UPB_WIRE_TYPE_DELIMITED), badlen_delim(err, buf) ); +} + /* A set of handlers that covers all .proto types *****************************/ @@ -436,6 +446,21 @@ upb::reffed_ptr NewMessageDef() { ASSERT(f->set_message_subdef(md.get(), NULL)); ASSERT(md->AddField(f.get(), NULL)); + f = upb::FieldDef::New(); + ASSERT(f->set_name("f_group", NULL)); + ASSERT(f->set_number(UPB_DESCRIPTOR_TYPE_GROUP, NULL)); + f->set_descriptor_type(UPB_DESCRIPTOR_TYPE_GROUP); + ASSERT(f->set_message_subdef(md.get(), NULL)); + ASSERT(md->AddField(f.get(), NULL)); + + f = upb::FieldDef::New(); + ASSERT(f->set_name("r_group", NULL)); + ASSERT(f->set_number(rep_fn(UPB_DESCRIPTOR_TYPE_GROUP), NULL)); + f->set_label(UPB_LABEL_REPEATED); + f->set_descriptor_type(UPB_DESCRIPTOR_TYPE_GROUP); + ASSERT(f->set_message_subdef(md.get(), NULL)); + ASSERT(md->AddField(f.get(), NULL)); + upb::reffed_ptr e = upb::EnumDef::New(); ASSERT(e->AddValue("FOO", 1, NULL)); ASSERT(e->Freeze(NULL)); @@ -492,6 +517,8 @@ upb::reffed_ptr NewHandlers(TestMode mode) { // to this type, eg: message M { optional M m = 1; } reg_subm(h.get(), UPB_DESCRIPTOR_TYPE_MESSAGE); reg_subm(h.get(), rep_fn(UPB_DESCRIPTOR_TYPE_MESSAGE)); + reg_subm(h.get(), UPB_DESCRIPTOR_TYPE_GROUP); + reg_subm(h.get(), rep_fn(UPB_DESCRIPTOR_TYPE_GROUP)); // For NOP_FIELD we register no handlers, so we can pad a proto freely without // changing the output. @@ -645,6 +672,12 @@ void assert_successful_parse(const string& proto, void assert_does_not_parse_at_eof(const string& proto) { run_decoder(proto, NULL); + + // Also test that we fail to parse at end-of-submessage, not just + // end-of-message. + run_decoder(submsg(UPB_DESCRIPTOR_TYPE_MESSAGE, proto), NULL); + run_decoder(cat(submsg(UPB_DESCRIPTOR_TYPE_MESSAGE, proto), thirty_byte_nop), + NULL); } void assert_does_not_parse(const string& proto) { @@ -859,6 +892,18 @@ void test_invalid() { tag(UPB_DESCRIPTOR_TYPE_GROUP, UPB_WIRE_TYPE_START_GROUP)), tag(UPB_DESCRIPTOR_TYPE_GROUP, UPB_WIRE_TYPE_END_GROUP))); + // Unknown string extends past enclosing submessage. + assert_does_not_parse( + cat (badlen_submsg(-1, UPB_DESCRIPTOR_TYPE_MESSAGE, + submsg(12345, string(" "))), + submsg(UPB_DESCRIPTOR_TYPE_MESSAGE, string(" ")))); + + // Unknown fixed-length field extends past enclosing submessage. + assert_does_not_parse( + cat (badlen_submsg(-1, UPB_DESCRIPTOR_TYPE_MESSAGE, + cat( tag(12345, UPB_WIRE_TYPE_64BIT), uint64(0))), + submsg(UPB_DESCRIPTOR_TYPE_MESSAGE, string(" ")))); + // Test exceeding the resource limit of stack depth. string buf; for (int i = 0; i <= MAX_NESTING; i++) { @@ -942,8 +987,7 @@ void test_valid() { // Unknown field inside a known submessage. assert_successful_parse( - cat (submsg(UPB_DESCRIPTOR_TYPE_MESSAGE, - submsg(12345, string(" "))), + cat (submsg(UPB_DESCRIPTOR_TYPE_MESSAGE, submsg(12345, string(" "))), tag(UPB_DESCRIPTOR_TYPE_INT32, UPB_WIRE_TYPE_VARINT), varint(5)), LINE("<") -- cgit v1.2.3