@ -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<const upb::MessageDef> 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 < upb : : EnumDef > e = upb : : EnumDef : : New ( ) ;
ASSERT ( e - > AddValue ( " FOO " , 1 , NULL ) ) ;
ASSERT ( e - > Freeze ( NULL ) ) ;
@ -492,6 +517,8 @@ upb::reffed_ptr<const upb::Handlers> 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 ( " < " )