-
-
Notifications
You must be signed in to change notification settings - Fork 617
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
Add a new rule to detect integer overflow when converting between integer types #1149
Conversation
Signed-off-by: Cosmin Cojocar <[email protected]>
Signed-off-by: Cosmin Cojocar <[email protected]>
Signed-off-by: Cosmin Cojocar <[email protected]>
Signed-off-by: Cosmin Cojocar <[email protected]>
Signed-off-by: Cosmin Cojocar <[email protected]>
Could you add documentation about how to fix it and make the linter pass? 🙏 |
dst := instr.Type().String() | ||
if isIntOverflow(src, dst) { | ||
issue := newIssue(pass.Analyzer.Name, | ||
fmt.Sprintf("integer overflow conversion %s -> %s", src, dst), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I might have missed something about the implementation, but I would like to suggest this
fmt.Sprintf("integer overflow conversion %s -> %s", src, dst), | |
fmt.Sprintf("possible integer overflow conversion %s -> %s", src, dst), |
It might not happen depending on people code.
It's better to report a possible error, than affirming there is one. People would argue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ccojocar what do you think about the changes I suggested?
Do you agree with them?
Would you change it? Or do you want me to open a PR for them?
} | ||
|
||
func parseIntType(intType string) (integer, error) { | ||
re := regexp.MustCompile(`(?P<type>u?int)(?P<size>\d{2})?`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This regexp will be computed each time parseInt will be called, it should be moved out the function
it := matches[re.SubexpIndex("type")] | ||
is := matches[re.SubexpIndex("size")] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add something like this
it := matches[re.SubexpIndex("type")] | |
is := matches[re.SubexpIndex("size")] | |
// int64 => int 64, uint8 => uint 8 | |
it := matches[re.SubexpIndex("type")] | |
is := matches[re.SubexpIndex("size")] |
return true | ||
} | ||
// converting int to uint of a smaller size might lead to overflow | ||
if srcInt.signed && !dstInt.signed && dstInt.size < srcInt.size && srcInt.size-dstInt.size > 8 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This 8 is magical number here
return integer{signed: signed, size: intSize}, nil | ||
} | ||
|
||
func isIntOverflow(src string, dst string) bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this
func isIntOverflow(src string, dst string) bool { | |
func couldIntOverflow(src string, dst string) bool { |
|
||
import "github.com/securego/gosec/v2" | ||
|
||
var SampleCodeG115 = []CodeSample{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit worried these tests are only focusing on things that could be reported.
I would expect to be added to cover conversion of things that should pass.
They are likely the ones to report false positive if something is invalid in the current implementation, or if a later refactoring screw everything
This check has rolled out and ergo suddenly comments on it! This check seems over-prescriptive. In the builtin functions, len returns type int, despite only returning zero or positive ints. Casting out of len into uint32 is thus more declarative. This is just one example where this change enforces a //nolint flag. The act of casting is an assertion that the programmer knows what they are doing and are content with the potential for data loss. Whilst I'm sure that a zero-trust environment would want to scrutinize this sort of thing, it's overkill for normal programs. |
There is perfectly valid code that can be guaranteed not to overflow that this check catches. For example; v,_ := strconv.ParseInt("1",10,32)
v32 := int32(v) As the GoDoc states;
Tbh, I'm not sure how one is supposed to cast bigger (or bare) ints/uints (for example, received from a library) into smaller size ints/uints at all with this check? Doing just At the very least, it seems to me like this check should be opt-in instead of opt-out. |
@moitias The type of v is still See more discussions in #1185. Also if this rule doesn't work for your use case, feel free to exclude it but in some cases integer overflow can lead to security issues and there isn't a protection for this in the go runtime at the moment.
|
Well, if we're being pedantic, no, the type of
Without commit access to Go stdlib (and considering Go 1 compatibility promise), I don't think I can do that.
And that, indeed, is the problem. There are safe ways of doing the conversion (again pointing out the very straightforward As a sidenote (or, another nit); this also has nothing to do with what happens before
Yeah, but this checker does not allow the developer to do it safely either, so they will need to disable the checker (locally or globally), making this checker essentially useless for any case that actually needs to do conversions and of course, nothing but lost CPU time for any case that doesn't do conversions. So, I'd argue that the usefulness of this check is dependent on it being 'smart'. If it is not, people will disable it and overflows might then creep in. |
@moitias @FairlySadPanda @ccoVeille I am looking forward to your contributions to improve this rule. I think is more productive to do this instead of just complaining and using an OSS tool maintained by volunteers ;-). |
Look, I appreciate the work you are putting into this (and helping me out) but I'm trying to point out - to help you out in turn - that this rule in its current form seems to be a bit prematurely turned on because it seems to have no use cases at all. This is because if one has it enabled, there is no way of doing the conversion securely while in fact there obviously are. Could you please, to clarify the reasoning for this rule, at least describe one way of doing a conversion to a smaller bit size safely or are you of the opinion that it is never acceptable/secure to do? I would hope we could at least agree that linter warnings should have a way of fixing them, right? |
I can understand your reaction. I could say Touché. But I'm more likely to reply you positively than being affected. I'm a smiling person. Be sure I have nothing against you or the idea you got. I wish the issues we are facing now were identified before it was merged, but there were not 🤷 You can understand people are reacting when their CI is now a Christmas tree 🎄 I wish I had reviewed your PR earlier. I wish others may have reviewed earlier. There problems was not with the idea or the code, but with the review of your changes suggestions. That said, sometimes shit happens. Let's try to find a solution. |
A change to the rule gosec(G115) made a large amount of FP for gosec appear when updating to the latest golang-ci linter. securego/gosec#1185 securego/gosec#1149 We're going to ignore this rule for the time being while waiting for gosec to get updates so that bound checking and example snippets of `valid` code is added for this rule Signed-off-by: Christopher Phillips <[email protected]>
* chore(deps): update tools to latest versions Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * chore: disable gosec(G115) A change to the rule gosec(G115) made a large amount of FP for gosec appear when updating to the latest golang-ci linter. securego/gosec#1185 securego/gosec#1149 We're going to ignore this rule for the time being while waiting for gosec to get updates so that bound checking and example snippets of `valid` code is added for this rule Signed-off-by: Christopher Phillips <[email protected]> --------- Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Signed-off-by: Christopher Phillips <[email protected]> Co-authored-by: spiffcs <[email protected]>
fixes #1130