Skip to content

Commit 4864e77

Browse files
committed
Merge branch 'master' of git.semmle.com:Semmle/ql into UrlSearch
2 parents 0ebbd80 + 0b62a1d commit 4864e77

File tree

146 files changed

+2475
-540
lines changed

Some content is hidden

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

146 files changed

+2475
-540
lines changed

change-notes/1.24/analysis-javascript.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,14 @@
4242
- [ncp](https://www.npmjs.com/package/ncp)
4343
- [node-dir](https://www.npmjs.com/package/node-dir)
4444
- [path-exists](https://www.npmjs.com/package/path-exists)
45+
- [pg](https://www.npmjs.com/package/pg)
4546
- [react](https://www.npmjs.com/package/react)
4647
- [recursive-readdir](https://www.npmjs.com/package/recursive-readdir)
4748
- [request](https://www.npmjs.com/package/request)
4849
- [rimraf](https://www.npmjs.com/package/rimraf)
4950
- [send](https://www.npmjs.com/package/send)
51+
- [SockJS](https://www.npmjs.com/package/sockjs)
52+
- [SockJS-client](https://www.npmjs.com/package/sockjs-client)
5053
- [typeahead.js](https://www.npmjs.com/package/typeahead.js)
5154
- [vinyl-fs](https://www.npmjs.com/package/vinyl-fs)
5255
- [write-file-atomic](https://www.npmjs.com/package/write-file-atomic)
@@ -82,6 +85,7 @@
8285
| Use of password hash with insufficient computational effort (`js/insufficient-password-hash`) | Fewer false positive results | This query now recognizes additional cases that do not require secure hashing. |
8386
| Useless regular-expression character escape (`js/useless-regexp-character-escape`) | Fewer false positive results | This query now distinguishes escapes in strings and regular expression literals. |
8487
| Identical operands (`js/redundant-operation`) | Fewer results | This query now recognizes cases where the operands change a value using ++/-- expressions. |
88+
| Superfluous trailing arguments (`js/superfluous-trailing-arguments`) | Fewer results | This query now recognizes cases where a function uses the `Function.arguments` value to process a variable number of parameters. |
8589

8690
## Changes to libraries
8791

change-notes/1.24/analysis-python.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Support for Django version 2.x and 3.x
1515

1616
| **Query** | **Expected impact** | **Change** |
1717
|----------------------------|------------------------|------------------------------------------------------------------|
18+
| Uncontrolled command line (`py/command-line-injection`) | More results | We now model the `fabric` and `invoke` pacakges for command execution. |
1819

1920
### Web framework support
2021

cpp/ql/src/semmle/code/cpp/Function.qll

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,16 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
133133
*/
134134
Type getUnspecifiedType() { result = getType().getUnspecifiedType() }
135135

136-
/** Gets the nth parameter of this function. */
136+
/**
137+
* Gets the nth parameter of this function. There is no result for the
138+
* implicit `this` parameter, and there is no `...` varargs pseudo-parameter.
139+
*/
137140
Parameter getParameter(int n) { params(unresolveElement(result), underlyingElement(this), n, _) }
138141

139-
/** Gets a parameter of this function. */
142+
/**
143+
* Gets a parameter of this function. There is no result for the implicit
144+
* `this` parameter, and there is no `...` varargs pseudo-parameter.
145+
*/
140146
Parameter getAParameter() { params(unresolveElement(result), underlyingElement(this), _, _) }
141147

142148
/**

cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,14 @@ private DataFlow::Node getNodeForSource(Expr source) {
6060
(
6161
result = DataFlow::exprNode(source)
6262
or
63-
result = DataFlow::definitionByReferenceNode(source)
63+
// Some of the sources in `isUserInput` are intended to match the value of
64+
// an expression, while others (those modeled below) are intended to match
65+
// the taint that propagates out of an argument, like the `char *` argument
66+
// to `gets`. It's impossible here to tell which is which, but the "access
67+
// to argv" source is definitely not intended to match an output argument,
68+
// and it causes false positives if we let it.
69+
result = DataFlow::definitionByReferenceNode(source) and
70+
not argv(source.(VariableAccess).getTarget())
6471
)
6572
}
6673

@@ -183,7 +190,7 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) {
183190
i2.(UnaryInstruction).getUnary() = i1
184191
or
185192
i2.(ChiInstruction).getPartial() = i1 and
186-
not isChiForAllAliasedMemory(i2)
193+
not i2.isResultConflated()
187194
or
188195
exists(BinaryInstruction bin |
189196
bin = i2 and
@@ -276,19 +283,6 @@ private predicate modelTaintToParameter(Function f, int parameterIn, int paramet
276283
)
277284
}
278285

279-
/**
280-
* Holds if `chi` is on the chain of chi-instructions for all aliased memory.
281-
* Taint should not pass through these instructions since they tend to mix up
282-
* unrelated objects.
283-
*/
284-
private predicate isChiForAllAliasedMemory(Instruction instr) {
285-
instr.(ChiInstruction).getTotal() instanceof AliasedDefinitionInstruction
286-
or
287-
isChiForAllAliasedMemory(instr.(ChiInstruction).getTotal())
288-
or
289-
isChiForAllAliasedMemory(instr.(PhiInstruction).getAnInputOperand().getAnyDef())
290-
}
291-
292286
private predicate modelTaintToReturnValue(Function f, int parameterIn) {
293287
// Taint flow from parameter to return value
294288
exists(FunctionInput modelIn, FunctionOutput modelOut |

cpp/ql/src/semmle/code/cpp/ir/implementation/IRConfiguration.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ class IRConfiguration extends TIRConfiguration {
1616
* Holds if IR should be created for function `func`. By default, holds for all functions.
1717
*/
1818
predicate shouldCreateIRForFunction(Language::Function func) { any() }
19+
20+
predicate shouldEvaluateDebugStringsForFunction(Language::Function func) { any() }
1921
}
2022

2123
private newtype TIREscapeAnalysisConfiguration = MkIREscapeAnalysisConfiguration()

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRBlock.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ class IRBlockBase extends TIRBlock {
2727
* by debugging and printing code only.
2828
*/
2929
int getDisplayIndex() {
30+
exists(IRConfiguration::IRConfiguration config |
31+
config.shouldEvaluateDebugStringsForFunction(this.getEnclosingFunction())
32+
) and
3033
this =
3134
rank[result + 1](IRBlock funcBlock |
3235
funcBlock.getEnclosingFunction() = getEnclosingFunction()

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRSanity.qll

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import IRTypeSanity // module is in IRType.qll
55
module InstructionSanity {
66
private import internal.InstructionImports as Imports
77
private import Imports::OperandTag
8+
private import Imports::Overlap
89
private import internal.IRInternal
910

1011
/**
@@ -272,4 +273,48 @@ module InstructionSanity {
272273
func = switchInstr.getEnclosingIRFunction() and
273274
funcText = Language::getIdentityString(func.getFunction())
274275
}
276+
277+
/**
278+
* Holds if `instr` is on the chain of chi/phi instructions for all aliased
279+
* memory.
280+
*/
281+
private predicate isOnAliasedDefinitionChain(Instruction instr) {
282+
instr instanceof AliasedDefinitionInstruction
283+
or
284+
isOnAliasedDefinitionChain(instr.(ChiInstruction).getTotal())
285+
or
286+
isOnAliasedDefinitionChain(instr.(PhiInstruction).getAnInputOperand().getAnyDef())
287+
}
288+
289+
private predicate shouldBeConflated(Instruction instr) {
290+
isOnAliasedDefinitionChain(instr)
291+
or
292+
instr instanceof UnmodeledDefinitionInstruction
293+
or
294+
instr.getOpcode() instanceof Opcode::InitializeNonLocal
295+
}
296+
297+
query predicate notMarkedAsConflated(Instruction instr) {
298+
shouldBeConflated(instr) and
299+
not instr.isResultConflated()
300+
}
301+
302+
query predicate wronglyMarkedAsConflated(Instruction instr) {
303+
instr.isResultConflated() and
304+
not shouldBeConflated(instr)
305+
}
306+
307+
query predicate invalidOverlap(
308+
MemoryOperand useOperand, string message, IRFunction func, string funcText
309+
) {
310+
exists(Overlap overlap |
311+
overlap = useOperand.getDefinitionOverlap() and
312+
overlap instanceof MayPartiallyOverlap and
313+
message =
314+
"MemoryOperand '" + useOperand.toString() + "' has a `getDefinitionOverlap()` of '" +
315+
overlap.toString() + "'." and
316+
func = useOperand.getEnclosingIRFunction() and
317+
funcText = Language::getIdentityString(func.getFunction())
318+
)
319+
}
275320
}

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ private import Imports::OperandTag
1515
* `File` and line number. Used for assigning register names when printing IR.
1616
*/
1717
private Instruction getAnInstructionAtLine(IRFunction irFunc, Language::File file, int line) {
18+
exists(IRConfiguration::IRConfiguration config |
19+
config.shouldEvaluateDebugStringsForFunction(irFunc.getFunction())
20+
) and
1821
exists(Language::Location ___location |
1922
irFunc = result.getEnclosingIRFunction() and
2023
___location = result.getLocation() and
@@ -39,13 +42,20 @@ class Instruction extends Construction::TInstruction {
3942
result = getResultString() + " = " + getOperationString() + " " + getOperandsString()
4043
}
4144

45+
private predicate shouldGenerateDumpStrings() {
46+
exists(IRConfiguration::IRConfiguration config |
47+
config.shouldEvaluateDebugStringsForFunction(this.getEnclosingFunction())
48+
)
49+
}
50+
4251
/**
4352
* Gets a string describing the operation of this instruction. This includes
4453
* the opcode and the immediate value, if any. For example:
4554
*
4655
* VariableAddress[x]
4756
*/
4857
final string getOperationString() {
58+
shouldGenerateDumpStrings() and
4959
if exists(getImmediateString())
5060
then result = getOperationPrefix() + getOpcode().toString() + "[" + getImmediateString() + "]"
5161
else result = getOperationPrefix() + getOpcode().toString()
@@ -57,10 +67,12 @@ class Instruction extends Construction::TInstruction {
5767
string getImmediateString() { none() }
5868

5969
private string getOperationPrefix() {
70+
shouldGenerateDumpStrings() and
6071
if this instanceof SideEffectInstruction then result = "^" else result = ""
6172
}
6273

6374
private string getResultPrefix() {
75+
shouldGenerateDumpStrings() and
6476
if getResultIRType() instanceof IRVoidType
6577
then result = "v"
6678
else
@@ -74,6 +86,7 @@ class Instruction extends Construction::TInstruction {
7486
* used by debugging and printing code only.
7587
*/
7688
int getDisplayIndexInBlock() {
89+
shouldGenerateDumpStrings() and
7790
exists(IRBlock block |
7891
this = block.getInstruction(result)
7992
or
@@ -87,6 +100,7 @@ class Instruction extends Construction::TInstruction {
87100
}
88101

89102
private int getLineRank() {
103+
shouldGenerateDumpStrings() and
90104
this =
91105
rank[result](Instruction instr |
92106
instr =
@@ -105,6 +119,7 @@ class Instruction extends Construction::TInstruction {
105119
* Example: `r1_1`
106120
*/
107121
string getResultId() {
122+
shouldGenerateDumpStrings() and
108123
result = getResultPrefix() + getAST().getLocation().getStartLine() + "_" + getLineRank()
109124
}
110125

@@ -116,6 +131,7 @@ class Instruction extends Construction::TInstruction {
116131
* Example: `r1_1(int*)`
117132
*/
118133
final string getResultString() {
134+
shouldGenerateDumpStrings() and
119135
result = getResultId() + "(" + getResultLanguageType().getDumpString() + ")"
120136
}
121137

@@ -126,6 +142,7 @@ class Instruction extends Construction::TInstruction {
126142
* Example: `func:r3_4, this:r3_5`
127143
*/
128144
string getOperandsString() {
145+
shouldGenerateDumpStrings() and
129146
result =
130147
concat(Operand operand |
131148
operand = getAnOperand()
@@ -321,6 +338,17 @@ class Instruction extends Construction::TInstruction {
321338
Construction::hasModeledMemoryResult(this)
322339
}
323340

341+
/**
342+
* Holds if this is an instruction with a memory result that represents a
343+
* conflation of more than one memory allocation.
344+
*
345+
* This happens in practice when dereferencing a pointer that cannot be
346+
* tracked back to a single local allocation. Such memory is instead modeled
347+
* as originating on the `AliasedDefinitionInstruction` at the entry of the
348+
* function.
349+
*/
350+
final predicate isResultConflated() { Construction::hasConflatedMemoryResult(this) }
351+
324352
/**
325353
* Gets the successor of this instruction along the control flow edge
326354
* specified by `kind`.

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,8 @@ class PositionalArgumentOperand extends ArgumentOperand {
384384

385385
class SideEffectOperand extends TypedOperand {
386386
override SideEffectOperandTag tag;
387+
388+
override string toString() { result = "SideEffect" }
387389
}
388390

389391
/**

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.qll

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,19 @@ class PrintIRConfiguration extends TPrintIRConfiguration {
1818
predicate shouldPrintFunction(Language::Function func) { any() }
1919
}
2020

21-
private predicate shouldPrintFunction(Language::Function func) {
22-
exists(PrintIRConfiguration config | config.shouldPrintFunction(func))
23-
}
24-
2521
/**
26-
* Override of `IRConfiguration` to only create IR for the functions that are to be dumped.
22+
* Override of `IRConfiguration` to only evaluate debug strings for the functions that are to be dumped.
2723
*/
2824
private class FilteredIRConfiguration extends IRConfiguration {
29-
override predicate shouldCreateIRForFunction(Language::Function func) {
25+
override predicate shouldEvaluateDebugStringsForFunction(Language::Function func) {
3026
shouldPrintFunction(func)
3127
}
3228
}
3329

30+
private predicate shouldPrintFunction(Language::Function func) {
31+
exists(PrintIRConfiguration config | config.shouldPrintFunction(func))
32+
}
33+
3434
private string getAdditionalInstructionProperty(Instruction instr, string key) {
3535
exists(IRPropertyProvider provider | result = provider.getInstructionProperty(instr, key))
3636
}

0 commit comments

Comments
 (0)