@@ -580,25 +580,27 @@ impl Session {
580580 // Step 1: Build pass1 template
581581 // - Pre-allocate buffers for attributes with known fixed size
582582 // - Use NULL pointers for all other attributes to query their size
583- let mut buffers1 : Vec < Vec < u8 > > = Vec :: with_capacity ( attributes. len ( ) ) ;
583+ let mut buffers : Vec < Vec < u8 > > = Vec :: with_capacity ( attributes. len ( ) ) ;
584584 let mut template1: Vec < CK_ATTRIBUTE > = Vec :: with_capacity ( attributes. len ( ) ) ;
585585
586586 for attr_type in attributes. iter ( ) {
587587 if let Some ( size) = attr_type. fixed_size ( ) {
588+ // We know the needed size, we allocate
588589 let mut buffer = vec ! [ 0u8 ; size] ;
589590 template1. push ( CK_ATTRIBUTE {
590591 type_ : ( * attr_type) . into ( ) ,
591592 pValue : buffer. as_mut_ptr ( ) as * mut c_void ,
592593 ulValueLen : size as CK_ULONG ,
593594 } ) ;
594- buffers1 . push ( buffer) ;
595+ buffers . push ( buffer) ;
595596 } else {
597+ // This is a variable size, we set length to 0 and set the buffer ptr to NULL
596598 template1. push ( CK_ATTRIBUTE {
597599 type_ : ( * attr_type) . into ( ) ,
598600 pValue : std:: ptr:: null_mut ( ) ,
599601 ulValueLen : 0 ,
600602 } ) ;
601- buffers1 . push ( Vec :: new ( ) ) ;
603+ buffers . push ( Vec :: new ( ) ) ;
602604 }
603605 }
604606
@@ -636,57 +638,63 @@ impl Session {
636638 // NULL pointer but has a length - needs fetching in pass2
637639 pass2_indices. push ( i) ;
638640 } else if !attr. pValue . is_null ( ) {
639- // Has data already - satisfied in pass1
640- pass1_indices. push ( i) ;
641+ // If buffer was pre-allocated but too small, need to fetch in pass2
642+ if attr. ulValueLen > buffers[ i] . len ( ) as CK_ULONG {
643+ pass2_indices. push ( i) ;
644+ } else {
645+ // Has data already - satisfied in pass1
646+ pass1_indices. push ( i) ;
647+ }
641648 }
642649 }
643650
644651 // Step 4: Make pass2 call if needed for attributes that need fetching
645- let mut pass2_template_and_indices: Option < ( Vec < CK_ATTRIBUTE > , Vec < usize > ) > = None ;
646-
647- if !pass2_indices. is_empty ( ) {
648- let mut template2: Vec < CK_ATTRIBUTE > = Vec :: with_capacity ( pass2_indices. len ( ) ) ;
649-
650- for & idx in pass2_indices. iter ( ) {
651- let size = template1[ idx] . ulValueLen as usize ;
652- buffers1[ idx] . resize ( size, 0 ) ;
652+ let pass2_template_and_indices: Option < ( Vec < CK_ATTRIBUTE > , Vec < usize > ) > =
653+ if pass2_indices. is_empty ( ) {
654+ None
655+ } else {
656+ let mut template2: Vec < CK_ATTRIBUTE > = Vec :: with_capacity ( pass2_indices. len ( ) ) ;
653657
654- template2. push ( CK_ATTRIBUTE {
655- type_ : template1[ idx] . type_ ,
656- pValue : buffers1[ idx] . as_mut_ptr ( ) as * mut c_void ,
657- ulValueLen : buffers1[ idx] . len ( ) as CK_ULONG ,
658- } ) ;
659- }
658+ for & idx in pass2_indices. iter ( ) {
659+ let size = template1[ idx] . ulValueLen as usize ;
660+ buffers[ idx] . resize ( size, 0 ) ;
660661
661- let rv2 = unsafe {
662- Rv :: from ( get_pkcs11 ! ( self . client( ) , C_GetAttributeValue ) (
663- self . handle ( ) ,
664- object. handle ( ) ,
665- template2. as_mut_ptr ( ) ,
666- template2. len ( ) . try_into ( ) ?,
667- ) )
668- } ;
669-
670- match rv2 {
671- Rv :: Ok
672- | Rv :: Error ( RvError :: AttributeSensitive )
673- | Rv :: Error ( RvError :: AttributeTypeInvalid ) => {
674- // acceptable
662+ template2. push ( CK_ATTRIBUTE {
663+ type_ : template1[ idx] . type_ ,
664+ pValue : buffers[ idx] . as_mut_ptr ( ) as * mut c_void ,
665+ ulValueLen : buffers[ idx] . len ( ) as CK_ULONG ,
666+ } ) ;
675667 }
676- _ => {
677- rv2. into_result ( Function :: GetAttributeValue ) ?;
668+
669+ let rv2 = unsafe {
670+ Rv :: from ( get_pkcs11 ! ( self . client( ) , C_GetAttributeValue ) (
671+ self . handle ( ) ,
672+ object. handle ( ) ,
673+ template2. as_mut_ptr ( ) ,
674+ template2. len ( ) . try_into ( ) ?,
675+ ) )
676+ } ;
677+
678+ match rv2 {
679+ Rv :: Ok
680+ | Rv :: Error ( RvError :: AttributeSensitive )
681+ | Rv :: Error ( RvError :: AttributeTypeInvalid ) => {
682+ // acceptable
683+ }
684+ _ => {
685+ rv2. into_result ( Function :: GetAttributeValue ) ?;
686+ }
678687 }
679- }
680688
681- // Add indices satisfied by pass2 into pass1_indices
682- for ( i, & idx) in pass2_indices. iter ( ) . enumerate ( ) {
683- if template2[ i] . ulValueLen != CK_UNAVAILABLE_INFORMATION {
684- pass1_indices. push ( idx) ;
689+ // Add indices satisfied by pass2 into pass1_indices
690+ for ( i, & idx) in pass2_indices. iter ( ) . enumerate ( ) {
691+ if template2[ i] . ulValueLen != CK_UNAVAILABLE_INFORMATION {
692+ pass1_indices. push ( idx) ;
693+ }
685694 }
686- }
687695
688- pass2_template_and_indices = Some ( ( template2, pass2_indices. clone ( ) ) ) ;
689- }
696+ Some ( ( template2, pass2_indices) )
697+ } ;
690698
691699 // Step 5: Build result Vec<Attribute> preserving request order
692700 // Sort pass1_indices to preserve the original order from attributes[]
@@ -697,26 +705,14 @@ impl Session {
697705 let attr = if let Some ( ( ref template2, ref indices2) ) = pass2_template_and_indices {
698706 if let Some ( pos) = indices2. iter ( ) . position ( |& i| i == idx) {
699707 // attribute came from pass2
700- if template2[ pos] . ulValueLen != CK_UNAVAILABLE_INFORMATION {
701- template2[ pos] . try_into ( ) ?
702- } else {
703- continue ;
704- }
708+ template2[ pos] . try_into ( ) ?
705709 } else {
706710 // attribute came from pass1
707- if template1[ idx] . ulValueLen != CK_UNAVAILABLE_INFORMATION {
708- template1[ idx] . try_into ( ) ?
709- } else {
710- continue ;
711- }
711+ template1[ idx] . try_into ( ) ?
712712 }
713713 } else {
714714 // Only pass1 happened
715- if template1[ idx] . ulValueLen != CK_UNAVAILABLE_INFORMATION {
716- template1[ idx] . try_into ( ) ?
717- } else {
718- continue ;
719- }
715+ template1[ idx] . try_into ( ) ?
720716 } ;
721717
722718 results. push ( attr) ;
0 commit comments