@@ -133,20 +133,29 @@ fn get_extension_types(tlv_data: &[u8]) -> Result<Vec<ExtensionType>, ProgramErr
133
133
let mut start_index = 0 ;
134
134
while start_index < tlv_data. len ( ) {
135
135
let tlv_indices = get_tlv_indices ( start_index) ;
136
- if tlv_data. len ( ) < tlv_indices. value_start {
137
- return Ok ( extension_types) ;
136
+ if tlv_data. len ( ) < tlv_indices. length_start {
137
+ // not enough bytes to store the type, malformed
138
+ return Err ( ProgramError :: InvalidAccountData ) ;
138
139
}
139
140
let extension_type =
140
141
ExtensionType :: try_from ( & tlv_data[ tlv_indices. type_start ..tlv_indices. length_start ] ) ?;
141
142
if extension_type == ExtensionType :: Uninitialized {
142
143
return Ok ( extension_types) ;
143
144
} else {
145
+ if tlv_data. len ( ) < tlv_indices. value_start {
146
+ // not enough bytes to store the length, malformed
147
+ return Err ( ProgramError :: InvalidAccountData ) ;
148
+ }
144
149
extension_types. push ( extension_type) ;
145
150
let length = pod_from_bytes :: < Length > (
146
151
& tlv_data[ tlv_indices. length_start ..tlv_indices. value_start ] ,
147
152
) ?;
148
153
149
154
let value_end_index = tlv_indices. value_start . saturating_add ( usize:: from ( * length) ) ;
155
+ if value_end_index > tlv_data. len ( ) {
156
+ // value blows past the size of the slice, malformed
157
+ return Err ( ProgramError :: InvalidAccountData ) ;
158
+ }
150
159
start_index = value_end_index;
151
160
}
152
161
}
@@ -953,6 +962,27 @@ mod test {
953
962
) ;
954
963
}
955
964
965
+ #[ test]
966
+ fn get_extension_types_with_opaque_buffer ( ) {
967
+ // incorrect due to the length
968
+ assert_eq ! (
969
+ get_extension_types( & [ 1 , 0 , 1 , 1 ] ) . unwrap_err( ) ,
970
+ ProgramError :: InvalidAccountData ,
971
+ ) ;
972
+ // incorrect due to the huge enum number
973
+ assert_eq ! (
974
+ get_extension_types( & [ 0 , 1 , 0 , 0 ] ) . unwrap_err( ) ,
975
+ ProgramError :: InvalidAccountData ,
976
+ ) ;
977
+ // correct due to the good enum number and zero length
978
+ assert_eq ! (
979
+ get_extension_types( & [ 1 , 0 , 0 , 0 ] ) . unwrap( ) ,
980
+ vec![ ExtensionType :: try_from( 1 ) . unwrap( ) ]
981
+ ) ;
982
+ // correct since it's just uninitialized data at the end
983
+ assert_eq ! ( get_extension_types( & [ 0 , 0 ] ) . unwrap( ) , vec![ ] ) ;
984
+ }
985
+
956
986
#[ test]
957
987
fn mint_with_extension_pack_unpack ( ) {
958
988
let mint_size = ExtensionType :: get_account_len :: < Mint > ( & [
@@ -1586,12 +1616,21 @@ mod test {
1586
1616
let err = StateWithExtensionsMut :: < Mint > :: unpack_uninitialized ( & mut buffer) . unwrap_err ( ) ;
1587
1617
assert_eq ! ( err, ProgramError :: InvalidAccountData ) ;
1588
1618
1589
- let mut buffer = vec ! [ 0 ; BASE_ACCOUNT_LENGTH + 2 ] ;
1619
+ // ok since there are two bytes for the type, which is `Uninitialized`
1620
+ let mut buffer = vec ! [ 0 ; BASE_ACCOUNT_LENGTH + 3 ] ;
1590
1621
let mut state = StateWithExtensionsMut :: < Mint > :: unpack_uninitialized ( & mut buffer) . unwrap ( ) ;
1591
1622
let err = state. get_extension_mut :: < MintCloseAuthority > ( ) . unwrap_err ( ) ;
1592
1623
assert_eq ! ( err, ProgramError :: InvalidAccountData ) ;
1593
1624
1594
1625
assert_eq ! ( state. get_extension_types( ) . unwrap( ) , vec![ ] ) ;
1626
+
1627
+ // malformed since there aren't too bytes for the type
1628
+ let mut buffer = vec ! [ 0 ; BASE_ACCOUNT_LENGTH + 2 ] ;
1629
+ let state = StateWithExtensionsMut :: < Mint > :: unpack_uninitialized ( & mut buffer) . unwrap ( ) ;
1630
+ assert_eq ! (
1631
+ state. get_extension_types( ) . unwrap_err( ) ,
1632
+ ProgramError :: InvalidAccountData
1633
+ ) ;
1595
1634
}
1596
1635
1597
1636
#[ test]
0 commit comments