Skip to content

Commit adddebf

Browse files
committed
Merge branch 'master' of github.com:Semmle/ql into js/more-fs-modules
2 parents a589061 + e1c5449 commit adddebf

File tree

96 files changed

+1590
-214
lines changed

Some content is hidden

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

96 files changed

+1590
-214
lines changed

change-notes/1.24/analysis-java.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ The following changes in version 1.24 affect Java analysis in all applications.
55
## General improvements
66

77
* Alert suppression can now be done with single-line block comments (`/* ... */`) as well as line comments (`// ...`).
8+
* A `Customizations.qll` file has been added to allow customizations of the standard library that apply to all queries.
89

910
## New queries
1011

change-notes/1.24/analysis-javascript.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646
| Polynomial regular expression used on uncontrolled data (`js/polynomial-redos`) | security, external/cwe/cwe-730, external/cwe/cwe-400 | Highlights expensive regular expressions that may be used on malicious input. Results are shown on LGTM by default. |
4747
| Prototype pollution in utility function (`js/prototype-pollution-utility`) | security, external/cwe/cwe-400, external/cwe/cwe-471 | Highlights recursive copying operations that are susceptible to prototype pollution. Results are shown on LGTM by default. |
4848
| Unsafe jQuery plugin (`js/unsafe-jquery-plugin`) | Highlights potential XSS vulnerabilities in unsafely designed jQuery plugins. Results are shown on LGTM by default. |
49+
| Unnecessary use of `cat` process (`js/unnecessary-use-of-cat`) | correctness, security, maintainability | Highlights command executions of `cat` where the fs API should be used instead. Results are shown on LGTM by default. |
50+
4951

5052
## Changes to existing queries
5153

cpp/ql/src/Likely Bugs/Arithmetic/UnsignedGEZero.qll

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,33 @@ class ConstantZero extends Expr {
1515
}
1616
}
1717

