Index: src/OFConstantString.m ================================================================== --- src/OFConstantString.m +++ src/OFConstantString.m @@ -573,29 +573,36 @@ [self finishInitialization]; return self.stringByDeletingLastPathComponent; } -- (intmax_t)decimalValue +- (long long)longLongValue +{ + [self finishInitialization]; + + return self.longLongValue; +} + +- (long long)longLongValueWithBase: (int)base +{ + [self finishInitialization]; + + return [self longLongValueWithBase: base]; +} + +- (unsigned long long)unsignedLongLongValue { [self finishInitialization]; - return self.decimalValue; + return self.unsignedLongLongValue; } -- (uintmax_t)hexadecimalValue +- (unsigned long long)unsignedLongLongValueWithBase: (int)base { [self finishInitialization]; - return self.hexadecimalValue; -} - -- (uintmax_t)octalValue -{ - [self finishInitialization]; - - return self.octalValue; + return [self unsignedLongLongValueWithBase: base]; } - (float)floatValue { [self finishInitialization]; Index: src/OFCountedMapTableSet.m ================================================================== --- src/OFCountedMapTableSet.m +++ src/OFCountedMapTableSet.m @@ -136,26 +136,21 @@ [element elementsForName: @"object" namespace: OF_SERIALIZATION_NS]) { void *pool2 = objc_autoreleasePoolPush(); OFXMLElement *object; OFXMLAttribute *countAttribute; - intmax_t signedCount; - uintmax_t count; + unsigned long long count; object = [objectElement elementsForNamespace: OF_SERIALIZATION_NS].firstObject; countAttribute = [objectElement attributeForName: @"count"]; if (object == nil || countAttribute == nil) @throw [OFInvalidFormatException exception]; - signedCount = countAttribute.decimalValue; - if (signedCount < 0) - @throw [OFOutOfRangeException exception]; - - count = signedCount; + count = countAttribute.unsignedLongLongValue; if (count > SIZE_MAX || count > UINTPTR_MAX) @throw [OFOutOfRangeException exception]; [_mapTable setObject: (void *)(uintptr_t)count forKey: object.objectByDeserializing]; Index: src/OFDNSResolverSettings.m ================================================================== --- src/OFDNSResolverSettings.m +++ src/OFDNSResolverSettings.m @@ -32,10 +32,11 @@ #endif #import "OFInvalidFormatException.h" #import "OFOpenItemFailedException.h" #import "OFOutOfMemoryException.h" +#import "OFOutOfRangeException.h" #ifdef OF_WINDOWS # define interface struct # include # undef interface @@ -236,30 +237,41 @@ # if !defined(OF_WINDOWS) && !defined(OF_AMIGAOS4) - (void)parseResolvConfOption: (OFString *)option { @try { if ([option hasPrefix: @"ndots:"]) { + unsigned long long number; + option = [option substringWithRange: of_range(6, option.length - 6)]; + number = option.unsignedLongLongValue; + + if (number > UINT_MAX) + @throw [OFOutOfRangeException exception]; - _minNumberOfDotsInAbsoluteName = - (unsigned int)option.decimalValue; + _minNumberOfDotsInAbsoluteName = (unsigned int)number; } else if ([option hasPrefix: @"timeout:"]) { option = [option substringWithRange: of_range(8, option.length - 8)]; - _timeout = option.decimalValue; + _timeout = option.unsignedLongLongValue; } else if ([option hasPrefix: @"attempts:"]) { + unsigned long long number; + option = [option substringWithRange: of_range(9, option.length - 9)]; + number = option.unsignedLongLongValue; + + if (number > UINT_MAX) + @throw [OFOutOfRangeException exception]; - _maxAttempts = (unsigned int)option.decimalValue; + _maxAttempts = (unsigned int)number; } else if ([option hasPrefix: @"reload-period:"]) { option = [option substringWithRange: of_range(14, option.length - 14)]; - _configReloadInterval = option.decimalValue; + _configReloadInterval = option.unsignedLongLongValue; } else if ([option isEqual: @"tcp"]) _usesTCP = true; } @catch (OFInvalidFormatException *e) { } } Index: src/OFDNSResourceRecord.m ================================================================== --- src/OFDNSResourceRecord.m +++ src/OFDNSResourceRecord.m @@ -79,11 +79,12 @@ if ([string isEqual: @"IN"]) DNSClass = OF_DNS_CLASS_IN; else { @try { - DNSClass = (of_dns_class_t)string.decimalValue; + DNSClass = (of_dns_class_t) + [string unsignedLongLongValueWithBase: 0]; } @catch (OFInvalidFormatException *e) { @throw [OFInvalidArgumentException exception]; } } @@ -123,12 +124,12 @@ recordType = OF_DNS_RECORD_TYPE_SRV; else if ([string isEqual: @"ALL"]) recordType = OF_DNS_RECORD_TYPE_ALL; else { @try { - recordType = - (of_dns_record_type_t)string.decimalValue; + recordType = (of_dns_record_type_t) + [string unsignedLongLongValueWithBase: 0]; } @catch (OFInvalidFormatException *e) { @throw [OFInvalidArgumentException exception]; } } Index: src/OFDate.m ================================================================== --- src/OFDate.m +++ src/OFDate.m @@ -360,17 +360,23 @@ { self = [super init]; @try { void *pool = objc_autoreleasePoolPush(); + unsigned long long value; if (![element.name isEqual: self.className] || ![element.namespace isEqual: OF_SERIALIZATION_NS]) @throw [OFInvalidArgumentException exception]; + + value = [element unsignedLongLongValueWithBase: 16]; + + if (value > UINT64_MAX) + @throw [OFOutOfRangeException exception]; _seconds = OF_BSWAP_DOUBLE_IF_LE(OF_INT_TO_DOUBLE_RAW( - OF_BSWAP64_IF_LE(element.hexadecimalValue))); + OF_BSWAP64_IF_LE(value))); objc_autoreleasePoolPop(pool); } @catch (id e) { [self release]; @throw e; Index: src/OFHTTPClient.m ================================================================== --- src/OFHTTPClient.m +++ src/OFHTTPClient.m @@ -77,11 +77,11 @@ @interface OFHTTPClientRequestBodyStream: OFStream { OFHTTPClientRequestHandler *_handler; OFTCPSocket *_socket; bool _chunked; - uintmax_t _toWrite; + unsigned long long _toWrite; bool _atEndOfStream; } - (instancetype)initWithHandler: (OFHTTPClientRequestHandler *)handler socket: (OFTCPSocket *)sock; @@ -91,11 +91,11 @@ @interface OFHTTPClientResponse: OFHTTPResponse { OFTCPSocket *_socket; bool _hasContentLength, _chunked, _keepAlive; bool _atEndOfStream, _setAtEndOfStream; - intmax_t _toRead; + long long _toRead; } @property (nonatomic, setter=of_setKeepAlive:) bool of_keepAlive; - (instancetype)initWithSocket: (OFTCPSocket *)sock; @@ -443,10 +443,12 @@ } } - (bool)handleFirstLine: (OFString *)line { + long long status; + /* * It's possible that the write succeeds on a connection that is * keep-alive, but the connection has already been closed by the remote * end due to a timeout. In this case, we need to reconnect. */ @@ -462,11 +464,16 @@ _version = [[line substringWithRange: of_range(5, 3)] copy]; if (![_version isEqual: @"1.0"] && ![_version isEqual: @"1.1"]) @throw [OFUnsupportedVersionException exceptionWithVersion: _version]; - _status = (int)[line substringWithRange: of_range(9, 3)].decimalValue; + status = [line substringWithRange: of_range(9, 3)].longLongValue; + + if (status < 0 || status > 599) + @throw [OFInvalidServerReplyException exception]; + + _status = (int)status; return true; } - (bool)handleServerHeader: (OFString *)line @@ -730,11 +737,10 @@ { self = [super init]; @try { OFDictionary OF_GENERIC(OFString *, OFString *) *headers; - intmax_t contentLength; OFString *transferEncoding, *contentLengthString; _handler = [handler retain]; _socket = [sock retain]; @@ -747,15 +753,11 @@ if (contentLengthString != nil) { if (_chunked || contentLengthString.length == 0) @throw [OFInvalidArgumentException exception]; - contentLength = contentLengthString.decimalValue; - if (contentLength < 0) - @throw [OFOutOfRangeException exception]; - - _toWrite = contentLength; + _toWrite = contentLengthString.unsignedLongLongValue; } else if (!_chunked) @throw [OFInvalidArgumentException exception]; } @catch (id e) { [self release]; @throw e; @@ -893,15 +895,17 @@ @throw [OFInvalidServerReplyException exception]; _hasContentLength = true; @try { - _toRead = contentLength.decimalValue; + unsigned long long toRead = + contentLength.unsignedLongLongValue; - if (_toRead < 0) - @throw [OFInvalidServerReplyException - exception]; + if (toRead > LLONG_MAX) + @throw [OFOutOfRangeException exception]; + + _toRead = (long long)toRead; } @catch (OFInvalidFormatException *e) { @throw [OFInvalidServerReplyException exception]; } } } @@ -924,11 +928,11 @@ /* Content-Length */ if (!_chunked) { size_t ret; - if (length > (uintmax_t)_toRead) + if (length > (unsigned long long)_toRead) length = (size_t)_toRead; ret = [_socket readIntoBuffer: buffer length: length]; @@ -979,11 +983,11 @@ if (_setAtEndOfStream && _toRead == 0) _atEndOfStream = true; return 0; } else if (_toRead > 0) { - if (length > (uintmax_t)_toRead) + if (length > (unsigned long long)_toRead) length = (size_t)_toRead; length = [_socket readIntoBuffer: buffer length: length]; @@ -1024,12 +1028,17 @@ @throw [OFInvalidServerReplyException exception]; } @try { - if ((_toRead = line.hexadecimalValue) < 0) + unsigned long long toRead = + [line unsignedLongLongValueWithBase: 16]; + + if (toRead > LLONG_MAX) @throw [OFOutOfRangeException exception]; + + _toRead = (long long)toRead; } @catch (OFInvalidFormatException *e) { @throw [OFInvalidServerReplyException exception]; } if (_toRead == 0) { Index: src/OFHTTPCookie.m ================================================================== --- src/OFHTTPCookie.m +++ src/OFHTTPCookie.m @@ -36,11 +36,11 @@ dateWithDateString: value format: @"%a, %d %b %Y %H:%M:%S %z"]; cookie.expires = date; } else if ([lowercaseName isEqual: @"max-age"]) { OFDate *date = [OFDate dateWithTimeIntervalSinceNow: - value.decimalValue]; + value.unsignedLongLongValue]; cookie.expires = date; } else if ([lowercaseName isEqual: @"domain"]) cookie.domain = value; else if ([lowercaseName isEqual: @"path"]) cookie.path = value; Index: src/OFHTTPRequest.m ================================================================== --- src/OFHTTPRequest.m +++ src/OFHTTPRequest.m @@ -212,20 +212,20 @@ - (void)setProtocolVersionString: (OFString *)string { void *pool = objc_autoreleasePoolPush(); OFArray *components = [string componentsSeparatedByString: @"."]; - intmax_t major, minor; + unsigned long long major, minor; of_http_request_protocol_version_t protocolVersion; if (components.count != 2) @throw [OFInvalidFormatException exception]; - major = [components.firstObject decimalValue]; - minor = [components.lastObject decimalValue]; + major = [components.firstObject unsignedLongLongValue]; + minor = [components.lastObject unsignedLongLongValue]; - if (major < 0 || major > UINT8_MAX || minor < 0 || minor > UINT8_MAX) + if (major > UINT8_MAX || minor > UINT8_MAX) @throw [OFOutOfRangeException exception]; protocolVersion.major = (uint8_t)major; protocolVersion.minor = (uint8_t)minor; Index: src/OFHTTPResponse.m ================================================================== --- src/OFHTTPResponse.m +++ src/OFHTTPResponse.m @@ -269,20 +269,20 @@ - (void)setProtocolVersionString: (OFString *)string { void *pool = objc_autoreleasePoolPush(); OFArray *components = [string componentsSeparatedByString: @"."]; - intmax_t major, minor; + unsigned long long major, minor; of_http_request_protocol_version_t protocolVersion; if (components.count != 2) @throw [OFInvalidFormatException exception]; - major = [components.firstObject decimalValue]; - minor = [components.lastObject decimalValue]; + major = [components.firstObject unsignedLongLongValue]; + minor = [components.lastObject unsignedLongLongValue]; - if (major < 0 || major > UINT8_MAX || minor < 0 || minor > UINT8_MAX) + if (major > UINT8_MAX || minor > UINT8_MAX) @throw [OFOutOfRangeException exception]; protocolVersion.major = (uint8_t)major; protocolVersion.minor = (uint8_t)minor; @@ -304,11 +304,11 @@ } - (OFString *)stringWithEncoding: (of_string_encoding_t)encoding { void *pool = objc_autoreleasePoolPush(); - OFString *contentType, *contentLength, *ret; + OFString *contentType, *contentLengthString, *ret; OFData *data; if (encoding == OF_STRING_ENCODING_AUTODETECT && (contentType = [_headers objectForKey: @"Content-Type"]) != nil) encoding = encodingForContentType(contentType); @@ -316,13 +316,21 @@ if (encoding == OF_STRING_ENCODING_AUTODETECT) encoding = OF_STRING_ENCODING_UTF_8; data = [self readDataUntilEndOfStream]; - if ((contentLength = [_headers objectForKey: @"Content-Length"]) != nil) - if (data.count != (size_t)contentLength.decimalValue) + contentLengthString = [_headers objectForKey: @"Content-Length"]; + if (contentLengthString != nil) { + unsigned long long contentLength = + contentLengthString.unsignedLongLongValue; + + if (contentLength > SIZE_MAX) + @throw [OFOutOfRangeException exception]; + + if (data.count != (size_t)contentLength) @throw [OFTruncatedDataException exception]; + } ret = [[OFString alloc] initWithCString: (char *)data.items encoding: encoding length: data.count]; Index: src/OFHTTPServer.m ================================================================== --- src/OFHTTPServer.m +++ src/OFHTTPServer.m @@ -103,17 +103,17 @@ OF_DIRECT_MEMBERS @interface OFHTTPServerRequestBodyStream: OFStream { OFStreamSocket *_socket; bool _chunked; - intmax_t _toRead; + long long _toRead; bool _atEndOfStream, _setAtEndOfStream; } - (instancetype)initWithSocket: (OFStreamSocket *)sock chunked: (bool)chunked - contentLength: (uintmax_t)contentLength; + contentLength: (unsigned long long)contentLength; @end #ifdef OF_HAVE_THREADS OF_DIRECT_MEMBERS @interface OFHTTPServerThread: OFThread @@ -413,25 +413,22 @@ if (line.length == 0) { bool chunked = [[_headers objectForKey: @"Transfer-Encoding"] isEqual: @"chunked"]; OFString *contentLengthString = [_headers objectForKey: @"Content-Length"]; - intmax_t contentLength = 0; + unsigned long long contentLength = 0; if (contentLengthString != nil) { if (chunked || contentLengthString.length == 0) return [self sendErrorAndClose: 400]; @try { contentLength = - contentLengthString.decimalValue; + contentLengthString.unsignedLongLongValue; } @catch (OFInvalidFormatException *e) { return [self sendErrorAndClose: 400]; } - - if (contentLength < 0) - return [self sendErrorAndClose: 400]; } if (chunked || contentLengthString != nil) { [_requestBody release]; _requestBody = nil; @@ -480,12 +477,13 @@ of_range(0, pos)] retain]; @try { of_range_t range = of_range(pos + 1, value.length - pos - 1); - intmax_t portTmp = [value - substringWithRange: range].decimalValue; + unsigned long long portTmp = + [value substringWithRange: range] + .unsignedLongLongValue; if (portTmp < 1 || portTmp > UINT16_MAX) return [self sendErrorAndClose: 400]; _port = (uint16_t)portTmp; @@ -583,18 +581,21 @@ @end @implementation OFHTTPServerRequestBodyStream - (instancetype)initWithSocket: (OFStreamSocket *)sock chunked: (bool)chunked - contentLength: (uintmax_t)contentLength + contentLength: (unsigned long long)contentLength { self = [super init]; @try { + if (contentLength > LLONG_MAX) + @throw [OFOutOfRangeException exception]; + _socket = [sock retain]; _chunked = chunked; - _toRead = contentLength; + _toRead = (long long)contentLength; if (_chunked && _toRead > 0) @throw [OFInvalidArgumentException exception]; } @catch (id e) { [self release]; @@ -631,11 +632,11 @@ /* Content-Length */ if (!_chunked) { size_t ret; - if (length > (uintmax_t)_toRead) + if (length > (unsigned long long)_toRead) length = (size_t)_toRead; ret = [_socket readIntoBuffer: buffer length: length]; @@ -680,11 +681,11 @@ if (_setAtEndOfStream && _toRead == 0) _atEndOfStream = true; return 0; } else if (_toRead > 0) { - if (length > (uintmax_t)_toRead) + if (length > (unsigned long long)_toRead) length = (size_t)_toRead; length = [_socket readIntoBuffer: buffer length: length]; @@ -696,10 +697,11 @@ return length; } else { void *pool = objc_autoreleasePoolPush(); OFString *line; of_range_t range; + unsigned long long toRead; @try { line = [_socket tryReadLine]; } @catch (OFInvalidEncodingException *e) { @throw [OFInvalidFormatException exception]; @@ -723,12 +725,14 @@ @throw [OFTruncatedDataException exception]; else @throw [OFInvalidFormatException exception]; } - if ((_toRead = line.hexadecimalValue) < 0) + toRead = [line unsignedLongLongValueWithBase: 16]; + if (toRead > LLONG_MAX) @throw [OFOutOfRangeException exception]; + _toRead = (long long)toRead; if (_toRead == 0) { _setAtEndOfStream = true; _toRead = -2; } Index: src/OFINICategory.h ================================================================== --- src/OFINICategory.h +++ src/OFINICategory.h @@ -79,12 +79,12 @@ * @param key The key for which the integer value should be returned * @param defaultValue The value to return if the key does not exist * @return The integer value for the specified key or the specified default * value if it does not exist */ -- (intmax_t)integerForKey: (OFString *)key - defaultValue: (intmax_t)defaultValue; +- (long long)integerForKey: (OFString *)key + defaultValue: (long long)defaultValue; /*! * @brief Returns the bool value for the specified key or the specified default * value if it does not exist. * @@ -161,11 +161,11 @@ * the first key/value pair found is changed. * * @param integer The integer to which the value of the key should be set * @param key The key for which the new value should be set */ -- (void)setInteger: (intmax_t)integer +- (void)setInteger: (long long)integer forKey: (OFString *)key; /*! * @brief Sets the value of the specified key to the specified bool. * Index: src/OFINICategory.m ================================================================== --- src/OFINICategory.m +++ src/OFINICategory.m @@ -207,24 +207,21 @@ } return defaultValue; } -- (intmax_t)integerForKey: (OFString *)key - defaultValue: (intmax_t)defaultValue +- (long long)integerForKey: (OFString *)key + defaultValue: (long long)defaultValue { void *pool = objc_autoreleasePoolPush(); OFString *value = [self stringForKey: key defaultValue: nil]; - intmax_t ret; - - if (value != nil) { - if ([value hasPrefix: @"0x"] || [value hasPrefix: @"$"]) - ret = value.hexadecimalValue; - else - ret = value.decimalValue; - } else + long long ret; + + if (value != nil) + ret = [value longLongValueWithBase: 0]; + else ret = defaultValue; objc_autoreleasePoolPop(pool); return ret; @@ -352,16 +349,16 @@ } objc_autoreleasePoolPop(pool); } -- (void)setInteger: (intmax_t)integer +- (void)setInteger: (long long)integer forKey: (OFString *)key { void *pool = objc_autoreleasePoolPush(); - [self setString: [OFString stringWithFormat: @"%jd", integer] + [self setString: [OFString stringWithFormat: @"%lld", integer] forKey: key]; objc_autoreleasePoolPop(pool); } Index: src/OFINIFileSettings.m ================================================================== --- src/OFINIFileSettings.m +++ src/OFINIFileSettings.m @@ -86,11 +86,11 @@ forKey: key]; objc_autoreleasePoolPop(pool); } -- (void)setInteger: (intmax_t)integer +- (void)setInteger: (long long)integer forPath: (OFString *)path { void *pool = objc_autoreleasePoolPush(); OFString *category, *key; @@ -184,16 +184,16 @@ [ret retain]; objc_autoreleasePoolPop(pool); return [ret autorelease]; } -- (intmax_t)integerForPath: (OFString *)path - defaultValue: (intmax_t)defaultValue +- (long long)integerForPath: (OFString *)path + defaultValue: (long long)defaultValue { void *pool = objc_autoreleasePoolPush(); OFString *category, *key; - intmax_t ret; + long long ret; [self of_getCategory: &category andKey: &key forPath: path]; Index: src/OFNumber.m ================================================================== --- src/OFNumber.m +++ src/OFNumber.m @@ -883,22 +883,24 @@ self = [self initWithBool: true]; else if ([stringValue isEqual: @"false"]) self = [self initWithBool: false]; else @throw [OFInvalidArgumentException exception]; - } else if ([typeString isEqual: @"float"]) + } else if ([typeString isEqual: @"float"]) { + unsigned long long value = + [element unsignedLongLongValueWithBase: 16]; + + if (value > UINT64_MAX) + @throw [OFOutOfRangeException exception]; + self = [self initWithDouble: OF_BSWAP_DOUBLE_IF_LE( - OF_INT_TO_DOUBLE_RAW(OF_BSWAP64_IF_LE( - (uint64_t)element.hexadecimalValue)))]; - else if ([typeString isEqual: @"signed"]) - self = [self initWithIntMax: element.doubleValue]; + OF_INT_TO_DOUBLE_RAW(OF_BSWAP64_IF_LE(value)))]; + } else if ([typeString isEqual: @"signed"]) + self = [self initWithLongLong: element.longLongValue]; else if ([typeString isEqual: @"unsigned"]) - /* - * FIXME: This will fail if the value is bigger than - * INTMAX_MAX! - */ - self = [self initWithUIntMax: element.decimalValue]; + self = [self initWithUnsignedLongLong: + element.unsignedLongLongValue]; else @throw [OFInvalidArgumentException exception]; objc_autoreleasePoolPop(pool); } @catch (id e) { Index: src/OFSettings.h ================================================================== --- src/OFSettings.h +++ src/OFSettings.h @@ -81,11 +81,11 @@ * @brief Sets the specified path to the specified integer. * * @param integer The integer to set * @param path The path to store the integer at */ -- (void)setInteger: (intmax_t)integer +- (void)setInteger: (long long)integer forPath: (OFString *)path; /*! * @brief Sets the specified path to the specified bool. * @@ -148,12 +148,12 @@ * * @param path The path for which the integer value should be returned * @param defaultValue The default value to return if the path does not exist * @return The integer value of the specified path */ -- (intmax_t)integerForPath: (OFString *)path - defaultValue: (intmax_t)defaultValue; +- (long long)integerForPath: (OFString *)path + defaultValue: (long long)defaultValue; /*! * @brief Returns the bool for the specified path, or the default value if the * path does not exist. * Index: src/OFSettings.m ================================================================== --- src/OFSettings.m +++ src/OFSettings.m @@ -68,11 +68,11 @@ forPath: (OFString *)path { OF_UNRECOGNIZED_SELECTOR } -- (void)setInteger: (intmax_t)integer +- (void)setInteger: (long long)integer forPath: (OFString *)path { OF_UNRECOGNIZED_SELECTOR } @@ -110,12 +110,12 @@ defaultValue: (OFString *)defaultValue { OF_UNRECOGNIZED_SELECTOR } -- (intmax_t)integerForPath: (OFString *)path - defaultValue: (intmax_t)defaultValue +- (long long)integerForPath: (OFString *)path + defaultValue: (long long)defaultValue { OF_UNRECOGNIZED_SELECTOR } - (bool)boolForPath: (OFString *)path Index: src/OFString+JSONValue.m ================================================================== --- src/OFString+JSONValue.m +++ src/OFString+JSONValue.m @@ -526,11 +526,11 @@ } static inline OFNumber * parseNumber(const char **pointer, const char *stop, size_t *line) { - bool isHex = (*pointer + 1 < stop && (*pointer)[1] == 'x'); + bool isNegative = (*pointer < stop && (*pointer)[0] == '-'); bool hasDecimal = false; size_t i; OFString *string; OFNumber *number; @@ -555,20 +555,20 @@ @try { if (hasDecimal) number = [OFNumber numberWithDouble: string.doubleValue]; - else if (isHex) - number = [OFNumber numberWithIntMax: - string.hexadecimalValue]; else if ([string isEqual: @"Infinity"]) number = [OFNumber numberWithDouble: INFINITY]; else if ([string isEqual: @"-Infinity"]) number = [OFNumber numberWithDouble: -INFINITY]; + else if (isNegative) + number = [OFNumber numberWithLongLong: + [string longLongValueWithBase: 0]]; else - number = [OFNumber numberWithIntMax: - string.decimalValue]; + number = [OFNumber numberWithUnsignedLongLong: + [string unsignedLongLongValueWithBase: 0]]; } @finally { [string release]; } return number; Index: src/OFString+PropertyListValue.m ================================================================== --- src/OFString+PropertyListValue.m +++ src/OFString+PropertyListValue.m @@ -123,11 +123,27 @@ } static OFNumber * parseIntegerElement(OFXMLElement *element) { - return [OFNumber numberWithIntMax: element.decimalValue]; + void *pool = objc_autoreleasePoolPush(); + OFString *stringValue; + OFNumber *ret; + + stringValue = element.stringValue.stringByDeletingEnclosingWhitespaces; + + if ([stringValue hasPrefix: @"-"]) + ret = [OFNumber numberWithLongLong: stringValue.longLongValue]; + else + ret = [OFNumber numberWithUnsignedLongLong: + stringValue.unsignedLongLongValue]; + + [ret retain]; + + objc_autoreleasePoolPop(pool); + + return [ret autorelease]; } static id parseElement(OFXMLElement *element) { Index: src/OFString+Serialization.m ================================================================== --- src/OFString+Serialization.m +++ src/OFString+Serialization.m @@ -50,11 +50,11 @@ version = [root attributeForName: @"version"].stringValue; if (version == nil) @throw [OFInvalidArgumentException exception]; - if (version.decimalValue != 1) + if (version.unsignedLongLongValue != 1) @throw [OFUnsupportedVersionException exceptionWithVersion: version]; elements = [root elementsForNamespace: OF_SERIALIZATION_NS]; Index: src/OFString.h ================================================================== --- src/OFString.h +++ src/OFString.h @@ -169,47 +169,34 @@ * specified by Unicode! */ @property (readonly, nonatomic) OFString *capitalizedString; /*! - * @brief The decimal value of the string as an `intmax_t`. + * @brief The decimal value of the string as a `long long`. * * Leading and trailing whitespaces are ignored. * * If the string contains any non-number characters, an * @ref OFInvalidFormatException is thrown. * - * If the number is too big to fit into an `intmax_t`, an + * If the number is too big to fit into an `long long`, an * @ref OFOutOfRangeException is thrown. */ -@property (readonly, nonatomic) intmax_t decimalValue; +@property (readonly, nonatomic) long long longLongValue; /*! - * @brief The hexadecimal value of the string as an `uintmax_t`. + * @brief The decimal value of the string as an `unsigned long long`. * * Leading and trailing whitespaces are ignored. * * If the string contains any non-number characters, an * @ref OFInvalidFormatException is thrown. * - * If the number is too big to fit into an `uintmax_t`, an - * @ref OFOutOfRangeException is thrown. - */ -@property (readonly, nonatomic) uintmax_t hexadecimalValue; - -/*! - * @brief The octal value of the string as an `uintmax_t`. - * - * Leading and trailing whitespaces are ignored. - * - * If the string contains any non-number characters, an - * @ref OFInvalidFormatException is thrown. - * - * If the number is too big to fit into an `uintmax_t`, an - * @ref OFOutOfRangeException is thrown. - */ -@property (readonly, nonatomic) uintmax_t octalValue; + * If the number is too big to fit into an `unsigned long long`, an + * @ref OFOutOfRangeException is thrown. + */ +@property (readonly, nonatomic) unsigned long long unsignedLongLongValue; /*! * @brief The float value of the string as a float. * * If the string contains any non-number characters, an @@ -1023,10 +1010,49 @@ * @param range The range of the substring * @return The substring as a new autoreleased OFString */ - (OFString *)substringWithRange: (of_range_t)range; +/*! + * @brief The value of the string in the specified base as a `long long`. + * + * Leading and trailing whitespaces are ignored. + * + * If the string contains any non-number characters, an + * @ref OFInvalidFormatException is thrown. + * + * If the number is too big to fit into an `long long`, an + * @ref OFOutOfRangeException is thrown. + * + * @param base The base to use. If the base is 0, base 16 is assumed if the + * string starts with 0x (after stripping white spaces). If the + * string starts with 0, base 8 is assumed. Otherwise, base 10 is + * assumed. + * @return The value of the string in the specified base + */ +- (long long)longLongValueWithBase: (int)base; + +/*! + * @brief The value of the string in the specified base as an + * `unsigned long long`. + * + * Leading and trailing whitespaces are ignored. + * + * If the string contains any non-number characters, an + * @ref OFInvalidFormatException is thrown. + * + * If the number is too big to fit into an `unsigned long long`, an + * @ref OFOutOfRangeException is thrown. + * + * @param base The base to use. If the base is 0, base 16 is assumed if the + * string starts with 0x (after stripping white spaces). If the + * string starts with 0, base 8 is assumed. Otherwise, base 10 is + * assumed. + * @return The value of the string in the specified base + */ +- (unsigned long long)unsignedLongLongValueWithBase: (int)base; + /*! * @brief Creates a new string by appending another string. * * @param string The string to append * @return A new, autoreleased OFString with the specified string appended Index: src/OFString.m ================================================================== --- src/OFString.m +++ src/OFString.m @@ -15,10 +15,11 @@ * file. */ #include "config.h" +#include #include #include #include #include #include @@ -2311,183 +2312,86 @@ objc_autoreleasePoolPop(pool); return array; } -- (intmax_t)decimalValue +- (long long)longLongValue +{ + return [self longLongValueWithBase: 10]; +} + +- (long long)longLongValueWithBase: (int)base { void *pool = objc_autoreleasePoolPush(); - const of_unichar_t *characters = self.characters; - size_t i = 0, length = self.length; - intmax_t value = 0; - bool expectWhitespace = false; - - while (length > 0 && of_ascii_isspace(*characters)) { - characters++; - length--; - } - - if (length == 0) { - objc_autoreleasePoolPop(pool); - return 0; - } - - if (characters[0] == '-' || characters[0] == '+') - i++; - - for (; i < length; i++) { - if (expectWhitespace) { - if (of_ascii_isspace(characters[i])) - continue; - - @throw [OFInvalidFormatException exception]; - } - - if (characters[i] >= '0' && characters[i] <= '9') { - if (INTMAX_MAX / 10 < value || - INTMAX_MAX - value * 10 < characters[i] - '0') - @throw [OFOutOfRangeException exception]; - - value = (value * 10) + (characters[i] - '0'); - } else if (of_ascii_isspace(characters[i])) - expectWhitespace = true; - else - @throw [OFInvalidFormatException exception]; - } - - if (characters[0] == '-') - value *= -1; + const char *UTF8String = self.UTF8String; + char *endPointer = NULL; + long long value; + + value = strtoll(UTF8String, &endPointer, base); + + if ((value == LLONG_MIN || value == LLONG_MAX) && errno == ERANGE) + @throw [OFOutOfRangeException exception]; + + /* Check if there are any invalid chars left */ + if (endPointer != NULL) + for (; *endPointer != '\0'; endPointer++) + /* Use isspace since strtoll uses the same. */ + if (!isspace(*endPointer)) + @throw [OFInvalidFormatException exception]; objc_autoreleasePoolPop(pool); return value; } -- (uintmax_t)hexadecimalValue -{ - void *pool = objc_autoreleasePoolPush(); - const of_unichar_t *characters = self.characters; - size_t i = 0, length = self.length; - uintmax_t value = 0; - bool expectWhitespace = false, foundValue = false; - - while (length > 0 && of_ascii_isspace(*characters)) { - characters++; - length--; - } - - if (length == 0) { - objc_autoreleasePoolPop(pool); - return 0; - } - - if (length >= 2 && characters[0] == '0' && characters[1] == 'x') - i = 2; - else if (length >= 1 && (characters[0] == 'x' || characters[0] == '$')) - i = 1; - - for (; i < length; i++) { - uintmax_t newValue; - - if (expectWhitespace) { - if (of_ascii_isspace(characters[i])) - continue; - - @throw [OFInvalidFormatException exception]; - } - - if (characters[i] >= '0' && characters[i] <= '9') { - newValue = (value << 4) | (characters[i] - '0'); - foundValue = true; - } else if (characters[i] >= 'A' && characters[i] <= 'F') { - newValue = (value << 4) | (characters[i] - 'A' + 10); - foundValue = true; - } else if (characters[i] >= 'a' && characters[i] <= 'f') { - newValue = (value << 4) | (characters[i] - 'a' + 10); - foundValue = true; - } else if (characters[i] == 'h' || - of_ascii_isspace(characters[i])) { - expectWhitespace = true; - continue; - } else - @throw [OFInvalidFormatException exception]; - - if (newValue < value) - @throw [OFOutOfRangeException exception]; - - value = newValue; - } - - if (!foundValue) - @throw [OFInvalidFormatException exception]; - - objc_autoreleasePoolPop(pool); - - return value; -} - -- (uintmax_t)octalValue -{ - void *pool = objc_autoreleasePoolPush(); - const of_unichar_t *characters = self.characters; - size_t i = 0, length = self.length; - uintmax_t value = 0; - bool expectWhitespace = false; - - while (length > 0 && of_ascii_isspace(*characters)) { - characters++; - length--; - } - - if (length == 0) { - objc_autoreleasePoolPop(pool); - return 0; - } - - for (; i < length; i++) { - uintmax_t newValue; - - if (expectWhitespace) { - if (of_ascii_isspace(characters[i])) - continue; - - @throw [OFInvalidFormatException exception]; - } - - if (characters[i] >= '0' && characters[i] <= '7') - newValue = (value << 3) | (characters[i] - '0'); - else if (of_ascii_isspace(characters[i])) { - expectWhitespace = true; - continue; - } else - @throw [OFInvalidFormatException exception]; - - if (newValue < value) - @throw [OFOutOfRangeException exception]; - - value = newValue; - } +- (unsigned long long)unsignedLongLongValue +{ + return [self unsignedLongLongValueWithBase: 10]; +} + +- (unsigned long long)unsignedLongLongValueWithBase: (int)base +{ + void *pool = objc_autoreleasePoolPush(); + const char *UTF8String = self.UTF8String; + char *endPointer = NULL; + unsigned long long value; + + /* Use isspace since strtoull uses the same. */ + while (isspace(*UTF8String)) + UTF8String++; + + if (*UTF8String == '-') + @throw [OFInvalidFormatException exception]; + + value = strtoull(UTF8String, &endPointer, base); + + if (value == ULLONG_MAX && errno == ERANGE) + @throw [OFOutOfRangeException exception]; + + /* Check if there are any invalid chars left */ + if (endPointer != NULL) + for (; *endPointer != '\0'; endPointer++) + /* Use isspace since strtoull uses the same. */ + if (!isspace(*endPointer)) + @throw [OFInvalidFormatException exception]; objc_autoreleasePoolPop(pool); return value; } - (float)floatValue { void *pool = objc_autoreleasePoolPush(); - -#if defined(OF_AMIGAOS_M68K) || defined(OF_MORPHOS) OFString *stripped = self.stringByDeletingEnclosingWhitespaces; if ([stripped caseInsensitiveCompare: @"INF"] == OF_ORDERED_SAME || [stripped caseInsensitiveCompare: @"INFINITY"] == OF_ORDERED_SAME) return INFINITY; if ([stripped caseInsensitiveCompare: @"-INF"] == OF_ORDERED_SAME || [stripped caseInsensitiveCompare: @"-INFINITY"] == OF_ORDERED_SAME) return -INFINITY; -#endif #ifdef HAVE_STRTOF_L const char *UTF8String = self.UTF8String; #else /* @@ -2500,23 +2404,24 @@ withString: decimalPoint].UTF8String; #endif char *endPointer = NULL; float value; - while (of_ascii_isspace(*UTF8String)) - UTF8String++; - #ifdef HAVE_STRTOF_L value = strtof_l(UTF8String, &endPointer, cLocale); #else value = strtof(UTF8String, &endPointer); #endif + if (value == HUGE_VALF) + @throw [OFOutOfRangeException exception]; + /* Check if there are any invalid chars left */ if (endPointer != NULL) for (; *endPointer != '\0'; endPointer++) - if (!of_ascii_isspace(*endPointer)) + /* Use isspace since strtof uses the same. */ + if (!isspace(*endPointer)) @throw [OFInvalidFormatException exception]; objc_autoreleasePoolPop(pool); return value; @@ -2523,21 +2428,18 @@ } - (double)doubleValue { void *pool = objc_autoreleasePoolPush(); - -#if defined(OF_AMIGAOS_M68K) || defined(OF_MORPHOS) OFString *stripped = self.stringByDeletingEnclosingWhitespaces; if ([stripped caseInsensitiveCompare: @"INF"] == OF_ORDERED_SAME || [stripped caseInsensitiveCompare: @"INFINITY"] == OF_ORDERED_SAME) return INFINITY; if ([stripped caseInsensitiveCompare: @"-INF"] == OF_ORDERED_SAME || [stripped caseInsensitiveCompare: @"-INFINITY"] == OF_ORDERED_SAME) return -INFINITY; -#endif #ifdef HAVE_STRTOD_L const char *UTF8String = self.UTF8String; #else /* @@ -2550,23 +2452,24 @@ withString: decimalPoint].UTF8String; #endif char *endPointer = NULL; double value; - while (of_ascii_isspace(*UTF8String)) - UTF8String++; - #ifdef HAVE_STRTOD_L value = strtod_l(UTF8String, &endPointer, cLocale); #else value = strtod(UTF8String, &endPointer); #endif + if (value == HUGE_VAL) + @throw [OFOutOfRangeException exception]; + /* Check if there are any invalid chars left */ if (endPointer != NULL) for (; *endPointer != '\0'; endPointer++) - if (!of_ascii_isspace(*endPointer)) + /* Use isspace since strtod uses the same. */ + if (!isspace(*endPointer)) @throw [OFInvalidFormatException exception]; objc_autoreleasePoolPop(pool); return value; Index: src/OFTarArchiveEntry.m ================================================================== --- src/OFTarArchiveEntry.m +++ src/OFTarArchiveEntry.m @@ -51,24 +51,25 @@ for (size_t i = cStringLength; i < length; i++) buffer[i] = '\0'; } -static uintmax_t -octalValueFromBuffer(const unsigned char *buffer, size_t length, uintmax_t max) +static unsigned long long +octalValueFromBuffer(const unsigned char *buffer, size_t length, + unsigned long long max) { - uintmax_t value = 0; + unsigned long long value = 0; if (length == 0) return 0; if (buffer[0] == 0x80) { for (size_t i = 1; i < length; i++) value = (value << 8) | buffer[i]; } else - value = stringFromBuffer(buffer, length, - OF_STRING_ENCODING_ASCII).octalValue; + value = [stringFromBuffer(buffer, length, + OF_STRING_ENCODING_ASCII) unsignedLongLongValueWithBase: 8]; if (value > max) @throw [OFOutOfRangeException exception]; return value; Index: src/OFURL.m ================================================================== --- src/OFURL.m +++ src/OFURL.m @@ -486,16 +486,16 @@ portString = [OFString stringWithUTF8String: tmp2 length: UTF8String - tmp2]; if (portString.length == 0 || - portString.decimalValue > 65535) + portString.unsignedLongLongValue > 65535) @throw [OFInvalidFormatException exception]; _port = [[OFNumber alloc] initWithUInt16: - (uint16_t)portString.decimalValue]; + (uint16_t)portString.unsignedLongLongValue]; } else if (*UTF8String != '\0') @throw [OFInvalidFormatException exception]; isIPv6Host = true; } else if ((tmp2 = strchr(UTF8String, ':')) != NULL) { @@ -507,15 +507,15 @@ _URLEncodedHost = [[OFString alloc] initWithUTF8String: UTF8String]; portString = [OFString stringWithUTF8String: tmp2]; - if (portString.decimalValue > 65535) + if (portString.unsignedLongLongValue > 65535) @throw [OFInvalidFormatException exception]; _port = [[OFNumber alloc] initWithUInt16: - (uint16_t)portString.decimalValue]; + (uint16_t)portString.unsignedLongLongValue]; } else _URLEncodedHost = [[OFString alloc] initWithUTF8String: UTF8String]; if (!isIPv6Host) Index: src/OFXMLNode.h ================================================================== --- src/OFXMLNode.h +++ src/OFXMLNode.h @@ -39,18 +39,18 @@ * single child with the specified string value. */ @property (nonatomic, copy) OFString *stringValue; /*! - * @brief The contents of the receiver as a decimal value. + * @brief The contents of the receiver as a `long long` value. */ -@property (readonly, nonatomic) intmax_t decimalValue; +@property (readonly, nonatomic) long long longLongValue; /*! - * @brief The contents of the receiver as a hexadecimal value. + * @brief The contents of the receiver as an `unsigned long long` value. */ -@property (readonly, nonatomic) uintmax_t hexadecimalValue; +@property (readonly, nonatomic) unsigned long long unsignedLongLongValue; /*! * @brief The contents of the receiver as a float value. */ @property (readonly, nonatomic) float floatValue; @@ -87,8 +87,34 @@ * @return An OFString representing the OFXMLNode as an XML string with * indentation */ - (OFString *)XMLStringWithIndentation: (unsigned int)indentation level: (unsigned int)level; + +/*! + * @brief The contents of the receiver as a `long long` value in the specified + * base. + * + * @param base The base to use. If the base is 0, base 16 is assumed if the + * string starts with 0x (after stripping white spaces). If the + * string starts with 0, base 8 is assumed. Otherwise, base 10 is + * assumed. + * @return The contents of the receiver as a `long long` value in the specified + * base + */ +- (long long)longLongValueWithBase: (int)base; + +/*! + * @brief The contents of the receiver as an `unsigned long long` value in the + * specified base. + * + * @param base The base to use. If the base is 0, base 16 is assumed if the + * string starts with 0x (after stripping white spaces). If the + * string starts with 0, base 8 is assumed. Otherwise, base 10 is + * assumed. + * @return The contents of the receiver as an `unsigned long long` value in the + * specified base + */ +- (unsigned long long)unsignedLongLongValueWithBase: (int)base; @end OF_ASSUME_NONNULL_END Index: src/OFXMLNode.m ================================================================== --- src/OFXMLNode.m +++ src/OFXMLNode.m @@ -44,18 +44,28 @@ - (void)setStringValue: (OFString *)stringValue { OF_UNRECOGNIZED_SELECTOR } -- (intmax_t)decimalValue +- (long long)longLongValue +{ + return self.stringValue.longLongValue; +} + +- (long long)longLongValueWithBase: (int)base +{ + return [self.stringValue longLongValueWithBase: base]; +} + +- (unsigned long long)unsignedLongLongValue { - return self.stringValue.decimalValue; + return self.stringValue.unsignedLongLongValue; } -- (uintmax_t)hexadecimalValue +- (unsigned long long)unsignedLongLongValueWithBase: (int)base { - return self.stringValue.hexadecimalValue; + return [self.stringValue unsignedLongLongValueWithBase: base]; } - (float)floatValue { return self.stringValue.floatValue; Index: src/socket.m ================================================================== --- src/socket.m +++ src/socket.m @@ -374,22 +374,22 @@ @throw [OFInvalidFormatException exception]; addr = 0; for (OFString *component in components) { - intmax_t number; + unsigned long long number; if (component.length == 0) @throw [OFInvalidFormatException exception]; if ([component indexOfCharacterFromSet: whitespaceCharacterSet] != OF_NOT_FOUND) @throw [OFInvalidFormatException exception]; - number = component.decimalValue; + number = component.unsignedLongLongValue; - if (number < 0 || number > UINT8_MAX) + if (number > UINT8_MAX) @throw [OFInvalidFormatException exception]; addr = (addr << 8) | (number & 0xFF); } @@ -401,17 +401,17 @@ } static uint16_t parseIPv6Component(OFString *component) { - uintmax_t number; + unsigned long long number; if ([component indexOfCharacterFromSet: [OFCharacterSet whitespaceCharacterSet]] != OF_NOT_FOUND) @throw [OFInvalidFormatException exception]; - number = component.hexadecimalValue; + number = [component unsignedLongLongValueWithBase: 16]; if (number > UINT16_MAX) @throw [OFInvalidFormatException exception]; return (uint16_t)number; Index: tests/OFStringTests.m ================================================================== --- tests/OFStringTests.m +++ tests/OFStringTests.m @@ -1067,28 +1067,33 @@ [C(@"c:\\..\\asd").stringByStandardizingPath isEqual: @"c:\\..\\asd"]) # endif #endif - TEST(@"-[decimalValue]", - C(@"1234").decimalValue == 1234 && - C(@"\r\n+123 ").decimalValue == 123 && - C(@"-500\t").decimalValue == -500 && - C(@"\t\t\r\n").decimalValue == 0) - - TEST(@"-[hexadecimalValue]", - C(@"123f").hexadecimalValue == 0x123f && - C(@"\t\n0xABcd\r").hexadecimalValue == 0xABCD && - C(@" xbCDE").hexadecimalValue == 0xBCDE && - C(@"$CdEf").hexadecimalValue == 0xCDEF && - C(@"\rFeh ").hexadecimalValue == 0xFE && - C(@"\r\t").hexadecimalValue == 0) - - TEST(@"-[octalValue]", - C(@"1234567").octalValue == 01234567 && - C(@"\r\n123").octalValue == 0123 && - C(@"765\t").octalValue == 0765 && C(@"\t\t\r\n").octalValue == 0) + TEST(@"-[longLongValue]", + C(@"1234").longLongValue == 1234 && + C(@"\r\n+123 ").longLongValue == 123 && + C(@"-500\t").longLongValue == -500 && + [C(@"-0x10\t") longLongValueWithBase: 0] == -0x10 && + C(@"\t\t\r\n").longLongValue == 0 && + [C(@"123f") longLongValueWithBase: 16] == 0x123f && + [C(@"\t\n0xABcd\r") longLongValueWithBase: 0] == 0xABCD && + [C(@"1234567") longLongValueWithBase: 8] == 01234567 && + [C(@"\r\n0123") longLongValueWithBase: 0] == 0123 && + [C(@"765\t") longLongValueWithBase: 8] == 0765 && + [C(@"\t\t\r\n") longLongValueWithBase: 8] == 0) + + TEST(@"-[unsignedLongLongValue]", + C(@"1234").unsignedLongLongValue == 1234 && + C(@"\r\n+123 ").unsignedLongLongValue == 123 && + C(@"\t\t\r\n").unsignedLongLongValue == 0 && + [C(@"123f") unsignedLongLongValueWithBase: 16] == 0x123f && + [C(@"\t\n0xABcd\r") unsignedLongLongValueWithBase: 0] == 0xABCD && + [C(@"1234567") unsignedLongLongValueWithBase: 8] == 01234567 && + [C(@"\r\n0123") unsignedLongLongValueWithBase: 0] == 0123 && + [C(@"765\t") unsignedLongLongValueWithBase: 8] == 0765 && + [C(@"\t\t\r\n") unsignedLongLongValueWithBase: 8] == 0) /* * These test numbers can be generated without rounding if we have IEEE * floating point numbers, thus we can use == on them. */ @@ -1122,25 +1127,21 @@ C(@"\r -INFINITY\n").doubleValue == -INFINITY && isnan(C(@" NAN\t\t").doubleValue)) #undef INPUT #undef EXPECTED - EXPECT_EXCEPTION(@"Detect invalid characters in -[decimalValue] #1", - OFInvalidFormatException, [C(@"abc") decimalValue]) - EXPECT_EXCEPTION(@"Detect invalid characters in -[decimalValue] #2", - OFInvalidFormatException, [C(@"0a") decimalValue]) - EXPECT_EXCEPTION(@"Detect invalid characters in -[decimalValue] #3", - OFInvalidFormatException, [C(@"0 1") decimalValue]) - - EXPECT_EXCEPTION(@"Detect invalid chars in -[hexadecimalValue] #1", - OFInvalidFormatException, [C(@"0xABCDEFG") hexadecimalValue]) - EXPECT_EXCEPTION(@"Detect invalid chars in -[hexadecimalValue] #2", - OFInvalidFormatException, [C(@"0x") hexadecimalValue]) - EXPECT_EXCEPTION(@"Detect invalid chars in -[hexadecimalValue] #3", - OFInvalidFormatException, [C(@"$") hexadecimalValue]) - EXPECT_EXCEPTION(@"Detect invalid chars in -[hexadecimalValue] #4", - OFInvalidFormatException, [C(@"$ ") hexadecimalValue]) + EXPECT_EXCEPTION(@"Detect invalid chars in -[longLongValue] #1", + OFInvalidFormatException, [C(@"abc") longLongValue]) + EXPECT_EXCEPTION(@"Detect invalid chars in -[longLongValue] #2", + OFInvalidFormatException, [C(@"0a") longLongValue]) + EXPECT_EXCEPTION(@"Detect invalid chars in -[longLongValue] #3", + OFInvalidFormatException, [C(@"0 1") longLongValue]) + EXPECT_EXCEPTION(@"Detect invalid chars in -[longLongValue] #4", + OFInvalidFormatException, + [C(@"0xABCDEFG") longLongValueWithBase: 0]) + EXPECT_EXCEPTION(@"Detect invalid chars in -[longLongValue] #5", + OFInvalidFormatException, [C(@"0x") longLongValueWithBase: 0]) EXPECT_EXCEPTION(@"Detect invalid chars in -[floatValue] #1", OFInvalidFormatException, [C(@"0.0a") floatValue]) EXPECT_EXCEPTION(@"Detect invalid chars in -[floatValue] #2", OFInvalidFormatException, [C(@"0 0") floatValue]) @@ -1164,21 +1165,21 @@ */ EXPECT_EXCEPTION(@"Detect invalid chars in -[doubleValue] #3", OFInvalidFormatException, [C(@"0,0") doubleValue]) #endif - EXPECT_EXCEPTION(@"Detect out of range in -[decimalValue]", + EXPECT_EXCEPTION(@"Detect out of range in -[longLongValue]", OFOutOfRangeException, - [C(@"12345678901234567890123456789012345678901234567890" + [C(@"-12345678901234567890123456789012345678901234567890" @"12345678901234567890123456789012345678901234567890") - decimalValue]) + longLongValueWithBase: 16]) - EXPECT_EXCEPTION(@"Detect out of range in -[hexadecimalValue]", + EXPECT_EXCEPTION(@"Detect out of range in -[unsignedLongLongValue]", OFOutOfRangeException, [C(@"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF" @"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF") - hexadecimalValue]) + unsignedLongLongValueWithBase: 16]) TEST(@"-[characters]", (ua = C(@"fööbär🀺").characters) && !memcmp(ua, ucstr + 1, sizeof(ucstr) - 8)) #ifdef OF_BIG_ENDIAN Index: utils/ofhttp/OFHTTP.m ================================================================== --- utils/ofhttp/OFHTTP.m +++ utils/ofhttp/OFHTTP.m @@ -67,11 +67,11 @@ of_http_request_method_t _method; OFMutableDictionary *_clientHeaders; OFHTTPClient *_HTTPClient; char *_buffer; OFStream *_output; - intmax_t _received, _length, _resumedFrom; + unsigned long long _received, _length, _resumedFrom; ProgressBar *_progressBar; } - (void)downloadNextURL; @end @@ -374,18 +374,18 @@ @try { size_t pos = [proxy rangeOfString: @":" options: OF_STRING_SEARCH_BACKWARDS].location; OFString *host; - intmax_t port; + unsigned long long port; if (pos == OF_NOT_FOUND) @throw [OFInvalidFormatException exception]; host = [proxy substringWithRange: of_range(0, pos)]; - port = [proxy substringWithRange: - of_range(pos + 1, proxy.length - pos - 1)].decimalValue; + port = [proxy substringWithRange: of_range(pos + 1, + proxy.length - pos - 1)].unsignedLongLongValue; if (port > UINT16_MAX) @throw [OFOutOfRangeException exception]; [OFTCPSocket setSOCKS5Host: host]; @@ -783,11 +783,11 @@ if (type == nil) type = OF_LOCALIZED(@"type_unknown", @"unknown"); if (lengthString != nil) { - _length = lengthString.decimalValue; + _length = lengthString.unsignedLongLongValue; if (_resumedFrom + _length >= GIBIBYTE) { lengthString = [OFString stringWithFormat: @"%,.2f", (float)(_resumedFrom + _length) / GIBIBYTE]; @@ -1012,14 +1012,14 @@ @try { uintmax_t size = [[OFFileManager defaultManager] attributesOfItemAtPath: _currentFileName].fileSize; OFString *range; - if (size > INTMAX_MAX) + if (size > ULLONG_MAX) @throw [OFOutOfRangeException exception]; - _resumedFrom = (intmax_t)size; + _resumedFrom = (unsigned long long)size; range = [OFString stringWithFormat: @"bytes=%jd-", _resumedFrom]; [clientHeaders setObject: range forKey: @"Range"];