From 6da5b3637e6c65f20f80118efe51b5d4a6f6fa26 Mon Sep 17 00:00:00 2001 From: moneroexamples Date: Wed, 20 Dec 2017 08:04:17 +0800 Subject: [PATCH] added asan compiler option, basic string cleaning https://github.com/moneroexamples/onion-monero-blockchain-explorer/issues/91 --- CMakeLists.txt | 10 +- main.cpp | 85 +++++---- src/page.h | 2 +- src/tools.h | 467 +++++++++++++++++++++++++------------------------ 4 files changed, 299 insertions(+), 265 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e0c44e2..d25663c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,12 @@ set(PROJECT_NAME project(${PROJECT_NAME}) set(CMAKE_CXX_FLAGS - "${CMAKE_CXX_FLAGS} -std=c++14") + "${CMAKE_CXX_FLAGS} -std=c++14 -fsanitize=address -fno-omit-frame-pointer") + +set(CMAKE_C_FLAGS + "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer -DLEAK_SANITIZER") + +# if (WIN32) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wa,-mbig-obj -O3") @@ -102,16 +107,15 @@ set(LIBRARIES cryptonote_basic daemonizer cncrypto - blocks lmdb ringct common mnemonics - epee easylogging checkpoints version + epee ${Boost_LIBRARIES} pthread unbound diff --git a/main.cpp b/main.cpp index 1f428dc..73b9baf 100644 --- a/main.cpp +++ b/main.cpp @@ -11,6 +11,7 @@ #include using boost::filesystem::path; +using xmreg::remove_bad_chars; using namespace std; @@ -276,18 +277,18 @@ main(int ac, const char* av[]) CROW_ROUTE(app, "/block/") ([&](const crow::request& req, string block_hash) { - return crow::response(xmrblocks.show_block(block_hash)); + return crow::response(xmrblocks.show_block(remove_bad_chars(block_hash))); }); CROW_ROUTE(app, "/tx/") ([&](const crow::request& req, string tx_hash) { - return crow::response(xmrblocks.show_tx(tx_hash)); + return crow::response(xmrblocks.show_tx(remove_bad_chars(tx_hash))); }); CROW_ROUTE(app, "/tx//") ([&](string tx_hash, uint16_t with_ring_signatures) { - return xmrblocks.show_tx(tx_hash, with_ring_signatures); + return xmrblocks.show_tx(remove_bad_chars(tx_hash), with_ring_signatures); }); CROW_ROUTE(app, "/myoutputs").methods("POST"_method) @@ -304,13 +305,13 @@ main(int ac, const char* av[]) return string("xmr address, viewkey or tx hash not provided"); } - string tx_hash = post_body["tx_hash"]; - string xmr_address = post_body["xmr_address"]; - string viewkey = post_body["viewkey"]; + string tx_hash = remove_bad_chars(post_body["tx_hash"]); + string xmr_address = remove_bad_chars(post_body["xmr_address"]); + string viewkey = remove_bad_chars(post_body["viewkey"]); // this will be only not empty when checking raw tx data // using tx pusher - string raw_tx_data = post_body["raw_tx_data"]; + string raw_tx_data = remove_bad_chars(post_body["raw_tx_data"]); string domain = get_domain(req); @@ -326,8 +327,10 @@ main(int ac, const char* av[]) string domain = get_domain(req); - return xmrblocks.show_my_outputs(tx_hash, xmr_address, - viewkey, string {}, + return xmrblocks.show_my_outputs(remove_bad_chars(tx_hash), + remove_bad_chars(xmr_address), + remove_bad_chars(viewkey), + string {}, domain); }); @@ -345,18 +348,21 @@ main(int ac, const char* av[]) "tx hash not provided"); } - string tx_hash = post_body["txhash"]; - string tx_prv_key = post_body["txprvkey"]; - string xmr_address = post_body["xmraddress"]; + string tx_hash = remove_bad_chars(post_body["txhash"]); + string tx_prv_key = remove_bad_chars(post_body["txprvkey"]); + string xmr_address = remove_bad_chars(post_body["xmraddress"]); // this will be only not empty when checking raw tx data // using tx pusher - string raw_tx_data = post_body["raw_tx_data"]; + string raw_tx_data = remove_bad_chars(post_body["raw_tx_data"]); string domain = get_domain(req); - return xmrblocks.show_prove(tx_hash, xmr_address, - tx_prv_key, raw_tx_data, domain); + return xmrblocks.show_prove(tx_hash, + xmr_address, + tx_prv_key, + raw_tx_data, + domain); }); @@ -366,8 +372,11 @@ main(int ac, const char* av[]) string domain = get_domain(req); - return xmrblocks.show_prove(tx_hash, xmr_address, - tx_prv_key, string {}, domain); + return xmrblocks.show_prove(remove_bad_chars(tx_hash), + remove_bad_chars(xmr_address), + remove_bad_chars(tx_prv_key), + string {}, + domain); }); if (enable_pusher) @@ -388,8 +397,8 @@ main(int ac, const char* av[]) return string("Raw tx data or action not provided"); } - string raw_tx_data = post_body["rawtxdata"]; - string action = post_body["action"]; + string raw_tx_data = remove_bad_chars(post_body["rawtxdata"]); + string action = remove_bad_chars(post_body["action"]); if (action == "check") return xmrblocks.show_checkrawtx(raw_tx_data, action); @@ -423,8 +432,8 @@ main(int ac, const char* av[]) return string("Viewkey not provided. Cant decrypt key image file without it"); } - string raw_data = post_body["rawkeyimgsdata"]; - string viewkey = post_body["viewkey"]; + string raw_data = remove_bad_chars(post_body["rawkeyimgsdata"]); + string viewkey = remove_bad_chars(post_body["viewkey"]); return xmrblocks.show_checkrawkeyimgs(raw_data, viewkey); }); @@ -455,8 +464,8 @@ main(int ac, const char* av[]) "key image file without it"); } - string raw_data = post_body["rawoutputkeysdata"]; - string viewkey = post_body["viewkey"]; + string raw_data = remove_bad_chars(post_body["rawoutputkeysdata"]); + string viewkey = remove_bad_chars(post_body["viewkey"]); return xmrblocks.show_checkcheckrawoutput(raw_data, viewkey); }); @@ -465,7 +474,7 @@ main(int ac, const char* av[]) CROW_ROUTE(app, "/search").methods("GET"_method) ([&](const crow::request& req) { - return xmrblocks.search(string(req.url_params.get("value"))); + return xmrblocks.search(remove_bad_chars(string(req.url_params.get("value")))); }); CROW_ROUTE(app, "/mempool") @@ -496,7 +505,7 @@ main(int ac, const char* av[]) CROW_ROUTE(app, "/api/transaction/") ([&](const crow::request &req, string tx_hash) { - myxmr::jsonresponse r{xmrblocks.json_transaction(tx_hash)}; + myxmr::jsonresponse r{xmrblocks.json_transaction(remove_bad_chars(tx_hash))}; return r; }); @@ -504,7 +513,7 @@ main(int ac, const char* av[]) CROW_ROUTE(app, "/api/rawtransaction/") ([&](const crow::request &req, string tx_hash) { - myxmr::jsonresponse r{xmrblocks.json_rawtransaction(tx_hash)}; + myxmr::jsonresponse r{xmrblocks.json_rawtransaction(remove_bad_chars(tx_hash))}; return r; }); @@ -512,7 +521,7 @@ main(int ac, const char* av[]) CROW_ROUTE(app, "/api/block/") ([&](const crow::request &req, string block_no_or_hash) { - myxmr::jsonresponse r{xmrblocks.json_block(block_no_or_hash)}; + myxmr::jsonresponse r{xmrblocks.json_block(remove_bad_chars(block_no_or_hash))}; return r; }); @@ -520,7 +529,7 @@ main(int ac, const char* av[]) CROW_ROUTE(app, "/api/rawblock/") ([&](const crow::request &req, string block_no_or_hash) { - myxmr::jsonresponse r{xmrblocks.json_rawblock(block_no_or_hash)}; + myxmr::jsonresponse r{xmrblocks.json_rawblock(remove_bad_chars(block_no_or_hash))}; return r; }); @@ -534,7 +543,8 @@ main(int ac, const char* av[]) string limit = regex_search(req.raw_url, regex {"limit=\\d+"}) ? req.url_params.get("limit") : "25"; - myxmr::jsonresponse r{xmrblocks.json_transactions(page, limit)}; + myxmr::jsonresponse r{xmrblocks.json_transactions( + remove_bad_chars(page), remove_bad_chars(limit))}; return r; }); @@ -551,7 +561,8 @@ main(int ac, const char* av[]) string limit = regex_search(req.raw_url, regex {"limit=\\d+"}) ? req.url_params.get("limit") : "100000000"; - myxmr::jsonresponse r{xmrblocks.json_mempool(page, limit)}; + myxmr::jsonresponse r{xmrblocks.json_mempool( + remove_bad_chars(page), remove_bad_chars(limit))}; return r; }); @@ -559,7 +570,7 @@ main(int ac, const char* av[]) CROW_ROUTE(app, "/api/search/") ([&](const crow::request &req, string search_value) { - myxmr::jsonresponse r{xmrblocks.json_search(search_value)}; + myxmr::jsonresponse r{xmrblocks.json_search(remove_bad_chars(search_value))}; return r; }); @@ -605,7 +616,11 @@ main(int ac, const char* av[]) cerr << "Cant parse tx_prove as bool. Using default value" << endl; } - myxmr::jsonresponse r{xmrblocks.json_outputs(tx_hash, address, viewkey, tx_prove)}; + myxmr::jsonresponse r{xmrblocks.json_outputs( + remove_bad_chars(tx_hash), + remove_bad_chars(address), + remove_bad_chars(viewkey), + tx_prove)}; return r; }); @@ -635,7 +650,11 @@ main(int ac, const char* av[]) cerr << "Cant parse tx_prove as bool. Using default value" << endl; } - myxmr::jsonresponse r{xmrblocks.json_outputsblocks(limit, address, viewkey, in_mempool_aswell)}; + myxmr::jsonresponse r{xmrblocks.json_outputsblocks( + remove_bad_chars(limit), + remove_bad_chars(address), + remove_bad_chars(viewkey), + in_mempool_aswell)}; return r; }); diff --git a/src/page.h b/src/page.h index 5796be3..904f107 100644 --- a/src/page.h +++ b/src/page.h @@ -5458,7 +5458,7 @@ namespace xmreg {"has_payment_id8" , txd.payment_id8 != null_hash8}, {"confirmations" , txd.no_confirmations}, {"payment_id" , pid_str}, - {"payment_id_as_ascii" , std::regex_replace(txd.payment_id_as_ascii, e, " ")}, + {"payment_id_as_ascii" , remove_bad_chars(txd.payment_id_as_ascii)}, {"payment_id8" , pid8_str}, {"extra" , txd.get_extra_str()}, {"with_ring_signatures" , static_cast( diff --git a/src/tools.h b/src/tools.h index dbd96a0..ad185c1 100644 --- a/src/tools.h +++ b/src/tools.h @@ -41,318 +41,329 @@ namespace xmreg { - using namespace cryptonote; - using namespace crypto; - using namespace std; +using namespace cryptonote; +using namespace crypto; +using namespace std; - namespace bf = boost::filesystem; +namespace bf = boost::filesystem; - using json = nlohmann::json; +using json = nlohmann::json; - struct outputs_visitor +struct outputs_visitor +{ + std::vector& m_output_keys; + + const Blockchain& m_bch; + + outputs_visitor(std::vector& output_keys, const Blockchain& bch) : + m_output_keys(output_keys), m_bch(bch) { - std::vector& m_output_keys; + } - const Blockchain& m_bch; - - outputs_visitor(std::vector& output_keys, const Blockchain& bch) : - m_output_keys(output_keys), m_bch(bch) - { - } - - bool handle_output(uint64_t unlock_time, const crypto::public_key &pubkey) - { - m_output_keys.push_back(pubkey); - return true; - } - }; - - - template - bool - parse_str_secret_key(const string& key_str, T& secret_key); - - template - bool - parse_str_secret_key(const string& key_str, std::vector& secret_keys) + bool handle_output(uint64_t unlock_time, const crypto::public_key &pubkey) { - const size_t num_keys = key_str.size() / 64; - if (num_keys * 64 != key_str.size()) - return false; - secret_keys.resize(num_keys); - for (size_t i = 0; i < num_keys; ++i) - { - if (!parse_str_secret_key(key_str.substr(64*i, 64), secret_keys[i])) - return false; - } + m_output_keys.push_back(pubkey); return true; } +}; - bool - get_tx_pub_key_from_str_hash(Blockchain& core_storage, - const string& hash_str, - transaction& tx); +template +bool +parse_str_secret_key(const string& key_str, T& secret_key); - bool - parse_str_address(const string& address_str, - address_parse_info& address_info, - bool testnet = false); +template +bool +parse_str_secret_key(const string& key_str, std::vector& secret_keys) +{ + const size_t num_keys = key_str.size() / 64; + if (num_keys * 64 != key_str.size()) + return false; + secret_keys.resize(num_keys); + for (size_t i = 0; i < num_keys; ++i) + { + if (!parse_str_secret_key(key_str.substr(64*i, 64), secret_keys[i])) + return false; + } + return true; +} - inline bool - is_separator(char c); - string - print_address(const address_parse_info& address, +bool +get_tx_pub_key_from_str_hash(Blockchain& core_storage, + const string& hash_str, + transaction& tx); + +bool +parse_str_address(const string& address_str, + address_parse_info& address_info, bool testnet = false); - string - print_sig (const signature& sig); +inline bool +is_separator(char c); - string - remove_trailing_path_separator(const string& in_path); +string +print_address(const address_parse_info& address, + bool testnet = false); - bf::path - remove_trailing_path_separator(const bf::path& in_path); +string +print_sig (const signature& sig); - string - timestamp_to_str_gm(time_t timestamp, const char* format = "%F %T"); +string +remove_trailing_path_separator(const string& in_path); - ostream& - operator<< (ostream& os, const address_parse_info& addr_info); +bf::path +remove_trailing_path_separator(const bf::path& in_path); + +string +timestamp_to_str_gm(time_t timestamp, const char* format = "%F %T"); + +ostream& +operator<< (ostream& os, const address_parse_info& addr_info); - string - get_default_lmdb_folder(bool testnet = false); +string +get_default_lmdb_folder(bool testnet = false); - bool - generate_key_image(const crypto::key_derivation& derivation, - const std::size_t output_index, - const crypto::secret_key& sec_key, - const crypto::public_key& pub_key, - crypto::key_image& key_img); +bool +generate_key_image(const crypto::key_derivation& derivation, + const std::size_t output_index, + const crypto::secret_key& sec_key, + const crypto::public_key& pub_key, + crypto::key_image& key_img); - bool - get_blockchain_path(const boost::optional& bc_path, - bf::path& blockchain_path, - bool testnet = false); +bool +get_blockchain_path(const boost::optional& bc_path, + bf::path& blockchain_path, + bool testnet = false); - uint64_t - sum_money_in_outputs(const transaction& tx); +uint64_t +sum_money_in_outputs(const transaction& tx); - pair - sum_money_in_outputs(const string& json_str); +pair +sum_money_in_outputs(const string& json_str); - pair - sum_money_in_outputs(const json& _json); +pair +sum_money_in_outputs(const json& _json); - array - summary_of_in_out_rct( - const transaction& tx, - vector>& output_pub_keys, - vector& input_key_imgs); +array +summary_of_in_out_rct( + const transaction& tx, + vector>& output_pub_keys, + vector& input_key_imgs); - // this version for mempool txs from json - array - summary_of_in_out_rct(const json& _json); +// this version for mempool txs from json +array +summary_of_in_out_rct(const json& _json); - uint64_t - sum_money_in_inputs(const transaction& tx); +uint64_t +sum_money_in_inputs(const transaction& tx); - pair - sum_money_in_inputs(const string& json_str); +pair +sum_money_in_inputs(const string& json_str); - pair - sum_money_in_inputs(const json& _json); +pair +sum_money_in_inputs(const json& _json); - uint64_t - count_nonrct_inputs(const transaction& tx); +uint64_t +count_nonrct_inputs(const transaction& tx); - uint64_t - count_nonrct_inputs(const string& json_str); +uint64_t +count_nonrct_inputs(const string& json_str); - uint64_t - count_nonrct_inputs(const json& _json); +uint64_t +count_nonrct_inputs(const json& _json); - array - sum_money_in_tx(const transaction& tx); +array +sum_money_in_tx(const transaction& tx); - array - sum_money_in_txs(const vector& txs); +array +sum_money_in_txs(const vector& txs); - uint64_t - sum_fees_in_txs(const vector& txs); +uint64_t +sum_fees_in_txs(const vector& txs); - uint64_t - get_mixin_no(const transaction& tx); +uint64_t +get_mixin_no(const transaction& tx); - vector - get_mixin_no(const string& json_str); +vector +get_mixin_no(const string& json_str); - vector - get_mixin_no(const json& _json); +vector +get_mixin_no(const json& _json); - vector - get_mixin_no_in_txs(const vector& txs); +vector +get_mixin_no_in_txs(const vector& txs); - vector> - get_ouputs(const transaction& tx); +vector> +get_ouputs(const transaction& tx); - vector> - get_ouputs_tuple(const transaction& tx); +vector> +get_ouputs_tuple(const transaction& tx); - vector - get_key_images(const transaction& tx); +vector +get_key_images(const transaction& tx); - bool - get_payment_id(const vector& extra, - crypto::hash& payment_id, - crypto::hash8& payment_id8); +bool +get_payment_id(const vector& extra, + crypto::hash& payment_id, + crypto::hash8& payment_id8); - bool - get_payment_id(const transaction& tx, - crypto::hash& payment_id, - crypto::hash8& payment_id8); +bool +get_payment_id(const transaction& tx, + crypto::hash& payment_id, + crypto::hash8& payment_id8); - inline double - get_xmr(uint64_t core_amount) - { - return static_cast(core_amount) / 1e12; - } +inline double +get_xmr(uint64_t core_amount) +{ + return static_cast(core_amount) / 1e12; +} - array - timestamp_difference(uint64_t t1, uint64_t t2); +array +timestamp_difference(uint64_t t1, uint64_t t2); - string - read(string filename); +string +read(string filename); - pair - timestamps_time_scale(const vector& timestamps, - uint64_t timeN, uint64_t resolution = 80, - uint64_t time0 = 1397818193 /* timestamp of the second block */); +pair +timestamps_time_scale(const vector& timestamps, + uint64_t timeN, uint64_t resolution = 80, + uint64_t time0 = 1397818193 /* timestamp of the second block */); - bool - decode_ringct(const rct::rctSig & rv, - const crypto::public_key pub, - const crypto::secret_key &sec, - unsigned int i, - rct::key & mask, - uint64_t & amount); +bool +decode_ringct(const rct::rctSig & rv, + const crypto::public_key pub, + const crypto::secret_key &sec, + unsigned int i, + rct::key & mask, + uint64_t & amount); - bool - decode_ringct(const rct::rctSig & rv, - const crypto::key_derivation &derivation, - unsigned int i, - rct::key & mask, - uint64_t & amount); +bool +decode_ringct(const rct::rctSig & rv, + const crypto::key_derivation &derivation, + unsigned int i, + rct::key & mask, + uint64_t & amount); - bool - url_decode(const std::string& in, std::string& out); +bool +url_decode(const std::string& in, std::string& out); - map - parse_crow_post_data(const string& req_body); +map +parse_crow_post_data(const string& req_body); // from wallet2::decrypt - string - decrypt(const std::string &ciphertext, - const crypto::secret_key &skey, - bool authenticated = true); +string +decrypt(const std::string &ciphertext, + const crypto::secret_key &skey, + bool authenticated = true); // based on // crypto::public_key wallet2::get_tx_pub_key_from_received_outs(const tools::wallet2::transfer_details &td) const - public_key - get_tx_pub_key_from_received_outs(const transaction &tx); +public_key +get_tx_pub_key_from_received_outs(const transaction &tx); - static - string - xmr_amount_to_str(const uint64_t& xmr_amount, - string _format="{:0.12f}", - bool zero_to_question_mark=true) +static +string +xmr_amount_to_str(const uint64_t& xmr_amount, + string _format="{:0.12f}", + bool zero_to_question_mark=true) +{ + string amount_str = "?"; + + if (!zero_to_question_mark) { - string amount_str = "?"; - - if (!zero_to_question_mark) + amount_str = fmt::format(_format, XMR_AMOUNT(xmr_amount)); + } + else + { + if (xmr_amount > 0 && zero_to_question_mark == true) { amount_str = fmt::format(_format, XMR_AMOUNT(xmr_amount)); } - else - { - if (xmr_amount > 0 && zero_to_question_mark == true) - { - amount_str = fmt::format(_format, XMR_AMOUNT(xmr_amount)); - } - } - - return amount_str; } - bool - is_output_ours(const size_t& output_index, - const transaction& tx, - const public_key& pub_tx_key, - const secret_key& private_view_key, - const public_key& public_spend_key); + return amount_str; +} - bool - get_real_output_for_key_image(const key_image& ki, - const transaction& tx, - const secret_key& private_view_key, - const public_key& public_spend_key, - uint64_t output_idx, - public_key output_pub_key); +bool +is_output_ours(const size_t& output_index, + const transaction& tx, + const public_key& pub_tx_key, + const secret_key& private_view_key, + const public_key& public_spend_key); + +bool +get_real_output_for_key_image(const key_image& ki, + const transaction& tx, + const secret_key& private_view_key, + const public_key& public_spend_key, + uint64_t output_idx, + public_key output_pub_key); // based on http://stackoverflow.com/a/9943098/248823 - template - void chunks(Iterator begin, - Iterator end, - iterator_traits::difference_type k, - Func f) +template +void chunks(Iterator begin, + Iterator end, + iterator_traits::difference_type k, + Func f) +{ + Iterator chunk_begin; + Iterator chunk_end; + chunk_end = chunk_begin = begin; + + do { - Iterator chunk_begin; - Iterator chunk_end; - chunk_end = chunk_begin = begin; - - do - { - if(std::distance(chunk_end, end) < k) - chunk_end = end; - else - std::advance(chunk_end, k); - f(chunk_begin,chunk_end); - chunk_begin = chunk_end; - } - while(std::distance(chunk_begin,end) > 0); + if(std::distance(chunk_end, end) < k) + chunk_end = end; + else + std::advance(chunk_end, k); + f(chunk_begin,chunk_end); + chunk_begin = chunk_end; } + while(std::distance(chunk_begin,end) > 0); +} + +/* + * Remove all characters in in_str that match the given + * regular expression + */ +inline string +remove_bad_chars(string const& in_str, std::regex const& rgx = std::regex {"[^a-zA-Z0-9]"}) +{ + return std::regex_replace(in_str, rgx, ""); +} - bool - make_tx_from_json(const string& json_str, transaction& tx); - string - make_printable(const string& in_s); +bool +make_tx_from_json(const string& json_str, transaction& tx); - string - get_human_readable_timestamp(uint64_t ts); +string +make_printable(const string& in_s); + +string +get_human_readable_timestamp(uint64_t ts); // Get the median of an unordered set of numbers of arbitrary // type without modifying the underlying dataset. // taken from http://stackoverflow.com/a/19695285 - template - typename std::iterator_traits::value_type - calc_median(It it_begin, It it_end) - { - using T = typename std::iterator_traits::value_type; - std::vector data(it_begin, it_end); - std::nth_element(data.begin(), data.begin() + data.size() / 2, data.end()); - return data[data.size() / 2]; - } +template +typename std::iterator_traits::value_type +calc_median(It it_begin, It it_end) +{ + using T = typename std::iterator_traits::value_type; + std::vector data(it_begin, it_end); + std::nth_element(data.begin(), data.begin() + data.size() / 2, data.end()); + return data[data.size() / 2]; +} - void - pause_execution(uint64_t no_seconds, const string& text = "now"); +void +pause_execution(uint64_t no_seconds, const string& text = "now"); }