Bug 489820 and bug 483209 - Make the HTML5 parser check buffer bounds less often and place limits on buffer growth. rs=sicking.
authorHenri Sivonen <hsivonen@iki.fi>
Fri, 12 Feb 2010 09:49:06 +0200
changeset 39516 a0f0fde99844258a5ff7f8a06d2bf14232f87f9d
parent 39515 42ccfcc82e1e19667e9303153216f2047ec965de
child 39517 86215ba5e99e3ee022f8403940a9868d3aeaef5c
push id12240
push userhsivonen@iki.fi
push dateWed, 17 Mar 2010 08:29:32 +0000
treeherdermozilla-central@8606d3764288 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssicking
bugs489820, 483209
milestone1.9.3a4pre
Bug 489820 and bug 483209 - Make the HTML5 parser check buffer bounds less often and place limits on buffer growth. rs=sicking.
parser/html/nsHtml5Tokenizer.cpp
parser/html/nsHtml5Tokenizer.h
parser/html/nsHtml5TreeBuilder.cpp
parser/html/nsHtml5TreeBuilder.h
parser/html/nsHtml5TreeBuilderCppSupplement.h
--- a/parser/html/nsHtml5Tokenizer.cpp
+++ b/parser/html/nsHtml5Tokenizer.cpp
@@ -186,48 +186,16 @@ nsHtml5Tokenizer::setLineNumber(PRInt32 
 }
 
 nsHtml5HtmlAttributes* 
 nsHtml5Tokenizer::emptyAttributes()
 {
   return nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES;
 }
 
-void 
-nsHtml5Tokenizer::clearStrBufAndAppendCurrentC(PRUnichar c)
-{
-  strBuf[0] = c;
-  strBufLen = 1;
-}
-
-void 
-nsHtml5Tokenizer::clearStrBufAndAppendForceWrite(PRUnichar c)
-{
-  strBuf[0] = c;
-  strBufLen = 1;
-}
-
-void 
-nsHtml5Tokenizer::clearStrBufForNextState()
-{
-  strBufLen = 0;
-}
-
-void 
-nsHtml5Tokenizer::appendStrBuf(PRUnichar c)
-{
-  if (strBufLen == strBuf.length) {
-    jArray<PRUnichar,PRInt32> newBuf = jArray<PRUnichar,PRInt32>(strBuf.length + NS_HTML5TOKENIZER_BUFFER_GROW_BY);
-    nsHtml5ArrayCopy::arraycopy(strBuf, newBuf, strBuf.length);
-    strBuf.release();
-    strBuf = newBuf;
-  }
-  strBuf[strBufLen++] = c;
-}
-
 nsString* 
 nsHtml5Tokenizer::strBufToString()
 {
   return nsHtml5Portability::newStringFromBuffer(strBuf, 0, strBufLen);
 }
 
 void 
 nsHtml5Tokenizer::strBufToDoctypeName()
@@ -239,92 +207,28 @@ void
 nsHtml5Tokenizer::emitStrBuf()
 {
   if (strBufLen > 0) {
     tokenHandler->characters(strBuf, 0, strBufLen);
   }
 }
 
 void 
-nsHtml5Tokenizer::clearLongStrBufForNextState()
-{
-  longStrBufLen = 0;
-}
-
-void 
-nsHtml5Tokenizer::clearLongStrBuf()
-{
-  longStrBufLen = 0;
-}
-
-void 
-nsHtml5Tokenizer::clearLongStrBufAndAppendCurrentC(PRUnichar c)
-{
-  longStrBuf[0] = c;
-  longStrBufLen = 1;
-}
-
-void 
-nsHtml5Tokenizer::clearLongStrBufAndAppendToComment(PRUnichar c)
-{
-  longStrBuf[0] = c;
-  longStrBufLen = 1;
-}
-
-void 
-nsHtml5Tokenizer::appendLongStrBuf(PRUnichar c)
-{
-  if (longStrBufLen == longStrBuf.length) {
-    jArray<PRUnichar,PRInt32> newBuf = jArray<PRUnichar,PRInt32>(longStrBufLen + (longStrBufLen >> 1));
-    nsHtml5ArrayCopy::arraycopy(longStrBuf, newBuf, longStrBuf.length);
-    longStrBuf.release();
-    longStrBuf = newBuf;
-  }
-  longStrBuf[longStrBufLen++] = c;
-}
-
-void 
 nsHtml5Tokenizer::appendSecondHyphenToBogusComment()
 {
   appendLongStrBuf('-');
 }
 
 void 
 nsHtml5Tokenizer::adjustDoubleHyphenAndAppendToLongStrBufAndErr(PRUnichar c)
 {
 
   appendLongStrBuf(c);
 }
 
