Skip to content

Commit 4b59c0c

Browse files
authored
Merge branch 'master' into hresult-boolean-qhelp
2 parents 308631e + 2a9abcb commit 4b59c0c

File tree

235 files changed

+9585
-1131
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

235 files changed

+9585
-1131
lines changed

.gitignore

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
# qltest projects and artifacts
99
*/ql/test/**/*.testproj
1010
*/ql/test/**/*.actual
11-
/.vs/slnx.sqlite
12-
/.vs/ql/v15/Browse.VC.opendb
13-
/.vs/ql/v15/Browse.VC.db
14-
/.vs/ProjectSettings.json
1511

12+
# Visual studio temporaries, except a file used by QL4VS
13+
.vs/*
14+
!.vs/VSWorkspaceSettings.json

change-notes/1.19/analysis-cpp.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,17 @@
88
|-----------------------------|-----------|--------------------------------------------------------------------|
99
| Cast between HRESULT and a Boolean type (`cpp/hresult-boolean-conversion`) | external/cwe/cwe-253 | Finds logic errors caused by mistakenly treating the Windows `HRESULT` type as a Boolean instead of testing it with the appropriate macros. Enabled by default. |
1010
| Setting a DACL to `NULL` in a `SECURITY_DESCRIPTOR` (`cpp/unsafe-dacl-security-descriptor`) | external/cwe/cwe-732 | This query finds code that creates world-writable objects on Windows by setting their DACL to `NULL`. Enabled by default. |
11+
| Cast from char* to wchar_t* | security, external/cwe/cwe-704 | Detects potentially dangerous casts from char* to wchar_t*. Enabled by default on LGTM. |
1112

1213
## Changes to existing queries
1314

1415
| **Query** | **Expected impact** | **Change** |
1516
|----------------------------|------------------------|------------------------------------------------------------------|
1617
| Resource not released in destructor | Fewer false positive results | Placement new is now excluded from the query. |
17-
18+
| Missing return statement (`cpp/missing-return`) | Visible by default | The precision of this query has been increased from 'medium' to 'high', which makes it visible by default in LGTM. It was 'medium' in release 1.17 and 1.18 because it had false positives due to an extractor bug that was fixed in 1.18. |
19+
| Call to memory access function may overflow buffer | More correct results | Array indexing with a negative index is now detected by this query. |
20+
| Suspicious add with sizeof | Fewer false positive results | Arithmetic with void pointers (where allowed) is now excluded from this query. |
21+
| Wrong type of arguments to formatting function | Fewer false positive results | False positive results involving typedefs have been removed. Expected argument types are determined more accurately, especially for wide string and pointer types. Custom (non-standard) formatting functions are also identified more accurately. |
1822

1923
## Changes to QL libraries
2024

change-notes/1.19/analysis-javascript.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,30 @@
99
* Support for popular libraries has been improved. Consequently, queries may produce more results on code bases that use the following features:
1010
- file system access, for example through [fs-extra](https://github.com/jprichardson/node-fs-extra) or [globby](https://www.npmjs.com/package/globby)
1111

12+
* The type inference now handles nested imports (that is, imports not appearing at the toplevel). This may yield fewer false-positive results on projects that use this non-standard language feature.
1213

1314
## New queries
1415

1516
| **Query** | **Tags** | **Purpose** |
1617
|-----------------------------------------------|------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
1718
| Enabling Node.js integration for Electron web content renderers (`js/enabling-electron-renderer-node-integration`) | security, frameworks/electron, external/cwe/cwe-094 | Highlights Electron web content renderer preferences with Node.js integration enabled, indicating a violation of [CWE-94](https://cwe.mitre.org/data/definitions/94.html). Results are not shown on LGTM by default. |
18-
| Stored cross-site scripting (`js/stored-xss`) | security, external/cwe/cwe-079, external/cwe/cwe-116 | Highlights uncontrolled stored values flowing into HTML content, indicating a violation of [CWE-079](https://cwe.mitre.org/data/definitions/79.html). Results shown on LGTM by default. |
19+
| Host header poisoning in email generation | security, external/cwe/cwe-640 | Highlights code that generates emails with links that can be hijacked by HTTP host header poisoning, indicating a violation of [CWE-640](https://cwe.mitre.org/data/definitions/640.html). Results shown on LGTM by default. |
1920
| Replacement of a substring with itself (`js/identity-replacement`) | correctness, security, external/cwe/cwe-116 | Highlights string replacements that replace a string with itself, which usually indicates a mistake. Results shown on LGTM by default. |
21+
| Stored cross-site scripting (`js/stored-xss`) | security, external/cwe/cwe-079, external/cwe/cwe-116 | Highlights uncontrolled stored values flowing into HTML content, indicating a violation of [CWE-079](https://cwe.mitre.org/data/definitions/79.html). Results shown on LGTM by default. |
22+
| Unclear precedence of nested operators (`js/unclear-operator-precedence`) | maintainability, correctness, external/cwe/cwe-783 | Highlights nested binary operators whose relative precedence is easy to misunderstand. Results shown on LGTM by default. |
2023

2124
## Changes to existing queries
2225

2326
| **Query** | **Expected impact** | **Change** |
2427
|--------------------------------|----------------------------|----------------------------------------------|
28+
| Useless assignment to local variable | Fewer false-positive results | This rule now recognizes additional ways default values can be set. |
2529
| Regular expression injection | Fewer false-positive results | This rule now identifies calls to `String.prototype.search` with more precision. |
2630
| Unbound event handler receiver | Fewer false-positive results | This rule now recognizes additional ways class methods can be bound. |
2731
| Remote property injection | Fewer results | The precision of this rule has been revised to "medium". Results are no longer shown on LGTM by default. |
2832
| Missing CSRF middleware | Fewer false-positive results | This rule now recognizes additional CSRF protection middlewares. |
33+
| Server-side URL redirect | More results | This rule now recognizes redirection calls in more cases. |
34+
| Whitespace contradicts operator precedence | Fewer false-positive results | This rule no longer flags operators with asymmetric whitespace. |
2935

3036
## Changes to QL libraries
37+
38+
* The flow configuration framework now supports distinguishing and tracking different kinds of taint, specified by an extensible class `FlowLabel` (which can also be referred to by its alias `TaintKind`).

cpp/ql/src/Documentation/CommentedOutCode.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ class CommentBlock extends Comment {
119119
*/
120120
predicate hasLocationInfo(string filepath, int startline, int startcolumn, int endline, int endcolumn) {
121121
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, _, _) and
122-
this.lastComment().getLocation().hasLocationInfo(filepath, _, _, endline, endcolumn)
122+
this.lastComment().getLocation().hasLocationInfo(_, _, _, endline, endcolumn)
123123
}
124124
}
125125

