-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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 query to ensure predicates starting with 'get' return a value #18164
Merged
Napalys
merged 10 commits into
github:main
from
Napalys:napalys/ql-validate-predicate-get-returns
Dec 2, 2024
Merged
Changes from 9 commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
986e1cb
Add ValidatePredicateGetReturns query and tests
Napalys a763dd7
Fixed github-advanced-security bot warning
Napalys a5521b9
Update ql/ql/src/queries/style/ValidatePredicateGetReturns.ql
Napalys 029b567
Update ql/ql/src/queries/style/ValidatePredicateGetReturns.ql
Napalys e33f7aa
Added test cases for 'as' prefix
Napalys 96c1086
Modified comments to reflect 'as' changes
Napalys a462ec9
Now the error message reflects properly the prefix
Napalys 7c1aa84
Fixed bug where some predicates were flagged without return type even…
Napalys 67745e6
Reused isGetPredicate to retrieve the prefix of the predicate
Napalys 7db9b7d
Now flag aliases with the 'get' or 'as' prefix that resolve to predic…
Napalys File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
/** | ||
* @name Predicates starting with "get" or "as" should return a value | ||
* @description Checks if predicates that start with "get" or "as" actually return a value. | ||
* @kind problem | ||
* @problem.severity warning | ||
* @id ql/predicates-get-should-return-value | ||
* @tags correctness | ||
* maintainability | ||
* @precision high | ||
*/ | ||
|
||
import ql | ||
import codeql_ql.ast.Ast | ||
|
||
/** | ||
* Identifies predicates whose names start with "get", "as" followed by an uppercase letter. | ||
* This ensures that only predicates like "getValue" are matched, excluding names like "getter". | ||
*/ | ||
predicate isGetPredicate(Predicate pred, string prefix) { | ||
prefix = pred.getName().regexpCapture("(get|as)[A-Z].*", 1) | ||
} | ||
|
||
/** | ||
* Checks if a predicate has a return type. | ||
*/ | ||
predicate hasReturnType(Predicate pred) { exists(pred.getReturnTypeExpr()) } | ||
|
||
/** | ||
* Checks if a predicate is an alias using getAlias(). | ||
*/ | ||
predicate isAlias(Predicate pred) { exists(pred.(ClasslessPredicate).getAlias()) } | ||
|
||
from Predicate pred, string prefix | ||
where | ||
isGetPredicate(pred, prefix) and | ||
not hasReturnType(pred) and | ||
not isAlias(pred) | ||
select pred, "This predicate starts with '" + prefix + "' but does not return a value." |
3 changes: 3 additions & 0 deletions
3
ql/ql/test/queries/style/ValidatePredicateGetReturns/ValidatePredicateGetReturns.expected
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
| test.qll:4:11:4:18 | ClasslessPredicate getValue | This predicate starts with 'get' but does not return a value. | | ||
| test.qll:25:11:25:28 | ClasslessPredicate getImplementation2 | This predicate starts with 'get' but does not return a value. | | ||
| test.qll:31:11:31:17 | ClasslessPredicate asValue | This predicate starts with 'as' but does not return a value. | |
1 change: 1 addition & 0 deletions
1
ql/ql/test/queries/style/ValidatePredicateGetReturns/ValidatePredicateGetReturns.qlref
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
queries/style/ValidatePredicateGetReturns.ql |
42 changes: 42 additions & 0 deletions
42
ql/ql/test/queries/style/ValidatePredicateGetReturns/test.qll
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import ql | ||
|
||
// NOT OK -- Predicate starts with "get" but does not return a value | ||
predicate getValue() { none() } | ||
|
||
// OK -- starts with get and returns a value | ||
string getData() { result = "data" } | ||
|
||
// OK -- starts with get but followed by a lowercase letter, probably should be ignored | ||
predicate getterFunction() { none() } | ||
|
||
// OK -- starts with get and returns a value | ||
string getImplementation() { result = "implementation" } | ||
|
||
// OK -- is an alias | ||
predicate getAlias = getImplementation/0; | ||
|
||
// OK -- Starts with "get" but followed by a lowercase letter, probably be ignored | ||
predicate getvalue() { none() } | ||
|
||
// OK -- Does not start with "get", should be ignored | ||
predicate retrieveValue() { none() } | ||
|
||
// NOT OK -- starts with get and does not return value | ||
predicate getImplementation2() { none() } | ||
|
||
// OK -- is an alias | ||
predicate getAlias2 = getImplementation2/0; | ||
|
||
// NOT OK -- starts with as and does not return value | ||
predicate asValue() { none() } | ||
|
||
// OK -- starts with as but followed by a lowercase letter, probably should be ignored | ||
predicate assessment() { none() } | ||
|
||
// OK -- starts with as and returns a value | ||
string asString() { result = "string" } | ||
|
||
// OK -- starts with get and returns a value | ||
HiddenType getInjectableCompositeActionNode() { | ||
exists(HiddenType hidden | result = hidden.toString()) | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Should we instead check that whatever it aliases has a return type?
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 think that's a very reasonable extension of this query, but I don't mind merging as-is, hence approved.
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.
Is this what you have had in mind 01b62ad ?
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.
Yes, thanks for adding.