Skip to content

Commit a04ee0b

Browse files
committed
Fix temporary object access(ss.str().c_str()), which may return wrong value in jsteemann::aoi.
Also add max digits length check.
1 parent 0089248 commit a04ee0b

File tree

1 file changed

+34
-14
lines changed

1 file changed

+34
-14
lines changed

src/ascii-parser-basetype.cc

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,6 +1008,7 @@ bool AsciiParser::ReadBasicType(nonstd::optional<value::uint4> *value) {
10081008

10091009
bool AsciiParser::ReadBasicType(uint32_t *value) {
10101010
std::stringstream ss;
1011+
constexpr uint32_t kMaxDigits = 100;
10111012

10121013
// head character
10131014
bool has_sign = false;
@@ -1042,27 +1043,36 @@ bool AsciiParser::ReadBasicType(uint32_t *value) {
10421043
return false;
10431044
}
10441045

1046+
uint32_t digits=0;
10451047
while (!Eof()) {
1048+
1049+
if (digits > kMaxDigits) {
1050+
return false;
1051+
}
1052+
10461053
char c;
10471054
if (!Char1(&c)) {
10481055
return false;
10491056
}
10501057

10511058
if ((c >= '0') && (c <= '9')) {
10521059
ss << c;
1060+
digits++;
10531061
} else {
10541062
_sr->seek_from_current(-1);
10551063
break;
10561064
}
10571065
}
10581066

1059-
if (has_sign && (ss.str().size() == 1)) {
1067+
std::string str = ss.str();
1068+
1069+
if (has_sign && (str.size() == 1)) {
10601070
// sign only
10611071
PushError("Integer value expected but got sign character only.\n");
10621072
return false;
10631073
}
10641074

1065-
if ((ss.str().size() > 1) && (ss.str()[0] == '0')) {
1075+
if ((str.size() > 1) && (str[0] == '0')) {
10661076
PushError("Zero padded integer value is not allowed.\n");
10671077
return false;
10681078
}
@@ -1071,7 +1081,7 @@ bool AsciiParser::ReadBasicType(uint32_t *value) {
10711081

10721082
#if defined(__cpp_exceptions) || defined(__EXCEPTIONS)
10731083
try {
1074-
(*value) = uint32_t(std::stoull(ss.str()));
1084+
(*value) = uint32_t(std::stoull(str));
10751085
} catch (const std::invalid_argument &e) {
10761086
(void)e;
10771087
PushError("Not an 64bit unsigned integer literal.\n");
@@ -1085,10 +1095,12 @@ bool AsciiParser::ReadBasicType(uint32_t *value) {
10851095
#else
10861096
// use jsteemann/atoi
10871097
int retcode = 0;
1098+
const char* start = str.c_str();
1099+
const char* end = str.c_str() + str.size();
10881100
auto result = jsteemann::atoi<uint32_t>(
1089-
ss.str().c_str(), ss.str().c_str() + ss.str().size(), retcode);
1090-
DCOUT("sz = " << ss.str().size());
1091-
DCOUT("ss = " << ss.str() << ", retcode = " << retcode
1101+
start, end, retcode);
1102+
DCOUT("sz = " << str.size());
1103+
DCOUT("ss = " << str << ", retcode = " << retcode
10921104
<< ", result = " << result);
10931105
if (retcode == jsteemann::SUCCESS) {
10941106
(*value) = result;
@@ -1159,13 +1171,15 @@ bool AsciiParser::ReadBasicType(int64_t *value) {
11591171
}
11601172
}
11611173

1162-
if (has_sign && (ss.str().size() == 1)) {
1174+
std::string str = ss.str();
1175+
1176+
if (has_sign && (str.size() == 1)) {
11631177
// sign only
11641178
PushError("Integer value expected but got sign character only.\n");
11651179
return false;
11661180
}
11671181

1168-
if ((ss.str().size() > 1) && (ss.str()[0] == '0')) {
1182+
if ((str.size() > 1) && (str[0] == '0')) {
11691183
PushError("Zero padded integer value is not allowed.\n");
11701184
return false;
11711185
}
@@ -1175,7 +1189,7 @@ bool AsciiParser::ReadBasicType(int64_t *value) {
11751189
// TODO(syoyo): Use ryu parse.
11761190
#if defined(__cpp_exceptions) || defined(__EXCEPTIONS)
11771191
try {
1178-
(*value) = std::stoull(ss.str());
1192+
(*value) = std::stoull(str);
11791193
} catch (const std::invalid_argument &e) {
11801194
(void)e;
11811195
PushError("Not an 64bit unsigned integer literal.\n");
@@ -1190,8 +1204,10 @@ bool AsciiParser::ReadBasicType(int64_t *value) {
11901204
#else
11911205
// use jsteemann/atoi
11921206
int retcode;
1207+
const char* start = str.c_str();
1208+
const char* end = str.c_str() + str.size();
11931209
auto result = jsteemann::atoi<int64_t>(
1194-
ss.str().c_str(), ss.str().c_str() + ss.str().size(), retcode);
1210+
start, end, retcode);
11951211
if (retcode == jsteemann::SUCCESS) {
11961212
(*value) = result;
11971213
return true;
@@ -1263,13 +1279,15 @@ bool AsciiParser::ReadBasicType(uint64_t *value) {
12631279
}
12641280
}
12651281

1266-
if (has_sign && (ss.str().size() == 1)) {
1282+
std::string str = ss.str();
1283+
1284+
if (has_sign && (str.size() == 1)) {
12671285
// sign only
12681286
PushError("Integer value expected but got sign character only.\n");
12691287
return false;
12701288
}
12711289

1272-
if ((ss.str().size() > 1) && (ss.str()[0] == '0')) {
1290+
if ((str.size() > 1) && (str[0] == '0')) {
12731291
PushError("Zero padded integer value is not allowed.\n");
12741292
return false;
12751293
}
@@ -1279,7 +1297,7 @@ bool AsciiParser::ReadBasicType(uint64_t *value) {
12791297
// TODO(syoyo): Use ryu parse.
12801298
#if defined(__cpp_exceptions) || defined(__EXCEPTIONS)
12811299
try {
1282-
(*value) = std::stoull(ss.str());
1300+
(*value) = std::stoull(str);
12831301
} catch (const std::invalid_argument &e) {
12841302
(void)e;
12851303
PushError("Not an 64bit unsigned integer literal.\n");
@@ -1294,8 +1312,10 @@ bool AsciiParser::ReadBasicType(uint64_t *value) {
12941312
#else
12951313
// use jsteemann/atoi
12961314
int retcode;
1315+
const char* start = str.c_str();
1316+
const char* end = str.c_str() + str.size();
12971317
auto result = jsteemann::atoi<uint64_t>(
1298-
ss.str().c_str(), ss.str().c_str() + ss.str().size(), retcode);
1318+
start, end, retcode);
12991319
if (retcode == jsteemann::SUCCESS) {
13001320
(*value) = result;
13011321
return true;

0 commit comments

Comments
 (0)