Skip to content

Go: go/comparison-of-identical-expressions false positive when a variable is reassigned in a range loop (go-all 8.0.0) #22770

Description

@gomaja

Description of the false positive

Since codeql/go-queries 1.6.12 (with codeql/go-all 8.0.0), go/comparison-of-identical-expressions reports a comparison between a variable and the value it was initialised from, even though the variable may be reassigned inside a range loop between the two. With codeql/go-queries 1.6.11 (codeql/go-all 7.3.2), the same database gives no result.

The trigger is the range loop. The same assignment in a plain if or in a three-clause for loop is not reported. It looks related to the CFG rewrite in go-all 8.0.0, whose changelog mentions range statements. If assignments in a range body don't reach the code after the loop, other data-flow queries might be affected as well. I have only checked this query.

Code samples or links to source code

package repro

// Reported (line "if n == c"): n may be raised inside the range loop.
func Settle(c int, xs []int) int {
	for {
		n := c
		for _, x := range xs {
			if x > n {
				n = x
			}
		}
		if n == c { // <- "This expression compares an expression to itself."
			break
		}
		c = n
	}
	return c
}

// Also reported: unconditional assignment in a range loop.
func VariantD(c int, xs []int) int {
	n := c
	for _, x := range xs {
		n = x
	}
	if n == c { // <- reported
		return 0
	}
	return n
}

// Not reported: the same assignment in a three-clause loop.
func VariantB(c int, xs []int) int {
	n := c
	for i := 0; i < len(xs); i++ {
		if xs[i] > n {
			n = xs[i]
		}
	}
	if n == c {
		return 0
	}
	return n
}

To reproduce (CodeQL CLI 2.27.1, macOS arm64, Go 1.25.13). --no-tracing is used only because this machine has no Rosetta for the tracer.

codeql database create db --language=go --source-root src --build-mode=autobuild --no-tracing
codeql database analyze db codeql/go-queries@1.6.11:RedundantCode/CompareIdenticalValues.ql --format=sarif-latest --output=a.sarif --rerun
codeql database analyze db codeql/go-queries@1.6.12:RedundantCode/CompareIdenticalValues.ql --format=sarif-latest --output=b.sarif --rerun
  • a.sarif, go-queries 1.6.11 / go-all 7.3.2: 0 results.
  • b.sarif, go-queries 1.6.12 / go-all 8.0.0: 3 results: Settle, VariantD, and a third range-loop variant without the outer loop.

Without --rerun, the second command silently reuses the first command's cached results: its SARIF reports go-queries 1.6.11 and 0 results. This may be worth a look separately.

The same comparison is reported in real code here: https://github.com/gomaja/go-asn1/blob/2e83d89af0dc815fc1e0a589691032aa069153bc/runtime/ber/named_bit_size.go#L43. In that code, next starts as candidate and can be raised inside the range loop over the permitted intervals.

No activity

Activity on this issue will appear here.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions