From 525961c26137ca8a6416b9b2cd6b390593881be1 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Wed, 24 Feb 2021 09:57:24 +0000 Subject: [html parser] Check for integer overflow when computing new buffer sizes. --- .../src/nu/validator/htmlparser/impl/MetaScanner.java | 8 ++++---- .../src/nu/validator/htmlparser/impl/Portability.java | 15 ++++++++++++++- .../src/nu/validator/htmlparser/impl/Tokenizer.java | 8 ++++---- parser/html/nsHtml5MetaScanner.cpp | 2 +- parser/html/nsHtml5Portability.cpp | 9 +++++++++ parser/html/nsHtml5Portability.h | 3 ++- parser/html/nsHtml5Tokenizer.cpp | 4 ++-- 7 files changed, 36 insertions(+), 13 deletions(-) (limited to 'parser/html') 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 be7576ff0..29c5138a4 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 8f941ce01..a83c3d519 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 3d617fd01..028b7a7d1 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 9fa3d3a70..f7beddafd 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 newBuf = jArray::newJArray(strBuf.length + (strBuf.length << 1)); + jArray newBuf = jArray::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 400f06204..613f4e530 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 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 2a9d9422b..3421b410c 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 60285ce8e..4c6a32f73 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))) { -- cgit v1.2.3