Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- "Function-like macros"
- The parameter list of variadic macros previously included the ellipsis in name of the final parameter, potentially leading to incorrect analysis. This has been corrected.
- The parameter list of function-like macros with no parameters (i.e. `MACRO()`) was interpreted in a shared library as having a single parameter with an empty name. This does not seem to have had an impact on any existing queries, but has been fixed to correctly show no parameters.
446 changes: 446 additions & 0 deletions cpp/common/src/codingstandards/cpp/Identifiers.qll

Large diffs are not rendered by default.

11 changes: 9 additions & 2 deletions cpp/common/src/codingstandards/cpp/Macro.qll
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
import cpp

/**
* Macros with a parameter
* Macros with parentheses, e.g. `#define MACRO(x) (x * 2)`.
*
* Note that this includes macros with empty parameter lists, e.g. `#define MACRO() 42`.
*/
class FunctionLikeMacro extends Macro {
FunctionLikeMacro() { this.getHead().regexpMatch("[_a-zA-Z0-9]+\\s*\\([^\\)]*?\\)") }

string getParameter(int i) {
result =
this.getHead().regexpCapture("[_a-zA-Z0-9]+\\s*\\(([^\\)]*)\\)", 1).splitAt(",", i).trim()
this.getHead()
.regexpCapture("[_a-zA-Z0-9]+\\s*\\(([^\\)]*)\\)", 1)
.splitAt(",", i)
.trim()
.replaceAll("...", "") and
not result = ""
}

string getAParameter() { result = getParameter(_) }
Expand Down
65 changes: 65 additions & 0 deletions cpp/common/src/codingstandards/cpp/Unicode.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import codeql.util.Numbers

/**
* Provides properties of a Unicode code point, where the property is of 'enumeration', 'catalog',
* or 'string-valued' type, however, the only supported property is `NFC_QC`.
*
* For example, `Block` is an enumeration property, `Line_Break` is a catalog property, and
* `Uppercase_Mapping` is a string-valued property.
*
* For boolean properties, see `unicodeHasBooleanProperty`, and for numeric properties, see
* `unicodeHasNumericProperty`.
*/
extensible predicate unicodeHasProperty(int codePoint, string propertyName, string propertyValue);

/**
* Holds when the Unicode code point's boolean property of the given name is true.
*
* For example, `Alphabetic` is a boolean property that can be true or false for a code point.
*
* For other types of properties, see `unicodeHasProperty`.
*/
extensible predicate unicodeHasBooleanProperty(int codePoint, string propertyName);

bindingset[input]
int unescapedCodePointAt(string input, int index) {
exists(string match |
match = input.regexpFind("(\\\\u[0-9a-fA-F]{4}|.)", index, _) and
if match.matches("\\u%")
then result = parseHexInt(match.substring(2, match.length()))
else result = match.codePointAt(0)
)
}

bindingset[input]
string unescapeUnicode(string input) {
result =
concat(int code, int idx |
code = unescapedCodePointAt(input, idx)
|
code.toUnicode() order by idx
)
}

bindingset[id]
predicate nonUax44IdentifierCodepoint(string id, int index) {
exists(int codePoint |
codePoint = id.codePointAt(index) and
(
not unicodeHasBooleanProperty(codePoint, "XID_Start") and
not unicodeHasBooleanProperty(codePoint, "XID_Continue")
or
index = 0 and
not unicodeHasBooleanProperty(codePoint, "XID_Start")
)
)
}

bindingset[id]
predicate nonNfcNormalizedCodepoint(string id, int index, string noOrMaybe) {
exists(int codePoint |
codePoint = id.codePointAt(index) and
unicodeHasProperty(codePoint, "NFC_QC", noOrMaybe) and
noOrMaybe = ["N", "M"]
)
}
26 changes: 26 additions & 0 deletions cpp/common/src/codingstandards/cpp/exclusions/cpp/Naming2.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/
import cpp
import RuleMetadata
import codingstandards.cpp.exclusions.RuleMetadata

newtype Naming2Query = TPoorlyFormedIdentifierQuery()

predicate isNaming2QueryMetadata(Query query, string queryId, string ruleId, string category) {
query =
// `Query` instance for the `poorlyFormedIdentifier` query
Naming2Package::poorlyFormedIdentifierQuery() and
queryId =
// `@id` for the `poorlyFormedIdentifier` query
"cpp/misra/poorly-formed-identifier" and
ruleId = "RULE-5-10-1" and
category = "required"
}

module Naming2Package {
Query poorlyFormedIdentifierQuery() {
//autogenerate `Query` type
result =
// `Query` type for `poorlyFormedIdentifier` query
TQueryCPP(TNaming2PackageQuery(TPoorlyFormedIdentifierQuery()))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import Loops
import Macros
import MoveForward
import Naming
import Naming2
import Null
import OperatorInvariants
import Operators
Expand Down Expand Up @@ -90,6 +91,7 @@ newtype TCPPQuery =
TMacrosPackageQuery(MacrosQuery q) or
TMoveForwardPackageQuery(MoveForwardQuery q) or
TNamingPackageQuery(NamingQuery q) or
TNaming2PackageQuery(Naming2Query q) or
TNullPackageQuery(NullQuery q) or
TOperatorInvariantsPackageQuery(OperatorInvariantsQuery q) or
TOperatorsPackageQuery(OperatorsQuery q) or
Expand Down Expand Up @@ -145,6 +147,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId, string cat
isMacrosQueryMetadata(query, queryId, ruleId, category) or
isMoveForwardQueryMetadata(query, queryId, ruleId, category) or
isNamingQueryMetadata(query, queryId, ruleId, category) or
isNaming2QueryMetadata(query, queryId, ruleId, category) or
isNullQueryMetadata(query, queryId, ruleId, category) or
isOperatorInvariantsQueryMetadata(query, queryId, ruleId, category) or
isOperatorsQueryMetadata(query, queryId, ruleId, category) or
Expand Down
Loading
Loading