Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

G115 is reporting false positives (a summary) #1212

Open
czechbol opened this issue Sep 4, 2024 · 16 comments
Open

G115 is reporting false positives (a summary) #1212

czechbol opened this issue Sep 4, 2024 · 16 comments

Comments

@czechbol
Copy link
Contributor

czechbol commented Sep 4, 2024

Summary

G115 is still reporting false positives even after #1189 and #1194.

Known false positives

I'm writing these down without much investigation whether it is possible to implement fixes for them.

  • any kind of arithmetic done on the checked variable after the check:
func foo(a int) uint {
    if a != 3 || a != 4 {
        panic("not supported")
    }
    // the value being passed here is different than the one checked 
    // so it is tricky to determine if the check is valid
    //
    // this will be difficult to implement without introducing false negatives
    return uint(a-1)  // false positive 
}
  • explicit value checks are lacking:
func foo(a int) uint {
    if a == 3 || a != 4 {
        // see that sneaky NEQ there?
        return uint(a)  // false negative 
    }
    panic("not supported")
}
func foo(a int) uint16 {
    return uint16(a &0xffff) // false positive 
}
func foo() uint16 {
    a, b := 1234, 2345
    result := min(a,b)

    return uint(result) // false positive 
}
func foo(myArr []string) {
    // these seem to have a similar implementation difficulty to the arithmetic example
    for i, _ := range myArr {
        _ = uint64(i) // false positive 
    }

    for i := 0; i < 10; i++ {
        _ = uint64(i) // false positive 
    }

    for i := randIntMightBeNegativeEven(); i >= 0; i-- {
        _ = uint64(i) // false positive 
    }
}

Notes:

I recommend opening multiple small PRs that fix one issue at a time.

@ccoVeille
Copy link
Contributor

At least these use cases are less frequent than the previous ones.

@deerbone
Copy link

deerbone commented Sep 4, 2024

I'd say that people will hit the first one pretty frequently, and it also seems to me it's the most difficult to tackle without bringing in any false negatives.

@czechbol
Copy link
Contributor Author

czechbol commented Sep 5, 2024

@Victoremepunto you're getting that warning because golangci-lint has not released a new version with the changes from #1194 yet. The code you have there looks sound so once we have a new golangci-lint release, it should work.

@ccoVeille do you know and can share at least approximately when we can expect it?

@ccoVeille
Copy link
Contributor

I'm just a random gopher. I'm pretty active, but I'm not part of golangci-lint release.

@ldez might be a better candidate to reply that question

@ldez
Copy link
Contributor

ldez commented Sep 5, 2024

do you know and can share at least approximately when we can expect it?

I have no precise release date for now but soon, mainly because of G115 false positives.

@PlasmaPower
Copy link

I'm not sure if I should open a separate issue for this, but another false positive is casting the index produced by iterating over a range to an unsigned int. We do this a lot in our codebase. E.g.:

myArr := []string{"hello", "world"}

for i := range len(myArr) {
    _ = uint64(i) // shouldn't error but does with G115
}

for i, _ := range myArr {
    _ = uint64(i) // shouldn't error but does with G115
}

Ideally it'd be able to look at bounds in for loops as well, but I get that's more complicated:

for i := 0; i < 10; i++ {
    _ = uint64(i) // shouldn't error but does with G115
}

for i := randIntMightBeNegativeEven(); i >= 0; i-- {
    _ = uint64(i) // shouldn't error but does with G115
}

@ccoVeille
Copy link
Contributor

Quick follow up, golangci-lint 1.61.0 was shipped with gosec 2.21.2 💪

So everything that was made in gosec to improve G115 detection are now released 🎉

@czechbol
Copy link
Contributor Author

I'm not sure if I should open a separate issue for this, but another false positive is casting the index produced by iterating over a range to an unsigned int. We do this a lot in our codebase. E.g.:

@PlasmaPower You are correct, this seems like another issue. I'll get back to it a bit later and update my summary.

@Victoremepunto
Copy link

@Victoremepunto you're getting that warning because golangci-lint has not released a new version with the changes from #1194 yet. The code you have there looks sound so once we have a new golangci-lint release, it should work.

@ccoVeille do you know and can share at least approximately when we can expect it?

Hi! unfortunately, using golangci-lint 1.60.1 the problem is still there - might worth trying to get a simpler reproducer and add it to this issue?

check this: https://github.com/RedHatInsights/frontend-operator/actions/runs/10835444044/job/30066989278?pr=188#step:5:26

