Bug 880150 - Treat \<EOF> as U+FFFD outside a string, and drop it inside a string. r=dbaron

This commit is contained in:
Cameron McCormack 2013-06-10 17:04:27 +10:00
parent ceb1835b43
commit 0bf730fdcd
4 changed files with 95 additions and 4 deletions

View File

@ -534,8 +534,14 @@ nsCSSScanner::GatherEscape(nsString& aOutput, bool aInString)
MOZ_ASSERT(Peek() == '\\', "should not have been called");
int32_t ch = Peek(1);
if (ch < 0) {
// Backslash followed by EOF is not an escape.
return false;
// If we are in a string (or a url() containing a string), we want to drop
// the backslash on the floor. Otherwise, we want to treat it as a U+FFFD
// character.
Advance();
if (!aInString) {
aOutput.Append(0xFFFD);
}
return true;
}
if (IsVertSpace(ch)) {
if (aInString) {

View File

@ -133,6 +133,7 @@ MOCHITEST_FILES = test_acid3_test46.html \
test_moz_device_pixel_ratio.html \
test_namespace_rule.html \
test_of_type_selectors.xhtml \
test_parse_eof.html \
test_parse_ident.html \
test_parse_rule.html \
test_parse_url.html \

View File

@ -0,0 +1,69 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title>Test parsing behaviour of backslash just before EOF</title>
<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au">
<meta name="flags" content="">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<style>#a::before { content: "ab\</style>
<style>#b { background-image: url("ab\</style>
<style>#c { background-image: url(ab\</style>
<style>#d { counter-reset: ab\</style>
<style>
#a-ref::before { content: "ab"; }
#b-ref { background-image: url("ab"); }
#c-ref { background-image: url(ab<61>); }
#d-ref { counter-reset: ab<61>; }
</style>
<div style="display: none">
<div id="a"></div>
<div id="b"></div>
<div id="c"></div>
<div id="d"></div>
<div id="a-ref"></div>
<div id="b-ref"></div>
<div id="c-ref"></div>
<div id="d-ref"></div>
</div>
<script>
var a = document.getElementById("a");
var b = document.getElementById("b");
var c = document.getElementById("c");
var d = document.getElementById("d");
var a_ref = document.getElementById("a-ref");
var b_ref = document.getElementById("b-ref");
var c_ref = document.getElementById("c-ref");
var d_ref = document.getElementById("d-ref");
test(function() {
assert_equals(window.getComputedStyle(a, ":before").content,
window.getComputedStyle(a_ref, ":before").content);
}, "test backslash before EOF inside a string");
test(function() {
assert_equals(window.getComputedStyle(b, "").backgroundImage,
window.getComputedStyle(b_ref, "").backgroundImage);
}, "test backslash before EOF inside a url(\"\")");
test(function() {
assert_equals(window.getComputedStyle(c, "").backgroundImage,
window.getComputedStyle(c_ref, "").backgroundImage);
}, "test backslash before EOF inside a url()");
test(function() {
assert_equals(window.getComputedStyle(d, "").counterReset,
window.getComputedStyle(d_ref, "").counterReset);
}, "test backslash before EOF outside a string");
</script>
</body>
</html>

View File

@ -246,6 +246,18 @@ function run() {
}
}
function test_parseable_via_api(selector)
{
var threw = false;
try {
// Test that a selector is parseable when followed by EOF.
ifdoc.body.mozMatchesSelector(selector);
} catch(ex) {
threw = true;
}
ok(!threw, "selector '" + selector + "' was parsed");
}
function test_balanced_unparseable(selector)
{
var zi1 = ++gCounter;
@ -1159,8 +1171,11 @@ function run() {
test_balanced_unparseable("p #, p");
test_balanced_unparseable("p # , p");
// Test that a backslash alone is not treated as an escape.
test_unparseable_via_api("#\\");
// Test that a backslash alone at EOF outside of a string is treated
// as U+FFFD.
test_parseable_via_api("#a\\");
test_parseable_via_api("#\\");
test_parseable_via_api("\\");
// Test that newline escapes are only supported in strings.
test_balanced_unparseable("di\\\nv");