diff options
7 files changed, 36 insertions, 13 deletions
diff --git a/parser/html/java/htmlparser/src/nu/validator/htmlparser/impl/MetaScanner.java b/parser/html/java/htmlparser/src/nu/validator/htmlparser/impl/MetaScanner.java index be7576ff0e..29c5138a41 100644 --- a/parser/html/java/htmlparser/src/nu/validator/htmlparser/impl/MetaScanner.java +++ b/parser/html/java/htmlparser/src/nu/validator/htmlparser/impl/MetaScanner.java @@ -1,7 +1,7 @@ /* * Copyright (c) 2007 Henri Sivonen * Copyright (c) 2008-2015 Mozilla Foundation - * Copyright (c) 2018-2020 Moonchild Productions + * Copyright (c) 2018-2021 Moonchild Productions * Copyright (c) 2020 Binary Outcast * * Permission is hereby granted, free of charge, to any person obtaining a @@ -753,7 +753,7 @@ public abstract class MetaScanner { stateSave = state; } - private void handleCharInAttributeValue(int c) { + private void handleCharInAttributeValue(int c) throws SAXException { if (metaState == A) { if (contentIndex == CONTENT.length || charsetIndex == CHARSET.length) { addToBuffer(c); @@ -778,9 +778,9 @@ public abstract class MetaScanner { * Adds a character to the accumulation buffer. * @param c the character to add */ - private void addToBuffer(int c) { + private void addToBuffer(int c) throws SAXException { 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); strBuf = newBuf; } diff --git a/parser/html/java/htmlparser/src/nu/validator/htmlparser/impl/Portability.java b/parser/html/java/htmlparser/src/nu/validator/htmlparser/impl/Portability.java index 8f941ce018..a83c3d519b 100644 --- a/parser/html/java/htmlparser/src/nu/validator/htmlparser/impl/Portability.java +++ b/parser/html/java/htmlparser/src/nu/validator/htmlparser/impl/Portability.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2008-2015 Mozilla Foundation - * Copyright (c) 2018-2020 Moonchild Productions + * Copyright (c) 2018-2021 Moonchild Productions * Copyright (c) 2020 Binary Outcast * * Permission is hereby granted, free of charge, to any person obtaining a @@ -24,6 +24,8 @@ package nu.validator.htmlparser.impl; +import org.xml.sax.SAXException; + import nu.validator.htmlparser.annotation.Literal; import nu.validator.htmlparser.annotation.Local; import nu.validator.htmlparser.annotation.NoLength; @@ -31,6 +33,17 @@ import nu.validator.htmlparser.common.Interner; 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 /** diff --git a/parser/html/java/htmlparser/src/nu/validator/htmlparser/impl/Tokenizer.java b/parser/html/java/htmlparser/src/nu/validator/htmlparser/impl/Tokenizer.java index 3d617fd01f..028b7a7d1e 100644 --- a/parser/html/java/htmlparser/src/nu/validator/htmlparser/impl/Tokenizer.java +++ b/parser/html/java/htmlparser/src/nu/validator/htmlparser/impl/Tokenizer.java @@ -1,7 +1,7 @@ /* * Copyright (c) 2005-2007 Henri Sivonen * Copyright (c) 2007-2015 Mozilla Foundation - * Copyright (c) 2018-2020 Moonchild Productions + * Copyright (c) 2018-2021 Moonchild Productions * Copyright (c) 2020 Binary Outcast * Portions of comments Copyright 2004-2010 Apple Computer, Inc., Mozilla * Foundation, and Opera Software ASA. @@ -1009,8 +1009,8 @@ public class Tokenizer implements Locator { // ]NOCPP] } - private void appendStrBuf(@NoLength char[] buffer, int offset, int length) { - int newLen = strBufLen + length; + private void appendStrBuf(@NoLength char[] buffer, int offset, int length) throws SAXException { + int newLen = Portability.checkedAdd(strBufLen, length); // CPPONLY: assert newLen <= strBuf.length: "Previous buffer length insufficient."; // CPPONLY: if (strBuf.length < newLen) { // 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. */ - @Inline private void appendCharRefBufToStrBuf() { + @Inline private void appendCharRefBufToStrBuf() throws SAXException { appendStrBuf(charRefBuf, 0, charRefBufLen); charRefBufLen = 0; } diff --git a/parser/html/nsHtml5MetaScanner.cpp b/parser/html/nsHtml5MetaScanner.cpp index 9fa3d3a705..f7beddafd5 100644 --- a/parser/html/nsHtml5MetaScanner.cpp +++ b/parser/html/nsHtml5MetaScanner.cpp @@ -743,7 +743,7 @@ void nsHtml5MetaScanner::addToBuffer(int32_t c) { 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); strBuf = newBuf; } diff --git a/parser/html/nsHtml5Portability.cpp b/parser/html/nsHtml5Portability.cpp index 400f062048..613f4e5305 100644 --- a/parser/html/nsHtml5Portability.cpp +++ b/parser/html/nsHtml5Portability.cpp @@ -7,6 +7,15 @@ #include "jArray.h" #include "nsHtml5Portability.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* nsHtml5Portability::newLocalNameFromBuffer(char16_t* buf, int32_t offset, int32_t length, nsHtml5AtomTable* interner) diff --git a/parser/html/nsHtml5Portability.h b/parser/html/nsHtml5Portability.h index 2a9d9422b5..3421b410cf 100644 --- a/parser/html/nsHtml5Portability.h +++ b/parser/html/nsHtml5Portability.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2008-2015 Mozilla Foundation - * Copyright (c) 2018-2020 Moonchild Productions + * Copyright (c) 2018-2021 Moonchild Productions * Copyright (c) 2020 Binary Outcast * * Permission is hereby granted, free of charge, to any person obtaining a @@ -60,6 +60,7 @@ class nsHtml5StateSnapshot; class nsHtml5Portability { 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 nsHtml5String newStringFromBuffer(char16_t* buf, int32_t offset, int32_t length, nsHtml5TreeBuilder* treeBuilder, bool maybeAtomize); static nsHtml5String newEmptyString(); diff --git a/parser/html/nsHtml5Tokenizer.cpp b/parser/html/nsHtml5Tokenizer.cpp index 60285ce8ee..4c6a32f731 100644 --- a/parser/html/nsHtml5Tokenizer.cpp +++ b/parser/html/nsHtml5Tokenizer.cpp @@ -1,7 +1,7 @@ /* * Copyright (c) 2005-2007 Henri Sivonen * Copyright (c) 2007-2015 Mozilla Foundation - * Copyright (c) 2018-2020 Moonchild Productions + * Copyright (c) 2018-2021 Moonchild Productions * Copyright (c) 2020 Binary Outcast * Portions of comments Copyright 2004-2010 Apple Computer, Inc., Mozilla * Foundation, and Opera Software ASA. @@ -249,7 +249,7 @@ nsHtml5Tokenizer::emitStrBuf() void 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."); if (MOZ_UNLIKELY(strBuf.length < newLen)) { if (MOZ_UNLIKELY(!EnsureBufferSpace(length))) { |