зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
64adcb7cf0
Коммит
9c077fccbc
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче