mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Merge branch 'master' into master
This commit is contained in:
@@ -1,2 +1,2 @@
|
||||
[*.{ql,qll,qlref,dbscheme,qhelp,html,js,mjs,ts,json,yml}]
|
||||
[*]
|
||||
end_of_line = lf
|
||||
|
||||
63
.gitattributes
vendored
63
.gitattributes
vendored
@@ -1,23 +1,48 @@
|
||||
# The following file types will be normalized to LF line endings in the Git
|
||||
# database, and will keep those LF line endings in the working tree even on
|
||||
# Windows. Any other files will have whatever line endings they had when they
|
||||
# were committed. If you add new entries below, you should renormalize the
|
||||
# affected files by running the following from the root of this repo (requires
|
||||
# Git 2.16 or greater):
|
||||
# Text files will be normalized to LF line endings in the Git database, and will keep those LF line
|
||||
# endings in the working tree even on Windows. If you make changes below, you should renormalize the
|
||||
# affected files by running the following from the root of this repo (requires Git 2.16 or greater):
|
||||
#
|
||||
# git add --renormalize .
|
||||
# git status [just to show what files were renormalized]
|
||||
# git commit -m "Normalize line endings"
|
||||
#
|
||||
# Also, please update .editorconfig to handle any new entries as well.
|
||||
*.ql eol=lf
|
||||
*.qll eol=lf
|
||||
*.qlref eol=lf
|
||||
*.dbscheme eol=lf
|
||||
*.qhelp eol=lf
|
||||
*.html eol=lf
|
||||
*.js eol=lf
|
||||
*.mjs eol=lf
|
||||
*.ts eol=lf
|
||||
*.json eol=lf
|
||||
*.yml eol=lf
|
||||
|
||||
# Anything Git auto-detects as text gets normalized and checked out as LF
|
||||
* text=auto eol=lf
|
||||
|
||||
# Explicitly set a bunch of known extensions to text, in case auto detection gets confused.
|
||||
*.ql text
|
||||
*.qll text
|
||||
*.qlref text
|
||||
*.dbscheme text
|
||||
*.qhelp text
|
||||
*.html text
|
||||
*.htm text
|
||||
*.xhtml text
|
||||
*.xhtm text
|
||||
*.js text
|
||||
*.mjs text
|
||||
*.ts text
|
||||
*.json text
|
||||
*.yml text
|
||||
*.yaml text
|
||||
*.c text
|
||||
*.cpp text
|
||||
*.h text
|
||||
*.hpp text
|
||||
*.md text
|
||||
*.stats text
|
||||
*.xml text
|
||||
*.sh text
|
||||
*.pl text
|
||||
*.java text
|
||||
*.cs text
|
||||
*.py text
|
||||
*.lua text
|
||||
*.expected text
|
||||
|
||||
# Explicitly set a bunch of known extensions to binary, because Git < 2.10 will treat
|
||||
# `* text=auto eol=lf` as `* text eol=lf`
|
||||
*.png -text
|
||||
*.jpg -text
|
||||
*.jpeg -text
|
||||
*.gif -text
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -12,6 +12,4 @@
|
||||
/.vs/ql/v15/Browse.VC.opendb
|
||||
/.vs/ql/v15/Browse.VC.db
|
||||
/.vs/ProjectSettings.json
|
||||
/.vs/ql5/v15/Browse.VC.opendb
|
||||
/.vs/ql5/v15/Browse.VC.db
|
||||
/.vs/ql5/v15/.suo
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
| **Query** | **Expected impact** | **Change** |
|
||||
|----------------------------|------------------------|------------------------------------------------------------------|
|
||||
| *@name of query (Query ID)*| *Impact on results* | *How/why the query has changed* |
|
||||
| Resource not released in destructor | Fewer false positive results | Placement new is now excluded from the query. |
|
||||
|
||||
|
||||
## Changes to QL libraries
|
||||
|
||||
@@ -22,5 +22,6 @@
|
||||
| Regular expression injection | Fewer false-positive results | This rule now identifies calls to `String.prototype.search` with more precision. |
|
||||
| Unbound event handler receiver | Fewer false-positive results | This rule now recognizes additional ways class methods can be bound. |
|
||||
| Remote property injection | Fewer results | The precision of this rule has been revised to "medium". Results are no longer shown on LGTM by default. |
|
||||
| Missing CSRF middleware | Fewer false-positive results | This rule now recognizes additional CSRF protection middlewares. |
|
||||
|
||||
## Changes to QL libraries
|
||||
|
||||
@@ -21,17 +21,19 @@ import semmle.code.cpp.controlflow.SSA
|
||||
/**
|
||||
* Holds if `e` is either:
|
||||
* - a constant
|
||||
* - a char-typed expression, meaning it's a small number
|
||||
* - an array access to an array of constants
|
||||
* - flows from one of the above
|
||||
* In these cases the value of `e` is likely to be small and
|
||||
* controlled, so we consider it less likely to cause an overflow.
|
||||
*/
|
||||
predicate effectivelyConstant(Expr e) {
|
||||
predicate likelySmall(Expr e) {
|
||||
e.isConstant() or
|
||||
e.getType().getSize() <= 1 or
|
||||
e.(ArrayExpr).getArrayBase().getType().(ArrayType).getBaseType().isConst() or
|
||||
exists(SsaDefinition def, Variable v |
|
||||
def.getAUse(v) = e and
|
||||
effectivelyConstant(def.getDefiningValue(v))
|
||||
likelySmall(def.getDefiningValue(v))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -56,7 +58,7 @@ int getEffectiveMulOperands(MulExpr me) {
|
||||
result = count(Expr op |
|
||||
op = getMulOperand*(me) and
|
||||
not op instanceof MulExpr and
|
||||
not effectivelyConstant(op)
|
||||
not likelySmall(op)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
LPMALLOC pMalloc;
|
||||
HRESULT hr = CoGetMalloc(1, &pMalloc);
|
||||
|
||||
if (!hr)
|
||||
{
|
||||
// code ...
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>This query indicates that an <code>HRESULT</code> is being cast to a boolean type or vice versa.</p>
|
||||
<p>The typical success value (<code>S_OK</code>) of an <code>HRESULT</code> equals 0. However, 0 indicates failure for a boolean type.</p>
|
||||
<p>Casting an <code>HRESULT</code> to a boolean type and then using it in a test expression will yield an incorrect result.</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>To check if a call that returns an HRESULT succeeded use the <code>FAILED</code> macro.</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>In the following example, <code>HRESULT</code> is used in a test expression incorrectly as it may yield an incorrect result.</p>
|
||||
<sample src="HResultBooleanConversion.cpp" />
|
||||
|
||||
<p>To fix this issue, use the <code>FAILED</code> macro in the test expression.</p>
|
||||
</example>
|
||||
|
||||
<references>
|
||||
</references>
|
||||
|
||||
</qhelp>
|
||||
71
cpp/ql/src/Security/CWE/CWE-253/HResultBooleanConversion.ql
Normal file
71
cpp/ql/src/Security/CWE/CWE-253/HResultBooleanConversion.ql
Normal file
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* @name Cast between semantically different integer types: HRESULT to/from a Boolean type
|
||||
* @description Cast between semantically different integer types: HRESULT to/from a Boolean type.
|
||||
* Boolean types indicate success by a non-zero value, whereas success (S_OK) in HRESULT is indicated by a value of 0.
|
||||
* Casting an HRESULT to/from a Boolean type and then using it in a test expression will yield an incorrect result.
|
||||
* @kind problem
|
||||
* @id cpp/hresult-boolean-conversion
|
||||
* @problem.severity error
|
||||
* @precision high
|
||||
* @tags security
|
||||
* external/cwe/cwe-253
|
||||
* external/microsoft/C6214
|
||||
* external/microsoft/C6215
|
||||
* external/microsoft/C6216
|
||||
* external/microsoft/C6217
|
||||
* external/microsoft/C6230
|
||||
*/
|
||||
import cpp
|
||||
|
||||
predicate isHresultBooleanConverted( Expr e1, Cast e2 )
|
||||
{
|
||||
exists ( Type t1, Type t2 |
|
||||
t1 = e1.getType() and
|
||||
t2 = e2.getType() and
|
||||
((t1.hasName("bool") or t1.hasName("BOOL") or t1.hasName("_Bool")) and t2.hasName("HRESULT") or
|
||||
(t2.hasName("bool") or t2.hasName("BOOL") or t2.hasName("_Bool")) and t1.hasName("HRESULT")
|
||||
))
|
||||
}
|
||||
|
||||
predicate isHresultBooleanConverted( Expr e1 )
|
||||
{
|
||||
exists( Cast e2 |
|
||||
e2 = e1.getConversion() and
|
||||
isHresultBooleanConverted(e1, e2)
|
||||
)
|
||||
}
|
||||
|
||||
from Expr e1, string msg
|
||||
where exists
|
||||
(
|
||||
Cast e2 |
|
||||
e2 = e1.getConversion() |
|
||||
isHresultBooleanConverted( e1, e2 )
|
||||
and if e2.isImplicit() then ( msg = "Implicit conversion from " + e1.getType().toString() + " to " + e2.getType().toString())
|
||||
else ( msg = "Explicit conversion from " + e1.getType().toString() + " to " + e2.getType().toString())
|
||||
)
|
||||
or exists
|
||||
(
|
||||
ControlStructure ctls |
|
||||
ctls.getControllingExpr() = e1
|
||||
and e1.getType().(TypedefType).hasName("HRESULT")
|
||||
and not isHresultBooleanConverted(e1)
|
||||
and msg = "Direct usage of a type " + e1.getType().toString() + " as a conditional expression"
|
||||
)
|
||||
or
|
||||
(
|
||||
exists( BinaryLogicalOperation blop |
|
||||
blop.getAnOperand() = e1 |
|
||||
e1.getType().(TypedefType).hasName("HRESULT")
|
||||
and msg = "Usage of a type " + e1.getType().toString() + " as an argument of a binary logical operation"
|
||||
)
|
||||
or exists
|
||||
(
|
||||
UnaryLogicalOperation ulop |
|
||||
ulop.getAnOperand() = e1 |
|
||||
e1.getType().(TypedefType).hasName("HRESULT")
|
||||
and msg = "Usage of a type " + e1.getType().toString() + " as an argument of a unary logical operation"
|
||||
)
|
||||
and not isHresultBooleanConverted(e1)
|
||||
)
|
||||
select e1, msg
|
||||
@@ -10,33 +10,69 @@
|
||||
* external/cwe/cwe-404
|
||||
*/
|
||||
import cpp
|
||||
import Critical.NewDelete
|
||||
|
||||
// List pairs of functions that do resource acquisition/release
|
||||
// Extend this to add custom function pairs. As written the query
|
||||
// will only apply if the resource is the *return value* of the
|
||||
// first call and a *parameter* to the second. Other cases should
|
||||
// be handled differently.
|
||||
predicate resourceManagementPair(string acquire, string release) {
|
||||
|
||||
(acquire = "fopen" and release = "fclose")
|
||||
or
|
||||
(acquire = "open" and release = "close")
|
||||
or
|
||||
(acquire = "socket" and release = "close")
|
||||
|
||||
/**
|
||||
* An expression that acquires a resource, and the kind of resource that is acquired. The
|
||||
* kind of a resource indicates which acquisition/release expressions can be paired.
|
||||
*/
|
||||
predicate acquireExpr(Expr acquire, string kind) {
|
||||
exists(FunctionCall fc, Function f, string name |
|
||||
fc = acquire and
|
||||
f = fc.getTarget() and
|
||||
name = f.getName() and
|
||||
(
|
||||
(
|
||||
name = "fopen" and
|
||||
kind = "file"
|
||||
) or (
|
||||
name = "open" and
|
||||
kind = "file descriptor"
|
||||
) or (
|
||||
name = "socket" and
|
||||
kind = "file descriptor"
|
||||
)
|
||||
)
|
||||
) or (
|
||||
allocExpr(acquire, kind)
|
||||
)
|
||||
}
|
||||
|
||||
// List functions that return malloc-allocated memory. Customize
|
||||
// to list your own functions there
|
||||
predicate mallocFunction(Function malloc) {
|
||||
malloc.hasName("malloc") or malloc.hasName("calloc") or // Not realloc: doesn't acquire it, really
|
||||
malloc.hasName("strdup")
|
||||
}
|
||||
|
||||
private predicate isRelease(string release) {
|
||||
resourceManagementPair(_, release) or
|
||||
release = "free" or
|
||||
release = "delete"
|
||||
/**
|
||||
* An expression that releases a resource, and the kind of resource that is released. The
|
||||
* kind of a resource indicates which acquisition/release expressions can be paired.
|
||||
*/
|
||||
predicate releaseExpr(Expr release, Expr resource, string kind) {
|
||||
exists(FunctionCall fc, Function f, string name |
|
||||
fc = release and
|
||||
f = fc.getTarget() and
|
||||
name = f.getName() and
|
||||
(
|
||||
(
|
||||
name = "fclose" and
|
||||
resource = fc.getArgument(0) and
|
||||
kind = "file"
|
||||
) or (
|
||||
name = "close" and
|
||||
resource = fc.getArgument(0) and
|
||||
kind = "file descriptor"
|
||||
)
|
||||
)
|
||||
) or exists(string releaseKind |
|
||||
freeExpr(release, resource, releaseKind) and
|
||||
(
|
||||
(
|
||||
kind = "malloc" and
|
||||
releaseKind = "free"
|
||||
) or (
|
||||
kind = "new" and
|
||||
releaseKind = "delete"
|
||||
) or (
|
||||
kind = "new[]" and
|
||||
releaseKind = "delete[]"
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,35 +88,23 @@ Expr exprOrDereference(Expr e) {
|
||||
* Holds if the expression `e` releases expression `released`, whether directly
|
||||
* or via one or more function call(s).
|
||||
*/
|
||||
private predicate exprReleases(Expr e, Expr released, string releaseType) {
|
||||
private predicate exprReleases(Expr e, Expr released, string kind) {
|
||||
(
|
||||
// `e` is a call to a release function and `released` is any argument
|
||||
e.(FunctionCall).getTarget().getName() = releaseType and
|
||||
isRelease(releaseType) and
|
||||
e.(FunctionCall).getAnArgument() = released
|
||||
) or (
|
||||
// `e` is a call to `delete` and `released` is the target
|
||||
e.(DeleteExpr).getExpr() = released and
|
||||
releaseType = "delete"
|
||||
) or (
|
||||
// `e` is a call to `delete[]` and `released` is the target
|
||||
e.(DeleteArrayExpr).getExpr() = released and
|
||||
releaseType = "delete"
|
||||
// `e` is a call to a release function and `released` is the released argument
|
||||
releaseExpr(e, released, kind)
|
||||
) or exists(Function f, int arg |
|
||||
// `e` is a call to a function that releases one of it's parameters,
|
||||
// and `released` is the corresponding argument
|
||||
e.(FunctionCall).getTarget() = f and
|
||||
e.(FunctionCall).getArgument(arg) = released and
|
||||
exprReleases(_, exprOrDereference(f.getParameter(arg).getAnAccess()), releaseType)
|
||||
) or exists(Function f, Expr innerThis |
|
||||
exprReleases(_, exprOrDereference(f.getParameter(arg).getAnAccess()), kind)
|
||||
) or exists(Function f, ThisExpr innerThis |
|
||||
// `e` is a call to a method that releases `this`, and `released`
|
||||
// is the object that is called
|
||||
e.(FunctionCall).getTarget() = f and
|
||||
e.(FunctionCall).getQualifier() = exprOrDereference(released) and
|
||||
innerThis.getEnclosingFunction() = f and
|
||||
exprReleases(_, innerThis, releaseType) and
|
||||
innerThis instanceof ThisExpr and
|
||||
releaseType = "delete"
|
||||
exprReleases(_, innerThis, kind)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -109,28 +133,17 @@ class Resource extends MemberVariable {
|
||||
)
|
||||
}
|
||||
|
||||
predicate acquisitionWithRequiredRelease(Expr acquire, string releaseName) {
|
||||
acquire.(Assignment).getLValue() = this.getAnAccess() and
|
||||
predicate acquisitionWithRequiredRelease(Assignment acquireAssign, string kind) {
|
||||
// acquireAssign is an assignment to this resource
|
||||
acquireAssign.(Assignment).getLValue() = this.getAnAccess() and
|
||||
// Should be in this class, but *any* member method will do
|
||||
this.inSameClass(acquire) and
|
||||
this.inSameClass(acquireAssign) and
|
||||
// Check that it is an acquisition function and return the corresponding free
|
||||
(
|
||||
exists(Function f | f = acquire.(Assignment).getRValue().(FunctionCall).getTarget() and
|
||||
(resourceManagementPair(f.getName(), releaseName) or (mallocFunction(f) and (releaseName = "free" or releaseName = "delete")))
|
||||
)
|
||||
or
|
||||
(acquire = this.getANew() and releaseName = "delete")
|
||||
)
|
||||
acquireExpr(acquireAssign.getRValue(), kind)
|
||||
}
|
||||
|
||||
private Assignment getANew() {
|
||||
result.getLValue() = this.getAnAccess() and
|
||||
(result.getRValue() instanceof NewExpr or result.getRValue() instanceof NewArrayExpr) and
|
||||
this.inSameClass(result)
|
||||
}
|
||||
|
||||
Expr getAReleaseExpr(string releaseName) {
|
||||
exprReleases(result, this.getAnAccess(), releaseName)
|
||||
Expr getAReleaseExpr(string kind) {
|
||||
exprReleases(result, this.getAnAccess(), kind)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -68,10 +68,9 @@ class Parameter extends LocalScopeVariable, @parameter {
|
||||
*/
|
||||
private VariableDeclarationEntry getAnEffectiveDeclarationEntry() {
|
||||
if getFunction().isConstructedFrom(_)
|
||||
then exists (Parameter prototype
|
||||
| prototype = result.getVariable() and
|
||||
prototype.getIndex() = getIndex() and
|
||||
getFunction().isConstructedFrom(prototype.getFunction()))
|
||||
then exists (Function prototypeInstantiation
|
||||
| prototypeInstantiation.getParameter(getIndex()) = result.getVariable() and
|
||||
getFunction().isConstructedFrom(prototypeInstantiation))
|
||||
else result = getADeclarationEntry()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,23 +1,31 @@
|
||||
import semmle.code.cpp.Type
|
||||
|
||||
/** Holds if `d` is a complete class named `name`. */
|
||||
pragma[noinline]
|
||||
private string getTopLevelClassName(@usertype c) {
|
||||
isClass(c) and
|
||||
usertypes(c, result, _) and
|
||||
not namespacembrs(_, c) and // not in a namespace
|
||||
not member(_, _, c) and // not in some structure
|
||||
not class_instantiation(c, _) // not a template instantiation
|
||||
}
|
||||
|
||||
/** Holds if `d` is a unique complete class named `name`. */
|
||||
pragma[noinline]
|
||||
private predicate existsCompleteWithName(string name, @usertype d) {
|
||||
isClass(d) and
|
||||
is_complete(d) and
|
||||
usertypes(d, name, _)
|
||||
name = getTopLevelClassName(d) and
|
||||
strictcount(@usertype other | is_complete(other) and getTopLevelClassName(other) = name) = 1
|
||||
}
|
||||
|
||||
/** Holds if `c` is an incomplete class named `name`. */
|
||||
pragma[noinline]
|
||||
private predicate existsIncompleteWithName(string name, @usertype c) {
|
||||
isClass(c) and
|
||||
not is_complete(c) and
|
||||
usertypes(c, name, _)
|
||||
name = getTopLevelClassName(c)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `c` is an incomplete class, and there exists a complete class `d`
|
||||
* Holds if `c` is an incomplete class, and there exists a unique complete class `d`
|
||||
* with the same name.
|
||||
*/
|
||||
private predicate hasCompleteTwin(@usertype c, @usertype d) {
|
||||
@@ -30,10 +38,8 @@ private predicate hasCompleteTwin(@usertype c, @usertype d) {
|
||||
import Cached
|
||||
cached private module Cached {
|
||||
/**
|
||||
* If `c` is incomplete, and there exists a complete class with the same name,
|
||||
* then the result is that complete class. Otherwise, the result is `c`. If
|
||||
* multiple complete classes have the same name, this predicate may have
|
||||
* multiple results.
|
||||
* If `c` is incomplete, and there exists a unique complete class with the same name,
|
||||
* then the result is that complete class. Otherwise, the result is `c`.
|
||||
*/
|
||||
cached @usertype resolveClass(@usertype c) {
|
||||
hasCompleteTwin(c, result)
|
||||
|
||||
@@ -270,7 +270,7 @@ newtype TTranslatedElement =
|
||||
not ignoreExpr(initList) and
|
||||
isFirstValueInitializedElementInRange(initList, elementIndex) and
|
||||
elementCount =
|
||||
getNextExplicitlyInitializedElementAfter(initList, elementIndex) -
|
||||
getEndOfValueInitializedRange(initList, elementIndex) -
|
||||
elementIndex
|
||||
} or
|
||||
// The initialization of a base class from within a constructor.
|
||||
@@ -322,23 +322,30 @@ newtype TTranslatedElement =
|
||||
|
||||
/**
|
||||
* Gets the index of the first explicitly initialized element in `initList`
|
||||
* whose index is greater than `afterElementIndex`. If there are no remaining
|
||||
* explicitly initialized elements in `initList`, the result is the total number
|
||||
* of elements in the array being initialized.
|
||||
* whose index is greater than `afterElementIndex`, where `afterElementIndex`
|
||||
* is a first value-initialized element in a value-initialized range in
|
||||
* `initList`. If there are no remaining explicitly initialized elements in
|
||||
* `initList`, the result is the total number of elements in the array being
|
||||
* initialized.
|
||||
*/
|
||||
private int getNextExplicitlyInitializedElementAfter(
|
||||
private int getEndOfValueInitializedRange(ArrayAggregateLiteral initList, int afterElementIndex) {
|
||||
result = getNextExplicitlyInitializedElementAfter(initList, afterElementIndex)
|
||||
or
|
||||
isFirstValueInitializedElementInRange(initList, afterElementIndex) and
|
||||
not exists(getNextExplicitlyInitializedElementAfter(initList, afterElementIndex)) and
|
||||
result = initList.getType().getUnspecifiedType().(ArrayType).getArraySize()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the index of the first explicitly initialized element in `initList`
|
||||
* whose index is greater than `afterElementIndex`, where `afterElementIndex`
|
||||
* is a first value-initialized element in a value-initialized range in
|
||||
* `initList`.
|
||||
*/
|
||||
private int getNextExplicitlyInitializedElementAfter(
|
||||
ArrayAggregateLiteral initList, int afterElementIndex) {
|
||||
if exists(int x |
|
||||
x > afterElementIndex and
|
||||
exists(initList.getElementExpr(x)))
|
||||
then (
|
||||
if exists(initList.getElementExpr(afterElementIndex + 1))
|
||||
then result = afterElementIndex + 1
|
||||
else result = getNextExplicitlyInitializedElementAfter(initList, afterElementIndex+1))
|
||||
else
|
||||
result = initList.getType().getUnspecifiedType().(ArrayType).getArraySize() and
|
||||
// required for binding
|
||||
initList.isInitialized(afterElementIndex)
|
||||
isFirstValueInitializedElementInRange(initList, afterElementIndex) and
|
||||
result = min(int i | exists(initList.getElementExpr(i)) and i > afterElementIndex)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6303,3 +6303,35 @@ ir.cpp:
|
||||
# 958| Type = int
|
||||
# 958| ValueCategory = prvalue(load)
|
||||
# 959| 8: return ...
|
||||
# 961| designatedInit() -> int
|
||||
# 961| params:
|
||||
# 961| body: { ... }
|
||||
# 962| 0: declaration
|
||||
# 962| 0: definition of a1
|
||||
# 962| Type = int[1000]
|
||||
# 962| init: initializer for a1
|
||||
# 962| expr: {...}
|
||||
# 962| Type = int[1000]
|
||||
# 962| ValueCategory = prvalue
|
||||
# 962| 0: 10002
|
||||
# 962| Type = int
|
||||
# 962| Value = 10002
|
||||
# 962| ValueCategory = prvalue
|
||||
# 962| 1: 10900
|
||||
# 962| Type = int
|
||||
# 962| Value = 10900
|
||||
# 962| ValueCategory = prvalue
|
||||
# 963| 1: return ...
|
||||
# 963| 0: access to array
|
||||
# 963| Type = int
|
||||
# 963| ValueCategory = prvalue(load)
|
||||
# 963| 0: array to pointer conversion
|
||||
# 963| Type = int *
|
||||
# 963| ValueCategory = prvalue
|
||||
# 963| expr: a1
|
||||
# 963| Type = int[1000]
|
||||
# 963| ValueCategory = lvalue
|
||||
# 963| 1: 900
|
||||
# 963| Type = int
|
||||
# 963| Value = 900
|
||||
# 963| ValueCategory = prvalue
|
||||
|
||||
@@ -3906,3 +3906,49 @@ ir.cpp:
|
||||
# 950| v0_65(void) = ReturnVoid :
|
||||
# 950| v0_66(void) = UnmodeledUse : mu*
|
||||
# 950| v0_67(void) = ExitFunction :
|
||||
|
||||
# 961| designatedInit() -> int
|
||||
# 961| Block 0
|
||||
# 961| v0_0(void) = EnterFunction :
|
||||
# 961| mu0_1(unknown) = UnmodeledDefinition :
|
||||
# 962| r0_2(glval<int[1000]>) = VariableAddress[a1] :
|
||||
# 962| r0_3(int) = Constant[0] :
|
||||
# 962| r0_4(glval<int>) = PointerAdd : r0_2, r0_3
|
||||
# 962| r0_5(unknown[8]) = Constant[0] :
|
||||
# 962| mu0_6(unknown[8]) = Store : r0_4, r0_5
|
||||
#-----| Goto -> Block 2
|
||||
|
||||
# 962| Block 1
|
||||
# 962| r1_0(int) = Constant[900] :
|
||||
# 962| r1_1(glval<int>) = PointerAdd : r0_2, r1_0
|
||||
# 962| r1_2(int) = Constant[10900] :
|
||||
# 962| mu1_3(int) = Store : r1_1, r1_2
|
||||
# 962| r1_4(int) = Constant[901] :
|
||||
# 962| r1_5(glval<int>) = PointerAdd : r0_2, r1_4
|
||||
# 962| r1_6(unknown[396]) = Constant[0] :
|
||||
# 962| mu1_7(unknown[396]) = Store : r1_5, r1_6
|
||||
#-----| Goto -> Block 2
|
||||
|
||||
# 963| Block 2
|
||||
# 963| r2_0(glval<int>) = VariableAddress[#return] :
|
||||
# 963| r2_1(glval<int[1000]>) = VariableAddress[a1] :
|
||||
# 963| r2_2(int *) = Convert : r2_1
|
||||
# 963| r2_3(int) = Constant[900] :
|
||||
# 963| r2_4(int *) = PointerAdd[4] : r2_2, r2_3
|
||||
# 963| r2_5(int) = Load : r2_4, mu0_1
|
||||
# 963| m2_6(int) = Store : r2_0, r2_5
|
||||
# 961| r2_7(glval<int>) = VariableAddress[#return] :
|
||||
# 961| v2_8(void) = ReturnValue : r2_7, m2_6
|
||||
# 961| v2_9(void) = UnmodeledUse : mu*
|
||||
# 961| v2_10(void) = ExitFunction :
|
||||
|
||||
# 962| Block 3
|
||||
# 962| r3_0(int) = Constant[2] :
|
||||
# 962| r3_1(glval<int>) = PointerAdd : r0_2, r3_0
|
||||
# 962| r3_2(int) = Constant[10002] :
|
||||
# 962| mu3_3(int) = Store : r3_1, r3_2
|
||||
# 962| r3_4(int) = Constant[3] :
|
||||
# 962| r3_5(glval<int>) = PointerAdd : r0_2, r3_4
|
||||
# 962| r3_6(unknown[3588]) = Constant[0] :
|
||||
# 962| mu3_7(unknown[3588]) = Store : r3_5, r3_6
|
||||
#-----| Goto -> Block 2
|
||||
|
||||
@@ -958,6 +958,11 @@ void OperatorNewArray(int n) {
|
||||
new int[n] { 0, 1, 2 };
|
||||
}
|
||||
|
||||
int designatedInit() {
|
||||
int a1[1000] = { [2] = 10002, [900] = 10900 };
|
||||
return a1[900];
|
||||
}
|
||||
|
||||
#if 0
|
||||
void OperatorDelete() {
|
||||
delete static_cast<int*>(nullptr); // No destructor
|
||||
|
||||
@@ -3885,3 +3885,49 @@ ir.cpp:
|
||||
# 950| v0_65(void) = ReturnVoid :
|
||||
# 950| v0_66(void) = UnmodeledUse : mu*
|
||||
# 950| v0_67(void) = ExitFunction :
|
||||
|
||||
# 961| designatedInit() -> int
|
||||
# 961| Block 0
|
||||
# 961| v0_0(void) = EnterFunction :
|
||||
# 961| mu0_1(unknown) = UnmodeledDefinition :
|
||||
# 962| r0_2(glval<int[1000]>) = VariableAddress[a1] :
|
||||
# 962| r0_3(int) = Constant[0] :
|
||||
# 962| r0_4(glval<int>) = PointerAdd : r0_2, r0_3
|
||||
# 962| r0_5(unknown[8]) = Constant[0] :
|
||||
# 962| mu0_6(unknown[8]) = Store : r0_4, r0_5
|
||||
#-----| Goto -> Block 2
|
||||
|
||||
# 962| Block 1
|
||||
# 962| r1_0(int) = Constant[900] :
|
||||
# 962| r1_1(glval<int>) = PointerAdd : r0_2, r1_0
|
||||
# 962| r1_2(int) = Constant[10900] :
|
||||
# 962| mu1_3(int) = Store : r1_1, r1_2
|
||||
# 962| r1_4(int) = Constant[901] :
|
||||
# 962| r1_5(glval<int>) = PointerAdd : r0_2, r1_4
|
||||
# 962| r1_6(unknown[396]) = Constant[0] :
|
||||
# 962| mu1_7(unknown[396]) = Store : r1_5, r1_6
|
||||
#-----| Goto -> Block 2
|
||||
|
||||
# 963| Block 2
|
||||
# 963| r2_0(glval<int>) = VariableAddress[#return] :
|
||||
# 963| r2_1(glval<int[1000]>) = VariableAddress[a1] :
|
||||
# 963| r2_2(int *) = Convert : r2_1
|
||||
# 963| r2_3(int) = Constant[900] :
|
||||
# 963| r2_4(int *) = PointerAdd[4] : r2_2, r2_3
|
||||
# 963| r2_5(int) = Load : r2_4, mu0_1
|
||||
# 963| mu2_6(int) = Store : r2_0, r2_5
|
||||
# 961| r2_7(glval<int>) = VariableAddress[#return] :
|
||||
# 961| v2_8(void) = ReturnValue : r2_7, mu0_1
|
||||
# 961| v2_9(void) = UnmodeledUse : mu*
|
||||
# 961| v2_10(void) = ExitFunction :
|
||||
|
||||
# 962| Block 3
|
||||
# 962| r3_0(int) = Constant[2] :
|
||||
# 962| r3_1(glval<int>) = PointerAdd : r0_2, r3_0
|
||||
# 962| r3_2(int) = Constant[10002] :
|
||||
# 962| mu3_3(int) = Store : r3_1, r3_2
|
||||
# 962| r3_4(int) = Constant[3] :
|
||||
# 962| r3_5(glval<int>) = PointerAdd : r0_2, r3_4
|
||||
# 962| r3_6(unknown[3588]) = Constant[0] :
|
||||
# 962| mu3_7(unknown[3588]) = Store : r3_5, r3_6
|
||||
#-----| Goto -> Block 2
|
||||
|
||||
@@ -92,6 +92,7 @@
|
||||
| IR: VarArgs | 1 |
|
||||
| IR: VirtualMemberFunction | 1 |
|
||||
| IR: WhileStatements | 4 |
|
||||
| IR: designatedInit | 4 |
|
||||
| IR: min | 4 |
|
||||
| IR: operator= | 1 |
|
||||
| IR: ~Base | 1 |
|
||||
|
||||
@@ -3906,3 +3906,49 @@ ir.cpp:
|
||||
# 950| v0_65(void) = ReturnVoid :
|
||||
# 950| v0_66(void) = UnmodeledUse : mu*
|
||||
# 950| v0_67(void) = ExitFunction :
|
||||
|
||||
# 961| designatedInit() -> int
|
||||
# 961| Block 0
|
||||
# 961| v0_0(void) = EnterFunction :
|
||||
# 961| mu0_1(unknown) = UnmodeledDefinition :
|
||||
# 962| r0_2(glval<int[1000]>) = VariableAddress[a1] :
|
||||
# 962| r0_3(int) = Constant[0] :
|
||||
# 962| r0_4(glval<int>) = PointerAdd : r0_2, r0_3
|
||||
# 962| r0_5(unknown[8]) = Constant[0] :
|
||||
# 962| mu0_6(unknown[8]) = Store : r0_4, r0_5
|
||||
#-----| Goto -> Block 2
|
||||
|
||||
# 962| Block 1
|
||||
# 962| r1_0(int) = Constant[900] :
|
||||
# 962| r1_1(glval<int>) = PointerAdd : r0_2, r1_0
|
||||
# 962| r1_2(int) = Constant[10900] :
|
||||
# 962| mu1_3(int) = Store : r1_1, r1_2
|
||||
# 962| r1_4(int) = Constant[901] :
|
||||
# 962| r1_5(glval<int>) = PointerAdd : r0_2, r1_4
|
||||
# 962| r1_6(unknown[396]) = Constant[0] :
|
||||
# 962| mu1_7(unknown[396]) = Store : r1_5, r1_6
|
||||
#-----| Goto -> Block 2
|
||||
|
||||
# 963| Block 2
|
||||
# 963| r2_0(glval<int>) = VariableAddress[#return] :
|
||||
# 963| r2_1(glval<int[1000]>) = VariableAddress[a1] :
|
||||
# 963| r2_2(int *) = Convert : r2_1
|
||||
# 963| r2_3(int) = Constant[900] :
|
||||
# 963| r2_4(int *) = PointerAdd[4] : r2_2, r2_3
|
||||
# 963| r2_5(int) = Load : r2_4, mu0_1
|
||||
# 963| m2_6(int) = Store : r2_0, r2_5
|
||||
# 961| r2_7(glval<int>) = VariableAddress[#return] :
|
||||
# 961| v2_8(void) = ReturnValue : r2_7, m2_6
|
||||
# 961| v2_9(void) = UnmodeledUse : mu*
|
||||
# 961| v2_10(void) = ExitFunction :
|
||||
|
||||
# 962| Block 3
|
||||
# 962| r3_0(int) = Constant[2] :
|
||||
# 962| r3_1(glval<int>) = PointerAdd : r0_2, r3_0
|
||||
# 962| r3_2(int) = Constant[10002] :
|
||||
# 962| mu3_3(int) = Store : r3_1, r3_2
|
||||
# 962| r3_4(int) = Constant[3] :
|
||||
# 962| r3_5(glval<int>) = PointerAdd : r0_2, r3_4
|
||||
# 962| r3_6(unknown[3588]) = Constant[0] :
|
||||
# 962| mu3_7(unknown[3588]) = Store : r3_5, r3_6
|
||||
#-----| Goto -> Block 2
|
||||
|
||||
@@ -24,3 +24,9 @@ class Damson {
|
||||
int damson_x;
|
||||
void foo();
|
||||
};
|
||||
|
||||
namespace unrelated {
|
||||
class AppleCompatible {
|
||||
long apple_x;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -32,6 +32,9 @@
|
||||
| b1.cpp:23:7:23:12 | Damson | 5 members | 2 locations | 1 | foo |
|
||||
| b1.cpp:23:7:23:12 | Damson | 5 members | 2 locations | 2 | operator= |
|
||||
| b1.cpp:23:7:23:12 | Damson | 5 members | 2 locations | 3 | operator= |
|
||||
| b1.cpp:29:9:29:23 | AppleCompatible | 3 members | 1 locations | 0 | apple_x |
|
||||
| b1.cpp:29:9:29:23 | AppleCompatible | 3 members | 1 locations | 1 | operator= |
|
||||
| b1.cpp:29:9:29:23 | AppleCompatible | 3 members | 1 locations | 2 | operator= |
|
||||
| b2.cpp:2:7:2:21 | AppleCompatible | 3 members | 2 locations | 0 | apple_x |
|
||||
| b2.cpp:2:7:2:21 | AppleCompatible | 3 members | 2 locations | 1 | operator= |
|
||||
| b2.cpp:2:7:2:21 | AppleCompatible | 3 members | 2 locations | 2 | operator= |
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
| b1.cpp:11:7:11:22 | BananaCompatible | 0 | file://:0:0:0:0 | int | 1 types |
|
||||
| b1.cpp:16:7:16:12 | Cherry | 0 | file://:0:0:0:0 | int | 1 types |
|
||||
| b1.cpp:23:7:23:12 | Damson | 0 | file://:0:0:0:0 | int | 1 types |
|
||||
| b1.cpp:29:9:29:23 | AppleCompatible | 0 | file://:0:0:0:0 | long | 1 types |
|
||||
| b2.cpp:2:7:2:21 | AppleCompatible | 0 | file://:0:0:0:0 | int | 1 types |
|
||||
| b2.cpp:9:7:9:22 | BananaCompatible | 0 | file://:0:0:0:0 | int | 1 types |
|
||||
| b2.cpp:14:7:14:12 | Cherry | 0 | file://:0:0:0:0 | short | 1 types |
|
||||
|
||||
@@ -1,2 +1,6 @@
|
||||
| a.h:5:8:5:13 | cheese | y.cpp:4:8:4:10 | Foo | 3 |
|
||||
| x.cpp:3:6:3:10 | bar_x | a.h:4:8:4:10 | Bar | 3 |
|
||||
| x.cpp:19:6:19:10 | foo_x | y.cpp:4:8:4:10 | Foo | 3 |
|
||||
| x.cpp:23:5:23:17 | templateField | x.cpp:6:10:6:12 | Foo | 3 |
|
||||
| x.cpp:23:5:23:17 | templateField | x.cpp:12:9:12:11 | Foo | 3 |
|
||||
| x.cpp:26:18:26:29 | template_foo | x.cpp:22:7:22:14 | Template<Foo *> | 0 |
|
||||
|
||||
@@ -1,3 +1,31 @@
|
||||
#include "a.h"
|
||||
|
||||
Bar *bar_x;
|
||||
|
||||
namespace unrelated {
|
||||
struct Foo {
|
||||
short val;
|
||||
};
|
||||
}
|
||||
|
||||
struct ContainsAnotherFoo {
|
||||
class Foo {
|
||||
long val;
|
||||
};
|
||||
};
|
||||
|
||||
// The type of `foo_x` should not refer to any of the above classes, none of
|
||||
// which are named `Foo` in the global scope.
|
||||
Foo *foo_x;
|
||||
|
||||
template<typename T>
|
||||
class Template {
|
||||
T templateField;
|
||||
};
|
||||
|
||||
Template<Foo *> *template_foo;
|
||||
|
||||
// Instantiation of the template with unrelated classes named `Foo` should not
|
||||
// get mixed up with the instantiation above.
|
||||
template class Template<unrelated::Foo *>;
|
||||
template class Template<ContainsAnotherFoo::Foo *>;
|
||||
|
||||
9
cpp/ql/test/library-tests/structs/qualified_names/c1.cpp
Normal file
9
cpp/ql/test/library-tests/structs/qualified_names/c1.cpp
Normal file
@@ -0,0 +1,9 @@
|
||||
#include "header.h"
|
||||
|
||||
struct MultipleDefsButSameHeader {
|
||||
int i;
|
||||
};
|
||||
|
||||
struct OneDefInDifferentFile {
|
||||
int i;
|
||||
};
|
||||
6
cpp/ql/test/library-tests/structs/qualified_names/c2.cpp
Normal file
6
cpp/ql/test/library-tests/structs/qualified_names/c2.cpp
Normal file
@@ -0,0 +1,6 @@
|
||||
#include "header.h"
|
||||
|
||||
struct MultipleDefsButSameHeader {
|
||||
char char1;
|
||||
char char2;
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
namespace foo {
|
||||
class C;
|
||||
|
||||
C *x;
|
||||
}
|
||||
29
cpp/ql/test/library-tests/structs/qualified_names/defs.cpp
Normal file
29
cpp/ql/test/library-tests/structs/qualified_names/defs.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
namespace foo {
|
||||
class C {
|
||||
};
|
||||
}
|
||||
|
||||
namespace bar {
|
||||
class C {
|
||||
};
|
||||
}
|
||||
|
||||
class DefinedAndDeclared {
|
||||
};
|
||||
|
||||
// Despite this declaration being present, the variable below is associated
|
||||
// with the definition above rather than this declaration.
|
||||
class DefinedAndDeclared;
|
||||
|
||||
DefinedAndDeclared *definedAndDeclared;
|
||||
|
||||
#include "header.h"
|
||||
|
||||
// Because there are multiple definitions of `MultipleDefsButSameHeader`, the
|
||||
// type of this variable will refer to the declaration in `header.h` rather
|
||||
// than any of the definitions.
|
||||
MultipleDefsButSameHeader *mdbsh;
|
||||
|
||||
// Because there is only one definition of `OneDefInDifferentFile`, the type of
|
||||
// this variable will refer to that definition.
|
||||
OneDefInDifferentFile *odidf;
|
||||
@@ -0,0 +1,3 @@
|
||||
struct MultipleDefsButSameHeader;
|
||||
|
||||
struct OneDefInDifferentFile;
|
||||
@@ -0,0 +1,4 @@
|
||||
| decls.cpp:4:6:4:6 | x | decls.cpp:2:9:2:9 | C |
|
||||
| defs.cpp:18:21:18:38 | definedAndDeclared | defs.cpp:11:7:11:24 | DefinedAndDeclared |
|
||||
| defs.cpp:25:28:25:32 | mdbsh | header.h:1:8:1:32 | MultipleDefsButSameHeader |
|
||||
| defs.cpp:29:24:29:28 | odidf | c1.cpp:7:8:7:28 | OneDefInDifferentFile |
|
||||
@@ -0,0 +1,5 @@
|
||||
import cpp
|
||||
|
||||
from Variable x
|
||||
where exists(x.getFile().getRelativePath())
|
||||
select x, x.getType().(PointerType).getBaseType()
|
||||
@@ -116,32 +116,13 @@
|
||||
| isfromtemplateinstantiation.cpp:134:29:134:29 | Outer<int>::operator=(const Outer<int> &) | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<int> |
|
||||
| isfromtemplateinstantiation.cpp:134:29:134:29 | declaration of operator= | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<int> |
|
||||
| isfromtemplateinstantiation.cpp:134:29:134:29 | declaration of operator= | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<int> |
|
||||
| isfromtemplateinstantiation.cpp:135:31:135:31 | Outer<T>::Inner<long>::operator=(Inner<long> &&) | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<int> |
|
||||
| isfromtemplateinstantiation.cpp:135:31:135:31 | Outer<T>::Inner<long>::operator=(Inner<long> &&) | isfromtemplateinstantiation.cpp:135:31:135:35 | Inner<long> |
|
||||
| isfromtemplateinstantiation.cpp:135:31:135:31 | Outer<T>::Inner<long>::operator=(const Inner<long> &) | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<int> |
|
||||
| isfromtemplateinstantiation.cpp:135:31:135:31 | Outer<T>::Inner<long>::operator=(const Inner<long> &) | isfromtemplateinstantiation.cpp:135:31:135:35 | Inner<long> |
|
||||
| isfromtemplateinstantiation.cpp:135:31:135:31 | Outer<int>::Inner<long>::operator=(Inner<long> &&) | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<int> |
|
||||
| isfromtemplateinstantiation.cpp:135:31:135:31 | Outer<int>::Inner<long>::operator=(Inner<long> &&) | isfromtemplateinstantiation.cpp:135:31:135:35 | Inner<long> |
|
||||
| isfromtemplateinstantiation.cpp:135:31:135:31 | Outer<int>::Inner<long>::operator=(const Inner<long> &) | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<int> |
|
||||
| isfromtemplateinstantiation.cpp:135:31:135:31 | Outer<int>::Inner<long>::operator=(const Inner<long> &) | isfromtemplateinstantiation.cpp:135:31:135:35 | Inner<long> |
|
||||
| isfromtemplateinstantiation.cpp:135:31:135:31 | declaration of operator= | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<int> |
|
||||
| isfromtemplateinstantiation.cpp:135:31:135:31 | declaration of operator= | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<int> |
|
||||
| isfromtemplateinstantiation.cpp:135:31:135:31 | declaration of operator= | isfromtemplateinstantiation.cpp:135:31:135:35 | Inner<long> |
|
||||
| isfromtemplateinstantiation.cpp:135:31:135:31 | declaration of operator= | isfromtemplateinstantiation.cpp:135:31:135:35 | Inner<long> |
|
||||
| isfromtemplateinstantiation.cpp:135:31:135:35 | Inner<U> | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<int> |
|
||||
| isfromtemplateinstantiation.cpp:135:31:135:35 | Inner<long> | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<int> |
|
||||
| isfromtemplateinstantiation.cpp:135:31:135:35 | definition of Inner<U> | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<int> |
|
||||
| isfromtemplateinstantiation.cpp:136:7:136:7 | definition of x | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<int> |
|
||||
| isfromtemplateinstantiation.cpp:136:7:136:7 | definition of x | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<int> |
|
||||
| isfromtemplateinstantiation.cpp:136:7:136:7 | definition of x | isfromtemplateinstantiation.cpp:135:31:135:35 | Inner<long> |
|
||||
| isfromtemplateinstantiation.cpp:136:7:136:7 | x | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<int> |
|
||||
| isfromtemplateinstantiation.cpp:136:7:136:7 | x | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<int> |
|
||||
| isfromtemplateinstantiation.cpp:136:7:136:7 | x | isfromtemplateinstantiation.cpp:135:31:135:35 | Inner<long> |
|
||||
| isfromtemplateinstantiation.cpp:137:7:137:7 | definition of y | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<int> |
|
||||
| isfromtemplateinstantiation.cpp:137:7:137:7 | definition of y | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<int> |
|
||||
| isfromtemplateinstantiation.cpp:137:7:137:7 | definition of y | isfromtemplateinstantiation.cpp:135:31:135:35 | Inner<long> |
|
||||
| isfromtemplateinstantiation.cpp:137:7:137:7 | y | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<int> |
|
||||
| isfromtemplateinstantiation.cpp:137:7:137:7 | y | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<int> |
|
||||
| isfromtemplateinstantiation.cpp:137:7:137:7 | y | isfromtemplateinstantiation.cpp:135:31:135:35 | Inner<long> |
|
||||
| load.cpp:13:7:13:7 | basic_text_iprimitive<std_istream_mockup>::basic_text_iprimitive(basic_text_iprimitive<std_istream_mockup> &&) | load.cpp:13:7:13:27 | basic_text_iprimitive<std_istream_mockup> |
|
||||
| load.cpp:13:7:13:7 | basic_text_iprimitive<std_istream_mockup>::basic_text_iprimitive(const basic_text_iprimitive<std_istream_mockup> &) | load.cpp:13:7:13:27 | basic_text_iprimitive<std_istream_mockup> |
|
||||
|
||||
@@ -3,6 +3,7 @@ isFromUninstantiatedTemplate
|
||||
| file://:0:0:0:0 | 0 | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass<T> |
|
||||
| file://:0:0:0:0 | (int)... | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass<T> |
|
||||
| file://:0:0:0:0 | (int)... | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass<T> |
|
||||
| file://:0:0:0:0 | Inner<U> | file://:0:0:0:0 | Inner<U> |
|
||||
| file://:0:0:0:0 | declaration of 1st parameter | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<T> |
|
||||
| file://:0:0:0:0 | declaration of 1st parameter | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<T> |
|
||||
| file://:0:0:0:0 | initializer for MyClassEnumConst | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass<T> |
|
||||
@@ -433,15 +434,15 @@ isFromUninstantiatedTemplate
|
||||
| isfromtemplateinstantiation.cpp:135:31:135:31 | declaration of operator= | I | T | DeclarationEntry | |
|
||||
| isfromtemplateinstantiation.cpp:135:31:135:31 | operator= | I | T | Declaration | |
|
||||
| isfromtemplateinstantiation.cpp:135:31:135:31 | operator= | I | T | Declaration | |
|
||||
| isfromtemplateinstantiation.cpp:135:31:135:35 | Inner<U> | I | T | Declaration | |
|
||||
| isfromtemplateinstantiation.cpp:135:31:135:35 | Inner<U> | | T | Declaration | |
|
||||
| isfromtemplateinstantiation.cpp:135:31:135:35 | Inner<long> | I | T | Declaration | |
|
||||
| isfromtemplateinstantiation.cpp:136:7:136:7 | definition of x | | T | Definition | |
|
||||
| isfromtemplateinstantiation.cpp:136:7:136:7 | definition of x | I | T | Definition | |
|
||||
| isfromtemplateinstantiation.cpp:136:7:136:7 | definition of x | I | T | Definition | |
|
||||
| isfromtemplateinstantiation.cpp:136:7:136:7 | x | I | T | Declaration | |
|
||||
| isfromtemplateinstantiation.cpp:136:7:136:7 | x | | T | Declaration | |
|
||||
| isfromtemplateinstantiation.cpp:136:7:136:7 | x | I | T | Declaration | |
|
||||
| isfromtemplateinstantiation.cpp:137:7:137:7 | definition of y | | T | Definition | |
|
||||
| isfromtemplateinstantiation.cpp:137:7:137:7 | definition of y | I | T | Definition | |
|
||||
| isfromtemplateinstantiation.cpp:137:7:137:7 | definition of y | I | T | Definition | |
|
||||
| isfromtemplateinstantiation.cpp:137:7:137:7 | y | I | T | Declaration | |
|
||||
| isfromtemplateinstantiation.cpp:137:7:137:7 | y | | T | Declaration | |
|
||||
| isfromtemplateinstantiation.cpp:137:7:137:7 | y | I | T | Declaration | |
|
||||
| isfromtemplateinstantiation.cpp:144:28:144:56 | incomplete_never_instantiated<T> | | T | Declaration | |
|
||||
| isfromtemplateinstantiation.cpp:146:28:146:45 | never_instantiated<T> | | T | Declaration | |
|
||||
|
||||
1
cpp/ql/test/query-tests/AlertSuppression/.gitattributes
vendored
Normal file
1
cpp/ql/test/query-tests/AlertSuppression/.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
tstWindows.c eol=crlf
|
||||
@@ -88,3 +88,7 @@ void use_printf(float f, double d)
|
||||
// ^ there's a float -> double varargs promotion here, but it's unlikely that the author anticipates requiring a double
|
||||
printf("%f", d * d); // safe
|
||||
}
|
||||
|
||||
size_t three_chars(unsigned char a, unsigned char b, unsigned char c) {
|
||||
return a * b * c; // at most 16581375
|
||||
}
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
// semmle-extractor-options: --microsoft
|
||||
// winnt.h
|
||||
typedef long HRESULT;
|
||||
#define SUCCEEDED(hr) (((HRESULT)(hr)) >= 0)
|
||||
#define FAILED(hr) (((HRESULT)(hr)) < 0)
|
||||
|
||||
typedef _Bool bool;
|
||||
#define FALSE 0
|
||||
|
||||
// minwindef.h
|
||||
typedef int BOOL;
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
// winerror.h
|
||||
#define S_OK ((HRESULT)0L)
|
||||
#define S_FALSE ((HRESULT)1L)
|
||||
#define _HRESULT_TYPEDEF_(_sc) ((HRESULT)_sc)
|
||||
#define E_UNEXPECTED _HRESULT_TYPEDEF_(0x8000FFFFL)
|
||||
|
||||
HRESULT HresultFunction()
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
BOOL BoolFunction()
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool BoolFunction2()
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
HRESULT IncorrectHresultFunction()
|
||||
{
|
||||
return BoolFunction(); // BUG
|
||||
}
|
||||
|
||||
HRESULT IncorrectHresultFunction2()
|
||||
{
|
||||
return BoolFunction2(); // BUG
|
||||
}
|
||||
|
||||
void IncorrectTypeConversionTest() {
|
||||
|
||||
HRESULT hr = HresultFunction();
|
||||
if ((BOOL)hr) // BUG
|
||||
{
|
||||
// ...
|
||||
}
|
||||
if ((bool)hr) // BUG
|
||||
{
|
||||
// ...
|
||||
}
|
||||
if (SUCCEEDED(hr)) // Correct Usage
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
if (SUCCEEDED(BoolFunction())) // BUG
|
||||
{
|
||||
// ...
|
||||
}
|
||||
if (SUCCEEDED(BoolFunction2())) // BUG
|
||||
{
|
||||
// ...
|
||||
}
|
||||
if (BoolFunction()) // Correct Usage
|
||||
{
|
||||
// ...
|
||||
}
|
||||
BOOL b = IncorrectHresultFunction(); // BUG
|
||||
bool b2 = IncorrectHresultFunction(); // BUG
|
||||
|
||||
hr = E_UNEXPECTED;
|
||||
if (!hr) // BUG
|
||||
{
|
||||
// ...
|
||||
}
|
||||
if (!FAILED(hr)) // Correct Usage
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
hr = S_FALSE;
|
||||
if (hr) // BUG
|
||||
{
|
||||
// ...
|
||||
}
|
||||
if (SUCCEEDED(hr)) // Correct Usage
|
||||
{
|
||||
// ...
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
// semmle-extractor-options: --microsoft
|
||||
// winnt.h
|
||||
typedef long HRESULT;
|
||||
#define SUCCEEDED(hr) (((HRESULT)(hr)) >= 0)
|
||||
#define FAILED(hr) (((HRESULT)(hr)) < 0)
|
||||
|
||||
// minwindef.h
|
||||
typedef int BOOL;
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
// winerror.h
|
||||
#define S_OK ((HRESULT)0L)
|
||||
#define S_FALSE ((HRESULT)1L)
|
||||
#define _HRESULT_TYPEDEF_(_sc) ((HRESULT)_sc)
|
||||
#define E_UNEXPECTED _HRESULT_TYPEDEF_(0x8000FFFFL)
|
||||
|
||||
HRESULT HresultFunction()
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
BOOL BoolFunction()
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool BoolFunction2()
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
HRESULT IncorrectHresultFunction()
|
||||
{
|
||||
return BoolFunction(); // BUG
|
||||
}
|
||||
|
||||
HRESULT IncorrectHresultFunction2()
|
||||
{
|
||||
return BoolFunction2(); // BUG
|
||||
}
|
||||
|
||||
void IncorrectTypeConversionTest() {
|
||||
|
||||
HRESULT hr = HresultFunction();
|
||||
if ((BOOL)hr) // BUG
|
||||
{
|
||||
// ...
|
||||
}
|
||||
if ((bool)hr) // BUG
|
||||
{
|
||||
// ...
|
||||
}
|
||||
if (SUCCEEDED(hr)) // Correct Usage
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
if (SUCCEEDED(BoolFunction())) // BUG
|
||||
{
|
||||
// ...
|
||||
}
|
||||
if (SUCCEEDED(BoolFunction2())) // BUG
|
||||
{
|
||||
// ...
|
||||
}
|
||||
if (BoolFunction()) // Correct Usage
|
||||
{
|
||||
// ...
|
||||
}
|
||||
BOOL b = IncorrectHresultFunction(); // BUG
|
||||
bool b2 = IncorrectHresultFunction(); // BUG
|
||||
|
||||
hr = E_UNEXPECTED;
|
||||
if (!hr) // BUG
|
||||
{
|
||||
// ...
|
||||
}
|
||||
if (!FAILED(hr)) // Correct Usage
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
hr = S_FALSE;
|
||||
if (hr) // BUG
|
||||
{
|
||||
// ...
|
||||
}
|
||||
if (SUCCEEDED(hr)) // Correct Usage
|
||||
{
|
||||
// ...
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
| HResultBooleanConversion.c:42:12:42:23 | call to BoolFunction | Implicit conversion from BOOL to HRESULT |
|
||||
| HResultBooleanConversion.c:47:12:47:24 | call to BoolFunction2 | Implicit conversion from bool to HRESULT |
|
||||
| HResultBooleanConversion.c:53:15:53:16 | hr | Explicit conversion from HRESULT to BOOL |
|
||||
| HResultBooleanConversion.c:57:15:57:16 | hr | Explicit conversion from HRESULT to bool |
|
||||
| HResultBooleanConversion.c:66:9:66:33 | (...) | Explicit conversion from BOOL to HRESULT |
|
||||
| HResultBooleanConversion.c:70:9:70:34 | (...) | Explicit conversion from bool to HRESULT |
|
||||
| HResultBooleanConversion.c:78:14:78:37 | call to IncorrectHresultFunction | Implicit conversion from HRESULT to BOOL |
|
||||
| HResultBooleanConversion.c:79:15:79:38 | call to IncorrectHresultFunction | Implicit conversion from HRESULT to bool |
|
||||
| HResultBooleanConversion.c:82:10:82:11 | hr | Usage of a type HRESULT as an argument of a unary logical operation |
|
||||
| HResultBooleanConversion.c:92:9:92:10 | hr | Direct usage of a type HRESULT as a conditional expression |
|
||||
| HResultBooleanConversion.cpp:39:12:39:23 | call to BoolFunction | Implicit conversion from BOOL to HRESULT |
|
||||
| HResultBooleanConversion.cpp:44:12:44:24 | call to BoolFunction2 | Implicit conversion from bool to HRESULT |
|
||||
| HResultBooleanConversion.cpp:50:15:50:16 | hr | Explicit conversion from HRESULT to BOOL |
|
||||
| HResultBooleanConversion.cpp:54:15:54:16 | hr | Explicit conversion from HRESULT to bool |
|
||||
| HResultBooleanConversion.cpp:63:9:63:33 | (...) | Explicit conversion from BOOL to HRESULT |
|
||||
| HResultBooleanConversion.cpp:67:9:67:34 | (...) | Explicit conversion from bool to HRESULT |
|
||||
| HResultBooleanConversion.cpp:75:14:75:37 | call to IncorrectHresultFunction | Implicit conversion from HRESULT to BOOL |
|
||||
| HResultBooleanConversion.cpp:76:15:76:38 | call to IncorrectHresultFunction | Implicit conversion from HRESULT to bool |
|
||||
| HResultBooleanConversion.cpp:79:10:79:11 | hr | Implicit conversion from HRESULT to bool |
|
||||
| HResultBooleanConversion.cpp:89:9:89:10 | hr | Implicit conversion from HRESULT to bool |
|
||||
@@ -0,0 +1 @@
|
||||
Security/CWE/CWE-253/HResultBooleanConversion.ql
|
||||
@@ -11,5 +11,9 @@
|
||||
| ExternalOwners.cpp:49:3:49:20 | ... = ... | Resource a is acquired by class MyScreen but not released anywhere in this class. |
|
||||
| ListDelete.cpp:21:3:21:21 | ... = ... | Resource first is acquired by class MyThingColection but not released anywhere in this class. |
|
||||
| NoDestructor.cpp:23:3:23:20 | ... = ... | Resource n is acquired by class MyClass5 but not released anywhere in this class. |
|
||||
| PlacementNew.cpp:36:3:36:36 | ... = ... | Resource p1 is acquired by class MyTestForPlacementNew but not released anywhere in this class. |
|
||||
| SelfRegistering.cpp:25:3:25:24 | ... = ... | Resource side is acquired by class MyOwner but not released anywhere in this class. |
|
||||
| Variants.cpp:23:3:23:13 | ... = ... | Resource f is acquired by class MyClass4 but not released anywhere in this class. |
|
||||
| Variants.cpp:25:3:25:13 | ... = ... | Resource f is acquired by class MyClass4 but not released anywhere in this class. |
|
||||
| Variants.cpp:65:3:65:17 | ... = ... | Resource a is acquired by class MyClass6 but not released anywhere in this class. |
|
||||
| Variants.cpp:66:3:66:36 | ... = ... | Resource b is acquired by class MyClass6 but not released anywhere in this class. |
|
||||
| Variants.cpp:67:3:67:41 | ... = ... | Resource c is acquired by class MyClass6 but not released anywhere in this class. |
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
|
||||
typedef unsigned long size_t;
|
||||
|
||||
namespace std
|
||||
{
|
||||
using ::size_t;
|
||||
struct nothrow_t {};
|
||||
extern const nothrow_t nothrow;
|
||||
}
|
||||
|
||||
// nothrow new
|
||||
void* operator new(std::size_t size, const std::nothrow_t&) throw();
|
||||
|
||||
// placement new
|
||||
void* operator new (std::size_t size, void* ptr) throw();
|
||||
|
||||
// ---
|
||||
|
||||
class MyClassForPlacementNew
|
||||
{
|
||||
public:
|
||||
MyClassForPlacementNew(int _v) : v(_v) {}
|
||||
~MyClassForPlacementNew() {}
|
||||
|
||||
private:
|
||||
int v;
|
||||
};
|
||||
|
||||
class MyTestForPlacementNew
|
||||
{
|
||||
public:
|
||||
MyTestForPlacementNew()
|
||||
{
|
||||
void *buffer_ptr = buffer;
|
||||
|
||||
p1 = new MyClassForPlacementNew(1); // BAD: not released
|
||||
p2 = new (std::nothrow) MyClassForPlacementNew(2); // BAD: not released [NOT DETECTED]
|
||||
p3 = new (buffer_ptr) MyClassForPlacementNew(3); // GOOD: placement new, not an allocation
|
||||
}
|
||||
|
||||
~MyTestForPlacementNew()
|
||||
{
|
||||
}
|
||||
|
||||
MyClassForPlacementNew *p1, *p2, *p3;
|
||||
char buffer[sizeof(MyClassForPlacementNew)];
|
||||
};
|
||||
@@ -2,6 +2,8 @@
|
||||
// library
|
||||
typedef unsigned int size_t;
|
||||
void *malloc(size_t size);
|
||||
void *calloc(size_t nmemb, size_t size);
|
||||
void *realloc(void *ptr, size_t size);
|
||||
void free(void* ptr);
|
||||
|
||||
int *ID(int *x)
|
||||
@@ -34,3 +36,40 @@ public:
|
||||
|
||||
int *a, *b, *c, *d, *e, *f, *g;
|
||||
};
|
||||
|
||||
class MyClass5
|
||||
{
|
||||
public:
|
||||
MyClass5()
|
||||
{
|
||||
a = new int[10]; // GOOD
|
||||
b = (int *)calloc(10, sizeof(int)); // GOOD
|
||||
c = (int *)realloc(0, 10 * sizeof(int)); // GOOD
|
||||
}
|
||||
|
||||
~MyClass5()
|
||||
{
|
||||
delete [] a;
|
||||
free(b);
|
||||
free(c);
|
||||
}
|
||||
|
||||
int *a, *b, *c;
|
||||
};
|
||||
|
||||
class MyClass6
|
||||
{
|
||||
public:
|
||||
MyClass6()
|
||||
{
|
||||
a = new int[10]; // BAD
|
||||
b = (int *)calloc(10, sizeof(int)); // BAD
|
||||
c = (int *)realloc(0, 10 * sizeof(int)); // BAD
|
||||
}
|
||||
|
||||
~MyClass6()
|
||||
{
|
||||
}
|
||||
|
||||
int *a, *b, *c;
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @description If a synchronized method is overridden in a subclass, and the overriding method is
|
||||
* not synchronized, the thread-safety of the subclass may be broken.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @problem.severity warning
|
||||
* @precision very-high
|
||||
* @id java/non-sync-override
|
||||
* @tags reliability
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @description A resource that is opened for reading but not closed may cause a resource
|
||||
* leak.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @problem.severity warning
|
||||
* @precision high
|
||||
* @id java/input-resource-leak
|
||||
* @tags efficiency
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @name Potential database resource leak
|
||||
* @description A database resource that is opened but not closed may cause a resource leak.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @problem.severity warning
|
||||
* @precision high
|
||||
* @id java/database-resource-leak
|
||||
* @tags correctness
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @description A resource that is opened for writing but not closed may cause a resource
|
||||
* leak.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @problem.severity warning
|
||||
* @precision high
|
||||
* @id java/output-resource-leak
|
||||
* @tags efficiency
|
||||
|
||||
1
java/ql/test/library-tests/comments/.gitattributes
vendored
Normal file
1
java/ql/test/library-tests/comments/.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
TestWindows.java eol=crlf
|
||||
1
java/ql/test/query-tests/AlertSuppression/.gitattributes
vendored
Normal file
1
java/ql/test/query-tests/AlertSuppression/.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
TestWindows.java eol=crlf
|
||||
@@ -38,12 +38,15 @@ predicate hasCookieMiddleware(Express::RouteHandlerExpr expr, Express::RouteHand
|
||||
* // protected from CSRF
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* Currently the predicate only detects `csurf`-based protectors.
|
||||
*/
|
||||
DataFlow::CallNode csrfMiddlewareCreation() {
|
||||
exists (DataFlow::ModuleImportNode mod | result = mod.getACall() |
|
||||
mod.getPath() = "csurf"
|
||||
exists (DataFlow::SourceNode callee | result = callee.getACall() |
|
||||
callee = DataFlow::moduleImport("csurf")
|
||||
or
|
||||
callee = DataFlow::moduleImport("lusca") and
|
||||
exists(result.getOptionArgument(0, "csrf"))
|
||||
or
|
||||
callee = DataFlow::moduleMember("lusca", "csrf")
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -785,7 +785,8 @@ module Express {
|
||||
override MethodCallExpr astNode;
|
||||
|
||||
ResponseSendFileAsFileSystemAccess() {
|
||||
asExpr().(MethodCallExpr).calls(any(ResponseExpr res), "sendFile")
|
||||
exists (string name | name = "sendFile" or name = "sendfile" |
|
||||
asExpr().(MethodCallExpr).calls(any(ResponseExpr res), name))
|
||||
}
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
|
||||
@@ -25,4 +25,5 @@
|
||||
| tainted-array-steps.js:15:29:15:43 | parts.join('/') | This path depends on $@. | tainted-array-steps.js:9:24:9:30 | req.url | a user-provided value |
|
||||
| tainted-require.js:7:19:7:37 | req.param("module") | This path depends on $@. | tainted-require.js:7:19:7:37 | req.param("module") | a user-provided value |
|
||||
| tainted-sendFile.js:7:16:7:33 | req.param("gimme") | This path depends on $@. | tainted-sendFile.js:7:16:7:33 | req.param("gimme") | a user-provided value |
|
||||
| tainted-sendFile.js:9:16:9:33 | req.param("gimme") | This path depends on $@. | tainted-sendFile.js:9:16:9:33 | req.param("gimme") | a user-provided value |
|
||||
| views.js:1:43:1:55 | req.params[0] | This path depends on $@. | views.js:1:43:1:55 | req.params[0] | a user-provided value |
|
||||
|
||||
@@ -5,4 +5,6 @@ var app = express();
|
||||
app.get('/some/path', function(req, res) {
|
||||
// BAD: sending a file based on un-sanitized query parameters
|
||||
res.sendFile(req.param("gimme"));
|
||||
// BAD: same as above
|
||||
res.sendfile(req.param("gimme"));
|
||||
});
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
| MissingCsrfMiddlewareBad.js:7:9:7:22 | cookieParser() | This cookie middleware is serving a request handler $@ without CSRF protection. | MissingCsrfMiddlewareBad.js:10:26:11:1 | functio ... es) {\\n} | here |
|
||||
| csurf_api_example.js:39:37:39:50 | cookieParser() | This cookie middleware is serving a request handler $@ without CSRF protection. | csurf_api_example.js:39:53:41:3 | functio ... e')\\n } | here |
|
||||
| csurf_example.js:18:9:18:22 | cookieParser() | This cookie middleware is serving a request handler $@ without CSRF protection. | csurf_example.js:29:40:31:1 | functio ... sed')\\n} | here |
|
||||
| lusca_example.js:9:9:9:22 | cookieParser() | This cookie middleware is serving a request handler $@ without CSRF protection. | lusca_example.js:23:42:25:1 | functio ... sed')\\n} | here |
|
||||
| lusca_example.js:9:9:9:22 | cookieParser() | This cookie middleware is serving a request handler $@ without CSRF protection. | lusca_example.js:27:40:29:1 | functio ... sed')\\n} | here |
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
var express = require('express')
|
||||
var cookieParser = require('cookie-parser')
|
||||
var bodyParser = require('body-parser')
|
||||
|
||||
var parseForm = bodyParser.urlencoded({ extended: false })
|
||||
var lusca = require('lusca');
|
||||
|
||||
var app = express()
|
||||
app.use(cookieParser())
|
||||
|
||||
app.post('/process', parseForm, lusca.csrf(), function (req, res) { // OK
|
||||
res.send('data is being processed')
|
||||
})
|
||||
|
||||
app.post('/process', parseForm, lusca({csrf:true}), function (req, res) { // OK
|
||||
res.send('data is being processed')
|
||||
})
|
||||
|
||||
app.post('/process', parseForm, lusca({csrf:{}}), function (req, res) { // OK
|
||||
res.send('data is being processed')
|
||||
})
|
||||
|
||||
app.post('/process', parseForm, lusca(), function (req, res) { // NOT OK - missing csrf option
|
||||
res.send('data is being processed')
|
||||
})
|
||||
|
||||
app.post('/process_unsafe', parseForm, function (req, res) { // NOT OK
|
||||
res.send('data is being processed')
|
||||
})
|
||||
Reference in New Issue
Block a user