🚀 Launch Week Day 4:Introducing the Alert Details Page: A Better Way to Explore Alerts.Learn More →
Socket
Book a DemoInstallSign in
Socket

proxy-git.cwkhome.fun/kyoh86/exportloopref

Package Overview
Dependencies
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

proxy-git.cwkhome.fun/kyoh86/exportloopref

Go Modules
Version
v0.1.11
Version published
Created
Source

exportloopref

An analyzer that finds exporting pointers for loop variables. Pin them all!

PkgGoDev Go Report Card Coverage Status Release

What's this?

Sample problem code from: https://github.com/kyoh86/exportloopref/blob/main/testdata/src/simple/simple.go

package main

func main() {
	var intArray [4]*int
	var intSlice []*int
	var intRef *int
	var intStr struct{ x *int }

	println("loop expecting 10, 11, 12, 13")
	for i, p := range []int{10, 11, 12, 13} {
		printp(&p)                      // not a diagnostic
		intSlice = append(intSlice, &p) // want "exporting a pointer for the loop variable p"
		intArray[i] = &p                // want "exporting a pointer for the loop variable p"
		if i%2 == 0 {
			intRef = &p   // want "exporting a pointer for the loop variable p"
			intStr.x = &p // want "exporting a pointer for the loop variable p"
		}
		var vStr struct{ x *int }
		var vArray [4]*int
		var v *int
		if i%2 == 0 {
			v = &p         // not a diagnostic (x is local variable)
			vArray[1] = &p // not a diagnostic (x is local variable)
			vStr.x = &p
		}
		_ = v
	}

	println(`slice expecting "10, 11, 12, 13" but "13, 13, 13, 13"`)
	for _, p := range intSlice {
		printp(p)
	}
	println(`array expecting "10, 11, 12, 13" but "13, 13, 13, 13"`)
	for _, p := range intArray {
		printp(p)
	}
	println(`captured value expecting "12" but "13"`)
	printp(intRef)
}

func printp(p *int) {
	println(*p)
}

In Go, the p variable in the above loops is actually a single variable. So in many case (like the above), using it makes for us annoying bugs.

You can find them with exportloopref, and fix it.

package main

func main() {
	var intArray [4]*int
	var intSlice []*int
	var intRef *int
	var intStr struct{ x *int }

	println("loop expecting 10, 11, 12, 13")
	for i, p := range []int{10, 11, 12, 13} {
    p := p                          // FIX variable into the local variable
		printp(&p)
		intSlice = append(intSlice, &p) 
		intArray[i] = &p
		if i%2 == 0 {
			intRef = &p
			intStr.x = &p
		}
		var vStr struct{ x *int }
		var vArray [4]*int
		var v *int
		if i%2 == 0 {
			v = &p
			vArray[1] = &p
			vStr.x = &p
		}
		_ = v
	}

	println(`slice expecting "10, 11, 12, 13"`)
	for _, p := range intSlice {
		printp(p)
	}
	println(`array expecting "10, 11, 12, 13"`)
	for _, p := range intArray {
		printp(p)
	}
	println(`captured value expecting "12"`)
	printp(intRef)
}

func printp(p *int) {
	println(*p)
}

ref: https://github.com/kyoh86/exportloopref/blob/main/testdata/src/fixed/fixed.go

Sensing policy

I want to make exportloopref as accurately as possible. So some cases of lints will be false-negative.

e.g.

var s Foo
for _, p := range []int{10, 11, 12, 13} {
  s.Bar(&p) // If s stores the pointer, it will be bug.
}

If you want to report all of lints (with some false-positives), you should use looppointer.

Known false negatives

Case 1: pass the pointer to function to export.

Case 2: pass the pointer to local variable, and export it.

package main

type List []*int

func (l *List) AppendP(p *int) {
	*l = append(*l, p)
}

func main() {
	var slice []*int
	list := List{}

	println("loop expect exporting 10, 11, 12, 13")
	for _, v := range []int{10, 11, 12, 13} {
		list.AppendP(&v) // Case 1: wanted "exporting a pointer for the loop variable v", but cannot be found

		p := &v                  // p is the local variable
		slice = append(slice, p) // Case 2: wanted "exporting a pointer for the loop variable v", but cannot be found
	}

	println(`slice expecting "10, 11, 12, 13" but "13, 13, 13, 13"`)
	for _, p := range slice {
		printp(p)
	}
	println(`array expecting "10, 11, 12, 13" but "13, 13, 13, 13"`)
	for _, p := range ([]*int)(list) {
		printp(p)
	}
}

func printp(p *int) {
	println(*p)
}

Install

go:

$ go get github.com/kyoh86/exportloopref/cmd/exportloopref

homebrew:

$ brew install kyoh86/tap/exportloopref

gordon:

$ gordon install kyoh86/exportloopref

Usage

exportloopref [-flag] [package]

Flags

FlagDescription
-Vprint version and exit
-allno effect (deprecated)
-c intdisplay offending line with this many lines of context (default -1)
-cpuprofile stringwrite CPU profile to this file
-debug stringdebug flags, any subset of "fpstv"
-fixapply all suggested fixes
-flagsprint analyzer flags in JSON
-jsonemit JSON output
-memprofile stringwrite memory profile to this file
-sourceno effect (deprecated)
-tags stringno effect (deprecated)
-trace stringwrite trace log to this file
-vno effect (deprecated)

LICENSE

MIT License

This is distributed under the MIT License.

FAQs

Package last updated on 16 Nov 2022

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts