check accessing an element past the end of a container
This commit is contained in:
parent
2305bf260d
commit
b49ddc766d
@ -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();
|
||||
}
|
||||
|
@ -2338,7 +2338,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 +2373,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 +2466,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 +2481,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 +2813,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 +2866,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;
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
@ -6637,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
|
||||
@ -8912,6 +8923,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));
|
||||
|
@ -486,7 +486,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;
|
||||
@ -541,6 +541,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())
|
||||
{
|
||||
|
||||
@ -592,7 +599,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;
|
||||
}
|
||||
@ -690,7 +697,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;
|
||||
}
|
||||
@ -887,7 +894,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;
|
||||
}
|
||||
@ -986,7 +993,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;
|
||||
}
|
||||
|
@ -137,7 +137,7 @@ namespace tools
|
||||
bool on_create_account(const wallet_rpc::COMMAND_RPC_CREATE_ACCOUNT::request& req, wallet_rpc::COMMAND_RPC_CREATE_ACCOUNT::response& res, epee::json_rpc::error& er);
|
||||
bool on_label_account(const wallet_rpc::COMMAND_RPC_LABEL_ACCOUNT::request& req, wallet_rpc::COMMAND_RPC_LABEL_ACCOUNT::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);
|
||||
|
Loading…
Reference in New Issue
Block a user