@@ -26,12 +26,22 @@ use prost_types::Value;
26
26
/// we'll conservitively cap this to ~80% of that.
27
27
const MAX_DEPTH : usize = 80 ;
28
28
29
- pub struct ProtoVisitor {
30
- /// Budget left to spend on visiting.
29
+ pub struct ProtoVisitorBuilder {
30
+ /// Budget to spend on visiting.
31
31
bound : usize ,
32
+
33
+ /// Current level of nesting depth while visiting.
32
34
depth : usize ,
33
35
}
34
36
37
+ struct ProtoVisitor < ' a > {
38
+ /// Budget left to spend on visiting.
39
+ bound : & ' a mut usize ,
40
+
41
+ /// Current level of nesting depth while visiting.
42
+ depth : & ' a mut usize ,
43
+ }
44
+
35
45
#[ derive( thiserror:: Error , Debug ) ]
36
46
pub enum Error {
37
47
#[ error( transparent) ]
@@ -47,11 +57,15 @@ pub enum Error {
47
57
UnexpectedType ,
48
58
}
49
59
50
- impl ProtoVisitor {
60
+ impl ProtoVisitorBuilder {
51
61
pub fn new ( bound : usize ) -> Self {
52
62
Self { bound, depth : 0 }
53
63
}
54
64
65
+ fn new_visitor ( & mut self ) -> Result < ProtoVisitor < ' _ > , Error > {
66
+ ProtoVisitor :: new ( & mut self . bound , & mut self . depth )
67
+ }
68
+
55
69
/// Deserialize `bytes` as a `MoveValue` with layout `layout`. Can fail if the bytes do not
56
70
/// represent a value with this layout, or if the deserialized value exceeds the field/type size
57
71
/// budget.
@@ -60,7 +74,9 @@ impl ProtoVisitor {
60
74
bytes : & [ u8 ] ,
61
75
layout : & A :: MoveTypeLayout ,
62
76
) -> anyhow:: Result < Value > {
63
- A :: MoveValue :: visit_deserialize ( bytes, layout, & mut self )
77
+ let mut visitor = self . new_visitor ( ) ?;
78
+
79
+ A :: MoveValue :: visit_deserialize ( bytes, layout, & mut visitor)
64
80
}
65
81
66
82
/// Deserialize `bytes` as a `MoveStruct` with layout `layout`. Can fail if the bytes do not
@@ -71,38 +87,54 @@ impl ProtoVisitor {
71
87
bytes : & [ u8 ] ,
72
88
layout : & A :: MoveStructLayout ,
73
89
) -> anyhow:: Result < Struct > {
90
+ let mut visitor = self . new_visitor ( ) ?;
91
+
74
92
let Value {
75
93
kind : Some ( Kind :: StructValue ( struct_) ) ,
76
- } = A :: MoveStruct :: visit_deserialize ( bytes, layout, & mut self ) ?
94
+ } = A :: MoveStruct :: visit_deserialize ( bytes, layout, & mut visitor ) ?
77
95
else {
78
96
bail ! ( "Expected to deserialize a struct" ) ;
79
97
} ;
80
98
Ok ( struct_)
81
99
}
100
+ }
101
+
102
+ impl Drop for ProtoVisitor < ' _ > {
103
+ fn drop ( & mut self ) {
104
+ self . dec_depth ( ) ;
105
+ }
106
+ }
82
107
83
- fn inc_depth ( & mut self ) -> Result < ( ) , Error > {
84
- if self . depth > MAX_DEPTH {
108
+ impl < ' a > ProtoVisitor < ' a > {
109
+ fn new ( bound : & ' a mut usize , depth : & ' a mut usize ) -> Result < Self , Error > {
110
+ // Increment the depth since we're creating a new Visitor instance
111
+ Self :: inc_depth ( depth) ?;
112
+ Ok ( Self { bound, depth } )
113
+ }
114
+
115
+ fn inc_depth ( depth : & mut usize ) -> Result < ( ) , Error > {
116
+ if * depth > MAX_DEPTH {
85
117
Err ( Error :: TooNested )
86
118
} else {
87
- self . depth += 1 ;
119
+ * depth += 1 ;
88
120
Ok ( ( ) )
89
121
}
90
122
}
91
123
92
124
fn dec_depth ( & mut self ) {
93
- if self . depth == 0 {
125
+ if * self . depth == 0 {
94
126
panic ! ( "BUG: logic bug in Visitor implementation" ) ;
95
127
} else {
96
- self . depth -= 1 ;
128
+ * self . depth -= 1 ;
97
129
}
98
130
}
99
131
100
132
/// Deduct `size` from the overall budget. Errors if `size` exceeds the current budget.
101
133
fn debit ( & mut self , size : usize ) -> Result < ( ) , Error > {
102
- if self . bound < size {
134
+ if * self . bound < size {
103
135
Err ( Error :: OutOfBudget )
104
136
} else {
105
- self . bound -= size;
137
+ * self . bound -= size;
106
138
Ok ( ( ) )
107
139
}
108
140
}
@@ -121,59 +153,45 @@ impl ProtoVisitor {
121
153
}
122
154
}
123
155
124
- impl < ' b , ' l > Visitor < ' b , ' l > for ProtoVisitor {
156
+ impl < ' b , ' l > Visitor < ' b , ' l > for ProtoVisitor < ' _ > {
125
157
type Value = Value ;
126
158
type Error = Error ;
127
159
128
160
fn visit_u8 ( & mut self , _: & ValueDriver < ' _ , ' b , ' l > , value : u8 ) -> Result < Value , Error > {
129
- self . inc_depth ( ) ?;
130
161
self . debit_value ( ) ?;
131
- self . dec_depth ( ) ;
132
162
Ok ( Value :: from ( value) )
133
163
}
134
164
135
165
fn visit_u16 ( & mut self , _: & ValueDriver < ' _ , ' b , ' l > , value : u16 ) -> Result < Value , Error > {
136
- self . inc_depth ( ) ?;
137
166
self . debit_value ( ) ?;
138
- self . dec_depth ( ) ;
139
167
Ok ( Value :: from ( value) )
140
168
}
141
169
142
170
fn visit_u32 ( & mut self , _: & ValueDriver < ' _ , ' b , ' l > , value : u32 ) -> Result < Value , Error > {
143
- self . inc_depth ( ) ?;
144
171
self . debit_value ( ) ?;
145
- self . dec_depth ( ) ;
146
172
Ok ( Value :: from ( value) )
147
173
}
148
174
149
175
fn visit_u64 ( & mut self , _: & ValueDriver < ' _ , ' b , ' l > , value : u64 ) -> Result < Value , Error > {
150
- self . inc_depth ( ) ?;
151
176
let value = value. to_string ( ) ;
152
177
self . debit_string_value ( & value) ?;
153
- self . dec_depth ( ) ;
154
178
Ok ( Value :: from ( value) )
155
179
}
156
180
157
181
fn visit_u128 ( & mut self , _: & ValueDriver < ' _ , ' b , ' l > , value : u128 ) -> Result < Value , Error > {
158
- self . inc_depth ( ) ?;
159
182
let value = value. to_string ( ) ;
160
183
self . debit_string_value ( & value) ?;
161
- self . dec_depth ( ) ;
162
184
Ok ( Value :: from ( value) )
163
185
}
164
186
165
187
fn visit_u256 ( & mut self , _: & ValueDriver < ' _ , ' b , ' l > , value : U256 ) -> Result < Value , Error > {
166
- self . inc_depth ( ) ?;
167
188
let value = value. to_string ( ) ;
168
189
self . debit_string_value ( & value) ?;
169
- self . dec_depth ( ) ;
170
190
Ok ( Value :: from ( value) )
171
191
}
172
192
173
193
fn visit_bool ( & mut self , _: & ValueDriver < ' _ , ' b , ' l > , value : bool ) -> Result < Value , Error > {
174
- self . inc_depth ( ) ?;
175
194
self . debit_value ( ) ?;
176
- self . dec_depth ( ) ;
177
195
Ok ( Value :: from ( value) )
178
196
}
179
197
@@ -182,10 +200,8 @@ impl<'b, 'l> Visitor<'b, 'l> for ProtoVisitor {
182
200
_: & ValueDriver < ' _ , ' b , ' l > ,
183
201
value : AccountAddress ,
184
202
) -> Result < Value , Error > {
185
- self . inc_depth ( ) ?;
186
203
let value = value. to_canonical_string ( true ) ;
187
204
self . debit_string_value ( & value) ?;
188
- self . dec_depth ( ) ;
189
205
Ok ( Value :: from ( value) )
190
206
}
191
207
@@ -194,16 +210,12 @@ impl<'b, 'l> Visitor<'b, 'l> for ProtoVisitor {
194
210
_: & ValueDriver < ' _ , ' b , ' l > ,
195
211
value : AccountAddress ,
196
212
) -> Result < Value , Error > {
197
- self . inc_depth ( ) ?;
198
213
let value = value. to_canonical_string ( true ) ;
199
214
self . debit_string_value ( & value) ?;
200
- self . dec_depth ( ) ;
201
215
Ok ( Value :: from ( value) )
202
216
}
203
217
204
218
fn visit_vector ( & mut self , driver : & mut VecDriver < ' _ , ' b , ' l > ) -> Result < Value , Error > {
205
- self . inc_depth ( ) ?;
206
-
207
219
let value = if driver. element_layout ( ) . is_type ( & TypeTag :: U8 ) {
208
220
// Base64 encode arbitrary bytes
209
221
use base64:: { engine:: general_purpose:: STANDARD , Engine } ;
@@ -221,20 +233,20 @@ impl<'b, 'l> Visitor<'b, 'l> for ProtoVisitor {
221
233
} else {
222
234
let mut elems = vec ! [ ] ;
223
235
self . debit_value ( ) ?;
224
- while let Some ( elem) = driver. next_element ( self ) ? {
236
+
237
+ while let Some ( elem) =
238
+ driver. next_element ( & mut ProtoVisitor :: new ( self . bound , self . depth ) ?) ?
239
+ {
225
240
elems. push ( elem) ;
226
241
}
227
242
228
243
Value :: from ( elems)
229
244
} ;
230
245
231
- self . dec_depth ( ) ;
232
246
Ok ( value)
233
247
}
234
248
235
249
fn visit_struct ( & mut self , driver : & mut StructDriver < ' _ , ' b , ' l > ) -> Result < Value , Error > {
236
- self . inc_depth ( ) ?;
237
-
238
250
let ty = & driver. struct_layout ( ) . type_ ;
239
251
let layout = driver. struct_layout ( ) ;
240
252
@@ -298,19 +310,17 @@ impl<'b, 'l> Visitor<'b, 'l> for ProtoVisitor {
298
310
self . debit_str ( field. name . as_str ( ) ) ?;
299
311
}
300
312
301
- while let Some ( ( field, elem) ) = driver. next_field ( self ) ? {
313
+ while let Some ( ( field, elem) ) =
314
+ driver. next_field ( & mut ProtoVisitor :: new ( self . bound , self . depth ) ?) ?
315
+ {
302
316
map. fields . insert ( field. name . as_str ( ) . to_owned ( ) , elem) ;
303
317
}
304
318
Value :: from ( Kind :: StructValue ( map) )
305
319
} ;
306
-
307
- self . dec_depth ( ) ;
308
320
Ok ( value)
309
321
}
310
322
311
323
fn visit_variant ( & mut self , driver : & mut VariantDriver < ' _ , ' b , ' l > ) -> Result < Value , Error > {
312
- self . inc_depth ( ) ?;
313
-
314
324
let mut map = Struct :: default ( ) ;
315
325
self . debit_value ( ) ?;
316
326
@@ -324,11 +334,12 @@ impl<'b, 'l> Visitor<'b, 'l> for ProtoVisitor {
324
334
self . debit_str ( field. name . as_str ( ) ) ?;
325
335
}
326
336
327
- while let Some ( ( field, elem) ) = driver. next_field ( self ) ? {
337
+ while let Some ( ( field, elem) ) =
338
+ driver. next_field ( & mut ProtoVisitor :: new ( self . bound , self . depth ) ?) ?
339
+ {
328
340
map. fields . insert ( field. name . as_str ( ) . to_owned ( ) , elem) ;
329
341
}
330
342
331
- self . dec_depth ( ) ;
332
343
Ok ( Value :: from ( Kind :: StructValue ( map) ) )
333
344
}
334
345
}
@@ -551,13 +562,13 @@ pub(crate) mod tests {
551
562
552
563
let bytes = serialize ( value. clone ( ) ) ;
553
564
554
- let deser = ProtoVisitor :: new ( bound)
565
+ let deser = ProtoVisitorBuilder :: new ( bound)
555
566
. deserialize_value ( & bytes, & type_layout)
556
567
. unwrap ( ) ;
557
568
558
569
assert_eq ! ( expected, proto_value_to_json_value( deser) ) ;
559
570
560
- ProtoVisitor :: new ( bound - 1 )
571
+ ProtoVisitorBuilder :: new ( bound - 1 )
561
572
. deserialize_value ( & bytes, & type_layout)
562
573
. unwrap_err ( ) ;
563
574
}
@@ -580,7 +591,7 @@ pub(crate) mod tests {
580
591
let bound = required_budget ( & expected) ;
581
592
let bytes = serialize ( value. clone ( ) ) ;
582
593
583
- let deser = ProtoVisitor :: new ( bound)
594
+ let deser = ProtoVisitorBuilder :: new ( bound)
584
595
. deserialize_value ( & bytes, & layout)
585
596
. unwrap ( ) ;
586
597
@@ -592,7 +603,7 @@ pub(crate) mod tests {
592
603
593
604
let bytes = serialize ( value. clone ( ) ) ;
594
605
595
- let err = ProtoVisitor :: new ( bound)
606
+ let err = ProtoVisitorBuilder :: new ( bound)
596
607
. deserialize_value ( & bytes, & layout)
597
608
. unwrap_err ( ) ;
598
609
@@ -643,7 +654,7 @@ pub(crate) mod tests {
643
654
644
655
fn json < T : serde:: Serialize > ( layout : A :: MoveTypeLayout , data : T ) -> serde_json:: Value {
645
656
let bcs = bcs:: to_bytes ( & data) . unwrap ( ) ;
646
- let proto_value = ProtoVisitor :: new ( 1024 * 1024 )
657
+ let proto_value = ProtoVisitorBuilder :: new ( 1024 * 1024 )
647
658
. deserialize_value ( & bcs, & layout)
648
659
. unwrap ( ) ;
649
660
proto_value_to_json_value ( proto_value)
0 commit comments