univalue: Throw exception on invalid pushes over silent ignore

This commit is contained in:
MacroFake 2022-07-06 11:46:41 +02:00
parent ccccc17b91
commit fa277cd55d
No known key found for this signature in database
GPG Key ID: CE2B75697E69A548
3 changed files with 49 additions and 48 deletions

View File

@ -82,14 +82,14 @@ public:
bool isArray() const { return (typ == VARR); } bool isArray() const { return (typ == VARR); }
bool isObject() const { return (typ == VOBJ); } bool isObject() const { return (typ == VOBJ); }
bool push_back(const UniValue& val); void push_back(const UniValue& val);
bool push_backV(const std::vector<UniValue>& vec); void push_backV(const std::vector<UniValue>& vec);
template <class It> template <class It>
bool push_backV(It first, It last); void push_backV(It first, It last);
void __pushKV(const std::string& key, const UniValue& val); void __pushKV(const std::string& key, const UniValue& val);
bool pushKV(const std::string& key, const UniValue& val); void pushKV(const std::string& key, const UniValue& val);
bool pushKVs(const UniValue& obj); void pushKVs(const UniValue& obj);
std::string write(unsigned int prettyIndent = 0, std::string write(unsigned int prettyIndent = 0,
unsigned int indentLevel = 0) const; unsigned int indentLevel = 0) const;
@ -140,11 +140,10 @@ public:
}; };
template <class It> template <class It>
bool UniValue::push_backV(It first, It last) void UniValue::push_backV(It first, It last)
{ {
if (typ != VARR) return false; if (typ != VARR) throw std::runtime_error{"JSON value is not an array as expected"};
values.insert(values.end(), first, last); values.insert(values.end(), first, last);
return true;
} }
enum jtokentype { enum jtokentype {

View File

@ -108,53 +108,45 @@ bool UniValue::setObject()
return true; return true;
} }
bool UniValue::push_back(const UniValue& val_) void UniValue::push_back(const UniValue& val_)
{ {
if (typ != VARR) if (typ != VARR) throw std::runtime_error{"JSON value is not an array as expected"};
return false;
values.push_back(val_); values.push_back(val_);
return true;
} }
bool UniValue::push_backV(const std::vector<UniValue>& vec) void UniValue::push_backV(const std::vector<UniValue>& vec)
{ {
if (typ != VARR) if (typ != VARR) throw std::runtime_error{"JSON value is not an array as expected"};
return false;
values.insert(values.end(), vec.begin(), vec.end()); values.insert(values.end(), vec.begin(), vec.end());
return true;
} }
void UniValue::__pushKV(const std::string& key, const UniValue& val_) void UniValue::__pushKV(const std::string& key, const UniValue& val_)
{ {
if (typ != VOBJ) throw std::runtime_error{"JSON value is not an object as expected"};
keys.push_back(key); keys.push_back(key);
values.push_back(val_); values.push_back(val_);
} }
bool UniValue::pushKV(const std::string& key, const UniValue& val_) void UniValue::pushKV(const std::string& key, const UniValue& val_)
{ {
if (typ != VOBJ) if (typ != VOBJ) throw std::runtime_error{"JSON value is not an object as expected"};
return false;
size_t idx; size_t idx;
if (findKey(key, idx)) if (findKey(key, idx))
values[idx] = val_; values[idx] = val_;
else else
__pushKV(key, val_); __pushKV(key, val_);
return true;
} }
bool UniValue::pushKVs(const UniValue& obj) void UniValue::pushKVs(const UniValue& obj)
{ {
if (typ != VOBJ || obj.typ != VOBJ) if (typ != VOBJ || obj.typ != VOBJ) throw std::runtime_error{"JSON value is not an object as expected"};
return false;
for (size_t i = 0; i < obj.keys.size(); i++) for (size_t i = 0; i < obj.keys.size(); i++)
__pushKV(obj.keys[i], obj.values.at(i)); __pushKV(obj.keys[i], obj.values.at(i));
return true;
} }
void UniValue::getObjMap(std::map<std::string,UniValue>& kv) const void UniValue::getObjMap(std::map<std::string,UniValue>& kv) const

View File

