Skip to content

Commit

Permalink
[FIX] caja-html-sanitizer: avoid catastrophic backtracking in lexCss
Browse files Browse the repository at this point in the history
The caja-html-sanitizer uses a complex regular expression to tokenize
CSS styles before parsing and sanitizing them. That regular expression
contains a sub-expression that allows alternative interpretations of
arbitrarily long input sequences and therefore might cause extensive
backtracking (see googlearchive/caja#2037 ).

To prevent this, the corresponding sub-expression has been rewritten to
simulate an atomic group (or possessive quantifier) as described in
https://instanceof.me/post/52245507631/regex-emulate-atomic-grouping-with-lookahead.

Change-Id: Ia9e8e038d8b4cf5a7cf2684a14877fc08bf1be80
BCP: 002075129500001766652020
  • Loading branch information
codeworrior committed Apr 3, 2020
1 parent bf20511 commit c00ebef
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 3 deletions.
6 changes: 5 additions & 1 deletion src/sap.ui.core/src/sap/ui/thirdparty/caja-html-sanitizer.js
Original file line number Diff line number Diff line change
Expand Up @@ -964,7 +964,11 @@ var decodeCss;
// FUNCTION ::= ident '('
// Diff: We exclude url explicitly.
// TODO: should we be tolerant of "fn ("?
var FUNCTION = '(?!url[(])' + IDENT + '[(]';
// ##### BEGIN: MODIFIED BY SAP
// Avoid risk of 'catastrophic backtracking' when unicode escapes are used
// var FUNCTION = '(?!url[(])' + IDENT + '[(]';
var FUNCTION = '(?!url[(])(?=(' + IDENT + '))\\1[(]';
// ##### END: MODIFIED BY SAP
// INCLUDES ::= "~="
var INCLUDES = '~=';
// DASHMATCH ::= "|="
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
/*global QUnit */
sap.ui.define(["sap/base/security/sanitizeHTML"], function(sanitizeHTML) {
sap.ui.define([
"sap/base/security/sanitizeHTML",
"sap/ui/thirdparty/caja-html-sanitizer"
], function(sanitizeHTML) {
"use strict";

QUnit.module("Sanitize check");
QUnit.module("Sanitizer Functionality");

QUnit.test("valid HTML5", function(assert) {

Expand Down Expand Up @@ -84,4 +87,75 @@ sap.ui.define(["sap/base/security/sanitizeHTML"], function(sanitizeHTML) {

});

QUnit.module("Sanitizer Performance", {
before: function(assert) {
// add a custom assertion "lower than"
QUnit.assert.lt = function(actual, expected, message) {
this.pushResult({
result: actual < expected,
actual: actual,
expected: "< " + expected,
message: message
});
};
},
after: function(assert) {
delete QUnit.assert.lt;
}
});

QUnit.test("lexCss", function(assert) {

assert.equal(typeof window.lexCss, "function", "[precondition] there should be a global function 'lexCss'");

[
{
input: "width: 100%",
tokens: ["width", ":", " ", "100%"]
},
{
input: "background-image: url(foobar.png);",
tokens: ["background-image", ":", " ", "url(\"foobar.png\")", ";"]
},
{
input: "background-image: url('foobar.png');",
tokens: ["background-image", ":", " ", "url(\"foobar.png\")", ";"]
},
{
input: "background-image: url(\"foobar.png\");",
tokens: ["background-image", ":", " ", "url(\"foobar.png\")", ";"]
},
{
input: "width: calc(100px+20em);",
tokens: ["width", ":", " ", "calc(", "100px", "+20em", ")", ";"]
},
{
input: "font: 10pt normal 'Helvetic Neue',sans-serif;",
tokens: ["font", ":", " ", "10pt", " ", "normal", " ", "\"Helvetic Neue\"", ",", "sans-serif", ";"]
},
{
input: "font-size:10.0pt; font-family:\\5320\\7265\\6669\\2020\\2020\\2020\\2020\\2020\\2020\\2020\\2020\\2020\\2020; color:black",
tokens: [
"font-size", ":", "10.0pt", ";", " ",
"font-family", ":", "\u5320\u7265\u6669\u2020\u2020\u2020\u2020\u2020\u2020\u2020\u2020\u2020\u2020", ";", " ",
"color", ":", "black"
]
}
].forEach(function(oData) {
var N = 4,
t0, t1, tokens, i;

// act
t0 = Date.now();
for (i = 0; i < N; i++) {
tokens = window.lexCss(oData.input);
}
t1 = Date.now();

// assert
assert.deepEqual(tokens, oData.tokens, "tokenizing \"" + oData.input + "\" should return the expected tokens");
assert.lt((t1 - t0) / N, 100, "avg. call time should be less than 100ms");
});
});

});

0 comments on commit c00ebef

Please sign in to comment.