Skip to content

Commit 96d6115

Browse files
authored
Merge branch 'master' into js/sql-type-tracking
2 parents a9983fd + 0da1e68 commit 96d6115

File tree

119 files changed

+6547
-1087
lines changed

Some content is hidden

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

119 files changed

+6547
-1087
lines changed

change-notes/1.25/analysis-javascript.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## General improvements
44

55
* Support for the following frameworks and libraries has been improved:
6+
- [express](https://www.npmjs.com/package/express)
67
- [fstream](https://www.npmjs.com/package/fstream)
78
- [jGrowl](https://github.com/stanlemon/jGrowl)
89
- [jQuery](https://jquery.com/)
@@ -14,6 +15,8 @@
1415
- [sequelize](https://www.npmjs.com/package/sequelize)
1516
- [spanner](https://www.npmjs.com/package/spanner)
1617
- [sqlite](https://www.npmjs.com/package/sqlite)
18+
- [ssh2](https://www.npmjs.com/package/ssh2)
19+
- [ssh2-streams](https://www.npmjs.com/package/ssh2-streams)
1720

1821
## New queries
1922

@@ -30,10 +33,14 @@
3033
| Misspelled variable name (`js/misspelled-variable-name`) | Message changed | The message for this query now correctly identifies the misspelled variable in additional cases. |
3134
| Uncontrolled data used in path expression (`js/path-injection`) | More results | This query now recognizes additional file system calls. |
3235
| Uncontrolled command line (`js/command-line-injection`) | More results | This query now recognizes additional command execution calls. |
36+
| Client-side URL redirect (`js/client-side-unvalidated-url-redirection`) | Less results | This query now recognizes additional safe patterns of doing URL redirects. |
37+
| Client-side cross-site scripting (`js/xss`) | Less results | This query now recognizes additional safe strings based on URLs. |
38+
| Incomplete URL scheme check (`js/incomplete-url-scheme-check`) | More results | This query now recognizes additional url scheme checks. |
39+
| Prototype pollution in utility function (`js/prototype-pollution-utility`) | More results | This query now recognizes additional utility functions as vulnerable to prototype polution. |
3340
| Expression has no effect (`js/useless-expression`) | Less results | This query no longer flags an expression when that expression is the only content of the containing file. |
3441
| Unknown directive (`js/unknown-directive`) | Less results | This query no longer flags directives generated by the Babel compiler. |
3542
| Code injection (`js/code-injection`) | More results | More potential vulnerabilities involving NoSQL code operators are now recognized. |
36-
| Zip Slip (`js/zipslip`) | More results | This query now recognizes zip-slip vulnerabilities involving links. |
43+
| Zip Slip (`js/zipslip`) | More results | This query now recognizes additional vulnerabilities. |
3744

3845
## Changes to libraries
3946

cpp/ql/src/semmle/code/cpp/exprs/Access.qll

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@ private import semmle.code.cpp.dataflow.EscapesTree
66
/**
77
* A C/C++ access expression. This refers to a function, variable, or enum constant.
88
*/
9-
abstract class Access extends Expr, NameQualifiableElement {
9+
class Access extends Expr, NameQualifiableElement, @access {
10+
// As `@access` is a union type containing `@routineexpr` (which describes function accesses
11+
// that are called), we need to exclude function calls.
12+
Access() { this instanceof @routineexpr implies not iscall(underlyingElement(this), _) }
13+
1014
/** Gets the accessed function, variable, or enum constant. */
11-
abstract Declaration getTarget();
15+
Declaration getTarget() { none() } // overridden in subclasses
1216

1317
override predicate mayBeImpure() { none() }
1418

cpp/ql/src/semmle/code/cpp/exprs/Cast.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ private import semmle.code.cpp.internal.ResolveClass
77
* Instances of this class are not present in the main AST which is navigated by parent/child links. Instead,
88
* instances of this class are attached to nodes in the main AST via special conversion links.
99
*/
10-
abstract class Conversion extends Expr {
10+
class Conversion extends Expr, @conversion {
1111
/** Gets the expression being converted. */
1212
Expr getExpr() { result.getConversion() = this }
1313

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

Lines changed: 84 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,66 @@ private newtype TOperand =
1414
not Construction::isInCycle(useInstr) and
1515
strictcount(Construction::getRegisterOperandDefinition(useInstr, tag)) = 1
1616
} or
17-
TNonPhiMemoryOperand(
18-
Instruction useInstr, MemoryOperandTag tag, Instruction defInstr, Overlap overlap
19-
) {
20-
defInstr = Construction::getMemoryOperandDefinition(useInstr, tag, overlap) and
21-
not Construction::isInCycle(useInstr) and
22-
strictcount(Construction::getMemoryOperandDefinition(useInstr, tag, _)) = 1
17+
TNonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) {
18+
useInstr.getOpcode().hasOperand(tag)
2319
} or
2420
TPhiOperand(
2521
PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap
2622
) {
2723
defInstr = Construction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap)
2824
}
2925

26+
/**
27+
* Base class for all register operands. This is a placeholder for the IPA union type that we will
28+
* eventually use for this purpose.
29+
*/
30+
private class RegisterOperandBase extends TRegisterOperand {
31+
/** Gets a textual representation of this element. */
32+
abstract string toString();
33+
}
34+
35+
/**
36+
* Returns the register operand with the specified parameters.
37+
*/
38+
private RegisterOperandBase registerOperand(
39+
Instruction useInstr, RegisterOperandTag tag, Instruction defInstr
40+
) {
41+
result = TRegisterOperand(useInstr, tag, defInstr)
42+
}
43+
44+
/**
45+
* Base class for all non-Phi memory operands. This is a placeholder for the IPA union type that we
46+
* will eventually use for this purpose.
47+
*/
48+
private class NonPhiMemoryOperandBase extends TNonPhiMemoryOperand {
49+
/** Gets a textual representation of this element. */
50+
abstract string toString();
51+
}
52+
53+
/**
54+
* Returns the non-Phi memory operand with the specified parameters.
55+
*/
56+
private NonPhiMemoryOperandBase nonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) {
57+
result = TNonPhiMemoryOperand(useInstr, tag)
58+
}
59+
60+
/**
61+
* Base class for all Phi operands. This is a placeholder for the IPA union type that we will
62+
* eventually use for this purpose.
63+
*/
64+
private class PhiOperandBase extends TPhiOperand {
65+
abstract string toString();
66+
}
67+
68+
/**
69+
* Returns the Phi operand with the specified parameters.
70+
*/
71+
private PhiOperandBase phiOperand(
72+
Instruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap
73+
) {
74+
result = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap)
75+
}
76+
3077
/**
3178
* A source operand of an `Instruction`. The operand represents a value consumed by the instruction.
3279
*/
@@ -165,8 +212,8 @@ class Operand extends TOperand {
165212
*/
166213
class MemoryOperand extends Operand {
167214
MemoryOperand() {
168-
this = TNonPhiMemoryOperand(_, _, _, _) or
169-
this = TPhiOperand(_, _, _, _)
215+
this instanceof NonPhiMemoryOperandBase or
216+
this instanceof PhiOperandBase
170217
}
171218

172219
/**
@@ -200,18 +247,15 @@ class MemoryOperand extends Operand {
200247
*/
201248
class NonPhiOperand extends Operand {
202249
Instruction useInstr;
203-
Instruction defInstr;
204250
OperandTag tag;
205251

206252
NonPhiOperand() {
207-
this = TRegisterOperand(useInstr, tag, defInstr) or
208-
this = TNonPhiMemoryOperand(useInstr, tag, defInstr, _)
253+
this = registerOperand(useInstr, tag, _) or
254+
this = nonPhiMemoryOperand(useInstr, tag)
209255
}
210256

211257
final override Instruction getUse() { result = useInstr }
212258

213-
final override Instruction getAnyDef() { result = defInstr }
214-
215259
final override string getDumpLabel() { result = tag.getLabel() }
216260

217261
final override int getDumpSortOrder() { result = tag.getSortOrder() }
@@ -222,22 +266,41 @@ class NonPhiOperand extends Operand {
222266
/**
223267
* An operand that consumes a register (non-memory) result.
224268
*/
225-
class RegisterOperand extends NonPhiOperand, TRegisterOperand {
269+
class RegisterOperand extends NonPhiOperand, RegisterOperandBase {
226270
override RegisterOperandTag tag;
271+
Instruction defInstr;
272+
273+
RegisterOperand() { this = registerOperand(useInstr, tag, defInstr) }
274+
275+
final override string toString() { result = tag.toString() }
276+
277+
final override Instruction getAnyDef() { result = defInstr }
227278

228279
final override Overlap getDefinitionOverlap() {
229280
// All register results overlap exactly with their uses.
230281
result instanceof MustExactlyOverlap
231282
}
232283
}
233284

234-
class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOperand {
285+
class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, NonPhiMemoryOperandBase {
235286
override MemoryOperandTag tag;
236-
Overlap overlap;
237287

238-
NonPhiMemoryOperand() { this = TNonPhiMemoryOperand(useInstr, tag, defInstr, overlap) }
288+
NonPhiMemoryOperand() { this = nonPhiMemoryOperand(useInstr, tag) }
239289

240-
final override Overlap getDefinitionOverlap() { result = overlap }
290+
final override string toString() { result = tag.toString() }
291+
292+
final override Instruction getAnyDef() {
293+
result = unique(Instruction defInstr | hasDefinition(defInstr, _))
294+
}
295+
296+
final override Overlap getDefinitionOverlap() { hasDefinition(_, result) }
297+
298+
pragma[noinline]
299+
private predicate hasDefinition(Instruction defInstr, Overlap overlap) {
300+
defInstr = Construction::getMemoryOperandDefinition(useInstr, tag, overlap) and
301+
not Construction::isInCycle(useInstr) and
302+
strictcount(Construction::getMemoryOperandDefinition(useInstr, tag, _)) = 1
303+
}
241304
}
242305

243306
class TypedOperand extends NonPhiMemoryOperand {
@@ -254,8 +317,6 @@ class TypedOperand extends NonPhiMemoryOperand {
254317
*/
255318
class AddressOperand extends RegisterOperand {
256319
override AddressOperandTag tag;
257-
258-
override string toString() { result = "Address" }
259320
}
260321

261322
/**
@@ -264,8 +325,6 @@ class AddressOperand extends RegisterOperand {
264325
*/
265326
class BufferSizeOperand extends RegisterOperand {
266327
override BufferSizeOperandTag tag;
267-
268-
override string toString() { result = "BufferSize" }
269328
}
270329

271330
/**
@@ -274,62 +333,48 @@ class BufferSizeOperand extends RegisterOperand {
274333
*/
275334
class LoadOperand extends TypedOperand {
276335
override LoadOperandTag tag;
277-
278-
override string toString() { result = "Load" }
279336
}
280337

281338
/**
282339
* The source value operand of a `Store` instruction.
283340
*/
284341
class StoreValueOperand extends RegisterOperand {
285342
override StoreValueOperandTag tag;
286-
287-
override string toString() { result = "StoreValue" }
288343
}
289344

290345
/**
291346
* The sole operand of a unary instruction (e.g. `Convert`, `Negate`, `Copy`).
292347
*/
293348
class UnaryOperand extends RegisterOperand {
294349
override UnaryOperandTag tag;
295-
296-
override string toString() { result = "Unary" }
297350
}
298351

299352
/**
300353
* The left operand of a binary instruction (e.g. `Add`, `CompareEQ`).
301354
*/
302355
class LeftOperand extends RegisterOperand {
303356
override LeftOperandTag tag;
304-
305-
override string toString() { result = "Left" }
306357
}
307358

308359
/**
309360
* The right operand of a binary instruction (e.g. `Add`, `CompareEQ`).
310361
*/
311362
class RightOperand extends RegisterOperand {
312363
override RightOperandTag tag;
313-
314-
override string toString() { result = "Right" }
315364
}
316365

317366
/**
318367
* The condition operand of a `ConditionalBranch` or `Switch` instruction.
319368
*/
320369
class ConditionOperand extends RegisterOperand {
321370
override ConditionOperandTag tag;
322-
323-
override string toString() { result = "Condition" }
324371
}
325372

326373
/**
327374
* The operand representing the target function of an `Call` instruction.
328375
*/
329376
class CallTargetOperand extends RegisterOperand {
330377
override CallTargetOperandTag tag;
331-
332-
override string toString() { result = "CallTarget" }
333378
}
334379

335380
/**
@@ -347,43 +392,34 @@ class ArgumentOperand extends RegisterOperand {
347392
*/
348393
class ThisArgumentOperand extends ArgumentOperand {
349394
override ThisArgumentOperandTag tag;
350-
351-
override string toString() { result = "ThisArgument" }
352395
}
353396

354397
/**
355398
* An operand representing an argument to a function call.
356399
*/
357400
class PositionalArgumentOperand extends ArgumentOperand {
358401
override PositionalArgumentOperandTag tag;
359-
int argIndex;
360-
361-
PositionalArgumentOperand() { argIndex = tag.getArgIndex() }
362-
363-
override string toString() { result = "Arg(" + argIndex + ")" }
364402

365403
/**
366404
* Gets the zero-based index of the argument.
367405
*/
368-
final int getIndex() { result = argIndex }
406+
final int getIndex() { result = tag.getArgIndex() }
369407
}
370408

371409
class SideEffectOperand extends TypedOperand {
372410
override SideEffectOperandTag tag;
373-
374-
override string toString() { result = "SideEffect" }
375411
}
376412

377413
/**
378414
* An operand of a `PhiInstruction`.
379415
*/
380-
class PhiInputOperand extends MemoryOperand, TPhiOperand {
416+
class PhiInputOperand extends MemoryOperand, PhiOperandBase {
381417
PhiInstruction useInstr;
382418
Instruction defInstr;
383419
IRBlock predecessorBlock;
384420
Overlap overlap;
385421

386-
PhiInputOperand() { this = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap) }
422+
PhiInputOperand() { this = phiOperand(useInstr, defInstr, predecessorBlock, overlap) }
387423

388424
override string toString() { result = "Phi" }
389425

@@ -413,8 +449,6 @@ class PhiInputOperand extends MemoryOperand, TPhiOperand {
413449
class ChiTotalOperand extends NonPhiMemoryOperand {
414450
override ChiTotalOperandTag tag;
415451

416-
override string toString() { result = "ChiTotal" }
417-
418452
final override MemoryAccessKind getMemoryAccess() { result instanceof ChiTotalMemoryAccess }
419453
}
420454

@@ -424,7 +458,5 @@ class ChiTotalOperand extends NonPhiMemoryOperand {
424458
class ChiPartialOperand extends NonPhiMemoryOperand {
425459
override ChiPartialOperandTag tag;
426460

427-
override string toString() { result = "ChiPartial" }
428-
429461
final override MemoryAccessKind getMemoryAccess() { result instanceof ChiPartialMemoryAccess }
430462
}

cpp/ql/src/semmle/code/cpp/ir/implementation/internal/OperandTag.qll

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,9 @@ PositionalArgumentOperandTag positionalArgumentOperand(int argIndex) {
221221
result = TPositionalArgumentOperand(argIndex)
222222
}
223223

224-
class ChiTotalOperandTag extends MemoryOperandTag, TChiTotalOperand {
224+
abstract class ChiOperandTag extends MemoryOperandTag { }
225+
226+
class ChiTotalOperandTag extends ChiOperandTag, TChiTotalOperand {
225227
final override string toString() { result = "ChiTotal" }
226228

227229
final override int getSortOrder() { result = 13 }
@@ -231,7 +233,7 @@ class ChiTotalOperandTag extends MemoryOperandTag, TChiTotalOperand {
231233

232234
ChiTotalOperandTag chiTotalOperand() { result = TChiTotalOperand() }
233235

234-
class ChiPartialOperandTag extends MemoryOperandTag, TChiPartialOperand {
236+
class ChiPartialOperandTag extends ChiOperandTag, TChiPartialOperand {
235237
final override string toString() { result = "ChiPartial" }
236238

237239
final override int getSortOrder() { result = 14 }

0 commit comments

Comments
 (0)