Permalink
Browse files

Return error if precision or exponent of numbers are larger than we s…

…upport. Fixes #127. (See also related issue #128)
  • Loading branch information...
1 parent 4bc6ae1 commit b95c5b64aff3209da683b5d1aedccbc1ad34b8fb Stig Brautaset committed Mar 20, 2012
View
@@ -36,11 +36,22 @@
#define SBStringIsSurrogateLowCharacter(character) ((character >= 0xDC00UL) && (character <= 0xDFFFUL))
#define SBStringIsSurrogateHighCharacter(character) ((character >= 0xD800UL) && (character <= 0xDBFFUL))
+static int const DECIMAL_MAX_PRECISION = 38;
+static int const DECIMAL_EXPONENT_MAX = 127;
+static short const DECIMAL_EXPONENT_MIN = -128;
+static int const LONG_LONG_DIGITS = 20;
+
+static NSCharacterSet *kDecimalDigitCharacterSet;
+
@implementation SBJsonTokeniser
@synthesize error = _error;
@synthesize stream = _stream;
++ (void)initialize {
+ kDecimalDigitCharacterSet = [NSCharacterSet decimalDigitCharacterSet];
+}
+
- (id)init {
self = [super init];
if (self) {
@@ -241,7 +252,6 @@ - (sbjson_token_t)getStringToken:(NSObject**)token {
- (sbjson_token_t)getNumberToken:(NSObject**)token {
NSUInteger numberStart = _stream.index;
- NSCharacterSet *digits = [NSCharacterSet decimalDigitCharacterSet];
unichar ch;
if (![_stream getUnichar:&ch])
@@ -262,13 +272,13 @@ - (sbjson_token_t)getNumberToken:(NSObject**)token {
if (![_stream getNextUnichar:&ch])
return sbjson_token_eof;
- if ([digits characterIsMember:ch]) {
+ if ([kDecimalDigitCharacterSet characterIsMember:ch]) {
self.error = @"Leading zero is illegal in number";
return sbjson_token_error;
}
}
- while ([digits characterIsMember:ch]) {
+ while ([kDecimalDigitCharacterSet characterIsMember:ch]) {
mantissa *= 10;
mantissa += (ch - '0');
mantissa_length++;
@@ -285,7 +295,7 @@ - (sbjson_token_t)getNumberToken:(NSObject**)token {
if (![_stream getNextUnichar:&ch])
return sbjson_token_eof;
- while ([digits characterIsMember:ch]) {
+ while ([kDecimalDigitCharacterSet characterIsMember:ch]) {
mantissa *= 10;
mantissa += (ch - '0');
mantissa_length++;
@@ -321,7 +331,7 @@ - (sbjson_token_t)getNumberToken:(NSObject**)token {
short explicit_exponent = 0;
short explicit_exponent_length = 0;
- while ([digits characterIsMember:ch]) {
+ while ([kDecimalDigitCharacterSet characterIsMember:ch]) {
explicit_exponent *= 10;
explicit_exponent += (ch - '0');
explicit_exponent_length++;
@@ -345,20 +355,29 @@ - (sbjson_token_t)getNumberToken:(NSObject**)token {
self.error = @"No digits after initial minus";
return sbjson_token_error;
- } else if (mantissa_length >= 19) {
-
+ } else if (mantissa_length > DECIMAL_MAX_PRECISION) {
+ self.error = @"Precision is too high";
+ return sbjson_token_error;
+
+ } else if (exponent > DECIMAL_EXPONENT_MAX || exponent < DECIMAL_EXPONENT_MIN) {
+ self.error = @"Exponent out of range";
+ return sbjson_token_error;
+ }
+
+ if (mantissa_length <= LONG_LONG_DIGITS) {
+ if (!isFloat && !hasExponent) {
+ *token = [NSNumber numberWithLongLong: isNegative ? -mantissa : mantissa];
+
+ } else {
+ *token = [NSDecimalNumber decimalNumberWithMantissa:mantissa
+ exponent:exponent
+ isNegative:isNegative];
+ }
+
+ } else {
NSString *number = [_stream stringWithRange:NSMakeRange(numberStart, _stream.index - numberStart)];
*token = [NSDecimalNumber decimalNumberWithString:number];
- } else if (!isFloat && !hasExponent) {
- if (!isNegative)
- *token = [NSNumber numberWithUnsignedLongLong:mantissa];
- else
- *token = [NSNumber numberWithLongLong:-mantissa];
- } else {
- *token = [NSDecimalNumber decimalNumberWithMantissa:mantissa
- exponent:exponent
- isNegative:isNegative];
}
return sbjson_token_number;
View
@@ -17,6 +17,7 @@ Miscellaneous
* Added an optional comparator that is used when sorting keys.
* Be more memory-efficient when parsing long strings containing escaped characters.
* Add a Workspace that includes the sample projects, for ease of browsing.
+* Report error for numbers with exponents outside range of -128 to 127.
3.0 (June 18th, 2011)
@@ -0,0 +1 @@
+Exponent out of range
@@ -0,0 +1 @@
+[1e128]
@@ -0,0 +1 @@
+Exponent out of range
@@ -0,0 +1 @@
+[1e-129]
@@ -0,0 +1 @@
+Precision is too high
@@ -0,0 +1 @@
+[123456789012345678901234567890123456789]
View
@@ -67,7 +67,7 @@ - (void)testData {
}];
- STAssertEquals(count, (NSUInteger)28, nil);
+ STAssertEquals(count, (NSUInteger)31, nil);
}
- (void)testWriteRecursion {

0 comments on commit b95c5b6

Please sign in to comment.