Bug 1309834. r=wchen.

MozReview-Commit-ID: FO7bXlx6lv
This commit is contained in:
Henri Sivonen
2016-10-14 11:47:17 +03:00
parent 988847604e
commit fa187d93c8
5 changed files with 65 additions and 36 deletions

View File

@@ -50,12 +50,12 @@ struct jArray {
L length;
static jArray<T,L> newJArray(L const len) {
MOZ_ASSERT(len >= 0, "Negative length.");
jArray<T,L> newArray = { new T[len], len };
jArray<T,L> newArray = { new T[size_t(len)], len };
return newArray;
}
static jArray<T,L> newFallibleJArray(L const len) {
MOZ_ASSERT(len >= 0, "Negative length.");
T* a = new (mozilla::fallible) T[len];
T* a = new (mozilla::fallible) T[size_t(len)];
jArray<T,L> newArray = { a, a ? len : 0 };
return newArray;
}

View File

@@ -36,43 +36,43 @@ class nsHtml5ArrayCopy {
static inline void
arraycopy(char16_t* source, int32_t sourceOffset, char16_t* target, int32_t targetOffset, int32_t length)
{
memcpy(&(target[targetOffset]), &(source[sourceOffset]), length * sizeof(char16_t));
memcpy(&(target[targetOffset]), &(source[sourceOffset]), size_t(length) * sizeof(char16_t));
}
static inline void
arraycopy(char16_t* source, char16_t* target, int32_t length)
{
memcpy(target, source, length * sizeof(char16_t));
memcpy(target, source, size_t(length) * sizeof(char16_t));
}
static inline void
arraycopy(int32_t* source, int32_t* target, int32_t length)
{
memcpy(target, source, length * sizeof(int32_t));
memcpy(target, source, size_t(length) * sizeof(int32_t));
}
static inline void
arraycopy(nsString** source, nsString** target, int32_t length)
{
memcpy(target, source, length * sizeof(nsString*));
memcpy(target, source, size_t(length) * sizeof(nsString*));
}
static inline void
arraycopy(nsHtml5AttributeName** source, nsHtml5AttributeName** target, int32_t length)
{
memcpy(target, source, length * sizeof(nsHtml5AttributeName*));
memcpy(target, source, size_t(length) * sizeof(nsHtml5AttributeName*));
}
static inline void
arraycopy(nsHtml5StackNode** source, nsHtml5StackNode** target, int32_t length)
{
memcpy(target, source, length * sizeof(nsHtml5StackNode*));
memcpy(target, source, size_t(length) * sizeof(nsHtml5StackNode*));
}
static inline void
arraycopy(nsHtml5StackNode** arr, int32_t sourceOffset, int32_t targetOffset, int32_t length)
{
memmove(&(arr[targetOffset]), &(arr[sourceOffset]), length * sizeof(nsHtml5StackNode*));
memmove(&(arr[targetOffset]), &(arr[sourceOffset]), size_t(length) * sizeof(nsHtml5StackNode*));
}
};
#endif // nsHtml5ArrayCopy_h

View File

@@ -4,39 +4,56 @@
#include "mozilla/Likely.h"
// INT32_MAX is (2^31)-1. Therefore, the highest power-of-two that fits
// is 2^30. Note that this is counting char16_t units. The underlying
// bytes will be twice that, but they fit even in 32-bit size_t even
// if a contiguous chunk of memory of that size is pretty unlikely to
// be available on a 32-bit system.
#define MAX_POWER_OF_TWO_IN_INT32 0x40000000
bool
nsHtml5Tokenizer::EnsureBufferSpace(int32_t aLength)
{
MOZ_ASSERT(aLength >= 0, "Negative length.");
MOZ_RELEASE_ASSERT(aLength >= 0, "Negative length.");
if (aLength > MAX_POWER_OF_TWO_IN_INT32) {
// Can't happen when loading from network.
return false;
}
CheckedInt<int32_t> worstCase(strBufLen);
worstCase += aLength;
worstCase += charRefBufLen;
// Add 2 to account for emissions of LT_GT, LT_SOLIDUS and RSQB_RSQB.
// Adding to the general worst case instead of only the
// TreeBuilder-exposed worst case to avoid re-introducing a bug when
// unifying the tokenizer and tree builder buffers in the future.
size_t worstCase = size_t(strBufLen) +
size_t(aLength) +
size_t(charRefBufLen) +
size_t(2);
if (worstCase > INT32_MAX) {
// Since we index into the buffer using int32_t due to the Java heritage
// of the code, let's treat this as OOM.
worstCase += 2;
if (!worstCase.isValid()) {
return false;
}
if (worstCase.value() > MAX_POWER_OF_TWO_IN_INT32) {
return false;
}
// TODO: Unify nsHtml5Tokenizer::strBuf and nsHtml5TreeBuilder::charBuffer
// so that the call below becomes unnecessary.
tokenHandler->EnsureBufferSpace(worstCase);
if (!tokenHandler->EnsureBufferSpace(worstCase.value())) {
return false;
}
if (!strBuf) {
if (worstCase.value() < MAX_POWER_OF_TWO_IN_INT32) {
// Add one to round to the next power of two to avoid immediate
// reallocation once there are a few characters in the buffer.
strBuf = jArray<char16_t,int32_t>::newFallibleJArray(mozilla::RoundUpPow2(worstCase + 1));
worstCase += 1;
}
strBuf = jArray<char16_t,int32_t>::newFallibleJArray(mozilla::RoundUpPow2(worstCase.value()));
if (!strBuf) {
return false;
}
} else if (worstCase > size_t(strBuf.length)) {
jArray<char16_t,int32_t> newBuf = jArray<char16_t,int32_t>::newFallibleJArray(mozilla::RoundUpPow2(worstCase));
} else if (worstCase.value() > strBuf.length) {
jArray<char16_t,int32_t> newBuf = jArray<char16_t,int32_t>::newFallibleJArray(mozilla::RoundUpPow2(worstCase.value()));
if (!newBuf) {
return false;
}
memcpy(newBuf,strBuf, sizeof(char16_t) * strBufLen);
memcpy(newBuf, strBuf, sizeof(char16_t) * size_t(strBufLen));
strBuf = newBuf;
}
return true;

View File

@@ -961,30 +961,42 @@ nsHtml5TreeBuilder::accumulateCharacters(const char16_t* aBuf, int32_t aStart, i
charBufferLen += aLength;
}
// INT32_MAX is (2^31)-1. Therefore, the highest power-of-two that fits
// is 2^30. Note that this is counting char16_t units. The underlying
// bytes will be twice that, but they fit even in 32-bit size_t even
// if a contiguous chunk of memory of that size is pretty unlikely to
// be available on a 32-bit system.
#define MAX_POWER_OF_TWO_IN_INT32 0x40000000
bool
nsHtml5TreeBuilder::EnsureBufferSpace(size_t aLength)
nsHtml5TreeBuilder::EnsureBufferSpace(int32_t aLength)
{
// TODO: Unify nsHtml5Tokenizer::strBuf and nsHtml5TreeBuilder::charBuffer
// so that this method becomes unnecessary.
size_t worstCase = size_t(charBufferLen) + aLength;
if (worstCase > INT32_MAX) {
// Since we index into the buffer using int32_t due to the Java heritage
// of the code, let's treat this as OOM.
CheckedInt<int32_t> worstCase(charBufferLen);
worstCase += aLength;
if (!worstCase.isValid()) {
return false;
}
if (worstCase.value() > MAX_POWER_OF_TWO_IN_INT32) {
return false;
}
if (!charBuffer) {
if (worstCase.value() < MAX_POWER_OF_TWO_IN_INT32) {
// Add one to round to the next power of two to avoid immediate
// reallocation once there are a few characters in the buffer.
charBuffer = jArray<char16_t,int32_t>::newFallibleJArray(mozilla::RoundUpPow2(worstCase + 1));
worstCase += 1;
}
charBuffer = jArray<char16_t,int32_t>::newFallibleJArray(mozilla::RoundUpPow2(worstCase.value()));
if (!charBuffer) {
return false;
}
} else if (worstCase > size_t(charBuffer.length)) {
jArray<char16_t,int32_t> newBuf = jArray<char16_t,int32_t>::newFallibleJArray(mozilla::RoundUpPow2(worstCase));
} else if (worstCase.value() > charBuffer.length) {
jArray<char16_t,int32_t> newBuf = jArray<char16_t,int32_t>::newFallibleJArray(mozilla::RoundUpPow2(worstCase.value()));
if (!newBuf) {
return false;
}
memcpy(newBuf, charBuffer, sizeof(char16_t) * charBufferLen);
memcpy(newBuf, charBuffer, sizeof(char16_t) * size_t(charBufferLen));
charBuffer = newBuf;
}
return true;

View File

@@ -138,7 +138,7 @@
* next call to this method.
* @return true if successful; false if out of memory
*/
bool EnsureBufferSpace(size_t aLength);
bool EnsureBufferSpace(int32_t aLength);
void EnableViewSource(nsHtml5Highlighter* aHighlighter);