@@ -40,6 +40,9 @@ use tree_builder::tag_sets::*;
40
40
use util:: str:: to_escaped_string;
41
41
42
42
pub use self :: PushFlag :: * ;
43
+ use std:: ops:: { Deref , DerefMut } ;
44
+ use std:: cmp:: max;
45
+ use std:: slice:: Iter ;
43
46
44
47
#[ macro_use] mod tag_sets;
45
48
@@ -48,6 +51,69 @@ mod types;
48
51
49
52
include ! ( concat!( env!( "OUT_DIR" ) , "/rules.rs" ) ) ;
50
53
54
+ #[ derive( Clone ) ]
55
+ pub struct LimitedVec < T > {
56
+ vec : Vec < T > ,
57
+ limit : usize ,
58
+ }
59
+
60
+ impl < T > LimitedVec < T > {
61
+ pub fn new ( limit : usize ) -> Self {
62
+ LimitedVec {
63
+ vec : vec ! [ ] ,
64
+ limit : if limit == 0 { 10 } else { limit } ,
65
+ }
66
+ }
67
+
68
+ fn lower_bound ( & self ) -> usize {
69
+ let len = self . vec . len ( ) ;
70
+ // Watch out for overflow!
71
+ max ( len, self . limit ) - self . limit
72
+ }
73
+
74
+ pub fn push ( & mut self , other : T ) {
75
+ self . vec . push ( other)
76
+ }
77
+
78
+ pub fn remove ( & mut self , pos : usize ) {
79
+ let lower_bound = self . lower_bound ( ) ;
80
+ self . vec . remove ( pos + lower_bound) ;
81
+ }
82
+
83
+ pub fn truncate ( & mut self , pos : usize ) {
84
+ let lower_bound = self . lower_bound ( ) ;
85
+ self . vec . truncate ( pos + lower_bound) ;
86
+ }
87
+
88
+ pub fn pop ( & mut self ) -> Option < T > {
89
+ self . vec . pop ( )
90
+ }
91
+
92
+ pub fn insert ( & mut self , index : usize , element : T ) {
93
+ let lower_bound = self . lower_bound ( ) ;
94
+ self . vec . insert ( index + lower_bound, element)
95
+ }
96
+
97
+ fn real_iter ( & self ) -> Iter < T > {
98
+ self . vec . iter ( )
99
+ }
100
+ }
101
+
102
+ impl < T > Deref for LimitedVec < T > {
103
+ type Target = [ T ] ;
104
+ fn deref ( & self ) -> & [ T ] {
105
+ let bottom = self . lower_bound ( ) ;
106
+ & self . vec [ bottom..]
107
+ }
108
+ }
109
+
110
+ impl < T > DerefMut for LimitedVec < T > {
111
+ fn deref_mut ( & mut self ) -> & mut [ T ] {
112
+ let bottom = self . lower_bound ( ) ;
113
+ & mut self . vec [ bottom..]
114
+ }
115
+ }
116
+
51
117
/// Tree builder options, with an impl for Default.
52
118
#[ derive( Copy , Clone ) ]
53
119
pub struct TreeBuilderOpts {
@@ -67,6 +133,13 @@ pub struct TreeBuilderOpts {
67
133
/// Obsolete, ignored.
68
134
pub ignore_missing_rules : bool ,
69
135
136
+ /// The maximum amount that the parser will process through the list
137
+ /// of active formatting elements and the the stack of open elements.
138
+ /// This is set to a finite number to prevent denial-of-service security
139
+ /// vulnerabilities. 0 is treated as the default (currently 20); any other
140
+ /// value is used as-is.
141
+ pub max_stack_depth : u8 ,
142
+
70
143
/// Initial TreeBuilder quirks mode. Default: NoQuirks
71
144
pub quirks_mode : QuirksMode ,
72
145
}
@@ -79,6 +152,7 @@ impl Default for TreeBuilderOpts {
79
152
iframe_srcdoc : false ,
80
153
drop_doctype : false ,
81
154
ignore_missing_rules : false ,
155
+ max_stack_depth : 10 ,
82
156
quirks_mode : NoQuirks ,
83
157
}
84
158
}
@@ -112,10 +186,10 @@ pub struct TreeBuilder<Handle, Sink> {
112
186
doc_handle : Handle ,
113
187
114
188
/// Stack of open elements, most recently added at end.
115
- open_elems : Vec < Handle > ,
189
+ open_elems : LimitedVec < Handle > ,
116
190
117
191
/// List of active formatting elements.
118
- active_formatting : Vec < FormatEntry < Handle > > ,
192
+ active_formatting : LimitedVec < FormatEntry < Handle > > ,
119
193
120
194
//§ the-element-pointers
121
195
/// Head element pointer.
@@ -165,8 +239,8 @@ impl<Handle, Sink> TreeBuilder<Handle, Sink>
165
239
pending_table_text : vec ! ( ) ,
166
240
quirks_mode : opts. quirks_mode ,
167
241
doc_handle : doc_handle,
168
- open_elems : vec ! ( ) ,
169
- active_formatting : vec ! ( ) ,
242
+ open_elems : LimitedVec :: new ( opts . max_stack_depth as usize ) ,
243
+ active_formatting : LimitedVec :: new ( opts . max_stack_depth as usize ) ,
170
244
head_elem : None ,
171
245
form_elem : None ,
172
246
frameset_ok : true ,
@@ -197,8 +271,8 @@ impl<Handle, Sink> TreeBuilder<Handle, Sink>
197
271
pending_table_text : vec ! ( ) ,
198
272
quirks_mode : opts. quirks_mode ,
199
273
doc_handle : doc_handle,
200
- open_elems : vec ! ( ) ,
201
- active_formatting : vec ! ( ) ,
274
+ open_elems : LimitedVec :: new ( opts . max_stack_depth as usize ) ,
275
+ active_formatting : LimitedVec :: new ( opts . max_stack_depth as usize ) ,
202
276
head_elem : None ,
203
277
form_elem : form_elem,
204
278
frameset_ok : true ,
@@ -251,10 +325,10 @@ impl<Handle, Sink> TreeBuilder<Handle, Sink>
251
325
/// internal state. This is intended to support garbage-collected DOMs.
252
326
pub fn trace_handles ( & self , tracer : & Tracer < Handle =Handle > ) {
253
327
tracer. trace_handle ( & self . doc_handle ) ;
254
- for e in & self . open_elems {
328
+ for e in self . open_elems . real_iter ( ) {
255
329
tracer. trace_handle ( e) ;
256
330
}
257
- for e in & self . active_formatting {
331
+ for e in self . active_formatting . real_iter ( ) {
258
332
match e {
259
333
& Element ( ref h, _) => tracer. trace_handle ( h) ,
260
334
_ => ( ) ,
@@ -477,7 +551,7 @@ impl<Handle, Sink> TokenSink
477
551
}
478
552
479
553
fn end ( & mut self ) {
480
- for elem in self . open_elems . drain ( .. ) . rev ( ) {
554
+ for elem in self . open_elems . into_iter ( ) . rev ( ) {
481
555
self . sink . pop ( & elem) ;
482
556
}
483
557
}
@@ -688,6 +762,11 @@ impl<Handle, Sink> TreeBuilder<Handle, Sink>
688
762
}
689
763
) ;
690
764
765
+ if fmt_elem_stack_index == 0 {
766
+ self . sink . parse_error ( Borrowed ( "Tree too complex to parse correctly – returned tree will be inaccurate" ) ) ;
767
+ return
768
+ }
769
+
691
770
// 11.
692
771
let common_ancestor = self . open_elems [ fmt_elem_stack_index - 1 ] . clone ( ) ;
693
772
0 commit comments