@ -85,6 +85,16 @@ BOOST_AUTO_TEST_CASE(univalue_constructor)
BOOST_CHECK_EQUAL(v9.getValStr(), "zappa"); BOOST_CHECK_EQUAL(v9.getValStr(), "zappa");
} }
BOOST_AUTO_TEST_CASE(univalue_push_throw)
{
UniValue j;
BOOST_CHECK_THROW(j.push_back(1), std::runtime_error);
BOOST_CHECK_THROW(j.push_backV({1}), std::runtime_error);
BOOST_CHECK_THROW(j.__pushKV("k", 1), std::runtime_error);
BOOST_CHECK_THROW(j.pushKV("k", 1), std::runtime_error);
BOOST_CHECK_THROW(j.pushKVs({}), std::runtime_error);
}
BOOST_AUTO_TEST_CASE(univalue_typecheck) BOOST_AUTO_TEST_CASE(univalue_typecheck)
{ {
UniValue v1; UniValue v1;
@ -198,13 +208,13 @@ BOOST_AUTO_TEST_CASE(univalue_array)
UniValue arr(UniValue::VARR); UniValue arr(UniValue::VARR);
UniValue v((int64_t)1023LL); UniValue v((int64_t)1023LL);
BOOST_CHECK(arr.push_back(v)); arr.push_back(v);
std::string vStr("zippy"); std::string vStr("zippy");
BOOST_CHECK(arr.push_back(vStr)); arr.push_back(vStr);
const char *s = "pippy"; const char *s = "pippy";
BOOST_CHECK(arr.push_back(s)); arr.push_back(s);
std::vector<UniValue> vec; std::vector<UniValue> vec;
v.setStr("boing"); v.setStr("boing");
@ -213,13 +223,13 @@ BOOST_AUTO_TEST_CASE(univalue_array)
v.setStr("going"); v.setStr("going");
vec.push_back(v); vec.push_back(v);
BOOST_CHECK(arr.push_backV(vec)); arr.push_backV(vec);
BOOST_CHECK(arr.push_back((uint64_t) 400ULL)); arr.push_back(uint64_t{400ULL});
BOOST_CHECK(arr.push_back((int64_t) -400LL)); arr.push_back(int64_t{-400LL});
BOOST_CHECK(arr.push_back((int) -401)); arr.push_back(int{-401});
BOOST_CHECK(arr.push_back(-40.1)); arr.push_back(-40.1);
BOOST_CHECK(arr.push_back(true)); arr.push_back(true);
BOOST_CHECK_EQUAL(arr.empty(), false); BOOST_CHECK_EQUAL(arr.empty(), false);
BOOST_CHECK_EQUAL(arr.size(), 10); BOOST_CHECK_EQUAL(arr.size(), 10);
@ -260,39 +270,39 @@ BOOST_AUTO_TEST_CASE(univalue_object)
strKey = "age"; strKey = "age";
v.setInt(100); v.setInt(100);
BOOST_CHECK(obj.pushKV(strKey, v)); obj.pushKV(strKey, v);
strKey = "first"; strKey = "first";
strVal = "John"; strVal = "John";
BOOST_CHECK(obj.pushKV(strKey, strVal)); obj.pushKV(strKey, strVal);
strKey = "last"; strKey = "last";
const char *cVal = "Smith"; const char* cVal = "Smith";
BOOST_CHECK(obj.pushKV(strKey, cVal)); obj.pushKV(strKey, cVal);
strKey = "distance"; strKey = "distance";
BOOST_CHECK(obj.pushKV(strKey, (int64_t) 25)); obj.pushKV(strKey, int64_t{25});
strKey = "time"; strKey = "time";
BOOST_CHECK(obj.pushKV(strKey, (uint64_t) 3600)); obj.pushKV(strKey, uint64_t{3600});
strKey = "calories"; strKey = "calories";
BOOST_CHECK(obj.pushKV(strKey, (int) 12)); obj.pushKV(strKey, int{12});
strKey = "temperature"; strKey = "temperature";
BOOST_CHECK(obj.pushKV(strKey, (double) 90.012)); obj.pushKV(strKey, double{90.012});
strKey = "moon"; strKey = "moon";
BOOST_CHECK(obj.pushKV(strKey, true)); obj.pushKV(strKey, true);
strKey = "spoon"; strKey = "spoon";
BOOST_CHECK(obj.pushKV(strKey, false)); obj.pushKV(strKey, false);
UniValue obj2(UniValue::VOBJ); UniValue obj2(UniValue::VOBJ);
BOOST_CHECK(obj2.pushKV("cat1", 9000)); obj2.pushKV("cat1", 9000);
BOOST_CHECK(obj2.pushKV("cat2", 12345)); obj2.pushKV("cat2", 12345);
BOOST_CHECK(obj.pushKVs(obj2)); obj.pushKVs(obj2);
BOOST_CHECK_EQUAL(obj.empty(), false); BOOST_CHECK_EQUAL(obj.empty(), false);
BOOST_CHECK_EQUAL(obj.size(), 11); BOOST_CHECK_EQUAL(obj.size(), 11);