aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt10
-rw-r--r--Dockerfile6
-rw-r--r--Makefile2
-rw-r--r--README.md10
-rw-r--r--contrib/epee/include/misc_os_dependent.h4
-rw-r--r--contrib/epee/include/net/abstract_tcp_server.h2
-rw-r--r--contrib/epee/include/net/abstract_tcp_server2.inl12
-rw-r--r--contrib/epee/include/net/http_client.h186
-rw-r--r--contrib/epee/include/net/http_protocol_handler.inl7
-rw-r--r--contrib/epee/include/net/levin_protocol_handler_async.h1
-rw-r--r--contrib/epee/include/net/net_parse_helpers.h4
-rw-r--r--contrib/epee/include/net/network_throttle.hpp2
-rw-r--r--contrib/epee/include/string_tools.h2
-rw-r--r--contrib/epee/src/mlog.cpp1
-rw-r--r--contrib/epee/src/network_throttle-detail.cpp8
-rw-r--r--contrib/epee/src/network_throttle.cpp3
-rw-r--r--contrib/epee/src/wipeable_string.cpp13
-rwxr-xr-xcontrib/fuzz_testing/fuzz.sh16
-rw-r--r--external/easylogging++/ea_config.h1
-rw-r--r--external/easylogging++/easylogging++.cc5
-rw-r--r--src/blockchain_db/blockchain_db.cpp10
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.cpp2
-rw-r--r--src/blockchain_utilities/blockchain_import.cpp2
-rw-r--r--src/checkpoints/checkpoints.cpp10
-rw-r--r--src/checkpoints/checkpoints.h4
-rw-r--r--src/common/download.cpp5
-rw-r--r--src/common/updates.cpp2
-rw-r--r--src/common/util.cpp14
-rw-r--r--src/cryptonote_basic/cryptonote_basic.h2
-rw-r--r--src/cryptonote_basic/cryptonote_format_utils.cpp12
-rw-r--r--src/cryptonote_core/blockchain.cpp58
-rw-r--r--src/cryptonote_core/blockchain.h26
-rw-r--r--src/cryptonote_core/cryptonote_core.cpp19
-rw-r--r--src/cryptonote_core/cryptonote_core.h21
-rw-r--r--src/cryptonote_core/cryptonote_tx_utils.cpp6
-rw-r--r--src/cryptonote_protocol/block_queue.cpp3
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_handler.inl28
-rw-r--r--src/daemon/command_parser_executor.cpp6
-rw-r--r--src/daemon/rpc_command_executor.cpp2
-rw-r--r--src/daemonizer/windows_service.cpp3
-rw-r--r--src/debug_utilities/cn_deserialize.cpp8
-rw-r--r--src/debug_utilities/object_sizes.cpp2
-rw-r--r--src/mnemonics/electrum-words.cpp2
-rw-r--r--src/p2p/net_node.inl4
-rw-r--r--src/ringct/rctOps.cpp3
-rw-r--r--src/rpc/core_rpc_server.cpp34
-rw-r--r--src/rpc/daemon_handler.cpp4
-rw-r--r--src/rpc/message.cpp2
-rw-r--r--src/simplewallet/simplewallet.cpp10
-rw-r--r--src/version.cpp.in2
-rw-r--r--src/wallet/api/unsigned_transaction.cpp4
-rw-r--r--src/wallet/node_rpc_proxy.cpp1
-rw-r--r--src/wallet/wallet2.cpp56
-rw-r--r--src/wallet/wallet_rpc_server.cpp47
-rw-r--r--src/wallet/wallet_rpc_server.h2
-rw-r--r--src/wallet/wallet_rpc_server_commands_defs.h4
-rw-r--r--tests/data/fuzz/base58/ENC10
-rw-r--r--tests/data/fuzz/base58/ENC21
-rw-r--r--tests/data/fuzz/http-client/RESP18
-rw-r--r--tests/data/fuzz/levin/LEVIN1bin0 -> 33 bytes
-rw-r--r--tests/data/fuzz/load-from-binary/BINARY1bin0 -> 10 bytes
-rw-r--r--tests/data/fuzz/load-from-json/JSON11
-rw-r--r--tests/data/fuzz/parse-url/URL11
-rw-r--r--tests/data/fuzz/parse-url/URL21
-rw-r--r--tests/fuzz/CMakeLists.txt77
-rw-r--r--tests/fuzz/base58.cpp74
-rw-r--r--tests/fuzz/fuzzer.cpp33
-rw-r--r--tests/fuzz/http-client.cpp98
-rw-r--r--tests/fuzz/levin.cpp345
-rw-r--r--tests/fuzz/load_from_binary.cpp76
-rw-r--r--tests/fuzz/load_from_json.cpp76
-rw-r--r--tests/fuzz/parse_url.cpp74
-rw-r--r--tests/unit_tests/slow_memmem.cpp4
-rw-r--r--tests/unit_tests/vercmp.cpp2
74 files changed, 1245 insertions, 341 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b11d6ba6f..11c549d7c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -238,6 +238,16 @@ if(STATIC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DZMQ_STATIC")
endif()
+if(SANITIZE)
+ if (MSVC)
+ message(FATAL_ERROR "Cannot sanitize with MSVC")
+ else()
+ message(STATUS "Using ASAN")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
+ endif()
+endif()
+
# Set default blockchain storage location:
# memory was the default in Cryptonote before Monero implimented LMDB, it still works but is unneccessary.
# set(DATABASE memory)
diff --git a/Dockerfile b/Dockerfile
index 71b0658a0..138dec4c7 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -21,8 +21,10 @@ RUN apt-get update && \
WORKDIR /src
COPY . .
+
+ARG NPROC
RUN rm -rf build && \
- make -j$(nproc) release-static
+ if [ -z "$NPROC" ];then make -j$(nproc) release-static;else make -j$NPROC release-static;fi
# runtime stage
FROM ubuntu:16.04
@@ -45,4 +47,4 @@ VOLUME /wallet
EXPOSE 18080
EXPOSE 18081
-ENTRYPOINT ["monerod", "--p2p-bind-ip=0.0.0.0", "--p2p-bind-port=18080", "--rpc-bind-ip=127.0.0.1", "--rpc-bind-port=18081", "--non-interactive"]
+ENTRYPOINT ["monerod", "--p2p-bind-ip=0.0.0.0", "--p2p-bind-port=18080", "--rpc-bind-ip=0.0.0.0", "--rpc-bind-port=18081", "--non-interactive", "--confirm-external-bind"]
diff --git a/Makefile b/Makefile
index 4f6e6465f..5a5e4b703 100644
--- a/Makefile
+++ b/Makefile
@@ -114,7 +114,7 @@ release-static-win32:
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)
+ cd build/fuzz && cmake -D STATIC=ON -D SANITIZE=ON -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!" ; \
diff --git a/README.md b/README.md
index c2eacc9bd..d76137b6f 100644
--- a/README.md
+++ b/README.md
@@ -129,6 +129,10 @@ Installing a snap is very quick. Snaps are secure. They are isolated with all of
xbps-install -S monero
+* GuixSD
+
+ guix package -i monero
+
* OS X via [Homebrew](http://brew.sh)
brew tap sammy007/cryptonight
@@ -136,7 +140,11 @@ Installing a snap is very quick. Snaps are secure. They are isolated with all of
* Docker
+ # Build using all available cores
docker build -t monero .
+
+ # or build using a specific number of cores (reduce RAM requirement)
+ docker build --build-arg NPROC=1 -t monero .
# either run in foreground
docker run -it -v /monero/chain:/root/.bitmonero -v /monero/wallet:/wallet -p 18080:18080 monero
@@ -168,6 +176,7 @@ library archives (`.a`).
| OpenSSL | basically any | NO | `libssl-dev` | `openssl` | NO | sha256 sum |
| libzmq | 3.0.0 | NO | `libzmq3-dev` | `zeromq` | NO | ZeroMQ library |
| libunbound | 1.4.16 | YES | `libunbound-dev` | `unbound` | NO | DNS resolver |
+| libsodium | ? | NO | `libsodium-dev` | ? | NO | libsodium |
| libminiupnpc | 2.0 | YES | `libminiupnpc-dev` | `miniupnpc` | YES | NAT punching |
| libunwind | any | NO | `libunwind8-dev` | `libunwind` | YES | Stack traces |
| liblzma | any | NO | `liblzma-dev` | `xz` | YES | For libunwind |
@@ -178,6 +187,7 @@ library archives (`.a`).
| Doxygen | any | NO | `doxygen` | `doxygen` | YES | Documentation |
| Graphviz | any | NO | `graphviz` | `graphviz` | YES | Documentation |
+
[^] On Debian/Ubuntu `libgtest-dev` only includes sources and headers. You must
build the library binary manually. This can be done with the following command ```sudo apt-get install libgtest-dev && cd /usr/src/gtest && sudo cmake . && sudo make && sudo mv libg* /usr/lib/ ```
diff --git a/contrib/epee/include/misc_os_dependent.h b/contrib/epee/include/misc_os_dependent.h
index 81cecf714..99690b301 100644
--- a/contrib/epee/include/misc_os_dependent.h
+++ b/contrib/epee/include/misc_os_dependent.h
@@ -23,6 +23,10 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
+#ifdef _WIN32
+#include <Winsock2.h>
+#endif
+
#ifdef WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
diff --git a/contrib/epee/include/net/abstract_tcp_server.h b/contrib/epee/include/net/abstract_tcp_server.h
index 000305cfa..cbad1717c 100644
--- a/contrib/epee/include/net/abstract_tcp_server.h
+++ b/contrib/epee/include/net/abstract_tcp_server.h
@@ -305,7 +305,7 @@ namespace net_utils
m_connections.back().powner = this;
m_connections.back().m_self_it = --m_connections.end();
m_connections.back().m_context.m_remote_address = remote_address;
- m_connections.back().m_htread = threads_helper::create_thread(ConnectionHandlerProc, &m_connections.back());
+ m_connections.back().m_htread = threads_helper::create_thread(ConnectionHandlerProc, &m_connections.back()); // ugh, seems very risky
return true;
}
diff --git a/contrib/epee/include/net/abstract_tcp_server2.inl b/contrib/epee/include/net/abstract_tcp_server2.inl
index 04d884af2..870f6c2b2 100644
--- a/contrib/epee/include/net/abstract_tcp_server2.inl
+++ b/contrib/epee/include/net/abstract_tcp_server2.inl
@@ -735,7 +735,17 @@ PRAGMA_WARNING_DISABLE_VS(4355)
boost::asio::placeholders::error));
return true;
- CATCH_ENTRY_L0("boosted_tcp_server<t_protocol_handler>::init_server", false);
+ }
+ catch (const std::exception &e)
+ {
+ MFATAL("Error starting server: " << e.what());
+ return false;
+ }
+ catch (...)
+ {
+ MFATAL("Error starting server");
+ return false;
+ }
}
//-----------------------------------------------------------------------------
PUSH_WARNINGS
diff --git a/contrib/epee/include/net/http_client.h b/contrib/epee/include/net/http_client.h
index 1a9d5d064..1edf65928 100644
--- a/contrib/epee/include/net/http_client.h
+++ b/contrib/epee/include/net/http_client.h
@@ -27,6 +27,7 @@
#pragma once
+#include <ctype.h>
#include <boost/shared_ptr.hpp>
#include <boost/regex.hpp>
#include <boost/lexical_cast.hpp>
@@ -236,7 +237,8 @@ namespace net_utils
namespace http
{
- class http_simple_client: public i_target_handler
+ template<typename net_client_type>
+ class http_simple_client_template: public i_target_handler
{
private:
enum reciev_machine_state
@@ -259,7 +261,7 @@ namespace net_utils
};
- blocked_mode_client m_net_client;
+ net_client_type m_net_client;
std::string m_host_buff;
std::string m_port;
http_client_auth m_auth;
@@ -276,7 +278,7 @@ namespace net_utils
bool m_ssl;
public:
- explicit http_simple_client()
+ explicit http_simple_client_template()
: i_target_handler()
, m_net_client()
, m_host_buff()
@@ -428,6 +430,15 @@ namespace net_utils
CRITICAL_REGION_LOCAL(m_lock);
return invoke(uri, "POST", body, timeout, ppresponse_info, additional_params);
}
+ //---------------------------------------------------------------------------
+ bool test(const std::string &s, std::chrono::milliseconds timeout) // TEST FUNC ONLY
+ {
+ CRITICAL_REGION_LOCAL(m_lock);
+ m_net_client.set_test_data(s);
+ m_state = reciev_machine_state_header;
+ return handle_reciev(timeout);
+ }
+ //---------------------------------------------------------------------------
private:
//---------------------------------------------------------------------------
inline bool handle_reciev(std::chrono::milliseconds timeout)
@@ -742,87 +753,107 @@ namespace net_utils
return true;
}
//---------------------------------------------------------------------------
- inline
- bool parse_header(http_header_info& body_info, const std::string& m_cache_to_process)
- {
+ inline bool parse_header(http_header_info& body_info, const std::string& m_cache_to_process)
+ {
MTRACE("http_stream_filter::parse_cached_header(*)");
-
- STATIC_REGEXP_EXPR_1(rexp_mach_field,
- "\n?((Connection)|(Referer)|(Content-Length)|(Content-Type)|(Transfer-Encoding)|(Content-Encoding)|(Host)|(Cookie)|(User-Agent)|(Origin)"
- // 12 3 4 5 6 7 8 9 10 11
- "|([\\w-]+?)) ?: ?((.*?)(\r?\n))[^\t ]",
- //12 13 14 15
- boost::regex::icase | boost::regex::normal);
- boost::smatch result;
- std::string::const_iterator it_current_bound = m_cache_to_process.begin();
- std::string::const_iterator it_end_bound = m_cache_to_process.end();
-
-
-
- //lookup all fields and fill well-known fields
- while( boost::regex_search( it_current_bound, it_end_bound, result, rexp_mach_field, boost::match_default) && result[0].matched)
+ const char *ptr = m_cache_to_process.c_str();
+ while (ptr[0] != '\r' || ptr[1] != '\n')
{
- const size_t field_val = 14;
- //const size_t field_etc_name = 11;
-
- int i = 2; //start position = 2
- if(result[i++].matched)//"Connection"
- body_info.m_connection = result[field_val];
- else if(result[i++].matched)//"Referrer"
- body_info.m_referer = result[field_val];
- else if(result[i++].matched)//"Content-Length"
- body_info.m_content_length = result[field_val];
- else if(result[i++].matched)//"Content-Type"
- body_info.m_content_type = result[field_val];
- else if(result[i++].matched)//"Transfer-Encoding"
- body_info.m_transfer_encoding = result[field_val];
- else if(result[i++].matched)//"Content-Encoding"
- body_info.m_content_encoding = result[field_val];
- else if(result[i++].matched)//"Host"
- { body_info.m_host = result[field_val];
- string_tools::trim(body_info.m_host);
+ // optional \n
+ if (*ptr == '\n')
+ ++ptr;
+ // an identifier composed of letters or -
+ const char *key_pos = ptr;
+ while (isalnum(*ptr) || *ptr == '_' || *ptr == '-')
+ ++ptr;
+ const char *key_end = ptr;
+ // optional space (not in RFC, but in previous code)
+ if (*ptr == ' ')
+ ++ptr;
+ CHECK_AND_ASSERT_MES(*ptr == ':', true, "http_stream_filter::parse_cached_header() invalid header in: " << m_cache_to_process);
+ ++ptr;
+ // optional whitespace, but not newlines - line folding is obsolete, let's ignore it
+ while (isblank(*ptr))
+ ++ptr;
+ const char *value_pos = ptr;
+ while (*ptr != '\r' && *ptr != '\n')
+ ++ptr;
+ const char *value_end = ptr;
+ // optional trailing whitespace
+ while (value_end > value_pos && isblank(*(value_end-1)))
+ --value_end;
+ if (*ptr == '\r')
+ ++ptr;
+ CHECK_AND_ASSERT_MES(*ptr == '\n', true, "http_stream_filter::parse_cached_header() invalid header in: " << m_cache_to_process);
+ ++ptr;
+
+ const std::string key = std::string(key_pos, key_end - key_pos);
+ const std::string value = std::string(value_pos, value_end - value_pos);
+ if (!key.empty())
+ {
+ if (!string_tools::compare_no_case(key, "Connection"))
+ body_info.m_connection = value;
+ else if(!string_tools::compare_no_case(key, "Referrer"))
+ body_info.m_referer = value;
+ else if(!string_tools::compare_no_case(key, "Content-Length"))
+ body_info.m_content_length = value;
+ else if(!string_tools::compare_no_case(key, "Content-Type"))
+ body_info.m_content_type = value;
+ else if(!string_tools::compare_no_case(key, "Transfer-Encoding"))
+ body_info.m_transfer_encoding = value;
+ else if(!string_tools::compare_no_case(key, "Content-Encoding"))
+ body_info.m_content_encoding = value;
+ else if(!string_tools::compare_no_case(key, "Host"))
+ body_info.m_host = value;
+ else if(!string_tools::compare_no_case(key, "Cookie"))
+ body_info.m_cookie = value;
+ else if(!string_tools::compare_no_case(key, "User-Agent"))
+ body_info.m_user_agent = value;
+ else if(!string_tools::compare_no_case(key, "Origin"))
+ body_info.m_origin = value;
+ else
+ body_info.m_etc_fields.emplace_back(key, value);
}
- else if(result[i++].matched)//"Cookie"
- body_info.m_cookie = result[field_val];
- else if(result[i++].matched)//"User-Agent"
- body_info.m_user_agent = result[field_val];
- else if(result[i++].matched)//"Origin"
- body_info.m_origin = result[field_val];
- else if(result[i++].matched)//e.t.c (HAVE TO BE MATCHED!)
- body_info.m_etc_fields.emplace_back(result[12], result[field_val]);
- else
- {CHECK_AND_ASSERT_MES(false, false, "http_stream_filter::parse_cached_header() not matched last entry in:"<<m_cache_to_process);}
-
- it_current_bound = result[(int)result.size()-1]. first;
}
- return true;
-
+ return true;
}
- inline
- bool analize_first_response_line()
+ //---------------------------------------------------------------------------
+ inline bool analize_first_response_line()
{
-
- //First line response, look like this: "HTTP/1.1 200 OK"
- STATIC_REGEXP_EXPR_1(rexp_match_first_response_line, "^HTTP/(\\d+).(\\d+) ((\\d)\\d{2})( [^\n]*)?\r?\n", boost::regex::icase | boost::regex::normal);
- // 1 2 34 5
- //size_t match_len = 0;
- boost::smatch result;
- if(boost::regex_search( m_header_cache, result, rexp_match_first_response_line, boost::match_default) && result[0].matched)
- {
- CHECK_AND_ASSERT_MES(result[1].matched&&result[2].matched, false, "http_stream_filter::handle_invoke_reply_line() assert failed...");
- m_response_info.m_http_ver_hi = boost::lexical_cast<int>(result[1]);
- m_response_info.m_http_ver_lo = boost::lexical_cast<int>(result[2]);
- m_response_info.m_response_code = boost::lexical_cast<int>(result[3]);
-
- m_header_cache.erase(to_nonsonst_iterator(m_header_cache, result[0].first), to_nonsonst_iterator(m_header_cache, result[0].second));
- return true;
- }else
- {
- LOG_ERROR("http_stream_filter::handle_invoke_reply_line(): Failed to match first response line:" << m_header_cache);
- return false;
- }
-
+ //First line response, look like this: "HTTP/1.1 200 OK"
+ const char *ptr = m_header_cache.c_str();
+ CHECK_AND_ASSERT_MES(!memcmp(ptr, "HTTP/", 5), false, "Invalid first response line: " + m_header_cache);
+ ptr += 5;
+ CHECK_AND_ASSERT_MES(isdigit(*ptr), false, "Invalid first response line: " + m_header_cache);
+ unsigned long ul;
+ char *end;
+ ul = strtoul(ptr, &end, 10);
+ CHECK_AND_ASSERT_MES(ul <= INT_MAX && *end =='.', false, "Invalid first response line: " + m_header_cache);
+ m_response_info.m_http_ver_hi = ul;
+ ptr = end + 1;
+ CHECK_AND_ASSERT_MES(isdigit(*ptr), false, "Invalid first response line: " + m_header_cache + ", ptr: " << ptr);
+ ul = strtoul(ptr, &end, 10);
+ CHECK_AND_ASSERT_MES(ul <= INT_MAX && isblank(*end), false, "Invalid first response line: " + m_header_cache + ", ptr: " << ptr);
+ m_response_info.m_http_ver_lo = ul;
+ ptr = end + 1;
+ while (isblank(*ptr))
+ ++ptr;
+ CHECK_AND_ASSERT_MES(isdigit(*ptr), false, "Invalid first response line: " + m_header_cache);
+ ul = strtoul(ptr, &end, 10);
+ CHECK_AND_ASSERT_MES(ul >= 100 && ul <= 999 && isspace(*end), false, "Invalid first response line: " + m_header_cache);
+ m_response_info.m_response_code = ul;
+ ptr = end;
+ // ignore the optional text, till the end
+ while (*ptr != '\r' && *ptr != '\n')
+ ++ptr;
+ if (*ptr == '\r')
+ ++ptr;
+ CHECK_AND_ASSERT_MES(*ptr == '\n', false, "Invalid first response line: " << m_header_cache);
+ ++ptr;
+
+ m_header_cache.erase(0, ptr - m_header_cache.c_str());
+ return true;
}
inline
bool set_reply_content_encoder()
@@ -957,6 +988,7 @@ namespace net_utils
return true;
}
};
+ typedef http_simple_client_template<blocked_mode_client> http_simple_client;
}
}
}
diff --git a/contrib/epee/include/net/http_protocol_handler.inl b/contrib/epee/include/net/http_protocol_handler.inl
index c555707ac..c18f7f706 100644
--- a/contrib/epee/include/net/http_protocol_handler.inl
+++ b/contrib/epee/include/net/http_protocol_handler.inl
@@ -345,7 +345,12 @@ namespace net_utils
{
analize_http_method(result, m_query_info.m_http_method, m_query_info.m_http_ver_hi, m_query_info.m_http_ver_hi);
m_query_info.m_URI = result[10];
- parse_uri(m_query_info.m_URI, m_query_info.m_uri_content);
+ if (!parse_uri(m_query_info.m_URI, m_query_info.m_uri_content))
+ {
+ m_state = http_state_error;
+ MERROR("Failed to parse URI: m_query_info.m_URI");
+ return false;
+ }
m_query_info.m_http_method_str = result[2];
m_query_info.m_full_request_str = result[0];
diff --git a/contrib/epee/include/net/levin_protocol_handler_async.h b/contrib/epee/include/net/levin_protocol_handler_async.h
index 7b526e4e7..ae6622a29 100644
--- a/contrib/epee/include/net/levin_protocol_handler_async.h
+++ b/contrib/epee/include/net/levin_protocol_handler_async.h
@@ -99,6 +99,7 @@ public:
async_protocol_handler_config():m_pcommands_handler(NULL), m_pcommands_handler_destroy(NULL), m_max_packet_size(LEVIN_DEFAULT_MAX_PACKET_SIZE)
{}
+ ~async_protocol_handler_config() { set_handler(NULL, NULL); }
void del_out_connections(size_t count);
};
diff --git a/contrib/epee/include/net/net_parse_helpers.h b/contrib/epee/include/net/net_parse_helpers.h
index 08d2a2000..708cce0ff 100644
--- a/contrib/epee/include/net/net_parse_helpers.h
+++ b/contrib/epee/include/net/net_parse_helpers.h
@@ -103,7 +103,7 @@ namespace net_utils
STATIC_REGEXP_EXPR_1(rexp_match_uri, "^([^?#]*)(\\?([^#]*))?(#(.*))?", boost::regex::icase | boost::regex::normal);
boost::smatch result;
- if(!boost::regex_search(uri, result, rexp_match_uri, boost::match_default) && result[0].matched)
+ if(!(boost::regex_search(uri, result, rexp_match_uri, boost::match_default) && result[0].matched))
{
LOG_PRINT_L1("[PARSE URI] regex not matched for uri: " << uri);
content.m_path = uri;
@@ -139,7 +139,7 @@ namespace net_utils
// 12 34 5 6 7
content.port = 0;
boost::smatch result;
- if(!boost::regex_search(url_str, result, rexp_match_uri, boost::match_default) && result[0].matched)
+ if(!(boost::regex_search(url_str, result, rexp_match_uri, boost::match_default) && result[0].matched))
{
LOG_PRINT_L1("[PARSE URI] regex not matched for uri: " << rexp_match_uri);
//content.m_path = uri;
diff --git a/contrib/epee/include/net/network_throttle.hpp b/contrib/epee/include/net/network_throttle.hpp
index 464b34726..fffd22a6a 100644
--- a/contrib/epee/include/net/network_throttle.hpp
+++ b/contrib/epee/include/net/network_throttle.hpp
@@ -121,8 +121,6 @@ class network_throttle_manager {
friend class connection_basic; // FRIEND - to directly access global throttle-s. !! REMEMBER TO USE LOCKS!
friend class connection_basic_pimpl; // ditto
- static int xxx;
-
public:
static i_network_throttle & get_global_throttle_in(); ///< singleton ; for friend class ; caller MUST use proper locks! like m_lock_get_global_throttle_in
static i_network_throttle & get_global_throttle_inreq(); ///< ditto ; use lock ... use m_lock_get_global_throttle_inreq obviously
diff --git a/contrib/epee/include/string_tools.h b/contrib/epee/include/string_tools.h
index 307323aa1..5a1ef0743 100644
--- a/contrib/epee/include/string_tools.h
+++ b/contrib/epee/include/string_tools.h
@@ -161,7 +161,7 @@ DISABLE_GCC_WARNING(maybe-uninitialized)
val = boost::lexical_cast<XType>(str_id);
return true;
}
- catch(std::exception& /*e*/)
+ catch(const std::exception& /*e*/)
{
//const char* pmsg = e.what();
return false;
diff --git a/contrib/epee/src/mlog.cpp b/contrib/epee/src/mlog.cpp
index a30efbc6a..5b9472006 100644
--- a/contrib/epee/src/mlog.cpp
+++ b/contrib/epee/src/mlog.cpp
@@ -59,6 +59,7 @@ static std::string generate_log_filename(const char *base)
strcpy(tmp, "unknown");
else
strftime(tmp, sizeof(tmp), "%Y-%m-%d-%H-%M-%S", &tm);
+ tmp[sizeof(tmp) - 1] = 0;
filename += "-";
filename += tmp;
return filename;
diff --git a/contrib/epee/src/network_throttle-detail.cpp b/contrib/epee/src/network_throttle-detail.cpp
index 317dde8e0..ed6bc07ed 100644
--- a/contrib/epee/src/network_throttle-detail.cpp
+++ b/contrib/epee/src/network_throttle-detail.cpp
@@ -231,8 +231,10 @@ network_time_seconds network_throttle::get_sleep_time_after_tick(size_t packet_s
}
void network_throttle::logger_handle_net(const std::string &filename, double time, size_t size) {
- boost::mutex mutex;
- mutex.lock(); {
+ static boost::mutex mutex;
+
+ boost::lock_guard<boost::mutex> lock(mutex);
+ {
std::fstream file;
file.open(filename.c_str(), std::ios::app | std::ios::out );
file.precision(6);
@@ -240,7 +242,7 @@ void network_throttle::logger_handle_net(const std::string &filename, double tim
_warn("Can't open file " << filename);
file << static_cast<int>(time) << " " << static_cast<double>(size/1024) << "\n";
file.close();
- } mutex.unlock();
+ }
}
// fine tune this to decide about sending speed:
diff --git a/contrib/epee/src/network_throttle.cpp b/contrib/epee/src/network_throttle.cpp
index afacc3e96..dd1640a2e 100644
--- a/contrib/epee/src/network_throttle.cpp
+++ b/contrib/epee/src/network_throttle.cpp
@@ -71,9 +71,6 @@ boost::mutex network_throttle_manager::m_lock_get_global_throttle_in;
boost::mutex network_throttle_manager::m_lock_get_global_throttle_inreq;
boost::mutex network_throttle_manager::m_lock_get_global_throttle_out;
-int network_throttle_manager::xxx;
-
-
// ================================================================================================
// methods:
i_network_throttle & network_throttle_manager::get_global_throttle_in() {
diff --git a/contrib/epee/src/wipeable_string.cpp b/contrib/epee/src/wipeable_string.cpp
index 75191df71..894c47bbd 100644
--- a/contrib/epee/src/wipeable_string.cpp
+++ b/contrib/epee/src/wipeable_string.cpp
@@ -85,11 +85,15 @@ void wipeable_string::wipe()
void wipeable_string::grow(size_t sz, size_t reserved)
{
CHECK_AND_ASSERT_THROW_MES(wipefunc, "wipefunc is not set");
- if (reserved == 0)
+ if (reserved < sz)
reserved = sz;
- CHECK_AND_ASSERT_THROW_MES(reserved >= sz, "reserved < sz");
if (reserved <= buffer.capacity())
+ {
+ if (sz < buffer.size())
+ wipefunc(buffer.data() + sz, buffer.size() - sz);
+ buffer.resize(sz);
return;
+ }
size_t old_sz = buffer.size();
std::unique_ptr<char[]> tmp{new char[old_sz]};
memcpy(tmp.get(), buffer.data(), old_sz * sizeof(char));
@@ -103,7 +107,7 @@ void wipeable_string::grow(size_t sz, size_t reserved)
void wipeable_string::push_back(char c)
{
grow(size() + 1);
- buffer.push_back(c);
+ buffer.back() = c;
}
void wipeable_string::pop_back()
@@ -113,9 +117,6 @@ void wipeable_string::pop_back()
void wipeable_string::resize(size_t sz)
{
- CHECK_AND_ASSERT_THROW_MES(wipefunc, "wipefunc is not set");
- if (sz < buffer.size())
- wipefunc(buffer.data() + sz, buffer.size() - sz);
grow(sz);
}
diff --git a/contrib/fuzz_testing/fuzz.sh b/contrib/fuzz_testing/fuzz.sh
index 35b74f7e4..f1c4ff202 100755
--- a/contrib/fuzz_testing/fuzz.sh
+++ b/contrib/fuzz_testing/fuzz.sh
@@ -10,12 +10,20 @@ fi
type="$1"
if test -z "$type"
then
- echo "usage: $0 block|transaction|signature|cold-outputs|cold-transaction"
+ echo "usage: $0 block|transaction|signature|cold-outputs|cold-transaction|load-from-binary|load-from-json|base58|parse-url|http-client|levin"
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 ;;
+ block|transaction|signature|cold-outputs|cold-transaction|load-from-binary|load-from-json|base58|parse-url|http-client|levin) ;;
+ *) echo "usage: $0 block|transaction|signature|cold-outputs|cold-transaction|load-from-binary|load-from-json|base58|parse-url|http-client|levin"; 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
+if test -d "fuzz-out/$type"
+then
+ dir="-"
+else
+ dir="tests/data/fuzz/$type"
+fi
+
+mkdir -p fuzz-out
+afl-fuzz -i "$dir" -m none -t 250 -o fuzz-out/$type build/fuzz/tests/fuzz/${type}_fuzz_tests @@
diff --git a/external/easylogging++/ea_config.h b/external/easylogging++/ea_config.h
index 2524d3477..6215e67de 100644
--- a/external/easylogging++/ea_config.h
+++ b/external/easylogging++/ea_config.h
@@ -8,3 +8,4 @@
#endif
#define ELPP_DISABLE_DEFAULT_CRASH_HANDLING
#define ELPP_NO_CHECK_MACROS
+#define ELPP_WINSOCK2
diff --git a/external/easylogging++/easylogging++.cc b/external/easylogging++/easylogging++.cc
index 31b201897..57742b2e5 100644
--- a/external/easylogging++/easylogging++.cc
+++ b/external/easylogging++/easylogging++.cc
@@ -1016,8 +1016,9 @@ const std::string OS::getBashOutput(const char* command) {
char hBuff[4096];
if (fgets(hBuff, sizeof(hBuff), proc) != nullptr) {
pclose(proc);
- if (hBuff[strlen(hBuff) - 1] == '\n') {
- hBuff[strlen(hBuff) - 1] = '\0';
+ const size_t len = strlen(hBuff);
+ if (len > 0 && hBuff[len - 1] == '\n') {
+ hBuff[len- 1] = '\0';
}
return std::string(hBuff);
}
diff --git a/src/blockchain_db/blockchain_db.cpp b/src/blockchain_db/blockchain_db.cpp
index 07b2451b0..7e77953c8 100644
--- a/src/blockchain_db/blockchain_db.cpp
+++ b/src/blockchain_db/blockchain_db.cpp
@@ -197,7 +197,7 @@ uint64_t BlockchainDB::add_block( const block& blk
{
// sanity
if (blk.tx_hashes.size() != txs.size())
- throw new std::runtime_error("Inconsistent tx/hashes sizes");
+ throw std::runtime_error("Inconsistent tx/hashes sizes");
block_txn_start(false);
@@ -283,7 +283,7 @@ block BlockchainDB::get_block_from_height(const uint64_t& height) const
blobdata bd = get_block_blob_from_height(height);
block b;
if (!parse_and_validate_block_from_blob(bd, b))
- throw new DB_ERROR("Failed to parse block from blob retrieved from the db");
+ throw DB_ERROR("Failed to parse block from blob retrieved from the db");
return b;
}
@@ -293,7 +293,7 @@ block BlockchainDB::get_block(const crypto::hash& h) const
blobdata bd = get_block_blob(h);
block b;
if (!parse_and_validate_block_from_blob(bd, b))
- throw new DB_ERROR("Failed to parse block from blob retrieved from the db");
+ throw DB_ERROR("Failed to parse block from blob retrieved from the db");
return b;
}
@@ -304,7 +304,7 @@ bool BlockchainDB::get_tx(const crypto::hash& h, cryptonote::transaction &tx) co
if (!get_tx_blob(h, bd))
return false;
if (!parse_and_validate_tx_from_blob(bd, tx))
- throw new DB_ERROR("Failed to parse transaction from blob retrieved from the db");
+ throw DB_ERROR("Failed to parse transaction from blob retrieved from the db");
return true;
}
@@ -313,7 +313,7 @@ transaction BlockchainDB::get_tx(const crypto::hash& h) const
{
transaction tx;
if (!get_tx(h, tx))
- throw new TX_DNE(std::string("tx with hash ").append(epee::string_tools::pod_to_hex(h)).append(" not found in db").c_str());
+ throw TX_DNE(std::string("tx with hash ").append(epee::string_tools::pod_to_hex(h)).append(" not found in db").c_str());
return tx;
}
diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp
index 07a0e67b1..ee4368e86 100644
--- a/src/blockchain_db/lmdb/db_lmdb.cpp
+++ b/src/blockchain_db/lmdb/db_lmdb.cpp
@@ -2894,7 +2894,7 @@ uint64_t BlockchainLMDB::add_block(const block& blk, const size_t& block_size, c
{
BlockchainDB::add_block(blk, block_size, cumulative_difficulty, coins_generated, txs);
}
- catch (DB_ERROR_TXN_START& e)
+ catch (const DB_ERROR_TXN_START& e)
{
throw;
}
diff --git a/src/blockchain_utilities/blockchain_import.cpp b/src/blockchain_utilities/blockchain_import.cpp
index 70d1dd696..758deb7e4 100644
--- a/src/blockchain_utilities/blockchain_import.cpp
+++ b/src/blockchain_utilities/blockchain_import.cpp
@@ -459,7 +459,7 @@ int import_from_file(cryptonote::core& core, const std::string& import_file_path
// tx number 1: coinbase tx
// tx number 2 onwards: archived_txs
- for (transaction tx : archived_txs)
+ for (const transaction &tx : archived_txs)
{
// add blocks with verification.
// for Blockchain and blockchain_storage add_new_block().
diff --git a/src/checkpoints/checkpoints.cpp b/src/checkpoints/checkpoints.cpp
index c66c4f5d6..67a313bc2 100644
--- a/src/checkpoints/checkpoints.cpp
+++ b/src/checkpoints/checkpoints.cpp
@@ -204,7 +204,7 @@ namespace cryptonote
return true;
}
- bool checkpoints::load_checkpoints_from_json(const std::string json_hashfile_fullpath)
+ bool checkpoints::load_checkpoints_from_json(const std::string &json_hashfile_fullpath)
{
boost::system::error_code errcode;
if (! (boost::filesystem::exists(json_hashfile_fullpath, errcode)))
@@ -218,7 +218,11 @@ namespace cryptonote
uint64_t prev_max_height = get_max_height();
LOG_PRINT_L1("Hard-coded max checkpoint height is " << prev_max_height);
t_hash_json hashes;
- epee::serialization::load_t_from_json_file(hashes, json_hashfile_fullpath);
+ if (!epee::serialization::load_t_from_json_file(hashes, json_hashfile_fullpath))
+ {
+ MERROR("Error loading checkpoints from " << json_hashfile_fullpath);
+ return false;
+ }
for (std::vector<t_hashline>::const_iterator it = hashes.hashlines.begin(); it != hashes.hashlines.end(); )
{
uint64_t height;
@@ -286,7 +290,7 @@ namespace cryptonote
return true;
}
- bool checkpoints::load_new_checkpoints(const std::string json_hashfile_fullpath, bool testnet, bool dns)
+ bool checkpoints::load_new_checkpoints(const std::string &json_hashfile_fullpath, bool testnet, bool dns)
{
bool result;
diff --git a/src/checkpoints/checkpoints.h b/src/checkpoints/checkpoints.h
index 3e034f6f0..83969f7b8 100644
--- a/src/checkpoints/checkpoints.h
+++ b/src/checkpoints/checkpoints.h
@@ -165,7 +165,7 @@ namespace cryptonote
*
* @return true if loading successful and no conflicts
*/
- bool load_new_checkpoints(const std::string json_hashfile_fullpath, bool testnet=false, bool dns=true);
+ bool load_new_checkpoints(const std::string &json_hashfile_fullpath, bool testnet=false, bool dns=true);
/**
* @brief load new checkpoints from json
@@ -174,7 +174,7 @@ namespace cryptonote
*
* @return true if loading successful and no conflicts
*/
- bool load_checkpoints_from_json(const std::string json_hashfile_fullpath);
+ bool load_checkpoints_from_json(const std::string &json_hashfile_fullpath);
/**
* @brief load new checkpoints from DNS
diff --git a/src/common/download.cpp b/src/common/download.cpp
index 28aac5a59..d330479de 100644
--- a/src/common/download.cpp
+++ b/src/common/download.cpp
@@ -147,9 +147,10 @@ namespace tools
lock.unlock();
- uint16_t port = u_c.port ? u_c.port : 80;
+ bool ssl = u_c.schema == "https";
+ uint16_t port = u_c.port ? u_c.port : ssl ? 443 : 80;
MDEBUG("Connecting to " << u_c.host << ":" << port);
- client.set_server(u_c.host, std::to_string(port), boost::none);
+ client.set_server(u_c.host, std::to_string(port), boost::none, ssl);
if (!client.connect(std::chrono::seconds(30)))
{
boost::lock_guard<boost::mutex> lock(control->mutex);
diff --git a/src/common/updates.cpp b/src/common/updates.cpp
index eff6754af..2d9c2d89c 100644
--- a/src/common/updates.cpp
+++ b/src/common/updates.cpp
@@ -99,7 +99,7 @@ namespace tools
std::string get_update_url(const std::string &software, const std::string &subdir, const std::string &buildtag, const std::string &version, bool user)
{
- const char *base = user ? "https://downloads.getmonero.org/" : "http://updates.getmonero.org/";
+ const char *base = user ? "https://downloads.getmonero.org/" : "https://updates.getmonero.org/";
#ifdef _WIN32
static const char *extension = strncmp(buildtag.c_str(), "install-", 8) ? ".zip" : ".exe";
#else
diff --git a/src/common/util.cpp b/src/common/util.cpp
index d9e12ffe4..2a2f50c4f 100644
--- a/src/common/util.cpp
+++ b/src/common/util.cpp
@@ -635,13 +635,13 @@ std::string get_nix_version_display_string()
int vercmp(const char *v0, const char *v1)
{
std::vector<std::string> f0, f1;
- boost::split(f0, v0, boost::is_any_of("."));
- boost::split(f1, v1, boost::is_any_of("."));
- while (f0.size() < f1.size())
- f0.push_back("0");
- while (f1.size() < f0.size())
- f1.push_back("0");
- for (size_t i = 0; i < f0.size(); ++i) {
+ boost::split(f0, v0, boost::is_any_of(".-"));
+ boost::split(f1, v1, boost::is_any_of(".-"));
+ for (size_t i = 0; i < std::max(f0.size(), f1.size()); ++i) {
+ if (i >= f0.size())
+ return -1;
+ if (i >= f1.size())
+ return 1;
int f0i = atoi(f0[i].c_str()), f1i = atoi(f1[i].c_str());
int n = f0i - f1i;
if (n)
diff --git a/src/cryptonote_basic/cryptonote_basic.h b/src/cryptonote_basic/cryptonote_basic.h
index 89dda8c3d..821c21d84 100644
--- a/src/cryptonote_basic/cryptonote_basic.h
+++ b/src/cryptonote_basic/cryptonote_basic.h
@@ -259,7 +259,7 @@ namespace cryptonote
ar.tag("rctsig_prunable");
ar.begin_object();
r = rct_signatures.p.serialize_rctsig_prunable(ar, rct_signatures.type, vin.size(), vout.size(),
- vin[0].type() == typeid(txin_to_key) ? boost::get<txin_to_key>(vin[0]).key_offsets.size() - 1 : 0);
+ vin.size() > 0 && vin[0].type() == typeid(txin_to_key) ? boost::get<txin_to_key>(vin[0]).key_offsets.size() - 1 : 0);
if (!r || !ar.stream().good()) return false;
ar.end_object();
}
diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp
index 8f7ab94db..21fa63842 100644
--- a/src/cryptonote_basic/cryptonote_format_utils.cpp
+++ b/src/cryptonote_basic/cryptonote_format_utils.cpp
@@ -630,17 +630,21 @@ namespace cryptonote
bool is_out_to_acc(const account_keys& acc, const txout_to_key& out_key, const crypto::public_key& tx_pub_key, const std::vector<crypto::public_key>& additional_tx_pub_keys, size_t output_index)
{
crypto::key_derivation derivation;
- generate_key_derivation(tx_pub_key, acc.m_view_secret_key, derivation);
+ bool r = generate_key_derivation(tx_pub_key, acc.m_view_secret_key, derivation);
+ CHECK_AND_ASSERT_MES(r, false, "Failed to generate key derivation");
crypto::public_key pk;
- derive_public_key(derivation, output_index, acc.m_account_address.m_spend_public_key, pk);
+ r = derive_public_key(derivation, output_index, acc.m_account_address.m_spend_public_key, pk);
+ CHECK_AND_ASSERT_MES(r, false, "Failed to derive public key");
if (pk == out_key.key)
return true;
// try additional tx pubkeys if available
if (!additional_tx_pub_keys.empty())
{
CHECK_AND_ASSERT_MES(output_index < additional_tx_pub_keys.size(), false, "wrong number of additional tx pubkeys");
- generate_key_derivation(additional_tx_pub_keys[output_index], acc.m_view_secret_key, derivation);
- derive_public_key(derivation, output_index, acc.m_account_address.m_spend_public_key, pk);
+ r = generate_key_derivation(additional_tx_pub_keys[output_index], acc.m_view_secret_key, derivation);
+ CHECK_AND_ASSERT_MES(r, false, "Failed to generate key derivation");
+ r = derive_public_key(derivation, output_index, acc.m_account_address.m_spend_public_key, pk);
+ CHECK_AND_ASSERT_MES(r, false, "Failed to derive public key");
return pk == out_key.key;
}
return false;
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index 123bd194b..709c5e852 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -321,6 +321,7 @@ bool Blockchain::init(BlockchainDB* db, const bool testnet, bool offline, const
if (!db->is_open())
{
LOG_ERROR("Attempted to init Blockchain with unopened DB");
+ delete db;
return false;
}
@@ -471,7 +472,7 @@ bool Blockchain::deinit()
// memory operation), otherwise we may cause a loop.
if (m_db == NULL)
{
- throw new DB_ERROR("The db pointer is null in Blockchain, the blockchain may be corrupt!");
+ throw DB_ERROR("The db pointer is null in Blockchain, the blockchain may be corrupt!");
}
try
@@ -489,7 +490,9 @@ bool Blockchain::deinit()
}
delete m_hardfork;
+ m_hardfork = NULL;
delete m_db;
+ m_db = NULL;
return true;
}
//------------------------------------------------------------------
@@ -2050,49 +2053,6 @@ bool Blockchain::get_transactions(const t_ids_container& txs_ids, t_tx_container
return true;
}
//------------------------------------------------------------------
-void Blockchain::print_blockchain(uint64_t start_index, uint64_t end_index) const
-{
- LOG_PRINT_L3("Blockchain::" << __func__);
- std::stringstream ss;
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
- auto h = m_db->height();
- if(start_index > h)
- {
- MERROR("Wrong starter index set: " << start_index << ", expected max index " << h);
- return;
- }
-
- for(size_t i = start_index; i <= h && i != end_index; i++)
- {
- ss << "height " << i << ", timestamp " << m_db->get_block_timestamp(i) << ", cumul_dif " << m_db->get_block_cumulative_difficulty(i) << ", size " << m_db->get_block_size(i) << "\nid\t\t" << m_db->get_block_hash_from_height(i) << "\ndifficulty\t\t" << m_db->get_block_difficulty(i) << ", nonce " << m_db->get_block_from_height(i).nonce << ", tx_count " << m_db->get_block_from_height(i).tx_hashes.size() << std::endl;
- }
- MCINFO("globlal", "Current blockchain:" << std::endl << ss.str());
-}
-//------------------------------------------------------------------
-void Blockchain::print_blockchain_index() const
-{
- LOG_PRINT_L3("Blockchain::" << __func__);
- std::stringstream ss;
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
- auto height = m_db->height();
- if (height != 0)
- {
- for(uint64_t i = 0; i <= height; i++)
- {
- ss << "height: " << i << ", hash: " << m_db->get_block_hash_from_height(i);
- }
- }
-
- MINFO("Current blockchain index:" << std::endl << ss.str());
-}
-//------------------------------------------------------------------
-//TODO: remove this function and references to it
-void Blockchain::print_blockchain_outs(const std::string& file) const
-{
- LOG_PRINT_L3("Blockchain::" << __func__);
- return;
-}
-//------------------------------------------------------------------
// Find the split point between us and foreign blockchain and return
// (by reference) the most recent common block hash along with up to
// BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT additional (more recent) hashes.
@@ -2338,7 +2298,7 @@ void Blockchain::on_new_tx_from_block(const cryptonote::transaction &tx)
TIME_MEASURE_FINISH(a);
if(m_show_time_stats)
{
- size_t ring_size = tx.vin[0].type() == typeid(txin_to_key) ? boost::get<txin_to_key>(tx.vin[0]).key_offsets.size() : 0;
+ size_t ring_size = !tx.vin.empty() && tx.vin[0].type() == typeid(txin_to_key) ? boost::get<txin_to_key>(tx.vin[0]).key_offsets.size() : 0;
MINFO("HASH: " << "-" << " I/M/O: " << tx.vin.size() << "/" << ring_size << "/" << tx.vout.size() << " H: " << 0 << " chcktx: " << a);
}
}
@@ -2373,7 +2333,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, uint64_t& max_used_block_heigh
TIME_MEASURE_FINISH(a);
if(m_show_time_stats)
{
- size_t ring_size = tx.vin[0].type() == typeid(txin_to_key) ? boost::get<txin_to_key>(tx.vin[0]).key_offsets.size() : 0;
+ size_t ring_size = !tx.vin.empty() && tx.vin[0].type() == typeid(txin_to_key) ? boost::get<txin_to_key>(tx.vin[0]).key_offsets.size() : 0;
MINFO("HASH: " << get_transaction_hash(tx) << " I/M/O: " << tx.vin.size() << "/" << ring_size << "/" << tx.vout.size() << " H: " << max_used_block_height << " ms: " << a + m_fake_scan_time << " B: " << get_object_blobsize(tx));
}
if (!res)
@@ -2466,6 +2426,7 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr
// mixRing - full and simple store it in opposite ways
if (rv.type == rct::RCTTypeFull || rv.type == rct::RCTTypeFullBulletproof)
{
+ CHECK_AND_ASSERT_MES(!pubkeys.empty() && !pubkeys[0].empty(), false, "empty pubkeys");
rv.mixRing.resize(pubkeys[0].size());
for (size_t m = 0; m < pubkeys[0].size(); ++m)
rv.mixRing[m].clear();
@@ -2480,6 +2441,7 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr
}
else if (rv.type == rct::RCTTypeSimple || rv.type == rct::RCTTypeSimpleBulletproof)
{
+ CHECK_AND_ASSERT_MES(!pubkeys.empty() && !pubkeys[0].empty(), false, "empty pubkeys");
rv.mixRing.resize(pubkeys.size());
for (size_t n = 0; n < pubkeys.size(); ++n)
{
@@ -2811,7 +2773,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
}
for (size_t n = 0; n < tx.vin.size(); ++n)
{
- if (memcmp(&boost::get<txin_to_key>(tx.vin[n]).k_image, &rv.p.MGs[n].II[0], 32))
+ if (rv.p.MGs[n].II.empty() || memcmp(&boost::get<txin_to_key>(tx.vin[n]).k_image, &rv.p.MGs[n].II[0], 32))
{
MERROR_VER("Failed to check ringct signatures: mismatched key image");
return false;
@@ -2864,7 +2826,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
MERROR_VER("Failed to check ringct signatures: Bad MGs size");
return false;
}
- if (rv.p.MGs[0].II.size() != tx.vin.size())
+ if (rv.p.MGs.empty() || rv.p.MGs[0].II.size() != tx.vin.size())
{
MERROR_VER("Failed to check ringct signatures: mismatched II/vin sizes");
return false;
diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h
index b76d0555f..2d5307ac0 100644
--- a/src/cryptonote_core/blockchain.h
+++ b/src/cryptonote_core/blockchain.h
@@ -680,32 +680,6 @@ namespace cryptonote
//debug functions
/**
- * @brief prints data about a snippet of the blockchain
- *
- * if start_index is greater than the blockchain height, do nothing
- *
- * @param start_index height on chain to start at
- * @param end_index height on chain to end at
- */
- void print_blockchain(uint64_t start_index, uint64_t end_index) const;
-
- /**
- * @brief prints every block's hash
- *
- * WARNING: This function will absolutely crush a terminal in prints, so
- * it is recommended to redirect this output to a log file (or null sink
- * if a log file is already set up, as should be the default)
- */
- void print_blockchain_index() const;
-
- /**
- * @brief currently does nothing, candidate for removal
- *
- * @param file
- */
- void print_blockchain_outs(const std::string& file) const;
-
- /**
* @brief check the blockchain against a set of checkpoints
*
* If a block fails a checkpoint and enforce is enabled, the blockchain
diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp
index 415657f9c..da8be18f2 100644
--- a/src/cryptonote_core/cryptonote_core.cpp
+++ b/src/cryptonote_core/cryptonote_core.cpp
@@ -377,7 +377,7 @@ namespace cryptonote
// folder might not be a directory, etc, etc
catch (...) { }
- BlockchainDB* db = new_db(db_type);
+ std::unique_ptr<BlockchainDB> db(new_db(db_type));
if (db == NULL)
{
LOG_ERROR("Attempted to use non-existent database type");
@@ -468,7 +468,7 @@ namespace cryptonote
m_blockchain_storage.set_user_options(blocks_threads,
blocks_per_sync, sync_mode, fast_sync);
- r = m_blockchain_storage.init(db, m_testnet, m_offline, test_options);
+ r = m_blockchain_storage.init(db.release(), m_testnet, m_offline, test_options);
r = m_mempool.init();
CHECK_AND_ASSERT_MES(r, false, "Failed to initialize memory pool");
@@ -1052,21 +1052,6 @@ namespace cryptonote
return m_blockchain_storage.find_blockchain_supplement(req_start_block, qblock_ids, blocks, total_height, start_height, max_count);
}
//-----------------------------------------------------------------------------------------------
- void core::print_blockchain(uint64_t start_index, uint64_t end_index) const
- {
- m_blockchain_storage.print_blockchain(start_index, end_index);
- }
- //-----------------------------------------------------------------------------------------------
- void core::print_blockchain_index() const
- {
- m_blockchain_storage.print_blockchain_index();
- }
- //-----------------------------------------------------------------------------------------------
- void core::print_blockchain_outs(const std::string& file)
- {
- m_blockchain_storage.print_blockchain_outs(file);
- }
- //-----------------------------------------------------------------------------------------------
bool core::get_random_outs_for_amounts(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res) const
{
return m_blockchain_storage.get_random_outs_for_amounts(req, res);
diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h
index 9f84ed303..adc201fb5 100644
--- a/src/cryptonote_core/cryptonote_core.h
+++ b/src/cryptonote_core/cryptonote_core.h
@@ -601,20 +601,6 @@ namespace cryptonote
const Blockchain& get_blockchain_storage()const{return m_blockchain_storage;}
/**
- * @copydoc Blockchain::print_blockchain
- *
- * @note see Blockchain::print_blockchain
- */
- void print_blockchain(uint64_t start_index, uint64_t end_index) const;
-
- /**
- * @copydoc Blockchain::print_blockchain_index
- *
- * @note see Blockchain::print_blockchain_index
- */
- void print_blockchain_index() const;
-
- /**
* @copydoc tx_memory_pool::print_pool
*
* @note see tx_memory_pool::print_pool
@@ -622,13 +608,6 @@ namespace cryptonote
std::string print_pool(bool short_format) const;
/**
- * @copydoc Blockchain::print_blockchain_outs
- *
- * @note see Blockchain::print_blockchain_outs
- */
- void print_blockchain_outs(const std::string& file);
-
- /**
* @copydoc miner::on_synchronized
*
* @note see miner::on_synchronized
diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp
index 89f24a4d4..916b1e05a 100644
--- a/src/cryptonote_core/cryptonote_tx_utils.cpp
+++ b/src/cryptonote_core/cryptonote_tx_utils.cpp
@@ -190,6 +190,12 @@ namespace cryptonote
//---------------------------------------------------------------
bool construct_tx_with_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, bool rct, bool bulletproof, rct::multisig_out *msout)
{
+ if (sources.empty())
+ {
+ LOG_ERROR("Empty sources");
+ return false;
+ }
+
std::vector<rct::key> amount_keys;
tx.set_null();
amount_keys.clear();
diff --git a/src/cryptonote_protocol/block_queue.cpp b/src/cryptonote_protocol/block_queue.cpp
index bfff35456..3844d3751 100644
--- a/src/cryptonote_protocol/block_queue.cpp
+++ b/src/cryptonote_protocol/block_queue.cpp
@@ -62,6 +62,7 @@ void block_queue::add_blocks(uint64_t height, std::list<cryptonote::block_comple
void block_queue::add_blocks(uint64_t height, uint64_t nblocks, const boost::uuids::uuid &connection_id, boost::posix_time::ptime time)
{
+ CHECK_AND_ASSERT_THROW_MES(nblocks > 0, "Empty span");
boost::unique_lock<boost::recursive_mutex> lock(mutex);
blocks.insert(span(height, nblocks, connection_id, time));
}
@@ -384,7 +385,7 @@ float block_queue::get_speed(const boost::uuids::uuid &connection_id) const
i->second = (i->second + span.rate) / 2;
}
float conn_rate = -1, best_rate = 0;
- for (auto i: speeds)
+ for (const auto &i: speeds)
{
if (i.first == connection_id)
conn_rate = i.second;
diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
index 389e8ba84..8aef31a5a 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl
+++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
@@ -266,13 +266,17 @@ namespace cryptonote
return true;
// from v6, if the peer advertises a top block version, reject if it's not what it should be (will only work if no voting)
- const uint8_t version = m_core.get_ideal_hard_fork_version(hshd.current_height - 1);
- if (version >= 6 && version != hshd.top_version)
+ if (hshd.current_height > 0)
{
- if (version < hshd.top_version)
- MCLOG_RED(el::Level::Warning, "global", context << " peer claims higher version that we think - we may be forked from the network and a software upgrade may be needed");
- LOG_DEBUG_CC(context, "Ignoring due to wrong top version for block " << (hshd.current_height - 1) << ": " << (unsigned)hshd.top_version << ", expected " << (unsigned)version);
- return false;
+ const uint8_t version = m_core.get_ideal_hard_fork_version(hshd.current_height - 1);
+ if (version >= 6 && version != hshd.top_version)
+ {
+ if (version < hshd.top_version)
+ MCLOG_RED(el::Level::Warning, "global", context << " peer claims higher version that we think (" <<
+ (unsigned)hshd.top_version << " for " << (hshd.current_height - 1) << "instead of " << (unsigned)version <<
+ ") - we may be forked from the network and a software upgrade may be needed");
+ return false;
+ }
}
context.m_remote_blockchain_height = hshd.current_height;
@@ -999,6 +1003,11 @@ skip:
MDEBUG(context << " next span in the queue has blocks " << start_height << "-" << (start_height + blocks.size() - 1)
<< ", we need " << previous_height);
+ if (blocks.empty())
+ {
+ MERROR("Next span has no blocks");
+ break;
+ }
block new_block;
if (!parse_and_validate_block_from_blob(blocks.front().block, new_block))
@@ -1494,6 +1503,7 @@ skip:
NOTIFY_REQUEST_CHAIN::request r = boost::value_initialized<NOTIFY_REQUEST_CHAIN::request>();
m_core.get_short_chain_history(r.block_ids);
+ CHECK_AND_ASSERT_MES(!r.block_ids.empty(), false, "Short chain history is empty");
if (!start_from_current_chain)
{
@@ -1581,6 +1591,12 @@ skip:
drop_connection(context, true, false);
return 1;
}
+ if (arg.total_height < arg.m_block_ids.size() || arg.start_height > arg.total_height - arg.m_block_ids.size())
+ {
+ LOG_ERROR_CCONTEXT("sent invalid start/nblocks/height, dropping connection");
+ drop_connection(context, true, false);
+ return 1;
+ }
context.m_remote_blockchain_height = arg.total_height;
context.m_last_response_height = arg.start_height + arg.m_block_ids.size()-1;
diff --git a/src/daemon/command_parser_executor.cpp b/src/daemon/command_parser_executor.cpp
index 5307b2472..8970f9407 100644
--- a/src/daemon/command_parser_executor.cpp
+++ b/src/daemon/command_parser_executor.cpp
@@ -173,7 +173,7 @@ bool t_command_parser_executor::print_block(const std::vector<std::string>& args
uint64_t height = boost::lexical_cast<uint64_t>(arg);
return m_executor.print_block_by_height(height);
}
- catch (boost::bad_lexical_cast&)
+ catch (const boost::bad_lexical_cast&)
{
crypto::hash block_hash;
if (parse_hash256(arg, block_hash))
@@ -420,7 +420,7 @@ bool t_command_parser_executor::out_peers(const std::vector<std::string>& args)
limit = std::stoi(args[0]);
}
- catch(std::exception& ex) {
+ catch(const std::exception& ex) {
_erro("stoi exception");
return false;
}
@@ -450,7 +450,7 @@ bool t_command_parser_executor::hard_fork_info(const std::vector<std::string>& a
try {
version = std::stoi(args[0]);
}
- catch(std::exception& ex) {
+ catch(const std::exception& ex) {
return false;
}
if (version <= 0 || version > 255)
diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp
index d7ee28baa..8aca668ad 100644
--- a/src/daemon/rpc_command_executor.cpp
+++ b/src/daemon/rpc_command_executor.cpp
@@ -1611,7 +1611,7 @@ bool t_rpc_command_executor::alt_chain_info()
}
tools::msg_writer() << boost::lexical_cast<std::string>(res.chains.size()) << " alternate chains found:";
- for (const auto chain: res.chains)
+ for (const auto &chain: res.chains)
{
uint64_t start_height = (chain.height - chain.length + 1);
tools::msg_writer() << chain.length << " blocks long, from height " << start_height << " (" << (ires.height - start_height - 1)
diff --git a/src/daemonizer/windows_service.cpp b/src/daemonizer/windows_service.cpp
index d540f5bf8..9b8e46615 100644
--- a/src/daemonizer/windows_service.cpp
+++ b/src/daemonizer/windows_service.cpp
@@ -26,6 +26,9 @@
// 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 <boost/chrono/chrono.hpp>
+#include <boost/thread/thread.hpp>
+
#undef UNICODE
#undef _UNICODE
diff --git a/src/debug_utilities/cn_deserialize.cpp b/src/debug_utilities/cn_deserialize.cpp
index a59c04dc6..04c0935c8 100644
--- a/src/debug_utilities/cn_deserialize.cpp
+++ b/src/debug_utilities/cn_deserialize.cpp
@@ -154,7 +154,11 @@ int main(int argc, char* argv[])
std::cout << "Parsed transaction:" << std::endl;
std::cout << cryptonote::obj_to_json_str(tx) << std::endl;
- if (cryptonote::parse_tx_extra(tx.extra, fields))
+ bool parsed = cryptonote::parse_tx_extra(tx.extra, fields);
+ if (!parsed)
+ std::cout << "Failed to parse tx_extra" << std::endl;
+
+ if (!fields.empty())
{
std::cout << "tx_extra has " << fields.size() << " field(s)" << std::endl;
for (size_t n = 0; n < fields.size(); ++n)
@@ -171,7 +175,7 @@ int main(int argc, char* argv[])
}
else
{
- std::cout << "Failed to parse tx_extra" << std::endl;
+ std::cout << "No fields were found in tx_extra" << std::endl;
}
}
else
diff --git a/src/debug_utilities/object_sizes.cpp b/src/debug_utilities/object_sizes.cpp
index 82d8a4add..967742229 100644
--- a/src/debug_utilities/object_sizes.cpp
+++ b/src/debug_utilities/object_sizes.cpp
@@ -51,7 +51,7 @@ class size_logger
public:
~size_logger()
{
- for (const auto i: types)
+ for (const auto &i: types)
std::cout << std::to_string(i.first) << "\t" << i.second << std::endl;
}
void add(const char *type, size_t size) { types.insert(std::make_pair(size, type)); }
diff --git a/src/mnemonics/electrum-words.cpp b/src/mnemonics/electrum-words.cpp
index 1b14905f6..ba67952aa 100644
--- a/src/mnemonics/electrum-words.cpp
+++ b/src/mnemonics/electrum-words.cpp
@@ -205,6 +205,8 @@ namespace
*/
bool checksum_test(std::vector<std::string> seed, uint32_t unique_prefix_length)
{
+ if (seed.empty())
+ return false;
// The last word is the checksum.
std::string last_word = seed.back();
seed.pop_back();
diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl
index 55be7c2cb..b6ef530d1 100644
--- a/src/p2p/net_node.inl
+++ b/src/p2p/net_node.inl
@@ -1856,8 +1856,8 @@ namespace nodetool
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::has_too_many_connections(const epee::net_utils::network_address &address)
{
- const uint8_t max_connections = 1;
- uint8_t count = 0;
+ const size_t max_connections = 1;
+ size_t count = 0;
m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
{
diff --git a/src/ringct/rctOps.cpp b/src/ringct/rctOps.cpp
index a7311482c..cc46d0aa7 100644
--- a/src/ringct/rctOps.cpp
+++ b/src/ringct/rctOps.cpp
@@ -76,6 +76,7 @@ namespace rct {
//Generates a vector of secret key
//Mainly used in testing
keyV skvGen(size_t rows ) {
+ CHECK_AND_ASSERT_THROW_MES(rows > 0, "0 keys requested");
keyV rv(rows);
size_t i = 0;
crypto::rand(rows * sizeof(key), (uint8_t*)&rv[0]);
@@ -351,6 +352,7 @@ namespace rct {
//This takes the outputs and commitments
//and hashes them into a 32 byte sized key
key cn_fast_hash(const ctkeyV &PC) {
+ if (PC.empty()) return rct::hash2rct(crypto::cn_fast_hash("", 0));
key rv;
cn_fast_hash(rv, &PC[0], 64*PC.size());
return rv;
@@ -367,6 +369,7 @@ namespace rct {
//put them in the key vector and it concatenates them
//and then hashes them
key cn_fast_hash(const keyV &keys) {
+ if (keys.empty()) return rct::hash2rct(crypto::cn_fast_hash("", 0));
key rv;
cn_fast_hash(rv, &keys[0], keys.size() * sizeof(keys[0]));
//dp(rv);
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index 803588cbd..a6109cb89 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -492,6 +492,11 @@ namespace cryptonote
{
if (std::find(missed_txs.begin(), missed_txs.end(), h) == missed_txs.end())
{
+ if (txs.empty())
+ {
+ res.status = "Failed: internal error - txs is empty";
+ return true;
+ }
// core returns the ones it finds in the right order
if (get_transaction_hash(txs.front()) != h)
{
@@ -1150,7 +1155,7 @@ namespace cryptonote
error_resp.message = "Internal error: can't get block by hash. Hash = " + req.hash + '.';
return false;
}
- if (blk.miner_tx.vin.front().type() != typeid(txin_gen))
+ if (blk.miner_tx.vin.size() != 1 || blk.miner_tx.vin.front().type() != typeid(txin_gen))
{
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
error_resp.message = "Internal error: coinbase transaction in the block has the wrong type";
@@ -1188,7 +1193,7 @@ namespace cryptonote
error_resp.message = "Internal error: can't get block by height. Height = " + boost::lexical_cast<std::string>(h) + ". Hash = " + epee::string_tools::pod_to_hex(block_hash) + '.';
return false;
}
- if (blk.miner_tx.vin.front().type() != typeid(txin_gen))
+ if (blk.miner_tx.vin.size() != 1 || blk.miner_tx.vin.front().type() != typeid(txin_gen))
{
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
error_resp.message = "Internal error: coinbase transaction in the block has the wrong type";
@@ -1274,7 +1279,7 @@ namespace cryptonote
error_resp.message = "Internal error: can't get block by hash. Hash = " + req.hash + '.';
return false;
}
- if (blk.miner_tx.vin.front().type() != typeid(txin_gen))
+ if (blk.miner_tx.vin.size() != 1 || blk.miner_tx.vin.front().type() != typeid(txin_gen))
{
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
error_resp.message = "Internal error: coinbase transaction in the block has the wrong type";
@@ -1436,19 +1441,25 @@ namespace cryptonote
{
failed = true;
}
- crypto::hash txid = *reinterpret_cast<const crypto::hash*>(txid_data.data());
- txids.push_back(txid);
+ else
+ {
+ crypto::hash txid = *reinterpret_cast<const crypto::hash*>(txid_data.data());
+ txids.push_back(txid);
+ }
}
}
if (!m_core.get_blockchain_storage().flush_txes_from_pool(txids))
{
- res.status = "Failed to remove one more tx";
+ res.status = "Failed to remove one or more tx(es)";
return false;
}
if (failed)
{
- res.status = "Failed to parse txid";
+ if (txids.empty())
+ res.status = "Failed to parse txid";
+ else
+ res.status = "Failed to parse some of the txids";
return false;
}
@@ -1705,13 +1716,16 @@ namespace cryptonote
PERF_TIMER(on_relay_tx);
bool failed = false;
+ res.status = "";
for (const auto &str: req.txids)
{
cryptonote::blobdata txid_data;
if(!epee::string_tools::parse_hexstr_to_binbuff(str, txid_data))
{
- res.status = std::string("Invalid transaction id: ") + str;
+ if (!res.status.empty()) res.status += ", ";
+ res.status += std::string("invalid transaction id: ") + str;
failed = true;
+ continue;
}
crypto::hash txid = *reinterpret_cast<const crypto::hash*>(txid_data.data());
@@ -1727,8 +1741,10 @@ namespace cryptonote
}
else
{
- res.status = std::string("Transaction not found in pool: ") + str;
+ if (!res.status.empty()) res.status += ", ";
+ res.status += std::string("transaction not found in pool: ") + str;
failed = true;
+ continue;
}
}
diff --git a/src/rpc/daemon_handler.cpp b/src/rpc/daemon_handler.cpp
index 6643ce4e4..908f9e187 100644
--- a/src/rpc/daemon_handler.cpp
+++ b/src/rpc/daemon_handler.cpp
@@ -799,6 +799,10 @@ namespace rpc
}
header.hash = hash_in;
+ if (b.miner_tx.vin.size() != 1 || b.miner_tx.vin.front().type() != typeid(txin_gen))
+ {
+ return false;
+ }
header.height = boost::get<txin_gen>(b.miner_tx.vin.front()).height;
header.major_version = b.major_version;
diff --git a/src/rpc/message.cpp b/src/rpc/message.cpp
index d6da124d1..98b40e667 100644
--- a/src/rpc/message.cpp
+++ b/src/rpc/message.cpp
@@ -111,7 +111,7 @@ FullMessage::FullMessage(Message* message)
FullMessage::FullMessage(const std::string& json_string, bool request)
{
doc.Parse(json_string.c_str());
- if (doc.HasParseError())
+ if (doc.HasParseError() || !doc.IsObject())
{
throw cryptonote::json::PARSE_FAIL();
}
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index 11a6d3177..ed426aedd 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -4335,9 +4335,9 @@ bool simple_wallet::sweep_single(const std::vector<std::string> &args_)
fail_msg_writer() << tr("Multiple transactions are created, which is not supposed to happen");
return true;
}
- if (ptx_vector[0].selected_transfers.size() > 1)
+ if (ptx_vector[0].selected_transfers.size() != 1)
{
- fail_msg_writer() << tr("The transaction uses multiple inputs, which is not supposed to happen");
+ fail_msg_writer() << tr("The transaction uses multiple or no inputs, which is not supposed to happen");
return true;
}
@@ -5189,7 +5189,7 @@ bool simple_wallet::show_transfers(const std::vector<std::string> &args_)
try {
min_height = boost::lexical_cast<uint64_t>(local_args[0]);
}
- catch (boost::bad_lexical_cast &) {
+ catch (const boost::bad_lexical_cast &) {
fail_msg_writer() << tr("bad min_height parameter:") << " " << local_args[0];
return true;
}
@@ -5201,7 +5201,7 @@ bool simple_wallet::show_transfers(const std::vector<std::string> &args_)
try {
max_height = boost::lexical_cast<uint64_t>(local_args[0]);
}
- catch (boost::bad_lexical_cast &) {
+ catch (const boost::bad_lexical_cast &) {
fail_msg_writer() << tr("bad max_height parameter:") << " " << local_args[0];
return true;
}
@@ -5364,7 +5364,7 @@ bool simple_wallet::unspent_outputs(const std::vector<std::string> &args_)
for (const auto& td : transfers)
{
uint64_t amount = td.amount();
- if (td.m_spent || amount < min_amount || amount > max_amount || td.m_subaddr_index.major != m_current_subaddress_account || subaddr_indices.count(td.m_subaddr_index.minor) == 0)
+ if (td.m_spent || amount < min_amount || amount > max_amount || td.m_subaddr_index.major != m_current_subaddress_account || (subaddr_indices.count(td.m_subaddr_index.minor) == 0 && !subaddr_indices.empty()))
continue;
amount_to_tds[amount].push_back(td);
if (min_height > td.m_block_height) min_height = td.m_block_height;
diff --git a/src/version.cpp.in b/src/version.cpp.in
index d1444f867..18d62db6b 100644
--- a/src/version.cpp.in
+++ b/src/version.cpp.in
@@ -1,5 +1,5 @@
#define DEF_MONERO_VERSION_TAG "@VERSIONTAG@"
-#define DEF_MONERO_VERSION "0.11.0.0"
+#define DEF_MONERO_VERSION "0.11.1.0-master"
#define DEF_MONERO_RELEASE_NAME "Helium Hydra"
#define DEF_MONERO_VERSION_FULL DEF_MONERO_VERSION "-" DEF_MONERO_VERSION_TAG
diff --git a/src/wallet/api/unsigned_transaction.cpp b/src/wallet/api/unsigned_transaction.cpp
index 4c8c5ade2..d22719189 100644
--- a/src/wallet/api/unsigned_transaction.cpp
+++ b/src/wallet/api/unsigned_transaction.cpp
@@ -293,6 +293,10 @@ std::vector<std::string> UnsignedTransactionImpl::recipientAddress() const
// TODO: return integrated address if short payment ID exists
std::vector<string> result;
for (const auto &utx: m_unsigned_tx_set.txes) {
+ if (utx.dests.empty()) {
+ MERROR("empty destinations, skipped");
+ continue;
+ }
result.push_back(cryptonote::get_account_address_as_str(m_wallet.m_wallet->testnet(), utx.dests[0].is_subaddress, utx.dests[0].addr));
}
return result;
diff --git a/src/wallet/node_rpc_proxy.cpp b/src/wallet/node_rpc_proxy.cpp
index 9f30e4ac5..07185d12c 100644
--- a/src/wallet/node_rpc_proxy.cpp
+++ b/src/wallet/node_rpc_proxy.cpp
@@ -68,7 +68,6 @@ void NodeRPCProxy::invalidate()
boost::optional<std::string> NodeRPCProxy::get_rpc_version(uint32_t &rpc_version) const
{
- const time_t now = time(NULL);
if (m_rpc_version == 0)
{
epee::json_rpc::request<cryptonote::COMMAND_RPC_GET_VERSION::request> req_t = AUTO_VAL_INIT(req_t);
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 436e7f972..78553708b 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -540,6 +540,11 @@ crypto::hash8 get_short_payment_id(const tools::wallet2::pending_tx &ptx)
{
if(get_encrypted_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id8))
{
+ if (ptx.dests.empty())
+ {
+ MWARNING("Encrypted payment id found, but no destinations public key, cannot decrypt");
+ return crypto::null_hash8;
+ }
decrypt_payment_id(payment_id8, ptx.dests[0].addr.m_view_public_key, ptx.tx_key);
}
}
@@ -986,7 +991,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
LOG_PRINT_L0("Public key wasn't found in the transaction extra. Skipping transaction " << txid);
if(0 != m_callback)
m_callback->on_skip_transaction(height, txid, tx);
- return;
+ break;
}
int num_vouts_received = 0;
@@ -3504,14 +3509,6 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas
const std::string old_keys_file = m_keys_file;
const std::string old_address_file = m_wallet_file + ".address.txt";
- // save to new file
- std::ofstream ostr;
- ostr.open(new_file, std::ios_base::binary | std::ios_base::out | std::ios_base::trunc);
- binary_archive<true> oar(ostr);
- bool success = ::serialization::serialize(oar, cache_file_data);
- ostr.close();
- THROW_WALLET_EXCEPTION_IF(!success || !ostr.good(), error::file_save_error, new_file);
-
// save keys to the new file
// if we here, main wallet file is saved and we only need to save keys and address files
if (!same_file) {
@@ -3538,6 +3535,14 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas
LOG_ERROR("error removing file: " << old_address_file);
}
} else {
+ // save to new file
+ std::ofstream ostr;
+ ostr.open(new_file, std::ios_base::binary | std::ios_base::out | std::ios_base::trunc);
+ binary_archive<true> oar(ostr);
+ bool success = ::serialization::serialize(oar, cache_file_data);
+ ostr.close();
+ THROW_WALLET_EXCEPTION_IF(!success || !ostr.good(), error::file_save_error, new_file);
+
// here we have "*.new" file, we need to rename it to be without ".new"
std::error_code e = tools::replace_file(new_file, m_wallet_file);
THROW_WALLET_EXCEPTION_IF(e, error::file_save_error, m_wallet_file, e);
@@ -4050,6 +4055,11 @@ crypto::hash wallet2::get_payment_id(const pending_tx &ptx) const
crypto::hash8 payment_id8 = null_hash8;
if(get_encrypted_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id8))
{
+ if (ptx.dests.empty())
+ {
+ MWARNING("Encrypted payment id found, but no destinations public key, cannot decrypt");
+ return crypto::null_hash;
+ }
if (decrypt_payment_id(payment_id8, ptx.dests[0].addr.m_view_public_key, ptx.tx_key))
{
memcpy(payment_id.data, payment_id8.data, 8);
@@ -4274,6 +4284,7 @@ bool wallet2::sign_tx(unsigned_tx_set &exported_txs, const std::string &signed_f
for (size_t n = 0; n < exported_txs.txes.size(); ++n)
{
tools::wallet2::tx_construction_data &sd = exported_txs.txes[n];
+ THROW_WALLET_EXCEPTION_IF(sd.sources.empty(), error::wallet_internal_error, "Empty sources");
LOG_PRINT_L1(" " << (n+1) << ": " << sd.sources.size() << " inputs, ring size " << sd.sources[0].outputs.size());
signed_txes.ptx.push_back(pending_tx());
tools::wallet2::pending_tx &ptx = signed_txes.ptx.back();
@@ -4950,6 +4961,7 @@ bool wallet2::tx_add_fake_output(std::vector<std::vector<tools::wallet2::get_out
if (global_index == real_index) // don't re-add real one
return false;
auto item = std::make_tuple(global_index, tx_public_key, mask);
+ CHECK_AND_ASSERT_MES(!outs.empty(), false, "internal error: outs is empty");
if (std::find(outs.back().begin(), outs.back().end(), item) != outs.back().end()) // don't add duplicates
return false;
outs.back().push_back(item);
@@ -5114,7 +5126,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
// if there are just enough outputs to mix with, use all of them.
// Eventually this should become impossible.
uint64_t num_outs = 0, num_recent_outs = 0;
- for (auto he: resp_t.result.histogram)
+ for (const auto &he: resp_t.result.histogram)
{
if (he.amount == amount)
{
@@ -6223,7 +6235,8 @@ bool wallet2::light_wallet_parse_rct_str(const std::string& rct_string, const cr
if (decrypt) {
// Decrypt the mask
crypto::key_derivation derivation;
- generate_key_derivation(tx_pub_key, get_account().get_keys().m_view_secret_key, derivation);
+ bool r = generate_key_derivation(tx_pub_key, get_account().get_keys().m_view_secret_key, derivation);
+ THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key derivation");
crypto::secret_key scalar;
crypto::derivation_to_scalar(derivation, internal_output_index, scalar);
sc_sub(decrypted_mask.bytes,encrypted_mask.bytes,rct::hash_to_scalar(rct::sk2rct(scalar)).bytes);
@@ -6635,7 +6648,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
LOG_PRINT_L2("Made a " << ((txBlob.size() + 1023) / 1024) << " kB tx, with " << print_money(available_for_fee) << " available for fee (" <<
print_money(needed_fee) << " needed)");
- if (needed_fee > available_for_fee && dsts[0].amount > 0)
+ if (needed_fee > available_for_fee && !dsts.empty() && dsts[0].amount > 0)
{
// we don't have enough for the fee, but we've only partially paid the current address,
// so we can take the fee from the paid amount, since we'll have to make another tx anyway
@@ -7413,12 +7426,14 @@ void wallet2::check_tx_key_helper(const crypto::hash &txid, const crypto::key_de
continue;
crypto::public_key derived_out_key;
- derive_public_key(derivation, n, address.m_spend_public_key, derived_out_key);
+ bool r = derive_public_key(derivation, n, address.m_spend_public_key, derived_out_key);
+ THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to derive public key");
bool found = out_key->key == derived_out_key;
crypto::key_derivation found_derivation = derivation;
if (!found && !additional_derivations.empty())
{
- derive_public_key(additional_derivations[n], n, address.m_spend_public_key, derived_out_key);
+ r = derive_public_key(additional_derivations[n], n, address.m_spend_public_key, derived_out_key);
+ THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to derive public key");
found = out_key->key == derived_out_key;
found_derivation = additional_derivations[n];
}
@@ -7923,13 +7938,15 @@ crypto::public_key wallet2::get_tx_pub_key_from_received_outs(const tools::walle
for (size_t i = 0; i < additional_tx_pub_keys.size(); ++i)
{
additional_derivations.push_back({});
- generate_key_derivation(additional_tx_pub_keys[i], keys.m_view_secret_key, additional_derivations.back());
+ bool r = generate_key_derivation(additional_tx_pub_keys[i], keys.m_view_secret_key, additional_derivations.back());
+ THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key derivation");
}
while (find_tx_extra_field_by_type(tx_extra_fields, pub_key_field, pk_index++)) {
const crypto::public_key tx_pub_key = pub_key_field.pub_key;
crypto::key_derivation derivation;
- generate_key_derivation(tx_pub_key, keys.m_view_secret_key, derivation);
+ bool r = generate_key_derivation(tx_pub_key, keys.m_view_secret_key, derivation);
+ THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key derivation");
for (size_t i = 0; i < td.m_tx.vout.size(); ++i)
{
@@ -8216,13 +8233,15 @@ uint64_t wallet2::import_key_images(const std::vector<std::pair<crypto::key_imag
const cryptonote::account_keys& keys = m_account.get_keys();
const crypto::public_key tx_pub_key = get_tx_pub_key_from_extra(spent_tx);
crypto::key_derivation derivation;
- generate_key_derivation(tx_pub_key, keys.m_view_secret_key, derivation);
+ bool r = generate_key_derivation(tx_pub_key, keys.m_view_secret_key, derivation);
+ THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key derivation");
const std::vector<crypto::public_key> additional_tx_pub_keys = get_additional_tx_pub_keys_from_extra(spent_tx);
std::vector<crypto::key_derivation> additional_derivations;
for (size_t i = 0; i < additional_tx_pub_keys.size(); ++i)
{
additional_derivations.push_back({});
- generate_key_derivation(additional_tx_pub_keys[i], keys.m_view_secret_key, additional_derivations.back());
+ r = generate_key_derivation(additional_tx_pub_keys[i], keys.m_view_secret_key, additional_derivations.back());
+ THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key derivation");
}
size_t output_index = 0;
for (const cryptonote::tx_out& out : spent_tx.vout)
@@ -8944,6 +8963,7 @@ uint64_t wallet2::get_blockchain_height_by_date(uint16_t year, uint8_t month, ui
throw std::runtime_error(oss.str());
}
cryptonote::block blk_min, blk_mid, blk_max;
+ if (res.blocks.size() < 3) throw std::runtime_error("Not enough blocks returned from daemon");
if (!parse_and_validate_block_from_blob(res.blocks[0].block, blk_min)) throw std::runtime_error("failed to parse blob at height " + std::to_string(height_min));
if (!parse_and_validate_block_from_blob(res.blocks[1].block, blk_mid)) throw std::runtime_error("failed to parse blob at height " + std::to_string(height_mid));
if (!parse_and_validate_block_from_blob(res.blocks[2].block, blk_max)) throw std::runtime_error("failed to parse blob at height " + std::to_string(height_max));
diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index 27e77710d..e3459571d 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -356,13 +356,24 @@ namespace tools
if (!m_wallet) return not_open(er);
try
{
- res.addresses.resize(m_wallet->get_num_subaddresses(req.account_index));
+ res.addresses.clear();
+ std::vector<uint32_t> req_address_index;
+ if (req.address_index.empty())
+ {
+ for (uint32_t i = 0; i < m_wallet->get_num_subaddresses(req.account_index); ++i)
+ req_address_index.push_back(i);
+ }
+ else
+ {
+ req_address_index = req.address_index;
+ }
tools::wallet2::transfer_container transfers;
m_wallet->get_transfers(transfers);
- cryptonote::subaddress_index index = {req.account_index, 0};
- for (; index.minor < m_wallet->get_num_subaddresses(req.account_index); ++index.minor)
+ for (uint32_t i : req_address_index)
{
- auto& info = res.addresses[index.minor];
+ res.addresses.resize(res.addresses.size() + 1);
+ auto& info = res.addresses.back();
+ const cryptonote::subaddress_index index = {req.account_index, i};
info.address = m_wallet->get_subaddress_as_str(index);
info.label = m_wallet->get_subaddress_label(index);
info.address_index = index.minor;
@@ -556,7 +567,7 @@ namespace tools
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
- bool wallet_rpc_server::validate_transfer(const std::list<wallet_rpc::transfer_destination>& destinations, const std::string& payment_id, std::vector<cryptonote::tx_destination_entry>& dsts, std::vector<uint8_t>& extra, epee::json_rpc::error& er)
+ bool wallet_rpc_server::validate_transfer(const std::list<wallet_rpc::transfer_destination>& destinations, const std::string& payment_id, std::vector<cryptonote::tx_destination_entry>& dsts, std::vector<uint8_t>& extra, bool at_least_one_destination, epee::json_rpc::error& er)
{
crypto::hash8 integrated_payment_id = crypto::null_hash8;
std::string extra_nonce;
@@ -611,6 +622,13 @@ namespace tools
}
}
+ if (at_least_one_destination && dsts.empty())
+ {
+ er.code = WALLET_RPC_ERROR_CODE_ZERO_DESTINATION;
+ er.message = "No destinations for this transfer";
+ return false;
+ }
+
if (!payment_id.empty())
{
@@ -662,7 +680,7 @@ namespace tools
}
// validate the transfer requested and populate dsts & extra
- if (!validate_transfer(req.destinations, req.payment_id, dsts, extra, er))
+ if (!validate_transfer(req.destinations, req.payment_id, dsts, extra, true, er))
{
return false;
}
@@ -672,6 +690,13 @@ namespace tools
uint64_t mixin = m_wallet->adjust_mixin(req.mixin);
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_2(dsts, mixin, req.unlock_time, req.priority, extra, req.account_index, req.subaddr_indices, m_trusted_daemon);
+ if (ptx_vector.empty())
+ {
+ er.code = WALLET_RPC_ERROR_CODE_TX_NOT_POSSIBLE;
+ er.message = "No transaction created";
+ return false;
+ }
+
// reject proposed transactions if there are more than one. see on_transfer_split below.
if (ptx_vector.size() != 1)
{
@@ -753,7 +778,7 @@ namespace tools
}
// validate the transfer requested and populate dsts & extra; RPC_TRANSFER::request and RPC_TRANSFER_SPLIT::request are identical types.
- if (!validate_transfer(req.destinations, req.payment_id, dsts, extra, er))
+ if (!validate_transfer(req.destinations, req.payment_id, dsts, extra, true, er))
{
return false;
}
@@ -950,7 +975,7 @@ namespace tools
destination.push_back(wallet_rpc::transfer_destination());
destination.back().amount = 0;
destination.back().address = req.address;
- if (!validate_transfer(destination, req.payment_id, dsts, extra, er))
+ if (!validate_transfer(destination, req.payment_id, dsts, extra, true, er))
{
return false;
}
@@ -1049,7 +1074,7 @@ namespace tools
destination.push_back(wallet_rpc::transfer_destination());
destination.back().amount = 0;
destination.back().address = req.address;
- if (!validate_transfer(destination, req.payment_id, dsts, extra, er))
+ if (!validate_transfer(destination, req.payment_id, dsts, extra, true, er))
{
return false;
}
@@ -1324,6 +1349,7 @@ namespace tools
rpc_payment.block_height = payment.m_block_height;
rpc_payment.unlock_time = payment.m_unlock_time;
rpc_payment.subaddr_index = payment.m_subaddr_index;
+ rpc_payment.address = m_wallet->get_subaddress_as_str(payment.m_subaddr_index);
res.payments.push_back(rpc_payment);
}
@@ -1345,11 +1371,13 @@ namespace tools
{
wallet_rpc::payment_details rpc_payment;
rpc_payment.payment_id = epee::string_tools::pod_to_hex(payment.first);
+ rpc_payment.subaddress = m_wallet->get_subaddress_as_str(payment.second.m_subaddr_index);
rpc_payment.tx_hash = epee::string_tools::pod_to_hex(payment.second.m_tx_hash);
rpc_payment.amount = payment.second.m_amount;
rpc_payment.block_height = payment.second.m_block_height;
rpc_payment.unlock_time = payment.second.m_unlock_time;
rpc_payment.subaddr_index = payment.second.m_subaddr_index;
+ rpc_payment.address = m_wallet->get_subaddress_as_str(payment.second.m_subaddr_index);
res.payments.push_back(std::move(rpc_payment));
}
@@ -1400,6 +1428,7 @@ namespace tools
rpc_payment.block_height = payment.m_block_height;
rpc_payment.unlock_time = payment.m_unlock_time;
rpc_payment.subaddr_index = payment.m_subaddr_index;
+ rpc_payment.address = m_wallet->get_subaddress_as_str(payment.m_subaddr_index);
res.payments.push_back(std::move(rpc_payment));
}
}
diff --git a/src/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h
index 00b1e9644..b20198b78 100644
--- a/src/wallet/wallet_rpc_server.h
+++ b/src/wallet/wallet_rpc_server.h
@@ -145,7 +145,7 @@ namespace tools
bool on_untag_accounts(const wallet_rpc::COMMAND_RPC_UNTAG_ACCOUNTS::request& req, wallet_rpc::COMMAND_RPC_UNTAG_ACCOUNTS::response& res, epee::json_rpc::error& er);
bool on_set_account_tag_description(const wallet_rpc::COMMAND_RPC_SET_ACCOUNT_TAG_DESCRIPTION::request& req, wallet_rpc::COMMAND_RPC_SET_ACCOUNT_TAG_DESCRIPTION::response& res, epee::json_rpc::error& er);
bool on_getheight(const wallet_rpc::COMMAND_RPC_GET_HEIGHT::request& req, wallet_rpc::COMMAND_RPC_GET_HEIGHT::response& res, epee::json_rpc::error& er);
- bool validate_transfer(const std::list<wallet_rpc::transfer_destination>& destinations, const std::string& payment_id, std::vector<cryptonote::tx_destination_entry>& dsts, std::vector<uint8_t>& extra, epee::json_rpc::error& er);
+ bool validate_transfer(const std::list<wallet_rpc::transfer_destination>& destinations, const std::string& payment_id, std::vector<cryptonote::tx_destination_entry>& dsts, std::vector<uint8_t>& extra, bool at_least_one_destination, epee::json_rpc::error& er);
bool on_transfer(const wallet_rpc::COMMAND_RPC_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_TRANSFER::response& res, epee::json_rpc::error& er);
bool on_transfer_split(const wallet_rpc::COMMAND_RPC_TRANSFER_SPLIT::request& req, wallet_rpc::COMMAND_RPC_TRANSFER_SPLIT::response& res, epee::json_rpc::error& er);
bool on_sweep_dust(const wallet_rpc::COMMAND_RPC_SWEEP_DUST::request& req, wallet_rpc::COMMAND_RPC_SWEEP_DUST::response& res, epee::json_rpc::error& er);
diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h
index 8d0b4c8db..76c02039b 100644
--- a/src/wallet/wallet_rpc_server_commands_defs.h
+++ b/src/wallet/wallet_rpc_server_commands_defs.h
@@ -95,8 +95,10 @@ namespace wallet_rpc
struct request
{
uint32_t account_index;
+ std::vector<uint32_t> address_index;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(account_index)
+ KV_SERIALIZE(address_index)
END_KV_SERIALIZE_MAP()
};
@@ -695,6 +697,7 @@ namespace wallet_rpc
uint64_t block_height;
uint64_t unlock_time;
cryptonote::subaddress_index subaddr_index;
+ std::string address;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(payment_id)
@@ -703,6 +706,7 @@ namespace wallet_rpc
KV_SERIALIZE(block_height)
KV_SERIALIZE(unlock_time)
KV_SERIALIZE(subaddr_index)
+ KV_SERIALIZE(address)
END_KV_SERIALIZE_MAP()
};
diff --git a/tests/data/fuzz/base58/ENC1 b/tests/data/fuzz/base58/ENC1
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/data/fuzz/base58/ENC1
diff --git a/tests/data/fuzz/base58/ENC2 b/tests/data/fuzz/base58/ENC2
new file mode 100644
index 000000000..73da627e4
--- /dev/null
+++ b/tests/data/fuzz/base58/ENC2
@@ -0,0 +1 @@
+9zZBkWRgMNPEnVofRFqWK9MKBwgXNyKELBJSttxb1t2UhDM114URntt5iYcXzXusoHZygfSojsbviXZhnP9pJ4p2SDcv81L \ No newline at end of file
diff --git a/tests/data/fuzz/http-client/RESP1 b/tests/data/fuzz/http-client/RESP1
new file mode 100644
index 000000000..3046dc886
--- /dev/null
+++ b/tests/data/fuzz/http-client/RESP1
@@ -0,0 +1,8 @@
+HTTP/1.1 200 Ok
+Server: Epee-based
+Content-Length: 5
+Content-Type: text/plain
+Last-Modified: Mon, 11 Dec 2017 09:03:03 GMT
+Accept-Ranges: bytes
+
+foo
diff --git a/tests/data/fuzz/levin/LEVIN1 b/tests/data/fuzz/levin/LEVIN1
new file mode 100644
index 000000000..51a640c61
--- /dev/null
+++ b/tests/data/fuzz/levin/LEVIN1
Binary files differ
diff --git a/tests/data/fuzz/load-from-binary/BINARY1 b/tests/data/fuzz/load-from-binary/BINARY1
new file mode 100644
index 000000000..c99d7e7bc
--- /dev/null
+++ b/tests/data/fuzz/load-from-binary/BINARY1
Binary files differ
diff --git a/tests/data/fuzz/load-from-json/JSON1 b/tests/data/fuzz/load-from-json/JSON1
new file mode 100644
index 000000000..9e26dfeeb
--- /dev/null
+++ b/tests/data/fuzz/load-from-json/JSON1
@@ -0,0 +1 @@
+{} \ No newline at end of file
diff --git a/tests/data/fuzz/parse-url/URL1 b/tests/data/fuzz/parse-url/URL1
new file mode 100644
index 000000000..e56ea71e3
--- /dev/null
+++ b/tests/data/fuzz/parse-url/URL1
@@ -0,0 +1 @@
+127.0.0.1 \ No newline at end of file
diff --git a/tests/data/fuzz/parse-url/URL2 b/tests/data/fuzz/parse-url/URL2
new file mode 100644
index 000000000..b66e7de9a
--- /dev/null
+++ b/tests/data/fuzz/parse-url/URL2
@@ -0,0 +1 @@
+iframe_test.html?api_url=http://api.vk.com/api.php&api_id=3289090&api_settings=1&viewer_id=562964060&viewer_type=0&sid=0aad8d1c5713130f9ca0076f2b7b47e532877424961367d81e7fa92455f069be7e21bc3193cbd0be11895&secret=368ebbc0ef&access_token=668bc03f43981d883f73876ffff4aa8564254b359cc745dfa1b3cde7bdab2e94105d8f6d8250717569c0a7&user_id=0&group_id=0&is_app_user=1&auth_key=d2f7a895ca5ff3fdb2a2a8ae23fe679a&language=0&parent_language=0&ad_info=ElsdCQBaQlxiAQRdFUVUXiN2AVBzBx5pU1BXIgZUJlIEAWcgAUoLQg==&referrer=unknown&lc_name=9834b6a3&hash= \ No newline at end of file
diff --git a/tests/fuzz/CMakeLists.txt b/tests/fuzz/CMakeLists.txt
index 853d46a12..5d58f9a3c 100644
--- a/tests/fuzz/CMakeLists.txt
+++ b/tests/fuzz/CMakeLists.txt
@@ -89,3 +89,80 @@ set_property(TARGET cold-transaction_fuzz_tests
PROPERTY
FOLDER "tests")
+add_executable(load-from-binary_fuzz_tests load_from_binary.cpp fuzzer.cpp)
+target_link_libraries(load-from-binary_fuzz_tests
+ PRIVATE
+ common
+ epee
+ ${Boost_PROGRAM_OPTIONS_LIBRARY}
+ ${CMAKE_THREAD_LIBS_INIT}
+ ${EXTRA_LIBRARIES})
+set_property(TARGET load-from-binary_fuzz_tests
+ PROPERTY
+ FOLDER "tests")
+
+add_executable(load-from-json_fuzz_tests load_from_json.cpp fuzzer.cpp)
+target_link_libraries(load-from-json_fuzz_tests
+ PRIVATE
+ common
+ epee
+ ${Boost_PROGRAM_OPTIONS_LIBRARY}
+ ${CMAKE_THREAD_LIBS_INIT}
+ ${EXTRA_LIBRARIES})
+set_property(TARGET load-from-json_fuzz_tests
+ PROPERTY
+ FOLDER "tests")
+
+add_executable(base58_fuzz_tests base58.cpp fuzzer.cpp)
+target_link_libraries(base58_fuzz_tests
+ PRIVATE
+ common
+ epee
+ ${Boost_PROGRAM_OPTIONS_LIBRARY}
+ ${CMAKE_THREAD_LIBS_INIT}
+ ${EXTRA_LIBRARIES})
+set_property(TARGET base58_fuzz_tests
+ PROPERTY
+ FOLDER "tests")
+
+add_executable(parse-url_fuzz_tests parse_url.cpp fuzzer.cpp)
+target_link_libraries(parse-url_fuzz_tests
+ PRIVATE
+ epee
+ ${Boost_REGEX_LIBRARY}
+ ${Boost_PROGRAM_OPTIONS_LIBRARY}
+ ${Boost_SYSTEM_LIBRARY}
+ ${CMAKE_THREAD_LIBS_INIT}
+ ${EXTRA_LIBRARIES})
+set_property(TARGET parse-url_fuzz_tests
+ PROPERTY
+ FOLDER "tests")
+
+add_executable(http-client_fuzz_tests http-client.cpp fuzzer.cpp)
+target_link_libraries(http-client_fuzz_tests
+ PRIVATE
+ epee
+ ${Boost_THREAD_LIBRARY}
+ ${Boost_REGEX_LIBRARY}
+ ${Boost_PROGRAM_OPTIONS_LIBRARY}
+ ${Boost_SYSTEM_LIBRARY}
+ ${CMAKE_THREAD_LIBS_INIT}
+ ${EXTRA_LIBRARIES})
+set_property(TARGET http-client_fuzz_tests
+ PROPERTY
+ FOLDER "tests")
+
+add_executable(levin_fuzz_tests levin.cpp fuzzer.cpp)
+target_link_libraries(levin_fuzz_tests
+ PRIVATE
+ common
+ epee
+ ${Boost_THREAD_LIBRARY}
+ ${Boost_REGEX_LIBRARY}
+ ${Boost_PROGRAM_OPTIONS_LIBRARY}
+ ${CMAKE_THREAD_LIBS_INIT}
+ ${EXTRA_LIBRARIES})
+set_property(TARGET levin_fuzz_tests
+ PROPERTY
+ FOLDER "tests")
+
diff --git a/tests/fuzz/base58.cpp b/tests/fuzz/base58.cpp
new file mode 100644
index 000000000..aea62f721
--- /dev/null
+++ b/tests/fuzz/base58.cpp
@@ -0,0 +1,74 @@
+// 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 "common/base58.h"
+#include "fuzzer.h"
+
+class Base58Fuzzer: public Fuzzer
+{
+public:
+ Base58Fuzzer() {}
+ virtual int init();
+ virtual int run(const std::string &filename);
+};
+
+int Base58Fuzzer::init()
+{
+ return 0;
+}
+
+int Base58Fuzzer::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;
+ }
+ try
+ {
+ std::string data;
+ tools::base58::decode(s, data);
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "Failed to load from binary: " << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+}
+
+int main(int argc, const char **argv)
+{
+ Base58Fuzzer fuzzer;
+ return run_fuzzer(argc, argv, fuzzer);
+}
+
diff --git a/tests/fuzz/fuzzer.cpp b/tests/fuzz/fuzzer.cpp
index ede3fcc40..686a5e5f0 100644
--- a/tests/fuzz/fuzzer.cpp
+++ b/tests/fuzz/fuzzer.cpp
@@ -44,41 +44,11 @@ static int __AFL_LOOP(int)
}
#endif
-using namespace epee;
-using namespace boost::program_options;
-
int run_fuzzer(int argc, const char **argv, Fuzzer &fuzzer)
{
- TRY_ENTRY();
- tools::on_startup();
- 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;
+ std::cout << "usage: " << argv[0] << " " << "<filename>" << std::endl;
return 1;
}
@@ -94,6 +64,5 @@ int run_fuzzer(int argc, const char **argv, Fuzzer &fuzzer)
return ret;
}
- CATCH_ENTRY_L0("fuzzer_main", 1);
return 0;
}
diff --git a/tests/fuzz/http-client.cpp b/tests/fuzz/http-client.cpp
new file mode 100644
index 000000000..21560df21
--- /dev/null
+++ b/tests/fuzz/http-client.cpp
@@ -0,0 +1,98 @@
+// 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 "net/http_client.h"
+#include "fuzzer.h"
+
+class dummy_client
+{
+public:
+ bool connect(const std::string& addr, int port, std::chrono::milliseconds timeout, bool ssl = false, const std::string& bind_ip = "0.0.0.0") { return true; }
+ bool connect(const std::string& addr, const std::string& port, std::chrono::milliseconds timeout, bool ssl = false, const std::string& bind_ip = "0.0.0.0") { return true; }
+ bool disconnect() { return true; }
+ bool send(const std::string& buff, std::chrono::milliseconds timeout) { return true; }
+ bool send(const void* data, size_t sz) { return true; }
+ bool is_connected() { return true; }
+ bool recv(std::string& buff, std::chrono::milliseconds timeout)
+ {
+ buff = data;
+ data.clear();
+ return true;
+ }
+
+ void set_test_data(const std::string &s) { data = s; }
+
+private:
+ std::string data;
+};
+
+class HTTPClientFuzzer: public Fuzzer
+{
+public:
+ HTTPClientFuzzer() {}
+ virtual int init();
+ virtual int run(const std::string &filename);
+
+private:
+ epee::net_utils::http::http_simple_client_template<dummy_client> client;
+};
+
+int HTTPClientFuzzer::init()
+{
+ return 0;
+}
+
+int HTTPClientFuzzer::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;
+ }
+ try
+ {
+ client.test(s, std::chrono::milliseconds(1000));
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "Failed to test http client: " << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+}
+
+int main(int argc, const char **argv)
+{
+ HTTPClientFuzzer fuzzer;
+ return run_fuzzer(argc, argv, fuzzer);
+}
+
diff --git a/tests/fuzz/levin.cpp b/tests/fuzz/levin.cpp
new file mode 100644
index 000000000..2fd60ae50
--- /dev/null
+++ b/tests/fuzz/levin.cpp
@@ -0,0 +1,345 @@
+// 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 "net/net_utils_base.h"
+#include "net/abstract_tcp_server2.h"
+#include "storages/levin_abstract_invoke2.h"
+#include "net/levin_protocol_handler_async.h"
+#include "fuzzer.h"
+
+namespace
+{
+ class call_counter
+ {
+ public:
+ call_counter() : m_counter(0) { }
+
+ // memory_order_relaxed is enough for call counter
+ void inc() volatile { m_counter.fetch_add(1, std::memory_order_relaxed); }
+ size_t get() volatile const { return m_counter.load(std::memory_order_relaxed); }
+ void reset() volatile { m_counter.store(0, std::memory_order_relaxed); }
+
+ private:
+ std::atomic<size_t> m_counter;
+ };
+
+ struct test_levin_connection_context : public epee::net_utils::connection_context_base
+ {
+ };
+
+ typedef epee::levin::async_protocol_handler_config<test_levin_connection_context> test_levin_protocol_handler_config;
+ typedef epee::levin::async_protocol_handler<test_levin_connection_context> test_levin_protocol_handler;
+
+ struct test_levin_commands_handler : public epee::levin::levin_commands_handler<test_levin_connection_context>
+ {
+ test_levin_commands_handler()
+ : m_return_code(LEVIN_OK)
+ , m_last_command(-1)
+ {
+ }
+
+ virtual int invoke(int command, const std::string& in_buff, std::string& buff_out, test_levin_connection_context& context)
+ {
+ m_invoke_counter.inc();
+ boost::unique_lock<boost::mutex> lock(m_mutex);
+ m_last_command = command;
+ m_last_in_buf = in_buff;
+ buff_out = m_invoke_out_buf;
+ return m_return_code;
+ }
+
+ virtual int notify(int command, const std::string& in_buff, test_levin_connection_context& context)
+ {
+ m_notify_counter.inc();
+ boost::unique_lock<boost::mutex> lock(m_mutex);
+ m_last_command = command;
+ m_last_in_buf = in_buff;
+ return m_return_code;
+ }
+
+ virtual void callback(test_levin_connection_context& context)
+ {
+ m_callback_counter.inc();
+ //std::cout << "test_levin_commands_handler::callback()" << std::endl;
+ }
+
+ virtual void on_connection_new(test_levin_connection_context& context)
+ {
+ m_new_connection_counter.inc();
+ //std::cout << "test_levin_commands_handler::on_connection_new()" << std::endl;
+ }
+
+ virtual void on_connection_close(test_levin_connection_context& context)
+ {
+ m_close_connection_counter.inc();
+ //std::cout << "test_levin_commands_handler::on_connection_close()" << std::endl;
+ }
+
+ size_t invoke_counter() const { return m_invoke_counter.get(); }
+ size_t notify_counter() const { return m_notify_counter.get(); }
+ size_t callback_counter() const { return m_callback_counter.get(); }
+ size_t new_connection_counter() const { return m_new_connection_counter.get(); }
+ size_t close_connection_counter() const { return m_close_connection_counter.get(); }
+
+ int return_code() const { return m_return_code; }
+ void return_code(int v) { m_return_code = v; }
+
+ const std::string& invoke_out_buf() const { return m_invoke_out_buf; }
+ void invoke_out_buf(const std::string& v) { m_invoke_out_buf = v; }
+
+ int last_command() const { return m_last_command; }
+ const std::string& last_in_buf() const { return m_last_in_buf; }
+
+ private:
+ call_counter m_invoke_counter;
+ call_counter m_notify_counter;
+ call_counter m_callback_counter;
+ call_counter m_new_connection_counter;
+ call_counter m_close_connection_counter;
+
+ boost::mutex m_mutex;
+
+ int m_return_code;
+ std::string m_invoke_out_buf;
+
+ int m_last_command;
+ std::string m_last_in_buf;
+ };
+
+ class test_connection : public epee::net_utils::i_service_endpoint
+ {
+ public:
+ test_connection(boost::asio::io_service& io_service, test_levin_protocol_handler_config& protocol_config)
+ : m_io_service(io_service)
+ , m_protocol_handler(this, protocol_config, m_context)
+ , m_send_return(true)
+ {
+ }
+
+ void start()
+ {
+ m_protocol_handler.after_init_connection();
+ }
+
+ // Implement epee::net_utils::i_service_endpoint interface
+ virtual bool do_send(const void* ptr, size_t cb)
+ {
+ m_send_counter.inc();
+ boost::unique_lock<boost::mutex> lock(m_mutex);
+ m_last_send_data.append(reinterpret_cast<const char*>(ptr), cb);
+ return m_send_return;
+ }
+
+ virtual bool close() { return true; }
+ virtual bool call_run_once_service_io() { return true; }
+ virtual bool request_callback() { return true; }
+ virtual boost::asio::io_service& get_io_service() { return m_io_service; }
+ virtual bool add_ref() { return true; }
+ virtual bool release() { return true; }
+
+ size_t send_counter() const { return m_send_counter.get(); }
+
+ const std::string& last_send_data() const { return m_last_send_data; }
+ void reset_last_send_data() { boost::unique_lock<boost::mutex> lock(m_mutex); m_last_send_data.clear(); }
+
+ bool send_return() const { return m_send_return; }
+ void send_return(bool v) { m_send_return = v; }
+
+ public:
+ test_levin_connection_context m_context;
+ test_levin_protocol_handler m_protocol_handler;
+
+ private:
+ boost::asio::io_service& m_io_service;
+
+ call_counter m_send_counter;
+ boost::mutex m_mutex;
+
+ std::string m_last_send_data;
+
+ bool m_send_return;
+ };
+
+#if 0
+ class async_protocol_handler_test : public ::testing::Test
+ {
+ public:
+ const static uint64_t invoke_timeout = 5 * 1000;
+ const static size_t max_packet_size = 10 * 1024 * 1024;
+
+ typedef std::unique_ptr<test_connection> test_connection_ptr;
+
+ async_protocol_handler_test():
+ m_pcommands_handler(new test_levin_commands_handler()),
+ m_commands_handler(*m_pcommands_handler)
+ {
+ m_handler_config.set_handler(m_pcommands_handler, [](epee::levin::levin_commands_handler<test_levin_connection_context> *handler) { delete handler; });
+ m_handler_config.m_invoke_timeout = invoke_timeout;
+ m_handler_config.m_max_packet_size = max_packet_size;
+ }
+
+ virtual void SetUp()
+ {
+ }
+
+ protected:
+ test_connection_ptr create_connection(bool start = true)
+ {
+ test_connection_ptr conn(new test_connection(m_io_service, m_handler_config));
+ if (start)
+ {
+ conn->start();
+ }
+ return conn;
+ }
+
+ protected:
+ boost::asio::io_service m_io_service;
+ test_levin_protocol_handler_config m_handler_config;
+ test_levin_commands_handler *m_pcommands_handler, &m_commands_handler;
+ };
+
+ class positive_test_connection_to_levin_protocol_handler_calls : public async_protocol_handler_test
+ {
+ };
+
+ class test_levin_protocol_handler__hanle_recv_with_invalid_data : public async_protocol_handler_test
+ {
+ public:
+ static const int expected_command = 5615871;
+ static const int expected_return_code = 782546;
+
+ test_levin_protocol_handler__hanle_recv_with_invalid_data()
+ : m_expected_invoke_out_buf(512, 'y')
+ {
+ }
+
+ virtual void SetUp()
+ {
+ async_protocol_handler_test::SetUp();
+
+ m_conn = create_connection();
+
+ m_in_data.assign(256, 't');
+
+ m_req_head.m_signature = LEVIN_SIGNATURE;
+ m_req_head.m_cb = m_in_data.size();
+ m_req_head.m_have_to_return_data = true;
+ m_req_head.m_command = expected_command;
+ m_req_head.m_return_code = LEVIN_OK;
+ m_req_head.m_flags = LEVIN_PACKET_REQUEST;
+ m_req_head.m_protocol_version = LEVIN_PROTOCOL_VER_1;
+
+ m_commands_handler.return_code(expected_return_code);
+ m_commands_handler.invoke_out_buf(m_expected_invoke_out_buf);
+ }
+
+ protected:
+ void prepare_buf()
+ {
+ m_buf.assign(reinterpret_cast<const char*>(&m_req_head), sizeof(m_req_head));
+ m_buf += m_in_data;
+ }
+
+ protected:
+ test_connection_ptr m_conn;
+ epee::levin::bucket_head2 m_req_head;
+ std::string m_in_data;
+ std::string m_buf;
+ std::string m_expected_invoke_out_buf;
+ };
+#endif
+}
+
+class LevinFuzzer: public Fuzzer
+{
+public:
+ LevinFuzzer() {} //: handler(endpoint, config, context) {}
+ virtual int init();
+ virtual int run(const std::string &filename);
+
+private:
+ //epee::net_utils::connection_context_base context;
+ //epee::levin::async_protocol_handler<> handler;
+};
+
+int LevinFuzzer::init()
+{
+ return 0;
+}
+
+int LevinFuzzer::run(const std::string &filename)
+{
+ std::string s;
+
+//
+ epee::levin::bucket_head2 req_head;
+ req_head.m_signature = LEVIN_SIGNATURE;
+ req_head.m_cb = 0;
+ req_head.m_have_to_return_data = true;
+ req_head.m_command = 2000;
+ req_head.m_flags = LEVIN_PACKET_REQUEST;
+ req_head.m_protocol_version = LEVIN_PROTOCOL_VER_1;
+ FILE *f=fopen("/tmp/out.levin", "w");
+ fwrite(&req_head,sizeof(req_head),1, f);
+ fclose(f);
+//
+ if (!epee::file_io_utils::load_file_to_string(filename, s))
+ {
+ std::cout << "Error: failed to load file " << filename << std::endl;
+ return 1;
+ }
+ try
+ {
+ //std::unique_ptr<test_connection> conn = new test();
+ boost::asio::io_service io_service;
+ test_levin_protocol_handler_config m_handler_config;
+ test_levin_commands_handler *m_pcommands_handler = new test_levin_commands_handler();
+ m_handler_config.set_handler(m_pcommands_handler, [](epee::levin::levin_commands_handler<test_levin_connection_context> *handler) { delete handler; });
+ std::unique_ptr<test_connection> conn(new test_connection(io_service, m_handler_config));
+ conn->start();
+ //m_commands_handler.invoke_out_buf(expected_out_data);
+ //m_commands_handler.return_code(expected_return_code);
+ conn->m_protocol_handler.handle_recv(s.data(), s.size());
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "Failed to test http client: " << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+}
+
+int main(int argc, const char **argv)
+{
+ LevinFuzzer fuzzer;
+ return run_fuzzer(argc, argv, fuzzer);
+}
+
diff --git a/tests/fuzz/load_from_binary.cpp b/tests/fuzz/load_from_binary.cpp
new file mode 100644
index 000000000..3c8dd177b
--- /dev/null
+++ b/tests/fuzz/load_from_binary.cpp
@@ -0,0 +1,76 @@
+// 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 "serialization/keyvalue_serialization.h"
+#include "storages/portable_storage_template_helper.h"
+#include "storages/portable_storage_base.h"
+#include "fuzzer.h"
+
+class PortableStorageFuzzer: public Fuzzer
+{
+public:
+ PortableStorageFuzzer() {}
+ virtual int init();
+ virtual int run(const std::string &filename);
+};
+
+int PortableStorageFuzzer::init()
+{
+ return 0;
+}
+
+int PortableStorageFuzzer::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;
+ }
+ try
+ {
+ epee::serialization::portable_storage ps;
+ ps.load_from_binary(s);
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "Failed to load from binary: " << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+}
+
+int main(int argc, const char **argv)
+{
+ PortableStorageFuzzer fuzzer;
+ return run_fuzzer(argc, argv, fuzzer);
+}
+
diff --git a/tests/fuzz/load_from_json.cpp b/tests/fuzz/load_from_json.cpp
new file mode 100644
index 000000000..5d39c89a6
--- /dev/null
+++ b/tests/fuzz/load_from_json.cpp
@@ -0,0 +1,76 @@
+// 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 "serialization/keyvalue_serialization.h"
+#include "storages/portable_storage_template_helper.h"
+#include "storages/portable_storage_base.h"
+#include "fuzzer.h"
+
+class PortableStorageFuzzer: public Fuzzer
+{
+public:
+ PortableStorageFuzzer() {}
+ virtual int init();
+ virtual int run(const std::string &filename);
+};
+
+int PortableStorageFuzzer::init()
+{
+ return 0;
+}
+
+int PortableStorageFuzzer::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;
+ }
+ try
+ {
+ epee::serialization::portable_storage ps;
+ ps.load_from_json(s);
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "Failed to load from binary: " << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+}
+
+int main(int argc, const char **argv)
+{
+ PortableStorageFuzzer fuzzer;
+ return run_fuzzer(argc, argv, fuzzer);
+}
+
diff --git a/tests/fuzz/parse_url.cpp b/tests/fuzz/parse_url.cpp
new file mode 100644
index 000000000..bf3a3bdd4
--- /dev/null
+++ b/tests/fuzz/parse_url.cpp
@@ -0,0 +1,74 @@
+// 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 "net/net_parse_helpers.h"
+#include "fuzzer.h"
+
+class ParseURLFuzzer: public Fuzzer
+{
+public:
+ ParseURLFuzzer() {}
+ virtual int init();
+ virtual int run(const std::string &filename);
+};
+
+int ParseURLFuzzer::init()
+{
+ return 0;
+}
+
+int ParseURLFuzzer::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;
+ }
+ try
+ {
+ epee::net_utils::http::url_content url;
+ epee::net_utils::parse_url(s, url);
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "Failed to load from binary: " << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+}
+
+int main(int argc, const char **argv)
+{
+ ParseURLFuzzer fuzzer;
+ return run_fuzzer(argc, argv, fuzzer);
+}
+
diff --git a/tests/unit_tests/slow_memmem.cpp b/tests/unit_tests/slow_memmem.cpp
index 0312019be..6e1dcb85f 100644
--- a/tests/unit_tests/slow_memmem.cpp
+++ b/tests/unit_tests/slow_memmem.cpp
@@ -81,7 +81,6 @@ static const struct {
{1,"x",1,"x",0},
{2,"x",1,"",1},
{1,"x",1,"",0},
- {1,"x",2,"",0},
{1,"x",2,"x",0},
{2,"ax",2,"x",0},
{1,"xx",2,"xx",0},
@@ -103,7 +102,7 @@ static const struct {
{8,"xxxxxxab",3,"xyz",0},
{8,"xxxxxxab",6,"abcdef",0},
{9,"\0xxxxxab",3,"ab",6},
- {4,"\0\0a",3,"\0a",1},
+ {4,"\0\0a",3,"\0a",1}, //
};
TEST(slowmem,Success)
@@ -122,7 +121,6 @@ TEST(slowmem,Success)
free(pat);
free(buf);
ASSERT_EQ(res,T[n].res);
-ASSERT_EQ(1,1);
#ifdef VERBOSE
if (res!=T[n].res) printf("failed (got %zu, expected %zu)",res,T[n].res); else printf("ok");
printf("\n");
diff --git a/tests/unit_tests/vercmp.cpp b/tests/unit_tests/vercmp.cpp
index d48dfdf7c..8f359585d 100644
--- a/tests/unit_tests/vercmp.cpp
+++ b/tests/unit_tests/vercmp.cpp
@@ -40,4 +40,6 @@ TEST(vercmp, two_one) { ASSERT_TRUE(tools::vercmp("2", "1") > 0); }
TEST(vercmp, ten_nine) { ASSERT_TRUE(tools::vercmp("10", "9") > 0); }
TEST(vercmp, one_dot_ten_one_dot_nine) { ASSERT_TRUE(tools::vercmp("1.10", "1.9") > 0); }
TEST(vercmp, one_one_dot_nine) { ASSERT_TRUE(tools::vercmp("1", "1.9") < 0); }
+TEST(vercmp, to_master) { ASSERT_TRUE(tools::vercmp("1.0", "1.0-master") < 0); }
+TEST(vercmp, from_master) { ASSERT_TRUE(tools::vercmp("1.0-master", "1.1") < 0); }