mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Merge pull request #1634 from aibaars/cookbook
Approved by aschackmull, dave-bartolomeo, hvitved, markshannon, xiemaisi, yh-semmle
This commit is contained in:
1
cpp/ql/examples/queries.xml
Normal file
1
cpp/ql/examples/queries.xml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<queries language="cpp"/>
|
||||||
16
cpp/ql/examples/snippets/addressof.ql
Normal file
16
cpp/ql/examples/snippets/addressof.ql
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* @id cpp/examples/addressof
|
||||||
|
* @name Address of reference variable
|
||||||
|
* @description Finds address-of expressions (`&`) that take the address
|
||||||
|
* of a reference variable
|
||||||
|
* @tags addressof
|
||||||
|
* reference
|
||||||
|
*/
|
||||||
|
|
||||||
|
import cpp
|
||||||
|
|
||||||
|
from AddressOfExpr addr, VariableAccess access
|
||||||
|
where
|
||||||
|
access = addr.getOperand() and
|
||||||
|
access.getTarget().getType() instanceof ReferenceType
|
||||||
|
select addr
|
||||||
17
cpp/ql/examples/snippets/arrayaccess.ql
Normal file
17
cpp/ql/examples/snippets/arrayaccess.ql
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/**
|
||||||
|
* @id cpp/examples/arrayaccess
|
||||||
|
* @name Array access
|
||||||
|
* @description Finds array access expressions with an index expression
|
||||||
|
* consisting of a postfix increment (`++`) expression.
|
||||||
|
* @tags array
|
||||||
|
* access
|
||||||
|
* index
|
||||||
|
* postfix
|
||||||
|
* increment
|
||||||
|
*/
|
||||||
|
|
||||||
|
import cpp
|
||||||
|
|
||||||
|
from ArrayExpr a
|
||||||
|
where a.getArrayOffset() instanceof PostfixIncrExpr
|
||||||
|
select a
|
||||||
16
cpp/ql/examples/snippets/castexpr.ql
Normal file
16
cpp/ql/examples/snippets/castexpr.ql
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* @id cpp/examples/castexpr
|
||||||
|
* @name Cast expressions
|
||||||
|
* @description Finds casts from a floating point type to an integer type
|
||||||
|
* @tags cast
|
||||||
|
* integer
|
||||||
|
* float
|
||||||
|
* type
|
||||||
|
*/
|
||||||
|
|
||||||
|
import cpp
|
||||||
|
|
||||||
|
from Cast c
|
||||||
|
where c.getExpr().getType() instanceof FloatingPointType
|
||||||
|
and c.getType() instanceof IntegralType
|
||||||
|
select c
|
||||||
15
cpp/ql/examples/snippets/catch_exception.ql
Normal file
15
cpp/ql/examples/snippets/catch_exception.ql
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* @id cpp/examples/catch-exception
|
||||||
|
* @name Catch exception
|
||||||
|
* @description Finds places where we catch exceptions of type `parse_error`
|
||||||
|
* @tags catch
|
||||||
|
* try
|
||||||
|
* exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
import cpp
|
||||||
|
|
||||||
|
from CatchBlock catch
|
||||||
|
// `stripType` converts `const parse_error &` to `parse_error`.
|
||||||
|
where catch.getParameter().getType().stripType().hasName("parse_error")
|
||||||
|
select catch
|
||||||
16
cpp/ql/examples/snippets/constructor_call.ql
Normal file
16
cpp/ql/examples/snippets/constructor_call.ql
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* @id cpp/examples/constructor-call
|
||||||
|
* @name Call to constructor
|
||||||
|
* @description Finds places where we call `new MyClass(...)`
|
||||||
|
* @tags call
|
||||||
|
* constructor
|
||||||
|
* new
|
||||||
|
*/
|
||||||
|
|
||||||
|
import cpp
|
||||||
|
|
||||||
|
from NewExpr new, Constructor c
|
||||||
|
where
|
||||||
|
c = new.getInitializer().(ConstructorCall).getTarget() and
|
||||||
|
c.getName() = "MyClass"
|
||||||
|
select new
|
||||||
20
cpp/ql/examples/snippets/derives_from_class.ql
Normal file
20
cpp/ql/examples/snippets/derives_from_class.ql
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/**
|
||||||
|
* @id cpp/examples/derives-from-class
|
||||||
|
* @name Class derives from
|
||||||
|
* @description Finds classes that derive from `std::exception`
|
||||||
|
* @tags base
|
||||||
|
* class
|
||||||
|
* derive
|
||||||
|
* inherit
|
||||||
|
* override
|
||||||
|
* subtype
|
||||||
|
* supertype
|
||||||
|
*/
|
||||||
|
|
||||||
|
import cpp
|
||||||
|
|
||||||
|
from Class type
|
||||||
|
where
|
||||||
|
type.getABaseClass+().hasName("exception") and
|
||||||
|
type.getNamespace().getName() = "std"
|
||||||
|
select type
|
||||||
14
cpp/ql/examples/snippets/emptyblock.ql
Normal file
14
cpp/ql/examples/snippets/emptyblock.ql
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* @id cpp/examples/emptyblock
|
||||||
|
* @name Empty blocks
|
||||||
|
* @description Finds empty block statements
|
||||||
|
* @tags empty
|
||||||
|
* block
|
||||||
|
* statement
|
||||||
|
*/
|
||||||
|
|
||||||
|
import cpp
|
||||||
|
|
||||||
|
from Block blk
|
||||||
|
where blk.getNumStmt() = 0
|
||||||
|
select blk
|
||||||
17
cpp/ql/examples/snippets/emptythen.ql
Normal file
17
cpp/ql/examples/snippets/emptythen.ql
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/**
|
||||||
|
* @id cpp/examples/emptythen
|
||||||
|
* @name If statements with empty then branch
|
||||||
|
* @description Finds `if` statements where the `then` branch is
|
||||||
|
* an empty block statement
|
||||||
|
* @tags if
|
||||||
|
* then
|
||||||
|
* empty
|
||||||
|
* conditional
|
||||||
|
* branch
|
||||||
|
*/
|
||||||
|
|
||||||
|
import cpp
|
||||||
|
|
||||||
|
from IfStmt i
|
||||||
|
where i.getThen().(Block).getNumStmt() = 0
|
||||||
|
select i
|
||||||
18
cpp/ql/examples/snippets/eq_true.ql
Normal file
18
cpp/ql/examples/snippets/eq_true.ql
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* @id cpp/examples/eq-true
|
||||||
|
* @name Equality test on boolean
|
||||||
|
* @description Finds tests like `==true`, `!=true`
|
||||||
|
* @tags equal
|
||||||
|
* comparison
|
||||||
|
* test
|
||||||
|
* boolean
|
||||||
|
*/
|
||||||
|
|
||||||
|
import cpp
|
||||||
|
|
||||||
|
from EqualityOperation eq, Expr trueExpr
|
||||||
|
where
|
||||||
|
trueExpr = eq.getAnOperand() and
|
||||||
|
trueExpr.getType() instanceof BoolType and
|
||||||
|
trueExpr.getValue().toInt() = 1
|
||||||
|
select eq
|
||||||
16
cpp/ql/examples/snippets/field_access.ql
Normal file
16
cpp/ql/examples/snippets/field_access.ql
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* @id cpp/examples/field-access
|
||||||
|
* @name Access of field
|
||||||
|
* @description Finds reads of `aDate` (defined on class `Order`)
|
||||||
|
* @tags access
|
||||||
|
* field
|
||||||
|
* read
|
||||||
|
*/
|
||||||
|
|
||||||
|
import cpp
|
||||||
|
|
||||||
|
from Field f, FieldAccess access
|
||||||
|
where f.hasName("aDate")
|
||||||
|
and f.getDeclaringType().hasName("Order")
|
||||||
|
and f = access.getTarget()
|
||||||
|
select access
|
||||||
18
cpp/ql/examples/snippets/function_call.ql
Normal file
18
cpp/ql/examples/snippets/function_call.ql
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* @id cpp/examples/function-call
|
||||||
|
* @name Call to function
|
||||||
|
* @description Finds calls to `std::map<...>::find()`
|
||||||
|
* @tags call
|
||||||
|
* function
|
||||||
|
* method
|
||||||
|
*/
|
||||||
|
|
||||||
|
import cpp
|
||||||
|
|
||||||
|
from FunctionCall call, Function fcn
|
||||||
|
where
|
||||||
|
call.getTarget() = fcn and
|
||||||
|
fcn.getDeclaringType().getSimpleName() = "map" and
|
||||||
|
fcn.getDeclaringType().getNamespace().getName() = "std" and
|
||||||
|
fcn.hasName("find")
|
||||||
|
select call
|
||||||
15
cpp/ql/examples/snippets/integer_literal.ql
Normal file
15
cpp/ql/examples/snippets/integer_literal.ql
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* @id cpp/examples/integer-literal
|
||||||
|
* @name Integer literal
|
||||||
|
* @description Finds places where we use the integer literal `2`
|
||||||
|
* @tags integer
|
||||||
|
* literal
|
||||||
|
*/
|
||||||
|
|
||||||
|
import cpp
|
||||||
|
|
||||||
|
from Literal literal
|
||||||
|
where
|
||||||
|
literal.getType() instanceof IntType and
|
||||||
|
literal.getValue().toInt() = 2
|
||||||
|
select literal
|
||||||
17
cpp/ql/examples/snippets/mutualrecursion.ql
Normal file
17
cpp/ql/examples/snippets/mutualrecursion.ql
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/**
|
||||||
|
* @id cpp/examples/mutualrecursion
|
||||||
|
* @name Mutual recursion
|
||||||
|
* @description Finds pairs of functions that call each other
|
||||||
|
* @tags function
|
||||||
|
* method
|
||||||
|
* recursion
|
||||||
|
*/
|
||||||
|
|
||||||
|
import cpp
|
||||||
|
|
||||||
|
from Function m, Function n
|
||||||
|
where
|
||||||
|
exists(FunctionCall c | c.getEnclosingFunction() = m and c.getTarget() = n) and
|
||||||
|
exists(FunctionCall c | c.getEnclosingFunction() = n and c.getTarget() = m) and
|
||||||
|
m != n
|
||||||
|
select m, n
|
||||||
18
cpp/ql/examples/snippets/override_method.ql
Normal file
18
cpp/ql/examples/snippets/override_method.ql
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* @id cpp/examples/override-method
|
||||||
|
* @name Override of method
|
||||||
|
* @description Finds methods that override `std::exception::what()`
|
||||||
|
* @tags function
|
||||||
|
* method
|
||||||
|
* override
|
||||||
|
*/
|
||||||
|
|
||||||
|
import cpp
|
||||||
|
|
||||||
|
from MemberFunction override, MemberFunction base
|
||||||
|
where
|
||||||
|
base.getName() = "what" and
|
||||||
|
base.getDeclaringType().getName() = "exception" and
|
||||||
|
base.getDeclaringType().getNamespace().getName() = "std" and
|
||||||
|
override.overrides+(base)
|
||||||
|
select override
|
||||||
14
cpp/ql/examples/snippets/returnstatement.ql
Normal file
14
cpp/ql/examples/snippets/returnstatement.ql
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* @id cpp/examples/returnstatement
|
||||||
|
* @name Return statements
|
||||||
|
* @description Finds return statements that return `0`
|
||||||
|
* @tags return
|
||||||
|
* statement
|
||||||
|
* literal
|
||||||
|
*/
|
||||||
|
|
||||||
|
import cpp
|
||||||
|
|
||||||
|
from ReturnStmt r
|
||||||
|
where r.getExpr().(Literal).getValue().toInt() = 0
|
||||||
|
select r
|
||||||
13
cpp/ql/examples/snippets/singletonblock.ql
Normal file
13
cpp/ql/examples/snippets/singletonblock.ql
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* @id cpp/examples/singletonblock
|
||||||
|
* @name Singleton blocks
|
||||||
|
* @description Finds block statements containing a single statement
|
||||||
|
* @tags block
|
||||||
|
* statement
|
||||||
|
*/
|
||||||
|
|
||||||
|
import cpp
|
||||||
|
|
||||||
|
from Block b
|
||||||
|
where b.getNumStmt() = 1
|
||||||
|
select b
|
||||||
17
cpp/ql/examples/snippets/switchcase.ql
Normal file
17
cpp/ql/examples/snippets/switchcase.ql
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/**
|
||||||
|
* @id cpp/examples/switchcase
|
||||||
|
* @name Switch statement case missing
|
||||||
|
* @description Finds switch statements with a missing enum constant case
|
||||||
|
* and no default case
|
||||||
|
* @tags switch
|
||||||
|
* case
|
||||||
|
* enum
|
||||||
|
*/
|
||||||
|
|
||||||
|
import cpp
|
||||||
|
|
||||||
|
from EnumSwitch es, EnumConstant ec
|
||||||
|
where
|
||||||
|
ec = es.getAMissingCase() and
|
||||||
|
not es.hasDefaultCase()
|
||||||
|
select es, ec
|
||||||
15
cpp/ql/examples/snippets/ternaryconditional.ql
Normal file
15
cpp/ql/examples/snippets/ternaryconditional.ql
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* @id cpp/examples/ternaryconditional
|
||||||
|
* @name Conditional expressions
|
||||||
|
* @description Finds conditional expressions of the form `... ? ... : ...`
|
||||||
|
* where the types of the resulting expressions differ
|
||||||
|
* @tags conditional
|
||||||
|
* ternary
|
||||||
|
* type
|
||||||
|
*/
|
||||||
|
|
||||||
|
import cpp
|
||||||
|
|
||||||
|
from ConditionalExpr e
|
||||||
|
where e.getThen().getType() != e.getElse().getType()
|
||||||
|
select e
|
||||||
15
cpp/ql/examples/snippets/throw_exception.ql
Normal file
15
cpp/ql/examples/snippets/throw_exception.ql
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* @id cpp/examples/throw-exception
|
||||||
|
* @name Throw exception of type
|
||||||
|
* @description Finds places where we throw `parse_error` or one of its sub-types
|
||||||
|
* @tags base
|
||||||
|
* class
|
||||||
|
* throw
|
||||||
|
* exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
import cpp
|
||||||
|
|
||||||
|
from ThrowExpr throw
|
||||||
|
where throw.getType().(Class).getABaseClass*().getName() = "parse_error"
|
||||||
|
select throw
|
||||||
14
cpp/ql/examples/snippets/todocomment.ql
Normal file
14
cpp/ql/examples/snippets/todocomment.ql
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* @id cpp/examples/todocomment
|
||||||
|
* @name TODO comments
|
||||||
|
* @description Finds comments containing the word "TODO"
|
||||||
|
* @tags comment
|
||||||
|
* matches
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
|
||||||
|
import cpp
|
||||||
|
|
||||||
|
from Comment c
|
||||||
|
where c.getContents().matches("%TODO%")
|
||||||
|
select c
|
||||||
15
cpp/ql/examples/snippets/toomanyparams.ql
Normal file
15
cpp/ql/examples/snippets/toomanyparams.ql
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* @id cpp/examples/toomanyparams
|
||||||
|
* @name Functions with many parameters
|
||||||
|
* @description Finds functions or methods with more than 10 parameters
|
||||||
|
* @tags function
|
||||||
|
* method
|
||||||
|
* parameter
|
||||||
|
* argument
|
||||||
|
*/
|
||||||
|
|
||||||
|
import cpp
|
||||||
|
|
||||||
|
from Function fcn
|
||||||
|
where fcn.getNumberOfParameters() > 10
|
||||||
|
select fcn
|
||||||
16
cpp/ql/examples/snippets/unusedlocalvar.ql
Normal file
16
cpp/ql/examples/snippets/unusedlocalvar.ql
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* @id cpp/examples/unusedlocalvar
|
||||||
|
* @name Unused local variable
|
||||||
|
* @description Finds local variables that are not accessed
|
||||||
|
* @tags variable
|
||||||
|
* local
|
||||||
|
* access
|
||||||
|
*/
|
||||||
|
|
||||||
|
import cpp
|
||||||
|
|
||||||
|
from LocalScopeVariable v
|
||||||
|
where
|
||||||
|
not v instanceof Parameter and
|
||||||
|
not exists(v.getAnAccess())
|
||||||
|
select v
|
||||||
18
cpp/ql/examples/snippets/unusedmethod.ql
Normal file
18
cpp/ql/examples/snippets/unusedmethod.ql
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* @id cpp/examples/unusedmethod
|
||||||
|
* @name Unused private method
|
||||||
|
* @description Finds private non-virtual methods that are not accessed
|
||||||
|
* @tags method
|
||||||
|
* access
|
||||||
|
* private
|
||||||
|
* virtual
|
||||||
|
*/
|
||||||
|
|
||||||
|
import cpp
|
||||||
|
|
||||||
|
from MemberFunction fcn
|
||||||
|
where
|
||||||
|
fcn.isPrivate() and
|
||||||
|
not fcn.isVirtual() and
|
||||||
|
not exists(FunctionCall call | fcn = call.getTarget())
|
||||||
|
select fcn.getDefinition()
|
||||||
13
cpp/ql/examples/snippets/unusedparam.ql
Normal file
13
cpp/ql/examples/snippets/unusedparam.ql
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* @id cpp/examples/unusedparam
|
||||||
|
* @name Unused parameter
|
||||||
|
* @description Finds parameters that are not accessed
|
||||||
|
* @tags parameter
|
||||||
|
* access
|
||||||
|
*/
|
||||||
|
|
||||||
|
import cpp
|
||||||
|
|
||||||
|
from Parameter p
|
||||||
|
where p.isNamed() and not exists(p.getAnAccess())
|
||||||
|
select p
|
||||||
21
cpp/ql/examples/snippets/voidreturntype.ql
Normal file
21
cpp/ql/examples/snippets/voidreturntype.ql
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* @id cpp/examples/voidreturntype
|
||||||
|
* @name Const method without return type
|
||||||
|
* @description Finds const methods whose return type is `void`
|
||||||
|
* @tags const
|
||||||
|
* function
|
||||||
|
* method
|
||||||
|
* modifier
|
||||||
|
* specifier
|
||||||
|
* return
|
||||||
|
* type
|
||||||
|
* void
|
||||||
|
*/
|
||||||
|
|
||||||
|
import cpp
|
||||||
|
|
||||||
|
from MemberFunction m
|
||||||
|
where
|
||||||
|
m.hasSpecifier("const") and
|
||||||
|
m.getType() instanceof VoidType
|
||||||
|
select m
|
||||||
13
cpp/ql/examples/snippets/volatilevariable.ql
Normal file
13
cpp/ql/examples/snippets/volatilevariable.ql
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* @id cpp/examples/volatilevariable
|
||||||
|
* @name Variable declared volatile
|
||||||
|
* @description Finds variables with a `volatile` modifier
|
||||||
|
* @tags variable
|
||||||
|
* volatile
|
||||||
|
*/
|
||||||
|
|
||||||
|
import cpp
|
||||||
|
|
||||||
|
from Variable f
|
||||||
|
where f.isVolatile()
|
||||||
|
select f
|
||||||
1
csharp/ql/examples/queries.xml
Normal file
1
csharp/ql/examples/queries.xml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<queries language="csharp"/>
|
||||||
17
csharp/ql/examples/snippets/array_access.ql
Normal file
17
csharp/ql/examples/snippets/array_access.ql
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/**
|
||||||
|
* @id cs/examples/array-access
|
||||||
|
* @name Array access
|
||||||
|
* @description Finds array access expressions with an index expression
|
||||||
|
* consisting of a unary increment or decrement, e.g. 'a[i++]'.
|
||||||
|
* @tags array
|
||||||
|
* access
|
||||||
|
* index
|
||||||
|
* unary
|
||||||
|
* assignment
|
||||||
|
*/
|
||||||
|
|
||||||
|
import csharp
|
||||||
|
|
||||||
|
from ArrayAccess a
|
||||||
|
where a.getAnIndex() instanceof MutatorOperation
|
||||||
|
select a
|
||||||
16
csharp/ql/examples/snippets/cast_expr.ql
Normal file
16
csharp/ql/examples/snippets/cast_expr.ql
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* @id cs/examples/cast-expr
|
||||||
|
* @name Cast expressions
|
||||||
|
* @description Finds casts from a floating point type to an integer type.
|
||||||
|
* @tags cast
|
||||||
|
* integer
|
||||||
|
* float
|
||||||
|
* type
|
||||||
|
*/
|
||||||
|
|
||||||
|
import csharp
|
||||||
|
|
||||||
|
from CastExpr c
|
||||||
|
where c.getExpr().getType() instanceof FloatingPointType
|
||||||
|
and c.getType() instanceof IntegralType
|
||||||
|
select c
|
||||||
14
csharp/ql/examples/snippets/catch_exception.ql
Normal file
14
csharp/ql/examples/snippets/catch_exception.ql
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* @id cs/examples/catch-exception
|
||||||
|
* @name Catch exception
|
||||||
|
* @description Finds places where we catch exceptions of type 'System.IO.IOException'.
|
||||||
|
* @tags catch
|
||||||
|
* try
|
||||||
|
* exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
import csharp
|
||||||
|
|
||||||
|
from CatchClause catch
|
||||||
|
where catch.getCaughtExceptionType().hasQualifiedName("System.IO.IOException")
|
||||||
|
select catch
|
||||||
14
csharp/ql/examples/snippets/constructor_call.ql
Normal file
14
csharp/ql/examples/snippets/constructor_call.ql
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* @id cs/examples/constructor-call
|
||||||
|
* @name Call to constructor
|
||||||
|
* @description Finds places where we call 'new System.Exception(...)'.
|
||||||
|
* @tags call
|
||||||
|
* constructor
|
||||||
|
* new
|
||||||
|
*/
|
||||||
|
|
||||||
|
import csharp
|
||||||
|
|
||||||
|
from ObjectCreation new
|
||||||
|
where new.getObjectType().hasQualifiedName("System.Exception")
|
||||||
|
select new
|
||||||
14
csharp/ql/examples/snippets/empty_block.ql
Normal file
14
csharp/ql/examples/snippets/empty_block.ql
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* @id cs/examples/empty-block
|
||||||
|
* @name Empty blocks
|
||||||
|
* @description Finds empty block statements.
|
||||||
|
* @tags empty
|
||||||
|
* block
|
||||||
|
* statement
|
||||||
|
*/
|
||||||
|
|
||||||
|
import csharp
|
||||||
|
|
||||||
|
from BlockStmt blk
|
||||||
|
where blk.isEmpty()
|
||||||
|
select blk
|
||||||
17
csharp/ql/examples/snippets/empty_then.ql
Normal file
17
csharp/ql/examples/snippets/empty_then.ql
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/**
|
||||||
|
* @id cs/examples/empty-then
|
||||||
|
* @name If statements with empty then branch
|
||||||
|
* @description Finds 'if' statements where the 'then' branch is
|
||||||
|
* an empty block statement.
|
||||||
|
* @tags if
|
||||||
|
* then
|
||||||
|
* empty
|
||||||
|
* conditional
|
||||||
|
* branch
|
||||||
|
*/
|
||||||
|
|
||||||
|
import csharp
|
||||||
|
|
||||||
|
from IfStmt i
|
||||||
|
where i.getThen().(BlockStmt).isEmpty()
|
||||||
|
select i
|
||||||
14
csharp/ql/examples/snippets/eq_true.ql
Normal file
14
csharp/ql/examples/snippets/eq_true.ql
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* @id cs/examples/eq-true
|
||||||
|
* @name Equality test on Boolean
|
||||||
|
* @description Finds tests like 'x==true', 'x==false', 'x!=true', '!=false'.
|
||||||
|
* @tags equals
|
||||||
|
* test
|
||||||
|
* boolean
|
||||||
|
*/
|
||||||
|
|
||||||
|
import csharp
|
||||||
|
|
||||||
|
from EqualityOperation eq
|
||||||
|
where eq.getAnOperand() instanceof BoolLiteral
|
||||||
|
select eq
|
||||||
17
csharp/ql/examples/snippets/extend_class.ql
Normal file
17
csharp/ql/examples/snippets/extend_class.ql
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/**
|
||||||
|
* @id cs/examples/extend-class
|
||||||
|
* @name Class extends/implements
|
||||||
|
* @description Finds classes/interfaces that extend/implement 'System.Collections.IEnumerator'.
|
||||||
|
* @tags class
|
||||||
|
* extends
|
||||||
|
* implements
|
||||||
|
* overrides
|
||||||
|
* subtype
|
||||||
|
* supertype
|
||||||
|
*/
|
||||||
|
|
||||||
|
import csharp
|
||||||
|
|
||||||
|
from RefType type
|
||||||
|
where type.getABaseType+().hasQualifiedName("System.Collections.IEnumerator")
|
||||||
|
select type
|
||||||
14
csharp/ql/examples/snippets/extern_method.ql
Normal file
14
csharp/ql/examples/snippets/extern_method.ql
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* @id cs/examples/extern-method
|
||||||
|
* @name Extern methods
|
||||||
|
* @description Finds methods that are 'extern'.
|
||||||
|
* @tags method
|
||||||
|
* native
|
||||||
|
* modifier
|
||||||
|
*/
|
||||||
|
|
||||||
|
import csharp
|
||||||
|
|
||||||
|
from Method m
|
||||||
|
where m.isExtern()
|
||||||
|
select m
|
||||||
15
csharp/ql/examples/snippets/field_read.ql
Normal file
15
csharp/ql/examples/snippets/field_read.ql
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* @id cs/examples/field-read
|
||||||
|
* @name Read of field
|
||||||
|
* @description Finds reads of 'VirtualAddress' (defined on 'Mono.Cecil.PE.Section').
|
||||||
|
* @tags field
|
||||||
|
* read
|
||||||
|
*/
|
||||||
|
|
||||||
|
import csharp
|
||||||
|
|
||||||
|
from Field f, FieldRead read
|
||||||
|
where f.hasName("VirtualAddress")
|
||||||
|
and f.getDeclaringType().hasQualifiedName("Mono.Cecil.PE.Section")
|
||||||
|
and f = read.getTarget()
|
||||||
|
select read
|
||||||
13
csharp/ql/examples/snippets/integer_literal.ql
Normal file
13
csharp/ql/examples/snippets/integer_literal.ql
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* @id cs/examples/integer-literal
|
||||||
|
* @name Integer literal
|
||||||
|
* @description Finds places where we use the integer literal '0'.
|
||||||
|
* @tags integer
|
||||||
|
* literal
|
||||||
|
*/
|
||||||
|
|
||||||
|
import csharp
|
||||||
|
|
||||||
|
from IntegerLiteral literal
|
||||||
|
where literal.getValue().toInt() = 0
|
||||||
|
select literal
|
||||||
15
csharp/ql/examples/snippets/method_call.ql
Normal file
15
csharp/ql/examples/snippets/method_call.ql
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* @id cs/examples/method-call
|
||||||
|
* @name Call to method
|
||||||
|
* @description Finds calls to method 'Company.Class.MethodName'.
|
||||||
|
* @tags call
|
||||||
|
* method
|
||||||
|
*/
|
||||||
|
|
||||||
|
import csharp
|
||||||
|
|
||||||
|
from MethodCall call, Method method
|
||||||
|
where call.getTarget() = method
|
||||||
|
and method.hasName("MethodName")
|
||||||
|
and method.getDeclaringType().hasQualifiedName("Company.Class")
|
||||||
|
select call
|
||||||
16
csharp/ql/examples/snippets/mutual_recursion.ql
Normal file
16
csharp/ql/examples/snippets/mutual_recursion.ql
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* @id cs/examples/mutual-recursion
|
||||||
|
* @name Mutual recursion
|
||||||
|
* @description Finds pairs of methods that call each other.
|
||||||
|
* @tags method
|
||||||
|
* recursion
|
||||||
|
*/
|
||||||
|
|
||||||
|
import csharp
|
||||||
|
|
||||||
|
from Method m, Method n
|
||||||
|
where m.calls(n)
|
||||||
|
and n.calls(m)
|
||||||
|
and m != n
|
||||||
|
select m, n
|
||||||
|
|
||||||
19
csharp/ql/examples/snippets/null_argument.ql
Normal file
19
csharp/ql/examples/snippets/null_argument.ql
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
/**
|
||||||
|
* @id cs/examples/null-argument
|
||||||
|
* @name Add null to collection
|
||||||
|
* @description Finds places where we add 'null' to a collection.
|
||||||
|
* @tags null
|
||||||
|
* parameter
|
||||||
|
* argument
|
||||||
|
* collection
|
||||||
|
* add
|
||||||
|
*/
|
||||||
|
|
||||||
|
import csharp
|
||||||
|
|
||||||
|
from MethodCall call, Method add
|
||||||
|
where call.getTarget() = add.getAnUltimateImplementor*()
|
||||||
|
and add.hasName("Add")
|
||||||
|
and add.getDeclaringType().getSourceDeclaration().hasQualifiedName("System.Collections.Generic.ICollection<>")
|
||||||
|
and call.getAnArgument() instanceof NullLiteral
|
||||||
|
select call
|
||||||
15
csharp/ql/examples/snippets/override_method.ql
Normal file
15
csharp/ql/examples/snippets/override_method.ql
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* @id cs/examples/override-method
|
||||||
|
* @name Override of method
|
||||||
|
* @description Finds methods that directly override 'Object.ToString'.
|
||||||
|
* @tags method
|
||||||
|
* override
|
||||||
|
*/
|
||||||
|
|
||||||
|
import csharp
|
||||||
|
|
||||||
|
from Method override, Method base
|
||||||
|
where base.hasName("ToString")
|
||||||
|
and base.getDeclaringType().hasQualifiedName("System.Object")
|
||||||
|
and base.getAnOverrider() = override
|
||||||
|
select override
|
||||||
13
csharp/ql/examples/snippets/qualifier.ql
Normal file
13
csharp/ql/examples/snippets/qualifier.ql
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* @id cs/examples/qualifier
|
||||||
|
* @name Expression qualifier
|
||||||
|
* @description Finds qualified expressions (e.g. 'a.b()') and their qualifiers ('a').
|
||||||
|
* @tags qualifier
|
||||||
|
* chain
|
||||||
|
*/
|
||||||
|
|
||||||
|
import csharp
|
||||||
|
|
||||||
|
from QualifiableExpr qualifiedExpr, Expr qualifier
|
||||||
|
where qualifier = qualifiedExpr.getQualifier()
|
||||||
|
select qualifiedExpr, qualifier
|
||||||
14
csharp/ql/examples/snippets/return_statement.ql
Normal file
14
csharp/ql/examples/snippets/return_statement.ql
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* @id cs/examples/return-statement
|
||||||
|
* @name Return statements
|
||||||
|
* @description Finds return statements that return 'null'.
|
||||||
|
* @tags return
|
||||||
|
* statement
|
||||||
|
* null
|
||||||
|
*/
|
||||||
|
|
||||||
|
import csharp
|
||||||
|
|
||||||
|
from ReturnStmt r
|
||||||
|
where r.getExpr() instanceof NullLiteral
|
||||||
|
select r
|
||||||
13
csharp/ql/examples/snippets/singleton_block.ql
Normal file
13
csharp/ql/examples/snippets/singleton_block.ql
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* @id cs/examples/singleton-block
|
||||||
|
* @name Singleton blocks
|
||||||
|
* @description Finds block statements containing a single statement.
|
||||||
|
* @tags block
|
||||||
|
* statement
|
||||||
|
*/
|
||||||
|
|
||||||
|
import csharp
|
||||||
|
|
||||||
|
from BlockStmt b
|
||||||
|
where b.getNumberOfStmts() = 1
|
||||||
|
select b
|
||||||
17
csharp/ql/examples/snippets/switch_case.ql
Normal file
17
csharp/ql/examples/snippets/switch_case.ql
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/**
|
||||||
|
* @id cs/examples/switch-case
|
||||||
|
* @name Switch statement case missing
|
||||||
|
* @description Finds switch statements with a missing enum constant case and no default case.
|
||||||
|
* @tags switch
|
||||||
|
* case
|
||||||
|
* enum
|
||||||
|
*/
|
||||||
|
|
||||||
|
import csharp
|
||||||
|
|
||||||
|
from SwitchStmt switch, Enum enum, EnumConstant missing
|
||||||
|
where switch.getCondition().getType() = enum
|
||||||
|
and missing.getDeclaringType() = enum
|
||||||
|
and not switch.getAConstCase().getExpr() = missing.getAnAccess()
|
||||||
|
and not exists(switch.getDefaultCase())
|
||||||
|
select switch
|
||||||
16
csharp/ql/examples/snippets/ternary_conditional.ql
Normal file
16
csharp/ql/examples/snippets/ternary_conditional.ql
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* @id cs/examples/ternary-conditional
|
||||||
|
* @name Conditional expressions
|
||||||
|
* @description Finds conditional expressions of the form '... ? ... : ...'
|
||||||
|
* where the types of the resulting expressions differ.
|
||||||
|
* @tags conditional
|
||||||
|
* type
|
||||||
|
*/
|
||||||
|
|
||||||
|
import csharp
|
||||||
|
|
||||||
|
from ConditionalExpr e
|
||||||
|
where e.getThen().stripImplicitCasts() != e.getElse().stripImplicitCasts()
|
||||||
|
and not e.getThen().getType() instanceof NullType
|
||||||
|
and not e.getElse().getType() instanceof NullType
|
||||||
|
select e
|
||||||
13
csharp/ql/examples/snippets/throw_exception.ql
Normal file
13
csharp/ql/examples/snippets/throw_exception.ql
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* @id cs/examples/throw-exception
|
||||||
|
* @name Throw exception of given type
|
||||||
|
* @description Finds places where we throw 'System.IO.IOException' or one of its subtypes.
|
||||||
|
* @tags throw
|
||||||
|
* exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
import csharp
|
||||||
|
|
||||||
|
from ThrowStmt throw
|
||||||
|
where throw.getThrownExceptionType().getBaseClass*().hasQualifiedName("System.IO.IOException")
|
||||||
|
select throw
|
||||||
13
csharp/ql/examples/snippets/todo_comment.ql
Normal file
13
csharp/ql/examples/snippets/todo_comment.ql
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* @id cs/examples/todo-comment
|
||||||
|
* @name TODO comments
|
||||||
|
* @description Finds comments containing the word "TODO".
|
||||||
|
* @tags comment
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
|
||||||
|
import csharp
|
||||||
|
|
||||||
|
from CommentLine c
|
||||||
|
where c.getText().regexpMatch("(?si).*\\bTODO\\b.*")
|
||||||
|
select c
|
||||||
14
csharp/ql/examples/snippets/too_many_params.ql
Normal file
14
csharp/ql/examples/snippets/too_many_params.ql
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* @id cs/examples/too-many-params
|
||||||
|
* @name Methods with many parameters
|
||||||
|
* @description Finds methods with more than ten parameters.
|
||||||
|
* @tags method
|
||||||
|
* parameter
|
||||||
|
* argument
|
||||||
|
*/
|
||||||
|
|
||||||
|
import csharp
|
||||||
|
|
||||||
|
from Method m
|
||||||
|
where m.getNumberOfParameters() > 10
|
||||||
|
select m
|
||||||
16
csharp/ql/examples/snippets/try_finally.ql
Normal file
16
csharp/ql/examples/snippets/try_finally.ql
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* @id cs/examples/try-finally
|
||||||
|
* @name Try-finally statements
|
||||||
|
* @description Finds try-finally statements without a catch clause.
|
||||||
|
* @tags try
|
||||||
|
* finally
|
||||||
|
* catch
|
||||||
|
* exceptions
|
||||||
|
*/
|
||||||
|
|
||||||
|
import csharp
|
||||||
|
|
||||||
|
from TryStmt t
|
||||||
|
where exists(t.getFinally())
|
||||||
|
and not exists(t.getACatchClause())
|
||||||
|
select t
|
||||||
14
csharp/ql/examples/snippets/unused_local_var.ql
Normal file
14
csharp/ql/examples/snippets/unused_local_var.ql
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* @id cs/examples/unused-local-var
|
||||||
|
* @name Unused local variable
|
||||||
|
* @description Finds local variables that are not accessed.
|
||||||
|
* @tags variable
|
||||||
|
* local
|
||||||
|
* access
|
||||||
|
*/
|
||||||
|
|
||||||
|
import csharp
|
||||||
|
|
||||||
|
from LocalVariable v
|
||||||
|
where not exists(v.getAnAccess())
|
||||||
|
select v
|
||||||
13
csharp/ql/examples/snippets/unused_param.ql
Normal file
13
csharp/ql/examples/snippets/unused_param.ql
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* @id cs/examples/unused-param
|
||||||
|
* @name Unused parameter
|
||||||
|
* @description Finds parameters that are not accessed.
|
||||||
|
* @tags parameter
|
||||||
|
* access
|
||||||
|
*/
|
||||||
|
|
||||||
|
import csharp
|
||||||
|
|
||||||
|
from Parameter p
|
||||||
|
where not exists(p.getAnAccess())
|
||||||
|
select p
|
||||||
16
csharp/ql/examples/snippets/void_return_type.ql
Normal file
16
csharp/ql/examples/snippets/void_return_type.ql
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* @id cs/examples/void-return-type
|
||||||
|
* @name Methods without return type
|
||||||
|
* @description Finds methods whose return type is 'void'.
|
||||||
|
* @tags method
|
||||||
|
* void
|
||||||
|
* modifier
|
||||||
|
* return
|
||||||
|
* type
|
||||||
|
*/
|
||||||
|
|
||||||
|
import csharp
|
||||||
|
|
||||||
|
from Method m
|
||||||
|
where m.getReturnType() instanceof VoidType
|
||||||
|
select m
|
||||||
14
csharp/ql/examples/snippets/volatile_field.ql
Normal file
14
csharp/ql/examples/snippets/volatile_field.ql
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* @id cs/examples/volatile-field
|
||||||
|
* @name Fields declared volatile
|
||||||
|
* @description Finds fields with a 'volatile' modifier.
|
||||||
|
* @tags field
|
||||||
|
* volatile
|
||||||
|
* synchronization
|
||||||
|
*/
|
||||||
|
|
||||||
|
import csharp
|
||||||
|
|
||||||
|
from Field f
|
||||||
|
where f.isVolatile()
|
||||||
|
select f
|
||||||
1
java/ql/examples/queries.xml
Normal file
1
java/ql/examples/queries.xml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<queries language="java"/>
|
||||||
17
java/ql/examples/snippets/arrayaccess.ql
Normal file
17
java/ql/examples/snippets/arrayaccess.ql
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/**
|
||||||
|
* @id java/examples/arrayaccess
|
||||||
|
* @name Array access
|
||||||
|
* @description Finds array access expressions with an index expression
|
||||||
|
* consisting of a unary assignment
|
||||||
|
* @tags array
|
||||||
|
* access
|
||||||
|
* index
|
||||||
|
* unary
|
||||||
|
* assignment
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
|
||||||
|
from ArrayAccess a
|
||||||
|
where a.getIndexExpr() instanceof UnaryAssignExpr
|
||||||
|
select a
|
||||||
16
java/ql/examples/snippets/castexpr.ql
Normal file
16
java/ql/examples/snippets/castexpr.ql
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* @id java/examples/castexpr
|
||||||
|
* @name Cast expressions
|
||||||
|
* @description Finds casts from a floating point type to an integer type
|
||||||
|
* @tags cast
|
||||||
|
* integer
|
||||||
|
* float
|
||||||
|
* type
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
|
||||||
|
from CastExpr c
|
||||||
|
where c.getExpr().getType() instanceof FloatingPointType
|
||||||
|
and c.getType() instanceof IntegralType
|
||||||
|
select c
|
||||||
14
java/ql/examples/snippets/catch_exception.ql
Normal file
14
java/ql/examples/snippets/catch_exception.ql
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* @id java/examples/catch-exception
|
||||||
|
* @name Catch exception
|
||||||
|
* @description Finds places where we catch exceptions of type com.example.AnException
|
||||||
|
* @tags catch
|
||||||
|
* try
|
||||||
|
* exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
|
||||||
|
from CatchClause catch
|
||||||
|
where catch.getACaughtType().hasQualifiedName("com.example", "AnException")
|
||||||
|
select catch
|
||||||
14
java/ql/examples/snippets/constructor_call.ql
Normal file
14
java/ql/examples/snippets/constructor_call.ql
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* @id java/examples/constructor-call
|
||||||
|
* @name Call to constructor
|
||||||
|
* @description Finds places where we call `new com.example.Class(...)`
|
||||||
|
* @tags call
|
||||||
|
* constructor
|
||||||
|
* new
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
|
||||||
|
from ClassInstanceExpr new
|
||||||
|
where new.getConstructedType().hasQualifiedName("com.example", "Class")
|
||||||
|
select new
|
||||||
14
java/ql/examples/snippets/emptyblock.ql
Normal file
14
java/ql/examples/snippets/emptyblock.ql
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* @id java/examples/emptyblock
|
||||||
|
* @name Empty blocks
|
||||||
|
* @description Finds empty block statements
|
||||||
|
* @tags empty
|
||||||
|
* block
|
||||||
|
* statement
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
|
||||||
|
from Block blk
|
||||||
|
where blk.getNumStmt() = 0
|
||||||
|
select blk
|
||||||
17
java/ql/examples/snippets/emptythen.ql
Normal file
17
java/ql/examples/snippets/emptythen.ql
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/**
|
||||||
|
* @id java/examples/emptythen
|
||||||
|
* @name If statements with empty then branch
|
||||||
|
* @description Finds 'if' statements where the 'then' branch is
|
||||||
|
* an empty block statement
|
||||||
|
* @tags if
|
||||||
|
* then
|
||||||
|
* empty
|
||||||
|
* conditional
|
||||||
|
* branch
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
|
||||||
|
from IfStmt i
|
||||||
|
where i.getThen().(Block).getNumStmt() = 0
|
||||||
|
select i
|
||||||
14
java/ql/examples/snippets/eq_true.ql
Normal file
14
java/ql/examples/snippets/eq_true.ql
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* @id java/examples/eq-true
|
||||||
|
* @name Equality test on boolean
|
||||||
|
* @description Finds tests like `==true`, `==false`, `!=true`, `!=false`
|
||||||
|
* @tags equals
|
||||||
|
* test
|
||||||
|
* boolean
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
|
||||||
|
from EqualityTest eq
|
||||||
|
where eq.getAnOperand() instanceof BooleanLiteral
|
||||||
|
select eq
|
||||||
17
java/ql/examples/snippets/extend_class.ql
Normal file
17
java/ql/examples/snippets/extend_class.ql
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/**
|
||||||
|
* @id java/examples/extend-class
|
||||||
|
* @name Class extends/implements
|
||||||
|
* @description Finds classes/interfaces that extend/implement com.example.Class
|
||||||
|
* @tags class
|
||||||
|
* extends
|
||||||
|
* implements
|
||||||
|
* overrides
|
||||||
|
* subtype
|
||||||
|
* supertype
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
|
||||||
|
from RefType type
|
||||||
|
where type.getASupertype+().hasQualifiedName("com.example", "Class")
|
||||||
|
select type
|
||||||
15
java/ql/examples/snippets/field_read.ql
Normal file
15
java/ql/examples/snippets/field_read.ql
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* @id java/examples/field-read
|
||||||
|
* @name Read of field
|
||||||
|
* @description Finds reads of aField (defined on com.example.Class)
|
||||||
|
* @tags field
|
||||||
|
* read
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
|
||||||
|
from Field f, FieldRead read
|
||||||
|
where f.hasName("aField")
|
||||||
|
and f.getDeclaringType().hasQualifiedName("com.example", "Class")
|
||||||
|
and f = read.getField()
|
||||||
|
select read
|
||||||
13
java/ql/examples/snippets/integer_literal.ql
Normal file
13
java/ql/examples/snippets/integer_literal.ql
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* @id java/examples/integer-literal
|
||||||
|
* @name Integer literal
|
||||||
|
* @description Finds places where we use the integer literal `0`
|
||||||
|
* @tags integer
|
||||||
|
* literal
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
|
||||||
|
from IntegerLiteral literal
|
||||||
|
where literal.getLiteral().toInt() = 0
|
||||||
|
select literal
|
||||||
15
java/ql/examples/snippets/method_call.ql
Normal file
15
java/ql/examples/snippets/method_call.ql
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* @id java/examples/method-call
|
||||||
|
* @name Call to method
|
||||||
|
* @description Finds calls to com.example.Class.methodName
|
||||||
|
* @tags call
|
||||||
|
* method
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
|
||||||
|
from MethodAccess call, Method method
|
||||||
|
where call.getMethod() = method
|
||||||
|
and method.hasName("methodName")
|
||||||
|
and method.getDeclaringType().hasQualifiedName("com.example", "Class")
|
||||||
|
select call
|
||||||
15
java/ql/examples/snippets/mutualrecursion.ql
Normal file
15
java/ql/examples/snippets/mutualrecursion.ql
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* @id java/examples/mutualrecursion
|
||||||
|
* @name Mutual recursion
|
||||||
|
* @description Finds pairs of methods that call each other
|
||||||
|
* @tags method
|
||||||
|
* recursion
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
|
||||||
|
from Method m, Method n
|
||||||
|
where exists(MethodAccess ma | ma.getCaller() = m and ma.getCallee() = n)
|
||||||
|
and exists(MethodAccess ma | ma.getCaller() = n and ma.getCallee() = m)
|
||||||
|
and m != n
|
||||||
|
select m, n
|
||||||
14
java/ql/examples/snippets/nativemethod.ql
Normal file
14
java/ql/examples/snippets/nativemethod.ql
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* @id java/examples/nativemethod
|
||||||
|
* @name Native methods
|
||||||
|
* @description Finds methods that are native
|
||||||
|
* @tags method
|
||||||
|
* native
|
||||||
|
* modifier
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
|
||||||
|
from Method m
|
||||||
|
where m.isNative()
|
||||||
|
select m
|
||||||
19
java/ql/examples/snippets/null_argument.ql
Normal file
19
java/ql/examples/snippets/null_argument.ql
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
/**
|
||||||
|
* @id java/examples/null-argument
|
||||||
|
* @name Add null to collection
|
||||||
|
* @description Finds places where we add null to a collection
|
||||||
|
* @tags null
|
||||||
|
* parameter
|
||||||
|
* argument
|
||||||
|
* collection
|
||||||
|
* add
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
|
||||||
|
from MethodAccess call, Method add
|
||||||
|
where call.getMethod().overrides*(add)
|
||||||
|
and add.hasName("add")
|
||||||
|
and add.getDeclaringType().getSourceDeclaration().hasQualifiedName("java.util", "Collection")
|
||||||
|
and call.getAnArgument() instanceof NullLiteral
|
||||||
|
select call
|
||||||
15
java/ql/examples/snippets/override_method.ql
Normal file
15
java/ql/examples/snippets/override_method.ql
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* @id java/examples/override-method
|
||||||
|
* @name Override of method
|
||||||
|
* @description Finds methods that override com.example.Class.baseMethod
|
||||||
|
* @tags method
|
||||||
|
* override
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
|
||||||
|
from Method override, Method base
|
||||||
|
where base.hasName("baseMethod")
|
||||||
|
and base.getDeclaringType().hasQualifiedName("com.example", "Class")
|
||||||
|
and override.overrides+(base)
|
||||||
|
select override
|
||||||
14
java/ql/examples/snippets/qualifiedthis.ql
Normal file
14
java/ql/examples/snippets/qualifiedthis.ql
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* @id java/examples/qualifiedthis
|
||||||
|
* @name Qualified 'this' access
|
||||||
|
* @description Finds 'this' accesses that are qualified by a type name
|
||||||
|
* @tags this
|
||||||
|
* access
|
||||||
|
* qualifier
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
|
||||||
|
from ThisAccess t
|
||||||
|
where exists(t.getQualifier())
|
||||||
|
select t
|
||||||
14
java/ql/examples/snippets/returnstatement.ql
Normal file
14
java/ql/examples/snippets/returnstatement.ql
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* @id java/examples/returnstatement
|
||||||
|
* @name Return statements
|
||||||
|
* @description Finds return statements that return 'null'
|
||||||
|
* @tags return
|
||||||
|
* statement
|
||||||
|
* null
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
|
||||||
|
from ReturnStmt r
|
||||||
|
where r.getResult() instanceof NullLiteral
|
||||||
|
select r
|
||||||
13
java/ql/examples/snippets/singletonblock.ql
Normal file
13
java/ql/examples/snippets/singletonblock.ql
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* @id java/examples/singletonblock
|
||||||
|
* @name Singleton blocks
|
||||||
|
* @description Finds block statements containing a single statement
|
||||||
|
* @tags block
|
||||||
|
* statement
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
|
||||||
|
from Block b
|
||||||
|
where b.getNumStmt() = 1
|
||||||
|
select b
|
||||||
17
java/ql/examples/snippets/switchcase.ql
Normal file
17
java/ql/examples/snippets/switchcase.ql
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/**
|
||||||
|
* @id java/examples/switchcase
|
||||||
|
* @name Switch statement case missing
|
||||||
|
* @description Finds switch statements with a missing enum constant case and no default case
|
||||||
|
* @tags switch
|
||||||
|
* case
|
||||||
|
* enum
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
|
||||||
|
from SwitchStmt switch, EnumType enum, EnumConstant missing
|
||||||
|
where switch.getExpr().getType() = enum
|
||||||
|
and missing.getDeclaringType() = enum
|
||||||
|
and not switch.getAConstCase().getValue() = missing.getAnAccess()
|
||||||
|
and not exists(switch.getDefaultCase())
|
||||||
|
select switch
|
||||||
14
java/ql/examples/snippets/synchronizedmethod.ql
Normal file
14
java/ql/examples/snippets/synchronizedmethod.ql
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* @id java/examples/synchronizedmethod
|
||||||
|
* @name Synchronized methods
|
||||||
|
* @description Finds methods that are synchronized
|
||||||
|
* @tags method
|
||||||
|
* synchronized
|
||||||
|
* modifier
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
|
||||||
|
from Method m
|
||||||
|
where m.isSynchronized()
|
||||||
|
select m
|
||||||
16
java/ql/examples/snippets/ternaryconditional.ql
Normal file
16
java/ql/examples/snippets/ternaryconditional.ql
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* @id java/examples/ternaryconditional
|
||||||
|
* @name Conditional expressions
|
||||||
|
* @description Finds conditional expressions of the form '... ? ... : ...'
|
||||||
|
* where the types of the resulting expressions differ
|
||||||
|
* @tags conditional
|
||||||
|
* type
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
|
||||||
|
from ConditionalExpr e
|
||||||
|
where e.getTrueExpr().getType() != e.getFalseExpr().getType()
|
||||||
|
and not e.getTrueExpr().getType() instanceof NullType
|
||||||
|
and not e.getFalseExpr().getType() instanceof NullType
|
||||||
|
select e
|
||||||
13
java/ql/examples/snippets/throw_exception.ql
Normal file
13
java/ql/examples/snippets/throw_exception.ql
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* @id java/examples/throw-exception
|
||||||
|
* @name Throw exception of type
|
||||||
|
* @description Finds places where we throw com.example.AnException or one of its subtypes
|
||||||
|
* @tags throw
|
||||||
|
* exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
|
||||||
|
from ThrowStmt throw
|
||||||
|
where throw.getThrownExceptionType().getASupertype*().hasQualifiedName("com.example", "AnException")
|
||||||
|
select throw, "Don't throw com.example.AnException"
|
||||||
13
java/ql/examples/snippets/todocomment.ql
Normal file
13
java/ql/examples/snippets/todocomment.ql
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* @id java/examples/todocomment
|
||||||
|
* @name TODO comments
|
||||||
|
* @description Finds comments containing the word "TODO"
|
||||||
|
* @tags comment
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
|
||||||
|
from JavadocText c
|
||||||
|
where c.getText().regexpMatch("(?si).*\\bTODO\\b.*")
|
||||||
|
select c
|
||||||
14
java/ql/examples/snippets/toomanyparams.ql
Normal file
14
java/ql/examples/snippets/toomanyparams.ql
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* @id java/examples/toomanyparams
|
||||||
|
* @name Methods with many parameters
|
||||||
|
* @description Finds methods with more than ten parameters
|
||||||
|
* @tags method
|
||||||
|
* parameter
|
||||||
|
* argument
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
|
||||||
|
from Method m
|
||||||
|
where m.getNumberOfParameters() > 10
|
||||||
|
select m
|
||||||
16
java/ql/examples/snippets/tryfinally.ql
Normal file
16
java/ql/examples/snippets/tryfinally.ql
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* @id java/examples/tryfinally
|
||||||
|
* @name Try-finally statements
|
||||||
|
* @description Finds try-finally statements without a catch clause
|
||||||
|
* @tags try
|
||||||
|
* finally
|
||||||
|
* catch
|
||||||
|
* exceptions
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
|
||||||
|
from TryStmt t
|
||||||
|
where exists(t.getFinally())
|
||||||
|
and not exists(t.getACatchClause())
|
||||||
|
select t
|
||||||
14
java/ql/examples/snippets/unusedlocalvar.ql
Normal file
14
java/ql/examples/snippets/unusedlocalvar.ql
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* @id java/examples/unusedlocalvar
|
||||||
|
* @name Unused local variable
|
||||||
|
* @description Finds local variables that are not accessed
|
||||||
|
* @tags variable
|
||||||
|
* local
|
||||||
|
* access
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
|
||||||
|
from LocalVariableDecl v
|
||||||
|
where not exists(v.getAnAccess())
|
||||||
|
select v
|
||||||
16
java/ql/examples/snippets/unusedmethod.ql
Normal file
16
java/ql/examples/snippets/unusedmethod.ql
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* @id java/examples/unusedmethod
|
||||||
|
* @name Unused private method
|
||||||
|
* @description Finds private methods that are not accessed
|
||||||
|
* @tags method
|
||||||
|
* access
|
||||||
|
* private
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
|
||||||
|
from Method m
|
||||||
|
where m.isPrivate()
|
||||||
|
and not exists(m.getAReference())
|
||||||
|
and not m instanceof InitializerMethod
|
||||||
|
select m
|
||||||
13
java/ql/examples/snippets/unusedparam.ql
Normal file
13
java/ql/examples/snippets/unusedparam.ql
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* @id java/examples/unusedparam
|
||||||
|
* @name Unused parameter
|
||||||
|
* @description Finds parameters that are not accessed
|
||||||
|
* @tags parameter
|
||||||
|
* access
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
|
||||||
|
from Parameter p
|
||||||
|
where not exists(p.getAnAccess())
|
||||||
|
select p
|
||||||
16
java/ql/examples/snippets/voidreturntype.ql
Normal file
16
java/ql/examples/snippets/voidreturntype.ql
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* @id java/examples/voidreturntype
|
||||||
|
* @name Methods without return type
|
||||||
|
* @description Finds methods whose return type is 'void'
|
||||||
|
* @tags method
|
||||||
|
* void
|
||||||
|
* modifier
|
||||||
|
* return
|
||||||
|
* type
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
|
||||||
|
from Method m
|
||||||
|
where m.getReturnType() instanceof VoidType
|
||||||
|
select m
|
||||||
14
java/ql/examples/snippets/volatilefield.ql
Normal file
14
java/ql/examples/snippets/volatilefield.ql
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* @id java/examples/volatilefield
|
||||||
|
* @name Fields declared volatile
|
||||||
|
* @description Finds fields with a 'volatile' modifier
|
||||||
|
* @tags field
|
||||||
|
* volatile
|
||||||
|
* synchronization
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
|
||||||
|
from Field f
|
||||||
|
where f.isVolatile()
|
||||||
|
select f
|
||||||
1
javascript/ql/examples/queries.xml
Normal file
1
javascript/ql/examples/queries.xml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<queries language="javascript"/>
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
/**
|
||||||
|
* @name IDOR through request to backend service
|
||||||
|
* @description Finds cases where the 'userId' field in a request to another service
|
||||||
|
* is an arbitrary user-controlled value, indicating lack of authentication.
|
||||||
|
* @kind path-problem
|
||||||
|
* @tags security
|
||||||
|
* @id js/examples/backend-idor
|
||||||
|
*/
|
||||||
|
|
||||||
|
import javascript
|
||||||
|
import DataFlow
|
||||||
|
import DataFlow::PathGraph
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tracks user-controlled values into a 'userId' property sent to a backend service.
|
||||||
|
*/
|
||||||
|
class IdorTaint extends TaintTracking::Configuration {
|
||||||
|
IdorTaint() { this = "IdorTaint" }
|
||||||
|
|
||||||
|
override predicate isSource(Node node) { node instanceof RemoteFlowSource }
|
||||||
|
|
||||||
|
override predicate isSink(Node node) { exists(ClientRequest req | node = req.getADataNode()) }
|
||||||
|
|
||||||
|
override predicate isAdditionalTaintStep(Node pred, Node succ) {
|
||||||
|
// Step from x -> { userId: x }
|
||||||
|
succ.(SourceNode).getAPropertyWrite("userId").getRhs() = pred
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode node) {
|
||||||
|
// After a check like `if (userId === session.user.id)`, the userId is considered safe.
|
||||||
|
node instanceof EqualityGuard
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sanitize values that have succesfully been compared to another value.
|
||||||
|
*/
|
||||||
|
class EqualityGuard extends TaintTracking::SanitizerGuardNode, ValueNode {
|
||||||
|
override EqualityTest astNode;
|
||||||
|
|
||||||
|
override predicate sanitizes(boolean outcome, Expr e) {
|
||||||
|
e = astNode.getAnOperand() and
|
||||||
|
outcome = astNode.getPolarity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
from IdorTaint cfg, PathNode source, PathNode sink
|
||||||
|
where cfg.hasFlowPath(source, sink)
|
||||||
|
select sink.getNode(), source, sink, "Unauthenticated user ID from $@.", source.getNode(), "here"
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/**
|
||||||
|
* @name Decoding after sanitization
|
||||||
|
* @description Tracks the return value of 'escapeHtml' into 'decodeURI', indicating
|
||||||
|
an ineffective sanitization attempt.
|
||||||
|
* @kind path-problem
|
||||||
|
* @tags security
|
||||||
|
* @id js/examples/decoding-after-sanitization
|
||||||
|
*/
|
||||||
|
|
||||||
|
import javascript
|
||||||
|
import DataFlow
|
||||||
|
import DataFlow::PathGraph
|
||||||
|
|
||||||
|
class DecodingAfterSanitization extends TaintTracking::Configuration {
|
||||||
|
DecodingAfterSanitization() { this = "DecodingAfterSanitization" }
|
||||||
|
|
||||||
|
override predicate isSource(Node node) { node.(CallNode).getCalleeName() = "escapeHtml" }
|
||||||
|
|
||||||
|
override predicate isSink(Node node) {
|
||||||
|
exists(CallNode call |
|
||||||
|
call.getCalleeName().matches("decodeURI%") and
|
||||||
|
node = call.getArgument(0)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
from DecodingAfterSanitization cfg, PathNode source, PathNode sink
|
||||||
|
where cfg.hasFlowPath(source, sink)
|
||||||
|
select sink.getNode(), source, sink, "URI decoding invalidates the HTML sanitization performed $@.",
|
||||||
|
source.getNode(), "here"
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
/**
|
||||||
|
* @name Decoding after sanitization (generalized)
|
||||||
|
* @description Tracks the return value of an HTML sanitizer into an escape-sequence decoder,
|
||||||
|
indicating an ineffective sanitization attempt.
|
||||||
|
* @kind path-problem
|
||||||
|
* @tags security
|
||||||
|
* @id js/examples/decoding-after-sanitization-generalized
|
||||||
|
*/
|
||||||
|
|
||||||
|
import javascript
|
||||||
|
import DataFlow
|
||||||
|
import DataFlow::PathGraph
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A call to a function that may introduce HTML meta-characters by
|
||||||
|
* replacing `%3C` or `\u003C` with `<`.
|
||||||
|
*/
|
||||||
|
class DecodingCall extends CallNode {
|
||||||
|
string kind;
|
||||||
|
|
||||||
|
Node input;
|
||||||
|
|
||||||
|
DecodingCall() {
|
||||||
|
getCalleeName().matches("decodeURI%") and
|
||||||
|
input = getArgument(0) and
|
||||||
|
kind = "URI decoding"
|
||||||
|
or
|
||||||
|
input = this.(JsonParserCall).getInput() and
|
||||||
|
kind = "JSON parsing"
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Gets the decoder kind, to be used in the alert message. */
|
||||||
|
string getKind() { result = kind }
|
||||||
|
|
||||||
|
/** Gets the input being decoded. */
|
||||||
|
Node getInput() { result = input }
|
||||||
|
}
|
||||||
|
|
||||||
|
class DecodingAfterSanitization extends TaintTracking::Configuration {
|
||||||
|
DecodingAfterSanitization() { this = "DecodingAfterSanitization" }
|
||||||
|
|
||||||
|
override predicate isSource(Node node) { node instanceof HtmlSanitizerCall }
|
||||||
|
|
||||||
|
override predicate isSink(Node node) { node = any(DecodingCall c).getInput() }
|
||||||
|
}
|
||||||
|
|
||||||
|
from DecodingAfterSanitization cfg, PathNode source, PathNode sink, DecodingCall decoder
|
||||||
|
where
|
||||||
|
cfg.hasFlowPath(source, sink) and
|
||||||
|
decoder.getInput() = sink.getNode()
|
||||||
|
select sink.getNode(), source, sink,
|
||||||
|
decoder.getKind() + " invalidates the HTML sanitization performed $@.", source.getNode(), "here"
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
/**
|
||||||
|
* @name Taint-tracking to 'eval' calls
|
||||||
|
* @description Tracks user-controlled values into 'eval' calls (special case of js/code-injection).
|
||||||
|
* @kind problem
|
||||||
|
* @tags security
|
||||||
|
* @id js/examples/eval-taint
|
||||||
|
*/
|
||||||
|
|
||||||
|
import javascript
|
||||||
|
import DataFlow
|
||||||
|
|
||||||
|
class EvalTaint extends TaintTracking::Configuration {
|
||||||
|
EvalTaint() { this = "EvalTaint" }
|
||||||
|
|
||||||
|
override predicate isSource(Node node) { node instanceof RemoteFlowSource }
|
||||||
|
|
||||||
|
override predicate isSink(Node node) { node = globalVarRef("eval").getACall().getArgument(0) }
|
||||||
|
}
|
||||||
|
|
||||||
|
from EvalTaint cfg, Node source, Node sink
|
||||||
|
where cfg.hasFlow(source, sink)
|
||||||
|
select sink, "Eval with user-controlled input from $@.", source, "here"
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* @name Taint-tracking to 'eval' calls (with path visualization)
|
||||||
|
* @description Tracks user-controlled values into 'eval' calls (special case of js/code-injection),
|
||||||
|
* and generates a visualizable path from the source to the sink.
|
||||||
|
* @kind path-problem
|
||||||
|
* @tags security
|
||||||
|
* @id js/examples/eval-taint-path
|
||||||
|
*/
|
||||||
|
|
||||||
|
import javascript
|
||||||
|
import DataFlow
|
||||||
|
import DataFlow::PathGraph
|
||||||
|
|
||||||
|
class EvalTaint extends TaintTracking::Configuration {
|
||||||
|
EvalTaint() { this = "EvalTaint" }
|
||||||
|
|
||||||
|
override predicate isSource(Node node) { node instanceof RemoteFlowSource }
|
||||||
|
|
||||||
|
override predicate isSink(Node node) { node = globalVarRef("eval").getACall().getArgument(0) }
|
||||||
|
}
|
||||||
|
|
||||||
|
from EvalTaint cfg, PathNode source, PathNode sink
|
||||||
|
where cfg.hasFlowPath(source, sink)
|
||||||
|
select sink.getNode(), source, sink, "Eval with user-controlled input from $@.", source.getNode(),
|
||||||
|
"here"
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/**
|
||||||
|
* @name Information disclosure through postMessage
|
||||||
|
* @description Tracks values from an 'authKey' property into a postMessage call with unrestricted origin,
|
||||||
|
indicating a leak of sensitive information.
|
||||||
|
* @kind path-problem
|
||||||
|
* @tags security
|
||||||
|
* @id js/examples/information-disclosure
|
||||||
|
*/
|
||||||
|
|
||||||
|
import javascript
|
||||||
|
import DataFlow
|
||||||
|
import DataFlow::PathGraph
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tracks authentication tokens ("authKey") to a postMessage call with unrestricted target origin.
|
||||||
|
*
|
||||||
|
* For example:
|
||||||
|
* ```
|
||||||
|
* win.postMessage(JSON.stringify({
|
||||||
|
* action: 'pause',
|
||||||
|
* auth: {
|
||||||
|
* key: window.state.authKey
|
||||||
|
* }
|
||||||
|
* }), '*');
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
class AuthKeyTracking extends DataFlow::Configuration {
|
||||||
|
AuthKeyTracking() { this = "AuthKeyTracking" }
|
||||||
|
|
||||||
|
override predicate isSource(Node node) { node.(PropRead).getPropertyName() = "authKey" }
|
||||||
|
|
||||||
|
override predicate isSink(Node node) {
|
||||||
|
exists(MethodCallNode call |
|
||||||
|
call.getMethodName() = "postMessage" and
|
||||||
|
call.getArgument(1).getStringValue() = "*" and // no restriction on target origin
|
||||||
|
call.getArgument(0) = node
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate isAdditionalFlowStep(Node pred, Node succ) {
|
||||||
|
// Step into objects: x -> { f: x }
|
||||||
|
succ.(SourceNode).getAPropertyWrite().getRhs() = pred
|
||||||
|
or
|
||||||
|
// Step through JSON serialization: x -> JSON.stringify(x)
|
||||||
|
// Note: TaintTracking::Configuration includes this step by default, but not DataFlow::Configuration
|
||||||
|
exists(CallNode call |
|
||||||
|
call = globalVarRef("JSON").getAMethodCall("stringify") and
|
||||||
|
pred = call.getArgument(0) and
|
||||||
|
succ = call
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
from AuthKeyTracking cfg, PathNode source, PathNode sink
|
||||||
|
where cfg.hasFlowPath(source, sink)
|
||||||
|
select sink.getNode(), source, sink, "Message leaks the authKey from $@.", source.getNode(), "here"
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* @name Extension of standard query: Stored XSS
|
||||||
|
* @description Extends the standard Stored XSS query with an additional source.
|
||||||
|
* @kind path-problem
|
||||||
|
* @tags security
|
||||||
|
* @id js/examples/stored-xss
|
||||||
|
*/
|
||||||
|
|
||||||
|
import javascript
|
||||||
|
import DataFlow
|
||||||
|
import semmle.javascript.security.dataflow.StoredXss
|
||||||
|
import DataFlow::PathGraph
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data returned from a MySQL query, such as the `data` parameter in this example:
|
||||||
|
* ```
|
||||||
|
* let mysql = require('mysql');
|
||||||
|
* let connection = mysql.createConnection();
|
||||||
|
*
|
||||||
|
* connection.query(..., (e, data) => { ... });
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
class MysqlSource extends StoredXss::Source {
|
||||||
|
MysqlSource() {
|
||||||
|
this = moduleImport("mysql")
|
||||||
|
.getAMemberCall("createConnection")
|
||||||
|
.getAMethodCall("query")
|
||||||
|
.getCallback(1)
|
||||||
|
.getParameter(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
from StoredXss::Configuration cfg, PathNode source, PathNode sink
|
||||||
|
where cfg.hasFlowPath(source, sink)
|
||||||
|
select sink.getNode(), source, sink, "Stored XSS from $@.", source.getNode(), "database value."
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
/**
|
||||||
|
* @name Extension of standard query: Stored XSS (with TrackedNode)
|
||||||
|
* @description Extends the standard Stored XSS query with an additional source,
|
||||||
|
* using TrackedNode to track MySQL connections globally.
|
||||||
|
* @kind path-problem
|
||||||
|
* @tags security
|
||||||
|
* @id js/examples/stored-xss-trackednode
|
||||||
|
*/
|
||||||
|
|
||||||
|
import javascript
|
||||||
|
import DataFlow
|
||||||
|
import semmle.javascript.security.dataflow.StoredXss
|
||||||
|
import DataFlow::PathGraph
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An instance of `mysql.createConnection()`, tracked globally.
|
||||||
|
*/
|
||||||
|
class MysqlConnection extends TrackedNode {
|
||||||
|
MysqlConnection() { this = moduleImport("mysql").getAMemberCall("createConnection") }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a call to the `query` method on this connection object.
|
||||||
|
*/
|
||||||
|
MethodCallNode getAQueryCall() {
|
||||||
|
this.flowsTo(result.getReceiver()) and
|
||||||
|
result.getMethodName() = "query"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data returned from a MySQL query.
|
||||||
|
*
|
||||||
|
* For example:
|
||||||
|
* ```
|
||||||
|
* let mysql = require('mysql');
|
||||||
|
*
|
||||||
|
* getData(mysql.createConnection());
|
||||||
|
*
|
||||||
|
* function getData(c) {
|
||||||
|
* c.query(..., (e, data) => { ... });
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
class MysqlSource extends StoredXss::Source {
|
||||||
|
MysqlSource() { this = any(MysqlConnection con).getAQueryCall().getCallback(1).getParameter(1) }
|
||||||
|
}
|
||||||
|
|
||||||
|
from StoredXss::Configuration cfg, PathNode source, PathNode sink
|
||||||
|
where cfg.hasFlowPath(source, sink)
|
||||||
|
select sink.getNode(), source, sink, "Stored XSS from $@.", source.getNode(), "database value."
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
/**
|
||||||
|
* @name Template injection
|
||||||
|
* @description Tracks user-controlled values to an unescaped lodash template placeholder.
|
||||||
|
* @kind path-problem
|
||||||
|
* @tags security
|
||||||
|
* @id js/examples/template-injection
|
||||||
|
*/
|
||||||
|
|
||||||
|
import javascript
|
||||||
|
import DataFlow
|
||||||
|
import DataFlow::PathGraph
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the name of an unescaped placeholder in a lodash template.
|
||||||
|
*
|
||||||
|
* For example, the string `<h1><%= title %></h1>` contains the placeholder `title`.
|
||||||
|
*/
|
||||||
|
bindingset[s]
|
||||||
|
string getAPlaceholderInString(string s) {
|
||||||
|
result = s.regexpCapture(".*<%=\\s*([a-zA-Z0-9_]+)\\s*%>.*", 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
class TemplateInjection extends TaintTracking::Configuration {
|
||||||
|
TemplateInjection() { this = "TemplateInjection" }
|
||||||
|
|
||||||
|
override predicate isSource(Node node) { node instanceof RemoteFlowSource }
|
||||||
|
|
||||||
|
override predicate isSink(Node node) {
|
||||||
|
exists(CallNode call, string placeholder |
|
||||||
|
call = LodashUnderscore::member("template").getACall() and
|
||||||
|
placeholder = getAPlaceholderInString(call.getArgument(0).getStringValue()) and
|
||||||
|
node = call.getOptionArgument(1, placeholder)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
from TemplateInjection cfg, PathNode source, PathNode sink
|
||||||
|
where cfg.hasFlowPath(source, sink)
|
||||||
|
select sink.getNode(), source, sink,
|
||||||
|
"User-controlled value from $@ occurs unescaped in a lodash template.", source.getNode(), "here."
|
||||||
13
javascript/ql/examples/snippets/argumentsparam.ql
Normal file
13
javascript/ql/examples/snippets/argumentsparam.ql
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* @id js/examples/argumentsparam
|
||||||
|
* @name Parameters called 'arguments'
|
||||||
|
* @description Finds parameters called 'arguments'
|
||||||
|
* @tags parameter
|
||||||
|
* arguments
|
||||||
|
*/
|
||||||
|
|
||||||
|
import javascript
|
||||||
|
|
||||||
|
from SimpleParameter p
|
||||||
|
where p.getName() = "arguments"
|
||||||
|
select p
|
||||||
14
javascript/ql/examples/snippets/call.ql
Normal file
14
javascript/ql/examples/snippets/call.ql
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* @id js/examples/call
|
||||||
|
* @name Calls to function
|
||||||
|
* @description Finds function calls of the form `eval(...)`
|
||||||
|
* @tags call
|
||||||
|
* function
|
||||||
|
* eval
|
||||||
|
*/
|
||||||
|
|
||||||
|
import javascript
|
||||||
|
|
||||||
|
from CallExpr c
|
||||||
|
where c.getCalleeName() = "eval"
|
||||||
|
select c
|
||||||
14
javascript/ql/examples/snippets/callback.ql
Normal file
14
javascript/ql/examples/snippets/callback.ql
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* @id js/examples/callback
|
||||||
|
* @name Callbacks
|
||||||
|
* @description Finds functions that are passed as arguments to other functions
|
||||||
|
* @tags function
|
||||||
|
* callback
|
||||||
|
* higher-order
|
||||||
|
*/
|
||||||
|
|
||||||
|
import javascript
|
||||||
|
|
||||||
|
from InvokeExpr invk, DataFlow::FunctionNode f
|
||||||
|
where f.flowsToExpr(invk.getAnArgument())
|
||||||
|
select invk, f
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user