-void 
-nsHtml5Tokenizer::appendLongStrBuf(jArray<PRUnichar,PRInt32> buffer, PRInt32 offset, PRInt32 length)
-{
-  PRInt32 reqLen = longStrBufLen + length;
-  if (longStrBuf.length < reqLen) {
-    jArray<PRUnichar,PRInt32> newBuf = jArray<PRUnichar,PRInt32>(reqLen + (reqLen >> 1));
-    nsHtml5ArrayCopy::arraycopy(longStrBuf, newBuf, longStrBuf.length);
-    longStrBuf.release();
-    longStrBuf = newBuf;
-  }
-  nsHtml5ArrayCopy::arraycopy(buffer, offset, longStrBuf, longStrBufLen, length);
-  longStrBufLen = reqLen;
-}
-
-void 
-nsHtml5Tokenizer::appendLongStrBuf(jArray<PRUnichar,PRInt32> arr)
-{
-  appendLongStrBuf(arr, 0, arr.length);
-}
-
-void 
-nsHtml5Tokenizer::appendStrBufToLongStrBuf()
-{
-  appendLongStrBuf(strBuf, 0, strBufLen);
-}
-
 nsString* 
 nsHtml5Tokenizer::longStrBufToString()
 {
   return nsHtml5Portability::newStringFromBuffer(longStrBuf, 0, longStrBufLen);
 }
 
 void 
 nsHtml5Tokenizer::emitComment(PRInt32 provisionalHyphens, PRInt32 pos)