cpp/ql/src/Likely Bugs/Arithmetic/PointlessComparison.ql

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,15 @@ import UnsignedGEZero
2222
// #define PRINTMSG(val,msg) { if (val >= PRINTLEVEL) printf(msg); }
2323
//
2424
// So to reduce the number of false positives, we do not report a result if
25-
// the comparison is in a macro expansion.
25+
// the comparison is in a macro expansion. Similarly for template
26+
// instantiations.
2627
from
2728
ComparisonOperation cmp, SmallSide ss,
2829
float left, float right, boolean value,
2930
string reason
3031
where
3132
not cmp.isInMacroExpansion() and
33+
not cmp.isFromTemplateInstantiation(_) and
3234
reachablePointlessComparison(cmp, left, right, value, ss) and
3335

3436
// a comparison between an enum and zero is always valid because whether

cpp/ql/src/Likely Bugs/Format/NonConstantFormat.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ predicate stringType(Type t, Type charType) {
2525
charType = t.(ArrayType).getBaseType()
2626
) and (
2727
charType.getUnspecifiedType() instanceof CharType or
28-
charType.getUnspecifiedType() instanceof WideCharType
28+
charType.getUnspecifiedType() instanceof Wchar_t
2929
)
3030
)
3131
or

cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.ql

Lines changed: 50 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ private predicate formattingFunctionCallExpectedType(FormattingFunctionCall ffc,
2525
ffc.getTarget() = f and
2626
f.getFormatParameterIndex() = i and
2727
ffc.getArgument(i) = fl and
28-
fl.getConversionType(pos) = expected
28+
fl.getConversionType(pos) = expected and
29+
count(fl.getConversionType(pos)) = 1
2930
)
3031
}
3132

