mirror of
https://github.com/github/codeql.git
synced 2026-05-18 21:27:08 +02:00
Compare commits
45 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
05ef589b79 | ||
|
|
57dafe2734 | ||
|
|
313624fd2e | ||
|
|
79ff559f7a | ||
|
|
19a53cde79 | ||
|
|
3610d35321 | ||
|
|
b9c727c772 | ||
|
|
f159c7e240 | ||
|
|
ed49c623f1 | ||
|
|
4939db1c96 | ||
|
|
bfa4c30784 | ||
|
|
19f238a51a | ||
|
|
3291a30bf4 | ||
|
|
40ad2c9db9 | ||
|
|
d5c8ea38b1 | ||
|
|
778a484ce0 | ||
|
|
5e7b7818df | ||
|
|
c88db424fa | ||
|
|
3522200e90 | ||
|
|
de1556042a | ||
|
|
25224cc4a0 | ||
|
|
2e49cd117a | ||
|
|
f9634040b0 | ||
|
|
39c788f4f1 | ||
|
|
2abe34b2f9 | ||
|
|
cbf06ae74d | ||
|
|
4d7e762629 | ||
|
|
374fd597d7 | ||
|
|
b0425a298c | ||
|
|
5167d43fbc | ||
|
|
898ba94837 | ||
|
|
2b7d69aaf4 | ||
|
|
b282444740 | ||
|
|
5e75a62f5c | ||
|
|
e683b51611 | ||
|
|
de108a843d | ||
|
|
6a75ebbae2 | ||
|
|
d57e93d5c6 | ||
|
|
e2a001f925 | ||
|
|
11e03b3161 | ||
|
|
265852058d | ||
|
|
7691c0a345 | ||
|
|
6d77a791ac | ||
|
|
828d3cb138 | ||
|
|
1c71a856e1 |
@@ -52,13 +52,13 @@ Type stripType(Type t) {
|
||||
|
||||
/**
|
||||
* Holds if `t` points to `base` via a specified number of levels of pointer
|
||||
* indirection. Intermediate typedefs and array types are allowed.
|
||||
* indirection. Intermediate typedefs and array types are allowed. Note that
|
||||
* `base` is a stripped type (via `stripType`).
|
||||
*/
|
||||
predicate pointerIndirection(Type t, int indirection, Type base) {
|
||||
exists(Type u |
|
||||
u = stripType(t) and
|
||||
u = stripType(base) and
|
||||
not u instanceof PointerType and
|
||||
(
|
||||
base = stripType(t) and
|
||||
not base instanceof PointerType and
|
||||
indirection = 0
|
||||
) or (
|
||||
pointerIndirection(stripType(t).(PointerType).getBaseType(), indirection - 1, base)
|
||||
|
||||
@@ -11,10 +11,21 @@
|
||||
|
||||
import cpp
|
||||
|
||||
from Initializer init, Variable v, VariableAccess va
|
||||
where init.getDeclaration() = v
|
||||
and va.getTarget() = v
|
||||
and va.getParent*() = init
|
||||
class VariableAccessInInitializer extends VariableAccess {
|
||||
Variable var;
|
||||
Initializer init;
|
||||
VariableAccessInInitializer() {
|
||||
init.getDeclaration() = var and
|
||||
init.getExpr().getAChild*() = this
|
||||
}
|
||||
|
||||
predicate initializesItself(Variable v, Initializer i) {
|
||||
v = var and i = init and var = this.getTarget()
|
||||
}
|
||||
}
|
||||
|
||||
from Initializer init, Variable v, VariableAccessInInitializer va
|
||||
where va.initializesItself(v, init)
|
||||
and (
|
||||
va.hasLValueToRValueConversion() or
|
||||
exists (Assignment assn | assn.getLValue() = va) or
|
||||
|
||||
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: Semmle C/C++ Default Queries
|
||||
Bundle-SymbolicName: com.semmle.plugin.semmlecode.cpp.queries;singleton:=true
|
||||
Bundle-Version: 1.18.0
|
||||
Bundle-Version: 1.18.2
|
||||
Bundle-Vendor: Semmle Ltd.
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Require-Bundle: com.semmle.plugin.qdt.ui;bundle-version="[1.18.0,1.18.0]"
|
||||
Require-Bundle: com.semmle.plugin.qdt.ui;bundle-version="[1.18.2,1.18.2]"
|
||||
|
||||
@@ -107,15 +107,17 @@ predicate defUndef(File f, string macroName) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Header file `hf` looks like it contains an x-macro called
|
||||
* `macroName`. That is, a macro that is used to interpret the
|
||||
* Header file `hf` looks like it contains an x-macro.
|
||||
* That is, a macro that is used to interpret the
|
||||
* data in `hf`, usually defined just before including that file
|
||||
* and undefined immediately afterwards.
|
||||
*/
|
||||
predicate hasXMacro(HeaderFile hf, string macroName) {
|
||||
usesMacro(hf, macroName) and
|
||||
forex(Include i | i.getIncludedFile() = hf |
|
||||
defUndef(i.getFile(), macroName)
|
||||
predicate hasXMacro(HeaderFile hf) {
|
||||
exists(string macroName |
|
||||
usesMacro(hf, macroName) and
|
||||
forex(File f | f.getAnIncludedFile() = hf |
|
||||
defUndef(f, macroName)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -135,7 +137,7 @@ where not hf instanceof IncludeGuardedHeader
|
||||
exists(UsingEntry ue | ue.getFile() = hf)
|
||||
)
|
||||
// Exclude files which look like they contain 'x-macros'
|
||||
and not hasXMacro(hf, _)
|
||||
and not hasXMacro(hf)
|
||||
// Exclude files which are always #imported.
|
||||
and not forex(Include i | i.getIncludedFile() = hf | i instanceof Import)
|
||||
// Exclude files which are only included once.
|
||||
|
||||
@@ -1,28 +1,5 @@
|
||||
import cpp
|
||||
|
||||
/**
|
||||
* Holds if `sizeof(s)` occurs as part of the parameter of a dynamic
|
||||
* memory allocation (`malloc`, `realloc`, etc.), except if `sizeof(s)`
|
||||
* only ever occurs as the immediate parameter to allocations.
|
||||
*
|
||||
* For example, holds for `s` if it occurs as
|
||||
* ```
|
||||
* malloc(sizeof(s) + 100 * sizeof(char))
|
||||
* ```
|
||||
* but not if it only ever occurs as
|
||||
* ```
|
||||
* malloc(sizeof(s))
|
||||
* ```
|
||||
*/
|
||||
private predicate isDynamicallyAllocatedWithDifferentSize(Class s) {
|
||||
exists(SizeofTypeOperator sof |
|
||||
sof.getTypeOperand().getUnspecifiedType() = s |
|
||||
// Check all ancestor nodes except the immediate parent for
|
||||
// allocations.
|
||||
isStdLibAllocationExpr(sof.getParent().(Expr).getParent+())
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `v` is a member variable of `c` that looks like it might be variable sized in practice. For
|
||||
* example:
|
||||
@@ -33,15 +10,40 @@ private predicate isDynamicallyAllocatedWithDifferentSize(Class s) {
|
||||
* };
|
||||
* ```
|
||||
* This requires that `v` is an array of size 0 or 1, and `v` is the last member of `c`. In addition,
|
||||
* there must be at least one instance where a `c` pointer is allocated with additional space.
|
||||
* there must be at least one instance where a `c` pointer is allocated with additional space. For
|
||||
* example, holds for `c` if it occurs as
|
||||
* ```
|
||||
* malloc(sizeof(c) + 100 * sizeof(char))
|
||||
* ```
|
||||
* but not if it only ever occurs as
|
||||
* ```
|
||||
* malloc(sizeof(c))
|
||||
* ```
|
||||
*/
|
||||
predicate memberMayBeVarSize(Class c, MemberVariable v) {
|
||||
exists(int i |
|
||||
// `v` is the last field in `c`
|
||||
i = max(int j | c.getCanonicalMember(j) instanceof Field | j) and
|
||||
v = c.getCanonicalMember(i) and
|
||||
v.getType().getUnspecifiedType().(ArrayType).getSize() <= 1
|
||||
) and
|
||||
isDynamicallyAllocatedWithDifferentSize(c)
|
||||
|
||||
// v is an array of size at most 1
|
||||
v.getType().getUnspecifiedType().(ArrayType).getArraySize() <= 1
|
||||
) and (
|
||||
exists(SizeofOperator so |
|
||||
// `sizeof(c)` is taken
|
||||
so.(SizeofTypeOperator).getTypeOperand().getUnspecifiedType() = c or
|
||||
so.(SizeofExprOperator).getExprOperand().getType().getUnspecifiedType() = c |
|
||||
|
||||
// arithmetic is performed on the result
|
||||
so.getParent*() instanceof AddExpr
|
||||
) or exists(AddressOfExpr aoe |
|
||||
// `&(c.v)` is taken
|
||||
aoe.getAddressable() = v
|
||||
) or exists(BuiltInOperationOffsetOf oo |
|
||||
// `offsetof(c, v)` using a builtin
|
||||
oo.getAChild().(VariableAccess).getTarget() = v
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -419,12 +419,17 @@ library class ExprEvaluator extends int {
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if the function `f` is considered by the analysis and may return `ret`. */
|
||||
pragma[noinline]
|
||||
private predicate interestingReturnValue(Function f, Expr ret) {
|
||||
interestingFunction(_, f) and
|
||||
returnStmt(f, ret)
|
||||
}
|
||||
|
||||
private int getFunctionValue(Function f) {
|
||||
interestingFunction(_, f)
|
||||
and
|
||||
// All returns must have the same int value
|
||||
// And it must have at least one return
|
||||
forex(Expr ret | returnStmt(f, ret) | result = getValueInternalNonSubExpr(ret))
|
||||
forex(Expr ret | interestingReturnValue(f, ret) | result = getValueInternalNonSubExpr(ret))
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,8 +31,11 @@ private cached module Cached {
|
||||
// or the node's predecessor has more than one successor,
|
||||
// then the node is the start of a new primitive basic block.
|
||||
or
|
||||
strictcount (Node pred, Node other
|
||||
| successors_extended(pred,node) and successors_extended(pred,other)) > 1
|
||||
strictcount(Node pred | successors_extended(pred, node)) > 1
|
||||
or
|
||||
exists(ControlFlowNode pred | successors_extended(pred, node) |
|
||||
strictcount(ControlFlowNode other | successors_extended(pred, other)) > 1
|
||||
)
|
||||
|
||||
// If the node has zero predecessors then it is the start of
|
||||
// a BB. However, the C++ AST contains many nodes with zero
|
||||
@@ -63,8 +66,14 @@ private cached module Cached {
|
||||
/** Holds if `node` is the `pos`th control-flow node in primitive basic block `bb`. */
|
||||
cached
|
||||
predicate primitive_basic_block_member(Node node, PrimitiveBasicBlock bb, int pos) {
|
||||
pos = getMemberIndex(node) and
|
||||
member_step*(bb, node)
|
||||
primitive_basic_block_entry_node(bb) and
|
||||
(
|
||||
pos = 0 and
|
||||
node = bb
|
||||
or
|
||||
pos = getMemberIndex(node) and
|
||||
member_step+(bb, node)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the number of control-flow nodes in the primitive basic block `bb`. */
|
||||
|
||||
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: Semmle C# Default Queries
|
||||
Bundle-SymbolicName: com.semmle.plugin.semmlecode.csharp.queries;singleton:=true
|
||||
Bundle-Version: 1.18.0
|
||||
Bundle-Version: 1.18.2
|
||||
Bundle-Vendor: Semmle Ltd.
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Require-Bundle: com.semmle.plugin.qdt.ui;bundle-version="[1.18.0,1.18.0]"
|
||||
Require-Bundle: com.semmle.plugin.qdt.ui;bundle-version="[1.18.2,1.18.2]"
|
||||
|
||||
@@ -2,8 +2,8 @@ Manifest-Version: 1.0
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: Semmle Default Java Queries
|
||||
Bundle-SymbolicName: com.semmle.plugin.semmlecode.queries;singleton:=true
|
||||
Bundle-Version: 1.18.0
|
||||
Bundle-Version: 1.18.2
|
||||
Bundle-Vendor: Semmle Ltd.
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Require-Bundle: com.semmle.plugin.qdt.ui;bundle-version="[1.18.0,1.18.0]"
|
||||
Require-Bundle: com.semmle.plugin.qdt.ui;bundle-version="[1.18.2,1.18.2]"
|
||||
|
||||
|
||||
@@ -25,9 +25,11 @@
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {string=} message
|
||||
* @param {string=} message
|
||||
* @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-17189187
|
||||
*/
|
||||
function DOMException() {}
|
||||
function DOMException(message, name) {}
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
|
||||
@@ -39,7 +39,7 @@ property of the name stored in variable <code>member</code>:
|
||||
|
||||
<p>
|
||||
However, this test is ineffective as written: the operator <code>!</code> binds more
|
||||
tighly than <code>in</code>, so it is applied first. Applying <code>!</code> to a
|
||||
tightly than <code>in</code>, so it is applied first. Applying <code>!</code> to a
|
||||
non-empty string yields <code>false</code>, so the <code>in</code> operator actually
|
||||
ends up checking whether <code>obj</code> contains a property called <code>"false"</code>.
|
||||
</p>
|
||||
|
||||
@@ -45,5 +45,4 @@ class OmittedArrayElement extends ArrayExpr {
|
||||
}
|
||||
|
||||
from OmittedArrayElement ae
|
||||
where not ae.getFile().getFileType().isTypeScript() // ignore quirks in TypeScript tokenizer
|
||||
select ae, "Avoid omitted array elements."
|
||||
@@ -36,8 +36,7 @@ where s.hasSemicolonInserted() and
|
||||
asi = strictcount(Stmt ss | asi(sc, ss, true)) and
|
||||
nstmt = strictcount(Stmt ss | asi(sc, ss, _)) and
|
||||
perc = ((1-asi/nstmt)*100).floor() and
|
||||
perc >= 90 and
|
||||
not s.getFile().getFileType().isTypeScript() // ignore some quirks in the TypeScript tokenizer
|
||||
perc >= 90
|
||||
select (LastLineOf)s, "Avoid automated semicolon insertion " +
|
||||
"(" + perc + "% of all statements in $@ have an explicit semicolon).",
|
||||
sc, "the enclosing " + sctype
|
||||
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: Semmle JavaScript Default Queries
|
||||
Bundle-SymbolicName: com.semmle.plugin.semmlecode.javascript.queries;singleton:=true
|
||||
Bundle-Version: 1.18.0
|
||||
Bundle-Version: 1.18.2
|
||||
Bundle-Vendor: Semmle Ltd.
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Require-Bundle: com.semmle.plugin.qdt.ui;bundle-version="[1.18.0,1.18.0]"
|
||||
Require-Bundle: com.semmle.plugin.qdt.ui;bundle-version="[1.18.2,1.18.2]"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @description Conditions that the user controls are not suited for making security-related decisions.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @precision high
|
||||
* @precision medium
|
||||
* @id js/user-controlled-bypass
|
||||
* @tags security
|
||||
* external/cwe/cwe-807
|
||||
@@ -83,8 +83,32 @@ predicate isTaintedGuardForSensitiveAction(Sink sink, DataFlow::Node source, Sen
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `e` effectively guards access to `action` by returning or throwing early.
|
||||
*
|
||||
* Example: `if (e) return; action(x)`.
|
||||
*/
|
||||
predicate isEarlyAbortGuard(Sink e, SensitiveAction action) {
|
||||
exists (IfStmt guard |
|
||||
// `e` is in the condition of an if-statement ...
|
||||
e.asExpr().getParentExpr*() = guard.getCondition() and
|
||||
// ... where the then-branch always throws or returns
|
||||
exists (Stmt abort |
|
||||
abort instanceof ThrowStmt or
|
||||
abort instanceof ReturnStmt |
|
||||
abort.nestedIn(guard) and
|
||||
abort.getBasicBlock().(ReachableBasicBlock).postDominates(guard.getThen().getBasicBlock() )
|
||||
) and
|
||||
// ... and the else-branch does not exist
|
||||
not exists (guard.getElse()) |
|
||||
// ... and `action` is outside the if-statement
|
||||
not action.asExpr().getEnclosingStmt().nestedIn(guard)
|
||||
)
|
||||
}
|
||||
|
||||
from DataFlow::Node source, DataFlow::Node sink, SensitiveAction action
|
||||
where isTaintedGuardForSensitiveAction(sink, source, action)
|
||||
where isTaintedGuardForSensitiveAction(sink, source, action) and
|
||||
not isEarlyAbortGuard(sink, action)
|
||||
select sink, "This condition guards a sensitive $@, but $@ controls it.",
|
||||
action, "action",
|
||||
source, "a user-provided value"
|
||||
|
||||
@@ -39,7 +39,6 @@ where misleadingIndentationCandidate(ctrl, s1, s2) and
|
||||
f.hasIndentation(ctrlStartLine, indent, _) and
|
||||
f.hasIndentation(startLine1, indent, _) and
|
||||
f.hasIndentation(startLine2, indent, _) and
|
||||
not s2 instanceof EmptyStmt and
|
||||
not f.getFileType().isTypeScript() // ignore quirks in TypeScript tokenizer
|
||||
not s2 instanceof EmptyStmt
|
||||
select (FirstLineOf)s2, "The indentation of this statement suggests that it is controlled by $@, while in fact it is not.",
|
||||
(FirstLineOf)ctrl, "this statement"
|
||||
@@ -27,7 +27,7 @@ class ES2015Module extends Module {
|
||||
|
||||
/** Gets an export declaration in this module. */
|
||||
ExportDeclaration getAnExport() {
|
||||
result.getContainer() = this
|
||||
result.getTopLevel() = this
|
||||
}
|
||||
|
||||
override Module getAnImportedModule() {
|
||||
@@ -55,7 +55,7 @@ class ES2015Module extends Module {
|
||||
/** An import declaration. */
|
||||
class ImportDeclaration extends Stmt, Import, @importdeclaration {
|
||||
override ES2015Module getEnclosingModule() {
|
||||
result = getContainer()
|
||||
result = getTopLevel()
|
||||
}
|
||||
|
||||
override PathExprInModule getImportedPath() {
|
||||
@@ -254,7 +254,7 @@ class BulkReExportDeclaration extends ReExportDeclaration, @exportalldeclaration
|
||||
* but we ignore this subtlety.
|
||||
*/
|
||||
private predicate isShadowedFromBulkExport(BulkReExportDeclaration reExport, string name) {
|
||||
exists (ExportNamedDeclaration other | other.getContainer() = reExport.getEnclosingModule() |
|
||||
exists (ExportNamedDeclaration other | other.getTopLevel() = reExport.getEnclosingModule() |
|
||||
other.getAnExportedDecl().getName() = name
|
||||
or
|
||||
other.getASpecifier().getExportedName() = name)
|
||||
|
||||
@@ -96,8 +96,7 @@ class AbstractProtoProperty extends AbstractProperty {
|
||||
* which in turn introduces a materialization.
|
||||
*/
|
||||
private AbstractValue getAnAssignedValue(AbstractValue b, string p) {
|
||||
exists (AnalyzedPropertyWrite apw, DataFlow::AnalyzedNode afn |
|
||||
apw.writes(b, p, afn) and
|
||||
result = afn.getALocalValue()
|
||||
exists (AnalyzedPropertyWrite apw |
|
||||
apw.writesValue(b, p, result)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -268,6 +268,12 @@ private class AnalyzedVariableExport extends AnalyzedPropertyWrite, DataFlow::Va
|
||||
propName = name and
|
||||
source = varDef.getSource().analyze()
|
||||
}
|
||||
|
||||
override predicate writesValue(AbstractValue baseVal, string propName, AbstractValue val) {
|
||||
baseVal = TAbstractExportsObject(export.getEnclosingModule()) and
|
||||
propName = name and
|
||||
val = varDef.getAnAssignedValue()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -301,7 +307,7 @@ private class AnalyzedExportAssign extends AnalyzedPropertyWrite, DataFlow::Valu
|
||||
}
|
||||
|
||||
override predicate writes(AbstractValue baseVal, string propName, DataFlow::AnalyzedNode source) {
|
||||
baseVal = TAbstractModuleObject(exportAssign.getContainer()) and
|
||||
baseVal = TAbstractModuleObject(exportAssign.getTopLevel()) and
|
||||
propName = "exports" and
|
||||
source = this
|
||||
}
|
||||
|
||||
@@ -160,18 +160,26 @@ private class IIFEWithAnalyzedReturnFlow extends CallWithAnalyzedReturnFlow {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the only access to `v`, which is the variable declared by `fn`.
|
||||
*
|
||||
* This predicate is not defined for global functions `fn`, or for
|
||||
* local variables `v` that do not have exactly one access.
|
||||
*/
|
||||
private VarAccess getOnlyAccess(FunctionDeclStmt fn, LocalVariable v) {
|
||||
v = fn.getVariable() and
|
||||
result = v.getAnAccess() and
|
||||
strictcount(v.getAnAccess()) = 1
|
||||
}
|
||||
|
||||
/** A function that only is used locally, making it amenable to type inference. */
|
||||
class LocalFunction extends Function {
|
||||
|
||||
DataFlow::Impl::ExplicitInvokeNode invk;
|
||||
|
||||
LocalFunction() {
|
||||
this instanceof FunctionDeclStmt and
|
||||
exists (LocalVariable v, Expr callee |
|
||||
callee = invk.getCalleeNode().asExpr() and
|
||||
v = getVariable() and
|
||||
v.getAnAccess() = callee and
|
||||
forall(VarAccess o | o = v.getAnAccess() | o = callee) and
|
||||
exists (LocalVariable v |
|
||||
getOnlyAccess(this, v) = invk.getCalleeNode().asExpr() and
|
||||
not exists(v.getAnAssignedExpr()) and
|
||||
not exists(ExportDeclaration export | export.exportsAs(v, _))
|
||||
) and
|
||||
|
||||
@@ -96,8 +96,24 @@ abstract class AnalyzedPropertyWrite extends DataFlow::Node {
|
||||
/**
|
||||
* Holds if this property write assigns `source` to property `propName` of one of the
|
||||
* concrete objects represented by `baseVal`.
|
||||
*
|
||||
* Note that not all property writes have an explicit `source` node; use predicate
|
||||
* `writesValue` below to cover these cases.
|
||||
*/
|
||||
abstract predicate writes(AbstractValue baseVal, string propName, DataFlow::AnalyzedNode source);
|
||||
predicate writes(AbstractValue baseVal, string propName, DataFlow::AnalyzedNode source) {
|
||||
none()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this property write assigns `val` to property `propName` of one of the
|
||||
* concrete objects represented by `baseVal`.
|
||||
*/
|
||||
predicate writesValue(AbstractValue baseVal, string propName, AbstractValue val) {
|
||||
exists (AnalyzedNode source |
|
||||
writes(baseVal, propName, source) and
|
||||
val = source.getALocalValue()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the flow information for the base node of this property write is incomplete
|
||||
|
||||
@@ -387,3 +387,105 @@ private module Sequelize {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides classes modelling the Google Cloud Spanner library.
|
||||
*/
|
||||
private module Spanner {
|
||||
/**
|
||||
* Gets a node that refers to the `Spanner` class
|
||||
*/
|
||||
DataFlow::SourceNode spanner() {
|
||||
// older versions
|
||||
result = DataFlow::moduleImport("@google-cloud/spanner")
|
||||
or
|
||||
// newer versions
|
||||
result = DataFlow::moduleMember("@google-cloud/spanner", "Spanner")
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a node that refers to an instance of the `Database` class.
|
||||
*/
|
||||
DataFlow::SourceNode database() {
|
||||
result = spanner().getAnInvocation().getAMethodCall("instance").getAMethodCall("database")
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a node that refers to an instance of the `v1.SpannerClient` class.
|
||||
*/
|
||||
DataFlow::SourceNode v1SpannerClient() {
|
||||
result = spanner().getAPropertyRead("v1").getAPropertyRead("SpannerClient").getAnInstantiation()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a node that refers to a transaction object.
|
||||
*/
|
||||
DataFlow::SourceNode transaction() {
|
||||
result = database().getAMethodCall("runTransaction").getCallback(0).getParameter(1)
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to a Spanner method that executes a SQL query.
|
||||
*/
|
||||
abstract class SqlExecution extends DatabaseAccess, DataFlow::InvokeNode {
|
||||
/**
|
||||
* Gets the position of the query argument; default is zero, which can be overridden
|
||||
* by subclasses.
|
||||
*/
|
||||
int getQueryArgumentPosition() {
|
||||
result = 0
|
||||
}
|
||||
|
||||
override DataFlow::Node getAQueryArgument() {
|
||||
result = getArgument(getQueryArgumentPosition()) or
|
||||
result = getOptionArgument(getQueryArgumentPosition(), "sql")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `Database.run`, `Database.runPartitionedUpdate` or `Database.runStream`.
|
||||
*/
|
||||
class DatabaseRunCall extends SqlExecution {
|
||||
DatabaseRunCall() {
|
||||
exists (string run | run = "run" or run = "runPartitionedUpdate" or run = "runStream" |
|
||||
this = database().getAMethodCall(run)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `Transaction.run`, `Transaction.runStream` or `Transaction.runUpdate`.
|
||||
*/
|
||||
class TransactionRunCall extends SqlExecution {
|
||||
TransactionRunCall() {
|
||||
exists (string run | run = "run" or run = "runStream" or run = "runUpdate" |
|
||||
this = transaction().getAMethodCall(run)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `v1.SpannerClient.executeSql` or `v1.SpannerClient.executeStreamingSql`.
|
||||
*/
|
||||
class ExecuteSqlCall extends SqlExecution {
|
||||
ExecuteSqlCall() {
|
||||
exists (string exec | exec = "executeSql" or exec = "executeStreamingSql" |
|
||||
this = v1SpannerClient().getAMethodCall(exec)
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getAQueryArgument() {
|
||||
// `executeSql` and `executeStreamingSql` do not accept query strings directly
|
||||
result = getOptionArgument(0, "sql")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression that is interpreted as a SQL string.
|
||||
*/
|
||||
class QueryString extends SQL::SqlString {
|
||||
QueryString() {
|
||||
this = any(SqlExecution se).getAQueryArgument().asExpr()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,12 @@
|
||||
| ChatListScreen.js:3:1:5:1 | instance of function foo |
|
||||
| a2.js:1:1:2:0 | exports object of module a2 |
|
||||
| a2.js:1:1:2:0 | module object of module a2 |
|
||||
| a.js:1:1:13:0 | exports object of module a |
|
||||
| a.js:1:1:13:0 | module object of module a |
|
||||
| a.js:1:1:18:0 | exports object of module a |
|
||||
| a.js:1:1:18:0 | module object of module a |
|
||||
| a.js:3:8:5:1 | function setX |
|
||||
| a.js:3:8:5:1 | instance of function setX |
|
||||
| a.js:15:1:17:1 | function bump |
|
||||
| a.js:15:1:17:1 | instance of function bump |
|
||||
| amd2.js:1:1:4:0 | exports object of module amd2 |
|
||||
| amd2.js:1:1:4:0 | module object of module amd2 |
|
||||
| amd2.js:1:8:3:1 | anonymous function |
|
||||
@@ -36,8 +38,8 @@
|
||||
| arguments.js:30:2:33:1 | anonymous function |
|
||||
| arguments.js:30:2:33:1 | arguments object of anonymous function |
|
||||
| arguments.js:30:2:33:1 | instance of anonymous function |
|
||||
| b.js:1:1:55:0 | exports object of module b |
|
||||
| b.js:1:1:55:0 | module object of module b |
|
||||
| b.js:1:1:58:0 | exports object of module b |
|
||||
| b.js:1:1:58:0 | module object of module b |
|
||||
| backend.js:1:1:3:0 | exports object of module backend |
|
||||
| backend.js:1:1:3:0 | module object of module backend |
|
||||
| backend.js:1:17:1:18 | object literal |
|
||||
@@ -180,6 +182,10 @@
|
||||
| n.js:3:16:3:23 | object literal |
|
||||
| namespace-reexport.js:1:1:4:0 | exports object of module namespace-reexport |
|
||||
| namespace-reexport.js:1:1:4:0 | module object of module namespace-reexport |
|
||||
| nestedImport.js:1:1:13:0 | exports object of module nestedImport |
|
||||
| nestedImport.js:1:1:13:0 | module object of module nestedImport |
|
||||
| nestedImport.js:9:1:12:1 | function tst |
|
||||
| nestedImport.js:9:1:12:1 | instance of function tst |
|
||||
| nodeJsClient.js:1:1:6:0 | exports object of module nodeJsClient |
|
||||
| nodeJsClient.js:1:1:6:0 | module object of module nodeJsClient |
|
||||
| nodeJsLib.js:1:1:4:0 | exports object of module nodeJsLib |
|
||||
|
||||
@@ -10,3 +10,8 @@ let z = someGlobal;
|
||||
|
||||
export let w;
|
||||
w = "w";
|
||||
|
||||
export let notAlwaysZero = 0;
|
||||
function bump() {
|
||||
++notAlwaysZero;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
| a.js:9:5:9:5 | z | a.js:9:9:9:18 | someGlobal | file://:0:0:0:0 | indefinite value (global) |
|
||||
| a.js:9:5:9:5 | z | a.js:9:9:9:18 | someGlobal | file://:0:0:0:0 | non-zero value |
|
||||
| a.js:9:5:9:5 | z | a.js:9:9:9:18 | someGlobal | file://:0:0:0:0 | true |
|
||||
| a.js:14:12:14:24 | notAlwaysZero | a.js:14:28:14:28 | 0 | file://:0:0:0:0 | 0 |
|
||||
| amd.js:2:7:2:7 | m | amd.js:2:11:2:13 | mod | amd.js:1:1:7:0 | module object of module amd |
|
||||
| amd.js:2:7:2:7 | m | amd.js:2:11:2:13 | mod | file://:0:0:0:0 | indefinite value (call) |
|
||||
| amd.js:3:7:3:7 | e | amd.js:3:11:3:13 | exp | amd.js:1:1:7:0 | exports object of module amd |
|
||||
@@ -54,9 +55,12 @@
|
||||
| b.js:42:5:42:7 | z11 | b.js:42:11:42:18 | toString | file://:0:0:0:0 | indefinite value (import) |
|
||||
| b.js:45:5:45:7 | z12 | b.js:45:11:45:12 | f2 | ts2.ts:1:1:6:0 | exports object of module ts2 |
|
||||
| b.js:45:5:45:7 | z12 | b.js:45:11:45:12 | f2 | ts2.ts:1:10:1:22 | anonymous function |
|
||||
| b.js:45:5:45:7 | z12 | b.js:45:11:45:12 | f2 | ts2.ts:4:12:4:13 | object literal |
|
||||
| b.js:48:5:48:7 | z13 | b.js:48:11:48:11 | w | file://:0:0:0:0 | non-empty, non-numeric string |
|
||||
| b.js:51:5:51:7 | z14 | b.js:51:11:51:24 | foo_reexported | file://:0:0:0:0 | indefinite value (import) |
|
||||
| b.js:54:5:54:7 | z15 | b.js:54:11:54:19 | something | file://:0:0:0:0 | indefinite value (import) |
|
||||
| b.js:57:5:57:7 | z16 | b.js:57:11:57:23 | notAlwaysZero | file://:0:0:0:0 | 0 |
|
||||
| b.js:57:5:57:7 | z16 | b.js:57:11:57:23 | notAlwaysZero | file://:0:0:0:0 | non-zero value |
|
||||
| backend.js:1:7:1:13 | Backend | backend.js:1:17:1:18 | {} | backend.js:1:17:1:18 | object literal |
|
||||
| classAccessors.js:10:9:10:11 | myX | classAccessors.js:10:15:10:20 | this.x | file://:0:0:0:0 | indefinite value (call) |
|
||||
| classAccessors.js:10:9:10:11 | myX | classAccessors.js:10:15:10:20 | this.x | file://:0:0:0:0 | indefinite value (heap) |
|
||||
@@ -171,6 +175,10 @@
|
||||
| mixed.js:9:5:9:6 | fn | mixed.js:9:10:9:19 | __filename | file://:0:0:0:0 | numeric string |
|
||||
| mixed.js:10:5:10:6 | dn | mixed.js:10:10:10:18 | __dirname | file://:0:0:0:0 | non-empty, non-numeric string |
|
||||
| mixed.js:10:5:10:6 | dn | mixed.js:10:10:10:18 | __dirname | file://:0:0:0:0 | numeric string |
|
||||
| nestedImport.js:2:5:2:6 | x1 | nestedImport.js:2:10:2:12 | foo | esLib.js:3:8:3:24 | function foo |
|
||||
| nestedImport.js:6:7:6:8 | x2 | nestedImport.js:6:12:6:14 | foo | file://:0:0:0:0 | indefinite value (import) |
|
||||
| nestedImport.js:6:7:6:8 | x2 | nestedImport.js:6:12:6:14 | foo | nodeJsLib.js:3:15:3:37 | function nodeJsFoo |
|
||||
| nestedImport.js:11:7:11:8 | x3 | nestedImport.js:11:12:11:14 | foo | esLib.js:3:8:3:24 | function foo |
|
||||
| nodeJsClient.js:1:5:1:6 | nj | nodeJsClient.js:1:10:1:31 | require ... JsLib') | file://:0:0:0:0 | indefinite value (call) |
|
||||
| nodeJsClient.js:1:5:1:6 | nj | nodeJsClient.js:1:10:1:31 | require ... JsLib') | nodeJsLib.js:1:1:4:0 | exports object of module nodeJsLib |
|
||||
| nodeJsClient.js:1:5:1:6 | nj | nodeJsClient.js:1:10:1:31 | require ... JsLib') | nodeJsLib.js:1:18:1:43 | function nodeJsModule |
|
||||
|
||||
@@ -52,3 +52,6 @@ let z14 = foo_reexported;
|
||||
|
||||
import { something } from './reexport-unknown';
|
||||
let z15 = something;
|
||||
|
||||
import { notAlwaysZero } from './a';
|
||||
let z16 = notAlwaysZero;
|
||||
|
||||
12
javascript/ql/test/library-tests/Flow/nestedImport.js
Normal file
12
javascript/ql/test/library-tests/Flow/nestedImport.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import { foo } from './esLib';
|
||||
let x1 = foo;
|
||||
|
||||
if (!foo) {
|
||||
import { foo } from './nodeJsLib';
|
||||
let x2 = foo;
|
||||
}
|
||||
|
||||
function tst() {
|
||||
import { foo } from './esLib';
|
||||
let x3 = foo;
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
| a.js:1:12:1:12 | x | a.js:1:16:1:16 | 0 | number |
|
||||
| a.js:1:19:1:19 | y | a.js:1:23:1:23 | 0 | number |
|
||||
| a.js:9:5:9:5 | z | a.js:9:9:9:18 | someGlobal | boolean, class, date, function, null, number, object, regular expression,string or undefined |
|
||||
| a.js:14:12:14:24 | notAlwaysZero | a.js:14:28:14:28 | 0 | number |
|
||||
| amd.js:2:7:2:7 | m | amd.js:2:11:2:13 | mod | boolean, class, date, function, null, number, object, regular expression,string or undefined |
|
||||
| amd.js:3:7:3:7 | e | amd.js:3:11:3:13 | exp | boolean, class, date, function, null, number, object, regular expression,string or undefined |
|
||||
| arguments.js:2:7:2:7 | y | arguments.js:2:11:2:11 | x | number |
|
||||
@@ -32,6 +33,7 @@
|
||||
| b.js:48:5:48:7 | z13 | b.js:48:11:48:11 | w | string |
|
||||
| b.js:51:5:51:7 | z14 | b.js:51:11:51:24 | foo_reexported | boolean, class, date, function, null, number, object, regular expression,string or undefined |
|
||||
| b.js:54:5:54:7 | z15 | b.js:54:11:54:19 | something | boolean, class, date, function, null, number, object, regular expression,string or undefined |
|
||||
| b.js:57:5:57:7 | z16 | b.js:57:11:57:23 | notAlwaysZero | number |
|
||||
| backend.js:1:7:1:13 | Backend | backend.js:1:17:1:18 | {} | object |
|
||||
| classAccessors.js:10:9:10:11 | myX | classAccessors.js:10:15:10:20 | this.x | boolean, class, date, function, null, number, object, regular expression,string or undefined |
|
||||
| classAccessors.js:11:9:11:11 | myY | classAccessors.js:11:15:11:20 | this.y | boolean, class, date, function, null, number, object, regular expression,string or undefined |
|
||||
@@ -98,6 +100,9 @@
|
||||
| mixed.js:8:5:8:7 | exp | mixed.js:8:11:8:17 | exports | object |
|
||||
| mixed.js:9:5:9:6 | fn | mixed.js:9:10:9:19 | __filename | string |
|
||||
| mixed.js:10:5:10:6 | dn | mixed.js:10:10:10:18 | __dirname | string |
|
||||
| nestedImport.js:2:5:2:6 | x1 | nestedImport.js:2:10:2:12 | foo | function |
|
||||
| nestedImport.js:6:7:6:8 | x2 | nestedImport.js:6:12:6:14 | foo | boolean, class, date, function, null, number, object, regular expression,string or undefined |
|
||||
| nestedImport.js:11:7:11:8 | x3 | nestedImport.js:11:12:11:14 | foo | function |
|
||||
| nodeJsClient.js:1:5:1:6 | nj | nodeJsClient.js:1:10:1:31 | require ... JsLib') | boolean, class, date, function, null, number, object, regular expression,string or undefined |
|
||||
| nodeJsClient.js:2:5:2:6 | es | nodeJsClient.js:2:10:2:27 | require('./esLib') | boolean, class, date, function, null, number, object, regular expression,string or undefined |
|
||||
| nodeJsClient.js:4:5:4:6 | x1 | nodeJsClient.js:4:10:4:15 | nj.foo | boolean, class, date, function, null, number, object, regular expression,string or undefined |
|
||||
|
||||
@@ -18,4 +18,5 @@
|
||||
| ExpansiveMethod in expansive_signature.ts | has no properties |
|
||||
| ExpansiveParameter in expansive_signature.ts | has no properties |
|
||||
| ExpansiveSignature in expansive_signature.ts | has no properties |
|
||||
| ExpansiveSignatureTypeBound in expansive_signature.ts | has no properties |
|
||||
| ExpansiveX in used_from_expansion.ts | has no properties |
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
| ExpansiveMethod in expansive_signature.ts | has properties |
|
||||
| ExpansiveParameter in expansive_signature.ts | has properties |
|
||||
| ExpansiveSignature in expansive_signature.ts | has properties |
|
||||
| ExpansiveSignatureTypeBound in expansive_signature.ts | has properties |
|
||||
| ExpansiveX in used_from_expansion.ts | has properties |
|
||||
| Function in global scope | has properties |
|
||||
| Intl.CollatorOptions in global scope | has properties |
|
||||
|
||||
@@ -19,3 +19,7 @@ interface ExpansiveMethod<T> {
|
||||
interface ExpansiveFunctionType<T> {
|
||||
x: () => ExpansiveFunctionType<T[]>;
|
||||
}
|
||||
|
||||
interface ExpansiveSignatureTypeBound<T> {
|
||||
foo : { <G extends ExpansiveSignatureTypeBound<T[]>>(x: G): G };
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
| greaterThanTS.ts:2 | console . log ( x >= 1 ) ; |
|
||||
| greaterThanTS.ts:3 | console . log ( x >>= 1 ) ; |
|
||||
| greaterThanTS.ts:4 | console . log ( x >>>= 1 ) ; |
|
||||
| greaterThanTS.ts:5 | console . log ( x >> 1 ) ; |
|
||||
| greaterThanTS.ts:6 | console . log ( x >>> 1 ) ; |
|
||||
| greaterThanTS.ts:8 | console . log ( x >= 1 ) ; |
|
||||
| greaterThanTS.ts:9 | console . log ( x >= 1 ) ; |
|
||||
| greaterThanTS.ts:10 | console . log ( x >= 1 ) ; |
|
||||
| mixed.ts:2 | console . log ( x >= 1 ) ; |
|
||||
| mixed.ts:3 | console . log ( `${ /r/g >= 1 }` ) ; |
|
||||
| mixed.ts:4 | console . log ( /r/g ) ; |
|
||||
| mixed.ts:5 | console . log ( `${ 1 }${ 1 }` ) ; |
|
||||
| regexpTS.ts:2 | console . log ( /foo/g ) ; |
|
||||
| regexpTS.ts:3 | console . log ( /foo/g ) ; |
|
||||
| templateLiteralsJS.js:2 | console . log ( ` template~without~placeholders ` ) ; |
|
||||
| templateLiteralsJS.js:3 | console . log ( ` template~with~placeholder~ ${ x } . ` ) ; |
|
||||
| templateLiteralsTS.ts:2 | console . log ( `template~without~placeholders` ) ; |
|
||||
| templateLiteralsTS.ts:3 | console . log ( `template~with~placeholder~${ x }.` ) ; |
|
||||
| templateLiteralsTS.ts:4 | console . log ( `template~with~placeholder~${ x }.` ) ; |
|
||||
| templateLiteralsTS.ts:5 | console . log ( `template~with~placeholder~${ x }.` ) ; |
|
||||
| templateLiteralsTS.ts:6 | console . log ( `template~with~placeholder~${ x }.` ) ; |
|
||||
@@ -0,0 +1,15 @@
|
||||
import javascript
|
||||
|
||||
Token getATokenAtLine(File file, int line) {
|
||||
result.getFile() = file and
|
||||
result.getLocation().getStartLine() = line
|
||||
}
|
||||
|
||||
bindingset[line]
|
||||
string getTokenStringAtLine(File file, int line) {
|
||||
result = concat(Token tok | tok = getATokenAtLine(file, line) | tok.toString().replaceAll(" ", "~") + " " order by tok.getLocation().getStartColumn())
|
||||
}
|
||||
|
||||
from File file, int line
|
||||
where exists(CallExpr call | call.getFile() = file and call.getLocation().getStartLine() = line)
|
||||
select file.getBaseName() + ":" + line, getTokenStringAtLine(file, line)
|
||||
@@ -0,0 +1,11 @@
|
||||
function f(x) {
|
||||
console.log(x >= 1);
|
||||
console.log(x >>= 1);
|
||||
console.log(x >>>= 1);
|
||||
console.log(x >> 1);
|
||||
console.log(x >>> 1);
|
||||
|
||||
console.log(x>=1);
|
||||
console.log(x>= 1);
|
||||
console.log(x >=1);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
function f(x) {
|
||||
console.log(x >= 1);
|
||||
console.log(`${/r/g >= 1}`);
|
||||
console.log( /r/g);
|
||||
console.log( `${1}${1}`);
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
function f() {
|
||||
console.log(/foo/g);
|
||||
console.log( /foo/g);
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
function f(x) {
|
||||
console.log(`template without placeholders`);
|
||||
console.log(`template with placeholder ${x}.`);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
function f(x) {
|
||||
console.log(`template without placeholders`);
|
||||
console.log(`template with placeholder ${x}.`);
|
||||
console.log(`template with placeholder ${x }.`);
|
||||
console.log(`template with placeholder ${ x}.`);
|
||||
console.log(`template with placeholder ${ x }.`);
|
||||
}
|
||||
@@ -14,4 +14,24 @@
|
||||
| postgres3.js:15:16:15:40 | 'SELECT ... s name' |
|
||||
| sequelize2.js:10:17:10:118 | 'SELECT ... Y name' |
|
||||
| sequelize.js:8:17:8:118 | 'SELECT ... Y name' |
|
||||
| spanner2.js:5:26:5:35 | "SQL code" |
|
||||
| spanner2.js:7:35:7:44 | "SQL code" |
|
||||
| spanner.js:6:8:6:17 | "SQL code" |
|
||||
| spanner.js:7:8:7:26 | { sql: "SQL code" } |
|
||||
| spanner.js:7:15:7:24 | "SQL code" |
|
||||
| spanner.js:8:25:8:34 | "SQL code" |
|
||||
| spanner.js:9:25:9:43 | { sql: "SQL code" } |
|
||||
| spanner.js:9:32:9:41 | "SQL code" |
|
||||
| spanner.js:10:14:10:23 | "SQL code" |
|
||||
| spanner.js:11:14:11:31 | { sql: "SQL code"} |
|
||||
| spanner.js:11:21:11:30 | "SQL code" |
|
||||
| spanner.js:14:10:14:19 | "SQL code" |
|
||||
| spanner.js:15:10:15:28 | { sql: "SQL code" } |
|
||||
| spanner.js:15:17:15:26 | "SQL code" |
|
||||
| spanner.js:16:16:16:25 | "SQL code" |
|
||||
| spanner.js:17:16:17:34 | { sql: "SQL code" } |
|
||||
| spanner.js:17:23:17:32 | "SQL code" |
|
||||
| spanner.js:18:16:18:25 | "SQL code" |
|
||||
| spanner.js:19:16:19:34 | { sql: "SQL code" } |
|
||||
| spanner.js:19:23:19:32 | "SQL code" |
|
||||
| sqlite.js:7:8:7:45 | "UPDATE ... id = ?" |
|
||||
|
||||
20
javascript/ql/test/library-tests/frameworks/SQL/spanner.js
Normal file
20
javascript/ql/test/library-tests/frameworks/SQL/spanner.js
Normal file
@@ -0,0 +1,20 @@
|
||||
const { Spanner } = require("@google-cloud/spanner");
|
||||
const spanner = new Spanner();
|
||||
const instance = spanner.instance('inst');
|
||||
const db = instance.database('db');
|
||||
|
||||
db.run("SQL code", (err, rows) => {});
|
||||
db.run({ sql: "SQL code" }, (err, rows) => {});
|
||||
db.runPartitionedUpdate("SQL code", (err, rows) => {});
|
||||
db.runPartitionedUpdate({ sql: "SQL code" }, (err, rows) => {});
|
||||
db.runStream("SQL code");
|
||||
db.runStream({ sql: "SQL code"});
|
||||
|
||||
db.runTransaction((err, tx) => {
|
||||
tx.run("SQL code");
|
||||
tx.run({ sql: "SQL code" });
|
||||
tx.runStream("SQL code");
|
||||
tx.runStream({ sql: "SQL code" });
|
||||
tx.runUpdate("SQL code");
|
||||
tx.runUpdate({ sql: "SQL code" });
|
||||
});
|
||||
@@ -0,0 +1,7 @@
|
||||
const spanner = require("@google-cloud/spanner");
|
||||
const client = new spanner.v1.SpannerClient({});
|
||||
|
||||
client.executeSql("not SQL code", (err, rows) => {});
|
||||
client.executeSql({ sql: "SQL code" }, (err, rows) => {});
|
||||
client.executeStreamingSql("not SQL code", (err, rows) => {});
|
||||
client.executeStreamingSql({ sql: "SQL code" }, (err, rows) => {});
|
||||
@@ -1,12 +0,0 @@
|
||||
function foo(arg) {
|
||||
console.log(arg);
|
||||
console.log(arg);
|
||||
console.log(arg);
|
||||
console.log(arg);
|
||||
console.log(arg);
|
||||
console.log(arg);
|
||||
console.log(arg);
|
||||
console.log(arg);
|
||||
console.log(arg);
|
||||
console.log(`Unknown option '${arg}'.`);
|
||||
}
|
||||
@@ -10,3 +10,5 @@
|
||||
| tst.js:76:9:76:10 | v1 | This condition guards a sensitive $@, but $@ controls it. | tst.js:78:9:78:22 | process.exit() | action | tst.js:75:14:75:24 | req.cookies | a user-provided value |
|
||||
| tst.js:76:9:76:10 | v1 | This condition guards a sensitive $@, but $@ controls it. | tst.js:78:9:78:22 | process.exit() | action | tst.js:75:39:75:58 | req.params.requestId | a user-provided value |
|
||||
| tst.js:90:9:90:41 | req.coo ... secret" | This condition guards a sensitive $@, but $@ controls it. | tst.js:92:9:92:22 | process.exit() | action | tst.js:90:9:90:19 | req.cookies | a user-provided value |
|
||||
| tst.js:111:13:111:32 | req.query.vulnerable | This condition guards a sensitive $@, but $@ controls it. | tst.js:114:9:114:16 | verify() | action | tst.js:111:13:111:32 | req.query.vulnerable | a user-provided value |
|
||||
| tst.js:118:13:118:32 | req.query.vulnerable | This condition guards a sensitive $@, but $@ controls it. | tst.js:121:13:121:20 | verify() | action | tst.js:118:13:118:32 | req.query.vulnerable | a user-provided value |
|
||||
|
||||
@@ -99,3 +99,34 @@ app.get('/user/:id', function(req, res) {
|
||||
console.log(commit.author().toString());
|
||||
}
|
||||
});
|
||||
|
||||
app.get('/user/:id', function(req, res) {
|
||||
if (!req.body || !username || !password || riskAssessnment == null) { // OK: early return below
|
||||
res.status(400).send({ error: '...', id: '...' });
|
||||
return
|
||||
}
|
||||
customerLogin.customerLogin(username, password, riskAssessment, clientIpAddress);
|
||||
|
||||
while (!verified) {
|
||||
if (req.query.vulnerable) { // NOT OK
|
||||
break;
|
||||
}
|
||||
verify();
|
||||
}
|
||||
|
||||
while (!verified) {
|
||||
if (req.query.vulnerable) { // NOT OK
|
||||
break;
|
||||
} else {
|
||||
verify();
|
||||
}
|
||||
}
|
||||
|
||||
while (!verified) {
|
||||
if (req.query.vulnerable) { // OK: early return
|
||||
return;
|
||||
}
|
||||
verify();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user