18+
/**
19+
* Holds if `candidate` is an expression such that if it's unsigned then we
20+
* want an alert at `ge`.
21+
*/
22+
private predicate lookForUnsignedAt(GEExpr ge, Expr candidate) {
23+
// Base case: `candidate >= 0`
24+
ge.getRightOperand() instanceof ConstantZero and
25+
candidate = ge.getLeftOperand().getFullyConverted() and
26+
// left operand was a signed or unsigned IntegralType before conversions
27+
// (not a pointer, checking a pointer >= 0 is an entirely different mistake)
28+
// (not an enum, as the fully converted type of an enum is compiler dependent
29+
// so checking an enum >= 0 is always reasonable)
30+
ge.getLeftOperand().getUnderlyingType() instanceof IntegralType
31+
or
32+
// Recursive case: `...(largerType)candidate >= 0`
33+
exists(Conversion conversion |
34+
lookForUnsignedAt(ge, conversion) and
35+
candidate = conversion.getExpr() and
36+
conversion.getType().getSize() > candidate.getType().getSize()
37+
)
38+
}
39+
1840
class UnsignedGEZero extends GEExpr {
1941
UnsignedGEZero() {
20-
this.getRightOperand() instanceof ConstantZero and
21-
// left operand was a signed or unsigned IntegralType before conversions
22-
// (not a pointer, checking a pointer >= 0 is an entirely different mistake)
23-
// (not an enum, as the fully converted type of an enum is compiler dependent
24-
// so checking an enum >= 0 is always reasonable)
25-
getLeftOperand().getUnderlyingType() instanceof IntegralType and
2642
exists(Expr ue |
27-
// ue is some conversion of the left operand
28-
ue = getLeftOperand().getConversion*() and
29-
// ue is unsigned
30-
ue.getUnderlyingType().(IntegralType).isUnsigned() and
31-
// ue may be converted to zero or more strictly larger possibly signed types
32-
// before it is fully converted
33-
forall(Expr following | following = ue.getConversion+() |
34-
following.getType().getSize() > ue.getType().getSize()
35-
)
43+
lookForUnsignedAt(this, ue) and
44+
ue.getUnderlyingType().(IntegralType).isUnsigned()
3645
)
3746
}
3847
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import semmle.code.cpp.exprs.Access
1919
class Field extends MemberVariable {
2020
Field() { fieldoffsets(underlyingElement(this), _, _) }
2121

22+
override string getCanonicalQLClass() { result = "Field" }
23+
2224
/**
2325
* Gets the offset of this field in bytes from the start of its declaring
2426
* type (on the machine where facts were extracted).
@@ -84,6 +86,8 @@ class Field extends MemberVariable {
8486
class BitField extends Field {
8587
BitField() { bitfield(underlyingElement(this), _, _) }
8688

89+
override string getCanonicalQLClass() { result = "BitField" }
90+
8791
/**
8892
* Gets the size of this bitfield in bits (on the machine where facts
8993
* were extracted).

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ private import semmle.code.cpp.internal.ResolveClass
2828
* can have multiple declarations.
2929
*/
3030
class Variable extends Declaration, @variable {
31+
override string getCanonicalQLClass() { result = "Variable" }
32+
3133
/** Gets the initializer of this variable, if any. */
3234
Initializer getInitializer() { result.getDeclaration() = this }
3335

@@ -351,6 +353,8 @@ class StackVariable extends LocalScopeVariable {
351353
* A local variable can be declared by a `DeclStmt` or a `ConditionDeclExpr`.
352354
*/
353355
class LocalVariable extends LocalScopeVariable, @localvariable {
356+
override string getCanonicalQLClass() { result = "LocalVariable" }
357+
354358
override string getName() { localvariables(underlyingElement(this), _, result) }
355359

356360
override Type getType() { localvariables(underlyingElement(this), unresolveElement(result), _) }
@@ -396,6 +400,8 @@ class NamespaceVariable extends GlobalOrNamespaceVariable {
396400
NamespaceVariable() {
397401
exists(Namespace n | namespacembrs(unresolveElement(n), underlyingElement(this)))
398402
}
403+
404+
override string getCanonicalQLClass() { result = "NamespaceVariable" }
399405
}
400406

401407
/**
@@ -415,6 +421,8 @@ class NamespaceVariable extends GlobalOrNamespaceVariable {
415421
*/
416422
class GlobalVariable extends GlobalOrNamespaceVariable {
417423
GlobalVariable() { not this instanceof NamespaceVariable }
424+
425+
override string getCanonicalQLClass() { result = "GlobalVariable" }
418426
}
419427

420428
/**
@@ -434,6 +442,8 @@ class GlobalVariable extends GlobalOrNamespaceVariable {
434442
class MemberVariable extends Variable, @membervariable {
435443
MemberVariable() { this.isMember() }
436444

445+
override string getCanonicalQLClass() { result = "MemberVariable" }
446+
437447
/** Holds if this member is private. */
438448
predicate isPrivate() { this.hasSpecifier("private") }
439449

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,20 @@ class Expr extends StmtParent, @expr {
442442
else result = this
443443
}
444444

445+
/**
446+
* Gets the unique non-`Conversion` expression `e` for which
447+
* `this = e.getConversion*()`.
448+
*
449+
* For example, if called on the expression `(int)(char)x`, this predicate
450+
* gets the expression `x`.
451+
*/
452+
Expr getUnconverted() {
453+
not this instanceof Conversion and
454+
result = this
455+
or
456+
result = this.(Conversion).getExpr().getUnconverted()
457+
}
458+
445459
/**
446460
* Gets the type of this expression, after any implicit conversions and explicit casts, and after resolving typedefs.
447461
*

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ private predicate modelTaintToParameter(Function f, int parameterIn, int paramet
267267

268268
/**
269269
* Holds if `chi` is on the chain of chi-instructions for all aliased memory.
270-
* Taint shoud not pass through these instructions since they tend to mix up
270+
* Taint should not pass through these instructions since they tend to mix up
271271
* unrelated objects.
272272
*/
273273
private predicate isChiForAllAliasedMemory(Instruction instr) {

cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,10 +131,7 @@ class ExprNode extends InstructionNode {
131131
* `Conversion`, then the result is that `Conversion`'s non-`Conversion` base
132132
* expression.
133133
*/
134-
Expr getExpr() {
135-
result.getConversion*() = instr.getConvertedResultExpression() and
136-
not result instanceof Conversion
137-
}
134+
Expr getExpr() { result = instr.getUnconvertedResultExpression() }
138135

139136
/**
140137
* Gets the expression corresponding to this node, if any. The returned

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

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ private newtype TOpcode =
8282
TSizedBufferReadSideEffect() or
8383
TSizedBufferMustWriteSideEffect() or
8484
TSizedBufferMayWriteSideEffect() or
85+
TInitializeDynamicAllocation() or
8586
TChi() or
8687
TInlineAsm() or
8788
TUnreached() or
@@ -213,23 +214,28 @@ abstract class IndirectReadOpcode extends IndirectMemoryAccessOpcode {
213214
}
214215

215216
/**
216-
* An opcode that accesses a memory buffer of unknown size.
217+
* An opcode that accesses a memory buffer.
217218
*/
218219
abstract class BufferAccessOpcode extends Opcode {
219220
final override predicate hasAddressOperand() { any() }
220221
}
221222

223+
/**
224+
* An opcode that accesses a memory buffer of unknown size.
225+
*/
226+
abstract class UnsizedBufferAccessOpcode extends BufferAccessOpcode { }
227+
222228
/**
223229
* An opcode that writes to a memory buffer of unknown size.
224230
*/
225-
abstract class BufferWriteOpcode extends BufferAccessOpcode {
231+
abstract class UnsizedBufferWriteOpcode extends UnsizedBufferAccessOpcode {
226232
final override MemoryAccessKind getWriteMemoryAccess() { result instanceof BufferMemoryAccess }
227233
}
228234

229235
/**
230236
* An opcode that reads from a memory buffer of unknown size.
231237
*/
232-
abstract class BufferReadOpcode extends BufferAccessOpcode {
238+
abstract class UnsizedBufferReadOpcode extends UnsizedBufferAccessOpcode {
233239
final override MemoryAccessKind getReadMemoryAccess() { result instanceof BufferMemoryAccess }
234240
}
235241

@@ -261,9 +267,7 @@ abstract class EntireAllocationReadOpcode extends EntireAllocationAccessOpcode {
261267
/**
262268
* An opcode that accesses a memory buffer whose size is determined by a `BufferSizeOperand`.
263269
*/
264-
abstract class SizedBufferAccessOpcode extends Opcode {
265-
final override predicate hasAddressOperand() { any() }
266-
270+
abstract class SizedBufferAccessOpcode extends BufferAccessOpcode {
267271
final override predicate hasBufferSizeOperand() { any() }
268272
}
269273

@@ -666,17 +670,18 @@ module Opcode {
666670
final override string toString() { result = "IndirectMayWriteSideEffect" }
667671
}
668672

669-
class BufferReadSideEffect extends ReadSideEffectOpcode, BufferReadOpcode, TBufferReadSideEffect {
673+
class BufferReadSideEffect extends ReadSideEffectOpcode, UnsizedBufferReadOpcode,
674+
TBufferReadSideEffect {
670675
final override string toString() { result = "BufferReadSideEffect" }
671676
}
672677

673-
class BufferMustWriteSideEffect extends WriteSideEffectOpcode, BufferWriteOpcode,
678+
class BufferMustWriteSideEffect extends WriteSideEffectOpcode, UnsizedBufferWriteOpcode,
674679
TBufferMustWriteSideEffect {
675680
final override string toString() { result = "BufferMustWriteSideEffect" }
676681
}
677682

678-
class BufferMayWriteSideEffect extends WriteSideEffectOpcode, BufferWriteOpcode, MayWriteOpcode,
679-
TBufferMayWriteSideEffect {
683+
class BufferMayWriteSideEffect extends WriteSideEffectOpcode, UnsizedBufferWriteOpcode,
684+
MayWriteOpcode, TBufferMayWriteSideEffect {
680685
final override string toString() { result = "BufferMayWriteSideEffect" }
681686
}
682687

@@ -695,6 +700,11 @@ module Opcode {
695700
final override string toString() { result = "SizedBufferMayWriteSideEffect" }
696701
}
697702

703+
class InitializeDynamicAllocation extends SideEffectOpcode, EntireAllocationWriteOpcode,
704+
TInitializeDynamicAllocation {
705+
final override string toString() { result = "InitializeDynamicAllocation" }
706+
}
707+
698708
class Chi extends Opcode, TChi {
699709
final override string toString() { result = "Chi" }
700710

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) {
176176

177177
/**
178178
* A temporary variable introduced by IR construction. The most common examples are the variable
179-
* generated to hold the return value of afunction, or the variable generated to hold the result of
179+
* generated to hold the return value of a function, or the variable generated to hold the result of
180180
* a condition operator (`a ? b : c`).
181181
*/
182182
class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVariable {

0 commit comments

Comments
 (0)