@@ -322,7 +322,8 @@ impl Value {
322322 }
323323 }
324324 Self :: Enum { tag, value, .. } => {
325- if let CoreTypeConcrete :: Enum ( info) = Self :: resolve_type ( ty, registry) ? {
325+ let resolved_ty = Self :: resolve_type ( ty, registry) ?;
326+ if let CoreTypeConcrete :: Enum ( info) = resolved_ty {
326327 native_assert ! ( * tag < info. variants. len( ) , "Variant index out of range." ) ;
327328
328329 let payload_type_id = & info. variants [ * tag] ;
@@ -336,7 +337,7 @@ impl Value {
336337 let ptr = arena. alloc_layout ( layout) . cast :: < ( ) > ( ) . as_ptr ( ) ;
337338
338339 match tag_layout. size ( ) {
339- 0 => native_panic ! ( "An enum without variants cannot be instantiated." ) ,
340+ 0 => { }
340341 1 => * ptr. cast :: < u8 > ( ) = * tag as u8 ,
341342 2 => * ptr. cast :: < u16 > ( ) = * tag as u16 ,
342343 4 => * ptr. cast :: < u32 > ( ) = * tag as u32 ,
@@ -351,8 +352,12 @@ impl Value {
351352 variant_layouts[ * tag] . size ( ) ,
352353 ) ;
353354
354- // alloc returns a reference so its never null
355- NonNull :: new_unchecked ( arena. alloc ( ptr) as * mut _ ) . cast ( )
355+ if resolved_ty. is_memory_allocated ( registry) ? {
356+ // alloc returns a reference so its never null
357+ NonNull :: new_unchecked ( arena. alloc ( ptr) as * mut _ ) . cast ( )
358+ } else {
359+ NonNull :: new_unchecked ( ptr) . cast ( )
360+ }
356361 } else {
357362 Err ( Error :: UnexpectedValue ( format ! (
358363 "expected value of type {:?} but got an enum value" ,
@@ -1490,7 +1495,9 @@ mod test {
14901495 }
14911496
14921497 #[ test]
1493- fn test_to_ptr_enum_no_variant ( ) {
1498+ fn test_to_ptr_single_variant_enum_u8 ( ) {
1499+ // A single-variant enum carries no tag: its tag type is `i0`, so
1500+ // `tag_layout.size() == 0` and the payload is written at offset 0.
14941501 let program = ProgramParser :: new ( )
14951502 . parse (
14961503 "type u8 = u8;
@@ -1500,20 +1507,49 @@ mod test {
15001507
15011508 let registry = ProgramRegistry :: < CoreType , CoreLibfunc > :: new ( & program) . unwrap ( ) ;
15021509
1503- let result = Value :: Enum {
1510+ // Keep the arena alive for as long as we dereference `ptr`. `&Bump::new()`
1511+ // would be dropped at the end of the `let` statement, freeing the arena and
1512+ // turning the read below into a use-after-free.
1513+ let arena = Bump :: new ( ) ;
1514+ let ptr = Value :: Enum {
15041515 tag : 0 ,
15051516 value : Box :: new ( Value :: Uint8 ( 10 ) ) ,
15061517 debug_name : None ,
15071518 }
1508- . to_ptr ( & Bump :: new ( ) , & registry, & program. type_declarations [ 1 ] . id )
1509- . unwrap_err ( ) ;
1519+ . to_ptr ( & arena , & registry, & program. type_declarations [ 1 ] . id )
1520+ . unwrap ( ) ;
15101521
1511- let error = result . to_string ( ) . clone ( ) ;
1512- let error_msg = error . split ( " \n " ) . collect :: < Vec < & str > > ( ) [ 0 ] ;
1522+ assert_eq ! ( unsafe { * ptr . cast :: < u8 > ( ) . as_ptr ( ) } , 10 ) ;
1523+ }
15131524
1514- assert_eq ! (
1515- error_msg,
1516- "An enum without variants cannot be instantiated."
1525+ #[ test]
1526+ fn test_to_ptr_single_variant_enum_array ( ) {
1527+ // A single-variant enum such as `enum Wrapper { Only: Array<felt252> }`
1528+ // carries no tag: its tag type is `i0`, so `tag_layout.size() == 0`.
1529+ let program = ProgramParser :: new ( )
1530+ . parse (
1531+ "type felt252 = felt252;
1532+ type Array<felt252> = Array<felt252>;
1533+ type Wrapper = Enum<ut@Wrapper, Array<felt252>>;" ,
1534+ )
1535+ . unwrap ( ) ;
1536+
1537+ let registry = ProgramRegistry :: < CoreType , CoreLibfunc > :: new ( & program) . unwrap ( ) ;
1538+
1539+ let result = Value :: Enum {
1540+ tag : 0 ,
1541+ value : Box :: new ( Value :: Array ( vec ! [
1542+ Value :: Felt252 ( Felt :: from( 1 ) ) ,
1543+ Value :: Felt252 ( Felt :: from( 2 ) ) ,
1544+ Value :: Felt252 ( Felt :: from( 3 ) ) ,
1545+ ] ) ) ,
1546+ debug_name : None ,
1547+ }
1548+ . to_ptr ( & Bump :: new ( ) , & registry, & program. type_declarations [ 2 ] . id ) ;
1549+
1550+ assert ! (
1551+ result. is_ok( ) ,
1552+ "single-variant enum must serialize, got: {result:?}"
15171553 ) ;
15181554 }
15191555
0 commit comments