@@ -1157,20 +1157,39 @@ PROTOBUF_ALWAYS_INLINE const char* TcParser::RepeatedVarint(
11571157 }
11581158 SetCachedHasBitForRepeated (hasbits, data.hasbit_idx ());
11591159 auto & field = RefAt<RepeatedField<FieldType>>(msg, data.offset ());
1160- Arena* arena = msg->GetArena ();
11611160 const auto expected_tag = UnalignedLoad<TagType>(ptr);
1161+ // Count the number of varint (same as number of bytes with 0 in top bit)
1162+ // and preallocte space in repeated field.
1163+ int len = 0 ;
1164+ auto ptr2 = ptr;
1165+ do {
1166+ ptr2 += sizeof (TagType);
1167+ // Defend against overflowing avaible data due to malformed input of
1168+ // infinite number of bytes with top bit set. Longest legal varin is 10
1169+ // bytes, which is also < 16 bytes of slop.
1170+ int limit = 10 ;
1171+ while ((*ptr2 & 0x80 ) && limit--) ptr2++;
1172+ len++;
1173+ ptr2++;
1174+ if (ABSL_PREDICT_FALSE (!ctx->DataAvailable (ptr2))) break ;
1175+ } while (UnalignedLoadNoPrefetch<TagType>(ptr2) == expected_tag);
1176+ int added = 0 ;
1177+ field.Reserve (field.size () + len);
1178+ // Allows us to skip SOO checks.
1179+ FieldType* x = field.AddNAlreadyReserved (len);
11621180 do {
1181+ ABSL_DCHECK (ctx->DataAvailable (ptr));
1182+ ABSL_DCHECK_EQ (UnalignedLoadNoPrefetch<TagType>(ptr), expected_tag);
11631183 ptr += sizeof (TagType);
11641184 FieldType tmp;
11651185 ptr = ParseVarint (ptr, &tmp);
11661186 if (ABSL_PREDICT_FALSE (ptr == nullptr )) {
11671187 PROTOBUF_MUSTTAIL return Error (PROTOBUF_TC_PARAM_NO_DATA_PASS);
11681188 }
1169- field.AddWithArena (arena, ZigZagDecodeHelper<FieldType, zigzag>(tmp));
1170- if (ABSL_PREDICT_FALSE (!ctx->DataAvailable (ptr))) {
1171- PROTOBUF_MUSTTAIL return ToParseLoop (PROTOBUF_TC_PARAM_NO_DATA_PASS);
1172- }
1173- } while (UnalignedLoad<TagType>(ptr) == expected_tag);
1189+ added++;
1190+ *x = (ZigZagDecodeHelper<FieldType, zigzag>(tmp));
1191+ x++;
1192+ } while (added < len);
11741193 PROTOBUF_MUSTTAIL return ToTagDispatch (PROTOBUF_TC_PARAM_NO_DATA_PASS);
11751194}
11761195
0 commit comments