Skip to content

Commit 121fd7c

Browse files
authored
Merge pull request #27 from PhysShell/claude/zen-pasteur-76hfs1
docs(oracle): first Dapper three-way — the Infer# trio is ownership-transfer (precision win)
2 parents 7ec0d65 + b002059 commit 121fd7c

1 file changed

Lines changed: 36 additions & 0 deletions

File tree

‎docs/notes/oracle.md‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,42 @@ Pair this with the extractor's planned `--stats` coverage (methods analysed vs
101101
skipped) and the picture is complete: how much we looked at, and how our verdicts
102102
line up with two independent engines.
103103

104+
## What the first Dapper three-way showed (a worked example)
105+
106+
Running all three on Dapper's **product code** (commit `72a54c4`; `--exclude-tests`
107+
dropped 165 test/benchmark findings) gave **Own.NET 0 · Infer# 3 · CodeQL 2**
108+
leak-class, `agree 0`, and **`own-only 0`** (no false positives from us). The five
109+
oracle-only findings are both classes we deliberately don't model — and one of them
110+
is arguably a *precision win for us*:
111+
112+
- **Infer# ×3** — all `WrappedBasicReader` / `DbWrappedReader` in `SqlMapper`
113+
(`SqlMapper.cs:1952`, `:3294`, `SqlMapper.IDataReader.cs:118`): "resource
114+
allocated … is not closed." But that wrapper is Dapper's **caller-owned disposal
115+
handle** — `ExecuteReader*` does `return DbWrappedReader.Create(cmd, reader)`
116+
(ownership handed to the caller), and the `GetRowParser`/`GetDbDataReader` adapter
117+
wraps the *caller's own* reader (disposing it would close the caller's reader).
118+
`WrappedBasicReader.Dispose()` simply forwards to `_reader.Dispose()` — it exists
119+
precisely so the **holder** disposes it. So these are Infer# **over-reports on the
120+
returns-`IDisposable` pattern** — exactly the escape / ownership-transfer case
121+
Own.NET treats as *not a leak*. Our `0` is the right verdict here; Infer#'s `3`
122+
look like false positives. (Verified against `WrappedReader.cs` and the
123+
`ExecuteReader` return; the two `SqlMapper.cs` sites match the same direct-return
124+
and adapter shapes.)
125+
- **CodeQL ×2** — `cs/dispose-not-called-on-throw` at `SqlMapper.cs:1242/1333`: a
126+
disposable local may leak *only if* an exception is thrown mid-method. We don't
127+
model exceptional CFG edges, so this is an honest recall gap **by design**, not a
128+
logic bug.
129+
130+
Caveat: `own-only 0` also reflects **coverage** — Dapper's core is heavily async and
131+
interprocedural, which we under-analyse, so "found nothing" partly means "didn't
132+
reach it." Telling the two apart needs the extractor's `--stats` (analysed vs
133+
skipped) — the missing signal this run made concrete.
134+
135+
Net: the oracle did its job. It turned "are we behind?" into a precise map —
136+
precision held (0 FPs; we look *more* correct than Infer# on ownership transfer),
137+
and the recall gap is two named, roadmapped classes (interprocedural escape
138+
tracking, exception-path disposal).
139+
104140
## Honest gaps (v1)
105141

106142
- **No tool versions pinned in the report yet.** `microsoft/infersharpaction@v1.5`

0 commit comments

Comments
 (0)