@ldez
Copy link
Contributor

ldez commented Sep 12, 2024

Hi! unfortunately, using golangci-lint 1.60.1 the problem is still there

Maybe it's because the fix is inside golangci-lint v1.61.0 and not v1.60.1 😉

@Victoremepunto
Copy link

Hi! unfortunately, using golangci-lint 1.60.1 the problem is still there

Maybe it's because the fix is inside golangci-lint v1.61.0 and not v1.60.1 😉

lol, I'm sorry the version I used was v1.61.0, I just mistyped it. Here's an excerpt of the GHA logs:


run golangci-lint
  Running [/home/runner/golangci-lint-1.61.0-linux-amd64/golangci-lint run] in [/home/runner/work/frontend-operator/frontend-operator] ...
  Error: controllers/status.go:120:44: G115: integer overflow conversion int -> int32 (gosec)

@ben-krieger
Copy link
Contributor

Hi! unfortunately, using golangci-lint 1.60.1 the problem is still there

Maybe it's because the fix is inside golangci-lint v1.61.0 and not v1.60.1 😉

lol, I'm sorry the version I used was v1.61.0, I just mistyped it. Here's an excerpt of the GHA logs:


run golangci-lint
  Running [/home/runner/golangci-lint-1.61.0-linux-amd64/golangci-lint run] in [/home/runner/work/frontend-operator/frontend-operator] ...
  Error: controllers/status.go:120:44: G115: integer overflow conversion int -> int32 (gosec)

In order to keep this thread a useful source of truth, let me fill in some details.

@Victoremepunto's issue was that accessing a struct field is considered a different value every time in SSA. This is because without deeper analysis (than SSA), you can't rule out a concurrent routine modifying that value between accesses.

Therefore, the issue could have been resolved without any changes to gosec by simply changing

if results.Managed < math.MinInt32 || results.Managed > math.MaxInt32 {
	return crd.FrontendDeployments{}, "", errors.NewClowderError("value out of range for int32")
}
deploymentStats.ManagedDeployments = int32(results.Managed)

to

managed := results.Managed
if managed < math.MinInt32 || managed > math.MaxInt32 {
	return crd.FrontendDeployments{}, "", errors.NewClowderError("value out of range for int32")
}
deploymentStats.ManagedDeployments = int32(managed)

However, since struct field access is a common use case and modifying the value at the same time as reading it is a race condition (which is usually considered a bug), #1221 treats field accesses as not being modified between time-of-check and time-of-use (TOCTOU).

And yes, TOCTOU is its own type of potential security vulnerability. Maybe a future linter can better look for this.

@czechbol
Copy link
Contributor Author

Thanks @ben-krieger for the explanation. I purposefully decided to ignore TOCTOU in that PR.

The proposal of a separate lint rule for it is a very good idea since a different lint message would explain the issue better.

AnkushinDaniil added a commit to NethermindEth/juno that referenced this issue Sep 16, 2024
Exclude G115 from the gosec linter to address the issue with securego/gosec#1212.
AnkushinDaniil added a commit to NethermindEth/juno that referenced this issue Sep 17, 2024
* chore: Update golangci-lint to version 1.61.0

* chore: Exclude G115 from gosec linter

Exclude G115 from the gosec linter to address the issue with securego/gosec#1212.

* chore: Remove unused variable assignments

Remove unused variable assignments in node/node.go and utils/pipeline/pipeline_test.go files.

* chore: Remove unused nolint directives

Remove unused nolint directives in the starknet client.go and handlers.go files.
@ldemailly
Copy link
Contributor

ldemailly commented Sep 17, 2024

Contributing a real world example of false positive with min:

p1.R = uint8(min(255, uint16(p1.R)+uint16(p2.R)))

@ccojocar
Copy link
Member

On this, I think we need to start the Obfuscated Go Integer Overflow Contest. 😄

AnkushinDaniil added a commit to AnkushinDaniil/juno that referenced this issue Sep 24, 2024
* chore: Update golangci-lint to version 1.61.0

* chore: Exclude G115 from gosec linter

Exclude G115 from the gosec linter to address the issue with securego/gosec#1212.

* chore: Remove unused variable assignments

Remove unused variable assignments in node/node.go and utils/pipeline/pipeline_test.go files.

* chore: Remove unused nolint directives

Remove unused nolint directives in the starknet client.go and handlers.go files.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants