diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 2c5b5ee89..dc6fa338a 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -138,6 +138,7 @@ bool RPCConsole::RPCExecuteCommandLine(std::string &strResult, const std::string { STATE_EATING_SPACES, STATE_EATING_SPACES_IN_ARG, + STATE_EATING_SPACES_IN_BRACKETS, STATE_ARGUMENT, STATE_SINGLEQUOTED, STATE_DOUBLEQUOTED, @@ -222,6 +223,7 @@ bool RPCConsole::RPCExecuteCommandLine(std::string &strResult, const std::string } case STATE_ARGUMENT: // In or after argument case STATE_EATING_SPACES_IN_ARG: + case STATE_EATING_SPACES_IN_BRACKETS: case STATE_EATING_SPACES: // Handle runs of whitespace switch(ch) { @@ -229,6 +231,8 @@ bool RPCConsole::RPCExecuteCommandLine(std::string &strResult, const std::string case '\'': state = STATE_SINGLEQUOTED; break; case '\\': state = STATE_ESCAPE_OUTER; break; case '(': case ')': case '\n': + if (state == STATE_EATING_SPACES_IN_ARG) + throw std::runtime_error("Invalid Syntax"); if (state == STATE_ARGUMENT) { if (ch == '(' && stack.size() && stack.back().size() > 0) @@ -240,7 +244,7 @@ bool RPCConsole::RPCExecuteCommandLine(std::string &strResult, const std::string stack.back().push_back(curarg); curarg.clear(); - state = STATE_EATING_SPACES; + state = STATE_EATING_SPACES_IN_BRACKETS; } if ((ch == ')' || ch == '\n') && stack.size() > 0) { @@ -257,12 +261,20 @@ bool RPCConsole::RPCExecuteCommandLine(std::string &strResult, const std::string } break; case ' ': case ',': case '\t': - if(state == STATE_ARGUMENT || (state == STATE_EATING_SPACES_IN_ARG && ch == ',')) // Space ends argument + if(state == STATE_EATING_SPACES_IN_ARG && curarg.empty() && ch == ',') + throw std::runtime_error("Invalid Syntax"); + + else if(state == STATE_ARGUMENT) // Space ends argument { stack.back().push_back(curarg); curarg.clear(); } - state = (ch == ',' ? STATE_EATING_SPACES_IN_ARG : STATE_EATING_SPACES); + if ((state == STATE_EATING_SPACES_IN_BRACKETS || state == STATE_ARGUMENT) && ch == ',') + { + state = STATE_EATING_SPACES_IN_ARG; + break; + } + state = STATE_EATING_SPACES; break; default: curarg += ch; state = STATE_ARGUMENT; } diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp index 0aeef0455..26ac5e211 100644 --- a/src/qt/test/rpcnestedtests.cpp +++ b/src/qt/test/rpcnestedtests.cpp @@ -15,6 +15,7 @@ #include "util.h" #include +#include #include @@ -77,16 +78,6 @@ void RPCNestedTests::rpcNestedTests() RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo "); //whitespace at the end will be tolerated QVERIFY(result.substr(0,1) == "{"); -#if QT_VERSION >= 0x050300 - // do the QVERIFY_EXCEPTION_THROWN checks only with Qt5.3 and higher (QVERIFY_EXCEPTION_THROWN was introduced in Qt5.3) - QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo() .\n"), std::runtime_error); //invalid syntax - QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo() getblockchaininfo()"), std::runtime_error); //invalid syntax - (RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo(")); //tolerate non closing brackets if we have no arguments - (RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo()()()")); //tolerate non command brackts - QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo(True)"), UniValue); //invalid argument - QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "a(getblockchaininfo(True))"), UniValue); //method not found -#endif - (RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo()[\"chain\"]")); //Quote path identifier are allowed, but look after a child contaning the quotes in the key QVERIFY(result == "null"); @@ -113,8 +104,25 @@ void RPCNestedTests::rpcNestedTests() QVERIFY(result == "[\"abc\",\"abc\"]"); RPCConsole::RPCExecuteCommandLine(result, "rpcNestedTest abc\t\tabc"); QVERIFY(result == "[\"abc\",\"abc\"]"); - RPCConsole::RPCExecuteCommandLine(result, "rpcNestedTest abc,,abc"); - QVERIFY(result == "[\"abc\",\"\",\"abc\"]"); + RPCConsole::RPCExecuteCommandLine(result, "rpcNestedTest(abc )"); + QVERIFY(result == "[\"abc\"]"); + RPCConsole::RPCExecuteCommandLine(result, "rpcNestedTest( abc )"); + QVERIFY(result == "[\"abc\"]"); + RPCConsole::RPCExecuteCommandLine(result, "rpcNestedTest( abc , cba )"); + QVERIFY(result == "[\"abc\",\"cba\"]"); + +#if QT_VERSION >= 0x050300 + // do the QVERIFY_EXCEPTION_THROWN checks only with Qt5.3 and higher (QVERIFY_EXCEPTION_THROWN was introduced in Qt5.3) + QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo() .\n"), std::runtime_error); //invalid syntax + QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo() getblockchaininfo()"), std::runtime_error); //invalid syntax + (RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo(")); //tolerate non closing brackets if we have no arguments + (RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo()()()")); //tolerate non command brackts + QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo(True)"), UniValue); //invalid argument + QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "a(getblockchaininfo(True))"), UniValue); //method not found + QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "rpcNestedTest abc,,abc"), std::runtime_error); //don't tollerate empty arguments when using , + QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "rpcNestedTest(abc,,abc)"), std::runtime_error); //don't tollerate empty arguments when using , + QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "rpcNestedTest(abc,,)"), std::runtime_error); //don't tollerate empty arguments when using , +#endif delete pcoinsTip; delete pcoinsdbview;