-
Notifications
You must be signed in to change notification settings - Fork 1.9k
CPP: Add a query to find incorrectly used switch #6081
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
Conversation
MathiasVP
left a comment
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.
Thanks for another contribution, @ihsinme!
cpp/ql/src/experimental/Security/CWE/CWE-561/FindIncorrectlyUsedSwitch.ql
Outdated
Show resolved
Hide resolved
| from SwitchStmt sw, string msg | ||
| where | ||
| isRealRange(sw.getExpr()) and | ||
| isRealRange(sw.getExpr().getAChild*()) and |
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 guess we need isRealRange(sw.getExpr()) to check that we have a meaningful range for the expression that's being branched on. But what why do we need to need isRealRange(sw.getExpr().getAChild*()) as well?
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.
to exclude the situation when a significant range is formed from operations with elements with the maximum range. for example (a + b) >> c in the presence of a significant range only for c we can get a fairly beautiful overall range, but this will not be what we are looking for.
| predicate isNotAllSelected(SwitchStmt swtmp) { | ||
| not swtmp.getExpr().isConstant() and | ||
| exists(int i | | ||
| i != 0 and |
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.
Why exclude 0 here?
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.
0 is also excluded in isConditionBig predicate through significant range. this is done in order to exclude quite frequent stylistic situations before processing, when the developer processes 0, and in the switch block either excludes the selection, or truncates the values of the conditions. here is an example from trimming selection.
aappleby/smhasher#91
| ( | ||
| lb.getName().charAt(0) = "d" or | ||
| lb.getName().charAt(0) = "c" | ||
| ) and | ||
| ( | ||
| lb.getName().charAt(1) = "e" or | ||
| lb.getName().charAt(1) = "a" | ||
| ) and | ||
| ( | ||
| lb.getName().charAt(2) = "f" or | ||
| lb.getName().charAt(2) = "s" | ||
| ) |
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 will match labels with the names "def", "des", "daf", "das", "cef", "ces", "caf", "cas". Is that the intended effect?
Would it be better to flag all LabelStmt inside switch statements that have no GotoStmt jumping to them?
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 will match labels with the names "def", "des", "daf", "das", "cef", "ces", "caf", "cas". Is that the intended effect?
I was hoping to find all the labels that start with these characters.
Would it be better to flag all
LabelStmtinside switch statements that have noGotoStmtjumping to them?
your offer is much better from a security point of view. it will also cover situations when you forgot to write case. I'll look at it live and change the code.
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.
Good day.
my analysis shows that unused labels are the result of constructs using complex transitions such as
or a macro that generates various labels
or the result of #ifdef constraints
unfortunately in all these situations, the developer assumes the presence of unmanaged labels.
I want to find a label similar to default for example default dafalt defalt defaul and so on.
which is possible and is used in the transition operator (or maybe not),
but it creates the possibility that one of the developers might mistake this label as part of a switch construct.
therefore, such a label is bad, at least from a stylistic point of view.
if you do not like the current code, I suggest changing it to detect specific erroneous labels,
with similar ones on default it is not difficult to do this.
with labels similar to case, I'll think about it, because I wanted to take into account, among other things, caseTARARATARARA
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.
my analysis shows that unused labels are the result of constructs using complex transitions such as
To filter out such labels you could require that there doesn't exist a LabelLiteral whose getLabel gives you back the label.
I admit those labels are all quite... intricate... I don't particularly mind this solution. Have you found any bugs caused by a misspelled default:?
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.
at the initial stage of the formation of the request, I found two ambiguous situations of using labels. but this did not look like an example of an error.
I keep looking.
cpp/ql/test/experimental/query-tests/Security/CWE/CWE-561/semmle/tests/test.c
Show resolved
Hide resolved
cpp/ql/src/experimental/Security/CWE/CWE-561/FindIncorrectlyUsedSwitch.qhelp
Outdated
Show resolved
Hide resolved
cpp/ql/src/experimental/Security/CWE/CWE-561/FindIncorrectlyUsedSwitch.qhelp
Outdated
Show resolved
Hide resolved
|
Thanks a lot for your corrections and comments. I want to separately apologize for the comments that you have already made to me in other PRs.( |
…edSwitch.qhelp Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com>
|
good afternoon @MathiasVP. until I found detection when using labels( but I improved the query a bit. and found several situations of incorrect operation of the ranges.
it would be great if you could help me understand the cause of these errors. Thank you. |
This was a bug in our range analysis. I've fixed it in #6315 and verified that this PR removes the alert. Thanks for catching it!
I haven't quite figured out yet why this alert is raised. I'll take a look at it on Monday. |
…edSwitch.ql Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com>
The problem here is your predicate isConditionBig(SwitchStmt swtmp) {
// ...
not exists(int iu, int il |
// ...
upperBound(swtmp.getExpr()) = iu and
// ...
lowerBound(swtmp.getExpr()) = il
)
}You're saying that the predicate holds whenever there doesn't exist integers Instead, you should state something like:
Does that make sense? |
Good day. I very much missed that the enum throws an error. this increases the potential for false detection. I am still thinking about a fix:
|
|
could you take a look at the range of w1 is defined as [-2.3]. |
|
Good afternoon @MathiasVP. I fixed the predicate if there is a loop before the |
Thanks for continuing with this PR! I don't see any changes to the What you're observing is actually more general than something that happens with loops. See for instance this example: https://ideone.com/S5x6pn. Very rarely are there good reasons for code like this, though. |
This is working as intended (unfortunately). It's due to the use of widening which we use in the range analysis library to ensure that the analysis terminates in a reasonable amount of time. You can add more values to the predicates here and here to see if that improves your analysis. I don't think we can merge changes to those predicates, however. They are very important for performance on some databases. |
I may be wrong, but the predicate changed work. https://lgtm.com/query/7750306597002152773/ the example you gave (if before) is the example of dead code I'm looking for. if there was a loop, it would be used by the compiler as live code. |
Ah, I see what you mean. The code you added in the |
|
I'm happy with this PR now @ihsinme. Do you want to make any more changes before I merge it? |
|
I do not plan to make changes yet |
good day.
in this request, I am considering finding a error use of the
switchblock.I have identified 4 main areas:
1.when the value range of the condition is less than the selection items.
2. when the selection items are larger than the range of values.
3.when there are labels in the body with names similar to
defaultorcase4.when there is code before the first case element.
I would like to draw your attention to the predicate
isRealRangeunfortunately the restriction onintdid not allow usingbitShiftRightand make it more elegant.regarding fixes in real software, I am currently awaiting a response from some projects and continue to look for a solution in others.
htacg/tidy-html5#953
Hamlib/Hamlib#723