Add cookbook queries

This commit is contained in:
Arthur Baars
2019-07-25 13:30:50 +02:00
parent a1b4d09b42
commit 30860daac4
156 changed files with 2342 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
/**
* @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

View File

@@ -0,0 +1,16 @@
/**
* @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

View File

@@ -0,0 +1,15 @@
/**
* @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

View File

@@ -0,0 +1,14 @@
/**
* @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

View File

@@ -0,0 +1,15 @@
/**
* @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

View File

@@ -0,0 +1,19 @@
/**
* @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

View File

@@ -0,0 +1,13 @@
/**
* @name Empty blocks
* @description Finds empty block statements
* @tags empty
* block
* statement
*/
import cpp
from Block blk
where blk.getNumStmt() = 0
select blk

View File

@@ -0,0 +1,16 @@
/**
* @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

View File

@@ -0,0 +1,17 @@
/**
* @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

View File

@@ -0,0 +1,15 @@
/**
* @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

View File

@@ -0,0 +1,17 @@
/**
* @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

View File

@@ -0,0 +1,14 @@
/**
* @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

View File

@@ -0,0 +1,16 @@
/**
* @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

View File

@@ -0,0 +1,17 @@
/**
* @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

View File

@@ -0,0 +1 @@
<queries language="cpp"/>

View File

@@ -0,0 +1,13 @@
/**
* @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

View File

@@ -0,0 +1,12 @@
/**
* @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

View File

@@ -0,0 +1,16 @@
/**
* @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

View File

@@ -0,0 +1,14 @@
/**
* @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

View File

@@ -0,0 +1,14 @@
/**
* @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

View File

@@ -0,0 +1,13 @@
/**
* @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

View File

@@ -0,0 +1,14 @@
/**
* @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

View File

@@ -0,0 +1,15 @@
/**
* @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

View File

@@ -0,0 +1,17 @@
/**
* @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()

View File

@@ -0,0 +1,12 @@
/**
* @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

View File

@@ -0,0 +1,20 @@
/**
* @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

View File

@@ -0,0 +1,12 @@
/**
* @name Variable declared volatile
* @description Finds variables with a `volatile` modifier
* @tags variable
* volatile
*/
import cpp
from Variable f
where f.isVolatile()
select f

View File

@@ -0,0 +1,16 @@
/**
* @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

View File

@@ -0,0 +1,15 @@
/**
* @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

View File

@@ -0,0 +1,13 @@
/**
* @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

View File

@@ -0,0 +1,13 @@
/**
* @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

View File

@@ -0,0 +1,13 @@
/**
* @name Empty blocks
* @description Finds empty block statements.
* @tags empty
* block
* statement
*/
import csharp
from BlockStmt blk
where blk.isEmpty()
select blk

View File

@@ -0,0 +1,16 @@
/**
* @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

View File

@@ -0,0 +1,13 @@
/**
* @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

View File

@@ -0,0 +1,16 @@
/**
* @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

View File

@@ -0,0 +1,13 @@
/**
* @name Extern methods
* @description Finds methods that are 'extern'.
* @tags method
* native
* modifier
*/
import csharp
from Method m
where m.isExtern()
select m

View File

@@ -0,0 +1,14 @@
/**
* @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

View File

@@ -0,0 +1,12 @@
/**
* @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

View File

@@ -0,0 +1,14 @@
/**
* @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

View File

@@ -0,0 +1,15 @@
/**
* @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

View File

@@ -0,0 +1,18 @@
/**
* @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

View File

@@ -0,0 +1,14 @@
/**
* @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

View File

@@ -0,0 +1,12 @@
/**
* @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

View File

@@ -0,0 +1 @@
<queries language="csharp"/>

View File

@@ -0,0 +1,13 @@
/**
* @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

View File

@@ -0,0 +1,12 @@
/**
* @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

View File

@@ -0,0 +1,16 @@
/**
* @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

View File

@@ -0,0 +1,15 @@
/**
* @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

View File

@@ -0,0 +1,12 @@
/**
* @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

View File

@@ -0,0 +1,12 @@
/**
* @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

View File

@@ -0,0 +1,13 @@
/**
* @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

View File

@@ -0,0 +1,15 @@
/**
* @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

View File

@@ -0,0 +1,13 @@
/**
* @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

View File

@@ -0,0 +1,12 @@
/**
* @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

View File

@@ -0,0 +1,15 @@
/**
* @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

View File

@@ -0,0 +1,13 @@
/**
* @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

View File

@@ -0,0 +1,16 @@
/**
* @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

View File

@@ -0,0 +1,15 @@
/**
* @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

View File

@@ -0,0 +1,13 @@
/**
* @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

View File

@@ -0,0 +1,13 @@
/**
* @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

View File

@@ -0,0 +1,13 @@
/**
* @name Empty blocks
* @description Finds empty block statements
* @tags empty
* block
* statement
*/
import java
from Block blk
where blk.getNumStmt() = 0
select blk

