Index: src/OFString+URLEncoding.m ================================================================== --- src/OFString+URLEncoding.m +++ src/OFString+URLEncoding.m @@ -36,25 +36,25 @@ - (OFString *)stringByURLEncodingWithAllowedCharacters: (const char *)allowed { void *pool = objc_autoreleasePoolPush(); const char *string = [self UTF8String]; - char *retCString; - size_t i; - OFString *ret; + size_t length = [self UTF8StringLength]; + char *retCString, *retCString2; + size_t i = 0; /* * Worst case: 3 times longer than before. * Oh, and we can't use [self allocWithSize:] here as self might be a * @"" literal. */ - if ((retCString = malloc(([self UTF8StringLength] * 3) + 1)) == NULL) + if ((retCString = malloc(length * 3 + 1)) == NULL) @throw [OFOutOfMemoryException exceptionWithRequestedSize: - ([self UTF8StringLength] * 3) + 1]; + length * 3 + 1]; - for (i = 0; *string != '\0'; string++) { - unsigned char c = *string; + while (length--) { + unsigned char c = *string++; if (of_ascii_isalnum(c) || strchr(allowed, c) != NULL) retCString[i++] = c; else { unsigned char high, low; @@ -67,55 +67,57 @@ (high > 9 ? high - 10 + 'A' : high + '0'); retCString[i++] = (low > 9 ? low - 10 + 'A' : low + '0'); } } + retCString[i] = '\0'; objc_autoreleasePoolPop(pool); - @try { - ret = [OFString stringWithUTF8String: retCString - length: i]; - } @finally { - free(retCString); - } - - return ret; + /* We don't care if it fails, as we only made it smaller. */ + if ((retCString2 = realloc(retCString, i + 1)) == NULL) + retCString2 = retCString; + + return [OFString stringWithUTF8StringNoCopy: retCString2 + length: i + freeWhenDone: true]; } - (OFString *)stringByURLDecoding { void *pool = objc_autoreleasePoolPush(); - OFString *ret; const char *string = [self UTF8String]; - char *retCString; + size_t length = [self UTF8StringLength]; + char *retCString, *retCString2; char byte = 0; int state = 0; - size_t i; + size_t i = 0; - if ((retCString = malloc([self UTF8StringLength] + 1)) == NULL) + if ((retCString = malloc(length + 1)) == NULL) @throw [OFOutOfMemoryException - exceptionWithRequestedSize: [self UTF8StringLength] + 1]; + exceptionWithRequestedSize: length + 1]; - for (i = 0; *string; string++) { + while (length--) { + char c = *string++; + switch (state) { case 0: - if (*string == '%') + if (c == '%') state = 1; else - retCString[i++] = *string; + retCString[i++] = c; break; case 1: case 2:; uint8_t shift = (state == 1 ? 4 : 0); - if (*string >= '0' && *string <= '9') - byte += (*string - '0') << shift; - else if (*string >= 'A' && *string <= 'F') - byte += (*string - 'A' + 10) << shift; - else if (*string >= 'a' && *string <= 'f') - byte += (*string - 'a' + 10) << shift; + if (c >= '0' && c <= '9') + byte += (c - '0') << shift; + else if (c >= 'A' && c <= 'F') + byte += (c - 'A' + 10) << shift; + else if (c >= 'a' && c <= 'f') + byte += (c - 'a' + 10) << shift; else { free(retCString); @throw [OFInvalidFormatException exception]; } @@ -135,14 +137,14 @@ if (state != 0) { free(retCString); @throw [OFInvalidFormatException exception]; } - @try { - ret = [OFString stringWithUTF8String: retCString - length: i]; - } @finally { - free(retCString); - } - return ret; + /* We don't care if it fails, as we only made it smaller. */ + if ((retCString2 = realloc(retCString, i + 1)) == NULL) + retCString2 = retCString; + + return [OFString stringWithUTF8StringNoCopy: retCString2 + length: i + freeWhenDone: true]; } @end