Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: correctly apply configuration precedence in reverse parsing order #12

Merged
merged 3 commits into from
Dec 5, 2023

Conversation

LeoniePhiline
Copy link
Contributor

@LeoniePhiline LeoniePhiline commented Dec 5, 2023

#11 - Correctly apply configuration precedence in reverse parsing order

Fixes #11

Commits

Commits contain logically distinct changes are are best reviewed individually.

  1. Bugfix (a2a3be2)
  2. Error-test improvement (a0b086a)
  3. stylistic improvement (a598857).

Read #12 (comment) for more details.

Description

Previously, the order of precedence applied to
parsed configuration was incorrect.

Configuration was parsed, then sorted in
alphabetical order.

Algorithms (ciphers, key
exchange algorithms, MACs, etc.) were incorrectly
applied during parsing.

The correct precedence order follows
https://linux.die.net/man/5/ssh_config: the
configuration is read from top to bottom,
precedence is applied from bottom (lowest)
to the top (highest precedence).

Options preceding the first Host block are
considered implicit command line options, in
line with OpenSSH's own implementation.

This patch includes the following changes:

  • Remove the alphabetic ordering of host sections.

  • Merge matching host sections in reverse order.

  • More efficiently merge host sections with vastly reduced clones. (clone on demand.)

  • Resolve algorithms not during the parsing, but during the resolving stage.

  • More efficiently resolve algorithms, without source list mutation.

  • Adjust existing unit tests to test the corrected precedence algorithm.

Type of change

This is a bugfix, but some users may depend on the old, broken algorithm. For these users, this change could be considered breaking. On the other hand, this can be said about any bugfix: There might always be someone who abused the previous, incorrect behavior.

Please select relevant options.

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

Checklist

  • My code follows the contribution guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • My changes generate no new warnings
  • I formatted the code with cargo fmt
  • I checked my code using cargo clippy and reports no warnings
  • I have added tests that prove my fix is effective or that my feature works
  • The changes I've made are Windows, MacOS, Linux compatible (or I've handled them using cfg target_os)
  • I increased or maintained the code coverage for the project, compared to the previous commit

Acceptance tests

wait for a project maintainer to fulfill this section...

  • regression test: ...

This change fixes veeso#11:

Previously, the order of precedence applied to
parsed configuration was incorrect.

Configuration was parsed, then sorted in
alphabetical order.

Algorithms (ciphers, key
exchange algorithms, MACs, etc.) were incorrectly
applied during parsing.

The correct precedence order follows
https://linux.die.net/man/5/ssh_config: the
configuration is read from top to bottom,
precedence is applied from bottom (lowest)
to the top (highest precedence).

Options preceding the first `Host` block are
considered implicit command line options, in
line with OpenSSH's own implementation.

This patch includes the following changes:

- Remove the alphabetic ordering of host sections.

- Merge matching host sections in reverse order.

- More efficiently merge host sections with
  vastly reduced `clone`s. (`clone` on demand.)

- Resolve algorithms not during the parsing,
  but during the resolving stage.

- More efficiently resolve algorithms, without
  source list mutation.

- Adjust existing unit tests to test the corrected
  precedence algorithm.
@LeoniePhiline
Copy link
Contributor Author

LeoniePhiline commented Dec 5, 2023

@veeso I will push two additional commits with improvements made along the journey of fixing this bug.

These two additional commits are optional and can be reviewed and accepted or rejected separately from the bugfix commit.

In detail:

  • The first additional commit improves error-tests by replacing Result::is_err with a match against the error enum.
    Previously, only the existence of an error result was checked. With the first additional commit, the kind of error is checked as well.

  • The second additional commit improves success-tests by applying the Rust 2018 idiom of returning Result from tests. This way, Result::unwrap and Result::is_ok can be replaced by ?. Any error occurring in a success-test is propagated to the test runner.

    Some tests called .ok().unwrap() on Results, effectively first turning them into Options before unwrapping. This unidiomatic pattern is replaced by ? as well.

@coveralls
Copy link

coveralls commented Dec 5, 2023

Pull Request Test Coverage Report for Build 7101669807

  • 284 of 300 (94.67%) changed or added relevant lines in 2 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage decreased (-0.3%) to 97.467%

Changes Missing Coverage Covered Lines Changed/Added Lines %
src/parser/mod.rs 164 180 91.11%
Totals Coverage Status
Change from base Build 5712204231: -0.3%
Covered Lines: 1193
Relevant Lines: 1224

💛 - Coveralls

This change improves error-tests by replacing
`Result::is_err` with a match against the error
enum.

Previously, only the existence of an error result
was checked.

With the first additional commit,
the kind of error is checked as well.
This change improves success-tests by applying
the Rust 2018 idiom of returning `Result`
from tests.

This way, `Result::unwrap` and `Result::is_ok`
can be replaced by `?`.

Any error occurring in a success-test
is propagated to the test runner.

Some tests previously called `.ok().unwrap()` on
`Result`s, effectively first turning them into
`Option`s before unwrapping.

This unidiomatic pattern is replaced
by `?` as well.
@veeso
Copy link
Owner

veeso commented Dec 5, 2023

Amazing job, thank you

@veeso veeso merged commit 02ff1b9 into veeso:main Dec 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants