Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: tools/dom/src/Validators.dart

Issue 1365093003: Fix node_validator xss tests for IE and Firefox (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of dart.dom.html; 5 part of dart.dom.html;
6 6
7 7
8 /** 8 /**
9 * Interface used to validate that only accepted elements and attributes are 9 * Interface used to validate that only accepted elements and attributes are
10 * allowed while parsing HTML strings into DOM nodes. 10 * allowed while parsing HTML strings into DOM nodes.
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 } 134 }
135 135
136 136
137 class _ThrowsNodeValidator implements NodeValidator { 137 class _ThrowsNodeValidator implements NodeValidator {
138 final NodeValidator validator; 138 final NodeValidator validator;
139 139
140 _ThrowsNodeValidator(this.validator) {} 140 _ThrowsNodeValidator(this.validator) {}
141 141
142 bool allowsElement(Element element) { 142 bool allowsElement(Element element) {
143 if (!validator.allowsElement(element)) { 143 if (!validator.allowsElement(element)) {
144 throw new ArgumentError(element._safeTagName); 144 throw new ArgumentError(Element._safeTagName(element));
145 } 145 }
146 return true; 146 return true;
147 } 147 }
148 148
149 bool allowsAttribute(Element element, String attributeName, String value) { 149 bool allowsAttribute(Element element, String attributeName, String value) {
150 if (!validator.allowsAttribute(element, attributeName, value)) { 150 if (!validator.allowsAttribute(element, attributeName, value)) {
151 throw new ArgumentError('${element._safeTagName}[$attributeName="$value"]' ); 151 throw new ArgumentError('${Element._safeTagName(element)}[$attributeName=" $value"]');
152 } 152 }
153 } 153 }
154 } 154 }
155 155
156 156
157 /** 157 /**
158 * Standard tree sanitizer which validates a node tree against the provided 158 * Standard tree sanitizer which validates a node tree against the provided
159 * validator and removes any nodes or attributes which are not allowed. 159 * validator and removes any nodes or attributes which are not allowed.
160 */ 160 */
161 class _ValidatingTreeSanitizer implements NodeTreeSanitizer { 161 class _ValidatingTreeSanitizer implements NodeTreeSanitizer {
(...skipping 21 matching lines...) Expand all
183 // or is the fragment, so ask it to remove the child. And if that fails 183 // or is the fragment, so ask it to remove the child. And if that fails
184 // try to set the outer html. 184 // try to set the outer html.
185 if (parent == null) { 185 if (parent == null) {
186 node.remove(); 186 node.remove();
187 } else { 187 } else {
188 parent._removeChild(node); 188 parent._removeChild(node);
189 } 189 }
190 } 190 }
191 191
192 /// Sanitize the element, assuming we can't trust anything about it. 192 /// Sanitize the element, assuming we can't trust anything about it.
193 void _sanitizeUntrustedElement(Element element, Node parent) { 193 void _sanitizeUntrustedElement(/* Element */ element, Node parent) {
194 // If the _hasCorruptedAttributes does not successfully return false, 194 // If the _hasCorruptedAttributes does not successfully return false,
195 // then we consider it corrupted and remove. 195 // then we consider it corrupted and remove.
196 // TODO(alanknight): This is a workaround because on Firefox 196 // TODO(alanknight): This is a workaround because on Firefox
197 // embed/object 197 // embed/object
198 // tags typeof is "function", not "object". We don't recognize them, and 198 // tags typeof is "function", not "object". We don't recognize them, and
199 // can't call methods. This does mean that you can't explicitly allow an 199 // can't call methods. This does mean that you can't explicitly allow an
200 // embed tag. The only thing that will let it through is a null 200 // embed tag. The only thing that will let it through is a null
201 // sanitizer that doesn't traverse the tree at all. But sanitizing while 201 // sanitizer that doesn't traverse the tree at all. But sanitizing while
202 // allowing embeds seems quite unlikely. 202 // allowing embeds seems quite unlikely. This is also the reason that we
203 // can't declare the type of element, as an embed won't pass any type
204 // check in dart2js.
203 var corrupted = true; 205 var corrupted = true;
204 var attrs; 206 var attrs;
205 var isAttr; 207 var isAttr;
206 try { 208 try {
207 // If getting/indexing attributes throws, count that as corrupt. 209 // If getting/indexing attributes throws, count that as corrupt.
208 attrs = element.attributes; 210 attrs = element.attributes;
209 isAttr = attrs['is']; 211 isAttr = attrs['is'];
210 corrupted = Element._hasCorruptedAttributes(element); 212 // On IE, erratically, the hasCorruptedAttributes test can return false,
213 // even though it clearly is corrupted. A separate copy of the test
214 // inlining just the basic check seems to help.
215 var corruptedTest1 = Element._hasCorruptedAttributes(element);
216 var corruptedTest2 = JS('bool', r'!(#.attributes instanceof NamedNodeMap)' , element);
217 corrupted = corruptedTest1 || corruptedTest2;
211 } catch(e) {} 218 } catch(e) {}
212 var elementText = 'element unprintable'; 219 var elementText = 'element unprintable';
213 try { 220 try {
214 elementText = element.toString(); 221 elementText = element.toString();
215 } catch(e) {} 222 } catch(e) {}
216 var elementTagName = element._safeTagName; 223 try {
217 _sanitizeElement(element, parent, corrupted, elementText, elementTagName, 224 var elementTagName = Element._safeTagName(element);
218 attrs, isAttr); 225 _sanitizeElement(element, parent, corrupted, elementText, elementTagName,
226 attrs, isAttr);
227 } on ArgumentError { // Thrown by _ThrowsNodeValidator
228 rethrow;
229 } catch(e) { // Unexpected exception sanitizing -> remove
230 _removeNode(element, parent);
231 window.console.warn('Removing corrupted element $elementText');
232 }
219 } 233 }
220 234
221 /// Having done basic sanity checking on the element, and computed the 235 /// Having done basic sanity checking on the element, and computed the
222 /// important attributes we want to check, remove it if it's not valid 236 /// important attributes we want to check, remove it if it's not valid
223 /// or not allowed, either as a whole or particular attributes. 237 /// or not allowed, either as a whole or particular attributes.
224 void _sanitizeElement(Element element, Node parent, bool corrupted, 238 void _sanitizeElement(Element element, Node parent, bool corrupted,
225 String text, String tag, Map attrs, String isAttr) { 239 String text, String tag, Map attrs, String isAttr) {
226 if (false != corrupted) { 240 if (false != corrupted) {
241 _removeNode(element, parent);
227 window.console.warn( 242 window.console.warn(
228 'Removing element due to corrupted attributes on <$text>'); 243 'Removing element due to corrupted attributes on <$text>');
229 _removeNode(element, parent);
230 return; 244 return;
231 } 245 }
232 if (!validator.allowsElement(element)) { 246 if (!validator.allowsElement(element)) {
247 _removeNode(element, parent);
233 window.console.warn( 248 window.console.warn(
234 'Removing disallowed element <$tag>'); 249 'Removing disallowed element <$tag> from $parent');
235 _removeNode(element, parent);
236 return; 250 return;
237 } 251 }
238 252
239 if (isAttr != null) { 253 if (isAttr != null) {
240 if (!validator.allowsAttribute(element, 'is', isAttr)) { 254 if (!validator.allowsAttribute(element, 'is', isAttr)) {
255 _removeNode(element, parent);
241 window.console.warn('Removing disallowed type extension ' 256 window.console.warn('Removing disallowed type extension '
242 '<$tag is="$isAttr">'); 257 '<$tag is="$isAttr">');
243 _removeNode(element, parent);
244 return; 258 return;
245 } 259 }
246 } 260 }
247 261
248 // TODO(blois): Need to be able to get all attributes, irrespective of 262 // TODO(blois): Need to be able to get all attributes, irrespective of
249 // XMLNS. 263 // XMLNS.
250 var keys = attrs.keys.toList(); 264 var keys = attrs.keys.toList();
251 for (var i = attrs.length - 1; i >= 0; --i) { 265 for (var i = attrs.length - 1; i >= 0; --i) {
252 var name = keys[i]; 266 var name = keys[i];
253 if (!validator.allowsAttribute(element, name.toLowerCase(), 267 if (!validator.allowsAttribute(element, name.toLowerCase(),
(...skipping 19 matching lines...) Expand all
273 case Node.COMMENT_NODE: 287 case Node.COMMENT_NODE:
274 case Node.DOCUMENT_FRAGMENT_NODE: 288 case Node.DOCUMENT_FRAGMENT_NODE:
275 case Node.TEXT_NODE: 289 case Node.TEXT_NODE:
276 case Node.CDATA_SECTION_NODE: 290 case Node.CDATA_SECTION_NODE:
277 break; 291 break;
278 default: 292 default:
279 _removeNode(node, parent); 293 _removeNode(node, parent);
280 } 294 }
281 } 295 }
282 } 296 }
OLDNEW
« no previous file with comments | « tools/dom/src/NodeValidatorBuilder.dart ('k') | tools/dom/templates/html/impl/impl_Element.darttemplate » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698