Bug 1490973 - Avoid repeatedly calling Append() in NS_UnescapeURL(). r=froydnj

MozReview-Commit-ID: H29SAvXS4Jl

Differential Revision: https://phabricator.services.mozilla.com/D5769

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Henri Sivonen 2018-09-13 20:49:31 +00:00
Родитель 64adcb7cf0
Коммит 9c077fccbc
1 изменённых файлов: 39 добавлений и 21 удалений

Просмотреть файл

@ -9,6 +9,7 @@
#include "mozilla/ArrayUtils.h"
#include "mozilla/BinarySearch.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/TextUtils.h"
#include "nsTArray.h"
#include "nsCRT.h"
#include "plstr.h"
@ -521,8 +522,6 @@ NS_EscapeURL(const nsString& aStr, const nsTArray<char16_t>& aForbidden,
return aStr;
}
#define ISHEX(c) memchr(hexCharsUpperLower, c, sizeof(hexCharsUpperLower)-1)
bool
NS_UnescapeURL(const char* aStr, int32_t aLen, uint32_t aFlags,
nsACString& aResult)
@ -550,8 +549,15 @@ NS_UnescapeURL(const char* aStr, int32_t aLen, uint32_t aFlags,
MOZ_ASSERT(aResult.IsEmpty(),
"Passing a non-empty string as an out parameter!");
uint32_t len;
if (aLen < 0) {
aLen = strlen(aStr);
size_t stringLength = strlen(aStr);
if (stringLength >= UINT32_MAX) {
return NS_ERROR_OUT_OF_MEMORY;
}
len = stringLength;
} else {
len = aLen;
}
bool ignoreNonAscii = !!(aFlags & esc_OnlyASCII);
@ -560,50 +566,62 @@ NS_UnescapeURL(const char* aStr, int32_t aLen, uint32_t aFlags,
bool skipControl = !!(aFlags & esc_SkipControl);
bool skipInvalidHostChar = !!(aFlags & esc_Host);
unsigned char* destPtr;
uint32_t destPos;
if (writing) {
if (!aResult.SetCapacity(aLen, mozilla::fallible)) {
if (!aResult.SetLength(len, mozilla::fallible)) {
return NS_ERROR_OUT_OF_MEMORY;
}
destPos = 0;
destPtr = reinterpret_cast<unsigned char*>(aResult.BeginWriting());
}
const char* last = aStr;
const char* p = aStr;
const char* end = aStr + len;
for (int i = 0; i < aLen; ++i, ++p) {
if (*p == HEX_ESCAPE && i < aLen - 2) {
for (const char* p = aStr; p < end; ++p) {
if (*p == HEX_ESCAPE && p + 2 < end) {
unsigned char c1 = *((unsigned char*)p + 1);
unsigned char c2 = *((unsigned char*)p + 2);
unsigned char u = (UNHEX(c1) << 4) + UNHEX(c2);
if (ISHEX(c1) && ISHEX(c2) &&
if (mozilla::IsAsciiHexDigit(c1) && mozilla::IsAsciiHexDigit(c2) &&
(!skipInvalidHostChar || dontNeedEscape(u, aFlags) || c1 >= '8') &&
((c1 < '8' && !ignoreAscii) || (c1 >= '8' && !ignoreNonAscii)) &&
!(skipControl &&
(c1 < '2' || (c1 == '7' && (c2 == 'f' || c2 == 'F'))))) {
if (!writing) {
if (MOZ_UNLIKELY(!writing)) {
writing = true;
if (!aResult.SetCapacity(aLen, mozilla::fallible)) {
if (!aResult.SetLength(len, mozilla::fallible)) {
return NS_ERROR_OUT_OF_MEMORY;
}
destPos = 0;
destPtr = reinterpret_cast<unsigned char*>(aResult.BeginWriting());
}
if (p > last) {
if (!aResult.Append(last, p - last, mozilla::fallible)) {
return NS_ERROR_OUT_OF_MEMORY;
}
auto toCopy = p - last;
memcpy(destPtr + destPos, last, toCopy);
destPos += toCopy;
MOZ_ASSERT(destPos <= len);
last = p;
}
if (!aResult.Append(u, mozilla::fallible)) {
return NS_ERROR_OUT_OF_MEMORY;
}
i += 2;
destPtr[destPos] = u;
destPos += 1;
MOZ_ASSERT(destPos <= len);
p += 2;
last += 3;
}
}
}
if (writing && last < aStr + aLen) {
if (!aResult.Append(last, aStr + aLen - last, mozilla::fallible)) {
return NS_ERROR_OUT_OF_MEMORY;
}
if (writing && last < end) {
auto toCopy = end - last;
memcpy(destPtr + destPos, last, toCopy);
destPos += toCopy;
MOZ_ASSERT(destPos <= len);
}
if (writing) {
aResult.Truncate(destPos);
}
aDidAppend = writing;