View File

@@ -0,0 +1,16 @@
/**
* @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

View File

@@ -0,0 +1,13 @@
/**
* @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

View File

@@ -0,0 +1,16 @@
/**
* @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

View File

@@ -0,0 +1,14 @@
/**
* @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

View File

@@ -0,0 +1,12 @@
/**
* @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

View File

@@ -0,0 +1,14 @@
/**
* @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

View File

@@ -0,0 +1,14 @@
/**
* @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

View File

@@ -0,0 +1,13 @@
/**
* @name Native methods
* @description Finds methods that are native
* @tags method
* native
* modifier
*/
import java
from Method m
where m.isNative()
select m

View File

@@ -0,0 +1,18 @@
/**
* @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

View File

@@ -0,0 +1,14 @@
/**
* @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

View File

@@ -0,0 +1,13 @@
/**
* @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

View File

@@ -0,0 +1 @@
<queries language="java"/>

View File

@@ -0,0 +1,13 @@
/**
* @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

View File

@@ -0,0 +1,12 @@
/**
* @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

View File

@@ -0,0 +1,16 @@
/**
* @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

View File

@@ -0,0 +1,13 @@
/**
* @name Synchronized methods
* @description Finds methods that are synchronized
* @tags method
* synchronized
* modifier
*/
import java
from Method m
where m.isSynchronized()
select m

View File

@@ -0,0 +1,15 @@
/**
* @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

View File

@@ -0,0 +1,12 @@
/**
* @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"

View File

@@ -0,0 +1,12 @@
/**
* @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

View File

@@ -0,0 +1,13 @@
/**
* @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

View File

@@ -0,0 +1,15 @@
/**
* @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

View File

@@ -0,0 +1,13 @@
/**
* @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

View File

@@ -0,0 +1,15 @@
/**
* @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

View File

@@ -0,0 +1,12 @@
/**
* @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

View File

@@ -0,0 +1,15 @@
/**
* @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

View File

@@ -0,0 +1,13 @@
/**
* @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

View File

@@ -0,0 +1,12 @@
/**
* @name Parameters called 'arguments'
* @description Finds parameters called 'arguments'
* @tags parameter
* arguments
*/
import javascript
from SimpleParameter p
where p.getName() = "arguments"
select p

View File

@@ -0,0 +1,13 @@
/**
* @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

View File

@@ -0,0 +1,13 @@
/**
* @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

View File

@@ -0,0 +1,15 @@
/**
* @name Classes with a default constructor
* @description Finds classes that do not declare an explicit constructor
* @tags class
* constructor
* default constructor
* ECMAScript 6
* ECMAScript 2015
*/
import javascript
from ClassDefinition c
where c.getConstructor().isSynthetic()
select c

View File

@@ -0,0 +1,14 @@
/**
* @name Classes called 'File'
* @description Finds classes called 'File'
* @tags class
* name
* ECMAScript 6
* ECMAScript 2015
*/
import javascript
from ClassDefinition cd
where cd.getName() = "File"
select cd

View File

@@ -0,0 +1,16 @@
/**
* @name Constant property name in `[]` property access
* @description Finds property accesses using the square bracket notation
* where the property name is a constant string
* @tags property access
* computed
* brackets
* index
* constant
*/
import javascript
from IndexExpr idx
where idx.getIndex() instanceof StringLiteral
select idx

View File

@@ -0,0 +1,48 @@
/**
* @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/cookbook/backend-idor
*/
import javascript::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"

View File

@@ -0,0 +1,29 @@
/**
* @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/cookbook/decoding-after-sanitization
*/
import javascript::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"

View File

@@ -0,0 +1,51 @@
/**
* @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/cookbook/decoding-after-sanitization-generalized
*/
import javascript::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"

View File

@@ -0,0 +1,21 @@
/**
* @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/cookbook/eval-taint
*/
import javascript::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"

View File

@@ -0,0 +1,24 @@
/**
* @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/cookbook/eval-taint-path
*/
import javascript::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"

View File

@@ -0,0 +1,55 @@
/**
* @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/cookbook/information-disclosure
*/
import javascript::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"

View File

@@ -0,0 +1,34 @@
/**
* @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/cookbook/stored-xss
*/
import javascript::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."

Some files were not shown because too many files have changed in this diff Show More