[html parser] Check for integer overflow when computing new buffer sizes.

This commit is contained in:
Moonchild 2021-02-24 09:57:24 +00:00 • committed by roytam1
commit 5934c74a3f
7 changed files with 36 additions and 13 deletions

View file

@ -1,7 +1,7 @@
/* /*
* Copyright (c) 2007 Henri Sivonen * Copyright (c) 2007 Henri Sivonen
* Copyright (c) 2008-2015 Mozilla Foundation * Copyright (c) 2008-2015 Mozilla Foundation
* Copyright (c) 2018-2020 Moonchild Productions * Copyright (c) 2018-2021 Moonchild Productions
* Copyright (c) 2020 Binary Outcast * Copyright (c) 2020 Binary Outcast
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
@ -753,7 +753,7 @@ public abstract class MetaScanner {
stateSave = state; stateSave = state;
} }
private void handleCharInAttributeValue(int c) { private void handleCharInAttributeValue(int c) throws SAXException {
if (metaState == A) { if (metaState == A) {
if (contentIndex == CONTENT.length || charsetIndex == CHARSET.length) { if (contentIndex == CONTENT.length || charsetIndex == CHARSET.length) {
addToBuffer(c); addToBuffer(c);
@ -778,9 +778,9 @@ public abstract class MetaScanner {
* Adds a character to the accumulation buffer. * Adds a character to the accumulation buffer.
* @param c the character to add * @param c the character to add
*/ */
private void addToBuffer(int c) { private void addToBuffer(int c) throws SAXException {
if (strBufLen == strBuf.length) { if (strBufLen == strBuf.length) {
char[] newBuf = new char[strBuf.length + (strBuf.length << 1)]; char[] newBuf = new char[Portability.checkedAdd(strBuf.length, (strBuf.length << 1))];
System.arraycopy(strBuf, 0, newBuf, 0, strBuf.length); System.arraycopy(strBuf, 0, newBuf, 0, strBuf.length);
strBuf = newBuf; strBuf = newBuf;
} }

View file

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2008-2015 Mozilla Foundation * Copyright (c) 2008-2015 Mozilla Foundation
* Copyright (c) 2018-2020 Moonchild Productions * Copyright (c) 2018-2021 Moonchild Productions
* Copyright (c) 2020 Binary Outcast * Copyright (c) 2020 Binary Outcast
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
@ -24,6 +24,8 @@
package nu.validator.htmlparser.impl; package nu.validator.htmlparser.impl;
import org.xml.sax.SAXException;
import nu.validator.htmlparser.annotation.Literal; import nu.validator.htmlparser.annotation.Literal;
import nu.validator.htmlparser.annotation.Local; import nu.validator.htmlparser.annotation.Local;
import nu.validator.htmlparser.annotation.NoLength; import nu.validator.htmlparser.annotation.NoLength;
@ -31,6 +33,17 @@ import nu.validator.htmlparser.common.Interner;
public final class Portability { public final class Portability {
public static int checkedAdd(int a, int b) throws SAXException {
// This can't be translated code, because in C++ signed integer overflow is UB, so the below code would be wrong.
assert a >= 0;
assert b >= 0;
int sum = a + b;
if (sum < a || sum < b) {
throw new SAXException("Integer overflow");
}
return sum;
}
// Allocating methods // Allocating methods
/** /**

View file

@ -1,7 +1,7 @@
/* /*
* Copyright (c) 2005-2007 Henri Sivonen * Copyright (c) 2005-2007 Henri Sivonen
* Copyright (c) 2007-2015 Mozilla Foundation * Copyright (c) 2007-2015 Mozilla Foundation
* Copyright (c) 2018-2020 Moonchild Productions * Copyright (c) 2018-2021 Moonchild Productions
* Copyright (c) 2020 Binary Outcast * Copyright (c) 2020 Binary Outcast
* Portions of comments Copyright 2004-2010 Apple Computer, Inc., Mozilla * Portions of comments Copyright 2004-2010 Apple Computer, Inc., Mozilla
* Foundation, and Opera Software ASA. * Foundation, and Opera Software ASA.
@ -1009,8 +1009,8 @@ public class Tokenizer implements Locator {
// ]NOCPP] // ]NOCPP]
} }
private void appendStrBuf(@NoLength char[] buffer, int offset, int length) { private void appendStrBuf(@NoLength char[] buffer, int offset, int length) throws SAXException {
int newLen = strBufLen + length; int newLen = Portability.checkedAdd(strBufLen, length);
// CPPONLY: assert newLen <= strBuf.length: "Previous buffer length insufficient."; // CPPONLY: assert newLen <= strBuf.length: "Previous buffer length insufficient.";
// CPPONLY: if (strBuf.length < newLen) { // CPPONLY: if (strBuf.length < newLen) {
// CPPONLY: if (!EnsureBufferSpace(length)) { // CPPONLY: if (!EnsureBufferSpace(length)) {
@ -1024,7 +1024,7 @@ public class Tokenizer implements Locator {
/** /**
* Append the contents of the char reference buffer to the main one. * Append the contents of the char reference buffer to the main one.
*/ */
@Inline private void appendCharRefBufToStrBuf() { @Inline private void appendCharRefBufToStrBuf() throws SAXException {
appendStrBuf(charRefBuf, 0, charRefBufLen); appendStrBuf(charRefBuf, 0, charRefBufLen);
charRefBufLen = 0; charRefBufLen = 0;
} }

View file

@ -743,7 +743,7 @@ void
nsHtml5MetaScanner::addToBuffer(int32_t c) nsHtml5MetaScanner::addToBuffer(int32_t c)
{ {
if (strBufLen == strBuf.length) { if (strBufLen == strBuf.length) {
jArray<char16_t,int32_t> newBuf = jArray<char16_t,int32_t>::newJArray(strBuf.length + (strBuf.length << 1)); jArray<char16_t,int32_t> newBuf = jArray<char16_t,int32_t>::newJArray(nsHtml5Portability::checkedAdd(strBuf.length, (strBuf.length << 1)));
nsHtml5ArrayCopy::arraycopy(strBuf, newBuf, strBuf.length); nsHtml5ArrayCopy::arraycopy(strBuf, newBuf, strBuf.length);
strBuf = newBuf; strBuf = newBuf;
} }

View file

@ -7,6 +7,15 @@
#include "jArray.h" #include "jArray.h"
#include "nsHtml5Portability.h" #include "nsHtml5Portability.h"
#include "nsHtml5TreeBuilder.h" #include "nsHtml5TreeBuilder.h"
#include "mozilla/CheckedInt.h"
int32_t nsHtml5Portability::checkedAdd(int32_t a, int32_t b) {
mozilla::CheckedInt<int32_t> sum(a);
sum += b;
MOZ_RELEASE_ASSERT(sum.isValid(),
"HTML input too large for signed 32-bit integer.");
return sum.value();
}
nsIAtom* nsIAtom*
nsHtml5Portability::newLocalNameFromBuffer(char16_t* buf, int32_t offset, int32_t length, nsHtml5AtomTable* interner) nsHtml5Portability::newLocalNameFromBuffer(char16_t* buf, int32_t offset, int32_t length, nsHtml5AtomTable* interner)

View file

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2008-2015 Mozilla Foundation * Copyright (c) 2008-2015 Mozilla Foundation
* Copyright (c) 2018-2020 Moonchild Productions * Copyright (c) 2018-2021 Moonchild Productions
* Copyright (c) 2020 Binary Outcast * Copyright (c) 2020 Binary Outcast
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
@ -60,6 +60,7 @@ class nsHtml5StateSnapshot;
class nsHtml5Portability class nsHtml5Portability
{ {
public: public:
static int32_t checkedAdd(int32_t a, int32_t b);
static nsIAtom* newLocalNameFromBuffer(char16_t* buf, int32_t offset, int32_t length, nsHtml5AtomTable* interner); static nsIAtom* newLocalNameFromBuffer(char16_t* buf, int32_t offset, int32_t length, nsHtml5AtomTable* interner);
static nsHtml5String newStringFromBuffer(char16_t* buf, int32_t offset, int32_t length, nsHtml5TreeBuilder* treeBuilder, bool maybeAtomize); static nsHtml5String newStringFromBuffer(char16_t* buf, int32_t offset, int32_t length, nsHtml5TreeBuilder* treeBuilder, bool maybeAtomize);
static nsHtml5String newEmptyString(); static nsHtml5String newEmptyString();

View file

@ -1,7 +1,7 @@
/* /*
* Copyright (c) 2005-2007 Henri Sivonen * Copyright (c) 2005-2007 Henri Sivonen
* Copyright (c) 2007-2015 Mozilla Foundation * Copyright (c) 2007-2015 Mozilla Foundation
* Copyright (c) 2018-2020 Moonchild Productions * Copyright (c) 2018-2021 Moonchild Productions
* Copyright (c) 2020 Binary Outcast * Copyright (c) 2020 Binary Outcast
* Portions of comments Copyright 2004-2010 Apple Computer, Inc., Mozilla * Portions of comments Copyright 2004-2010 Apple Computer, Inc., Mozilla
* Foundation, and Opera Software ASA. * Foundation, and Opera Software ASA.
@ -249,7 +249,7 @@ nsHtml5Tokenizer::emitStrBuf()
void void
nsHtml5Tokenizer::appendStrBuf(char16_t* buffer, int32_t offset, int32_t length) nsHtml5Tokenizer::appendStrBuf(char16_t* buffer, int32_t offset, int32_t length)
{ {
int32_t newLen = strBufLen + length; int32_t newLen = nsHtml5Portability::checkedAdd(strBufLen, length);
MOZ_ASSERT(newLen <= strBuf.length, "Previous buffer length insufficient."); MOZ_ASSERT(newLen <= strBuf.length, "Previous buffer length insufficient.");
if (MOZ_UNLIKELY(strBuf.length < newLen)) { if (MOZ_UNLIKELY(strBuf.length < newLen)) {
if (MOZ_UNLIKELY(!EnsureBufferSpace(length))) { if (MOZ_UNLIKELY(!EnsureBufferSpace(length))) {