Skip to content

Commit e8923a8

Browse files
Add conformance tests for utf8 validation.
PiperOrigin-RevId: 858895922
1 parent e0d114c commit e8923a8

20 files changed

+232
-28
lines changed

conformance/binary_json_conformance_suite.cc

Lines changed: 60 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -318,8 +318,11 @@ void BinaryAndJsonConformanceSuite::RunSuiteImpl() {
318318
this, /*run_proto3_tests=*/true);
319319
BinaryAndJsonConformanceSuiteImpl<TestAllTypesProto2Editions>(
320320
this, /*run_proto3_tests=*/false);
321-
RunDelimitedFieldTests();
322-
RunUnstableTests();
321+
if (!this->performance_) {
322+
RunDelimitedFieldTests();
323+
RunUnstableTests();
324+
RunUtf8ValidationTests();
325+
}
323326
}
324327
}
325328

@@ -389,6 +392,18 @@ void BinaryAndJsonConformanceSuite::RunUnstableTests() {
389392
R"pb(map_string_bytes { key: "foo" value: "barbaz" })pb");
390393
}
391394

395+
void BinaryAndJsonConformanceSuite::RunUtf8ValidationTests() {
396+
ExpectParseFailureForProto<TestAllTypesEdition2023>(
397+
len(133, "\xA0\xB0\xC0\xD0"), "RejectInvalidUtf8.String.Extension",
398+
RECOMMENDED);
399+
RunValidBinaryProtobufTest<
400+
TestAllTypesEdition2023>(absl::StrCat(
401+
"AcceptInvalidUtf8.Bytes.Extension"),
402+
REQUIRED, len(134, "\xA0\xB0\xC0\xD0"),
403+
R"pb([protobuf_test_messages.editions
404+
.extension_bytes]: "\xA0\xB0\xC0\xD0")pb");
405+
}
406+
392407
void BinaryAndJsonConformanceSuite::RunMessageSetTests() {
393408
RunValidBinaryProtobufTest<TestAllTypesProto2>(
394409
absl::StrCat("ValidMessageSetEncoding"), REQUIRED,
@@ -476,10 +491,9 @@ void BinaryAndJsonConformanceSuite::RunMessageSetTests() {
476491
}
477492

478493
template <typename MessageType>
479-
void BinaryAndJsonConformanceSuiteImpl<MessageType>::
480-
ExpectParseFailureForProtoWithProtoVersion(const std::string& proto,
481-
const std::string& test_name,
482-
ConformanceLevel level) {
494+
void BinaryAndJsonConformanceSuite::ExpectParseFailureForProto(
495+
const std::string& proto, const std::string& test_name,
496+
ConformanceLevel level) {
483497
MessageType prototype;
484498
// We don't expect output, but if the program erroneously accepts the protobuf
485499
// we let it send its response as this. We must not leave it unspecified.
@@ -493,22 +507,34 @@ void BinaryAndJsonConformanceSuiteImpl<MessageType>::
493507
absl::StrCat(setting.ConformanceLevelToString(level), ".",
494508
setting.GetSyntaxIdentifier(), ".ProtobufInput.", test_name);
495509

496-
if (!suite_.RunTest(effective_test_name, request, &response)) {
510+
if (!RunTest(effective_test_name, request, &response)) {
497511
return;
498512
}
499513

500514
TestStatus test;
501515
test.set_name(effective_test_name);
502516
if (response.result_case() == ConformanceResponse::kParseError) {
503-
suite_.ReportSuccess(test);
517+
ReportSuccess(test);
504518
} else if (response.result_case() == ConformanceResponse::kSkipped) {
505-
suite_.ReportSkip(test, request, response);
519+
ReportSkip(test, request, response);
520+
} else if (response.result_case() == ConformanceResponse::kRuntimeError) {
521+
test.set_failure_message(
522+
"Should have failed to parse, but raised an error instead.");
523+
ReportFailure(test, level, request, response);
506524
} else {
507525
test.set_failure_message("Should have failed to parse, but didn't.");
508-
suite_.ReportFailure(test, level, request, response);
526+
ReportFailure(test, level, request, response);
509527
}
510528
}
511529

530+
template <typename MessageType>
531+
void BinaryAndJsonConformanceSuiteImpl<MessageType>::
532+
ExpectParseFailureForProtoWithProtoVersion(const std::string& proto,
533+
const std::string& test_name,
534+
ConformanceLevel level) {
535+
suite_.ExpectParseFailureForProto<MessageType>(proto, test_name, level);
536+
}
537+
512538
// Expect that this precise protobuf will cause a parse error.
513539
template <typename MessageType>
514540
void BinaryAndJsonConformanceSuiteImpl<MessageType>::ExpectParseFailureForProto(
@@ -1531,6 +1557,29 @@ void BinaryAndJsonConformanceSuiteImpl<MessageType>::TestUnknownWireType() {
15311557
}
15321558
}
15331559

1560+
template <typename MessageType>
1561+
void BinaryAndJsonConformanceSuiteImpl<MessageType>::TestInvalidUtf8String() {
1562+
if (run_proto3_tests_) {
1563+
ExpectParseFailureForProto(len(14, "\xA0\xB0\xC0\xD0"),
1564+
"RejectInvalidUtf8.String.Singular",
1565+
RECOMMENDED);
1566+
ExpectParseFailureForProto(len(44, "\xA0\xB0\xC0\xD0"),
1567+
"RejectInvalidUtf8.String.Repeated",
1568+
RECOMMENDED);
1569+
ExpectParseFailureForProto(len(113, "\xA0\xB0\xC0\xD0"),
1570+
"RejectInvalidUtf8.String.Oneof", RECOMMENDED);
1571+
ExpectParseFailureForProto(
1572+
len(69, absl::StrCat(len(1, "\xA0\xB0\xC0\xD0"), len(2, "foo"))),
1573+
"RejectInvalidUtf8.String.MapKey", RECOMMENDED);
1574+
ExpectParseFailureForProto(
1575+
len(69, absl::StrCat(len(1, "foo"), len(2, "\xA0\xB0\xC0\xD0"))),
1576+
"RejectInvalidUtf8.String.MapValue", RECOMMENDED);
1577+
} else {
1578+
// TODO - Once conformance tests can express failures that are
1579+
// not expected to be fixed, add proto2 coverage here.
1580+
}
1581+
}
1582+
15341583
template <typename MessageType>
15351584
void BinaryAndJsonConformanceSuiteImpl<MessageType>::TestOneofMessage() {
15361585
MessageType message;
@@ -1702,6 +1751,7 @@ void BinaryAndJsonConformanceSuiteImpl<MessageType>::RunAllTests() {
17021751
TestIllegalTags();
17031752
TestUnmatchedGroup();
17041753
TestUnknownWireType();
1754+
TestInvalidUtf8String();
17051755

17061756
int64_t kInt64Min = -9223372036854775808ULL;
17071757
int64_t kInt64Max = 9223372036854775807ULL;

conformance/binary_json_conformance_suite.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,17 @@ class BinaryAndJsonConformanceSuite : public ConformanceTestSuite {
5555
const std::string& input_protobuf,
5656
const std::string& equivalent_text_format);
5757

58+
template <typename MessageType>
59+
void ExpectParseFailureForProto(const std::string& proto,
60+
const std::string& test_name,
61+
ConformanceLevel level);
62+
5863
void RunDelimitedFieldTests();
5964

6065
void RunUnstableTests();
6166

67+
void RunUtf8ValidationTests();
68+
6269
void RunMessageSetTests();
6370

6471
template <typename MessageType>
@@ -154,6 +161,7 @@ class BinaryAndJsonConformanceSuiteImpl {
154161
void TestIllegalTags();
155162
void TestUnmatchedGroup();
156163
void TestUnknownWireType();
164+
void TestInvalidUtf8String();
157165
void TestOneofMessage();
158166
void TestUnknownMessage();
159167
void TestUnknownOrdering();

conformance/failure_list_cpp.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,15 @@ Recommended.*.JsonInput.FieldMaskInvalidCharacter
3535
Required.*.JsonInput.SingleValueForRepeatedFieldInt32 # Should have failed to parse, but didn't.
3636
Required.*.JsonInput.SingleValueForRepeatedFieldMessage # Should have failed to parse, but didn't.
3737
Required.*.ProtobufInput.BadTag_FieldNumberSlightlyTooHigh # Should have failed to parse, but didn't.
38+
Recommended.Editions.ProtobufInput.RejectInvalidUtf8.String.Extension # Should have failed to parse, but didn't.
39+
# TODO: Uncomment once conformance tests can express failures that are not expected to be fixed.
40+
# Recommended.Editions_Proto2.ProtobufInput.RejectInvalidUtf8.String.MapKey # Should have failed to parse, but didn't.
41+
# Recommended.Editions_Proto2.ProtobufInput.RejectInvalidUtf8.String.MapValue # Should have failed to parse, but didn't.
42+
# Recommended.Editions_Proto2.ProtobufInput.RejectInvalidUtf8.String.Oneof # Should have failed to parse, but didn't.
43+
# Recommended.Editions_Proto2.ProtobufInput.RejectInvalidUtf8.String.Repeated # Should have failed to parse, but didn't.
44+
# Recommended.Editions_Proto2.ProtobufInput.RejectInvalidUtf8.String.Singular # Should have failed to parse, but didn't.
45+
# Recommended.Proto2.ProtobufInput.RejectInvalidUtf8.String.MapKey # Should have failed to parse, but didn't.
46+
# Recommended.Proto2.ProtobufInput.RejectInvalidUtf8.String.MapValue # Should have failed to parse, but didn't.
47+
# Recommended.Proto2.ProtobufInput.RejectInvalidUtf8.String.Oneof # Should have failed to parse, but didn't.
48+
# Recommended.Proto2.ProtobufInput.RejectInvalidUtf8.String.Repeated # Should have failed to parse, but didn't.
49+
# Recommended.Proto2.ProtobufInput.RejectInvalidUtf8.String.Singular # Should have failed to parse, but didn't.

conformance/failure_list_csharp.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Recommended.Editions_Proto3.ValueRejectInfNumberValue.JsonOutput
3636
Recommended.Editions_Proto3.ValueRejectNanNumberValue.JsonOutput
3737
Required.Editions_Proto2.ProtobufInput.UnknownOrdering.ProtobufOutput
3838
Required.Editions_Proto3.ProtobufInput.UnknownOrdering.ProtobufOutput
39-
39+
Recommended.Editions.ProtobufInput.RejectInvalidUtf8.String.Extension # Should have failed to parse, but didn't.
4040
Required.*.ProtobufInput.BadTag_FieldNumberTooHigh # Should have failed to parse, but didn't.
4141
Required.*.ProtobufInput.BadTag_FieldNumberSlightlyTooHigh # Should have failed to parse, but didn't.
4242
Required.*.ProtobufInput.BadTag_OverlongVarint # Should have failed to parse, but didn't.

conformance/failure_list_java.txt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,11 @@ Required.*.JsonInput.StringFieldNotAString
4545
Required.*.ProtobufInput.UnknownOrdering.ProtobufOutput # Unknown field mismatch
4646
Required.*.ProtobufInput.BadTag_FieldNumberTooHigh # Should have failed to parse, but didn't.
4747
Required.*.ProtobufInput.BadTag_FieldNumberSlightlyTooHigh # Should have failed to parse, but didn't.
48-
Required.*.ProtobufInput.BadTag_OverlongVarint # Should have failed to parse, but didn't.
48+
Required.*.ProtobufInput.BadTag_OverlongVarint # Should have failed to parse, but didn't.
49+
# TODO: Uncomment once conformance tests can express failures that are not expected to be fixed.
50+
# Recommended.Editions_Proto2.ProtobufInput.RejectInvalidUtf8.String.Oneof # Should have failed to parse, but didn't.
51+
# Recommended.Editions_Proto2.ProtobufInput.RejectInvalidUtf8.String.Repeated # Should have failed to parse, but didn't.
52+
# Recommended.Editions_Proto2.ProtobufInput.RejectInvalidUtf8.String.Singular # Should have failed to parse, but didn't.
53+
# Recommended.Proto2.ProtobufInput.RejectInvalidUtf8.String.Oneof # Should have failed to parse, but didn't.
54+
# Recommended.Proto2.ProtobufInput.RejectInvalidUtf8.String.Repeated # Should have failed to parse, but didn't.
55+
# Recommended.Proto2.ProtobufInput.RejectInvalidUtf8.String.Singular # Should have failed to parse, but didn't.

conformance/failure_list_java_lite.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,11 @@ Required.*.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAG
99
Required.*.ProtobufInput.BadTag_FieldNumberTooHigh # Should have failed to parse, but didn't.
1010
Required.*.ProtobufInput.BadTag_FieldNumberSlightlyTooHigh # Should have failed to parse, but didn't.
1111
Required.*.ProtobufInput.BadTag_OverlongVarint # Should have failed to parse, but didn't.
12+
Recommended.Editions.ProtobufInput.RejectInvalidUtf8.String.Extension # Should have failed to parse, but didn't.
13+
# TODO: Uncomment once conformance tests can express failures that are not expected to be fixed.
14+
# Recommended.Editions_Proto2.ProtobufInput.RejectInvalidUtf8.String.Oneof # Should have failed to parse, but didn't.
15+
# Recommended.Editions_Proto2.ProtobufInput.RejectInvalidUtf8.String.Repeated # Should have failed to parse, but didn't.
16+
# Recommended.Editions_Proto2.ProtobufInput.RejectInvalidUtf8.String.Singular # Should have failed to parse, but didn't.
17+
# Recommended.Proto2.ProtobufInput.RejectInvalidUtf8.String.Oneof # Should have failed to parse, but didn't.
18+
# Recommended.Proto2.ProtobufInput.RejectInvalidUtf8.String.Repeated # Should have failed to parse, but didn't.
19+
# Recommended.Proto2.ProtobufInput.RejectInvalidUtf8.String.Singular # Should have failed to parse, but didn't.

conformance/failure_list_jruby.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,10 @@ Required.Proto3.ProtobufInput.UnknownOrdering.ProtobufOutput
147147
Required.*.ProtobufInput.BadTag_FieldNumberTooHigh # Should have failed to parse, but didn't.
148148
Required.*.ProtobufInput.BadTag_FieldNumberSlightlyTooHigh # Should have failed to parse, but didn't.
149149
Required.*.ProtobufInput.BadTag_OverlongVarint # Should have failed to parse, but didn't.
150+
# TODO: Uncomment once conformance tests can express failures that are not expected to be fixed.
151+
# Recommended.Editions_Proto2.ProtobufInput.RejectInvalidUtf8.String.Oneof # Should have failed to parse, but didn't.
152+
# Recommended.Editions_Proto2.ProtobufInput.RejectInvalidUtf8.String.Repeated # Should have failed to parse, but didn't.
153+
# Recommended.Editions_Proto2.ProtobufInput.RejectInvalidUtf8.String.Singular # Should have failed to parse, but didn't.
154+
# Recommended.Proto2.ProtobufInput.RejectInvalidUtf8.String.Oneof # Should have failed to parse, but didn't.
155+
# Recommended.Proto2.ProtobufInput.RejectInvalidUtf8.String.Repeated # Should have failed to parse, but didn't.
156+
# Recommended.Proto2.ProtobufInput.RejectInvalidUtf8.String.Singular # Should have failed to parse, but didn't.
Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
1-
Recommended.*.JsonInput.FieldNameDuplicate # Should have failed to parse, but didn't.
2-
Recommended.*.JsonInput.FieldNameDuplicateDifferentCasing1 # Should have failed to parse, but didn't.
3-
Recommended.*.JsonInput.FieldNameDuplicateDifferentCasing2 # Should have failed to parse, but didn't.
4-
Required.*.JsonInput.Int32FieldQuotedExponentialValue.* # Failed to parse input or produce output.
5-
Required.*.JsonInput.AnyWithNoType.* # Failed to parse input or produce output.
1+
Recommended.*.JsonInput.FieldNameDuplicate # Should have failed to parse, but didn't.
2+
Recommended.*.JsonInput.FieldNameDuplicateDifferentCasing1 # Should have failed to parse, but didn't.
3+
Recommended.*.JsonInput.FieldNameDuplicateDifferentCasing2 # Should have failed to parse, but didn't.
4+
Required.*.JsonInput.Int32FieldQuotedExponentialValue.* # Failed to parse input or produce output.
5+
Required.*.JsonInput.AnyWithNoType.* # Failed to parse input or produce output.
6+
# TODO: Uncomment once conformance tests can express failures that are not expected to be fixed.
7+
# Recommended.Editions_Proto2.ProtobufInput.RejectInvalidUtf8.String.MapKey # Should have failed to parse, but didn't.
8+
# Recommended.Editions_Proto2.ProtobufInput.RejectInvalidUtf8.String.MapValue # Should have failed to parse, but didn't.
9+
# Recommended.Editions_Proto2.ProtobufInput.RejectInvalidUtf8.String.Oneof # Should have failed to parse, but didn't.
10+
# Recommended.Editions_Proto2.ProtobufInput.RejectInvalidUtf8.String.Repeated # Should have failed to parse, but didn't.
11+
# Recommended.Editions_Proto2.ProtobufInput.RejectInvalidUtf8.String.Singular # Should have failed to parse, but didn't.
12+
# Recommended.Proto2.ProtobufInput.RejectInvalidUtf8.String.MapKey # Should have failed to parse, but didn't.
13+
# Recommended.Proto2.ProtobufInput.RejectInvalidUtf8.String.MapValue # Should have failed to parse, but didn't.
14+
# Recommended.Proto2.ProtobufInput.RejectInvalidUtf8.String.Oneof # Should have failed to parse, but didn't.
15+
# Recommended.Proto2.ProtobufInput.RejectInvalidUtf8.String.Repeated # Should have failed to parse, but didn't.
16+
# Recommended.Proto2.ProtobufInput.RejectInvalidUtf8.String.Singular # Should have failed to parse, but didn't.

0 commit comments

Comments
 (0)