fix(platform-browser): prevent clobbered elements from freezing the browser

see
4f69d38f09
This commit is contained in:
Victor Berchet
2017-03-14 17:15:46 -07:00
committed by Chuck Jazdzewski
parent 52bbc9baf4
commit a4076c70cc
6 changed files with 58 additions and 5 deletions

View File

@ -61,6 +61,14 @@ const _chromeNumKeyPadMap = {
'\x90': 'NumLock'
};
let nodeContains: (a: any, b: any) => boolean;
if (global['Node']) {
nodeContains = global['Node'].prototype.contains || function(node) {
return !!(this.compareDocumentPosition(node) & 16);
};
}
/**
* A `DomAdapter` powered by full browser DOM APIs.
*
@ -107,6 +115,7 @@ export class BrowserDomAdapter extends GenericBrowserDomAdapter {
get attrToPropMap(): any { return _attrToPropMap; }
contains(nodeA: any, nodeB: any): boolean { return nodeContains.call(nodeA, nodeB); }
querySelector(el: Element, selector: string): any { return el.querySelector(selector); }
querySelectorAll(el: any, selector: string): any[] { return el.querySelectorAll(selector); }
on(el: Node, evt: any, listener: any) { el.addEventListener(evt, listener, false); }

View File

@ -52,6 +52,7 @@ export abstract class DomAdapter {
/** @internal */
_attrToPropMap: {[key: string]: string};
abstract contains(nodeA: any, nodeB: any): boolean;
abstract parse(templateHtml: string): any;
abstract querySelector(el: any, selector: string): any;
abstract querySelectorAll(el: any, selector: string): any[];

View File

@ -9,7 +9,6 @@
import {isDevMode} from '@angular/core';
import {DomAdapter, getDOM} from '../dom/dom_adapter';
import {DOCUMENT} from '../dom/dom_tokens';
import {sanitizeSrcset, sanitizeUrl} from './url_sanitizer';
@ -146,11 +145,15 @@ class SanitizingHtmlSerializer {
if (DOM.isElementNode(current)) {
this.endElement(current as Element);
}
if (DOM.nextSibling(current)) {
current = DOM.nextSibling(current);
let next = checkClobberedElement(current, DOM.nextSibling(current));
if (next) {
current = next;
break;
}
current = DOM.parentElement(current);
current = checkClobberedElement(current, DOM.parentElement(current));
}
}
return this.buf.join('');
@ -191,7 +194,15 @@ class SanitizingHtmlSerializer {
}
}
private chars(chars: any /** TODO #9100 */) { this.buf.push(encodeEntities(chars)); }
private chars(chars: string) { this.buf.push(encodeEntities(chars)); }
}
function checkClobberedElement(node: Node, nextNode: Node): Node {
if (nextNode && DOM.contains(node, nextNode)) {
throw new Error(
`Failed to sanitize html because the element is clobbered: ${DOM.getOuterHTML(node)}`);
}
return nextNode;
}
// Regular Expressions for parsing tags and attributes