@@ -33,6 +33,9 @@ use std::default::Default;
3333use std:: mem:: replace;
3434use std:: borrow:: Cow :: Borrowed ;
3535use std:: collections:: VecDeque ;
36+ use std:: ops:: { Deref , DerefMut } ;
37+ use std:: cmp:: max;
38+ use std:: slice:: Iter ;
3639
3740#[ macro_use] mod tag_sets;
3841
@@ -46,6 +49,69 @@ mod rules {
4649 include ! ( concat!( env!( "OUT_DIR" ) , "/rules.rs" ) ) ;
4750}
4851
52+ #[ derive( Clone ) ]
53+ pub struct LimitedVec < T > {
54+ vec : Vec < T > ,
55+ limit : usize ,
56+ }
57+
58+ impl < T > LimitedVec < T > {
59+ pub fn new ( limit : usize ) -> Self {
60+ LimitedVec {
61+ vec : vec ! [ ] ,
62+ limit : if limit == 0 { 10 } else { limit } ,
63+ }
64+ }
65+
66+ fn lower_bound ( & self ) -> usize {
67+ let len = self . vec . len ( ) ;
68+ // Watch out for overflow!
69+ max ( len, self . limit ) - self . limit
70+ }
71+
72+ pub fn push ( & mut self , other : T ) {
73+ self . vec . push ( other)
74+ }
75+
76+ pub fn remove ( & mut self , pos : usize ) {
77+ let lower_bound = self . lower_bound ( ) ;
78+ self . vec . remove ( pos + lower_bound) ;
79+ }
80+
81+ pub fn truncate ( & mut self , pos : usize ) {
82+ let lower_bound = self . lower_bound ( ) ;
83+ self . vec . truncate ( pos + lower_bound) ;
84+ }
85+
86+ pub fn pop ( & mut self ) -> Option < T > {
87+ self . vec . pop ( )
88+ }
89+
90+ pub fn insert ( & mut self , index : usize , element : T ) {
91+ let lower_bound = self . lower_bound ( ) ;
92+ self . vec . insert ( index + lower_bound, element)
93+ }
94+
95+ fn real_iter ( & self ) -> Iter < T > {
96+ self . vec . iter ( )
97+ }
98+ }
99+
100+ impl < T > Deref for LimitedVec < T > {
101+ type Target = [ T ] ;
102+ fn deref ( & self ) -> & [ T ] {
103+ let bottom = self . lower_bound ( ) ;
104+ & self . vec [ bottom..]
105+ }
106+ }
107+
108+ impl < T > DerefMut for LimitedVec < T > {
109+ fn deref_mut ( & mut self ) -> & mut [ T ] {
110+ let bottom = self . lower_bound ( ) ;
111+ & mut self . vec [ bottom..]
112+ }
113+ }
114+
49115/// Tree builder options, with an impl for Default.
50116#[ derive( Copy , Clone ) ]
51117pub struct TreeBuilderOpts {
@@ -65,6 +131,13 @@ pub struct TreeBuilderOpts {
65131 /// Obsolete, ignored.
66132 pub ignore_missing_rules : bool ,
67133
134+ /// The maximum amount that the parser will process through the list
135+ /// of active formatting elements and the the stack of open elements.
136+ /// This is set to a finite number to prevent denial-of-service security
137+ /// vulnerabilities. 0 is treated as the default (currently 10); any other
138+ /// value is used as-is.
139+ pub max_stack_depth : u8 ,
140+
68141 /// Initial TreeBuilder quirks mode. Default: NoQuirks
69142 pub quirks_mode : QuirksMode ,
70143}
@@ -77,6 +150,7 @@ impl Default for TreeBuilderOpts {
77150 iframe_srcdoc : false ,
78151 drop_doctype : false ,
79152 ignore_missing_rules : false ,
153+ max_stack_depth : 10 ,
80154 quirks_mode : NoQuirks ,
81155 }
82156 }
@@ -110,10 +184,10 @@ pub struct TreeBuilder<Handle, Sink> {
110184 doc_handle : Handle ,
111185
112186 /// Stack of open elements, most recently added at end.
113- open_elems : Vec < Handle > ,
187+ open_elems : LimitedVec < Handle > ,
114188
115189 /// List of active formatting elements.
116- active_formatting : Vec < FormatEntry < Handle > > ,
190+ active_formatting : LimitedVec < FormatEntry < Handle > > ,
117191
118192 //§ the-element-pointers
119193 /// Head element pointer.
@@ -163,8 +237,8 @@ impl<Handle, Sink> TreeBuilder<Handle, Sink>
163237 pending_table_text : vec ! ( ) ,
164238 quirks_mode : opts. quirks_mode ,
165239 doc_handle : doc_handle,
166- open_elems : vec ! ( ) ,
167- active_formatting : vec ! ( ) ,
240+ open_elems : LimitedVec :: new ( opts . max_stack_depth as usize ) ,
241+ active_formatting : LimitedVec :: new ( opts . max_stack_depth as usize ) ,
168242 head_elem : None ,
169243 form_elem : None ,
170244 frameset_ok : true ,
@@ -195,8 +269,8 @@ impl<Handle, Sink> TreeBuilder<Handle, Sink>
195269 pending_table_text : vec ! ( ) ,
196270 quirks_mode : opts. quirks_mode ,
197271 doc_handle : doc_handle,
198- open_elems : vec ! ( ) ,
199- active_formatting : vec ! ( ) ,
272+ open_elems : LimitedVec :: new ( opts . max_stack_depth as usize ) ,
273+ active_formatting : LimitedVec :: new ( opts . max_stack_depth as usize ) ,
200274 head_elem : None ,
201275 form_elem : form_elem,
202276 frameset_ok : true ,
@@ -249,10 +323,10 @@ impl<Handle, Sink> TreeBuilder<Handle, Sink>
249323 /// internal state. This is intended to support garbage-collected DOMs.
250324 pub fn trace_handles ( & self , tracer : & Tracer < Handle =Handle > ) {
251325 tracer. trace_handle ( & self . doc_handle ) ;
252- for e in & self . open_elems {
326+ for e in self . open_elems . real_iter ( ) {
253327 tracer. trace_handle ( e) ;
254328 }
255- for e in & self . active_formatting {
329+ for e in self . active_formatting . real_iter ( ) {
256330 match e {
257331 & Element ( ref h, _) => tracer. trace_handle ( h) ,
258332 _ => ( ) ,
@@ -475,7 +549,7 @@ impl<Handle, Sink> TokenSink
475549 }
476550
477551 fn end ( & mut self ) {
478- for elem in self . open_elems . drain ( .. ) . rev ( ) {
552+ for elem in self . open_elems . into_iter ( ) . rev ( ) {
479553 self . sink . pop ( & elem) ;
480554 }
481555 }
0 commit comments