Bug 1309834. r=wchen. a=ritu
MozReview-Commit-ID: FO7bXlx6lv
--- a/parser/html/jArray.h
+++ b/parser/html/jArray.h
@@ -45,22 +45,22 @@ struct staticJArray {
};
template<class T, class L>
struct jArray {
T* arr;
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;
}
operator T*() { return arr; }
T& operator[] (L const index) {
MOZ_ASSERT(index >= 0, "Array access with negative index.");
MOZ_ASSERT(index < length, "Array index out of bounds.");
return arr[index];
--- a/parser/html/nsHtml5ArrayCopy.h
+++ b/parser/html/nsHtml5ArrayCopy.h
@@ -31,48 +31,48 @@ class nsHtml5AttributeName;
// Unfortunately, these don't work as template functions because the arguments
// would need coercion from a template class, which complicates things.
class nsHtml5ArrayCopy {
public:
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
--- a/parser/html/nsHtml5TokenizerCppSupplement.h
+++ b/parser/html/nsHtml5TokenizerCppSupplement.h
@@ -1,47 +1,64 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#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) {
- // 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));
+ 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.
+ 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;
}
void
nsHtml5Tokenizer::StartPlainText()
{
--- a/parser/html/nsHtml5TreeBuilderCppSupplement.h
+++ b/parser/html/nsHtml5TreeBuilderCppSupplement.h
@@ -956,40 +956,52 @@ void
nsHtml5TreeBuilder::accumulateCharacters(const char16_t* aBuf, int32_t aStart, int32_t aLength)
{
MOZ_RELEASE_ASSERT(charBufferLen + aLength <= charBuffer.length,
"About to memcpy past the end of the buffer!");
memcpy(charBuffer + charBufferLen, aBuf + aStart, sizeof(char16_t) * aLength);
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) {
- // 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));
+ 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.
+ 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;
}
nsIContentHandle*
nsHtml5TreeBuilder::AllocateContentHandle()
{
--- a/parser/html/nsHtml5TreeBuilderHSupplement.h
+++ b/parser/html/nsHtml5TreeBuilderHSupplement.h
@@ -133,17 +133,17 @@
/**
* Makes sure the buffers are large enough to be able to tokenize aLength
* UTF-16 code units before having to make the buffers larger.
*
* @param aLength the number of UTF-16 code units to be tokenized before the
* 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);
void errStrayStartTag(nsIAtom* aName);
void errStrayEndTag(nsIAtom* aName);
void errUnclosedElements(int32_t aIndex, nsIAtom* aName);