import changes from UXP:

- Handle URL token in a closer way to the CSS3 spec (d9137b4b7)
- Fix failure to print when pages contain zero-sized <canvas> element. Fixes #1058 (1091fcac8)
- backport m-c 1510114: Fix Use-After-Free in the HTML5 Parser (4ed4303dd)
- PR#1070, PR#1071
This commit is contained in:
2019-05-11 10:12:05 +08:00
parent d3db14ffa8
commit 89eeeb225d
10 changed files with 90 additions and 34 deletions
+21
View File
@@ -1067,6 +1067,7 @@ Scanner.prototype = {
// aToken.mIdent may be "url" at this point; clear that out
aToken.mIdent.length = 0;
let hasString = false;
let ch = this.Peek();
// Do we have a string?
if (ch == QUOTATION_MARK || ch == APOSTROPHE) {
@@ -1075,6 +1076,7 @@ Scanner.prototype = {
aToken.mType = eCSSToken_Bad_URL;
return;
}
hasString = true;
} else {
// Otherwise, this is the start of a non-quoted url (which may be empty).
aToken.mSymbol = 0;
@@ -1093,6 +1095,25 @@ Scanner.prototype = {
}
} else {
aToken.mType = eCSSToken_Bad_URL;
if (!hasString) {
// Consume until before the next right parenthesis, which follows
// how <bad-url-token> is consumed in CSS Syntax 3 spec.
// Note that, we only do this when "url(" is not followed by a
// string, because in the spec, "url(" followed by a string is
// handled as a url function rather than a <url-token>, so the
// rest of content before ")" should be consumed in balance,
// which will be done by the parser.
// The closing ")" is not consumed here. It is left to the parser
// so that the parser can handle both cases.
do {
if (IsVertSpace(ch)) {
this.AdvanceLine();
} else {
this.Advance();
}
ch = this.Peek();
} while (ch >= 0 && ch != RIGHT_PARENTHESIS);
}
}
},
+1 -2
View File
@@ -128,8 +128,7 @@ var LEX_TESTS = [
["url:http://example.com"]],
// In CSS Level 3, this is an ordinary URL, not a BAD_URL.
["url(http://example.com", ["url:http://example.com"]],
// See bug 1153981 to understand why this gets a SYMBOL token.
["url(http://example.com @", ["bad_url:http://example.com", "symbol:@"]],
["url(http://example.com @", ["bad_url:http://example.com"]],
["quo\\ting", ["ident:quoting"]],
["'bad string\n", ["bad_string:bad string", "whitespace"]],
["~=", ["includes"]],
+17 -11
View File
@@ -567,17 +567,23 @@ HTMLCanvasElement::CopyInnerTo(Element* aDest)
HTMLCanvasElement* dest = static_cast<HTMLCanvasElement*>(aDest);
dest->mOriginalCanvas = this;
nsCOMPtr<nsISupports> cxt;
dest->GetContext(NS_LITERAL_STRING("2d"), getter_AddRefs(cxt));
RefPtr<CanvasRenderingContext2D> context2d =
static_cast<CanvasRenderingContext2D*>(cxt.get());
if (context2d && !mPrintCallback) {
CanvasImageSource source;
source.SetAsHTMLCanvasElement() = this;
ErrorResult err;
context2d->DrawImage(source,
0.0, 0.0, err);
rv = err.StealNSResult();
// We make sure that the canvas is not zero sized since that would cause
// the DrawImage call below to return an error, which would cause printing
// to fail.
nsIntSize size = GetWidthHeight();
if (size.height > 0 && size.width > 0) {
nsCOMPtr<nsISupports> cxt;
dest->GetContext(NS_LITERAL_STRING("2d"), getter_AddRefs(cxt));
RefPtr<CanvasRenderingContext2D> context2d =
static_cast<CanvasRenderingContext2D*>(cxt.get());
if (context2d && !mPrintCallback) {
CanvasImageSource source;
source.SetAsHTMLCanvasElement() = this;
ErrorResult err;
context2d->DrawImage(source,
0.0, 0.0, err);
rv = err.StealNSResult();
}
}
}
return rv;
+4
View File
@@ -3617,6 +3617,10 @@ PaintedLayerData::AccumulateEventRegions(ContainerState* aState, nsDisplayLayerE
if (alreadyHadRegions) {
mDispatchToContentHitRegion.OrWith(CombinedTouchActionRegion());
}
// Avoid quadratic performance as a result of the region growing to include
// and arbitrarily large number of rects, which can happen on some pages.
mMaybeHitRegion.SimplifyOutward(8);
// Calculate scaled versions of the bounds of mHitRegion and mMaybeHitRegion
// for quick access in FindPaintedLayerFor().
+1 -1
View File
@@ -1163,7 +1163,6 @@ void
nsDisplayListBuilder::MarkFramesForDisplayList(nsIFrame* aDirtyFrame,
const nsFrameList& aFrames,
const nsRect& aDirtyRect) {
mFramesMarkedForDisplay.SetCapacity(mFramesMarkedForDisplay.Length() + aFrames.GetLength());
for (nsIFrame* e : aFrames) {
// Skip the AccessibleCaret frame when building no caret.
if (!IsBuildingCaret()) {
@@ -1175,6 +1174,7 @@ nsDisplayListBuilder::MarkFramesForDisplayList(nsIFrame* aDirtyFrame,
}
}
}
mFramesMarkedForDisplay.AppendElement(e);
MarkOutOfFlowFrameForDisplay(aDirtyFrame, e, aDirtyRect);
}
+1 -1
View File
@@ -1213,7 +1213,7 @@ private:
PLArenaPool mPool;
nsCOMPtr<nsISelection> mBoundingSelection;
AutoTArray<PresShellState,8> mPresShellStates;
AutoTArray<nsIFrame*,100> mFramesMarkedForDisplay;
AutoTArray<nsIFrame*,400> mFramesMarkedForDisplay;
AutoTArray<ThemeGeometry,2> mThemeGeometries;
nsDisplayTableItem* mCurrentTableItem;
DisplayListClipState mClipState;
@@ -22,17 +22,16 @@
#two { background-color: green; }
</style>
<style type="text/css">
/* not a URI token; the unterminated string ends at end of line, so
the brace never matches */
#three { background-color: green; }
/* not a URI token; bad-url token is consumed until the first closing ) */
#foo { background: url(foo"bar) }
#three { background-color: red; }
#three { background-color: green; }
</style>
<style type="text/css">
/* not a URI token; the unterminated string ends at end of line */
/* not a URI token; bad-url token is consumed until the first closing ) */
#four { background-color: green; }
#foo { background: url(foo"bar) }
) }
#four { background-color: green; }
#four { background-color: red; }
</style>
<style type="text/css">
/* not a URI token; the unterminated string ends at end of line, so
@@ -68,18 +67,19 @@
#eleven { background: url([) green; }
</style>
<style type="text/css">
/* not a URI token; brace matching should work only after invalid URI token */
#twelve { background: url(}{""{)}); background-color: green; }
/* not a URI token; bad-url token is consumed until the first closing )
so the brace immediately after it closes the declaration block */
#twelve { background-color: green; }
#twelve { background: url(}{""{)}); background-color: red; }
</style>
<style type="text/css">
/* invalid URI token absorbs the [ */
#thirteen { background: url([""); background-color: green; }
</style>
<style type="text/css">
/* not a URI token; the opening ( is never matched */
#fourteen { background-color: green; }
/* not a URI token; bad-url token is consumed until the first closing ) */
#foo { background: url(() }
#fourteen { background-color: red; }
#fourteen { background-color: green; }
</style>
<!-- The next three tests test that invalid URI tokens absorb [ and { -->
<style type="text/css">
+21 -1
View File
@@ -1166,6 +1166,7 @@ nsCSSScanner::NextURL(nsCSSToken& aToken)
// aToken.mIdent may be "url" at this point; clear that out
aToken.mIdent.Truncate();
bool hasString = false;
int32_t ch = Peek();
// Do we have a string?
if (ch == '"' || ch == '\'') {
@@ -1175,7 +1176,7 @@ nsCSSScanner::NextURL(nsCSSToken& aToken)
return;
}
MOZ_ASSERT(aToken.mType == eCSSToken_String, "unexpected token type");
hasString = true;
} else {
// Otherwise, this is the start of a non-quoted url (which may be empty).
aToken.mSymbol = char16_t(0);
@@ -1195,6 +1196,25 @@ nsCSSScanner::NextURL(nsCSSToken& aToken)
} else {
mSeenBadToken = true;
aToken.mType = eCSSToken_Bad_URL;
if (!hasString) {
// Consume until before the next right parenthesis, which follows
// how <bad-url-token> is consumed in CSS Syntax 3 spec.
// Note that, we only do this when "url(" is not followed by a
// string, because in the spec, "url(" followed by a string is
// handled as a url function rather than a <url-token>, so the
// rest of content before ")" should be consumed in balance,
// which will be done by the parser.
// The closing ")" is not consumed here. It is left to the parser
// so that the parser can handle both cases.
do {
if (IsVertSpace(ch)) {
AdvanceLine();
} else {
Advance();
}
ch = Peek();
} while (ch >= 0 && ch != ')');
}
}
}
+1 -2
View File
@@ -55,8 +55,7 @@ var LEX_TESTS = [
["url:http://example.com"]],
// In CSS Level 3, this is an ordinary URL, not a BAD_URL.
["url(http://example.com", ["url:http://example.com"]],
// See bug 1153981 to understand why this gets a SYMBOL token.
["url(http://example.com @", ["bad_url:http://example.com", "symbol:@"]],
["url(http://example.com @", ["bad_url:http://example.com"]],
["quo\\ting", ["ident:quoting"]],
["'bad string\n", ["bad_string:bad string", "whitespace"]],
["~=", ["includes"]],
+12 -5
View File
@@ -353,6 +353,12 @@ nsHtml5TreeOpExecutor::RunFlushLoop()
nsHtml5FlushLoopGuard guard(this); // this is also the self-kungfu!
RefPtr<nsParserBase> parserKungFuDeathGrip(mParser);
RefPtr<nsHtml5StreamParser> streamParserGrip;
if (mParser) {
streamParserGrip = GetParser()->GetStreamParser();
}
mozilla::Unused
<< streamParserGrip; // Intentionally not used within function
// Remember the entry time
(void) nsContentSink::WillParseImpl();
@@ -411,11 +417,6 @@ nsHtml5TreeOpExecutor::RunFlushLoop()
mOpQueue.Clear(); // clear in order to be able to assert in destructor
return;
}
// Not sure if this grip is still needed, but previously, the code
// gripped before calling ParseUntilBlocked();
RefPtr<nsHtml5StreamParser> streamKungFuDeathGrip =
GetParser()->GetStreamParser();
mozilla::Unused << streamKungFuDeathGrip; // Not used within function
// Now parse content left in the document.write() buffer queue if any.
// This may generate tree ops on its own or dequeue a speculation.
nsresult rv = GetParser()->ParseUntilBlocked();
@@ -531,6 +532,12 @@ nsHtml5TreeOpExecutor::FlushDocumentWrite()
RefPtr<nsHtml5TreeOpExecutor> kungFuDeathGrip(this);
RefPtr<nsParserBase> parserKungFuDeathGrip(mParser);
mozilla::Unused << parserKungFuDeathGrip; // Intentionally not used within function
RefPtr<nsHtml5StreamParser> streamParserGrip;
if (mParser) {
streamParserGrip = GetParser()->GetStreamParser();
}
mozilla::Unused
<< streamParserGrip; // Intentionally not used within function
NS_ASSERTION(!mReadingFromStage,
"Got doc write flush when reading from stage");