1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "nsTreeSanitizer.h"
8 
9 #include "mozilla/ArrayUtils.h"
10 #include "mozilla/BindingStyleRule.h"
11 #include "mozilla/DeclarationBlock.h"
12 #include "mozilla/ServoDeclarationBlock.h"
13 #include "mozilla/StyleSheetInlines.h"
14 #ifdef MOZ_OLD_STYLE
15 #include "mozilla/css/Declaration.h"
16 #include "mozilla/css/StyleRule.h"
17 #endif
18 #include "mozilla/css/Rule.h"
19 #include "mozilla/dom/CSSRuleList.h"
20 #include "mozilla/dom/SRIMetadata.h"
21 #include "nsCSSParser.h"
22 #include "nsCSSPropertyID.h"
23 #include "nsUnicharInputStream.h"
24 #include "nsAttrName.h"
25 #include "nsIScriptError.h"
26 #include "nsIScriptSecurityManager.h"
27 #include "nsNetUtil.h"
28 #include "nsComponentManagerUtils.h"
29 #include "NullPrincipal.h"
30 #include "nsContentUtils.h"
31 #include "nsIParserUtils.h"
32 #include "nsIDocument.h"
33 #include "nsQueryObject.h"
34 
35 using namespace mozilla;
36 using namespace mozilla::dom;
37 
38 //
39 // Thanks to Mark Pilgrim and Sam Ruby for the initial whitelist
40 //
41 nsStaticAtom** const kElementsHTML[] = {
42     // clang-format off
43   &nsGkAtoms::a,
44   &nsGkAtoms::abbr,
45   &nsGkAtoms::acronym,
46   &nsGkAtoms::address,
47   &nsGkAtoms::area,
48   &nsGkAtoms::article,
49   &nsGkAtoms::aside,
50   &nsGkAtoms::audio,
51   &nsGkAtoms::b,
52   &nsGkAtoms::bdi,
53   &nsGkAtoms::bdo,
54   &nsGkAtoms::big,
55   &nsGkAtoms::blockquote,
56   // body checked specially
57   &nsGkAtoms::br,
58   &nsGkAtoms::button,
59   &nsGkAtoms::canvas,
60   &nsGkAtoms::caption,
61   &nsGkAtoms::center,
62   &nsGkAtoms::cite,
63   &nsGkAtoms::code,
64   &nsGkAtoms::col,
65   &nsGkAtoms::colgroup,
66   &nsGkAtoms::datalist,
67   &nsGkAtoms::dd,
68   &nsGkAtoms::del,
69   &nsGkAtoms::details,
70   &nsGkAtoms::dfn,
71   &nsGkAtoms::dir,
72   &nsGkAtoms::div,
73   &nsGkAtoms::dl,
74   &nsGkAtoms::dt,
75   &nsGkAtoms::em,
76   &nsGkAtoms::fieldset,
77   &nsGkAtoms::figcaption,
78   &nsGkAtoms::figure,
79   &nsGkAtoms::font,
80   &nsGkAtoms::footer,
81   &nsGkAtoms::form,
82   &nsGkAtoms::h1,
83   &nsGkAtoms::h2,
84   &nsGkAtoms::h3,
85   &nsGkAtoms::h4,
86   &nsGkAtoms::h5,
87   &nsGkAtoms::h6,
88   // head checked specially
89   &nsGkAtoms::header,
90   &nsGkAtoms::hgroup,
91   &nsGkAtoms::hr,
92   // html checked specially
93   &nsGkAtoms::i,
94   &nsGkAtoms::img,
95   &nsGkAtoms::input,
96   &nsGkAtoms::ins,
97   &nsGkAtoms::kbd,
98   &nsGkAtoms::label,
99   &nsGkAtoms::legend,
100   &nsGkAtoms::li,
101   &nsGkAtoms::link,
102   &nsGkAtoms::listing,
103   &nsGkAtoms::map,
104   &nsGkAtoms::mark,
105   &nsGkAtoms::menu,
106   &nsGkAtoms::meta,
107   &nsGkAtoms::meter,
108   &nsGkAtoms::nav,
109   &nsGkAtoms::nobr,
110   &nsGkAtoms::noscript,
111   &nsGkAtoms::ol,
112   &nsGkAtoms::optgroup,
113   &nsGkAtoms::option,
114   &nsGkAtoms::output,
115   &nsGkAtoms::p,
116   &nsGkAtoms::pre,
117   &nsGkAtoms::progress,
118   &nsGkAtoms::q,
119   &nsGkAtoms::rb,
120   &nsGkAtoms::rp,
121   &nsGkAtoms::rt,
122   &nsGkAtoms::rtc,
123   &nsGkAtoms::ruby,
124   &nsGkAtoms::s,
125   &nsGkAtoms::samp,
126   &nsGkAtoms::section,
127   &nsGkAtoms::select,
128   &nsGkAtoms::small,
129   &nsGkAtoms::source,
130   &nsGkAtoms::span,
131   &nsGkAtoms::strike,
132   &nsGkAtoms::strong,
133   &nsGkAtoms::sub,
134   &nsGkAtoms::summary,
135   &nsGkAtoms::sup,
136   // style checked specially
137   &nsGkAtoms::table,
138   &nsGkAtoms::tbody,
139   &nsGkAtoms::td,
140   &nsGkAtoms::textarea,
141   &nsGkAtoms::tfoot,
142   &nsGkAtoms::th,
143   &nsGkAtoms::thead,
144   &nsGkAtoms::time,
145   // title checked specially
146   &nsGkAtoms::tr,
147   &nsGkAtoms::track,
148   &nsGkAtoms::tt,
149   &nsGkAtoms::u,
150   &nsGkAtoms::ul,
151   &nsGkAtoms::var,
152   &nsGkAtoms::video,
153   &nsGkAtoms::wbr,
154   nullptr
155     // clang-format on
156 };
157 
158 nsStaticAtom** const kAttributesHTML[] = {
159     // clang-format off
160   &nsGkAtoms::abbr,
161   &nsGkAtoms::accept,
162   &nsGkAtoms::acceptcharset,
163   &nsGkAtoms::accesskey,
164   &nsGkAtoms::action,
165   &nsGkAtoms::alt,
166   &nsGkAtoms::as,
167   &nsGkAtoms::autocomplete,
168   &nsGkAtoms::autofocus,
169   &nsGkAtoms::autoplay,
170   &nsGkAtoms::axis,
171   &nsGkAtoms::_char,
172   &nsGkAtoms::charoff,
173   &nsGkAtoms::charset,
174   &nsGkAtoms::checked,
175   &nsGkAtoms::cite,
176   &nsGkAtoms::_class,
177   &nsGkAtoms::cols,
178   &nsGkAtoms::colspan,
179   &nsGkAtoms::content,
180   &nsGkAtoms::contenteditable,
181   &nsGkAtoms::contextmenu,
182   &nsGkAtoms::controls,
183   &nsGkAtoms::coords,
184   &nsGkAtoms::crossorigin,
185   &nsGkAtoms::datetime,
186   &nsGkAtoms::dir,
187   &nsGkAtoms::disabled,
188   &nsGkAtoms::draggable,
189   &nsGkAtoms::enctype,
190   &nsGkAtoms::face,
191   &nsGkAtoms::_for,
192   &nsGkAtoms::frame,
193   &nsGkAtoms::headers,
194   &nsGkAtoms::height,
195   &nsGkAtoms::hidden,
196   &nsGkAtoms::high,
197   &nsGkAtoms::href,
198   &nsGkAtoms::hreflang,
199   &nsGkAtoms::icon,
200   &nsGkAtoms::id,
201   &nsGkAtoms::integrity,
202   &nsGkAtoms::ismap,
203   &nsGkAtoms::itemid,
204   &nsGkAtoms::itemprop,
205   &nsGkAtoms::itemref,
206   &nsGkAtoms::itemscope,
207   &nsGkAtoms::itemtype,
208   &nsGkAtoms::kind,
209   &nsGkAtoms::label,
210   &nsGkAtoms::lang,
211   &nsGkAtoms::list,
212   &nsGkAtoms::longdesc,
213   &nsGkAtoms::loop,
214   &nsGkAtoms::low,
215   &nsGkAtoms::max,
216   &nsGkAtoms::maxlength,
217   &nsGkAtoms::media,
218   &nsGkAtoms::method,
219   &nsGkAtoms::min,
220   &nsGkAtoms::minlength,
221   &nsGkAtoms::multiple,
222   &nsGkAtoms::muted,
223   &nsGkAtoms::name,
224   &nsGkAtoms::nohref,
225   &nsGkAtoms::novalidate,
226   &nsGkAtoms::nowrap,
227   &nsGkAtoms::open,
228   &nsGkAtoms::optimum,
229   &nsGkAtoms::pattern,
230   &nsGkAtoms::placeholder,
231   &nsGkAtoms::playbackrate,
232   &nsGkAtoms::poster,
233   &nsGkAtoms::preload,
234   &nsGkAtoms::prompt,
235   &nsGkAtoms::pubdate,
236   &nsGkAtoms::radiogroup,
237   &nsGkAtoms::readonly,
238   &nsGkAtoms::rel,
239   &nsGkAtoms::required,
240   &nsGkAtoms::rev,
241   &nsGkAtoms::reversed,
242   &nsGkAtoms::role,
243   &nsGkAtoms::rows,
244   &nsGkAtoms::rowspan,
245   &nsGkAtoms::rules,
246   &nsGkAtoms::scoped,
247   &nsGkAtoms::scope,
248   &nsGkAtoms::selected,
249   &nsGkAtoms::shape,
250   &nsGkAtoms::span,
251   &nsGkAtoms::spellcheck,
252   &nsGkAtoms::src,
253   &nsGkAtoms::srclang,
254   &nsGkAtoms::start,
255   &nsGkAtoms::summary,
256   &nsGkAtoms::tabindex,
257   &nsGkAtoms::target,
258   &nsGkAtoms::title,
259   &nsGkAtoms::type,
260   &nsGkAtoms::usemap,
261   &nsGkAtoms::value,
262   &nsGkAtoms::width,
263   &nsGkAtoms::wrap,
264   nullptr
265     // clang-format on
266 };
267 
268 nsStaticAtom** const kPresAttributesHTML[] = {
269     // clang-format off
270   &nsGkAtoms::align,
271   &nsGkAtoms::background,
272   &nsGkAtoms::bgcolor,
273   &nsGkAtoms::border,
274   &nsGkAtoms::cellpadding,
275   &nsGkAtoms::cellspacing,
276   &nsGkAtoms::color,
277   &nsGkAtoms::compact,
278   &nsGkAtoms::clear,
279   &nsGkAtoms::hspace,
280   &nsGkAtoms::noshade,
281   &nsGkAtoms::pointSize,
282   &nsGkAtoms::size,
283   &nsGkAtoms::valign,
284   &nsGkAtoms::vspace,
285   nullptr
286     // clang-format on
287 };
288 
289 nsStaticAtom** const kURLAttributesHTML[] = {
290     // clang-format off
291   &nsGkAtoms::action,
292   &nsGkAtoms::href,
293   &nsGkAtoms::src,
294   &nsGkAtoms::longdesc,
295   &nsGkAtoms::cite,
296   &nsGkAtoms::background,
297   nullptr
298     // clang-format on
299 };
300 
301 nsStaticAtom** const kElementsSVG[] = {
302     // clang-format off
303   &nsGkAtoms::a, // a
304   &nsGkAtoms::circle, // circle
305   &nsGkAtoms::clipPath, // clipPath
306   &nsGkAtoms::colorProfile, // color-profile
307   &nsGkAtoms::cursor, // cursor
308   &nsGkAtoms::defs, // defs
309   &nsGkAtoms::desc, // desc
310   &nsGkAtoms::ellipse, // ellipse
311   &nsGkAtoms::elevation, // elevation
312   &nsGkAtoms::erode, // erode
313   &nsGkAtoms::ex, // ex
314   &nsGkAtoms::exact, // exact
315   &nsGkAtoms::exponent, // exponent
316   &nsGkAtoms::feBlend, // feBlend
317   &nsGkAtoms::feColorMatrix, // feColorMatrix
318   &nsGkAtoms::feComponentTransfer, // feComponentTransfer
319   &nsGkAtoms::feComposite, // feComposite
320   &nsGkAtoms::feConvolveMatrix, // feConvolveMatrix
321   &nsGkAtoms::feDiffuseLighting, // feDiffuseLighting
322   &nsGkAtoms::feDisplacementMap, // feDisplacementMap
323   &nsGkAtoms::feDistantLight, // feDistantLight
324   &nsGkAtoms::feDropShadow, // feDropShadow
325   &nsGkAtoms::feFlood, // feFlood
326   &nsGkAtoms::feFuncA, // feFuncA
327   &nsGkAtoms::feFuncB, // feFuncB
328   &nsGkAtoms::feFuncG, // feFuncG
329   &nsGkAtoms::feFuncR, // feFuncR
330   &nsGkAtoms::feGaussianBlur, // feGaussianBlur
331   &nsGkAtoms::feImage, // feImage
332   &nsGkAtoms::feMerge, // feMerge
333   &nsGkAtoms::feMergeNode, // feMergeNode
334   &nsGkAtoms::feMorphology, // feMorphology
335   &nsGkAtoms::feOffset, // feOffset
336   &nsGkAtoms::fePointLight, // fePointLight
337   &nsGkAtoms::feSpecularLighting, // feSpecularLighting
338   &nsGkAtoms::feSpotLight, // feSpotLight
339   &nsGkAtoms::feTile, // feTile
340   &nsGkAtoms::feTurbulence, // feTurbulence
341   &nsGkAtoms::filter, // filter
342   &nsGkAtoms::font, // font
343   &nsGkAtoms::font_face, // font-face
344   &nsGkAtoms::font_face_format, // font-face-format
345   &nsGkAtoms::font_face_name, // font-face-name
346   &nsGkAtoms::font_face_src, // font-face-src
347   &nsGkAtoms::font_face_uri, // font-face-uri
348   &nsGkAtoms::foreignObject, // foreignObject
349   &nsGkAtoms::g, // g
350   // glyph
351   &nsGkAtoms::glyphRef, // glyphRef
352   // hkern
353   &nsGkAtoms::image, // image
354   &nsGkAtoms::line, // line
355   &nsGkAtoms::linearGradient, // linearGradient
356   &nsGkAtoms::marker, // marker
357   &nsGkAtoms::mask, // mask
358   &nsGkAtoms::metadata, // metadata
359   &nsGkAtoms::missingGlyph, // missingGlyph
360   &nsGkAtoms::mpath, // mpath
361   &nsGkAtoms::path, // path
362   &nsGkAtoms::pattern, // pattern
363   &nsGkAtoms::polygon, // polygon
364   &nsGkAtoms::polyline, // polyline
365   &nsGkAtoms::radialGradient, // radialGradient
366   &nsGkAtoms::rect, // rect
367   &nsGkAtoms::stop, // stop
368   &nsGkAtoms::svg, // svg
369   &nsGkAtoms::svgSwitch, // switch
370   &nsGkAtoms::symbol, // symbol
371   &nsGkAtoms::text, // text
372   &nsGkAtoms::textPath, // textPath
373   &nsGkAtoms::title, // title
374   &nsGkAtoms::tref, // tref
375   &nsGkAtoms::tspan, // tspan
376   &nsGkAtoms::use, // use
377   &nsGkAtoms::view, // view
378   // vkern
379   nullptr
380     // clang-format on
381 };
382 
383 nsStaticAtom** const kAttributesSVG[] = {
384     // clang-format off
385   // accent-height
386   &nsGkAtoms::accumulate, // accumulate
387   &nsGkAtoms::additive, // additive
388   &nsGkAtoms::alignment_baseline, // alignment-baseline
389   // alphabetic
390   &nsGkAtoms::amplitude, // amplitude
391   // arabic-form
392   // ascent
393   &nsGkAtoms::attributeName, // attributeName
394   &nsGkAtoms::attributeType, // attributeType
395   &nsGkAtoms::azimuth, // azimuth
396   &nsGkAtoms::baseFrequency, // baseFrequency
397   &nsGkAtoms::baseline_shift, // baseline-shift
398   // baseProfile
399   // bbox
400   &nsGkAtoms::begin, // begin
401   &nsGkAtoms::bias, // bias
402   &nsGkAtoms::by, // by
403   &nsGkAtoms::calcMode, // calcMode
404   // cap-height
405   &nsGkAtoms::_class, // class
406   &nsGkAtoms::clip_path, // clip-path
407   &nsGkAtoms::clip_rule, // clip-rule
408   &nsGkAtoms::clipPathUnits, // clipPathUnits
409   &nsGkAtoms::color, // color
410   &nsGkAtoms::colorInterpolation, // color-interpolation
411   &nsGkAtoms::colorInterpolationFilters, // color-interpolation-filters
412   &nsGkAtoms::cursor, // cursor
413   &nsGkAtoms::cx, // cx
414   &nsGkAtoms::cy, // cy
415   &nsGkAtoms::d, // d
416   // descent
417   &nsGkAtoms::diffuseConstant, // diffuseConstant
418   &nsGkAtoms::direction, // direction
419   &nsGkAtoms::display, // display
420   &nsGkAtoms::divisor, // divisor
421   &nsGkAtoms::dominant_baseline, // dominant-baseline
422   &nsGkAtoms::dur, // dur
423   &nsGkAtoms::dx, // dx
424   &nsGkAtoms::dy, // dy
425   &nsGkAtoms::edgeMode, // edgeMode
426   &nsGkAtoms::elevation, // elevation
427   // enable-background
428   &nsGkAtoms::end, // end
429   &nsGkAtoms::fill, // fill
430   &nsGkAtoms::fill_opacity, // fill-opacity
431   &nsGkAtoms::fill_rule, // fill-rule
432   &nsGkAtoms::filter, // filter
433   &nsGkAtoms::filterUnits, // filterUnits
434   &nsGkAtoms::flood_color, // flood-color
435   &nsGkAtoms::flood_opacity, // flood-opacity
436   // XXX focusable
437   &nsGkAtoms::font, // font
438   &nsGkAtoms::font_family, // font-family
439   &nsGkAtoms::font_size, // font-size
440   &nsGkAtoms::font_size_adjust, // font-size-adjust
441   &nsGkAtoms::font_stretch, // font-stretch
442   &nsGkAtoms::font_style, // font-style
443   &nsGkAtoms::font_variant, // font-variant
444   &nsGkAtoms::fontWeight, // font-weight
445   &nsGkAtoms::format, // format
446   &nsGkAtoms::from, // from
447   &nsGkAtoms::fx, // fx
448   &nsGkAtoms::fy, // fy
449   // g1
450   // g2
451   // glyph-name
452   // glyphRef
453   // glyph-orientation-horizontal
454   // glyph-orientation-vertical
455   &nsGkAtoms::gradientTransform, // gradientTransform
456   &nsGkAtoms::gradientUnits, // gradientUnits
457   &nsGkAtoms::height, // height
458   // horiz-adv-x
459   // horiz-origin-x
460   // horiz-origin-y
461   &nsGkAtoms::id, // id
462   // ideographic
463   &nsGkAtoms::image_rendering, // image-rendering
464   &nsGkAtoms::in, // in
465   &nsGkAtoms::in2, // in2
466   &nsGkAtoms::intercept, // intercept
467   // k
468   &nsGkAtoms::k1, // k1
469   &nsGkAtoms::k2, // k2
470   &nsGkAtoms::k3, // k3
471   &nsGkAtoms::k4, // k4
472   // kerning
473   &nsGkAtoms::kernelMatrix, // kernelMatrix
474   &nsGkAtoms::kernelUnitLength, // kernelUnitLength
475   &nsGkAtoms::keyPoints, // keyPoints
476   &nsGkAtoms::keySplines, // keySplines
477   &nsGkAtoms::keyTimes, // keyTimes
478   &nsGkAtoms::lang, // lang
479   // lengthAdjust
480   &nsGkAtoms::letter_spacing, // letter-spacing
481   &nsGkAtoms::lighting_color, // lighting-color
482   &nsGkAtoms::limitingConeAngle, // limitingConeAngle
483   // local
484   &nsGkAtoms::marker, // marker
485   &nsGkAtoms::marker_end, // marker-end
486   &nsGkAtoms::marker_mid, // marker-mid
487   &nsGkAtoms::marker_start, // marker-start
488   &nsGkAtoms::markerHeight, // markerHeight
489   &nsGkAtoms::markerUnits, // markerUnits
490   &nsGkAtoms::markerWidth, // markerWidth
491   &nsGkAtoms::mask, // mask
492   &nsGkAtoms::maskContentUnits, // maskContentUnits
493   &nsGkAtoms::maskUnits, // maskUnits
494   // mathematical
495   &nsGkAtoms::max, // max
496   &nsGkAtoms::media, // media
497   &nsGkAtoms::method, // method
498   &nsGkAtoms::min, // min
499   &nsGkAtoms::mode, // mode
500   &nsGkAtoms::name, // name
501   &nsGkAtoms::numOctaves, // numOctaves
502   &nsGkAtoms::offset, // offset
503   &nsGkAtoms::opacity, // opacity
504   &nsGkAtoms::_operator, // operator
505   &nsGkAtoms::order, // order
506   &nsGkAtoms::orient, // orient
507   &nsGkAtoms::orientation, // orientation
508   // origin
509   // overline-position
510   // overline-thickness
511   &nsGkAtoms::overflow, // overflow
512   // panose-1
513   &nsGkAtoms::path, // path
514   &nsGkAtoms::pathLength, // pathLength
515   &nsGkAtoms::patternContentUnits, // patternContentUnits
516   &nsGkAtoms::patternTransform, // patternTransform
517   &nsGkAtoms::patternUnits, // patternUnits
518   &nsGkAtoms::pointer_events, // pointer-events XXX is this safe?
519   &nsGkAtoms::points, // points
520   &nsGkAtoms::pointsAtX, // pointsAtX
521   &nsGkAtoms::pointsAtY, // pointsAtY
522   &nsGkAtoms::pointsAtZ, // pointsAtZ
523   &nsGkAtoms::preserveAlpha, // preserveAlpha
524   &nsGkAtoms::preserveAspectRatio, // preserveAspectRatio
525   &nsGkAtoms::primitiveUnits, // primitiveUnits
526   &nsGkAtoms::r, // r
527   &nsGkAtoms::radius, // radius
528   &nsGkAtoms::refX, // refX
529   &nsGkAtoms::refY, // refY
530   &nsGkAtoms::repeatCount, // repeatCount
531   &nsGkAtoms::repeatDur, // repeatDur
532   &nsGkAtoms::requiredExtensions, // requiredExtensions
533   &nsGkAtoms::requiredFeatures, // requiredFeatures
534   &nsGkAtoms::restart, // restart
535   &nsGkAtoms::result, // result
536   &nsGkAtoms::rotate, // rotate
537   &nsGkAtoms::rx, // rx
538   &nsGkAtoms::ry, // ry
539   &nsGkAtoms::scale, // scale
540   &nsGkAtoms::seed, // seed
541   &nsGkAtoms::shape_rendering, // shape-rendering
542   &nsGkAtoms::slope, // slope
543   &nsGkAtoms::spacing, // spacing
544   &nsGkAtoms::specularConstant, // specularConstant
545   &nsGkAtoms::specularExponent, // specularExponent
546   &nsGkAtoms::spreadMethod, // spreadMethod
547   &nsGkAtoms::startOffset, // startOffset
548   &nsGkAtoms::stdDeviation, // stdDeviation
549   // stemh
550   // stemv
551   &nsGkAtoms::stitchTiles, // stitchTiles
552   &nsGkAtoms::stop_color, // stop-color
553   &nsGkAtoms::stop_opacity, // stop-opacity
554   // strikethrough-position
555   // strikethrough-thickness
556   &nsGkAtoms::string, // string
557   &nsGkAtoms::stroke, // stroke
558   &nsGkAtoms::stroke_dasharray, // stroke-dasharray
559   &nsGkAtoms::stroke_dashoffset, // stroke-dashoffset
560   &nsGkAtoms::stroke_linecap, // stroke-linecap
561   &nsGkAtoms::stroke_linejoin, // stroke-linejoin
562   &nsGkAtoms::stroke_miterlimit, // stroke-miterlimit
563   &nsGkAtoms::stroke_opacity, // stroke-opacity
564   &nsGkAtoms::stroke_width, // stroke-width
565   &nsGkAtoms::surfaceScale, // surfaceScale
566   &nsGkAtoms::systemLanguage, // systemLanguage
567   &nsGkAtoms::tableValues, // tableValues
568   &nsGkAtoms::target, // target
569   &nsGkAtoms::targetX, // targetX
570   &nsGkAtoms::targetY, // targetY
571   &nsGkAtoms::text_anchor, // text-anchor
572   &nsGkAtoms::text_decoration, // text-decoration
573   // textLength
574   &nsGkAtoms::text_rendering, // text-rendering
575   &nsGkAtoms::title, // title
576   &nsGkAtoms::to, // to
577   &nsGkAtoms::transform, // transform
578   &nsGkAtoms::type, // type
579   // u1
580   // u2
581   // underline-position
582   // underline-thickness
583   // unicode
584   &nsGkAtoms::unicode_bidi, // unicode-bidi
585   // unicode-range
586   // units-per-em
587   // v-alphabetic
588   // v-hanging
589   // v-ideographic
590   // v-mathematical
591   &nsGkAtoms::values, // values
592   &nsGkAtoms::vector_effect, // vector-effect
593   // vert-adv-y
594   // vert-origin-x
595   // vert-origin-y
596   &nsGkAtoms::viewBox, // viewBox
597   &nsGkAtoms::viewTarget, // viewTarget
598   &nsGkAtoms::visibility, // visibility
599   &nsGkAtoms::width, // width
600   // widths
601   &nsGkAtoms::word_spacing, // word-spacing
602   &nsGkAtoms::writing_mode, // writing-mode
603   &nsGkAtoms::x, // x
604   // x-height
605   &nsGkAtoms::x1, // x1
606   &nsGkAtoms::x2, // x2
607   &nsGkAtoms::xChannelSelector, // xChannelSelector
608   &nsGkAtoms::y, // y
609   &nsGkAtoms::y1, // y1
610   &nsGkAtoms::y2, // y2
611   &nsGkAtoms::yChannelSelector, // yChannelSelector
612   &nsGkAtoms::z, // z
613   &nsGkAtoms::zoomAndPan, // zoomAndPan
614   nullptr
615     // clang-format on
616 };
617 
618 nsStaticAtom** const kURLAttributesSVG[] = {
619     // clang-format off
620   &nsGkAtoms::href,
621   nullptr
622     // clang-format on
623 };
624 
625 nsStaticAtom** const kElementsMathML[] = {
626     // clang-format off
627    &nsGkAtoms::abs_, // abs
628    &nsGkAtoms::_and, // and
629    &nsGkAtoms::annotation_, // annotation
630    &nsGkAtoms::annotation_xml_, // annotation-xml
631    &nsGkAtoms::apply_, // apply
632    &nsGkAtoms::approx_, // approx
633    &nsGkAtoms::arccos_, // arccos
634    &nsGkAtoms::arccosh_, // arccosh
635    &nsGkAtoms::arccot_, // arccot
636    &nsGkAtoms::arccoth_, // arccoth
637    &nsGkAtoms::arccsc_, // arccsc
638    &nsGkAtoms::arccsch_, // arccsch
639    &nsGkAtoms::arcsec_, // arcsec
640    &nsGkAtoms::arcsech_, // arcsech
641    &nsGkAtoms::arcsin_, // arcsin
642    &nsGkAtoms::arcsinh_, // arcsinh
643    &nsGkAtoms::arctan_, // arctan
644    &nsGkAtoms::arctanh_, // arctanh
645    &nsGkAtoms::arg_, // arg
646    &nsGkAtoms::bind_, // bind
647    &nsGkAtoms::bvar_, // bvar
648    &nsGkAtoms::card_, // card
649    &nsGkAtoms::cartesianproduct_, // cartesianproduct
650    &nsGkAtoms::cbytes_, // cbytes
651    &nsGkAtoms::ceiling, // ceiling
652    &nsGkAtoms::cerror_, // cerror
653    &nsGkAtoms::ci_, // ci
654    &nsGkAtoms::cn_, // cn
655    &nsGkAtoms::codomain_, // codomain
656    &nsGkAtoms::complexes_, // complexes
657    &nsGkAtoms::compose_, // compose
658    &nsGkAtoms::condition_, // condition
659    &nsGkAtoms::conjugate_, // conjugate
660    &nsGkAtoms::cos_, // cos
661    &nsGkAtoms::cosh_, // cosh
662    &nsGkAtoms::cot_, // cot
663    &nsGkAtoms::coth_, // coth
664    &nsGkAtoms::cs_, // cs
665    &nsGkAtoms::csc_, // csc
666    &nsGkAtoms::csch_, // csch
667    &nsGkAtoms::csymbol_, // csymbol
668    &nsGkAtoms::curl_, // curl
669    &nsGkAtoms::declare, // declare
670    &nsGkAtoms::degree_, // degree
671    &nsGkAtoms::determinant_, // determinant
672    &nsGkAtoms::diff_, // diff
673    &nsGkAtoms::divergence_, // divergence
674    &nsGkAtoms::divide_, // divide
675    &nsGkAtoms::domain_, // domain
676    &nsGkAtoms::domainofapplication_, // domainofapplication
677    &nsGkAtoms::el_, // el
678    &nsGkAtoms::emptyset_, // emptyset
679    &nsGkAtoms::eq_, // eq
680    &nsGkAtoms::equivalent_, // equivalent
681    &nsGkAtoms::eulergamma_, // eulergamma
682    &nsGkAtoms::exists_, // exists
683    &nsGkAtoms::exp_, // exp
684    &nsGkAtoms::exponentiale_, // exponentiale
685    &nsGkAtoms::factorial_, // factorial
686    &nsGkAtoms::factorof_, // factorof
687    &nsGkAtoms::_false, // false
688    &nsGkAtoms::floor, // floor
689    &nsGkAtoms::fn_, // fn
690    &nsGkAtoms::forall_, // forall
691    &nsGkAtoms::gcd_, // gcd
692    &nsGkAtoms::geq_, // geq
693    &nsGkAtoms::grad, // grad
694    &nsGkAtoms::gt_, // gt
695    &nsGkAtoms::ident_, // ident
696    &nsGkAtoms::image, // image
697    &nsGkAtoms::imaginary_, // imaginary
698    &nsGkAtoms::imaginaryi_, // imaginaryi
699    &nsGkAtoms::implies_, // implies
700    &nsGkAtoms::in, // in
701    &nsGkAtoms::infinity, // infinity
702    &nsGkAtoms::int_, // int
703    &nsGkAtoms::integers_, // integers
704    &nsGkAtoms::intersect_, // intersect
705    &nsGkAtoms::interval_, // interval
706    &nsGkAtoms::inverse_, // inverse
707    &nsGkAtoms::lambda_, // lambda
708    &nsGkAtoms::laplacian_, // laplacian
709    &nsGkAtoms::lcm_, // lcm
710    &nsGkAtoms::leq_, // leq
711    &nsGkAtoms::limit_, // limit
712    &nsGkAtoms::list_, // list
713    &nsGkAtoms::ln_, // ln
714    &nsGkAtoms::log_, // log
715    &nsGkAtoms::logbase_, // logbase
716    &nsGkAtoms::lowlimit_, // lowlimit
717    &nsGkAtoms::lt_, // lt
718    &nsGkAtoms::maction_, // maction
719    &nsGkAtoms::maligngroup_, // maligngroup
720    &nsGkAtoms::malignmark_, // malignmark
721    &nsGkAtoms::math, // math
722    &nsGkAtoms::matrix, // matrix
723    &nsGkAtoms::matrixrow_, // matrixrow
724    &nsGkAtoms::max, // max
725    &nsGkAtoms::mean_, // mean
726    &nsGkAtoms::median_, // median
727    &nsGkAtoms::menclose_, // menclose
728    &nsGkAtoms::merror_, // merror
729    &nsGkAtoms::mfenced_, // mfenced
730    &nsGkAtoms::mfrac_, // mfrac
731    &nsGkAtoms::mglyph_, // mglyph
732    &nsGkAtoms::mi_, // mi
733    &nsGkAtoms::min, // min
734    &nsGkAtoms::minus_, // minus
735    &nsGkAtoms::mlabeledtr_, // mlabeledtr
736    &nsGkAtoms::mlongdiv_, // mlongdiv
737    &nsGkAtoms::mmultiscripts_, // mmultiscripts
738    &nsGkAtoms::mn_, // mn
739    &nsGkAtoms::mo_, // mo
740    &nsGkAtoms::mode, // mode
741    &nsGkAtoms::moment_, // moment
742    &nsGkAtoms::momentabout_, // momentabout
743    &nsGkAtoms::mover_, // mover
744    &nsGkAtoms::mpadded_, // mpadded
745    &nsGkAtoms::mphantom_, // mphantom
746    &nsGkAtoms::mprescripts_, // mprescripts
747    &nsGkAtoms::mroot_, // mroot
748    &nsGkAtoms::mrow_, // mrow
749    &nsGkAtoms::ms_, // ms
750    &nsGkAtoms::mscarries_, // mscarries
751    &nsGkAtoms::mscarry_, // mscarry
752    &nsGkAtoms::msgroup_, // msgroup
753    &nsGkAtoms::msline_, // msline
754    &nsGkAtoms::mspace_, // mspace
755    &nsGkAtoms::msqrt_, // msqrt
756    &nsGkAtoms::msrow_, // msrow
757    &nsGkAtoms::mstack_, // mstack
758    &nsGkAtoms::mstyle_, // mstyle
759    &nsGkAtoms::msub_, // msub
760    &nsGkAtoms::msubsup_, // msubsup
761    &nsGkAtoms::msup_, // msup
762    &nsGkAtoms::mtable_, // mtable
763    &nsGkAtoms::mtd_, // mtd
764    &nsGkAtoms::mtext_, // mtext
765    &nsGkAtoms::mtr_, // mtr
766    &nsGkAtoms::munder_, // munder
767    &nsGkAtoms::munderover_, // munderover
768    &nsGkAtoms::naturalnumbers_, // naturalnumbers
769    &nsGkAtoms::neq_, // neq
770    &nsGkAtoms::none, // none
771    &nsGkAtoms::_not, // not
772    &nsGkAtoms::notanumber_, // notanumber
773    &nsGkAtoms::note_, // note
774    &nsGkAtoms::notin_, // notin
775    &nsGkAtoms::notprsubset_, // notprsubset
776    &nsGkAtoms::notsubset_, // notsubset
777    &nsGkAtoms::_or, // or
778    &nsGkAtoms::otherwise, // otherwise
779    &nsGkAtoms::outerproduct_, // outerproduct
780    &nsGkAtoms::partialdiff_, // partialdiff
781    &nsGkAtoms::pi_, // pi
782    &nsGkAtoms::piece_, // piece
783    &nsGkAtoms::piecewise_, // piecewise
784    &nsGkAtoms::plus_, // plus
785    &nsGkAtoms::power_, // power
786    &nsGkAtoms::primes_, // primes
787    &nsGkAtoms::product_, // product
788    &nsGkAtoms::prsubset_, // prsubset
789    &nsGkAtoms::quotient_, // quotient
790    &nsGkAtoms::rationals_, // rationals
791    &nsGkAtoms::real_, // real
792    &nsGkAtoms::reals_, // reals
793    &nsGkAtoms::reln_, // reln
794    &nsGkAtoms::rem, // rem
795    &nsGkAtoms::root_, // root
796    &nsGkAtoms::scalarproduct_, // scalarproduct
797    &nsGkAtoms::sdev_, // sdev
798    &nsGkAtoms::sec_, // sec
799    &nsGkAtoms::sech_, // sech
800    &nsGkAtoms::selector_, // selector
801    &nsGkAtoms::semantics_, // semantics
802    &nsGkAtoms::sep_, // sep
803    &nsGkAtoms::set_, // set
804    &nsGkAtoms::setdiff_, // setdiff
805    &nsGkAtoms::share_, // share
806    &nsGkAtoms::sin_, // sin
807    &nsGkAtoms::sinh_, // sinh
808    &nsGkAtoms::subset_, // subset
809    &nsGkAtoms::sum, // sum
810    &nsGkAtoms::tan_, // tan
811    &nsGkAtoms::tanh_, // tanh
812    &nsGkAtoms::tendsto_, // tendsto
813    &nsGkAtoms::times_, // times
814    &nsGkAtoms::transpose_, // transpose
815    &nsGkAtoms::_true, // true
816    &nsGkAtoms::union_, // union
817    &nsGkAtoms::uplimit_, // uplimit
818    &nsGkAtoms::variance_, // variance
819    &nsGkAtoms::vector_, // vector
820    &nsGkAtoms::vectorproduct_, // vectorproduct
821    &nsGkAtoms::xor_, // xor
822    nullptr
823     // clang-format on
824 };
825 
826 nsStaticAtom** const kAttributesMathML[] = {
827     // clang-format off
828    &nsGkAtoms::accent_, // accent
829    &nsGkAtoms::accentunder_, // accentunder
830    &nsGkAtoms::actiontype_, // actiontype
831    &nsGkAtoms::align, // align
832    &nsGkAtoms::alignmentscope_, // alignmentscope
833    &nsGkAtoms::alt, // alt
834    &nsGkAtoms::altimg_, // altimg
835    &nsGkAtoms::altimg_height_, // altimg-height
836    &nsGkAtoms::altimg_valign_, // altimg-valign
837    &nsGkAtoms::altimg_width_, // altimg-width
838    &nsGkAtoms::background, // background
839    &nsGkAtoms::base, // base
840    &nsGkAtoms::bevelled_, // bevelled
841    &nsGkAtoms::cd_, // cd
842    &nsGkAtoms::cdgroup_, // cdgroup
843    &nsGkAtoms::charalign_, // charalign
844    &nsGkAtoms::close, // close
845    &nsGkAtoms::closure_, // closure
846    &nsGkAtoms::color, // color
847    &nsGkAtoms::columnalign_, // columnalign
848    &nsGkAtoms::columnalignment_, // columnalignment
849    &nsGkAtoms::columnlines_, // columnlines
850    &nsGkAtoms::columnspacing_, // columnspacing
851    &nsGkAtoms::columnspan_, // columnspan
852    &nsGkAtoms::columnwidth_, // columnwidth
853    &nsGkAtoms::crossout_, // crossout
854    &nsGkAtoms::decimalpoint_, // decimalpoint
855    &nsGkAtoms::definitionURL_, // definitionURL
856    &nsGkAtoms::denomalign_, // denomalign
857    &nsGkAtoms::depth_, // depth
858    &nsGkAtoms::dir, // dir
859    &nsGkAtoms::display, // display
860    &nsGkAtoms::displaystyle_, // displaystyle
861    &nsGkAtoms::edge_, // edge
862    &nsGkAtoms::encoding, // encoding
863    &nsGkAtoms::equalcolumns_, // equalcolumns
864    &nsGkAtoms::equalrows_, // equalrows
865    &nsGkAtoms::fence_, // fence
866    &nsGkAtoms::fontfamily_, // fontfamily
867    &nsGkAtoms::fontsize_, // fontsize
868    &nsGkAtoms::fontstyle_, // fontstyle
869    &nsGkAtoms::fontweight_, // fontweight
870    &nsGkAtoms::form, // form
871    &nsGkAtoms::frame, // frame
872    &nsGkAtoms::framespacing_, // framespacing
873    &nsGkAtoms::groupalign_, // groupalign
874    &nsGkAtoms::height, // height
875    &nsGkAtoms::href, // href
876    &nsGkAtoms::id, // id
877    &nsGkAtoms::indentalign_, // indentalign
878    &nsGkAtoms::indentalignfirst_, // indentalignfirst
879    &nsGkAtoms::indentalignlast_, // indentalignlast
880    &nsGkAtoms::indentshift_, // indentshift
881    &nsGkAtoms::indentshiftfirst_, // indentshiftfirst
882    &nsGkAtoms::indenttarget_, // indenttarget
883    &nsGkAtoms::index, // index
884    &nsGkAtoms::integer, // integer
885    &nsGkAtoms::largeop_, // largeop
886    &nsGkAtoms::length, // length
887    &nsGkAtoms::linebreak_, // linebreak
888    &nsGkAtoms::linebreakmultchar_, // linebreakmultchar
889    &nsGkAtoms::linebreakstyle_, // linebreakstyle
890    &nsGkAtoms::linethickness_, // linethickness
891    &nsGkAtoms::location_, // location
892    &nsGkAtoms::longdivstyle_, // longdivstyle
893    &nsGkAtoms::lquote_, // lquote
894    &nsGkAtoms::lspace_, // lspace
895    &nsGkAtoms::ltr, // ltr
896    &nsGkAtoms::mathbackground_, // mathbackground
897    &nsGkAtoms::mathcolor_, // mathcolor
898    &nsGkAtoms::mathsize_, // mathsize
899    &nsGkAtoms::mathvariant_, // mathvariant
900    &nsGkAtoms::maxsize_, // maxsize
901    &nsGkAtoms::minlabelspacing_, // minlabelspacing
902    &nsGkAtoms::minsize_, // minsize
903    &nsGkAtoms::movablelimits_, // movablelimits
904    &nsGkAtoms::msgroup_, // msgroup
905    &nsGkAtoms::name, // name
906    &nsGkAtoms::newline, // newline
907    &nsGkAtoms::notation_, // notation
908    &nsGkAtoms::numalign_, // numalign
909    &nsGkAtoms::number, // number
910    &nsGkAtoms::open, // open
911    &nsGkAtoms::order, // order
912    &nsGkAtoms::other_, // other
913    &nsGkAtoms::overflow, // overflow
914    &nsGkAtoms::position, // position
915    &nsGkAtoms::role, // role
916    &nsGkAtoms::rowalign_, // rowalign
917    &nsGkAtoms::rowlines_, // rowlines
918    &nsGkAtoms::rowspacing_, // rowspacing
919    &nsGkAtoms::rowspan, // rowspan
920    &nsGkAtoms::rquote_, // rquote
921    &nsGkAtoms::rspace_, // rspace
922    &nsGkAtoms::schemaLocation_, // schemaLocation
923    &nsGkAtoms::scriptlevel_, // scriptlevel
924    &nsGkAtoms::scriptminsize_, // scriptminsize
925    &nsGkAtoms::scriptsize_, // scriptsize
926    &nsGkAtoms::scriptsizemultiplier_, // scriptsizemultiplier
927    &nsGkAtoms::selection_, // selection
928    &nsGkAtoms::separator_, // separator
929    &nsGkAtoms::separators_, // separators
930    &nsGkAtoms::shift_, // shift
931    &nsGkAtoms::side_, // side
932    &nsGkAtoms::src, // src
933    &nsGkAtoms::stackalign_, // stackalign
934    &nsGkAtoms::stretchy_, // stretchy
935    &nsGkAtoms::subscriptshift_, // subscriptshift
936    &nsGkAtoms::superscriptshift_, // superscriptshift
937    &nsGkAtoms::symmetric_, // symmetric
938    &nsGkAtoms::type, // type
939    &nsGkAtoms::voffset_, // voffset
940    &nsGkAtoms::width, // width
941    &nsGkAtoms::xref_, // xref
942    nullptr
943     // clang-format on
944 };
945 
946 nsStaticAtom** const kURLAttributesMathML[] = {
947     // clang-format off
948   &nsGkAtoms::href,
949   &nsGkAtoms::src,
950   &nsGkAtoms::cdgroup_,
951   &nsGkAtoms::altimg_,
952   &nsGkAtoms::definitionURL_,
953   nullptr
954     // clang-format on
955 };
956 
957 nsTHashtable<nsRefPtrHashKey<nsAtom>>* nsTreeSanitizer::sElementsHTML = nullptr;
958 nsTHashtable<nsRefPtrHashKey<nsAtom>>* nsTreeSanitizer::sAttributesHTML =
959     nullptr;
960 nsTHashtable<nsRefPtrHashKey<nsAtom>>* nsTreeSanitizer::sPresAttributesHTML =
961     nullptr;
962 nsTHashtable<nsRefPtrHashKey<nsAtom>>* nsTreeSanitizer::sElementsSVG = nullptr;
963 nsTHashtable<nsRefPtrHashKey<nsAtom>>* nsTreeSanitizer::sAttributesSVG =
964     nullptr;
965 nsTHashtable<nsRefPtrHashKey<nsAtom>>* nsTreeSanitizer::sElementsMathML =
966     nullptr;
967 nsTHashtable<nsRefPtrHashKey<nsAtom>>* nsTreeSanitizer::sAttributesMathML =
968     nullptr;
969 nsIPrincipal* nsTreeSanitizer::sNullPrincipal = nullptr;
970 
nsTreeSanitizer(uint32_t aFlags)971 nsTreeSanitizer::nsTreeSanitizer(uint32_t aFlags)
972     : mAllowStyles(aFlags & nsIParserUtils::SanitizerAllowStyle),
973       mAllowComments(aFlags & nsIParserUtils::SanitizerAllowComments),
974       mDropNonCSSPresentation(aFlags &
975                               nsIParserUtils::SanitizerDropNonCSSPresentation),
976       mDropForms(aFlags & nsIParserUtils::SanitizerDropForms),
977       mCidEmbedsOnly(aFlags & nsIParserUtils::SanitizerCidEmbedsOnly),
978       mDropMedia(aFlags & nsIParserUtils::SanitizerDropMedia),
979       mFullDocument(false),
980       mLogRemovals(aFlags & nsIParserUtils::SanitizerLogRemovals) {
981   if (mCidEmbedsOnly) {
982     // Sanitizing styles for external references is not supported.
983     mAllowStyles = false;
984   }
985   if (!sElementsHTML) {
986     // Initialize lazily to avoid having to initialize at all if the user
987     // doesn't paste HTML or load feeds.
988     InitializeStatics();
989   }
990 }
991 
MustFlatten(int32_t aNamespace,nsAtom * aLocal)992 bool nsTreeSanitizer::MustFlatten(int32_t aNamespace, nsAtom* aLocal) {
993   if (aNamespace == kNameSpaceID_XHTML) {
994     if (mDropNonCSSPresentation &&
995         (nsGkAtoms::font == aLocal || nsGkAtoms::center == aLocal)) {
996       return true;
997     }
998     if (mDropForms &&
999         (nsGkAtoms::form == aLocal || nsGkAtoms::input == aLocal ||
1000          nsGkAtoms::keygen == aLocal || nsGkAtoms::option == aLocal ||
1001          nsGkAtoms::optgroup == aLocal)) {
1002       return true;
1003     }
1004     if (mFullDocument &&
1005         (nsGkAtoms::title == aLocal || nsGkAtoms::html == aLocal ||
1006          nsGkAtoms::head == aLocal || nsGkAtoms::body == aLocal)) {
1007       return false;
1008     }
1009     return !sElementsHTML->GetEntry(aLocal);
1010   }
1011   if (aNamespace == kNameSpaceID_SVG) {
1012     if (mCidEmbedsOnly || mDropMedia) {
1013       // Sanitizing CSS-based URL references inside SVG presentational
1014       // attributes is not supported, so flattening for cid: embed case.
1015       return true;
1016     }
1017     return !sElementsSVG->GetEntry(aLocal);
1018   }
1019   if (aNamespace == kNameSpaceID_MathML) {
1020     return !sElementsMathML->GetEntry(aLocal);
1021   }
1022   return true;
1023 }
1024 
IsURL(nsStaticAtom ** const * aURLs,nsAtom * aLocalName)1025 bool nsTreeSanitizer::IsURL(nsStaticAtom** const* aURLs, nsAtom* aLocalName) {
1026   nsStaticAtom** atomPtrPtr;
1027   while ((atomPtrPtr = *aURLs)) {
1028     if (*atomPtrPtr == aLocalName) {
1029       return true;
1030     }
1031     ++aURLs;
1032   }
1033   return false;
1034 }
1035 
MustPrune(int32_t aNamespace,nsAtom * aLocal,mozilla::dom::Element * aElement)1036 bool nsTreeSanitizer::MustPrune(int32_t aNamespace, nsAtom* aLocal,
1037                                 mozilla::dom::Element* aElement) {
1038   // To avoid attacks where a MathML script becomes something that gets
1039   // serialized in a way that it parses back as an HTML script, let's just
1040   // drop elements with the local name 'script' regardless of namespace.
1041   if (nsGkAtoms::script == aLocal) {
1042     return true;
1043   }
1044   if (aNamespace == kNameSpaceID_XHTML) {
1045     if (nsGkAtoms::title == aLocal && !mFullDocument) {
1046       // emulate the quirks of the old parser
1047       return true;
1048     }
1049     if (mDropForms &&
1050         (nsGkAtoms::select == aLocal || nsGkAtoms::button == aLocal ||
1051          nsGkAtoms::datalist == aLocal)) {
1052       return true;
1053     }
1054     if (mDropMedia &&
1055         (nsGkAtoms::img == aLocal || nsGkAtoms::video == aLocal ||
1056          nsGkAtoms::audio == aLocal || nsGkAtoms::source == aLocal)) {
1057       return true;
1058     }
1059     if (nsGkAtoms::meta == aLocal &&
1060         (aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::charset) ||
1061          aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv))) {
1062       // Throw away charset declarations even if they also have microdata
1063       // which they can't validly have.
1064       return true;
1065     }
1066     if (((!mFullDocument && nsGkAtoms::meta == aLocal) ||
1067          nsGkAtoms::link == aLocal) &&
1068         !(aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::itemprop) ||
1069           aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::itemscope))) {
1070       // emulate old behavior for non-Microdata <meta> and <link> presumably
1071       // in <head>. <meta> and <link> are whitelisted in order to avoid
1072       // corrupting Microdata when they appear in <body>. Note that
1073       // SanitizeAttributes() will remove the rel attribute from <link> and
1074       // the name attribute from <meta>.
1075       return true;
1076     }
1077   }
1078   if (mAllowStyles) {
1079     if (nsGkAtoms::style == aLocal &&
1080         !(aNamespace == kNameSpaceID_XHTML || aNamespace == kNameSpaceID_SVG)) {
1081       return true;
1082     }
1083     return false;
1084   }
1085   if (nsGkAtoms::style == aLocal) {
1086     return true;
1087   }
1088   return false;
1089 }
1090 
SanitizeStyleDeclaration(DeclarationBlock * aDeclaration)1091 bool nsTreeSanitizer::SanitizeStyleDeclaration(DeclarationBlock* aDeclaration) {
1092   return aDeclaration->RemovePropertyByID(eCSSProperty__moz_binding);
1093 }
1094 
SanitizeStyleSheet(const nsAString & aOriginal,nsAString & aSanitized,nsIDocument * aDocument,nsIURI * aBaseURI)1095 bool nsTreeSanitizer::SanitizeStyleSheet(const nsAString& aOriginal,
1096                                          nsAString& aSanitized,
1097                                          nsIDocument* aDocument,
1098                                          nsIURI* aBaseURI) {
1099   nsresult rv = NS_OK;
1100   aSanitized.Truncate();
1101   // aSanitized will hold the permitted CSS text.
1102   // -moz-binding is blacklisted.
1103   bool didSanitize = false;
1104   // Create a sheet to hold the parsed CSS
1105   RefPtr<StyleSheet> sheet;
1106   if (aDocument->IsStyledByServo()) {
1107     sheet = new ServoStyleSheet(mozilla::css::eAuthorSheetFeatures, CORS_NONE,
1108                                 aDocument->GetReferrerPolicy(), SRIMetadata());
1109   } else {
1110 #ifdef MOZ_OLD_STYLE
1111     sheet = new CSSStyleSheet(mozilla::css::eAuthorSheetFeatures, CORS_NONE,
1112                               aDocument->GetReferrerPolicy());
1113 #else
1114     MOZ_CRASH("old style system disabled");
1115 #endif
1116   }
1117   sheet->SetURIs(aDocument->GetDocumentURI(), nullptr, aBaseURI);
1118   sheet->SetPrincipal(aDocument->NodePrincipal());
1119   if (aDocument->IsStyledByServo()) {
1120     sheet->AsServo()->ParseSheetSync(
1121         aDocument->CSSLoader(), NS_ConvertUTF16toUTF8(aOriginal),
1122         aDocument->GetDocumentURI(), aBaseURI, aDocument->NodePrincipal(),
1123         /* aLoadData = */ nullptr, 0, aDocument->GetCompatibilityMode());
1124   } else {
1125 #ifdef MOZ_OLD_STYLE
1126     // Create the CSS parser, and parse the CSS text.
1127     nsCSSParser parser(nullptr, sheet->AsGecko());
1128     rv = parser.ParseSheet(aOriginal, aDocument->GetDocumentURI(), aBaseURI,
1129                            aDocument->NodePrincipal(),
1130                            /* aLoadData = */ nullptr, 0);
1131 #else
1132     MOZ_CRASH("old style system disabled");
1133 #endif
1134   }
1135   NS_ENSURE_SUCCESS(rv, true);
1136   // Mark the sheet as complete.
1137   MOZ_ASSERT(!sheet->HasForcedUniqueInner(),
1138              "should not get a forced unique inner during parsing");
1139   sheet->SetComplete();
1140   // Loop through all the rules found in the CSS text
1141   ErrorResult err;
1142   RefPtr<dom::CSSRuleList> rules =
1143       sheet->GetCssRules(*nsContentUtils::GetSystemPrincipal(), err);
1144   err.SuppressException();
1145   if (!rules) {
1146     return true;
1147   }
1148   uint32_t ruleCount = rules->Length();
1149   for (uint32_t i = 0; i < ruleCount; ++i) {
1150     mozilla::css::Rule* rule = rules->Item(i);
1151     if (!rule) continue;
1152     switch (rule->GetType()) {
1153       default:
1154         didSanitize = true;
1155         // Ignore these rule types.
1156         break;
1157       case mozilla::css::Rule::NAMESPACE_RULE:
1158       case mozilla::css::Rule::FONT_FACE_RULE: {
1159         // Append @namespace and @font-face rules verbatim.
1160         nsAutoString cssText;
1161         rule->GetCssText(cssText);
1162         aSanitized.Append(cssText);
1163         break;
1164       }
1165       case mozilla::css::Rule::STYLE_RULE: {
1166         // For style rules, we will just look for and remove the
1167         // -moz-binding properties.
1168         auto styleRule = static_cast<BindingStyleRule*>(rule);
1169         DeclarationBlock* styleDecl = styleRule->GetDeclarationBlock();
1170         MOZ_ASSERT(styleDecl);
1171         if (SanitizeStyleDeclaration(styleDecl)) {
1172           didSanitize = true;
1173         }
1174         nsAutoString decl;
1175         styleRule->GetCssText(decl);
1176         aSanitized.Append(decl);
1177       }
1178     }
1179   }
1180   if (didSanitize && mLogRemovals) {
1181     LogMessage("Removed some rules and/or properties from stylesheet.",
1182                aDocument);
1183   }
1184   return didSanitize;
1185 }
1186 
SanitizeAttributes(mozilla::dom::Element * aElement,nsTHashtable<nsRefPtrHashKey<nsAtom>> * aAllowed,nsStaticAtom ** const * aURLs,bool aAllowXLink,bool aAllowStyle,bool aAllowDangerousSrc)1187 void nsTreeSanitizer::SanitizeAttributes(
1188     mozilla::dom::Element* aElement,
1189     nsTHashtable<nsRefPtrHashKey<nsAtom>>* aAllowed,
1190     nsStaticAtom** const* aURLs, bool aAllowXLink, bool aAllowStyle,
1191     bool aAllowDangerousSrc) {
1192   uint32_t ac = aElement->GetAttrCount();
1193 
1194   for (int32_t i = ac - 1; i >= 0; --i) {
1195     const nsAttrName* attrName = aElement->GetAttrNameAt(i);
1196     int32_t attrNs = attrName->NamespaceID();
1197     RefPtr<nsAtom> attrLocal = attrName->LocalName();
1198 
1199     if (kNameSpaceID_None == attrNs) {
1200       if (aAllowStyle && nsGkAtoms::style == attrLocal) {
1201         RefPtr<DeclarationBlock> decl;
1202         nsAutoString value;
1203         aElement->GetAttr(attrNs, attrLocal, value);
1204         nsIDocument* document = aElement->OwnerDoc();
1205         if (document->IsStyledByServo()) {
1206           RefPtr<URLExtraData> urlExtra(aElement->GetURLDataForStyleAttr());
1207           decl = ServoDeclarationBlock::FromCssText(
1208               value, urlExtra, document->GetCompatibilityMode(),
1209               document->CSSLoader());
1210         } else {
1211 #ifdef MOZ_OLD_STYLE
1212           // Pass the CSS Loader object to the parser, to allow parser error
1213           // reports to include the outer window ID.
1214           nsCSSParser parser(document->CSSLoader());
1215           decl = parser.ParseStyleAttribute(value, document->GetDocumentURI(),
1216                                             aElement->GetBaseURIForStyleAttr(),
1217                                             document->NodePrincipal());
1218 #else
1219           MOZ_CRASH("old style system disabled");
1220 #endif
1221         }
1222         if (decl) {
1223           if (SanitizeStyleDeclaration(decl)) {
1224             nsAutoString cleanValue;
1225             decl->ToString(cleanValue);
1226             aElement->SetAttr(kNameSpaceID_None, nsGkAtoms::style, cleanValue,
1227                               false);
1228             if (mLogRemovals) {
1229               LogMessage(
1230                   "Removed -moz-binding styling from element style attribute.",
1231                   aElement->OwnerDoc(), aElement);
1232             }
1233           }
1234         }
1235         continue;
1236       }
1237       if (aAllowDangerousSrc && nsGkAtoms::src == attrLocal) {
1238         continue;
1239       }
1240       if (IsURL(aURLs, attrLocal)) {
1241         if (SanitizeURL(aElement, attrNs, attrLocal)) {
1242           // in case the attribute removal shuffled the attribute order, start
1243           // the loop again.
1244           --ac;
1245           i = ac;  // i will be decremented immediately thanks to the for loop
1246           continue;
1247         }
1248         // else fall through to see if there's another reason to drop this
1249         // attribute (in particular if the attribute is background="" on an
1250         // HTML element)
1251       }
1252       if (!mDropNonCSSPresentation &&
1253           (aAllowed == sAttributesHTML) &&  // element is HTML
1254           sPresAttributesHTML->GetEntry(attrLocal)) {
1255         continue;
1256       }
1257       if (aAllowed->GetEntry(attrLocal) &&
1258           !((attrLocal == nsGkAtoms::rel &&
1259              aElement->IsHTMLElement(nsGkAtoms::link)) ||
1260             (!mFullDocument && attrLocal == nsGkAtoms::name &&
1261              aElement->IsHTMLElement(nsGkAtoms::meta)))) {
1262         // name="" and rel="" are whitelisted, but treat them as blacklisted
1263         // for <meta name> (fragment case) and <link rel> (all cases) to avoid
1264         // document-wide metadata or styling overrides with non-conforming
1265         // <meta name itemprop> or
1266         // <link rel itemprop>
1267         continue;
1268       }
1269       const char16_t* localStr = attrLocal->GetUTF16String();
1270       // Allow underscore to cater to the MCE editor library.
1271       // Allow data-* on SVG and MathML, too, as a forward-compat measure.
1272       if (*localStr == '_' ||
1273           (attrLocal->GetLength() > 5 && localStr[0] == 'd' &&
1274            localStr[1] == 'a' && localStr[2] == 't' && localStr[3] == 'a' &&
1275            localStr[4] == '-')) {
1276         continue;
1277       }
1278       // else not allowed
1279     } else if (kNameSpaceID_XML == attrNs) {
1280       if (nsGkAtoms::base == attrLocal) {
1281         if (SanitizeURL(aElement, attrNs, attrLocal)) {
1282           // in case the attribute removal shuffled the attribute order, start
1283           // the loop again.
1284           --ac;
1285           i = ac;  // i will be decremented immediately thanks to the for loop
1286         }
1287         continue;
1288       }
1289       if (nsGkAtoms::lang == attrLocal || nsGkAtoms::space == attrLocal) {
1290         continue;
1291       }
1292       // else not allowed
1293     } else if (aAllowXLink && kNameSpaceID_XLink == attrNs) {
1294       if (nsGkAtoms::href == attrLocal) {
1295         if (SanitizeURL(aElement, attrNs, attrLocal)) {
1296           // in case the attribute removal shuffled the attribute order, start
1297           // the loop again.
1298           --ac;
1299           i = ac;  // i will be decremented immediately thanks to the for loop
1300         }
1301         continue;
1302       }
1303       if (nsGkAtoms::type == attrLocal || nsGkAtoms::title == attrLocal ||
1304           nsGkAtoms::show == attrLocal || nsGkAtoms::actuate == attrLocal) {
1305         continue;
1306       }
1307       // else not allowed
1308     }
1309     aElement->UnsetAttr(kNameSpaceID_None, attrLocal, false);
1310     if (mLogRemovals) {
1311       LogMessage("Removed unsafe attribute.", aElement->OwnerDoc(), aElement,
1312                  attrLocal);
1313     }
1314     // in case the attribute removal shuffled the attribute order, start the
1315     // loop again.
1316     --ac;
1317     i = ac;  // i will be decremented immediately thanks to the for loop
1318   }
1319 
1320   // If we've got HTML audio or video, add the controls attribute, because
1321   // otherwise the content is unplayable with scripts removed.
1322   if (aElement->IsAnyOfHTMLElements(nsGkAtoms::video, nsGkAtoms::audio)) {
1323     aElement->SetAttr(kNameSpaceID_None, nsGkAtoms::controls, EmptyString(),
1324                       false);
1325   }
1326 }
1327 
SanitizeURL(mozilla::dom::Element * aElement,int32_t aNamespace,nsAtom * aLocalName)1328 bool nsTreeSanitizer::SanitizeURL(mozilla::dom::Element* aElement,
1329                                   int32_t aNamespace, nsAtom* aLocalName) {
1330   nsAutoString value;
1331   aElement->GetAttr(aNamespace, aLocalName, value);
1332 
1333   // Get value and remove mandatory quotes
1334   static const char* kWhitespace = "\n\r\t\b";
1335   const nsAString& v = nsContentUtils::TrimCharsInSet(kWhitespace, value);
1336   // Fragment-only url cannot be harmful.
1337   if (!v.IsEmpty() && v.First() == u'#') {
1338     return false;
1339   }
1340 
1341   nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
1342   uint32_t flags = nsIScriptSecurityManager::DISALLOW_INHERIT_PRINCIPAL;
1343 
1344   nsCOMPtr<nsIURI> baseURI = aElement->GetBaseURI();
1345   nsCOMPtr<nsIURI> attrURI;
1346   nsresult rv = NS_NewURI(getter_AddRefs(attrURI), v, nullptr, baseURI);
1347   if (NS_SUCCEEDED(rv)) {
1348     if (mCidEmbedsOnly && kNameSpaceID_None == aNamespace) {
1349       if (nsGkAtoms::src == aLocalName || nsGkAtoms::background == aLocalName) {
1350         // comm-central uses a hack that makes nsIURIs created with cid: specs
1351         // actually have an about:blank spec. Therefore, nsIURI facilities are
1352         // useless for cid: when comm-central code is participating.
1353         if (!(v.Length() > 4 && (v[0] == 'c' || v[0] == 'C') &&
1354               (v[1] == 'i' || v[1] == 'I') && (v[2] == 'd' || v[2] == 'D') &&
1355               v[3] == ':')) {
1356           rv = NS_ERROR_FAILURE;
1357         }
1358       } else if (nsGkAtoms::cdgroup_ == aLocalName ||
1359                  nsGkAtoms::altimg_ == aLocalName ||
1360                  nsGkAtoms::definitionURL_ == aLocalName) {
1361         // Gecko doesn't fetch these now and shouldn't in the future, but
1362         // in case someone goofs with these in the future, let's drop them.
1363         rv = NS_ERROR_FAILURE;
1364       } else {
1365         rv = secMan->CheckLoadURIWithPrincipal(sNullPrincipal, attrURI, flags);
1366       }
1367     } else {
1368       rv = secMan->CheckLoadURIWithPrincipal(sNullPrincipal, attrURI, flags);
1369     }
1370   }
1371   if (NS_FAILED(rv)) {
1372     aElement->UnsetAttr(aNamespace, aLocalName, false);
1373     if (mLogRemovals) {
1374       LogMessage("Removed unsafe URI from element attribute.",
1375                  aElement->OwnerDoc(), aElement, aLocalName);
1376     }
1377     return true;
1378   }
1379   return false;
1380 }
1381 
Sanitize(nsIContent * aFragment)1382 void nsTreeSanitizer::Sanitize(nsIContent* aFragment) {
1383   // If you want to relax these preconditions, be sure to check the code in
1384   // here that notifies / does not notify or that fires mutation events if
1385   // in tree.
1386   NS_PRECONDITION(aFragment->IsNodeOfType(nsINode::eDOCUMENT_FRAGMENT),
1387                   "Argument was not DOM fragment.");
1388   NS_PRECONDITION(!aFragment->IsInUncomposedDoc(), "The fragment is in doc?");
1389 
1390   mFullDocument = false;
1391   SanitizeChildren(aFragment);
1392 }
1393 
Sanitize(nsIDocument * aDocument)1394 void nsTreeSanitizer::Sanitize(nsIDocument* aDocument) {
1395 // If you want to relax these preconditions, be sure to check the code in
1396 // here that notifies / does not notify or that fires mutation events if
1397 // in tree.
1398 #ifdef DEBUG
1399   NS_PRECONDITION(!aDocument->GetContainer(), "The document is in a shell.");
1400   RefPtr<mozilla::dom::Element> root = aDocument->GetRootElement();
1401   NS_PRECONDITION(root->IsHTMLElement(nsGkAtoms::html), "Not HTML root.");
1402 #endif
1403 
1404   mFullDocument = true;
1405   SanitizeChildren(aDocument);
1406 }
1407 
SanitizeChildren(nsINode * aRoot)1408 void nsTreeSanitizer::SanitizeChildren(nsINode* aRoot) {
1409   nsIContent* node = aRoot->GetFirstChild();
1410   while (node) {
1411     if (node->IsElement()) {
1412       mozilla::dom::Element* elt = node->AsElement();
1413       mozilla::dom::NodeInfo* nodeInfo = node->NodeInfo();
1414       nsAtom* localName = nodeInfo->NameAtom();
1415       int32_t ns = nodeInfo->NamespaceID();
1416 
1417       if (MustPrune(ns, localName, elt)) {
1418         if (mLogRemovals) {
1419           LogMessage("Removing unsafe node.", elt->OwnerDoc(), elt);
1420         }
1421         RemoveAllAttributes(elt);
1422         nsIContent* descendant = node;
1423         while ((descendant = descendant->GetNextNode(node))) {
1424           if (descendant->IsElement()) {
1425             RemoveAllAttributes(descendant->AsElement());
1426           }
1427         }
1428         nsIContent* next = node->GetNextNonChildNode(aRoot);
1429         node->RemoveFromParent();
1430         node = next;
1431         continue;
1432       }
1433       if (nsGkAtoms::style == localName) {
1434         // If styles aren't allowed, style elements got pruned above. Even
1435         // if styles are allowed, non-HTML, non-SVG style elements got pruned
1436         // above.
1437         NS_ASSERTION(ns == kNameSpaceID_XHTML || ns == kNameSpaceID_SVG,
1438                      "Should have only HTML or SVG here!");
1439         nsAutoString styleText;
1440         nsContentUtils::GetNodeTextContent(node, false, styleText);
1441 
1442         nsAutoString sanitizedStyle;
1443         nsCOMPtr<nsIURI> baseURI = node->GetBaseURI();
1444         if (SanitizeStyleSheet(styleText, sanitizedStyle, aRoot->OwnerDoc(),
1445                                baseURI)) {
1446           nsContentUtils::SetNodeTextContent(node, sanitizedStyle, true);
1447         } else {
1448           // If the node had non-text child nodes, this operation zaps those.
1449           // XXXgijs: if we're logging, we should theoretically report about
1450           // this, but this way of removing those items doesn't allow for that
1451           // to happen. Seems less likely to be a problem for actual chrome
1452           // consumers though.
1453           nsContentUtils::SetNodeTextContent(node, styleText, true);
1454         }
1455         if (ns == kNameSpaceID_XHTML) {
1456           SanitizeAttributes(elt, sAttributesHTML, kURLAttributesHTML, false,
1457                              mAllowStyles, false);
1458         } else {
1459           SanitizeAttributes(elt, sAttributesSVG, kURLAttributesSVG, true,
1460                              mAllowStyles, false);
1461         }
1462         node = node->GetNextNonChildNode(aRoot);
1463         continue;
1464       }
1465       if (MustFlatten(ns, localName)) {
1466         if (mLogRemovals) {
1467           LogMessage("Flattening unsafe node (descendants are preserved).",
1468                      elt->OwnerDoc(), elt);
1469         }
1470         RemoveAllAttributes(elt);
1471         nsCOMPtr<nsIContent> next = node->GetNextNode(aRoot);
1472         nsCOMPtr<nsIContent> parent = node->GetParent();
1473         nsCOMPtr<nsIContent> child;  // Must keep the child alive during move
1474         ErrorResult rv;
1475         while ((child = node->GetFirstChild())) {
1476           nsCOMPtr<nsINode> refNode = node;
1477           parent->InsertBefore(*child, refNode, rv);
1478           if (rv.Failed()) {
1479             break;
1480           }
1481         }
1482         node->RemoveFromParent();
1483         node = next;
1484         continue;
1485       }
1486       NS_ASSERTION(ns == kNameSpaceID_XHTML || ns == kNameSpaceID_SVG ||
1487                        ns == kNameSpaceID_MathML,
1488                    "Should have only HTML, MathML or SVG here!");
1489       if (ns == kNameSpaceID_XHTML) {
1490         SanitizeAttributes(elt, sAttributesHTML, kURLAttributesHTML, false,
1491                            mAllowStyles,
1492                            (nsGkAtoms::img == localName) && !mCidEmbedsOnly);
1493       } else if (ns == kNameSpaceID_SVG) {
1494         SanitizeAttributes(elt, sAttributesSVG, kURLAttributesSVG, true,
1495                            mAllowStyles, false);
1496       } else {
1497         SanitizeAttributes(elt, sAttributesMathML, kURLAttributesMathML, true,
1498                            false, false);
1499       }
1500       node = node->GetNextNode(aRoot);
1501       continue;
1502     }
1503     NS_ASSERTION(!node->GetFirstChild(), "How come non-element node had kids?");
1504     nsIContent* next = node->GetNextNonChildNode(aRoot);
1505     if (!mAllowComments && node->IsNodeOfType(nsINode::eCOMMENT)) {
1506       node->RemoveFromParent();
1507     }
1508     node = next;
1509   }
1510 }
1511 
RemoveAllAttributes(Element * aElement)1512 void nsTreeSanitizer::RemoveAllAttributes(Element* aElement) {
1513   const nsAttrName* attrName;
1514   while ((attrName = aElement->GetAttrNameAt(0))) {
1515     int32_t attrNs = attrName->NamespaceID();
1516     RefPtr<nsAtom> attrLocal = attrName->LocalName();
1517     aElement->UnsetAttr(attrNs, attrLocal, false);
1518   }
1519 }
1520 
LogMessage(const char * aMessage,nsIDocument * aDoc,Element * aElement,nsAtom * aAttr)1521 void nsTreeSanitizer::LogMessage(const char* aMessage, nsIDocument* aDoc,
1522                                  Element* aElement, nsAtom* aAttr) {
1523   if (mLogRemovals) {
1524     nsAutoString msg;
1525     msg.Assign(NS_ConvertASCIItoUTF16(aMessage));
1526     if (aElement) {
1527       msg.Append(NS_LITERAL_STRING(" Element: ") + aElement->LocalName() +
1528                  NS_LITERAL_STRING("."));
1529     }
1530     if (aAttr) {
1531       msg.Append(NS_LITERAL_STRING(" Attribute: ") +
1532                  nsDependentAtomString(aAttr) + NS_LITERAL_STRING("."));
1533     }
1534 
1535     nsContentUtils::ReportToConsoleNonLocalized(
1536         msg, nsIScriptError::warningFlag, NS_LITERAL_CSTRING("DOM"), aDoc);
1537   }
1538 }
1539 
InitializeStatics()1540 void nsTreeSanitizer::InitializeStatics() {
1541   NS_PRECONDITION(!sElementsHTML, "Initializing a second time.");
1542 
1543   sElementsHTML =
1544       new nsTHashtable<nsRefPtrHashKey<nsAtom>>(ArrayLength(kElementsHTML));
1545   for (uint32_t i = 0; kElementsHTML[i]; i++) {
1546     sElementsHTML->PutEntry(*kElementsHTML[i]);
1547   }
1548 
1549   sAttributesHTML =
1550       new nsTHashtable<nsRefPtrHashKey<nsAtom>>(ArrayLength(kAttributesHTML));
1551   for (uint32_t i = 0; kAttributesHTML[i]; i++) {
1552     sAttributesHTML->PutEntry(*kAttributesHTML[i]);
1553   }
1554 
1555   sPresAttributesHTML = new nsTHashtable<nsRefPtrHashKey<nsAtom>>(
1556       ArrayLength(kPresAttributesHTML));
1557   for (uint32_t i = 0; kPresAttributesHTML[i]; i++) {
1558     sPresAttributesHTML->PutEntry(*kPresAttributesHTML[i]);
1559   }
1560 
1561   sElementsSVG =
1562       new nsTHashtable<nsRefPtrHashKey<nsAtom>>(ArrayLength(kElementsSVG));
1563   for (uint32_t i = 0; kElementsSVG[i]; i++) {
1564     sElementsSVG->PutEntry(*kElementsSVG[i]);
1565   }
1566 
1567   sAttributesSVG =
1568       new nsTHashtable<nsRefPtrHashKey<nsAtom>>(ArrayLength(kAttributesSVG));
1569   for (uint32_t i = 0; kAttributesSVG[i]; i++) {
1570     sAttributesSVG->PutEntry(*kAttributesSVG[i]);
1571   }
1572 
1573   sElementsMathML =
1574       new nsTHashtable<nsRefPtrHashKey<nsAtom>>(ArrayLength(kElementsMathML));
1575   for (uint32_t i = 0; kElementsMathML[i]; i++) {
1576     sElementsMathML->PutEntry(*kElementsMathML[i]);
1577   }
1578 
1579   sAttributesMathML =
1580       new nsTHashtable<nsRefPtrHashKey<nsAtom>>(ArrayLength(kAttributesMathML));
1581   for (uint32_t i = 0; kAttributesMathML[i]; i++) {
1582     sAttributesMathML->PutEntry(*kAttributesMathML[i]);
1583   }
1584 
1585   nsCOMPtr<nsIPrincipal> principal = NullPrincipal::Create();
1586   principal.forget(&sNullPrincipal);
1587 }
1588 
ReleaseStatics()1589 void nsTreeSanitizer::ReleaseStatics() {
1590   delete sElementsHTML;
1591   sElementsHTML = nullptr;
1592 
1593   delete sAttributesHTML;
1594   sAttributesHTML = nullptr;
1595 
1596   delete sPresAttributesHTML;
1597   sPresAttributesHTML = nullptr;
1598 
1599   delete sElementsSVG;
1600   sElementsSVG = nullptr;
1601 
1602   delete sAttributesSVG;
1603   sAttributesSVG = nullptr;
1604 
1605   delete sElementsMathML;
1606   sElementsMathML = nullptr;
1607 
1608   delete sAttributesMathML;
1609   sAttributesMathML = nullptr;
1610 
1611   NS_IF_RELEASE(sNullPrincipal);
1612 }
1613