Skip to content

False negative: nil dereference not detected when function is called through a function variable #387

@yd-beep

Description

@yd-beep

Description

Nilaway fails to detect a nil pointer dereference when a function is called indirectly through a function variable. The same nil flow is correctly detected when the function is called directly.

Reproduction

package main

import "reflect"

type Config struct {
	Value string
}

// Function variable pointing to the actual implementation
var ProcessFunc = process

func process(cfg *Config) {
	// BUG: cfg can be nil, but we dereference it without checking
	if reflect.ValueOf(*cfg).IsZero() {
		return
	}
	println(cfg.Value)
}

// CASE 1: Direct call - nilaway DETECTS this (uncomment to verify)
// func callerDirect(cfg *Config) {
// 	process(cfg)
// }

// CASE 2: Call through function variable - nilaway MISSES this
func callerIndirect(cfg *Config) {
	ProcessFunc(cfg)
}

func main() {
	// Case 1 (nilaway detects) - uncomment to verify:
	// callerDirect(nil)

	// Case 2 (nilaway misses):
	callerIndirect(nil) // Panics at reflect.ValueOf(*cfg)
}

Steps to reproduce

# Case 2 (as-is): nilaway reports 0 issues
nilaway main.go
# Exit code: 0

# But the program panics at runtime
go run main.go
# panic: runtime error: invalid memory address or nil pointer dereference

To verify nilaway works for direct calls, uncomment Case 1 and comment out Case 2 in main():

nilaway main.go
# main.go:20:10: error: Potential nil panic detected...

Expected behavior

Nilaway should report a potential nil panic for both cases:

  • Case 1 (direct call): ✅ Detected
  • Case 2 (function variable): ❌ Not detected (false negative)

Actual behavior

Nilaway only detects the nil flow when the function is called directly. When called through a function variable (ProcessFunc(cfg) instead of process(cfg)), the nil flow is not tracked.

Environment

  • nilaway version: v0.0.0-20251208195206-89df5f7e6199
  • Go version: go1.25.5 darwin/arm64
  • OS: macOS

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions