Skip to content

Commit c023092

Browse files
laanwjjonasschnelli
authored andcommitted
univalue: add strict type checking
1 parent 7e98a3c commit c023092

File tree

2 files changed

+91
-20
lines changed

2 files changed

+91
-20
lines changed

src/univalue/univalue.cpp

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,12 @@
66
#include <ctype.h>
77
#include <iomanip>
88
#include <sstream>
9+
#include <stdexcept> // std::runtime_error
10+
911
#include "univalue.h"
1012

13+
#include "utilstrencodings.h" // ParseXX
14+
1115
using namespace std;
1216

1317
const UniValue NullUniValue;
@@ -224,4 +228,77 @@ const UniValue& find_value( const UniValue& obj, const std::string& name)
224228
}
225229

226230
return NullUniValue;
227-
}
231+
}
232+
233+
std::vector<std::string> UniValue::getKeys() const
234+
{
235+
if (typ != VOBJ)
236+
throw std::runtime_error("JSON value is not an object as expected");
237+
return keys;
238+
}
239+
240+
std::vector<UniValue> UniValue::getValues() const
241+
{
242+
if (typ != VOBJ && typ != VARR)
243+
throw std::runtime_error("JSON value is not an object or array as expected");
244+
return values;
245+
}
246+
247+
bool UniValue::get_bool() const
248+
{
249+
if (typ != VBOOL)
250+
throw std::runtime_error("JSON value is not a boolean as expected");
251+
return getBool();
252+
}
253+
254+
std::string UniValue::get_str() const
255+
{
256+
if (typ != VSTR)
257+
throw std::runtime_error("JSON value is not a string as expected");
258+
return getValStr();
259+
}
260+
261+
int UniValue::get_int() const
262+
{
263+
if (typ != VNUM)
264+
throw std::runtime_error("JSON value is not an integer as expected");
265+
int32_t retval;
266+
if (!ParseInt32(getValStr(), &retval))
267+
throw std::runtime_error("JSON integer out of range");
268+
return retval;
269+
}
270+
271+
int64_t UniValue::get_int64() const
272+
{
273+
if (typ != VNUM)
274+
throw std::runtime_error("JSON value is not an integer as expected");
275+
int64_t retval;
276+
if (!ParseInt64(getValStr(), &retval))
277+
throw std::runtime_error("JSON integer out of range");
278+
return retval;
279+
}
280+
281+
double UniValue::get_real() const
282+
{
283+
if (typ != VREAL && typ != VNUM)
284+
throw std::runtime_error("JSON value is not a number as expected");
285+
double retval;
286+
if (!ParseDouble(getValStr(), &retval))
287+
throw std::runtime_error("JSON double out of range");
288+
return retval;
289+
}
290+
291+
const UniValue& UniValue::get_obj() const
292+
{
293+
if (typ != VOBJ)
294+
throw std::runtime_error("JSON value is not an object as expected");
295+
return *this;
296+
}
297+
298+
const UniValue& UniValue::get_array() const
299+
{
300+
if (typ != VARR)
301+
throw std::runtime_error("JSON value is not an array as expected");
302+
return *this;
303+
}
304+

src/univalue/univalue.h

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313

1414
#include <sstream> // .get_int64()
1515
#include <utility> // std::pair
16-
#include <stdlib.h> // atoi(), atof() TODO: remove
1716

1817
class UniValue {
1918
public:
@@ -75,7 +74,7 @@ class UniValue {
7574

7675
bool isNull() const { return (typ == VNULL); }
7776
bool isTrue() const { return (typ == VBOOL) && (val == "1"); }
78-
bool isFalse() const { return (!isTrue()); }
77+
bool isFalse() const { return (typ == VBOOL) && (val != "1"); }
7978
bool isBool() const { return (typ == VBOOL); }
8079
bool isStr() const { return (typ == VSTR); }
8180
bool isNum() const { return (typ == VNUM); }
@@ -140,27 +139,22 @@ class UniValue {
140139
void writeObject(unsigned int prettyIndent, unsigned int indentLevel, std::string& s) const;
141140

142141
public:
143-
//
144-
// The following were added for compatibility with json_spirit.
145-
// Most duplicate other methods, and should be removed.
146-
//
147-
std::vector<std::string> getKeys() const { return keys; }
148-
std::vector<UniValue> getValues() const { return values; }
149-
bool get_bool() const { return getBool(); }
150-
std::string get_str() const { return getValStr(); }
151-
int get_int() const { return atoi(getValStr().c_str()); }
152-
double get_real() const { return atof(getValStr().c_str()); }
153-
const UniValue& get_obj() const { return *this; }
154-
const UniValue& get_array() const { return *this; }
142+
// Strict type-specific getters, these throw std::runtime_error if the
143+
// value is of unexpected type
144+
std::vector<std::string> getKeys() const;
145+
std::vector<UniValue> getValues() const;
146+
bool get_bool() const;
147+
std::string get_str() const;
148+
int get_int() const;
149+
int64_t get_int64() const;
150+
double get_real() const;
151+
const UniValue& get_obj() const;
152+
const UniValue& get_array() const;
153+
155154
enum VType type() const { return getType(); }
156155
bool push_back(std::pair<std::string,UniValue> pear) {
157156
return pushKV(pear.first, pear.second);
158157
}
159-
int64_t get_int64() const {
160-
int64_t ret;
161-
std::istringstream(getValStr()) >> ret;
162-
return ret;
163-
}
164158
friend const UniValue& find_value( const UniValue& obj, const std::string& name);
165159
};
166160

0 commit comments

Comments
 (0)