@@ -66,30 +67,15 @@ predicate formatOtherArgType(FormattingFunctionCall ffc, int pos, Type expected,
6667
class ExpectedType extends Type
6768
{
6869
ExpectedType() {
69-
formatArgType(_, _, this, _, _) or
70-
formatOtherArgType(_, _, this, _, _) or
71-
exists(ExpectedType t |
72-
this = t.(PointerType).getBaseType()
70+
exists(Type t |
71+
(
72+
formatArgType(_, _, t, _, _) or
73+
formatOtherArgType(_, _, t, _, _)
74+
) and this = t.getUnspecifiedType()
7375
)
7476
}
7577
}
7678

77-
/**
78-
* Gets an 'interesting' type that can be reached from `t` by removing
79-
* typedefs and specifiers. Note that this does not always mean removing
80-
* all typedefs and specifiers as `Type.getUnspecifiedType()` would, for
81-
* example if the interesting type is itself a typedef.
82-
*/
83-
ExpectedType getAnUnderlyingExpectedType(Type t) {
84-
(
85-
result = t
86-
) or (
87-
result = getAnUnderlyingExpectedType(t.(TypedefType).getBaseType())
88-
) or (
89-
result = getAnUnderlyingExpectedType(t.(SpecifiedType).getBaseType())
90-
)
91-
}
92-
9379
/**
9480
* Holds if it is safe to display a value of type `actual` when `printf`
9581
* expects a value of type `expected`.
@@ -100,59 +86,48 @@ ExpectedType getAnUnderlyingExpectedType(Type t) {
10086
* are converted to `double`.
10187
*/
10288
predicate trivialConversion(ExpectedType expected, Type actual) {
103-
formatArgType(_, _, expected, _, actual) and
104-
105-
exists(Type actualU |
106-
actualU = actual.getUnspecifiedType() and
89+
exists(Type exp, Type act |
90+
formatArgType(_, _, exp, _, act) and
91+
expected = exp.getUnspecifiedType() and
92+
actual = act.getUnspecifiedType()
93+
) and (
10794
(
108-
(
109-
// allow a pointer type to be displayed with `%p`
110-
expected instanceof VoidPointerType and actualU instanceof PointerType
111-
) or (
112-
// allow a function pointer type to be displayed with `%p`
113-
expected instanceof VoidPointerType and actualU instanceof FunctionPointerType and expected.getSize() = actual.getSize()
114-
) or (
115-
// allow an `enum` type to be displayed with `%i`, `%c` etc
116-
expected instanceof IntegralType and actualU instanceof Enum
117-
) or (
118-
// allow any `char *` type to be displayed with `%s`
119-
expected instanceof CharPointerType and actualU instanceof CharPointerType
120-
) or (
121-
// allow `wchar_t *`, or any pointer to an integral type of the same size, to be displayed
122-
// with `%ws`
123-
expected.(PointerType).getBaseType().hasName("wchar_t") and
124-
exists(Wchar_t t |
125-
actual.getUnspecifiedType().(PointerType).getBaseType().(IntegralType).getSize() = t.getSize()
126-
)
127-
) or (
128-
// allow an `int` (or anything promoted to `int`) to be displayed with `%c`
129-
expected instanceof CharType and actualU instanceof IntType
130-
) or (
131-
// allow an `int` (or anything promoted to `int`) to be displayed with `%wc`
132-
expected instanceof Wchar_t and actualU instanceof IntType
133-
) or (
134-
expected instanceof UnsignedCharType and actualU instanceof IntType
135-
) or (
136-
// allow the underlying type of a `size_t` (e.g. `unsigned long`) for
137-
// `%zu`, since this is the type of a `sizeof` expression
138-
expected instanceof Size_t and
139-
actual.getUnspecifiedType() = expected.getUnspecifiedType()
140-
) or (
141-
// allow the underlying type of a `ssize_t` (e.g. `long`) for `%zd`
142-
expected instanceof Ssize_t and
143-
actual.getUnspecifiedType() = expected.getUnspecifiedType()
144-
) or (
145-
// allow any integral type of the same size
146-
// (this permits signedness changes)
147-
expected.(IntegralType).getSize() = actualU.(IntegralType).getSize()
148-
) or (
149-
// allow a pointer to any integral type of the same size
150-
// (this permits signedness changes)
151-
expected.(PointerType).getBaseType().(IntegralType).getSize() = actualU.(PointerType).getBaseType().(IntegralType).getSize()
152-
) or (
153-
// allow expected, or a typedef or specified version of expected
154-
expected = getAnUnderlyingExpectedType(actual)
95+
// allow a pointer type to be displayed with `%p`
96+
expected instanceof VoidPointerType and actual instanceof PointerType
97+
) or (
98+
// allow a function pointer type to be displayed with `%p`
99+
expected instanceof VoidPointerType and actual instanceof FunctionPointerType and expected.getSize() = actual.getSize()
100+
) or (
101+
// allow an `enum` type to be displayed with `%i`, `%c` etc
102+
expected instanceof IntegralType and actual instanceof Enum
103+
) or (
104+
// allow any `char *` type to be displayed with `%s`
105+
expected instanceof CharPointerType and actual instanceof CharPointerType
106+
) or (
107+
// allow `wchar_t *`, or any pointer to an integral type of the same size, to be displayed
108+
// with `%ws`
109+
expected.(PointerType).getBaseType().hasName("wchar_t") and
110+
exists(Wchar_t t |
111+
actual.getUnspecifiedType().(PointerType).getBaseType().(IntegralType).getSize() = t.getSize()
155112
)
113+
) or (
114+
// allow an `int` (or anything promoted to `int`) to be displayed with `%c`
115+
expected instanceof CharType and actual instanceof IntType
116+
) or (
117+
// allow an `int` (or anything promoted to `int`) to be displayed with `%wc`
118+
expected instanceof Wchar_t and actual instanceof IntType
119+
) or (
120+
expected instanceof UnsignedCharType and actual instanceof IntType
121+
) or (
122+
// allow any integral type of the same size
123+
// (this permits signedness changes)
124+
expected.(IntegralType).getSize() = actual.(IntegralType).getSize()
125+
) or (
126+
// allow a pointer to any integral type of the same size
127+
// (this permits signedness changes)
128+
expected.(PointerType).getBaseType().(IntegralType).getSize() = actual.(PointerType).getBaseType().(IntegralType).getSize()
129+
) or (
130+
expected = actual
156131
)
157132
)
158133
}
@@ -164,16 +139,16 @@ int sizeof_IntType() {
164139
exists(IntType it | result = it.getSize())
165140
}
166141

167-
from FormattingFunctionCall ffc, int n, Expr arg, ExpectedType expected, Type actual
142+
from FormattingFunctionCall ffc, int n, Expr arg, Type expected, Type actual
168143
where (
169144
(
170145
formatArgType(ffc, n, expected, arg, actual) and
171-
not trivialConversion(expected, actual)
146+
not trivialConversion(expected.getUnspecifiedType(), actual.getUnspecifiedType())
172147
)
173148
or
174149
(
175150
formatOtherArgType(ffc, n, expected, arg, actual) and
176-
not actual.getUnderlyingType().(IntegralType).getSize() = sizeof_IntType()
151+
not actual.getUnspecifiedType().(IntegralType).getSize() = sizeof_IntType()
177152
)
178153
)
179154
and not arg.isAffectedByMacro()

cpp/ql/src/Likely Bugs/Memory Management/SuspiciousCallToMemset.ql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,13 @@ Type stripType(Type t) {
4141
result = stripType(t.(ArrayType).getBaseType()) or
4242
result = stripType(t.(ReferenceType).getBaseType()) or
4343
result = stripType(t.(SpecifiedType).getBaseType()) or
44+
result = stripType(t.(Decltype).getBaseType()) or
4445
(
4546
not t instanceof TypedefType and
4647
not t instanceof ArrayType and
4748
not t instanceof ReferenceType and
4849
not t instanceof SpecifiedType and
50+
not t instanceof Decltype and
4951
result = t
5052
)
5153
}

cpp/ql/src/Likely Bugs/UseInOwnInitializer.ql

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,21 @@
1111

1212
import cpp
1313

14-
from Initializer init, Variable v, VariableAccess va
15-
where init.getDeclaration() = v
16-
and va.getTarget() = v
17-
and va.getParent*() = init
14+
class VariableAccessInInitializer extends VariableAccess {
15+
Variable var;
16+
Initializer init;
17+
VariableAccessInInitializer() {
18+
init.getDeclaration() = var and
19+
init.getExpr().getAChild*() = this
20+
}
21+
22+
predicate initializesItself(Variable v, Initializer i) {
23+
v = var and i = init and var = this.getTarget()
24+
}
25+
}
26+
27+
from Initializer init, Variable v, VariableAccessInInitializer va
28+
where va.initializesItself(v, init)
1829
and (
1930
va.hasLValueToRValueConversion() or
2031
exists (Assignment assn | assn.getLValue() = va) or

cpp/ql/src/META-INF/MANIFEST.MF

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
22
Bundle-ManifestVersion: 2
33
Bundle-Name: Semmle C/C++ Default Queries
44
Bundle-SymbolicName: com.semmle.plugin.semmlecode.cpp.queries;singleton:=true
5-
Bundle-Version: 1.18.0.qualifier
5+
Bundle-Version: 1.18.1.qualifier
66
Bundle-Vendor: Semmle Ltd.
77
Bundle-ActivationPolicy: lazy
8-
Require-Bundle: com.semmle.plugin.qdt.ui;bundle-version="[1.18.0.qualifier,1.18.0.qualifier]"
8+
Require-Bundle: com.semmle.plugin.qdt.ui;bundle-version="[1.18.1.qualifier,1.18.1.qualifier]"

0 commit comments

Comments
 (0)