|
15 | 15 | // - sync.Pool: Can't trace through Get/Put |
16 | 16 | // - Embedded struct: `h.Msg()` where h embeds *Event |
17 | 17 | // - Closure-modified capture: Closure writes to outer var |
| 18 | +// - IIFE unreachable return: SSA doesn't eliminate unreachable code in IIFE |
18 | 19 | package zerolog |
19 | 20 |
|
20 | 21 | import ( |
@@ -1063,6 +1064,49 @@ func badLoggerFromContextThenNew(ctx context.Context, logger zerolog.Logger) { |
1063 | 1064 | logger.Info().Msg("ignored ctx logger") // want `zerolog call chain missing .Ctx\(ctx\)` |
1064 | 1065 | } |
1065 | 1066 |
|
| 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 | + |
1066 | 1110 | // ===== POINTER WITH CONDITIONAL STORE ===== |
1067 | 1111 |
|
1068 | 1112 | // Test case: Multiple stores to same pointer address - partial ctx |
|
0 commit comments