tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

nsTreeSanitizer.cpp (58896B)


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