@@ -9,19 +9,31 @@ use crate::abi::{AbiError, AbiErrorKind, AbiResult};
99use std:: str:: FromStr ;
1010use tw_coin_entry:: error:: prelude:: * ;
1111
12+ const MAX_RECURSION_DEPTH : usize = 20 ;
13+
1214pub struct Reader ;
1315
1416impl Reader {
1517 /// Doesn't accept tuple types with specified parameters, e.g `(uint32, address)`.
1618 pub fn parse_type < T : TypeConstructor > ( s : & str ) -> AbiResult < T > {
19+ Self :: parse_type_step ( s, 0 )
20+ }
21+
22+ /// Doesn't accept tuple types with specified parameters, e.g `(uint32, address)`.
23+ pub fn parse_type_step < T : TypeConstructor > ( s : & str , current_depth : usize ) -> AbiResult < T > {
24+ if current_depth > MAX_RECURSION_DEPTH {
25+ return AbiError :: err ( AbiErrorKind :: Error_invalid_param_type )
26+ . with_context ( || format ! ( "Max recursion depth exceeded: {MAX_RECURSION_DEPTH}" ) ) ;
27+ }
28+
1729 // Array
1830 if let Some ( remaining) = s. strip_suffix ( ']' ) {
1931 let Some ( ( element_type_str, len_str) ) = remaining. rsplit_once ( '[' ) else {
2032 return AbiError :: err ( AbiErrorKind :: Error_invalid_param_type )
2133 . with_context ( || format ! ( "Invalid array type: {s}" ) ) ;
2234 } ;
2335
24- let element_type = Reader :: parse_type :: < T > ( element_type_str)
36+ let element_type = Reader :: parse_type_step :: < T > ( element_type_str, current_depth + 1 )
2537 . with_context ( || format ! ( "Error parsing inner array type: {element_type_str}" ) ) ?;
2638 if let Some ( len) = parse_len ( len_str)
2739 . with_context ( || format ! ( "Error parsing fixed_array length: {len_str}" ) ) ?
@@ -113,3 +125,25 @@ fn parse_usize(usize_str: &str) -> AbiResult<Option<usize>> {
113125 . tw_err ( AbiErrorKind :: Error_invalid_param_type )
114126 . with_context ( || format ! ( "Expected a decimal string: {usize_str}" ) )
115127}
128+
129+ #[ cfg( test) ]
130+ mod tests {
131+ use super :: * ;
132+ use crate :: abi:: param_type:: ParamType ;
133+
134+ #[ test]
135+ fn test_parse_type_recursion ( ) {
136+ let depth = MAX_RECURSION_DEPTH ;
137+ let mut ty = "uint256" . to_string ( ) ;
138+
139+ // Append exactly MAX_RECURSION_DEPTH array brackets that must be allowed.
140+ for _ in 0 ..depth {
141+ ty. push_str ( "[]" ) ;
142+ }
143+ ParamType :: try_from_type_short ( & ty) . expect ( "Should parse within recursion limit" ) ;
144+
145+ // Append one more array bracket to exceed the limit.
146+ ty. push_str ( "[]" ) ;
147+ ParamType :: try_from_type_short ( & ty) . expect_err ( "Recursion limit exceeded" ) ;
148+ }
149+ }
0 commit comments