mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Add antlr4 visitor based pragma and import directive mutators
Co-authored-by: Kamil Śliwak <kamil.sliwak@codepoets.it>
This commit is contained in:
parent
95a284e526
commit
af14b8d425
@ -83,7 +83,9 @@ defaults:
|
||||
paths:
|
||||
- test/tools/ossfuzz/abiv2_proto_ossfuzz
|
||||
- test/tools/ossfuzz/const_opt_ossfuzz
|
||||
- test/tools/ossfuzz/solc_noopt_mutator_ossfuzz
|
||||
- test/tools/ossfuzz/solc_noopt_ossfuzz
|
||||
- test/tools/ossfuzz/solc_opt_mutator_ossfuzz
|
||||
- test/tools/ossfuzz/solc_opt_ossfuzz
|
||||
- test/tools/ossfuzz/strictasm_assembly_ossfuzz
|
||||
- test/tools/ossfuzz/strictasm_diff_ossfuzz
|
||||
|
@ -1,12 +1,14 @@
|
||||
add_custom_target(ossfuzz)
|
||||
add_dependencies(ossfuzz
|
||||
solc_opt_ossfuzz
|
||||
solc_opt_mutator_ossfuzz
|
||||
solc_noopt_ossfuzz
|
||||
solc_noopt_mutator_ossfuzz
|
||||
const_opt_ossfuzz
|
||||
strictasm_diff_ossfuzz
|
||||
strictasm_opt_ossfuzz
|
||||
strictasm_assembly_ossfuzz
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
if (OSSFUZZ)
|
||||
@ -27,31 +29,51 @@ if (OSSFUZZ)
|
||||
solc_opt_ossfuzz.cpp
|
||||
../fuzzer_common.cpp
|
||||
../../TestCaseReader.cpp
|
||||
)
|
||||
target_link_libraries(solc_opt_ossfuzz PRIVATE libsolc evmasm)
|
||||
set_target_properties(solc_opt_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE})
|
||||
|
||||
add_executable(solc_opt_mutator_ossfuzz
|
||||
solc_opt_ossfuzz.cpp
|
||||
../fuzzer_common.cpp
|
||||
../../TestCaseReader.cpp
|
||||
SolidityLexer.cpp
|
||||
SolidityParser.cpp
|
||||
SolidityMutator.cpp
|
||||
SolidityCustomMutatorInterface.cpp
|
||||
)
|
||||
target_compile_options(solc_opt_ossfuzz
|
||||
target_compile_options(solc_opt_mutator_ossfuzz
|
||||
PUBLIC
|
||||
${COMPILE_OPTIONS} -Wno-extra-semi -Wno-unused-parameter
|
||||
)
|
||||
target_include_directories(solc_opt_ossfuzz PRIVATE /usr/include/antlr4-runtime)
|
||||
target_link_libraries(solc_opt_ossfuzz PRIVATE libsolc evmasm antlr4-runtime)
|
||||
set_target_properties(solc_opt_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE})
|
||||
target_include_directories(solc_opt_mutator_ossfuzz PRIVATE /usr/include/antlr4-runtime)
|
||||
target_link_libraries(solc_opt_mutator_ossfuzz PRIVATE libsolc evmasm antlr4-runtime)
|
||||
set_target_properties(solc_opt_mutator_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE})
|
||||
|
||||
add_executable(solc_noopt_ossfuzz
|
||||
solc_noopt_ossfuzz.cpp
|
||||
../fuzzer_common.cpp
|
||||
../../TestCaseReader.cpp
|
||||
)
|
||||
target_link_libraries(solc_noopt_ossfuzz PRIVATE libsolc evmasm)
|
||||
set_target_properties(solc_noopt_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE})
|
||||
|
||||
add_executable(solc_noopt_mutator_ossfuzz
|
||||
solc_noopt_ossfuzz.cpp
|
||||
../fuzzer_common.cpp
|
||||
../../TestCaseReader.cpp
|
||||
SolidityLexer.cpp
|
||||
SolidityParser.cpp
|
||||
SolidityMutator.cpp
|
||||
SolidityCustomMutatorInterface.cpp
|
||||
)
|
||||
target_compile_options(solc_noopt_ossfuzz
|
||||
target_compile_options(solc_noopt_mutator_ossfuzz
|
||||
PUBLIC
|
||||
${COMPILE_OPTIONS} -Wno-extra-semi -Wno-unused-parameter
|
||||
)
|
||||
target_include_directories(solc_noopt_ossfuzz PRIVATE /usr/include/antlr4-runtime)
|
||||
target_link_libraries(solc_noopt_ossfuzz PRIVATE libsolc evmasm antlr4-runtime)
|
||||
set_target_properties(solc_noopt_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE})
|
||||
target_include_directories(solc_noopt_mutator_ossfuzz PRIVATE /usr/include/antlr4-runtime)
|
||||
target_link_libraries(solc_noopt_mutator_ossfuzz PRIVATE libsolc evmasm antlr4-runtime)
|
||||
set_target_properties(solc_noopt_mutator_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE})
|
||||
|
||||
add_executable(const_opt_ossfuzz const_opt_ossfuzz.cpp ../fuzzer_common.cpp)
|
||||
target_link_libraries(const_opt_ossfuzz PRIVATE libsolc evmasm)
|
||||
@ -96,14 +118,14 @@ if (OSSFUZZ)
|
||||
protoToYul.cpp
|
||||
yulProto.pb.cc
|
||||
protomutators/YulProtoMutator.cpp
|
||||
)
|
||||
)
|
||||
target_include_directories(yul_proto_diff_custom_mutate_ossfuzz PRIVATE /usr/include/libprotobuf-mutator)
|
||||
target_link_libraries(yul_proto_diff_custom_mutate_ossfuzz PRIVATE yul
|
||||
yulInterpreter
|
||||
protobuf-mutator-libfuzzer.a
|
||||
protobuf-mutator.a
|
||||
protobuf.a
|
||||
)
|
||||
)
|
||||
set_target_properties(yul_proto_diff_custom_mutate_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE})
|
||||
target_compile_options(yul_proto_diff_custom_mutate_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion)
|
||||
|
||||
@ -153,12 +175,24 @@ else()
|
||||
)
|
||||
target_link_libraries(solc_opt_ossfuzz PRIVATE libsolc evmasm)
|
||||
|
||||
add_library(solc_opt_mutator_ossfuzz
|
||||
solc_opt_ossfuzz.cpp
|
||||
../fuzzer_common.cpp
|
||||
)
|
||||
target_link_libraries(solc_opt_mutator_ossfuzz PRIVATE libsolc evmasm)
|
||||
|
||||
add_library(solc_noopt_ossfuzz
|
||||
solc_noopt_ossfuzz.cpp
|
||||
../fuzzer_common.cpp
|
||||
)
|
||||
target_link_libraries(solc_noopt_ossfuzz PRIVATE libsolc evmasm)
|
||||
|
||||
add_library(solc_noopt_mutator_ossfuzz
|
||||
solc_noopt_ossfuzz.cpp
|
||||
../fuzzer_common.cpp
|
||||
)
|
||||
target_link_libraries(solc_noopt_mutator_ossfuzz PRIVATE libsolc evmasm)
|
||||
|
||||
add_library(const_opt_ossfuzz
|
||||
const_opt_ossfuzz.cpp
|
||||
../fuzzer_common.cpp)
|
||||
|
88
test/tools/ossfuzz/SolidityCustomMutatorInterface.cpp
Normal file
88
test/tools/ossfuzz/SolidityCustomMutatorInterface.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
This file is part of solidity.
|
||||
|
||||
solidity is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
solidity is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
|
||||
#include <test/tools/ossfuzz/SolidityCustomMutatorInterface.h>
|
||||
|
||||
#include <test/tools/ossfuzz/SolidityLexer.h>
|
||||
#include <test/tools/ossfuzz/SolidityMutator.h>
|
||||
#include <test/tools/ossfuzz/SolidityParser.h>
|
||||
|
||||
#include <antlr4-runtime.h>
|
||||
#include <cstring>
|
||||
|
||||
using namespace std;
|
||||
using namespace antlr4;
|
||||
using namespace solidity::test::fuzzer;
|
||||
|
||||
namespace {
|
||||
/// Forward declare libFuzzer's default mutator definition
|
||||
extern "C" size_t LLVMFuzzerMutate(uint8_t* _data, size_t _size, size_t _maxSize);
|
||||
|
||||
/// Define Solidity's custom mutator by implementing libFuzzer's
|
||||
/// custom mutator external interface.
|
||||
extern "C" size_t LLVMFuzzerCustomMutator(
|
||||
uint8_t* _data,
|
||||
size_t _size,
|
||||
size_t _maxSize,
|
||||
unsigned int _seed
|
||||
)
|
||||
{
|
||||
if (_maxSize <= _size || _size == 0)
|
||||
return LLVMFuzzerMutate(_data, _size, _maxSize);
|
||||
return SolidityCustomMutatorInterface{_data, _size, _maxSize, _seed}.mutate();
|
||||
}
|
||||
}
|
||||
|
||||
SolidityCustomMutatorInterface::SolidityCustomMutatorInterface(uint8_t* _data, size_t _size, size_t _maxSize, unsigned int _seed):
|
||||
data(_data),
|
||||
size(_size),
|
||||
maxMutantSize(_maxSize),
|
||||
seed(_seed)
|
||||
{}
|
||||
|
||||
size_t SolidityCustomMutatorInterface::mutate()
|
||||
{
|
||||
antlr4::ANTLRInputStream aStream;
|
||||
try
|
||||
{
|
||||
aStream = antlr4::ANTLRInputStream(string(data, data + size));
|
||||
}
|
||||
// Range error is thrown by antlr4 runtime's ANTLRInputStream
|
||||
// See https://github.com/antlr/antlr4/issues/2036
|
||||
catch (range_error const&)
|
||||
{
|
||||
// Default to libFuzzer's mutator
|
||||
return LLVMFuzzerMutate(data, size, maxMutantSize);
|
||||
}
|
||||
SolidityLexer lexer(&aStream);
|
||||
lexer.removeErrorListeners();
|
||||
antlr4::CommonTokenStream tokens(&lexer);
|
||||
tokens.fill();
|
||||
SolidityParser parser(&tokens);
|
||||
parser.removeErrorListeners();
|
||||
SolidityMutator mutator(seed);
|
||||
parser.sourceUnit()->accept(&mutator);
|
||||
out = mutator.toString();
|
||||
solAssert(
|
||||
!out.empty() && data,
|
||||
"Solc custom mutator: Invalid mutant or memory pointer"
|
||||
);
|
||||
size_t mutantSize = min(out.size(), maxMutantSize - 1);
|
||||
mempcpy(data, out.data(), mutantSize);
|
||||
return mutantSize;
|
||||
}
|
54
test/tools/ossfuzz/SolidityCustomMutatorInterface.h
Normal file
54
test/tools/ossfuzz/SolidityCustomMutatorInterface.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
This file is part of solidity.
|
||||
|
||||
solidity is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
solidity is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
/**
|
||||
* Implements libFuzzer's custom mutator interface by making a call
|
||||
* to the Solidity custom mutator, defaulting to libfuzzer's
|
||||
* default mutator when the former fails.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <liblangutil/Exceptions.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <ostream>
|
||||
#include <random>
|
||||
|
||||
namespace solidity::test::fuzzer
|
||||
{
|
||||
struct SolidityCustomMutatorInterface
|
||||
{
|
||||
SolidityCustomMutatorInterface(uint8_t* _data, size_t _size, size_t _maxSize, unsigned _seed);
|
||||
/// Mutates input provided by libFuzzer by invoking Solidity
|
||||
/// custom mutator and @returns size of the mutant
|
||||
size_t mutate();
|
||||
|
||||
/// Raw pointer to libFuzzer provided input
|
||||
uint8_t* data;
|
||||
/// Size of libFuzzer provided input
|
||||
size_t size;
|
||||
/// Solidity mutant source code
|
||||
std::string out;
|
||||
/// Maximum length of mutant specified by libFuzzer
|
||||
size_t maxMutantSize;
|
||||
/// Pseudo random unsigned integer provided by libFuzzer to
|
||||
/// aid determinism
|
||||
unsigned int seed;
|
||||
};
|
||||
}
|
59
test/tools/ossfuzz/SolidityMutator.cpp
Normal file
59
test/tools/ossfuzz/SolidityMutator.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
This file is part of solidity.
|
||||
|
||||
solidity is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
solidity is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
|
||||
#include <test/tools/ossfuzz/SolidityMutator.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity::util;
|
||||
using namespace solidity::test::fuzzer;
|
||||
|
||||
antlrcpp::Any SolidityMutator::visitSourceUnit(SolidityParser::SourceUnitContext* _ctx)
|
||||
{
|
||||
if (_ctx->pragmaDirective().empty())
|
||||
m_out << Whiskers(s_pragmaDirective)("directive", "experimental SMTChecker").render();
|
||||
else
|
||||
visitChildren(_ctx);
|
||||
return antlrcpp::Any();
|
||||
}
|
||||
|
||||
antlrcpp::Any SolidityMutator::visitPragmaDirective(SolidityParser::PragmaDirectiveContext*)
|
||||
{
|
||||
auto PickLiteral = [&]() -> string
|
||||
{
|
||||
static const vector<string> alphanum = {
|
||||
"0",
|
||||
"experimental",
|
||||
"solidity < 142857",
|
||||
"solidity >=0.0.0",
|
||||
"solidity >=0.0.0 <0.8.0",
|
||||
"experimental __test",
|
||||
"experimental SMTChecker",
|
||||
"experimental ABIEncoderV2",
|
||||
"experimental \"xyz\""
|
||||
};
|
||||
|
||||
return alphanum[randomOneToN(alphanum.size()) - 1];
|
||||
};
|
||||
|
||||
string pragma = PickLiteral();
|
||||
|
||||
m_out << Whiskers(s_pragmaDirective)("directive", pragma).render();
|
||||
return antlrcpp::Any();
|
||||
}
|
68
test/tools/ossfuzz/SolidityMutator.h
Normal file
68
test/tools/ossfuzz/SolidityMutator.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
This file is part of solidity.
|
||||
|
||||
solidity is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
solidity is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
/**
|
||||
* Antlr4 visitor that does at least one, at most both of the
|
||||
* following while keeping mutant syntactically valid:
|
||||
* - mutates existing Solidity source code
|
||||
* - generates additional Solidity source code
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <test/tools/ossfuzz/SolidityBaseVisitor.h>
|
||||
|
||||
#include <libsolutil/Whiskers.h>
|
||||
|
||||
#include <random>
|
||||
|
||||
namespace solidity::test::fuzzer {
|
||||
using RandomEngine = std::mt19937_64;
|
||||
using Dist = std::uniform_int_distribution<uint32_t>;
|
||||
|
||||
class SolidityMutator: public SolidityBaseVisitor
|
||||
{
|
||||
public:
|
||||
SolidityMutator(unsigned int _seed): m_rand(_seed) {}
|
||||
std::string toString()
|
||||
{
|
||||
return m_out.str();
|
||||
}
|
||||
|
||||
antlrcpp::Any visitSourceUnit(SolidityParser::SourceUnitContext* _ctx) override;
|
||||
antlrcpp::Any visitPragmaDirective(SolidityParser::PragmaDirectiveContext* _ctx) override;
|
||||
private:
|
||||
/// @returns either true or false with roughly the same probability
|
||||
bool coinToss()
|
||||
{
|
||||
return m_rand() % 2 == 0;
|
||||
}
|
||||
/// @returns a pseudo randomly chosen unsigned integer between one
|
||||
/// and @param _n
|
||||
uint32_t randomOneToN(uint32_t _n)
|
||||
{
|
||||
return Dist(1, _n)(m_rand);
|
||||
}
|
||||
|
||||
/// Mutant stream
|
||||
std::ostringstream m_out;
|
||||
/// Random number generator
|
||||
RandomEngine m_rand;
|
||||
/// Whisker template strings for Solidity syntax
|
||||
const std::string s_pragmaDirective = R"(pragma <directive>;)";
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user