Fix cases where the most negative signed integer was negated, causing

undefined behavior.
This commit is contained in:
Michael Shields 2015-07-27 16:35:19 -07:00
parent d84702c903
commit 7f06e9dc28
2 changed files with 12 additions and 7 deletions

View File

@ -555,7 +555,7 @@ bool Reader::decodeNumber(Token& token, Value& decoded) {
++current;
// TODO: Help the compiler do the div and mod at compile time or get rid of them.
Value::LargestUInt maxIntegerValue =
isNegative ? Value::LargestUInt(-Value::minLargestInt)
isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1
: Value::maxLargestUInt;
Value::LargestUInt threshold = maxIntegerValue / 10;
Value::LargestUInt value = 0;
@ -576,7 +576,9 @@ bool Reader::decodeNumber(Token& token, Value& decoded) {
}
value = value * 10 + digit;
}
if (isNegative)
if (isNegative && value == maxIntegerValue)
decoded = Value::minLargestInt;
else if (isNegative)
decoded = -Value::LargestInt(value);
else if (value <= Value::LargestUInt(Value::maxInt))
decoded = Value::LargestInt(value);

View File

@ -75,12 +75,15 @@ static bool containsControlCharacter0(const char* str, unsigned len) {
std::string valueToString(LargestInt value) {
UIntToStringBuffer buffer;
char* current = buffer + sizeof(buffer);
bool isNegative = value < 0;
if (isNegative)
value = -value;
uintToString(LargestUInt(value), current);
if (isNegative)
if (value == Value::minLargestInt) {
uintToString(LargestUInt(Value::maxLargestInt) + 1, current);
*--current = '-';
} else if (value < 0) {
uintToString(LargestUInt(-value), current);
*--current = '-';
} else {
uintToString(LargestUInt(value), current);
}
assert(current >= buffer);
return current;
}