diff --git a/Makefile b/Makefile index 9344f387c..0f5ee5773 100644 --- a/Makefile +++ b/Makefile @@ -108,6 +108,10 @@ release-static-win32: mkdir -p build/release cd build/release && cmake -G "MSYS Makefiles" -D STATIC=ON -D ARCH="i686" -D BUILD_64=OFF -D CMAKE_BUILD_TYPE=Release -D BUILD_TAG="win-x32" -D CMAKE_TOOLCHAIN_FILE=../../cmake/32-bit-toolchain.cmake -D MSYS2_FOLDER=c:/msys32 ../.. && $(MAKE) +fuzz: + mkdir -p build/fuzz + cd build/fuzz && cmake -D BUILD_TESTS=ON -D USE_LTO=OFF -D CMAKE_C_COMPILER=afl-gcc -D CMAKE_CXX_COMPILER=afl-g++ -D ARCH="x86-64" -D CMAKE_BUILD_TYPE=fuzz -D BUILD_TAG="linux-x64" ../.. && $(MAKE) + clean: @echo "WARNING: Back-up your wallet if it exists within ./build!" ; \ read -r -p "This will destroy the build directory, continue (y/N)?: " CONTINUE; \ diff --git a/contrib/fuzz_testing/fuzz.sh b/contrib/fuzz_testing/fuzz.sh new file mode 100755 index 000000000..35b74f7e4 --- /dev/null +++ b/contrib/fuzz_testing/fuzz.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +AFLFUZZ=$(which afl-fuzz) +if ! test -x "$AFLFUZZ" +then + echo "afl-fuzz not found - install american-fuzzy-lop" + exit 1 +fi + +type="$1" +if test -z "$type" +then + echo "usage: $0 block|transaction|signature|cold-outputs|cold-transaction" + exit 1 +fi +case "$type" in + block|transaction|signature|cold-outputs|cold-transaction) ;; + *) echo "usage: $0 block|transaction|signature|cold-outputs|cold-transaction"; exit 1 ;; +esac + +afl-fuzz -i tests/data/fuzz/$type -m 150 -t 250 -o fuzz-out/$type build/fuzz/tests/fuzz/${type}_fuzz_tests diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index cb29b27a0..85763f8b5 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -77,6 +77,7 @@ file(COPY DESTINATION data) add_subdirectory(core_tests) +add_subdirectory(fuzz) add_subdirectory(crypto) add_subdirectory(functional_tests) add_subdirectory(performance_tests) @@ -114,6 +115,7 @@ set(enabled_tests hash performance_tests core_proxy + fuzz unit_tests) add_custom_target(tests DEPENDS enabled_tests) diff --git a/tests/data/fuzz/block/BLOCK1 b/tests/data/fuzz/block/BLOCK1 new file mode 100644 index 000000000..1d681ac23 Binary files /dev/null and b/tests/data/fuzz/block/BLOCK1 differ diff --git a/tests/data/fuzz/block/BLOCK2 b/tests/data/fuzz/block/BLOCK2 new file mode 100644 index 000000000..b9de418a9 Binary files /dev/null and b/tests/data/fuzz/block/BLOCK2 differ diff --git a/tests/data/fuzz/cold-outputs/OUTPUTS1 b/tests/data/fuzz/cold-outputs/OUTPUTS1 new file mode 100644 index 000000000..f449f61ad Binary files /dev/null and b/tests/data/fuzz/cold-outputs/OUTPUTS1 differ diff --git a/tests/data/fuzz/cold-outputs/OUTPUTS2 b/tests/data/fuzz/cold-outputs/OUTPUTS2 new file mode 100644 index 000000000..907bcdb91 Binary files /dev/null and b/tests/data/fuzz/cold-outputs/OUTPUTS2 differ diff --git a/tests/data/fuzz/cold-transaction/CTX1 b/tests/data/fuzz/cold-transaction/CTX1 new file mode 100644 index 000000000..0afecedbc Binary files /dev/null and b/tests/data/fuzz/cold-transaction/CTX1 differ diff --git a/tests/data/fuzz/signature/SIG1 b/tests/data/fuzz/signature/SIG1 new file mode 100644 index 000000000..e69de29bb diff --git a/tests/data/fuzz/signature/SIG2 b/tests/data/fuzz/signature/SIG2 new file mode 100644 index 000000000..f03e8a4de --- /dev/null +++ b/tests/data/fuzz/signature/SIG2 @@ -0,0 +1 @@ +SigV1WbMcLkLKXz3Su9iFUp9aYF5vSfpVetcytVWAgqhn3KNe1kidn7M2KfTRpuK8G1ba1w2u5mbyoWbkLPy2Gm97BM4W \ No newline at end of file diff --git a/tests/data/fuzz/transaction/TX1 b/tests/data/fuzz/transaction/TX1 new file mode 100644 index 000000000..706af6ace Binary files /dev/null and b/tests/data/fuzz/transaction/TX1 differ diff --git a/tests/data/fuzz/transaction/TX2 b/tests/data/fuzz/transaction/TX2 new file mode 100644 index 000000000..f751f97a2 Binary files /dev/null and b/tests/data/fuzz/transaction/TX2 differ diff --git a/tests/fuzz/CMakeLists.txt b/tests/fuzz/CMakeLists.txt new file mode 100644 index 000000000..853d46a12 --- /dev/null +++ b/tests/fuzz/CMakeLists.txt @@ -0,0 +1,91 @@ +# Copyright (c) 2014-2017, The Monero Project +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, are +# permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this list of +# conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, this list +# of conditions and the following disclaimer in the documentation and/or other +# materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its contributors may be +# used to endorse or promote products derived from this software without specific +# prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +# THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +add_executable(block_fuzz_tests block.cpp fuzzer.cpp) +target_link_libraries(block_fuzz_tests + PRIVATE + cryptonote_core + p2p + epee + ${CMAKE_THREAD_LIBS_INIT} + ${EXTRA_LIBRARIES}) +set_property(TARGET block_fuzz_tests + PROPERTY + FOLDER "tests") + +add_executable(transaction_fuzz_tests transaction.cpp fuzzer.cpp) +target_link_libraries(transaction_fuzz_tests + PRIVATE + cryptonote_core + p2p + epee + ${CMAKE_THREAD_LIBS_INIT} + ${EXTRA_LIBRARIES}) +set_property(TARGET transaction_fuzz_tests + PROPERTY + FOLDER "tests") + +add_executable(signature_fuzz_tests signature.cpp fuzzer.cpp) +target_link_libraries(signature_fuzz_tests + PRIVATE + wallet + cryptonote_core + p2p + epee + ${CMAKE_THREAD_LIBS_INIT} + ${EXTRA_LIBRARIES}) +set_property(TARGET signature_fuzz_tests + PROPERTY + FOLDER "tests") + +add_executable(cold-outputs_fuzz_tests cold-outputs.cpp fuzzer.cpp) +target_link_libraries(cold-outputs_fuzz_tests + PRIVATE + wallet + cryptonote_core + p2p + epee + ${CMAKE_THREAD_LIBS_INIT} + ${EXTRA_LIBRARIES}) +set_property(TARGET cold-outputs_fuzz_tests + PROPERTY + FOLDER "tests") + +add_executable(cold-transaction_fuzz_tests cold-transaction.cpp fuzzer.cpp) +target_link_libraries(cold-transaction_fuzz_tests + PRIVATE + wallet + cryptonote_core + p2p + epee + ${CMAKE_THREAD_LIBS_INIT} + ${EXTRA_LIBRARIES}) +set_property(TARGET cold-transaction_fuzz_tests + PROPERTY + FOLDER "tests") + diff --git a/tests/fuzz/block.cpp b/tests/fuzz/block.cpp new file mode 100644 index 000000000..099e8e3bd --- /dev/null +++ b/tests/fuzz/block.cpp @@ -0,0 +1,67 @@ +// Copyright (c) 2017, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "include_base_utils.h" +#include "common/command_line.h" +#include "file_io_utils.h" +#include "cryptonote_protocol/blobdatatype.h" +#include "cryptonote_basic/cryptonote_basic.h" +#include "cryptonote_basic/cryptonote_format_utils.h" +#include "fuzzer.h" + +class BlockFuzzer: public Fuzzer +{ +public: + virtual int run(const std::string &filename); + +private: +}; + +int BlockFuzzer::run(const std::string &filename) +{ + std::string s; + + if (!epee::file_io_utils::load_file_to_string(filename, s)) + { + std::cout << "Error: failed to load file " << filename << std::endl; + return 1; + } + cryptonote::block b = AUTO_VAL_INIT(b); + if(!parse_and_validate_block_from_blob(s, b)) + { + std::cout << "Error: failed to parse block from file " << filename << std::endl; + return 1; + } + return 0; +} + +int main(int argc, const char **argv) +{ + BlockFuzzer fuzzer; + return run_fuzzer(argc, argv, fuzzer); +} diff --git a/tests/fuzz/cold-outputs.cpp b/tests/fuzz/cold-outputs.cpp new file mode 100644 index 000000000..e585b4b13 --- /dev/null +++ b/tests/fuzz/cold-outputs.cpp @@ -0,0 +1,108 @@ +// Copyright (c) 2017, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "include_base_utils.h" +#include "file_io_utils.h" +#include "cryptonote_protocol/blobdatatype.h" +#include "cryptonote_basic/cryptonote_basic.h" +#include "cryptonote_basic/cryptonote_format_utils.h" +#include "wallet/wallet2.h" +#include "fuzzer.h" + +class ColdOutputsFuzzer: public Fuzzer +{ +public: + ColdOutputsFuzzer(): wallet(true) {} + virtual int init(); + virtual int run(const std::string &filename); + +private: + tools::wallet2 wallet; +}; + +int ColdOutputsFuzzer::init() +{ + static const char * const spendkey_hex = "0b4f47697ec99c3de6579304e5f25c68b07afbe55b71d99620bf6cbf4e45a80f"; + crypto::secret_key spendkey; + epee::string_tools::hex_to_pod(spendkey_hex, spendkey); + + try + { + boost::filesystem::remove("/tmp/cold-outputs-test.keys"); + boost::filesystem::remove("/tmp/cold-outputs-test.address.txt"); + boost::filesystem::remove("/tmp/cold-outputs-test"); + + wallet.init(""); + wallet.generate("/tmp/cold-outputs-test", "", spendkey, true, false); + + boost::filesystem::remove("/tmp/cold-outputs-test.keys"); + boost::filesystem::remove("/tmp/cold-outputs-test.address.txt"); + boost::filesystem::remove("/tmp/cold-outputs-test"); + } + catch (const std::exception &e) + { + std::cerr << "Error on ColdOutputsFuzzer::init: " << e.what() << std::endl; + return 1; + } + return 0; +} + +int ColdOutputsFuzzer::run(const std::string &filename) +{ + std::string s; + + if (!epee::file_io_utils::load_file_to_string(filename, s)) + { + std::cout << "Error: failed to load file " << filename << std::endl; + return 1; + } + s = std::string("\x01\x16serialization::archive") + s; + try + { + std::vector outputs; + std::stringstream iss; + iss << s; + boost::archive::portable_binary_iarchive ar(iss); + ar >> outputs; + size_t n_outputs = wallet.import_outputs(outputs); + std::cout << boost::lexical_cast(n_outputs) << " outputs imported" << std::endl; + } + catch (const std::exception &e) + { + std::cerr << "Failed to import outputs: " << e.what() << std::endl; + return 1; + } + return 0; +} + +int main(int argc, const char **argv) +{ + ColdOutputsFuzzer fuzzer; + return run_fuzzer(argc, argv, fuzzer); +} + diff --git a/tests/fuzz/cold-transaction.cpp b/tests/fuzz/cold-transaction.cpp new file mode 100644 index 000000000..c35d604a8 --- /dev/null +++ b/tests/fuzz/cold-transaction.cpp @@ -0,0 +1,110 @@ +// Copyright (c) 2017, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "include_base_utils.h" +#include "common/command_line.h" +#include "file_io_utils.h" +#include "cryptonote_protocol/blobdatatype.h" +#include "cryptonote_basic/cryptonote_basic.h" +#include "cryptonote_basic/cryptonote_format_utils.h" +#include "wallet/wallet2.h" +#include "fuzzer.h" + +class ColdTransactionFuzzer: public Fuzzer +{ +public: + ColdTransactionFuzzer(): wallet(true) {} + virtual int init(); + virtual int run(const std::string &filename); + +private: + tools::wallet2 wallet; +}; + + +int ColdTransactionFuzzer::init() +{ + static const char * const spendkey_hex = "0b4f47697ec99c3de6579304e5f25c68b07afbe55b71d99620bf6cbf4e45a80f"; + crypto::secret_key spendkey; + epee::string_tools::hex_to_pod(spendkey_hex, spendkey); + + try + { + boost::filesystem::remove("/tmp/cold-transaction-test.keys"); + boost::filesystem::remove("/tmp/cold-transaction-test.address.txt"); + boost::filesystem::remove("/tmp/cold-transaction-test"); + + wallet.init(""); + wallet.generate("/tmp/cold-transaction-test", "", spendkey, true, false); + + boost::filesystem::remove("/tmp/cold-transaction-test.keys"); + boost::filesystem::remove("/tmp/cold-transaction-test.address.txt"); + boost::filesystem::remove("/tmp/cold-transaction-test"); + } + catch (const std::exception &e) + { + std::cerr << "Error on ColdTransactionFuzzer::init: " << e.what() << std::endl; + return 1; + } + return 0; +} + +int ColdTransactionFuzzer::run(const std::string &filename) +{ + std::string s; + + if (!epee::file_io_utils::load_file_to_string(filename, s)) + { + std::cout << "Error: failed to load file " << filename << std::endl; + return 1; + } + s = std::string("\x01\x16serialization::archive") + s; + try + { + tools::wallet2::unsigned_tx_set exported_txs; + std::stringstream iss; + iss << s; + boost::archive::portable_binary_iarchive ar(iss); + ar >> exported_txs; + std::vector ptx; + bool success = wallet.sign_tx(exported_txs, "/tmp/cold-transaction-test-signed", ptx); + std::cout << (success ? "signed" : "error") << std::endl; + } + catch (const std::exception &e) + { + std::cerr << "Failed to sign transaction: " << e.what() << std::endl; + return 1; + } + return 0; +} + +int main(int argc, const char **argv) +{ + ColdTransactionFuzzer fuzzer; + return run_fuzzer(argc, argv, fuzzer); +} diff --git a/tests/fuzz/fuzzer.cpp b/tests/fuzz/fuzzer.cpp new file mode 100644 index 000000000..3edf8cd19 --- /dev/null +++ b/tests/fuzz/fuzzer.cpp @@ -0,0 +1,96 @@ +// Copyright (c) 2017, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include +#include "include_base_utils.h" +#include "common/command_line.h" +#include "fuzzer.h" + +#if (!defined(__clang__) || (__clang__ < 5)) +static int __AFL_LOOP(int) +{ + static int once = 0; + if (once) + return 0; + once = 1; + return 1; +} +#endif + +using namespace epee; +using namespace boost::program_options; + +int run_fuzzer(int argc, const char **argv, Fuzzer &fuzzer) +{ + TRY_ENTRY(); + string_tools::set_module_name_and_folder(argv[0]); + + //set up logging options + mlog_configure(mlog_get_default_log_path("fuzztests.log"), true); + mlog_set_log("*:FATAL,logging:none"); + + options_description desc_options("Allowed options"); + command_line::add_arg(desc_options, command_line::arg_help); + + variables_map vm; + bool r = command_line::handle_error_helper(desc_options, [&]() + { + store(parse_command_line(argc, argv, desc_options), vm); + notify(vm); + return true; + }); + if (!r) + return 1; + + if (command_line::get_arg(vm, command_line::arg_help)) + { + std::cout << desc_options << std::endl; + return 0; + } + + if (argc < 2) + { + std::cout << desc_options << std::endl; + return 1; + } + + int ret = fuzzer.init(); + if (ret) + return ret; + + const std::string filename = argv[1]; + while (__AFL_LOOP(1000)) + { + ret = fuzzer.run(filename); + if (ret) + return ret; + } + + CATCH_ENTRY_L0("fuzzer_main", 1); + return 0; +} diff --git a/tests/fuzz/fuzzer.h b/tests/fuzz/fuzzer.h new file mode 100644 index 000000000..a0a9c0173 --- /dev/null +++ b/tests/fuzz/fuzzer.h @@ -0,0 +1,38 @@ +// Copyright (c) 2017, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +class Fuzzer +{ +public: + virtual int init() { return 0; } + virtual int run(const std::string &filename) = 0; +}; + +int run_fuzzer(int argc, const char **argv, Fuzzer &fuzzer); diff --git a/tests/fuzz/signature.cpp b/tests/fuzz/signature.cpp new file mode 100644 index 000000000..69d0ad25b --- /dev/null +++ b/tests/fuzz/signature.cpp @@ -0,0 +1,105 @@ +// Copyright (c) 2017, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "include_base_utils.h" +#include "common/command_line.h" +#include "file_io_utils.h" +#include "cryptonote_protocol/blobdatatype.h" +#include "cryptonote_basic/cryptonote_basic.h" +#include "cryptonote_basic/cryptonote_format_utils.h" +#include "wallet/wallet2.h" +#include "fuzzer.h" + +class SignatureFuzzer: public Fuzzer +{ +public: + SignatureFuzzer(): Fuzzer(), wallet(true) {} + virtual int init(); + virtual int run(const std::string &filename); + +private: + tools::wallet2 wallet; + cryptonote::account_public_address address; +}; + +int SignatureFuzzer::init() +{ + static const char * const spendkey_hex = "0b4f47697ec99c3de6579304e5f25c68b07afbe55b71d99620bf6cbf4e45a80f"; + crypto::secret_key spendkey; + epee::string_tools::hex_to_pod(spendkey_hex, spendkey); + + try + { + boost::filesystem::remove("/tmp/signature-test.keys"); + boost::filesystem::remove("/tmp/signature-test.address.txt"); + boost::filesystem::remove("/tmp/signature-test"); + + wallet.init(""); + wallet.generate("/tmp/signature-test", "", spendkey, true, false); + + boost::filesystem::remove("/tmp/signature-test.keys"); + boost::filesystem::remove("/tmp/signature-test.address.txt"); + boost::filesystem::remove("/tmp/signature-test"); + + bool has_payment_id; + crypto::hash8 new_payment_id; + if (!cryptonote::get_account_address_from_str_or_url(address, has_payment_id, new_payment_id, true, "9uVsvEryzpN8WH2t1WWhFFCG5tS8cBNdmJYNRuckLENFimfauV5pZKeS1P2CbxGkSDTUPHXWwiYE5ZGSXDAGbaZgDxobqDN")) + { + std::cerr << "failed to parse address" << std::endl; + return 1; + } + } + catch (const std::exception &e) + { + std::cerr << "Error on SignatureFuzzer::init: " << e.what() << std::endl; + return 1; + } + return 0; +} + +int SignatureFuzzer::run(const std::string &filename) +{ + std::string s; + + if (!epee::file_io_utils::load_file_to_string(filename, s)) + { + std::cout << "Error: failed to load file " << filename << std::endl; + return 1; + } + + bool valid = wallet.verify("test", address, s); + std::cout << "Signature " << (valid ? "valid" : "invalid") << std::endl; + + return 0; +} + +int main(int argc, const char **argv) +{ + SignatureFuzzer fuzzer; + return run_fuzzer(argc, argv, fuzzer); +} diff --git a/tests/fuzz/transaction.cpp b/tests/fuzz/transaction.cpp new file mode 100644 index 000000000..21cd01bef --- /dev/null +++ b/tests/fuzz/transaction.cpp @@ -0,0 +1,67 @@ +// Copyright (c) 2017, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "include_base_utils.h" +#include "common/command_line.h" +#include "file_io_utils.h" +#include "cryptonote_protocol/blobdatatype.h" +#include "cryptonote_basic/cryptonote_basic.h" +#include "cryptonote_basic/cryptonote_format_utils.h" +#include "fuzzer.h" + +class TransactionFuzzer: public Fuzzer +{ +public: + virtual int run(const std::string &filename); + +private: +}; + +int TransactionFuzzer::run(const std::string &filename) +{ + std::string s; + + if (!epee::file_io_utils::load_file_to_string(filename, s)) + { + std::cout << "Error: failed to load file " << filename << std::endl; + return 1; + } + cryptonote::transaction tx = AUTO_VAL_INIT(tx); + if(!parse_and_validate_tx_from_blob(s, tx)) + { + std::cout << "Error: failed to parse transaction from file " << filename << std::endl; + return 1; + } + return 0; +} + +int main(int argc, const char **argv) +{ + TransactionFuzzer fuzzer; + return run_fuzzer(argc, argv, fuzzer); +}