Skip to content

Commit d1e4284

Browse files
mpywclaude
andauthored
test: Add edge case coverage and document new LIMITATION (#17)
Added test cases: - Closure in loop with varying ctx - Multiple MakeClosure in different branches - IIFE with unreachable return (documented as LIMITATION) The IIFE unreachable return is a false positive because SSA doesn't always eliminate unreachable code (e.g., `if true { ... } else { ... }`). All return paths are checked even if some are unreachable. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent c995a1c commit d1e4284

File tree

1 file changed

+44
-0
lines changed

1 file changed

+44
-0
lines changed

testdata/src/zerolog/evil_ssa.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
// - sync.Pool: Can't trace through Get/Put
1616
// - Embedded struct: `h.Msg()` where h embeds *Event
1717
// - Closure-modified capture: Closure writes to outer var
18+
// - IIFE unreachable return: SSA doesn't eliminate unreachable code in IIFE
1819
package zerolog
1920

2021
import (
@@ -1063,6 +1064,49 @@ func badLoggerFromContextThenNew(ctx context.Context, logger zerolog.Logger) {
10631064
logger.Info().Msg("ignored ctx logger") // want `zerolog call chain missing .Ctx\(ctx\)`
10641065
}
10651066

1067+
// ===== CLOSURE IN LOOP WITH VARYING CTX =====
1068+
1069+
// Test case: Closure created in loop with varying ctx
1070+
// Each iteration should be checked independently
1071+
func badClosureInLoopVaryingCtx(ctx context.Context, logger zerolog.Logger) {
1072+
for i := 0; i < 2; i++ {
1073+
e := logger.Info()
1074+
if i == 1 {
1075+
e = e.Ctx(ctx) // only second iteration has ctx
1076+
}
1077+
f := func() {
1078+
e.Msg("in loop closure") // want `zerolog call chain missing .Ctx\(ctx\)`
1079+
}
1080+
f()
1081+
}
1082+
}
1083+
1084+
// Test case: Multiple MakeClosure for same closure function
1085+
// If created in different branches with different bindings, all must have ctx
1086+
func badMultipleMakeClosureBranches(ctx context.Context, logger zerolog.Logger, cond bool) {
1087+
var f func()
1088+
if cond {
1089+
e := logger.Info().Ctx(ctx)
1090+
f = func() { e.Msg("branch 1") }
1091+
} else {
1092+
e := logger.Info() // no ctx
1093+
f = func() { e.Msg("branch 2") } // want `zerolog call chain missing .Ctx\(ctx\)`
1094+
}
1095+
f()
1096+
}
1097+
1098+
// LIMITATION (false positive): IIFE with unreachable return
1099+
// SSA doesn't always eliminate unreachable code, so all return paths are checked.
1100+
// Even though the second return is unreachable, analyzer still reports.
1101+
func limitationIIFEUnreachableReturn(ctx context.Context, logger zerolog.Logger) {
1102+
func() *zerolog.Event {
1103+
if true {
1104+
return logger.Info().Ctx(ctx)
1105+
}
1106+
return logger.Info() // unreachable, but SSA doesn't eliminate it
1107+
}().Msg("iife unreachable") // want `zerolog call chain missing .Ctx\(ctx\)`
1108+
}
1109+
10661110
// ===== POINTER WITH CONDITIONAL STORE =====
10671111

10681112
// Test case: Multiple stores to same pointer address - partial ctx

0 commit comments

Comments
 (0)