@@ -338,22 +242,16 @@ nsHtml5Tokenizer::flushChars(PRUnichar* 
 {
   if (pos > cstart) {
     tokenHandler->characters(buf, cstart, pos - cstart);
   }
   cstart = 0x7fffffff;
 }
 
 void 
-nsHtml5Tokenizer::resetAttributes()
-{
-  attributes = nsnull;
-}
-
-void 
 nsHtml5Tokenizer::strBufToElementNameString()
 {
   tagName = nsHtml5ElementName::elementNameByBuffer(strBuf, 0, strBufLen, interner);
 }
 
 PRInt32 
 nsHtml5Tokenizer::emitCurrentTagToken(PRBool selfClosing, PRInt32 pos)
 {
@@ -424,16 +322,17 @@ PRBool
 nsHtml5Tokenizer::tokenizeBuffer(nsHtml5UTF16Buffer* buffer)
 {
   PRInt32 state = stateSave;
   PRInt32 returnState = returnStateSave;
   PRUnichar c = '\0';
   shouldSuspend = PR_FALSE;
   lastCR = PR_FALSE;
   PRInt32 start = buffer->getStart();
+  PRInt32 end = buffer->getEnd();
   PRInt32 pos = start - 1;
   switch(state) {
     case NS_HTML5TOKENIZER_DATA:
     case NS_HTML5TOKENIZER_RCDATA:
     case NS_HTML5TOKENIZER_SCRIPT_DATA:
     case NS_HTML5TOKENIZER_PLAINTEXT:
     case NS_HTML5TOKENIZER_RAWTEXT:
     case NS_HTML5TOKENIZER_CDATA_SECTION:
@@ -451,25 +350,58 @@ nsHtml5Tokenizer::tokenizeBuffer(nsHtml5
       cstart = start;
       break;
     }
     default: {
       cstart = PR_INT32_MAX;
       break;
     }
   }
-  pos = stateLoop(state, c, pos, buffer->getBuffer(), PR_FALSE, returnState, buffer->getEnd());
-  if (pos == buffer->getEnd()) {
+  ensureBufferSpace(end - start);
+  pos = stateLoop(state, c, pos, buffer->getBuffer(), PR_FALSE, returnState, end);
+  if (pos == end) {
     buffer->setStart(pos);
   } else {
     buffer->setStart(pos + 1);
   }
   return lastCR;
 }
 
+void 
+nsHtml5Tokenizer::ensureBufferSpace(PRInt32 addedLength)
+{
+  PRInt32 newlongStrBufCapacity = longStrBufLen + addedLength;
+  if (newlongStrBufCapacity > NS_HTML5TOKENIZER_BUFFER_CLIP_THRESHOLD) {
+    longStrBuf[0] = 0x2026;
+    longStrBuf[1] = 0xfffd;
+    longStrBufLen = 2;
+    newlongStrBufCapacity = 2 + addedLength;
+  }
+  if (newlongStrBufCapacity > longStrBuf.length) {
+    jArray<PRUnichar,PRInt32> newBuf = jArray<PRUnichar,PRInt32>(newlongStrBufCapacity);
+    nsHtml5ArrayCopy::arraycopy(longStrBuf, newBuf, longStrBufLen);
+    longStrBuf.release();
+    longStrBuf = newBuf;
+  }
+  PRInt32 newStrBufCapacity = strBufLen + addedLength;
+  if (newStrBufCapacity > NS_HTML5TOKENIZER_BUFFER_CLIP_THRESHOLD) {
+    strBuf[0] = 0x2026;
+    strBuf[1] = 0xfffd;
+    strBufLen = 2;
+    newStrBufCapacity = 2 + addedLength;
+  }
+  if (newStrBufCapacity > strBuf.length) {
+    jArray<PRUnichar,PRInt32> newBuf = jArray<PRUnichar,PRInt32>(newStrBufCapacity);
+    nsHtml5ArrayCopy::arraycopy(strBuf, newBuf, strBufLen);
+    strBuf.release();
+    strBuf = newBuf;
+  }
+  tokenHandler->ensureBufferSpace(addedLength);
+}
+
 PRInt32 
 nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* buf, PRBool reconsume, PRInt32 returnState, PRInt32 endPos)
 {
   stateloop: for (; ; ) {
     switch(state) {
       case NS_HTML5TOKENIZER_DATA: {
         for (; ; ) {
           if (reconsume) {
--- a/parser/html/nsHtml5Tokenizer.h
+++ b/parser/html/nsHtml5Tokenizer.h
@@ -153,52 +153,105 @@ class nsHtml5Tokenizer
     void setLineNumber(PRInt32 line);
     inline PRInt32 getLineNumber()
     {
       return line;
     }
 
     nsHtml5HtmlAttributes* emptyAttributes();
   private:
-    void clearStrBufAndAppendCurrentC(PRUnichar c);
-    void clearStrBufAndAppendForceWrite(PRUnichar c);
-    void clearStrBufForNextState();
-    void appendStrBuf(PRUnichar c);
+    inline void clearStrBufAndAppendCurrentC(PRUnichar c)
+    {
+      strBuf[0] = c;
+      strBufLen = 1;
+    }
+
+    inline void clearStrBufAndAppendForceWrite(PRUnichar c)
+    {
+      strBuf[0] = c;
+      strBufLen = 1;
+    }
+
+    inline void clearStrBufForNextState()
+    {
+      strBufLen = 0;
+    }
+
+    inline void appendStrBuf(PRUnichar c)
+    {
+      strBuf[strBufLen++] = c;
+    }
+
   protected:
     nsString* strBufToString();
   private:
     void strBufToDoctypeName();
     void emitStrBuf();
-    void clearLongStrBufForNextState();
-    void clearLongStrBuf();
-    void clearLongStrBufAndAppendCurrentC(PRUnichar c);
-    void clearLongStrBufAndAppendToComment(PRUnichar c);
-    void appendLongStrBuf(PRUnichar c);
+    inline void clearLongStrBufForNextState()
+    {
+      longStrBufLen = 0;
+    }
+
+    inline void clearLongStrBuf()
+    {
+      longStrBufLen = 0;
+    }
+
+    inline void clearLongStrBufAndAppendCurrentC(PRUnichar c)
+    {
+      longStrBuf[0] = c;
+      longStrBufLen = 1;
+    }
+
+    inline void clearLongStrBufAndAppendToComment(PRUnichar c)
+    {
+      longStrBuf[0] = c;
+      longStrBufLen = 1;
+    }
+
+    inline void appendLongStrBuf(PRUnichar c)
+    {
+      longStrBuf[longStrBufLen++] = c;
+    }
+
     void appendSecondHyphenToBogusComment();
     void adjustDoubleHyphenAndAppendToLongStrBufAndErr(PRUnichar c);
-    void appendLongStrBuf(jArray<PRUnichar,PRInt32> buffer, PRInt32 offset, PRInt32 length);
-    void appendLongStrBuf(jArray<PRUnichar,PRInt32> arr);
-    void appendStrBufToLongStrBuf();
+    inline void appendLongStrBuf(jArray<PRUnichar,PRInt32> buffer, PRInt32 offset, PRInt32 length)
+    {
+      nsHtml5ArrayCopy::arraycopy(buffer, offset, longStrBuf, longStrBufLen, length);
+      longStrBufLen += length;
+    }
+
+    inline void appendStrBufToLongStrBuf()
+    {
+      appendLongStrBuf(strBuf, 0, strBufLen);
+    }
+
     nsString* longStrBufToString();
     void emitComment(PRInt32 provisionalHyphens, PRInt32 pos);
   protected:
     void flushChars(PRUnichar* buf, PRInt32 pos);
   private:
-    void resetAttributes();
+    inline void resetAttributes()
+    {
+      attributes = nsnull;
+    }
+
     void strBufToElementNameString();
     PRInt32 emitCurrentTagToken(PRBool selfClosing, PRInt32 pos);
     void attributeNameComplete();
     void addAttributeWithoutValue();
     void addAttributeWithValue();
   protected:
     void startErrorReporting();
   public:
     void start();
     PRBool tokenizeBuffer(nsHtml5UTF16Buffer* buffer);
   private:
+    void ensureBufferSpace(PRInt32 addedLength);
     PRInt32 stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* buf, PRBool reconsume, PRInt32 returnState, PRInt32 endPos);
     void initDoctypeFields();
     inline void adjustDoubleHyphenAndAppendToLongStrBufCarriageReturn()
     {
       silentCarriageReturn();
       adjustDoubleHyphenAndAppendToLongStrBufAndErr('\n');
     }
 
@@ -289,16 +342,17 @@ jArray<PRUnichar,PRInt32> nsHtml5Tokeniz
 jArray<PRUnichar,PRInt32> nsHtml5Tokenizer::XMP_ARR = 0;
 jArray<PRUnichar,PRInt32> nsHtml5Tokenizer::TEXTAREA_ARR = 0;
 jArray<PRUnichar,PRInt32> nsHtml5Tokenizer::IFRAME_ARR = 0;
 jArray<PRUnichar,PRInt32> nsHtml5Tokenizer::NOEMBED_ARR = 0;
 jArray<PRUnichar,PRInt32> nsHtml5Tokenizer::NOSCRIPT_ARR = 0;
 jArray<PRUnichar,PRInt32> nsHtml5Tokenizer::NOFRAMES_ARR = 0;
 #endif
 
+#define NS_HTML5TOKENIZER_BUFFER_CLIP_THRESHOLD 8000
 #define NS_HTML5TOKENIZER_DATA 0
 #define NS_HTML5TOKENIZER_RCDATA 1
 #define NS_HTML5TOKENIZER_SCRIPT_DATA 2
 #define NS_HTML5TOKENIZER_PLAINTEXT 3
 #define NS_HTML5TOKENIZER_TAG_OPEN 4
 #define NS_HTML5TOKENIZER_CLOSE_TAG_OPEN 5
 #define NS_HTML5TOKENIZER_TAG_NAME 6
 #define NS_HTML5TOKENIZER_BEFORE_ATTRIBUTE_NAME 7
--- a/parser/html/nsHtml5TreeBuilder.cpp
+++ b/parser/html/nsHtml5TreeBuilder.cpp
@@ -189,16 +189,32 @@ nsHtml5TreeBuilder::comment(PRUnichar* b
   }
   commentloop_end: ;
   flushCharacters();
   appendComment(stack[currentPtr]->node, buf, start, length);
   return;
 }
 
 void 
+nsHtml5TreeBuilder::ensureBufferSpace(PRInt32 addedLength)
+{
+  PRInt32 newCharBufferCapacity = charBufferLen + addedLength;
+  if (newCharBufferCapacity > NS_HTML5TREE_BUILDER_BUFFER_FLUSH_THRESHOLD) {
+    flushCharacters();
+    newCharBufferCapacity = addedLength;
+  }
+  if (newCharBufferCapacity > charBuffer.length) {
+    jArray<PRUnichar,PRInt32> newBuf = jArray<PRUnichar,PRInt32>(newCharBufferCapacity);
+    nsHtml5ArrayCopy::arraycopy(charBuffer, newBuf, charBufferLen);
+    charBuffer.release();
+    charBuffer = newBuf;
+  }
+}
+
+void 
 nsHtml5TreeBuilder::characters(const PRUnichar* buf, PRInt32 start, PRInt32 length)
 {
   if (needToDropLF) {
     if (buf[start] == '\n') {
       start++;
       length--;
       if (!length) {
         return;
@@ -3056,30 +3072,38 @@ nsHtml5TreeBuilder::clearLastListSlot()
 {
   listOfActiveFormattingElements[listPtr] = nsnull;
   return PR_TRUE;
 }
 
 void 
 nsHtml5TreeBuilder::push(nsHtml5StackNode* node)
 {
+  if (currentPtr == NS_HTML5TREE_BUILDER_STACK_MAX_DEPTH) {
+
+    pop();
+  }
   currentPtr++;
   if (currentPtr == stack.length) {
     jArray<nsHtml5StackNode*,PRInt32> newStack = jArray<nsHtml5StackNode*,PRInt32>(stack.length + 64);
     nsHtml5ArrayCopy::arraycopy(stack, newStack, stack.length);
     stack.release();
     stack = newStack;
   }
   stack[currentPtr] = node;
   elementPushed(node->ns, node->popName, node->node);
 }
 
 void 
 nsHtml5TreeBuilder::silentPush(nsHtml5StackNode* node)
 {
+  if (currentPtr == NS_HTML5TREE_BUILDER_STACK_MAX_DEPTH) {
+
+    pop();
+  }
   currentPtr++;
   if (currentPtr == stack.length) {
     jArray<nsHtml5StackNode*,PRInt32> newStack = jArray<nsHtml5StackNode*,PRInt32>(stack.length + 64);
     nsHtml5ArrayCopy::arraycopy(stack, newStack, stack.length);
     stack.release();
     stack = newStack;
   }
   stack[currentPtr] = node;
@@ -3718,30 +3742,16 @@ nsHtml5TreeBuilder::appendVoidFormToCurr
   formPointer = elt;
   nsHtml5StackNode* current = stack[currentPtr];
   appendElement(elt, current->node);
   elementPushed(kNameSpaceID_XHTML, nsHtml5Atoms::form, elt);
   elementPopped(kNameSpaceID_XHTML, nsHtml5Atoms::form, elt);
 }
 
 void 
-nsHtml5TreeBuilder::accumulateCharacter(PRUnichar c)
-{
-  PRInt32 newLen = charBufferLen + 1;
-  if (newLen > charBuffer.length) {
-    jArray<PRUnichar,PRInt32> newBuf = jArray<PRUnichar,PRInt32>(newLen);
-    nsHtml5ArrayCopy::arraycopy(charBuffer, newBuf, charBufferLen);
-    charBuffer.release();
-    charBuffer = newBuf;
-  }
-  charBuffer[charBufferLen] = c;
-  charBufferLen = newLen;
-}
-
-void 
 nsHtml5TreeBuilder::requestSuspension()
 {
   tokenizer->requestSuspension();
 }
 
 void 
 nsHtml5TreeBuilder::setFragmentContext(nsIAtom* context, PRInt32 ns, nsIContent** node, PRBool quirks)
 {
--- a/parser/html/nsHtml5TreeBuilder.h
+++ b/parser/html/nsHtml5TreeBuilder.h
@@ -96,16 +96,17 @@ class nsHtml5TreeBuilder : public nsAHtm
     jArray<PRUnichar,PRInt32> charBuffer;
     PRInt32 charBufferLen;
   private:
     PRBool quirks;
   public:
     void startTokenization(nsHtml5Tokenizer* self);
     void doctype(nsIAtom* name, nsString* publicIdentifier, nsString* systemIdentifier, PRBool forceQuirks);
     void comment(PRUnichar* buf, PRInt32 start, PRInt32 length);
+    void ensureBufferSpace(PRInt32 addedLength);
     void characters(const PRUnichar* buf, PRInt32 start, PRInt32 length);
     void eof();
     void endTokenization();
     void startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes, PRBool selfClosing);
     static nsString* extractCharsetFromContent(nsString* attributeValue);
   private:
     void checkMetaCharset(nsHtml5HtmlAttributes* attributes);
   public:
@@ -178,17 +179,21 @@ class nsHtml5TreeBuilder : public nsAHtm
     void appendToCurrentNodeAndPushElementMayFoster(PRInt32 ns, nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes, nsIContent** form);
     void appendVoidElementToCurrentMayFoster(PRInt32 ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContent** form);
     void appendVoidElementToCurrentMayFoster(PRInt32 ns, nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes);
     void appendVoidElementToCurrentMayFosterCamelCase(PRInt32 ns, nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes);
     void appendVoidElementToCurrent(PRInt32 ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContent** form);
     void appendVoidFormToCurrent(nsHtml5HtmlAttributes* attributes);
   protected:
     void accumulateCharacters(const PRUnichar* buf, PRInt32 start, PRInt32 length);
-    void accumulateCharacter(PRUnichar c);
+    inline void accumulateCharacter(PRUnichar c)
+    {
+      charBuffer[charBufferLen++] = c;
+    }
+
     void requestSuspension();
     nsIContent** createElement(PRInt32 ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes);
     nsIContent** createElement(PRInt32 ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContent** form);
     nsIContent** createHtmlElementSetAsRoot(nsHtml5HtmlAttributes* attributes);
     void detachFromParent(nsIContent** element);
     PRBool hasChildren(nsIContent** element);
     void appendElement(nsIContent** child, nsIContent** newParent);
     void appendChildrenToNewParent(nsIContent** oldParent, nsIContent** newParent);
@@ -239,16 +244,18 @@ class nsHtml5TreeBuilder : public nsAHtm
 
 #include "nsHtml5TreeBuilderHSupplement.h"
 };
 
 #ifdef nsHtml5TreeBuilder_cpp__
 jArray<const char*,PRInt32> nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS = nsnull;
 #endif
 
+#define NS_HTML5TREE_BUILDER_BUFFER_FLUSH_THRESHOLD 4096
+#define NS_HTML5TREE_BUILDER_STACK_MAX_DEPTH 200
 #define NS_HTML5TREE_BUILDER_OTHER 0
 #define NS_HTML5TREE_BUILDER_A 1
 #define NS_HTML5TREE_BUILDER_BASE 2
 #define NS_HTML5TREE_BUILDER_BODY 3
 #define NS_HTML5TREE_BUILDER_BR 4
 #define NS_HTML5TREE_BUILDER_BUTTON 5
 #define NS_HTML5TREE_BUILDER_CAPTION 6
 #define NS_HTML5TREE_BUILDER_COL 7
--- a/parser/html/nsHtml5TreeBuilderCppSupplement.h
+++ b/parser/html/nsHtml5TreeBuilderCppSupplement.h
@@ -600,26 +600,18 @@ nsHtml5TreeBuilder::elementPopped(PRInt3
     return;
   }
   return;
 }
 
 void
 nsHtml5TreeBuilder::accumulateCharacters(const PRUnichar* aBuf, PRInt32 aStart, PRInt32 aLength)
 {
-  PRInt32 newFillLen = charBufferLen + aLength;
-  if (newFillLen > charBuffer.length) {
-    PRInt32 newAllocLength = newFillLen + (newFillLen >> 1);
-    jArray<PRUnichar,PRInt32> newBuf(newAllocLength);
-    memcpy(newBuf, charBuffer, sizeof(PRUnichar) * charBufferLen);
-    charBuffer.release();
-    charBuffer = newBuf;
-  }
   memcpy(charBuffer + charBufferLen, aBuf + aStart, sizeof(PRUnichar) * aLength);
-  charBufferLen = newFillLen;
+  charBufferLen += aLength;
 }
 
 nsIContent**
 nsHtml5TreeBuilder::AllocateContentHandle()
 {
   if (mHandlesUsed == NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH) {
     mOldHandles.AppendElement(mHandles.forget());
     mHandles = new nsIContent*[NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH];