Skip to content

Move three dependent customizations into new file#460

Merged
ia0 merged 7 commits intogoogle:developfrom
hcyang-google:customization
Apr 19, 2022
Merged

Move three dependent customizations into new file#460
ia0 merged 7 commits intogoogle:developfrom
hcyang-google:customization

Conversation

@hcyang-google
Copy link
Collaborator

  • default_min_pin_length(_rp_ids) and max_rp_ids_length

  • Did some backing store tricks to make the list configurable in
    TestCustomization.

I need some suggestions on implementing the TestCustomization's list field.

* default_min_pin_length(_rp_ids) and max_rp_ids_length

* Did some backing store tricks to make the list configurable in
  TestCustomization.
self.default_min_pin_length
}

fn default_min_pin_length_rp_ids(&self) -> &[&str] {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ia0 @kaczmarczyck is there better way of doing this? The current implementation is quite complicated and I feel it's unnecessary.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think we should change the Customization API:

// Current PR:
fn default_min_pin_length_rp_ids(&self) -> &[&str];
// Proposal:
fn default_min_pin_length_rp_ids(&self) -> Vec<String>;

The cost of creating the vector seems to already be present in ctap::storage::min_pin_length_rp_ids(). It's not as clear for ctap::storage::set_min_pin_length_rp_ids because if the RP id was already present in the function argument then we recreate it. But it's probably fine since the cost is comparable to the final result.

There are 2 alternatives:

// This isn't yet supported (but will in the future):
fn default_min_pin_length_rp_ids(&self) -> impl Iterator<Item = &str>;
// This would add rp_ids if they are not already there. It could either be called with an empty Vec to get the list, or with the argument to merge. This is essentially the union of both usages.
fn merge_default_min_pin_length_rp_ids(&self, rp_ids: &mut Vec<String>);

@coveralls
Copy link

coveralls commented Apr 14, 2022

Coverage Status

Coverage decreased (-1.4%) to 88.27% when pulling bbc51af on hcyang-google:customization into 74b472d on google:develop.

@hcyang-google
Copy link
Collaborator Author

Add a test to verify that the list configuration implementation isn't broken.


#[test]
#[allow(clippy::assertions_on_constants)]
fn test_invariants() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be 2 tests: One part is testing the current customization, and the other is testing your implementation.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

self.default_min_pin_length
}

fn default_min_pin_length_rp_ids(&self) -> Vec<String> {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ia0 Now we do this, so this customization (and ENTERPRISE_RP_ID_LIST) won't be treated as constants anymore. But I think it should be fine? There's very limited code path affected.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed they look less like constants. But I would be a bit surprised if some optimizations would not trigger. The optimization we rely on is when we iterate on this list in set_min_pin_length_rp_ids. The whole loop should be eliminated. We could try to check that it's still the case. One possible trick is to call an extern function in the loop and see if the linker complains:

    for &rp_id in DEFAULT_MIN_PIN_LENGTH_RP_IDS.iter() {
        // Add the 2 following lines to test if it still links
        extern "C" { fn should_not_be_called(); }
        unsafe { should_not_be_called() };
        let rp_id = String::from(rp_id);
        if !min_pin_length_rp_ids.contains(&rp_id) {
            min_pin_length_rp_ids.push(rp_id);
        }
    }

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The optimization won't trigger. I think it's because to eliminate the loop code the function has be able to be computed at compilation time. But we have some heap allocation like String::from in that function which make it impossible to do so?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the String::from should matter if the list is empty. But yeah, it's possible the constant propagation is not aggressive enough. In particular, if collect is not able to see that the iterator is empty, then we won't get the optimization.

///
/// - The minimum PIN length must be at least 4.
/// - The minimum PIN length must be at most 63.
/// - default_min_pin_length_rp_ids() must be non-empty if MAX_RP_IDS_LENGTH is 0.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: MAX_RP_IDS_LENGTH is now max_rp_ids_length but we could as well do a pass on documentation after the code change if it's easier (there's a few other cases like this one below, I'm not commenting on them to minimize comments to those regarding design).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done. @ia0 are there more that needs to be improved in this CL or can this be approved and merged?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to test a bit the optimizations to see if there was a way to make it work with Vec<String> too. But actually ever Vec<&'static str> doesn't seem to work. Probably the iter() is too much.

self.default_min_pin_length
}

fn default_min_pin_length_rp_ids(&self) -> Vec<String> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed they look less like constants. But I would be a bit surprised if some optimizations would not trigger. The optimization we rely on is when we iterate on this list in set_min_pin_length_rp_ids. The whole loop should be eliminated. We could try to check that it's still the case. One possible trick is to call an extern function in the loop and see if the linker complains:

    for &rp_id in DEFAULT_MIN_PIN_LENGTH_RP_IDS.iter() {
        // Add the 2 following lines to test if it still links
        extern "C" { fn should_not_be_called(); }
        unsafe { should_not_be_called() };
        let rp_id = String::from(rp_id);
        if !min_pin_length_rp_ids.contains(&rp_id) {
            min_pin_length_rp_ids.push(rp_id);
        }
    }

Copy link
Member

@ia0 ia0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is approved on my side, but since it's a big PR, I think we should also wait for @kaczmarczyck to take a look too.

@ia0 ia0 requested a review from kaczmarczyck April 19, 2022 15:00
Copy link
Collaborator

@kaczmarczyck kaczmarczyck left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had a comment 5 days ago, and left everything else to you :)
I think the most interesting decision was the change from static strings, and since you are aware, feel free to merge when you think the impact on performance and binary size is small enough.

@ia0 ia0 merged commit 1e123ab into google:develop Apr 19, 2022
@hcyang-google hcyang-google deleted the customization branch April 20, 2022 06:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants