-
Notifications
You must be signed in to change notification settings - Fork 16
fix: release the reference lock before resolving its pointer #230
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
Open
OmarAlJarrah
wants to merge
5
commits into
speakeasy-api:main
Choose a base branch
from
OmarAlJarrah:fix/reference-resolve-self-deadlock
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
3efdc1c
fix: release the reference lock before resolving its pointer
OmarAlJarrah d02ba76
fix: stop GetObject recursing through a cyclic resolution chain
OmarAlJarrah 1fe8ffc
fix: keep parent links out of a cyclic resolution chain
OmarAlJarrah 9f9c8a6
refactor: flatten the double-check in Reference.resolve
OmarAlJarrah f58f208
fix: derive parent-link safety from the links, not the current call
OmarAlJarrah File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This still publishes a self-reference for the trimmed-pointer case. I verified after
ResolveAllReferencesreturnscircular reference detectedthatref.referenceResolutionCache.Object == ref. The tracker setscircularErrorFoundlater, but it does not clear this cache entry, so any subsequentref.GetObject()reaches line 299 and delegates straight back toref.GetObject()until the process exhausts its goroutine stack. The new test only checks the resolution error and therefore misses the corrupt post-resolution state. Please avoid publishing a result whose object is this reference (or otherwise represent the circular state without a self-delegating cache), and add a regression that safely verifiesGetObject()after the circular resolution attempt.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Confirmed and fixed in d02ba76, though not by suppressing the publish.
A pointer-identity check against the reference being resolved turned out to catch only the one-node case. Two references can close the loop between them without either being a self-reference:
The tracker reports
circular reference detected: test.yaml#/paths/~1b -> test.yaml#/paths/~1a -> test.yaml#/paths/~1b, but only on the hop after both caches are published, soa.cache.Object == bandb.cache.Object == aand neither== r.GetObjectthen alternates between them until the stack goes.Not publishing is also awkward here:
resolveObjectWithTrackingreadsref.referenceResolutionCache.ResolvedDocumentright afterresolvereturns a next reference, so an empty cache turns the overflow into a nil dereference.So
GetObjectnow walks the chain iteratively with a seen set and returns nil once it repeats, which covers a cycle of any length and leaves the resolution errors and the published cache as they were. Legitimate circular references were already safe because the tracker stops before the last hop's cache is published, and there is now a test pinning that alongside a multi-hop chain that still resolves.Both cycle shapes are regression tested through
GetObjectafter resolution: with the walk reverted they abort the binary withfatal error: stack overflow.go test ./...,-raceon./openapi/... ./references/... ./jsonpointer/..., andgolangci-lintare clean.