Branch data Line data Source code
# 1 : : // Copyright 2014 BitPay Inc. # 2 : : // Copyright 2015 Bitcoin Core Developers # 3 : : // Distributed under the MIT software license, see the accompanying # 4 : : // file COPYING or https://opensource.org/licenses/mit-license.php. # 5 : : # 6 : : #include <stdint.h> # 7 : : #include <errno.h> # 8 : : #include <string.h> # 9 : : #include <stdlib.h> # 10 : : #include <stdexcept> # 11 : : #include <vector> # 12 : : #include <limits> # 13 : : #include <string> # 14 : : #include <sstream> # 15 : : # 16 : : #include "univalue.h" # 17 : : # 18 : : namespace # 19 : : { # 20 : : static bool ParsePrechecks(const std::string& str) # 21 : 57066 : { # 22 [ - + ]: 57066 : if (str.empty()) // No empty string allowed # 23 : 0 : return false; # 24 [ + - ][ - + ]: 57066 : if (str.size() >= 1 && (json_isspace(str[0]) || json_isspace(str[str.size()-1]))) // No padding allowed # [ - + ] # 25 : 0 : return false; # 26 [ - + ]: 57066 : if (str.size() != strlen(str.c_str())) // No embedded NUL characters allowed # 27 : 0 : return false; # 28 : 57066 : return true; # 29 : 57066 : } # 30 : : # 31 : : bool ParseInt32(const std::string& str, int32_t *out) # 32 : 54450 : { # 33 [ - + ]: 54450 : if (!ParsePrechecks(str)) # 34 : 0 : return false; # 35 : 54450 : char *endp = nullptr; # 36 : 54450 : errno = 0; // strtol will not set errno if valid # 37 : 54450 : long int n = strtol(str.c_str(), &endp, 10); # 38 [ + - ]: 54450 : if(out) *out = (int32_t)n; # 39 : : // Note that strtol returns a *long int*, so even if strtol doesn't report an over/underflow # 40 : : // we still have to check that the returned value is within the range of an *int32_t*. On 64-bit # 41 : : // platforms the size of these types may be different. # 42 [ + - ][ + - ]: 54450 : return endp && *endp == 0 && !errno && # [ + - ] # 43 [ + - ]: 54450 : n >= std::numeric_limits<int32_t>::min() && # 44 [ + - ]: 54450 : n <= std::numeric_limits<int32_t>::max(); # 45 : 54450 : } # 46 : : # 47 : : bool ParseInt64(const std::string& str, int64_t *out) # 48 : 2582 : { # 49 [ - + ]: 2582 : if (!ParsePrechecks(str)) # 50 : 0 : return false; # 51 : 2582 : char *endp = nullptr; # 52 : 2582 : errno = 0; // strtoll will not set errno if valid # 53 : 2582 : long long int n = strtoll(str.c_str(), &endp, 10); # 54 [ + - ]: 2582 : if(out) *out = (int64_t)n; # 55 : : // Note that strtoll returns a *long long int*, so even if strtol doesn't report a over/underflow # 56 : : // we still have to check that the returned value is within the range of an *int64_t*. # 57 [ + - ][ + + ]: 2582 : return endp && *endp == 0 && !errno && # [ + - ] # 58 [ + - ]: 2582 : n >= std::numeric_limits<int64_t>::min() && # 59 [ + - ]: 2582 : n <= std::numeric_limits<int64_t>::max(); # 60 : 2582 : } # 61 : : # 62 : : bool ParseDouble(const std::string& str, double *out) # 63 : 34 : { # 64 [ - + ]: 34 : if (!ParsePrechecks(str)) # 65 : 0 : return false; # 66 [ + + ][ - + ]: 34 : if (str.size() >= 2 && str[0] == '0' && str[1] == 'x') // No hexadecimal floats allowed # [ # # ] # 67 : 0 : return false; # 68 : 34 : std::istringstream text(str); # 69 : 34 : text.imbue(std::locale::classic()); # 70 : 34 : double result; # 71 : 34 : text >> result; # 72 [ + - ]: 34 : if(out) *out = result; # 73 [ + - ][ + - ]: 34 : return text.eof() && !text.fail(); # 74 : 34 : } # 75 : : } # 76 : : # 77 : : const std::vector<std::string>& UniValue::getKeys() const # 78 : 76292 : { # 79 [ - + ]: 76292 : if (typ != VOBJ) # 80 : 0 : throw std::runtime_error("JSON value is not an object as expected"); # 81 : 76292 : return keys; # 82 : 76292 : } # 83 : : # 84 : : const std::vector<UniValue>& UniValue::getValues() const # 85 : 79571 : { # 86 [ + + ][ - + ]: 79571 : if (typ != VOBJ && typ != VARR) # 87 : 0 : throw std::runtime_error("JSON value is not an object or array as expected"); # 88 : 79571 : return values; # 89 : 79571 : } # 90 : : # 91 : : bool UniValue::get_bool() const # 92 : 5250 : { # 93 [ + + ]: 5250 : if (typ != VBOOL) # 94 : 17 : throw std::runtime_error("JSON value is not a boolean as expected"); # 95 : 5233 : return getBool(); # 96 : 5250 : } # 97 : : # 98 : : const std::string& UniValue::get_str() const # 99 : 523704 : { # 100 [ + + ]: 523704 : if (typ != VSTR) # 101 : 42 : throw std::runtime_error("JSON value is not a string as expected"); # 102 : 523662 : return getValStr(); # 103 : 523704 : } # 104 : : # 105 : : int UniValue::get_int() const # 106 : 54454 : { # 107 [ + + ]: 54454 : if (typ != VNUM) # 108 : 4 : throw std::runtime_error("JSON value is not an integer as expected"); # 109 : 54450 : int32_t retval; # 110 [ - + ]: 54450 : if (!ParseInt32(getValStr(), &retval)) # 111 : 0 : throw std::runtime_error("JSON integer out of range"); # 112 : 54450 : return retval; # 113 : 54450 : } # 114 : : # 115 : : int64_t UniValue::get_int64() const # 116 : 2583 : { # 117 [ + + ]: 2583 : if (typ != VNUM) # 118 : 1 : throw std::runtime_error("JSON value is not an integer as expected"); # 119 : 2582 : int64_t retval; # 120 [ + + ]: 2582 : if (!ParseInt64(getValStr(), &retval)) # 121 : 2 : throw std::runtime_error("JSON integer out of range"); # 122 : 2580 : return retval; # 123 : 2582 : } # 124 : : # 125 : : double UniValue::get_real() const # 126 : 35 : { # 127 [ + + ]: 35 : if (typ != VNUM) # 128 : 1 : throw std::runtime_error("JSON value is not a number as expected"); # 129 : 34 : double retval; # 130 [ - + ]: 34 : if (!ParseDouble(getValStr(), &retval)) # 131 : 0 : throw std::runtime_error("JSON double out of range"); # 132 : 34 : return retval; # 133 : 34 : } # 134 : : # 135 : : const UniValue& UniValue::get_obj() const # 136 : 957591 : { # 137 [ + + ]: 957591 : if (typ != VOBJ) # 138 : 2 : throw std::runtime_error("JSON value is not an object as expected"); # 139 : 957589 : return *this; # 140 : 957591 : } # 141 : : # 142 : : const UniValue& UniValue::get_array() const # 143 : 1264521 : { # 144 [ + + ]: 1264521 : if (typ != VARR) # 145 : 2 : throw std::runtime_error("JSON value is not an array as expected"); # 146 : 1264519 : return *this; # 147 : 1264521 : } # 148 : :