[rpcwallet] Clamp walletpassphrase value at 100M seconds

Larger values seem to trigger a bug on macos+libevent (resulting in the
rpc server stopping).
This commit is contained in:
Suhas Daftuar 2018-04-06 11:54:52 -04:00
parent 1d540046fe
commit 662d19ff72
2 changed files with 10 additions and 9 deletions

View file

@ -2349,8 +2349,7 @@ UniValue walletpassphrase(const JSONRPCRequest& request)
"This is needed prior to performing transactions related to private keys such as sending bitcoins\n" "This is needed prior to performing transactions related to private keys such as sending bitcoins\n"
"\nArguments:\n" "\nArguments:\n"
"1. \"passphrase\" (string, required) The wallet passphrase\n" "1. \"passphrase\" (string, required) The wallet passphrase\n"
"2. timeout (numeric, required) The time to keep the decryption key in seconds. Limited to at most 1073741824 (2^30) seconds.\n" "2. timeout (numeric, required) The time to keep the decryption key in seconds; capped at 100000000 (~3 years).\n"
" Any value greater than 1073741824 seconds will be set to 1073741824 seconds.\n"
"\nNote:\n" "\nNote:\n"
"Issuing the walletpassphrase command while the wallet is already unlocked will set a new unlock\n" "Issuing the walletpassphrase command while the wallet is already unlocked will set a new unlock\n"
"time that overrides the old one.\n" "time that overrides the old one.\n"
@ -2383,9 +2382,10 @@ UniValue walletpassphrase(const JSONRPCRequest& request)
if (nSleepTime < 0) { if (nSleepTime < 0) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Timeout cannot be negative."); throw JSONRPCError(RPC_INVALID_PARAMETER, "Timeout cannot be negative.");
} }
// Clamp timeout to 2^30 seconds // Clamp timeout
if (nSleepTime > (int64_t)1 << 30) { constexpr int64_t MAX_SLEEP_TIME = 100000000; // larger values trigger a macos/libevent bug?
nSleepTime = (int64_t)1 << 30; if (nSleepTime > MAX_SLEEP_TIME) {
nSleepTime = MAX_SLEEP_TIME;
} }
if (strWalletPass.length() > 0) if (strWalletPass.length() > 0)

View file

@ -64,14 +64,15 @@ class WalletEncryptionTest(BitcoinTestFramework):
assert_raises_rpc_error(-8, "Timeout cannot be negative.", self.nodes[0].walletpassphrase, passphrase2, -10) assert_raises_rpc_error(-8, "Timeout cannot be negative.", self.nodes[0].walletpassphrase, passphrase2, -10)
# Check the timeout # Check the timeout
# Check a time less than the limit # Check a time less than the limit
expected_time = int(time.time()) + (1 << 30) - 600 MAX_VALUE = 100000000
self.nodes[0].walletpassphrase(passphrase2, (1 << 30) - 600) expected_time = int(time.time()) + MAX_VALUE - 600
self.nodes[0].walletpassphrase(passphrase2, MAX_VALUE - 600)
actual_time = self.nodes[0].getwalletinfo()['unlocked_until'] actual_time = self.nodes[0].getwalletinfo()['unlocked_until']
assert_greater_than_or_equal(actual_time, expected_time) assert_greater_than_or_equal(actual_time, expected_time)
assert_greater_than(expected_time + 5, actual_time) # 5 second buffer assert_greater_than(expected_time + 5, actual_time) # 5 second buffer
# Check a time greater than the limit # Check a time greater than the limit
expected_time = int(time.time()) + (1 << 30) - 1 expected_time = int(time.time()) + MAX_VALUE - 1
self.nodes[0].walletpassphrase(passphrase2, (1 << 33)) self.nodes[0].walletpassphrase(passphrase2, MAX_VALUE + 1000)
actual_time = self.nodes[0].getwalletinfo()['unlocked_until'] actual_time = self.nodes[0].getwalletinfo()['unlocked_until']
assert_greater_than_or_equal(actual_time, expected_time) assert_greater_than_or_equal(actual_time, expected_time)
assert_greater_than(expected_time + 5, actual_time) # 5 second buffer assert_greater_than(expected_time + 5, actual_time) # 5 second buffer