-
Notifications
You must be signed in to change notification settings - Fork 0
feat(extractor): inter-procedural consume contract → use-after-handoff OWN002 (recall 8/10→9/11) #55
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
Merged
Merged
feat(extractor): inter-procedural consume contract → use-after-handoff OWN002 (recall 8/10→9/11) #55
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| using System; | ||
| using System.IO; | ||
|
|
||
| // FIX: read everything we need BEFORE handing ownership off, then never touch the stream. | ||
| static class HandoffUse | ||
| { | ||
| public static void Consume(Stream sink) | ||
| { | ||
| sink.CopyTo(Stream.Null); | ||
| sink.Dispose(); | ||
| } | ||
|
|
||
| static long Run(string path) | ||
| { | ||
| var s = File.OpenRead(path); | ||
| long len = s.Length; // read first ... | ||
| Consume(s); // ... then move ownership last | ||
| return len; | ||
| } | ||
| } |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| using System; | ||
| using System.IO; | ||
|
|
||
| // A pure inter-procedural use-after-handoff (no leak arm): a stream is handed to a | ||
| // consumer that takes OWNERSHIP (reads it, then disposes it), and the caller then touches | ||
| // the stream again. Unlike ownership-handoff-consume there is no leak arm -- the handoff | ||
| // itself is correct, so the ONLY bug is the use AFTER ownership moved. Common shape: | ||
| // serialize/compress into a stream, hand it to a sink that owns it, then accidentally read | ||
| // it once more (an ObjectDisposedException at runtime). | ||
| static class HandoffUse | ||
| { | ||
| // Consumer: takes ownership of `sink` and closes it. `sink` is `consume Stream`. | ||
| public static void Consume(Stream sink) | ||
| { | ||
| sink.CopyTo(Stream.Null); | ||
| sink.Dispose(); // Consume owns and closes it | ||
| } | ||
|
|
||
| // BUG: ownership moved into Consume (which disposed it), then the stream is read. -> OWN002 | ||
| static long Run(string path) | ||
| { | ||
| var s = File.OpenRead(path); | ||
| Consume(s); // ownership moves to Consume | ||
| return s.Length; // use-after-handoff (s is disposed) -> OWN002 | ||
| } | ||
| } |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| // OwnLang model of a PURE inter-procedural use-after-handoff (no leak arm). `take` takes | ||
| // the stream BY VALUE (a resource type => CONSUME): ownership moves in and it closes the | ||
| // stream, so a caller must not touch it after the handoff. `run` hands off then reads -> | ||
| // OWN002 (use after the resource was consumed by the callee). The fix reads BEFORE the | ||
| // handoff. The signature is the cut -- the caller is checked against `take`'s contract, | ||
| // not its body; no whole-program analysis. (`consume` is an OwnLang keyword, so the | ||
| // reduction names the consumer `take`; the C# consumer is `Consume`.) | ||
| module Corpus | ||
| resource Stream { | ||
| acquire open | ||
| release close | ||
| } | ||
| fn take(s: Stream) { | ||
| use s; | ||
| release s; | ||
| } | ||
| fn run() { | ||
| let s = acquire Stream(); | ||
| take(s); // ownership moves into the consumer | ||
| use s; // <-- touched after handoff -> OWN002 | ||
| } |
1 change: 1 addition & 0 deletions
1
corpus/real-world/ownership-handoff-use/expected-diagnostics.txt
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| OWN002 |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| # Inter-procedural use-after-handoff (pure) | ||
|
|
||
| **Pattern:** a stream is handed to a consumer that takes **ownership** (reads it, then | ||
| `Dispose()`s it), and the caller then touches the stream again. Unlike | ||
| `ownership-handoff-consume` there is **no leak arm** — the handoff itself is correct, so the | ||
| *only* bug is the use **after** ownership moved. Common shape: serialize/compress into a | ||
| stream, hand it to a sink that owns it, then accidentally read it once more (an | ||
| `ObjectDisposedException` at runtime). | ||
|
|
||
| **What the checker says:** using a resource after it was consumed by a callee is the generic | ||
| **OWN002** (use after release) — the same code `.own` produces for use-after-dispose. | ||
|
|
||
| **Why this case exists (the consume-contract proof).** The extractor used to treat any | ||
| argument-passing as an *escape* (untracked), so a stream handed to `Consume(s)` simply | ||
| vanished and the later `s.Length` was invisible — a **miss**. Now a call to a first-party | ||
| **consumer** — a method whose own body disposes a by-value `IDisposable` parameter — is | ||
| modelled as a **release of the argument at the call site**, the same shape as pool | ||
| `Return(buf)` (the resource leaves the caller's hands right there). The use *after* that | ||
| release then trips **OWN002**. The signal is the callee's own body, so it is inter-procedural | ||
| without a cross-call signature table (and so without a dangling-callee crash). This fixture is | ||
| a *miss* before and a *catch* after; `ownership-handoff-consume` is caught for its leak arm | ||
| either way, so this is the row that makes the use-after-handoff capability a measurable ratchet. | ||
|
|
||
| **Honesty / scope.** `case.own` is a faithful hand reduction of the C# pattern, not C# the | ||
| `.own` checker ingested. `before.cs` / `after.cs` are representative of the bug and its fix, | ||
| not a verbatim copy of one PR. |
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
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
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.
Uh oh!
There was an error while loading. Please reload this page.