diff --git a/e2e_tests/testdata/fuzz_tests_with_proto_inputs.cc b/e2e_tests/testdata/fuzz_tests_with_proto_inputs.cc index fb780b4c5..ce0553543 100644 --- a/e2e_tests/testdata/fuzz_tests_with_proto_inputs.cc +++ b/e2e_tests/testdata/fuzz_tests_with_proto_inputs.cc @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include #include #include #include @@ -24,11 +25,24 @@ namespace { using fuzztest::internal::CalculatorExpression; using fuzztest::internal::FoodMachineProcedure; using fuzztest::internal::RoboCourier560Plan; +using fuzztest::internal::SingleBytesField; using fuzztest::internal::TestProtobuf; -void BytesSummingToMagicValueWithOverloadedProto(const TestProtobuf& input) { +void BytesSummingToMagicValue(const SingleBytesField& input) { char sum = 0; - for (const char c : input.str()) { + for (const char c : input.data()) { + sum += c; + } + if (sum == 0x72) { + std::abort(); + } +} +FUZZ_TEST(ProtoPuzzles, BytesSummingToMagicValue); + +void BytesSummingToMagicValueWithOverloadedProto( + const SingleBytesField& input) { + char sum = 0; + for (const char c : input.data()) { sum += c; } if (sum == 0x72) { @@ -37,6 +51,16 @@ void BytesSummingToMagicValueWithOverloadedProto(const TestProtobuf& input) { } FUZZ_TEST(ProtoPuzzles, BytesSummingToMagicValueWithOverloadedProto); +void PrefixBytesSummingToMagicValue(const SingleBytesField& input) { + if (input.data().size() < 2) { + return; + } + if (input.data()[0] + input.data()[1] == 0x72) { + std::abort(); + } +} +FUZZ_TEST(ProtoPuzzles, PrefixBytesSummingToMagicValue); + void PrefixBytesSummingToMagicValueWithOverloadedProto( const TestProtobuf& input) { if (input.str().size() < 2) { @@ -48,6 +72,16 @@ void PrefixBytesSummingToMagicValueWithOverloadedProto( } FUZZ_TEST(ProtoPuzzles, PrefixBytesSummingToMagicValueWithOverloadedProto); +void PrefixIsMagicValue(const SingleBytesField& input) { + if (input.data().size() < 2) { + return; + } + if (input.data()[0] + input.data()[1] == 0x72) { + std::abort(); + } +} +FUZZ_TEST(ProtoPuzzles, PrefixIsMagicValue); + void PrefixIsMagicValueWithOverloadedProto(const TestProtobuf& input) { if (input.str().size() < 2) { return; @@ -58,6 +92,29 @@ void PrefixIsMagicValueWithOverloadedProto(const TestProtobuf& input) { } FUZZ_TEST(ProtoPuzzles, PrefixIsMagicValueWithOverloadedProto); +void ContainsCharactersSpecifiedAtStartOfString(const SingleBytesField& input) { + if (input.data().size() < 2) { + return; + } + char quantity = input.data()[0]; + char to_find = input.data()[1]; + + if (to_find == 0) { + return; + } + + char num_found = 0; + for (int i = 2; i < input.data().size(); ++i) { + if (input.data()[i] == to_find) { + num_found++; + } + } + if (num_found == quantity) { + abort(); + } +} +FUZZ_TEST(ProtoPuzzles, ContainsCharactersSpecifiedAtStartOfString); + void ContainsCharactersSpecifiedAtStartOfStringWithOverloadedProto( const TestProtobuf& input) { if (input.str().size() < 2) { @@ -248,4 +305,133 @@ void RunRoboCourier560(const RoboCourier560Plan& plan) { } FUZZ_TEST(ProtoPuzzles, RunRoboCourier560); +void IntegerConditionsOnTestProtobufLevel00(const TestProtobuf& input) { + int64_t integer_result; + if (input.b()) { + if (__builtin_add_overflow(input.i32(), input.i64(), &integer_result)) { + return; // [Hint] Overflow detected + } + } else { + if (__builtin_sub_overflow(input.i32(), input.i64(), &integer_result)) { + return; // [Hint] Overflow detected + } + } + if (integer_result < 1239291904) { + return; + } + + if (input.rep_b().empty()) { + return; + } + uint64_t unsigned_result; + if (input.rep_b()[0]) { + unsigned_result = input.u32() + input.u64() + input.rep_b()[0]; + } else { + unsigned_result = input.u32() - input.u64() - input.rep_b()[0]; + } + if (unsigned_result != 2000) { + return; + } + // [Hint] Reachable if all of the early returns above are not taken. + std::abort(); +} +FUZZ_TEST(ProtoPuzzles, IntegerConditionsOnTestProtobufLevel00); + +void IntegerConditionsOnTestProtobufLevel01(const TestProtobuf& input) { + int64_t integer_result; + if (input.b()) { + if (__builtin_add_overflow(input.i32(), input.i64(), &integer_result)) { + return; // [Hint] Overflow detected + } + } else { + if (__builtin_sub_overflow(input.i32(), input.i64(), &integer_result)) { + return; // [Hint] Overflow detected + } + } + if (integer_result < 1239291904) { + return; + } + + if (input.rep_b().empty()) { + return; + } + if (input.rep_b().size() < 5) { + return; + } + bool flip = false; + uint32_t num_trues = 0; + for (const bool& b : input.rep_b()) { + flip += b; + num_trues += b; + } + uint64_t unsigned_result; + if (flip) { + unsigned_result = input.u32() + input.u64() + num_trues; + } else { + unsigned_result = input.u32() - input.u64() + num_trues; + } + if (unsigned_result != 2000) { + return; + } + // [Hint] reachable if none of the early returns above are taken. + std::abort(); +} +FUZZ_TEST(ProtoPuzzles, IntegerConditionsOnTestProtobufLevel01); + +void IntegerConditionsOnTestProtobufLevel02(const TestProtobuf& input) { + int64_t integer_result; + if (input.b()) { + if (__builtin_add_overflow(input.i32(), input.i64(), &integer_result)) { + return; // [Hint] Overflow detected + } + } else { + if (__builtin_sub_overflow(input.i32(), input.i64(), &integer_result)) { + return; // [Hint] Overflow detected + } + } + if (integer_result < 1239291904) { + return; + } + + if (input.rep_b().empty()) { + return; + } + if (input.rep_b().size() < 5) { + return; + } + bool flip = false; + uint32_t num_trues = 0; + for (const bool& b : input.rep_b()) { + flip += b; + num_trues += b; + } + uint64_t unsigned_result; + if (flip) { + unsigned_result = input.u32() + input.u64() + num_trues; + } else { + unsigned_result = input.u32() - input.u64() + num_trues; + } + if (unsigned_result != 2000) { + return; + } + + uint64_t rep_u32_result = 0; + if (input.rep_u32().size() < 10) { + return; + } + for (int i = 0; i < input.rep_u32().size(); ++i) { + if (input.rep_b()[i % input.rep_b().size()]) { + rep_u32_result += input.rep_u32()[i]; + } else { + rep_u32_result -= input.rep_u32()[i]; + } + } + if (rep_u32_result < 65377) { + return; + } + // [Hint] Can happen if none of the early returns above are taken. + std::abort(); +} +FUZZ_TEST(ProtoPuzzles, IntegerConditionsOnTestProtobufLevel02); + } // namespace diff --git a/fuzztest/internal/test_protobuf.proto b/fuzztest/internal/test_protobuf.proto index adc3a90c9..d36871bdc 100644 --- a/fuzztest/internal/test_protobuf.proto +++ b/fuzztest/internal/test_protobuf.proto @@ -23,6 +23,10 @@ enum BareEnum { LABEL_OTHER = 10; } +message SingleBytesField { + optional bytes data = 1; +} + message TestSubProtobuf { optional int32 subproto_i32 = 1; repeated int32 subproto_rep_i32 = 2 [packed = true];