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

Abort reference resolution when a reference loop is detected #32

Merged
merged 3 commits into from
Sep 14, 2023

Conversation

simu
Copy link
Member

@simu simu commented Sep 12, 2023

This PR introduces logic to track the number of recursive calls to Token::resolve() for Token::Ref objects and uses that state to abort reference resolution with an error when the call depth exceeds 64.

Additionally, the PR introduces logic to track any already seen "reference paths" (i.e. fully qualified colon-delimited parameter keys). All reference paths which are found during resolution are checked against the set of seen paths and if a path is already in the set we know that we're trying to resolve a loop where one or more references contain references to each other. In this case, we abort the reference resolution with an error showing the reference paths which form a loop.

The PR introduces a custom struct ResolveState to keep track of the call depth and seen reference paths. This design allows us to change the information which is tracked during reference resolution without having to update all call sites.

The PR also carefully doesn't track state across boundaries where calls to Token::resolve() can't recurse into each other, e.g. for ValueList layers, Sequence elements, and Mapping key-value pairs. See the inline comments for detailed reasoning on why these recursive calls can't recurse into each other.

Additionally, the PR adds a number of new tests both for cases which shouldn't be detected as loops and cases which should be detected as loops.

Checklist

  • The PR has a meaningful title. The title will be used to auto generate the changelog
  • PR contains a single logical change (to build a better changelog).
  • Update the documentation.
  • Update tests.
  • Categorize the PR by setting a good title and adding one of the labels:
    bug, enhancement, documentation, change, breaking, dependency, internal
    as they show up in the changelog

@simu simu added the enhancement New feature or request label Sep 12, 2023
@simu simu force-pushed the feat/abort-on-ref-loop branch from 49f1b8f to e6ac8d9 Compare September 12, 2023 15:31
@simu simu force-pushed the feat/kapitan-patch branch from 6825201 to 39d59c3 Compare September 13, 2023 08:46
Base automatically changed from feat/kapitan-patch to main September 13, 2023 09:13
@simu simu force-pushed the feat/abort-on-ref-loop branch from e6ac8d9 to 0ab1953 Compare September 13, 2023 14:36
@simu simu marked this pull request as ready for review September 13, 2023 15:22
@simu simu requested a review from a team September 13, 2023 15:22
We track the number of recursive calls to `Token::resolve()` for
`Token::Ref` objects and abort resolution when the call depth exceeds
64.

We already introduce a custom struct `ResolveState` to keep track of the
call depth, so that we can easily add more state that we want to track
during reference resolution in the future.

We also already ensure we don't track call depth across boundaries where
calls to `Token::resolve()` can't recurse into each other, e.g. for
ValueList layers, Sequence elements, and Mapping key-value pairs. See
the inline comments for detailed reasoning on why these recursive calls
can't recurse into each other.
We add logic to track any reference paths which we've already seen while
resolving references in a `Value`. Whenever we encounter a reference
path which we've already seen before, we abort reference resolution and
provide the list of paths which form a loop in the error message.

Note that the already introduced boundaries where we don't need to track
paths seen by recursive calls (across ValueList layers, between Sequence
elements and between Mapping key-value pairs) still apply.

We also leave the recursion depth limit in place for now as a safeguard
for potential bugs in the loop detection.

The existing tests are updated to reflect the changed error messages for
the test cases which contain reference loops.
@simu simu force-pushed the feat/abort-on-ref-loop branch from 0ab1953 to 31f5ec0 Compare September 14, 2023 07:37
@simu simu merged commit 8d8c37d into main Sep 14, 2023
@simu simu deleted the feat/abort-on-ref-loop branch September 14, 2023 11:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants