diff --git a/HTMLKit/HTMLInputStreamReader.h b/HTMLKit/HTMLInputStreamReader.h index 372ce50..12a7f2e 100644 --- a/HTMLKit/HTMLInputStreamReader.h +++ b/HTMLKit/HTMLInputStreamReader.h @@ -28,8 +28,8 @@ - (void)unconsumeCurrentInputCharacter; - (BOOL)consumeCharacter:(UTF32Char)character; -- (BOOL)consumeUnsignedInt:(unsigned int *)result; -- (BOOL)consumeHexInt:(unsigned int *)result; +- (BOOL)consumeNumber:(unsigned long long *)result; +- (BOOL)consumeHexNumber:(unsigned long long *)result; - (BOOL)consumeString:(NSString *)string caseSensitive:(BOOL)caseSensitive; - (NSString *)consumeCharactersUpToCharactersInString:(NSString *)characters; - (NSString *)consumeCharactersUpToString:(NSString *)string; diff --git a/HTMLKit/HTMLInputStreamReader.m b/HTMLKit/HTMLInputStreamReader.m index 9ff56e3..b801ffe 100644 --- a/HTMLKit/HTMLInputStreamReader.m +++ b/HTMLKit/HTMLInputStreamReader.m @@ -111,28 +111,27 @@ return NO; } -- (BOOL)consumeUnsignedInt:(unsigned int *)result +- (BOOL)consumeNumber:(unsigned long long *)result { - long long scanned; - BOOL success = [_scanner scanLongLong:&scanned]; - if (success == NO || scanned < 0) return NO; - if (result != NULL) { - *result = MIN(UINT_MAX, (unsigned int)scanned); - } + unsigned long long scanned; + BOOL success = [_scanner scanUnsignedLongLong:&scanned]; + if (success == NO) return NO; + + *result = scanned; _location = _scanner.scanLocation; return success; } -- (BOOL)consumeHexInt:(unsigned int *)result +- (BOOL)consumeHexNumber:(unsigned long long *)result { NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString:@"0123456789ABCDEFabcdef"]; NSString *string = nil; BOOL success = [_scanner scanCharactersFromSet:set intoString:&string]; if (success == NO) return NO; - if (result != NULL) { - *result = MIN(UINT_MAX, (unsigned int)strtoull(string.UTF8String, NULL, 16)); - } + + unsigned long long scanned = strtoull(string.UTF8String, NULL, 16); + *result = scanned; _location = _scanner.scanLocation; return success; } diff --git a/HTMLKit/HTMLTokenizer.m b/HTMLKit/HTMLTokenizer.m index 51537a8..ff99493 100644 --- a/HTMLKit/HTMLTokenizer.m +++ b/HTMLKit/HTMLTokenizer.m @@ -268,17 +268,17 @@ [_inputStreamReader consumeNextInputCharacter]; UTF32Char character = [_inputStreamReader nextInputCharacter]; - unsigned int number; + unsigned long long number; BOOL success; switch (character) { case LATIN_CAPITAL_LETTER_X: case LATIN_SMALL_LETTER_X: [_inputStreamReader consumeNextInputCharacter]; - success = [_inputStreamReader consumeHexInt:&number]; + success = [_inputStreamReader consumeHexNumber:&number]; break; default: - success = [_inputStreamReader consumeUnsignedInt:&number]; + success = [_inputStreamReader consumeNumber:&number]; break; } @@ -292,20 +292,23 @@ [self emitParseError:@"Missing semicolon in numeric entity"]; } - unichar numericReplacement = NumericReplacementCharacter(number); - if (numericReplacement != NULL_CHAR) { - [self emitParseError:@"Invalid numeric entity (a defenied replacement exists)"]; - return StringFromUniChar(numericReplacement); - } if (isInvalidNumericRange(number)) { [self emitParseError:@"Invalid numeric entity (invalid Unicode range)"]; return StringFromUniChar(REPLACEMENT_CHAR); } - if (isControlOrUndefinedCharacter(number)) { + + UTF32Char numericChar = (UTF32Char)number; + unichar numericReplacement = NumericReplacementCharacter(numericChar); + if (numericReplacement != NULL_CHAR) { + [self emitParseError:@"Invalid numeric entity (a defenied replacement exists)"]; + return StringFromUniChar(numericReplacement); + } + + if (isControlOrUndefinedCharacter(numericChar)) { [self emitParseError:@"Invalid numeric entity (control or undefined character)"]; } - return StringFromUTF32Char(number); + return StringFromUTF32Char(numericChar); } - (NSString *)attemptToConsumeNamedCharacterReferenceInAttribute:(BOOL)inAttribute diff --git a/HTMLKit/HTMLTokenizerCharacters.h b/HTMLKit/HTMLTokenizerCharacters.h index 403509d..5071ead 100644 --- a/HTMLKit/HTMLTokenizerCharacters.h +++ b/HTMLKit/HTMLTokenizerCharacters.h @@ -151,10 +151,10 @@ NS_INLINE BOOL isStringAlphanumeric(NSString *string) return ([string rangeOfCharacterFromSet:set].location == NSNotFound); } -NS_INLINE BOOL isInvalidNumericRange(UTF32Char character) +NS_INLINE BOOL isInvalidNumericRange(unsigned long long numeric) { - return ((character >= 0xD800 && character <= 0xDFFF) || - character > 0x10FFFF); + return ((numeric >= 0xD800 && numeric <= 0xDFFF) || + numeric > 0x10FFFF); } NS_INLINE unichar NumericReplacementCharacter(UTF32Char character)