Merge branch 'master' into rdmarsh/cpp/ir-constructor-side-effects

This commit is contained in:
Robert Marsh
2019-11-12 10:31:04 -08:00
127 changed files with 1910 additions and 1002 deletions

View File

@@ -9,6 +9,7 @@ The following changes in version 1.23 affect C/C++ analysis in all applications.
| **Query** | **Tags** | **Purpose** |
|-----------------------------|-----------|--------------------------------------------------------------------|
| Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`) | reliability, japanese-era | This query is a combination of two old queries that were identical in purpose but separate as an implementation detail. This new query replaces Hard-coded Japanese era start date in call (`cpp/japanese-era/constructor-or-method-with-exact-era-date`) and Hard-coded Japanese era start date in struct (`cpp/japanese-era/struct-with-exact-era-date`). |
| Signed overflow check (`cpp/signed-overflow-check`) | correctness, reliability | Finds overflow checks that rely on signed integer addition to overflow, which has undefined behavior. Example: `a + b < a`. |
## Changes to existing queries
@@ -23,6 +24,8 @@ The following changes in version 1.23 affect C/C++ analysis in all applications.
| Too many arguments to formatting function (`cpp/too-many-format-arguments`) | Fewer false positive results | Fixed false positives resulting from mistmatching declarations of a formatting function. |
| Unclear comparison precedence (`cpp/comparison-precedence`) | Fewer false positive results | False positives involving template classes and functions have been fixed. |
| Comparison of narrow type with wide type in loop condition (`cpp/comparison-with-wider-type`) | Higher precision | The precision of this query has been increased to "high" as the alerts from this query have proved to be valuable on real-world projects. With this precision, results are now displayed by default in LGTM. |
| Non-constant format string (`cpp/non-constant-format`) | Fewer false positive results | Fixed false positives resulting from mistmatching declarations of a formatting function. |
| Wrong type of arguments to formatting function (`cpp/wrong-type-format-argument`) | More correct results and fewer false positive results | This query now understands explicitly specified argument numbers in format strings, such as the `1$` in `%1$s`. |
## Changes to libraries

View File

@@ -19,6 +19,7 @@ where
pointlessSelfComparison(cmp) and
not nanTest(cmp) and
not overflowTest(cmp) and
not cmp.isFromTemplateInstantiation(_) and
not exists(MacroInvocation mi |
// cmp is in mi
mi.getAnExpandedElement() = cmp and

View File

@@ -0,0 +1,3 @@
bool foo(int n1, unsigned short delta) {
return n1 + delta < n1; // BAD
}

View File

@@ -0,0 +1,4 @@
bool bar(unsigned short n1, unsigned short delta) {
// NB: Comparison is always false
return n1 + delta < n1; // GOOD (but misleading)
}

View File

@@ -0,0 +1,4 @@
#include <limits.h>
bool foo(int n1, unsigned short delta) {
return n1 > INT_MAX - delta; // GOOD
}

View File

@@ -0,0 +1,3 @@
bool bar(unsigned short n1, unsigned short delta) {
return (unsigned short)(n1 + delta) < n1; // GOOD
}

View File

@@ -0,0 +1,115 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
When checking for integer overflow, you may often write tests like
<code>a + b &lt; a</code>. This works fine if <code>a</code> or
<code>b</code> are unsigned integers, since any overflow in the addition
will cause the value to simply "wrap around." However, using
<i>signed</i> integers is problematic because signed overflow has undefined
behavior according to the C and C++ standards. If the addition overflows
and has an undefined result, the comparison will likewise be undefined;
it may produce an unintended result, or may be deleted entirely by an
optimizing compiler.
</p>
</overview>
<recommendation>
<p>
Solutions to this problem can be thought of as falling into one of two
categories: (1) rewrite the signed expression so that overflow cannot occur
but the signedness remains, or (2) rewrite (or cast) the signed expression
into unsigned form.
</p>
<p>
Below we list examples of expressions where signed overflow may
occur, along with proposed solutions. The list should not be
considered exhaustive.
</p>
<p>
Given <code>unsigned short i, delta</code> and <code>i + delta &lt; i</code>,
it is possible to rewrite it as <code>(unsigned short)(i + delta)&nbsp;&lt;&nbsp;i</code>.
Note that <code>i + delta</code>does not actually overflow, due to <code>int</code> promotion
</p>
<p>
Given <code>unsigned short i, delta</code> and <code>i + delta &lt; i</code>,
it is also possible to rewrite it as <code>USHORT_MAX - delta</code>. It must be true
that <code>delta &gt; 0</code> and the <code>limits.h</code> or <code>climits</code>
header has been included.
</p>
<p>
Given <code>int i, delta</code> and <code>i + delta &lt; i</code>,
it is possible to rewrite it as <code>INT_MAX - delta</code>. It must be true
that <code>delta &gt; 0</code> and the <code>limits.h</code> or <code>climits</code>
header has been included.
</p>
<p>
Given <code>int i, delta</code> and <code>i + delta &lt; i</code>,
it is also possible to rewrite it as <code>(unsigned)i + delta &lt; i</code>.
Note that program semantics are affected by this change.
</p>
<p>
Given <code>int i, delta</code> and <code>i + delta &lt; i</code>,
it is also possible to rewrite it as <code>unsigned int i, delta</code> and
<code>i + delta &lt; i</code>. Note that program semantics are
affected by this change.
</p>
</recommendation>
<example>
<p>
In the following example, even though <code>delta</code> has been declared
<code>unsigned short</code>, C/C++ type promotion rules require that its
type is promoted to the larger type used in the addition and comparison,
namely a <code>signed int</code>. Addition is performed on
signed integers, and may have undefined behavior if an overflow occurs.
As a result, the entire (comparison) expression may also have an undefined
result.
</p>
<sample src="SignedOverflowCheck-bad1.cpp" />
<p>
The following example builds upon the previous one. Instead of
performing an addition (which could overflow), we have re-framed the
solution so that a subtraction is used instead. Since <code>delta</code>
is promoted to a <code>signed int</code> and <code>INT_MAX</code> denotes
the largest possible positive value for an <code>signed int</code>,
the expression <code>INT_MAX - delta</code> can never be less than zero
or more than <code>INT_MAX</code>. Hence, any overflow and underflow
are avoided.
</p>
<sample src="SignedOverflowCheck-good1.cpp" />
<p>
In the following example, even though both <code>n</code> and <code>delta</code>
have been declared <code>unsigned short</code>, both are promoted to
<code>signed int</code> prior to addition. Because we started out with the
narrower <code>short</code> type, the addition is guaranteed not to overflow
and is therefore defined. But the fact that <code>n1 + delta</code> never
overflows means that the condition <code>n1 + delta &lt; n1</code> will never
hold true, which likely is not what the programmer intended. (see also the
<code>cpp/bad-addition-overflow-check</code> query).
</p>
<sample src="SignedOverflowCheck-bad2.cpp" />
<p>
The next example provides a solution to the previous one. Even though
<code>i + delta</code> does not overflow, casting it to an
<code>unsigned short</code> truncates the addition modulo 2^16,
so that <code>unsigned short</code> "wrap around" may now be observed.
Furthermore, since the left-hand side is now of type <code>unsigned short</code>,
the right-hand side does not need to be promoted to a <code>signed int</code>.
</p>
<sample src="SignedOverflowCheck-good2.cpp" />
</example>
<references>
<li><a href="http://c-faq.com/expr/preservingrules.html">comp.lang.c FAQ list · Question 3.19 (Preserving rules)</a></li>
<li><a href="https://wiki.sei.cmu.edu/confluence/display/c/INT31-C.+Ensure+that+integer+conversions+do+not+result+in+lost+or+misinterpreted+data">INT31-C. Ensure that integer conversions do not result in lost or misinterpreted data</a></li>
<li>W. Dietz, P. Li, J. Regehr, V. Adve. <a href="https://www.cs.utah.edu/~regehr/papers/overflow12.pdf">Understanding Integer Overflow in C/C++</a></li>
</references>
</qhelp>

View File

@@ -0,0 +1,31 @@
/**
* @name Undefined result of signed test for overflow
* @description Testing for overflow by adding a value to a variable
* to see if it "wraps around" works only for
* unsigned integer values.
* @kind problem
* @problem.severity warning
* @precision high
* @id cpp/signed-overflow-check
* @tags reliability
* security
*/
import cpp
private import semmle.code.cpp.valuenumbering.GlobalValueNumbering
private import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
from RelationalOperation ro, AddExpr add, Expr expr1, Expr expr2
where
ro.getAnOperand() = add and
add.getAnOperand() = expr1 and
ro.getAnOperand() = expr2 and
globalValueNumber(expr1) = globalValueNumber(expr2) and
add.getUnspecifiedType().(IntegralType).isSigned() and
not exists(MacroInvocation mi | mi.getAnAffectedElement() = add) and
exprMightOverflowPositively(add) and
exists(Compilation c | c.getAFileCompiled() = ro.getFile() |
not c.getAnArgument() = "-fwrapv" and
not c.getAnArgument() = "-fno-strict-overflow"
)
select ro, "Testing for signed overflow may produce undefined results."

View File

@@ -13,32 +13,33 @@ import semmle.code.cpp.security.boostorg.asio.protocols
class ExistsAnyFlowConfig extends DataFlow::Configuration {
ExistsAnyFlowConfig() { this = "ExistsAnyFlowConfig" }
override predicate isSource(DataFlow::Node source) { any() }
override predicate isSource(DataFlow::Node source) {
exists(BoostorgAsio::SslContextClass c | c.getAContructorCall() = source.asExpr())
}
override predicate isSink(DataFlow::Node sink) { any() }
override predicate isSink(DataFlow::Node sink) {
exists(BoostorgAsio::SslSetOptionsFunction f, FunctionCall fcSetOptions |
f.getACallToThisFunction() = fcSetOptions and
fcSetOptions.getQualifier() = sink.asExpr()
)
}
}
bindingset[flag]
predicate isOptionSet(ConstructorCall cc, int flag, FunctionCall fcSetOptions) {
exists(
BoostorgAsio::SslContextFlowsToSetOptionConfig config, ExistsAnyFlowConfig testConfig,
Expr optionsSink
|
config.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(optionsSink)) and
exists(VariableAccess contextSetOptions |
testConfig.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and
exists(BoostorgAsio::SslSetOptionsFunction f | f.getACallToThisFunction() = fcSetOptions |
contextSetOptions = fcSetOptions.getQualifier() and
forall(
Expr optionArgument, BoostorgAsio::SslOptionConfig optionArgConfig,
Expr optionArgumentSource
|
optionArgument = fcSetOptions.getArgument(0) and
optionArgConfig
.hasFlow(DataFlow::exprNode(optionArgumentSource), DataFlow::exprNode(optionArgument))
|
optionArgument.getValue().toInt().bitShiftRight(16).bitAnd(flag) = flag
)
exists(ExistsAnyFlowConfig anyFlowConfig, VariableAccess contextSetOptions |
anyFlowConfig.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and
exists(BoostorgAsio::SslSetOptionsFunction f | f.getACallToThisFunction() = fcSetOptions |
contextSetOptions = fcSetOptions.getQualifier() and
forall(
Expr optionArgument, BoostorgAsio::SslOptionConfig optionArgConfig,
Expr optionArgumentSource
|
optionArgument = fcSetOptions.getArgument(0) and
optionArgConfig
.hasFlow(DataFlow::exprNode(optionArgumentSource), DataFlow::exprNode(optionArgument))
|
optionArgument.getValue().toInt().bitShiftRight(16).bitAnd(flag) = flag
)
)
)
@@ -46,43 +47,18 @@ predicate isOptionSet(ConstructorCall cc, int flag, FunctionCall fcSetOptions) {
bindingset[flag]
predicate isOptionNotSet(ConstructorCall cc, int flag) {
not exists(
BoostorgAsio::SslContextFlowsToSetOptionConfig config, ExistsAnyFlowConfig testConfig,
Expr optionsSink
|
config.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(optionsSink)) and
exists(VariableAccess contextSetOptions |
testConfig.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and
exists(FunctionCall fcSetOptions, BoostorgAsio::SslSetOptionsFunction f |
f.getACallToThisFunction() = fcSetOptions
|
contextSetOptions = fcSetOptions.getQualifier() and
forall(
Expr optionArgument, BoostorgAsio::SslOptionConfig optionArgConfig,
Expr optionArgumentSource
|
optionArgument = fcSetOptions.getArgument(0) and
optionArgConfig
.hasFlow(DataFlow::exprNode(optionArgumentSource), DataFlow::exprNode(optionArgument))
|
optionArgument.getValue().toInt().bitShiftRight(16).bitAnd(flag) = flag
)
)
)
)
not exists(FunctionCall fcSetOptions | isOptionSet(cc, flag, fcSetOptions))
}
from
BoostorgAsio::SslContextCallTlsProtocolConfig configConstructor,
BoostorgAsio::SslContextFlowsToSetOptionConfig config, Expr protocolSource, Expr protocolSink,
ConstructorCall cc, Expr e, string msg
BoostorgAsio::SslContextCallTlsProtocolConfig configConstructor, Expr protocolSource,
Expr protocolSink, ConstructorCall cc, Expr e, string msg
where
configConstructor.hasFlow(DataFlow::exprNode(protocolSource), DataFlow::exprNode(protocolSink)) and
cc.getArgument(0) = protocolSink and
(
BoostorgAsio::isExprSslV23BoostProtocol(protocolSource) and
not exists(Expr optionsSink |
config.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(optionsSink)) and
not (
isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoSsl3(), _) and
isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1(), _) and
isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1_1(), _) and
@@ -91,8 +67,7 @@ where
or
BoostorgAsio::isExprTlsBoostProtocol(protocolSource) and
not BoostorgAsio::isExprSslV23BoostProtocol(protocolSource) and
not exists(Expr optionsSink |
config.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(optionsSink)) and
not (
isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1(), _) and
isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1_1(), _) and
isOptionNotSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1_2())

View File

@@ -126,7 +126,7 @@ class SALParameter extends Parameter {
}
/**
* A SAL element, i.e. a SAL annotation or a declaration entry
* A SAL element, that is, a SAL annotation or a declaration entry
* that may have SAL annotations.
*/
library class SALElement extends Element {

View File

@@ -34,7 +34,7 @@ characters before writing to the HTML page.</p>
<li>
OWASP:
<a href="https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet">XSS
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html">XSS
(Cross Site Scripting) Prevention Cheat Sheet</a>.
</li>
<li>

View File

@@ -89,9 +89,9 @@ class ParameterNullCheck extends ParameterCheck {
(
va = this.(NotExpr).getOperand() or
va = any(EQExpr eq | eq = this and eq.getAnOperand().getValue() = "0").getAnOperand() or
va = getAssertedFalseCondition(this) or
va = getCheckedFalseCondition(this) or
va = any(NEExpr eq |
eq = getAssertedFalseCondition(this) and eq.getAnOperand().getValue() = "0"
eq = getCheckedFalseCondition(this) and eq.getAnOperand().getValue() = "0"
).getAnOperand()
)
or
@@ -101,7 +101,7 @@ class ParameterNullCheck extends ParameterCheck {
va = this or
va = any(NEExpr eq | eq = this and eq.getAnOperand().getValue() = "0").getAnOperand() or
va = any(EQExpr eq |
eq = getAssertedFalseCondition(this) and eq.getAnOperand().getValue() = "0"
eq = getCheckedFalseCondition(this) and eq.getAnOperand().getValue() = "0"
).getAnOperand()
)
)
@@ -567,7 +567,7 @@ Expr getAnInitializedArgument(Call call) { result = call.getArgument(initialized
* the call, under the given context and evidence.
*/
pragma[nomagic]
int conditionallyInitializedArgument(
private int conditionallyInitializedArgument(
Call call, ConditionalInitializationFunction target, Context c, Evidence e
) {
target = getTarget(call) and
@@ -588,7 +588,7 @@ Expr getAConditionallyInitializedArgument(
/**
* Gets the type signature for the functions parameters.
*/
string typeSig(Function f) {
private string typeSig(Function f) {
result = concat(int i, Type pt |
pt = f.getParameter(i).getType()
|
@@ -599,7 +599,7 @@ string typeSig(Function f) {
/**
* Holds where qualifiedName and typeSig make up the signature for the function.
*/
predicate functionSignature(Function f, string qualifiedName, string typeSig) {
private predicate functionSignature(Function f, string qualifiedName, string typeSig) {
qualifiedName = f.getQualifiedName() and
typeSig = typeSig(f)
}
@@ -611,7 +611,7 @@ predicate functionSignature(Function f, string qualifiedName, string typeSig) {
* This is useful for identifying call to target dependencies across libraries, where the libraries
* are never statically linked together.
*/
Function getAPossibleDefinition(Function undefinedFunction) {
private Function getAPossibleDefinition(Function undefinedFunction) {
not undefinedFunction.isDefined() and
exists(string qn, string typeSig |
functionSignature(undefinedFunction, qn, typeSig) and functionSignature(result, qn, typeSig)
@@ -684,7 +684,7 @@ FieldAccess getAFieldAccess(Variable v) {
}
/**
* Gets a condition which is asserted to be false by the given `ne` expression, according to this pattern:
* Gets a condition which is checked to be false by the given `ne` expression, according to this pattern:
* ```
* int a = !!result;
* if (!a) { // <- ne
@@ -692,7 +692,7 @@ FieldAccess getAFieldAccess(Variable v) {
* }
* ```
*/
Expr getAssertedFalseCondition(NotExpr ne) {
private Expr getCheckedFalseCondition(NotExpr ne) {
exists(LocalVariable v |
result = v.getInitializer().getExpr().(NotExpr).getOperand().(NotExpr).getOperand() and
ne.getOperand() = v.getAnAccess() and

View File

@@ -1,9 +1,8 @@
import cpp
/**
* Gets a `Field` that is nested within the given `Struct`.
*
* This identifies `Field`s which are located in the same memory
* Gets a `Field` that is within the given `Struct`, either directly or nested
* inside one or more levels of member structs.
*/
private Field getANestedField(Struct s) {
result = s.getAField()
@@ -15,7 +14,7 @@ private Field getANestedField(Struct s) {
}
/**
* Unwraps a series of field accesses to determine the inner-most qualifier.
* Unwraps a series of field accesses to determine the outer-most qualifier.
*/
private Expr getUltimateQualifier(FieldAccess fa) {
exists(Expr qualifier | qualifier = fa.getQualifier() |

View File

@@ -8,25 +8,32 @@ import semmle.code.cpp.commons.StringAnalysis
import semmle.code.cpp.models.interfaces.FormattingFunction
import semmle.code.cpp.models.implementations.Printf
class PrintfFormatAttribute extends FormatAttribute {
PrintfFormatAttribute() {
getArchetype() = "printf" or
getArchetype() = "__printf__"
}
}
/**
* A function that can be identified as a `printf` style formatting
* function by its use of the GNU `format` attribute.
*/
class AttributeFormattingFunction extends FormattingFunction {
FormatAttribute printf_attrib;
override string getCanonicalQLClass() { result = "AttributeFormattingFunction" }
AttributeFormattingFunction() {
printf_attrib = getAnAttribute() and
(
printf_attrib.getArchetype() = "printf" or
printf_attrib.getArchetype() = "__printf__"
) and
exists(printf_attrib.getFirstFormatArgIndex()) // exclude `vprintf` style format functions
exists(PrintfFormatAttribute printf_attrib |
printf_attrib = getAnAttribute() and
exists(printf_attrib.getFirstFormatArgIndex()) // exclude `vprintf` style format functions
)
}
override int getFormatParameterIndex() { result = printf_attrib.getFormatIndex() }
override int getFormatParameterIndex() {
forex(PrintfFormatAttribute printf_attrib | printf_attrib = getAnAttribute() |
result = printf_attrib.getFormatIndex()
)
}
}
/**
@@ -124,15 +131,17 @@ class FormattingFunctionCall extends Expr {
}
/**
* Gets the argument corresponding to the nth conversion specifier
* Gets the argument corresponding to the nth conversion specifier.
*/
Expr getConversionArgument(int n) {
exists(FormatLiteral fl, int b, int o |
exists(FormatLiteral fl |
fl = this.getFormat() and
b = sum(int i, int toSum | i < n and toSum = fl.getNumArgNeeded(i) | toSum) and
o = fl.getNumArgNeeded(n) and
o > 0 and
result = this.getFormatArgument(b + o - 1)
(
result = this.getFormatArgument(fl.getParameterFieldValue(n))
or
result = this.getFormatArgument(fl.getFormatArgumentIndexFor(n, 2)) and
not exists(fl.getParameterFieldValue(n))
)
)
}
@@ -142,11 +151,14 @@ class FormattingFunctionCall extends Expr {
* an explicit minimum field width).
*/
Expr getMinFieldWidthArgument(int n) {
exists(FormatLiteral fl, int b |
exists(FormatLiteral fl |
fl = this.getFormat() and
b = sum(int i, int toSum | i < n and toSum = fl.getNumArgNeeded(i) | toSum) and
fl.hasImplicitMinFieldWidth(n) and
result = this.getFormatArgument(b)
(
result = this.getFormatArgument(fl.getMinFieldWidthParameterFieldValue(n))
or
result = this.getFormatArgument(fl.getFormatArgumentIndexFor(n, 0)) and
not exists(fl.getMinFieldWidthParameterFieldValue(n))
)
)
}
@@ -156,12 +168,14 @@ class FormattingFunctionCall extends Expr {
* precision).
*/
Expr getPrecisionArgument(int n) {
exists(FormatLiteral fl, int b, int o |
exists(FormatLiteral fl |
fl = this.getFormat() and
b = sum(int i, int toSum | i < n and toSum = fl.getNumArgNeeded(i) | toSum) and
(if fl.hasImplicitMinFieldWidth(n) then o = 1 else o = 0) and
fl.hasImplicitPrecision(n) and
result = this.getFormatArgument(b + o)
(
result = this.getFormatArgument(fl.getPrecisionParameterFieldValue(n))
or
result = this.getFormatArgument(fl.getFormatArgumentIndexFor(n, 1)) and
not exists(fl.getPrecisionParameterFieldValue(n))
)
)
}
@@ -361,6 +375,14 @@ class FormatLiteral extends Literal {
*/
string getParameterField(int n) { this.parseConvSpec(n, _, result, _, _, _, _, _) }
/**
* Gets the parameter field of the nth conversion specifier (if it has one) as a
* zero-based number.
*/
int getParameterFieldValue(int n) {
result = this.getParameterField(n).regexpCapture("([0-9]*)\\$", 1).toInt() - 1
}
/**
* Gets the flags of the nth conversion specifier.
*/
@@ -430,6 +452,14 @@ class FormatLiteral extends Literal {
*/
int getMinFieldWidth(int n) { result = this.getMinFieldWidthOpt(n).toInt() }
/**
* Gets the zero-based parameter number of the minimum field width of the nth
* conversion specifier, if it is implicit and uses a parameter field (such as `*1$`).
*/
int getMinFieldWidthParameterFieldValue(int n) {
result = this.getMinFieldWidthOpt(n).regexpCapture("\\*([0-9]*)\\$", 1).toInt() - 1
}
/**
* Gets the precision of the nth conversion specifier (empty string if none is given).
*/
@@ -460,6 +490,14 @@ class FormatLiteral extends Literal {
else result = this.getPrecisionOpt(n).regexpCapture("\\.([0-9]*)", 1).toInt()
}
/**
* Gets the zero-based parameter number of the precision of the nth conversion
* specifier, if it is implicit and uses a parameter field (such as `*1$`).
*/
int getPrecisionParameterFieldValue(int n) {
result = this.getPrecisionOpt(n).regexpCapture("\\.\\*([0-9]*)\\$", 1).toInt() - 1
}
/**
* Gets the length flag of the nth conversion specifier.
*/
@@ -777,19 +815,49 @@ class FormatLiteral extends Literal {
)
}
/**
* Holds if the nth conversion specifier of this format string (if `mode = 2`), it's
* minimum field width (if `mode = 0`) or it's precision (if `mode = 1`) requires a
* format argument.
*
* Most conversion specifiers require a format argument, whereas minimum field width
* and precision only require a format argument if they are present and a `*` was
* used for it's value in the format string.
*/
private predicate hasFormatArgumentIndexFor(int n, int mode) {
mode = 0 and
this.hasImplicitMinFieldWidth(n)
or
mode = 1 and
this.hasImplicitPrecision(n)
or
mode = 2 and
exists(this.getConvSpecOffset(n)) and
not this.getConversionChar(n) = "m"
}
/**
* Gets the computed format argument index for the nth conversion specifier of this
* format string (if `mode = 2`), it's minimum field width (if `mode = 0`) or it's
* precision (if `mode = 1`). Has no result if that element is not present. Does
* not account for positional arguments (`$`).
*/
int getFormatArgumentIndexFor(int n, int mode) {
hasFormatArgumentIndexFor(n, mode) and
(3 * n) + mode = rank[result + 1](int n2, int mode2 |
hasFormatArgumentIndexFor(n2, mode2)
|
(3 * n2) + mode2
)
}
/**
* Gets the number of arguments required by the nth conversion specifier
* of this format string.
*/
int getNumArgNeeded(int n) {
exists(this.getConvSpecOffset(n)) and
not this.getConversionChar(n) = "%" and
exists(int n1, int n2, int n3 |
(if this.hasImplicitMinFieldWidth(n) then n1 = 1 else n1 = 0) and
(if this.hasImplicitPrecision(n) then n2 = 1 else n2 = 0) and
(if this.getConversionChar(n) = "m" then n3 = 0 else n3 = 1) and
result = n1 + n2 + n3
)
result = count(int mode | hasFormatArgumentIndexFor(n, mode))
}
/**
@@ -801,7 +869,7 @@ class FormatLiteral extends Literal {
// At least one conversion specifier has a parameter field, in which case,
// they all should have.
result = max(string s | this.getParameterField(_) = s + "$" | s.toInt())
else result = sum(int n, int toSum | toSum = this.getNumArgNeeded(n) | toSum)
else result = count(int n, int mode | hasFormatArgumentIndexFor(n, mode))
}
/**

View File

@@ -67,7 +67,7 @@ module VirtualDispatch {
/**
* Holds if `c` cannot inherit the member function `f`,
* i.e. `c` or one of its supertypes overrides `f`.
* that is, `c` or one of its supertypes overrides `f`.
*/
private predicate cannotInherit(Class c, MemberFunction f) {
exists(Class overridingType, MemberFunction override |

View File

@@ -34,7 +34,7 @@ private newtype TOpcode =
TPointerSub() or
TPointerDiff() or
TConvert() or
TConvertToBase() or
TConvertToNonVirtualBase() or
TConvertToVirtualBase() or
TConvertToDerived() or
TCheckedConvertOrNull() or
@@ -110,6 +110,8 @@ abstract class RelationalOpcode extends CompareOpcode { }
abstract class CopyOpcode extends Opcode { }
abstract class ConvertToBaseOpcode extends UnaryOpcode { }
abstract class MemoryAccessOpcode extends Opcode { }
abstract class ReturnOpcode extends Opcode { }
@@ -302,11 +304,11 @@ module Opcode {
final override string toString() { result = "Convert" }
}
class ConvertToBase extends UnaryOpcode, TConvertToBase {
final override string toString() { result = "ConvertToBase" }
class ConvertToNonVirtualBase extends ConvertToBaseOpcode, TConvertToNonVirtualBase {
final override string toString() { result = "ConvertToNonVirtualBase" }
}
class ConvertToVirtualBase extends UnaryOpcode, TConvertToVirtualBase {
class ConvertToVirtualBase extends ConvertToBaseOpcode, TConvertToVirtualBase {
final override string toString() { result = "ConvertToVirtualBase" }
}

View File

@@ -991,14 +991,22 @@ class InheritanceConversionInstruction extends UnaryInstruction {
* to the address of a direct non-virtual base class.
*/
class ConvertToBaseInstruction extends InheritanceConversionInstruction {
ConvertToBaseInstruction() { getOpcode() instanceof Opcode::ConvertToBase }
ConvertToBaseInstruction() { getOpcode() instanceof ConvertToBaseOpcode }
}
/**
* Represents an instruction that converts from the address of a derived class
* to the address of a direct non-virtual base class.
*/
class ConvertToNonVirtualBaseInstruction extends ConvertToBaseInstruction {
ConvertToNonVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToNonVirtualBase }
}
/**
* Represents an instruction that converts from the address of a derived class
* to the address of a virtual base class.
*/
class ConvertToVirtualBaseInstruction extends InheritanceConversionInstruction {
class ConvertToVirtualBaseInstruction extends ConvertToBaseInstruction {
ConvertToVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToVirtualBase }
}

View File

@@ -109,7 +109,7 @@ private predicate operandIsPropagated(Operand operand, IntValue bitOffset) {
instr = operand.getUse() and
(
// Converting to a non-virtual base class adds the offset of the base class.
exists(ConvertToBaseInstruction convert |
exists(ConvertToNonVirtualBaseInstruction convert |
convert = instr and
bitOffset = Ints::mul(convert.getDerivation().getByteOffset(), 8)
)

View File

@@ -991,14 +991,22 @@ class InheritanceConversionInstruction extends UnaryInstruction {
* to the address of a direct non-virtual base class.
*/
class ConvertToBaseInstruction extends InheritanceConversionInstruction {
ConvertToBaseInstruction() { getOpcode() instanceof Opcode::ConvertToBase }
ConvertToBaseInstruction() { getOpcode() instanceof ConvertToBaseOpcode }
}
/**
* Represents an instruction that converts from the address of a derived class
* to the address of a direct non-virtual base class.
*/
class ConvertToNonVirtualBaseInstruction extends ConvertToBaseInstruction {
ConvertToNonVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToNonVirtualBase }
}
/**
* Represents an instruction that converts from the address of a derived class
* to the address of a virtual base class.
*/
class ConvertToVirtualBaseInstruction extends InheritanceConversionInstruction {
class ConvertToVirtualBaseInstruction extends ConvertToBaseInstruction {
ConvertToVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToVirtualBase }
}

View File

@@ -1038,7 +1038,7 @@ class TranslatedInheritanceConversion extends TranslatedSingleInstructionConvers
then
if expr.(BaseClassConversion).isVirtual()
then result instanceof Opcode::ConvertToVirtualBase
else result instanceof Opcode::ConvertToBase
else result instanceof Opcode::ConvertToNonVirtualBase
else result instanceof Opcode::ConvertToDerived
}
}

View File

@@ -752,7 +752,7 @@ abstract class TranslatedBaseStructorCall extends TranslatedStructorCallFromStru
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
tag = OnlyInstructionTag() and
opcode instanceof Opcode::ConvertToBase and
opcode instanceof Opcode::ConvertToNonVirtualBase and
resultType = getTypeForGLValue(call.getTarget().getDeclaringType())
}

View File

@@ -991,14 +991,22 @@ class InheritanceConversionInstruction extends UnaryInstruction {
* to the address of a direct non-virtual base class.
*/
class ConvertToBaseInstruction extends InheritanceConversionInstruction {
ConvertToBaseInstruction() { getOpcode() instanceof Opcode::ConvertToBase }
ConvertToBaseInstruction() { getOpcode() instanceof ConvertToBaseOpcode }
}
/**
* Represents an instruction that converts from the address of a derived class
* to the address of a direct non-virtual base class.
*/
class ConvertToNonVirtualBaseInstruction extends ConvertToBaseInstruction {
ConvertToNonVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToNonVirtualBase }
}
/**
* Represents an instruction that converts from the address of a derived class
* to the address of a virtual base class.
*/
class ConvertToVirtualBaseInstruction extends InheritanceConversionInstruction {
class ConvertToVirtualBaseInstruction extends ConvertToBaseInstruction {
ConvertToVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToVirtualBase }
}

View File

@@ -109,7 +109,7 @@ private predicate operandIsPropagated(Operand operand, IntValue bitOffset) {
instr = operand.getUse() and
(
// Converting to a non-virtual base class adds the offset of the base class.
exists(ConvertToBaseInstruction convert |
exists(ConvertToNonVirtualBaseInstruction convert |
convert = instr and
bitOffset = Ints::mul(convert.getDerivation().getByteOffset(), 8)
)

View File

@@ -3,7 +3,7 @@ import semmle.code.cpp.dataflow.DataFlow
module BoostorgAsio {
/**
* Represents boost::asio::ssl::context enum
* Represents the `boost::asio::ssl::context` enum.
*/
class SslContextMethod extends Enum {
SslContextMethod() {
@@ -12,7 +12,7 @@ module BoostorgAsio {
}
/**
* returns the value for a banned protocol
* Gets an enumeration constant for a banned protocol.
*/
EnumConstant getABannedProtocolConstant() {
result = this.getAnEnumConstant() and
@@ -56,14 +56,15 @@ module BoostorgAsio {
}
/**
* returns the value for a approved protocols, but that are hard-coded (i.e. no protocol negotiation)
* Gets an enumeration constant for an approved protocol, that is hard-coded
* (no protocol negotiation).
*/
EnumConstant getAnApprovedButHardcodedProtocolConstant() {
result = this.getATls12ProtocolConstant()
}
/**
* returns the value for a TLS v1.2 protocol
* Gets an enumeration constant for a TLS v1.2 protocol.
*/
EnumConstant getATls12ProtocolConstant() {
result = this.getAnEnumConstant() and
@@ -80,7 +81,7 @@ module BoostorgAsio {
}
/**
* returns the value for a TLS v1.3 protocol
* Gets an enumeration constant for a TLS v1.3 protocol.
*/
EnumConstant getATls13ProtocolConstant() {
result = this.getAnEnumConstant() and
@@ -97,7 +98,7 @@ module BoostorgAsio {
}
/**
* returns the value of a generic TLS or SSL/TLS protocol
* Gets an enumeration constant for a generic TLS or SSL/TLS protocol.
*/
EnumConstant getAGenericTlsProtocolConstant() {
result = this.getAnEnumConstant() and
@@ -116,7 +117,7 @@ module BoostorgAsio {
}
/**
* returns the value of a generic SSL/TLS protocol
* Gets an enumeration constant for a generic SSL/TLS protocol.
*/
EnumConstant getASslv23ProtocolConstant() {
result = this.getAnEnumConstant() and
@@ -135,7 +136,9 @@ module BoostorgAsio {
}
/**
* NOTE: ignore - Modern versions of OpenSSL do not support SSL v2 anymore, so this option is for backwards compatibility only
* Gets the value for the no_sslv2 constant, right shifted by 16 bits.
*
* Note that modern versions of OpelSSL do not support SSL v2, so this option is for backwards compatibility only.
*/
int getShiftedSslOptionsNoSsl2() {
// SSL_OP_NO_SSLv2 was removed from modern OpenSSL versions
@@ -143,7 +146,7 @@ module BoostorgAsio {
}
/**
* RightShift(16) value for no_sslv3 constant
* Gets the value for the no_sslv3 constant, right shifted by 16 bits.
*/
int getShiftedSslOptionsNoSsl3() {
// SSL_OP_NO_SSLv3 == 0x02000000U
@@ -151,7 +154,7 @@ module BoostorgAsio {
}
/**
* RightShift(16) value for no_tlsv1 constant
* Gets the value for the no_tlsv1 constant, right shifted by 16 bits.
*/
int getShiftedSslOptionsNoTls1() {
// SSL_OP_NO_TLSv1 == 0x04000000U
@@ -159,7 +162,7 @@ module BoostorgAsio {
}
/**
* RightShift(16) value for no_tlsv1_1 constant
* Gets the value for the no_tlsv1_1 constant, right shifted by 16 bits.
*/
int getShiftedSslOptionsNoTls1_1() {
// SSL_OP_NO_TLSv1_1 == 0x10000000U
@@ -167,7 +170,7 @@ module BoostorgAsio {
}
/**
* RightShift(16) value for no_tlsv1_2 constant
* Gets the value for the no_tlsv1_2 constant, right shifted by 16 bits.
*/
int getShiftedSslOptionsNoTls1_2() {
// SSL_OP_NO_TLSv1_2 == 0x08000000U
@@ -175,7 +178,7 @@ module BoostorgAsio {
}
/**
* RightShift(16) value for no_tlsv1_3 constant
* Gets the value for the no_tlsv1_3 constant, right shifted by 16 bits.
*/
int getShiftedSslOptionsNoTls1_3() {
// SSL_OP_NO_TLSv1_2 == 0x20000000U
@@ -183,7 +186,7 @@ module BoostorgAsio {
}
/**
* Represents boost::asio::ssl::context class
* Represents the `boost::asio::ssl::context` class.
*/
class SslContextClass extends Class {
SslContextClass() { this.getQualifiedName() = "boost::asio::ssl::context" }
@@ -196,7 +199,7 @@ module BoostorgAsio {
}
/**
* Represents boost::asio::ssl::context::set_options member function
* Represents `boost::asio::ssl::context::set_options` member function.
*/
class SslSetOptionsFunction extends Function {
SslSetOptionsFunction() {
@@ -205,7 +208,7 @@ module BoostorgAsio {
}
/**
* holds if the expression represents a banned protocol
* Holds if the expression represents a banned protocol.
*/
predicate isExprBannedBoostProtocol(Expr e) {
exists(Literal va | va = e |
@@ -244,7 +247,7 @@ module BoostorgAsio {
}
/**
* holds if the expression represents a TLS v1.2 protocol
* Holds if the expression represents a TLS v1.2 protocol.
*/
predicate isExprTls12BoostProtocol(Expr e) {
exists(Literal va | va = e |
@@ -269,7 +272,7 @@ module BoostorgAsio {
}
/**
* holds if the expression represents a protocol that requires Crypto Board approval
* Holds if the expression represents a protocol that requires Crypto Board approval.
*/
predicate isExprTls13BoostProtocol(Expr e) {
exists(Literal va | va = e |
@@ -294,7 +297,7 @@ module BoostorgAsio {
}
/**
* holds if the expression represents a generic TLS or SSL/TLS protocol
* Holds if the expression represents a generic TLS or SSL/TLS protocol.
*/
predicate isExprTlsBoostProtocol(Expr e) {
exists(Literal va | va = e |
@@ -325,7 +328,7 @@ module BoostorgAsio {
}
/**
* holds if the expression represents a generic SSl/TLS protocol
* Holds if the expression represents a generic SSl/TLS protocol.
*/
predicate isExprSslV23BoostProtocol(Expr e) {
exists(Literal va | va = e |
@@ -351,7 +354,8 @@ module BoostorgAsio {
//////////////////////// Dataflow /////////////////////
/**
* Abstract - Protocol value Flows to the first argument of the context constructor
* Abstract class for flows of protocol values to the first argument of a context
* constructor.
*/
abstract class SslContextCallAbstractConfig extends DataFlow::Configuration {
bindingset[this]
@@ -366,7 +370,7 @@ module BoostorgAsio {
}
/**
* any Protocol value Flows to the first argument of the context constructor
* Any protocol value that flows to the first argument of a context constructor.
*/
class SslContextCallConfig extends SslContextCallAbstractConfig {
SslContextCallConfig() { this = "SslContextCallConfig" }
@@ -380,7 +384,7 @@ module BoostorgAsio {
}
/**
* a banned protocol value Flows to the first argument of the context constructor
* A banned protocol value that flows to the first argument of a context constructor.
*/
class SslContextCallBannedProtocolConfig extends SslContextCallAbstractConfig {
SslContextCallBannedProtocolConfig() { this = "SslContextCallBannedProtocolConfig" }
@@ -395,7 +399,7 @@ module BoostorgAsio {
}
/**
* a TLS 1.2 protocol value Flows to the first argument of the context constructor
* A TLS 1.2 protocol value that flows to the first argument of a context constructor.
*/
class SslContextCallTls12ProtocolConfig extends SslContextCallAbstractConfig {
SslContextCallTls12ProtocolConfig() { this = "SslContextCallTls12ProtocolConfig" }
@@ -410,7 +414,7 @@ module BoostorgAsio {
}
/**
* a TLS 1.3 protocol value Flows to the first argument of the context constructor
* A TLS 1.3 protocol value that flows to the first argument of a context constructor.
*/
class SslContextCallTls13ProtocolConfig extends SslContextCallAbstractConfig {
SslContextCallTls13ProtocolConfig() { this = "SslContextCallTls12ProtocolConfig" }
@@ -425,7 +429,7 @@ module BoostorgAsio {
}
/**
* a generic TLS protocol value Flows to the first argument of the context constructor
* A generic TLS protocol value that flows to the first argument of a context constructor.
*/
class SslContextCallTlsProtocolConfig extends SslContextCallAbstractConfig {
SslContextCallTlsProtocolConfig() { this = "SslContextCallTlsProtocolConfig" }
@@ -440,7 +444,7 @@ module BoostorgAsio {
}
/**
* a context constructor call flows to a call calling SetOptions()
* A context constructor call that flows to a call to `SetOptions()`.
*/
class SslContextFlowsToSetOptionConfig extends DataFlow::Configuration {
SslContextFlowsToSetOptionConfig() { this = "SslContextFlowsToSetOptionConfig" }
@@ -464,7 +468,7 @@ module BoostorgAsio {
}
/**
* an option value flows to the 1st parameter of SetOptions()
* An option value that flows to the first parameter of a call to `SetOptions()`.
*/
class SslOptionConfig extends DataFlow::Configuration {
SslOptionConfig() { this = "SslOptionConfig" }

View File

@@ -35,15 +35,15 @@
| escape.cpp:146:5:146:18 | CopyValue | no_Point+8:0 | no_Point+8:0 |
| escape.cpp:146:7:146:17 | CopyValue | no_Point+8:0 | no_Point+8:0 |
| escape.cpp:146:17:146:17 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 |
| escape.cpp:149:5:149:14 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 |
| escape.cpp:149:5:149:14 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 |
| escape.cpp:149:5:149:14 | ConvertToNonVirtualBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 |
| escape.cpp:149:5:149:14 | ConvertToNonVirtualBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 |
| escape.cpp:149:16:149:16 | FieldAddress[b] | no_Derived+0:0 | no_Derived+0:0 |
| escape.cpp:150:18:150:27 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 |
| escape.cpp:150:18:150:27 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 |
| escape.cpp:150:18:150:27 | ConvertToNonVirtualBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 |
| escape.cpp:150:18:150:27 | ConvertToNonVirtualBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 |
| escape.cpp:150:29:150:29 | FieldAddress[b] | no_Derived+0:0 | no_Derived+0:0 |
| escape.cpp:151:5:151:14 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 |
| escape.cpp:151:5:151:14 | ConvertToNonVirtualBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 |
| escape.cpp:151:16:151:17 | FieldAddress[i2] | no_Derived+16:0 | no_Derived+16:0 |
| escape.cpp:152:19:152:28 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 |
| escape.cpp:152:19:152:28 | ConvertToNonVirtualBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 |
| escape.cpp:152:30:152:31 | FieldAddress[i2] | no_Derived+16:0 | no_Derived+16:0 |
| escape.cpp:155:17:155:30 | CopyValue | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 |
| escape.cpp:155:17:155:30 | Store | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 |

File diff suppressed because it is too large Load Diff

View File

@@ -700,65 +700,65 @@ test.cpp:
# 104| int inheritanceConversions(Derived*)
# 104| Block 0
# 104| v0_0(void) = EnterFunction :
# 104| m0_1(unknown) = AliasedDefinition :
# 104| v0_0(void) = EnterFunction :
# 104| m0_1(unknown) = AliasedDefinition :
# 104| valnum = unique
# 104| mu0_2(unknown) = UnmodeledDefinition :
# 104| mu0_2(unknown) = UnmodeledDefinition :
# 104| valnum = unique
# 104| r0_3(glval<Derived *>) = VariableAddress[pd] :
# 104| r0_3(glval<Derived *>) = VariableAddress[pd] :
# 104| valnum = r0_3
# 104| m0_4(Derived *) = InitializeParameter[pd] : &:r0_3
# 104| m0_4(Derived *) = InitializeParameter[pd] : &:r0_3
# 104| valnum = m0_4
# 105| r0_5(glval<int>) = VariableAddress[x] :
# 105| r0_5(glval<int>) = VariableAddress[x] :
# 105| valnum = unique
# 105| r0_6(glval<Derived *>) = VariableAddress[pd] :
# 105| r0_6(glval<Derived *>) = VariableAddress[pd] :
# 105| valnum = r0_3
# 105| r0_7(Derived *) = Load : &:r0_6, m0_4
# 105| r0_7(Derived *) = Load : &:r0_6, m0_4
# 105| valnum = m0_4
# 105| r0_8(Base *) = ConvertToBase[Derived : Base] : r0_7
# 105| r0_8(Base *) = ConvertToNonVirtualBase[Derived : Base] : r0_7
# 105| valnum = r0_8
# 105| r0_9(glval<int>) = FieldAddress[b] : r0_8
# 105| r0_9(glval<int>) = FieldAddress[b] : r0_8
# 105| valnum = r0_9
# 105| r0_10(int) = Load : &:r0_9, ~m0_1
# 105| r0_10(int) = Load : &:r0_9, ~m0_1
# 105| valnum = r0_10
# 105| m0_11(int) = Store : &:r0_5, r0_10
# 105| m0_11(int) = Store : &:r0_5, r0_10
# 105| valnum = r0_10
# 106| r0_12(glval<Base *>) = VariableAddress[pb] :
# 106| r0_12(glval<Base *>) = VariableAddress[pb] :
# 106| valnum = r0_12
# 106| r0_13(glval<Derived *>) = VariableAddress[pd] :
# 106| r0_13(glval<Derived *>) = VariableAddress[pd] :
# 106| valnum = r0_3
# 106| r0_14(Derived *) = Load : &:r0_13, m0_4
# 106| r0_14(Derived *) = Load : &:r0_13, m0_4
# 106| valnum = m0_4
# 106| r0_15(Base *) = ConvertToBase[Derived : Base] : r0_14
# 106| r0_15(Base *) = ConvertToNonVirtualBase[Derived : Base] : r0_14
# 106| valnum = r0_8
# 106| m0_16(Base *) = Store : &:r0_12, r0_15
# 106| m0_16(Base *) = Store : &:r0_12, r0_15
# 106| valnum = r0_8
# 107| r0_17(glval<int>) = VariableAddress[y] :
# 107| r0_17(glval<int>) = VariableAddress[y] :
# 107| valnum = r0_17
# 107| r0_18(glval<Base *>) = VariableAddress[pb] :
# 107| r0_18(glval<Base *>) = VariableAddress[pb] :
# 107| valnum = r0_12
# 107| r0_19(Base *) = Load : &:r0_18, m0_16
# 107| r0_19(Base *) = Load : &:r0_18, m0_16
# 107| valnum = r0_8
# 107| r0_20(glval<int>) = FieldAddress[b] : r0_19
# 107| r0_20(glval<int>) = FieldAddress[b] : r0_19
# 107| valnum = r0_9
# 107| r0_21(int) = Load : &:r0_20, ~m0_1
# 107| r0_21(int) = Load : &:r0_20, ~m0_1
# 107| valnum = r0_21
# 107| m0_22(int) = Store : &:r0_17, r0_21
# 107| m0_22(int) = Store : &:r0_17, r0_21
# 107| valnum = r0_21
# 109| r0_23(glval<int>) = VariableAddress[#return] :
# 109| r0_23(glval<int>) = VariableAddress[#return] :
# 109| valnum = r0_23
# 109| r0_24(glval<int>) = VariableAddress[y] :
# 109| r0_24(glval<int>) = VariableAddress[y] :
# 109| valnum = r0_17
# 109| r0_25(int) = Load : &:r0_24, m0_22
# 109| r0_25(int) = Load : &:r0_24, m0_22
# 109| valnum = r0_21
# 109| m0_26(int) = Store : &:r0_23, r0_25
# 109| m0_26(int) = Store : &:r0_23, r0_25
# 109| valnum = r0_21
# 104| r0_27(glval<int>) = VariableAddress[#return] :
# 104| r0_27(glval<int>) = VariableAddress[#return] :
# 104| valnum = r0_23
# 104| v0_28(void) = ReturnValue : &:r0_27, m0_26
# 104| v0_29(void) = UnmodeledUse : mu*
# 104| v0_30(void) = AliasedUse : ~m0_1
# 104| v0_31(void) = ExitFunction :
# 104| v0_28(void) = ReturnValue : &:r0_27, m0_26
# 104| v0_29(void) = UnmodeledUse : mu*
# 104| v0_30(void) = AliasedUse : ~m0_1
# 104| v0_31(void) = ExitFunction :
# 112| void test06()
# 112| Block 0

View File

@@ -1 +1,3 @@
| SignedOverflowCheck.cpp:35:9:35:23 | ... < ... | Bad overflow check. |
| SignedOverflowCheck.cpp:113:12:113:66 | ... < ... | Bad overflow check. |
| test.cpp:3:11:3:19 | ... < ... | Bad overflow check. |

View File

@@ -1,3 +1,4 @@
| templates.cpp:17:5:17:25 | ... < ... | Self comparison. |
| test.cpp:13:11:13:21 | ... == ... | Self comparison. |
| test.cpp:79:11:79:32 | ... == ... | Self comparison. |
| test.cpp:83:10:83:15 | ... == ... | Self comparison. |

View File

@@ -0,0 +1,130 @@
// Signed-comparison tests
/* 1. Signed-signed comparison. The semantics are undefined. */
bool cannotHoldAnother8(int n1) {
// clang 8.0.0 -O2: deleted (silently)
// gcc 9.2 -O2: deleted (silently)
// msvc 19.22 /O2: not deleted
return n1 + 8 < n1; // BAD
}
/* 2. Signed comparison with a narrower unsigned type. The narrower
type gets promoted to the (signed) larger type, and so the
semantics are undefined. */
bool cannotHoldAnotherUShort(int n1, unsigned short delta) {
// clang 8.0.0 -O2: deleted (silently)
// gcc 9.2 -O2: deleted (silently)
// msvc 19.22 /O2: not deleted
return n1 + delta < n1; // BAD
}
/* 3. Signed comparison with a non-narrower unsigned type. The
signed type gets promoted to (a possibly wider) unsigned type,
and the resulting comparison is unsigned. */
bool cannotHoldAnotherUInt(int n1, unsigned int delta) {
// clang 8.0.0 -O2: not deleted
// gcc 9.2 -O2: not deleted
// msvc 19.22 /O2: not deleted
return n1 + delta < n1; // GOOD
}
bool shortShort1(unsigned short n1, unsigned short delta) {
// BAD [BadAdditionOverflowCheck.ql]
// GOOD [SigneOverflowCheck.ql]: Test always fails, but will never overflow.
return n1 + delta < n1;
}
bool shortShort2(unsigned short n1, unsigned short delta) {
// clang 8.0.0 -O2: not deleted
// gcc 9.2 -O2: not deleted
// msvc 19.22 /O2: not deleted
return (unsigned short)(n1 + delta) < n1; // GOOD
}
/* Distinguish `varname` from `ptr->varname` and `obj.varname` */
struct N {
int n1;
} n, *np;
bool shortStruct1(unsigned short n1, unsigned short delta) {
return np->n1 + delta < n1; // GOOD
}
bool shortStruct1a(unsigned short n1, unsigned short delta) {
return n1 + delta < n.n1; // GOOD
}
bool shortStruct2(unsigned short n1, unsigned short delta) {
return (unsigned short)(n1 + delta) < n.n1; // GOOD
}
struct se {
int xPos;
short yPos;
short xSize;
short ySize;
};
extern se *getSo(void);
bool func1(se *so) {
se *o = getSo();
if (so->xPos + so->xSize < so->xPos // BAD
|| so->xPos > o->xPos + o->xSize) { // GOOD
// clang 8.0.0 -O2: not deleted
// gcc 9.2 -O2: not deleted
// msvc 19.22 /O2: not deleted
return false;
}
return true;
}
bool checkOverflow3(unsigned int a, unsigned short b) {
return (a + b < a); // GOOD
}
struct C {
unsigned int length;
};
int checkOverflow4(unsigned int ioff, C c) {
// not deleted by gcc or clang
if ((int)(ioff + c.length) < (int)ioff) return 0; // GOOD
return 1;
}
int overflow12(int n) {
// not deleted by gcc or clang
return (n + 32 <= (unsigned)n? -1: 1); // BAD: n + 32 can overflow
}
bool multipleCasts(char x) {
// BAD [UNDETECTED - BadAdditionOverflowCheck.ql]
// GOOD [SigneOverflowCheck.ql]: Test always fails, but will never overflow.
return (int)(unsigned short)x + 2 < (int)(unsigned short)x; // GOOD: cannot overflow
}
bool multipleCasts2(char x) {
// BAD [BadAdditionOverflowCheck.ql]
// GOOD [SigneOverflowCheck.ql]: Test always fails, but will never overflow.
return (int)(unsigned short)(x + '1') < (int)(unsigned short)x;
}
int does_it_overflow(int n1, unsigned short delta) {
return n1 + (unsigned)delta < n1; // GOOD: everything converted to unsigned
}
int overflow12b(int n) {
// not deleted by gcc or clang
return ((unsigned)(n + 32) <= (unsigned)n? -1: 1); // BAD: n + 32 may overflow
}
#define MACRO(E1, E2) (E1) <= (E2)? -1: 1
int overflow12_macro(int n) {
return MACRO((unsigned)(n + 32), (unsigned)n); // GOOD: inside a macro expansion
}

View File

@@ -0,0 +1,5 @@
| SignedOverflowCheck.cpp:8:12:8:22 | ... < ... | Testing for signed overflow may produce undefined results. |
| SignedOverflowCheck.cpp:18:12:18:26 | ... < ... | Testing for signed overflow may produce undefined results. |
| SignedOverflowCheck.cpp:73:6:73:36 | ... < ... | Testing for signed overflow may produce undefined results. |
| SignedOverflowCheck.cpp:99:10:99:30 | ... <= ... | Testing for signed overflow may produce undefined results. |
| SignedOverflowCheck.cpp:122:10:122:42 | ... <= ... | Testing for signed overflow may produce undefined results. |

View File

@@ -0,0 +1 @@
Likely Bugs/Arithmetic/SignedOverflowCheck.ql

View File

@@ -0,0 +1,22 @@
struct C1 {
static const int value = 5;
};
struct C2 {
static const int value = 6;
};
template<typename T1, typename T2>
bool compareValues() {
// Not all instantiations have T1 and T2 equal. Even if that's the case for
// all instantiations in the program, there could still be more such
// instantiations outside.
return
T1::value < T2::value || // GOOD
T1::value < T1::value || // BAD [NOT DETECTED]
C1::value < C1::value ; // BAD
}
bool callCompareValues() {
return compareValues<C1, C2> || compareValues<C1, C1>();
}

View File

@@ -1,11 +1,11 @@
// Test for BadAdditionOverflowCheck.
bool checkOverflow1(unsigned short a, unsigned short b) {
return (a + b < a); // BAD: a + b is automatically promoted to int.
return (a + b < a); // BAD: comparison always false (due to promotion).
}
// Test for BadAdditionOverflowCheck.
bool checkOverflow2(unsigned short a, unsigned short b) {
return ((unsigned short)(a + b) < a); // GOOD: explicit cast
return ((unsigned short)(a + b) < a); // GOOD
}
// Test for PointlessSelfComparison.

View File

@@ -0,0 +1,19 @@
__attribute__((format(printf, 1, 3)))
void myMultiplyDefinedPrintf(const char *format, const char *extraArg, ...)
{
// ...
}
__attribute__((format(printf, 1, 3)))
void myMultiplyDefinedPrintf2(const char *format, const char *extraArg, ...);
char *getString();
void test_custom_printf1()
{
myMultiplyDefinedPrintf("string", getString()); // GOOD
myMultiplyDefinedPrintf(getString(), "string"); // BAD [NOT DETECTED]
myMultiplyDefinedPrintf2("string", getString()); // GOOD (we can't tell which declaration is correct so we have to assume this is OK)
myMultiplyDefinedPrintf2(getString(), "string"); // GOOD (we can't tell which declaration is correct so we have to assume this is OK)
}

View File

@@ -0,0 +1,16 @@
__attribute__((format(printf, 2, 3)))
void myMultiplyDefinedPrintf(const char *extraArg, const char *format, ...); // this declaration does not match the definition
__attribute__((format(printf, 2, 3)))
void myMultiplyDefinedPrintf2(const char *extraArg, const char *format, ...);
char *getString();
void test_custom_printf2(char *string)
{
myMultiplyDefinedPrintf("string", getString()); // GOOD
myMultiplyDefinedPrintf(getString(), "string"); // BAD [NOT DETECTED]
myMultiplyDefinedPrintf2("string", getString()); // GOOD (we can't tell which declaration is correct so we have to assume this is OK)
myMultiplyDefinedPrintf2(getString(), "string"); // GOOD (we can't tell which declaration is correct so we have to assume this is OK)
}

View File

@@ -16,6 +16,43 @@
| printf1.h:114:18:114:18 | d | This argument should be of type 'long double' but is of type 'double' |
| printf1.h:147:19:147:19 | i | This argument should be of type 'long long' but is of type 'int' |
| printf1.h:148:19:148:20 | ui | This argument should be of type 'unsigned long long' but is of type 'unsigned int' |
| printf1.h:160:18:160:18 | i | This argument should be of type 'char *' but is of type 'int' |
| printf1.h:161:21:161:21 | s | This argument should be of type 'int' but is of type 'char *' |
| printf1.h:167:17:167:17 | i | This argument should be of type 'char *' but is of type 'int' |
| printf1.h:168:18:168:18 | i | This argument should be of type 'char *' but is of type 'int' |
| printf1.h:169:19:169:19 | i | This argument should be of type 'char *' but is of type 'int' |
| printf1.h:174:17:174:17 | s | This argument should be of type 'int' but is of type 'char *' |
| printf1.h:175:18:175:18 | s | This argument should be of type 'int' but is of type 'char *' |
| printf1.h:176:19:176:19 | s | This argument should be of type 'int' but is of type 'char *' |
| printf1.h:180:17:180:17 | s | This argument should be of type 'int' but is of type 'char *' |
| printf1.h:181:20:181:20 | i | This argument should be of type 'char *' but is of type 'int' |
| printf1.h:183:18:183:18 | s | This argument should be of type 'int' but is of type 'char *' |
| printf1.h:184:21:184:21 | i | This argument should be of type 'char *' but is of type 'int' |
| printf1.h:186:19:186:19 | s | This argument should be of type 'int' but is of type 'char *' |
| printf1.h:187:22:187:22 | i | This argument should be of type 'char *' but is of type 'int' |
| printf1.h:189:19:189:19 | s | This argument should be of type 'int' but is of type 'char *' |
| printf1.h:190:22:190:22 | i | This argument should be of type 'char *' but is of type 'int' |
| printf1.h:192:19:192:19 | s | This argument should be of type 'int' but is of type 'char *' |
| printf1.h:193:22:193:22 | s | This argument should be of type 'int' but is of type 'char *' |
| printf1.h:194:25:194:25 | i | This argument should be of type 'char *' but is of type 'int' |
| printf1.h:198:24:198:24 | s | This argument should be of type 'int' but is of type 'char *' |
| printf1.h:199:21:199:21 | i | This argument should be of type 'char *' but is of type 'int' |
| printf1.h:202:26:202:26 | s | This argument should be of type 'int' but is of type 'char *' |
| printf1.h:203:23:203:23 | i | This argument should be of type 'char *' but is of type 'int' |
| printf1.h:206:25:206:25 | s | This argument should be of type 'int' but is of type 'char *' |
| printf1.h:207:22:207:22 | i | This argument should be of type 'char *' but is of type 'int' |
| printf1.h:210:26:210:26 | s | This argument should be of type 'int' but is of type 'char *' |
| printf1.h:211:23:211:23 | i | This argument should be of type 'char *' but is of type 'int' |
| printf1.h:214:28:214:28 | s | This argument should be of type 'int' but is of type 'char *' |
| printf1.h:215:28:215:28 | s | This argument should be of type 'int' but is of type 'char *' |
| printf1.h:216:25:216:25 | i | This argument should be of type 'char *' but is of type 'int' |
| printf1.h:221:18:221:18 | s | This argument should be of type 'int' but is of type 'char *' |
| printf1.h:222:20:222:20 | s | This argument should be of type 'int' but is of type 'char *' |
| printf1.h:225:23:225:23 | i | This argument should be of type 'char *' but is of type 'int' |
| printf1.h:228:24:228:24 | i | This argument should be of type 'char *' but is of type 'int' |
| printf1.h:231:25:231:25 | i | This argument should be of type 'char *' but is of type 'int' |
| printf1.h:234:25:234:25 | i | This argument should be of type 'char *' but is of type 'int' |
| printf1.h:235:22:235:22 | s | This argument should be of type 'int' but is of type 'char *' |
| real_world.h:61:21:61:22 | & ... | This argument should be of type 'int *' but is of type 'short *' |
| real_world.h:62:22:62:23 | & ... | This argument should be of type 'short *' but is of type 'int *' |
| real_world.h:63:22:63:24 | & ... | This argument should be of type 'short *' but is of type 'unsigned int *' |

View File

@@ -0,0 +1,16 @@
__attribute__((format(printf, 1, 3)))
void myMultiplyDefinedPrintf(const char *format, const char *extraArg, ...)
{
// ...
}
__attribute__((format(printf, 1, 3)))
void myMultiplyDefinedPrintf2(const char *format, const char *extraArg, ...);
void test_custom_printf1()
{
myMultiplyDefinedPrintf("%i", "%f", 1); // GOOD
myMultiplyDefinedPrintf("%i", "%f", 1.0f); // BAD [NOT DETECTED]
myMultiplyDefinedPrintf2("%i", "%f", 1); // GOOD (we can't tell which declaration is correct so we have to assume this is OK)
myMultiplyDefinedPrintf2("%i", "%f", 1.0f); // GOOD (we can't tell which declaration is correct so we have to assume this is OK)
}

View File

@@ -0,0 +1,14 @@
__attribute__((format(printf, 2, 3)))
void myMultiplyDefinedPrintf(const char *extraArg, const char *format, ...); // this declaration does not match the definition
__attribute__((format(printf, 2, 3)))
void myMultiplyDefinedPrintf2(const char *extraArg, const char *format, ...);
void test_custom_printf2()
{
myMultiplyDefinedPrintf("%i", "%f", 1); // GOOD
myMultiplyDefinedPrintf("%i", "%f", 1.0f); // BAD [NOT DETECTED]
myMultiplyDefinedPrintf2("%i", "%f", 1); // GOOD (we can't tell which declaration is correct so we have to assume this is OK)
myMultiplyDefinedPrintf2("%i", "%f", 1.0f); // GOOD (we can't tell which declaration is correct so we have to assume this is OK)
}

View File

@@ -151,3 +151,86 @@ void fun4()
printf("%qi\n", ll); // GOOD
printf("%qu\n", ull); // GOOD
}
void complexFormatSymbols(int i, const char *s)
{
// positional arguments
printf("%1$i", i, s); // GOOD
printf("%2$s", i, s); // GOOD
printf("%1$s", i, s); // BAD
printf("%2$i", i, s); // BAD
// width / precision
printf("%4i", i); // GOOD
printf("%.4i", i); // GOOD
printf("%4.4i", i); // GOOD
printf("%4s", i); // BAD
printf("%.4s", i); // BAD
printf("%4.4s", i); // BAD
printf("%4s", s); // GOOD
printf("%.4s", s); // GOOD
printf("%4.4s", s); // GOOD
printf("%4i", s); // BAD
printf("%.4i", s); // BAD
printf("%4.4i", s); // BAD
// variable width / precision
printf("%*s", i, s); // GOOD
printf("%*s", s, s); // BAD
printf("%*s", i, i); // BAD
printf("%.*s", i, s); // GOOD
printf("%.*s", s, s); // BAD
printf("%.*s", i, i); // BAD
printf("%*.4s", i, s); // GOOD
printf("%*.4s", s, s); // BAD
printf("%*.4s", i, i); // BAD
printf("%4.*s", i, s); // GOOD
printf("%4.*s", s, s); // BAD
printf("%4.*s", i, i); // BAD
printf("%*.*s", i, i, s); // GOOD
printf("%*.*s", s, i, s); // BAD
printf("%*.*s", i, s, s); // BAD
printf("%*.*s", i, i, i); // BAD
// positional arguments mixed with variable width / precision
printf("%2$*1$s", i, s); // GOOD
printf("%2$*2$s", i, s); // BAD
printf("%1$*1$s", i, s); // BAD
printf("%2$*1$.4s", i, s); // GOOD
printf("%2$*2$.4s", i, s); // BAD
printf("%1$*1$.4s", i, s); // BAD
printf("%2$.*1$s", i, s); // GOOD
printf("%2$.*2$s", i, s); // BAD
printf("%1$.*1$s", i, s); // BAD
printf("%2$4.*1$s", i, s); // GOOD
printf("%2$4.*2$s", i, s); // BAD
printf("%1$4.*1$s", i, s); // BAD
printf("%2$*1$.*1$s", i, s); // GOOD
printf("%2$*2$.*1$s", i, s); // BAD
printf("%2$*1$.*2$s", i, s); // BAD
printf("%1$*1$.*1$s", i, s); // BAD
// left justify flag
printf("%-4s", s); // GOOD
printf("%1$-4s", s); // GOOD
printf("%-4i", s); // BAD
printf("%1$-4i", s); // BAD
printf("%1$-4s", s, i); // GOOD
printf("%2$-4s", s, i); // BAD
printf("%1$-.4s", s, i); // GOOD
printf("%2$-.4s", s, i); // BAD
printf("%1$-4.4s", s, i); // GOOD
printf("%2$-4.4s", s, i); // BAD
printf("%1$-*2$s", s, i); // GOOD
printf("%2$-*2$s", s, i); // BAD
printf("%1$-*1$s", s, i); // BAD
}

View File

@@ -1,3 +1,14 @@
| test2.cpp:15:32:15:33 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:15:32:15:33 | call to context | boost::asio::ssl::context::context | test2.cpp:14:40:14:72 | sslv23 | sslv23 | test2.cpp:15:32:15:33 | call to context | no_sslv3 has not been set |
| test2.cpp:23:32:23:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:23:32:23:65 | call to context | boost::asio::ssl::context::context | test2.cpp:23:32:23:64 | sslv23 | sslv23 | test2.cpp:23:32:23:65 | call to context | no_sslv3 has not been set |
| test2.cpp:23:32:23:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:23:32:23:65 | call to context | boost::asio::ssl::context::context | test2.cpp:23:32:23:64 | sslv23 | sslv23 | test2.cpp:23:32:23:65 | call to context | no_tlsv1 has not been set |
| test2.cpp:23:32:23:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:23:32:23:65 | call to context | boost::asio::ssl::context::context | test2.cpp:23:32:23:64 | sslv23 | sslv23 | test2.cpp:23:32:23:65 | call to context | no_tlsv1_1 has not been set |
| test2.cpp:31:32:31:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:31:32:31:65 | call to context | boost::asio::ssl::context::context | test2.cpp:31:32:31:64 | sslv23 | sslv23 | test2.cpp:31:32:31:65 | call to context | no_sslv3 has not been set |
| test2.cpp:31:32:31:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:31:32:31:65 | call to context | boost::asio::ssl::context::context | test2.cpp:31:32:31:64 | sslv23 | sslv23 | test2.cpp:31:32:31:65 | call to context | no_tlsv1 has not been set |
| test2.cpp:31:32:31:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:31:32:31:65 | call to context | boost::asio::ssl::context::context | test2.cpp:31:32:31:64 | sslv23 | sslv23 | test2.cpp:31:32:31:65 | call to context | no_tlsv1_1 has not been set |
| test2.cpp:45:35:45:98 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:45:35:45:98 | call to context | boost::asio::ssl::context::context | test2.cpp:45:65:45:97 | sslv23 | sslv23 | test2.cpp:45:35:45:98 | call to context | no_sslv3 has not been set |
| test2.cpp:52:32:52:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:52:32:52:65 | call to context | boost::asio::ssl::context::context | test2.cpp:52:32:52:64 | sslv23 | sslv23 | test2.cpp:52:32:52:65 | call to context | no_sslv3 has not been set |
| test2.cpp:52:32:52:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:52:32:52:65 | call to context | boost::asio::ssl::context::context | test2.cpp:52:32:52:64 | sslv23 | sslv23 | test2.cpp:52:32:52:65 | call to context | no_tlsv1 has not been set |
| test2.cpp:52:32:52:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:52:32:52:65 | call to context | boost::asio::ssl::context::context | test2.cpp:52:32:52:64 | sslv23 | sslv23 | test2.cpp:52:32:52:65 | call to context | no_tlsv1_1 has not been set |
| test.cpp:25:32:25:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test.cpp:25:32:25:65 | call to context | boost::asio::ssl::context::context | test.cpp:25:32:25:64 | sslv23 | sslv23 | test.cpp:25:32:25:65 | call to context | no_sslv3 has not been set |
| test.cpp:31:32:31:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test.cpp:31:32:31:65 | call to context | boost::asio::ssl::context::context | test.cpp:31:32:31:64 | sslv23 | sslv23 | test.cpp:31:32:31:65 | call to context | no_sslv3 has not been set |
| test.cpp:31:32:31:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test.cpp:31:32:31:65 | call to context | boost::asio::ssl::context::context | test.cpp:31:32:31:64 | sslv23 | sslv23 | test.cpp:31:32:31:65 | call to context | no_tlsv1 has not been set |

View File

@@ -0,0 +1,55 @@
#include "asio/boost_simulation.hpp"
void good1()
{
// GOOD
boost::asio::ssl::context::method m = boost::asio::ssl::context::sslv23;
boost::asio::ssl::context ctx(m);
ctx.set_options(boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::no_tlsv1_1 | boost::asio::ssl::context::no_sslv3);
}
void bad1()
{
// BAD: missing disable SSLv3
boost::asio::ssl::context::method m = boost::asio::ssl::context::sslv23;
boost::asio::ssl::context ctx(m);
ctx.set_options(boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::no_tlsv1_1);
}
void good2()
{
// GOOD [FALSE POSITIVE x 3]
boost::asio::ssl::context::options opts = boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::no_tlsv1_1 | boost::asio::ssl::context::no_sslv3;
boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
ctx.set_options(opts);
}
void bad2()
{
// BAD: missing disable SSLv3 [WITH FALSE POSITIVE x 2]
boost::asio::ssl::context::options opts = boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::no_tlsv1_1;
boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
ctx.set_options(opts);
}
void good3()
{
// GOOD
boost::asio::ssl::context *ctx = new boost::asio::ssl::context(boost::asio::ssl::context::sslv23);
ctx->set_options(boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::no_tlsv1_1 | boost::asio::ssl::context::no_sslv3);
}
void bad3()
{
// BAD: missing disable SSLv3
boost::asio::ssl::context *ctx = new boost::asio::ssl::context(boost::asio::ssl::context::sslv23);
ctx->set_options(boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::no_tlsv1_1);
}
void bad4()
{
// BAD: missing disable SSLv3
boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
}

View File

@@ -29,7 +29,7 @@ leaving the website vulnerable to cross-site scripting.</p>
<li>
OWASP:
<a href="https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet">XSS
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html">XSS
(Cross Site Scripting) Prevention Cheat Sheet</a>.
</li>
<li>

View File

@@ -33,7 +33,7 @@ the query cannot be changed by a malicious user.</p>
</example>
<references>
<li>OWASP: <a href="https://www.owasp.org/index.php?title=LDAP_Injection_Prevention_Cheat_Sheet">LDAP Injection Prevention Cheat Sheet</a>.</li>
<li>OWASP: <a href="https://cheatsheetseries.owasp.org/cheatsheets/LDAP_Injection_Prevention_Cheat_Sheet.html">LDAP Injection Prevention Cheat Sheet</a>.</li>
<li>OWASP: <a href="https://www.owasp.org/index.php/Preventing_LDAP_Injection_in_Java">Preventing LDAP Injection in Java</a>.</li>
<li>AntiXSS doc: <a href="http://www.nudoq.org/#!/Packages/AntiXSS/AntiXssLibrary/Encoder/M/LdapFilterEncode">LdapFilterEncode</a>.</li>
<li>AntiXSS doc: <a href="http://www.nudoq.org/#!/Packages/AntiXSS/AntiXssLibrary/Encoder/M/LdapDistinguishedNameEncode">LdapDistinguishedNameEncode</a>.</li>

View File

@@ -51,7 +51,7 @@ This next example shows how to specify the <code>X-Frame-Options</code> header w
<li>
OWASP:
<a href="https://www.owasp.org/index.php/Clickjacking_Defense_Cheat_Sheet">Clickjacking Defense Cheat Sheet</a>.
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html">Clickjacking Defense Cheat Sheet</a>.
</li>
<li>
Mozilla:

View File

@@ -32,7 +32,7 @@ It also shows how to remedy the problem by validating the user input against a k
<li>
OWASP:
<a href="https://www.owasp.org/index.php/Unvalidated_Redirects_and_Forwards_Cheat_Sheet">XSS
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html">XSS
Unvalidated Redirects and Forwards Cheat Sheet</a>.
</li>
<li>

View File

@@ -38,7 +38,7 @@ The solution is to set the <code>DtdProcessing</code> property to <code>DtdProce
<li>
OWASP:
<a href="https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet">XML External Entity (XXE) Prevention Cheat Sheet</a>.
<a href="https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html">XML External Entity (XXE) Prevention Cheat Sheet</a>.
</li>
<li>
Microsoft Docs: <a href="https://msdn.microsoft.com/en-us/library/system.xml.xmlreadersettings(v=vs.110).aspx#Anchor_6">System.XML: Security considerations</a>.

View File

@@ -34,7 +34,7 @@ private newtype TOpcode =
TPointerSub() or
TPointerDiff() or
TConvert() or
TConvertToBase() or
TConvertToNonVirtualBase() or
TConvertToVirtualBase() or
TConvertToDerived() or
TCheckedConvertOrNull() or
@@ -110,6 +110,8 @@ abstract class RelationalOpcode extends CompareOpcode { }
abstract class CopyOpcode extends Opcode { }
abstract class ConvertToBaseOpcode extends UnaryOpcode { }
abstract class MemoryAccessOpcode extends Opcode { }
abstract class ReturnOpcode extends Opcode { }
@@ -302,11 +304,11 @@ module Opcode {
final override string toString() { result = "Convert" }
}
class ConvertToBase extends UnaryOpcode, TConvertToBase {
final override string toString() { result = "ConvertToBase" }
class ConvertToNonVirtualBase extends ConvertToBaseOpcode, TConvertToNonVirtualBase {
final override string toString() { result = "ConvertToNonVirtualBase" }
}
class ConvertToVirtualBase extends UnaryOpcode, TConvertToVirtualBase {
class ConvertToVirtualBase extends ConvertToBaseOpcode, TConvertToVirtualBase {
final override string toString() { result = "ConvertToVirtualBase" }
}

View File

@@ -991,14 +991,22 @@ class InheritanceConversionInstruction extends UnaryInstruction {
* to the address of a direct non-virtual base class.
*/
class ConvertToBaseInstruction extends InheritanceConversionInstruction {
ConvertToBaseInstruction() { getOpcode() instanceof Opcode::ConvertToBase }
ConvertToBaseInstruction() { getOpcode() instanceof ConvertToBaseOpcode }
}
/**
* Represents an instruction that converts from the address of a derived class
* to the address of a direct non-virtual base class.
*/
class ConvertToNonVirtualBaseInstruction extends ConvertToBaseInstruction {
ConvertToNonVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToNonVirtualBase }
}
/**
* Represents an instruction that converts from the address of a derived class
* to the address of a virtual base class.
*/
class ConvertToVirtualBaseInstruction extends InheritanceConversionInstruction {
class ConvertToVirtualBaseInstruction extends ConvertToBaseInstruction {
ConvertToVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToVirtualBase }
}

View File

@@ -991,14 +991,22 @@ class InheritanceConversionInstruction extends UnaryInstruction {
* to the address of a direct non-virtual base class.
*/
class ConvertToBaseInstruction extends InheritanceConversionInstruction {
ConvertToBaseInstruction() { getOpcode() instanceof Opcode::ConvertToBase }
ConvertToBaseInstruction() { getOpcode() instanceof ConvertToBaseOpcode }
}
/**
* Represents an instruction that converts from the address of a derived class
* to the address of a direct non-virtual base class.
*/
class ConvertToNonVirtualBaseInstruction extends ConvertToBaseInstruction {
ConvertToNonVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToNonVirtualBase }
}
/**
* Represents an instruction that converts from the address of a derived class
* to the address of a virtual base class.
*/
class ConvertToVirtualBaseInstruction extends InheritanceConversionInstruction {
class ConvertToVirtualBaseInstruction extends ConvertToBaseInstruction {
ConvertToVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToVirtualBase }
}

View File

@@ -105,7 +105,7 @@ private predicate operandIsPropagated(Operand operand, IntValue bitOffset) {
(
// REVIEW: See the REVIEW comment bellow
// // Converting to a non-virtual base class adds the offset of the base class.
// exists(ConvertToBaseInstruction convert |
// exists(ConvertToNonVirtualBaseInstruction convert |
// convert = instr and
// bitOffset = Ints::mul(convert.getDerivation().getByteOffset(), 8)
// )

View File

@@ -56,9 +56,9 @@ def setup(sphinx):
# built documents.
#
# The short X.Y version.
version = u'1.22'
version = u'1.22.1'
# The full version, including alpha/beta/rc tags.
release = u'1.22'
release = u'1.22.1'
copyright = u'2019 Semmle Ltd'
author = u'Semmle Ltd'

View File

@@ -87,6 +87,10 @@ Now we can write a query using these classes:
Note that there is no need to check whether anything is added to the ``strlen`` expression, as it would be in the corrected C code ``malloc(strlen(string) + 1)``. This is because the corrected code would in fact be an ``AddExpr`` containing a ``StrlenCall``, not an instance of ``StrlenCall`` itself. A side-effect of this approach is that we omit certain unlikely patterns such as ``malloc(strlen(string) + 0``). In practice we can always come back and extend our query to cover this pattern if it is a concern.
.. pull-quote::
Tip
For some projects, this query may not return any results. Possibly the project you are querying does not have any problems of this kind, but it is also important to make sure the query itself is working properly. One solution is to set up a test project with examples of correct and incorrect code to run the query against (the C code at the very top of this page makes a good starting point). Another approach is to test each part of the query individually to make sure everything is working.
When you have defined the basic query then you can refine the query to include further coding patterns or to exclude false positives:

View File

@@ -20,17 +20,6 @@ These topics provide an overview of the CodeQL libraries for C# and show example
- :doc:`Tutorial: Analyzing data flow in C# <dataflow>` demonstrates how to write queries using the standard data flow and taint tracking libraries for C#.
.. raw:: html
<!-- Working with call graphs(call-graph) - how to construct and query call graphs, and work with dynamic and virtual dispatch. -->
.. raw:: html
<!-- Working with control flow(control-flow) - how to query intra-procedural control flow. -->
.. raw:: html
<!-- Working with comments(comments) - how to query comments and XML documentation. -->
Other resources
---------------

View File

@@ -78,6 +78,8 @@ Given this API, we can easily write a query that finds methods that are not call
`See this in the query console <https://lgtm.com/query/665280012/>`__. This simple query typically returns a large number of results.
.. pull-quote::
Note
We have to use ``polyCalls`` instead of ``calls`` here: we want to be reasonably sure that ``callee`` is not called, either directly or via overriding.

View File

@@ -18,6 +18,8 @@ Specifically, consider the following code snippet:
If ``l`` is bigger than 2\ :sup:`31`\ - 1 (the largest positive value of type ``int``), then this loop will never terminate: ``i`` will start at zero, being incremented all the way up to 2\ :sup:`31`\ - 1, which is still smaller than ``l``. When it is incremented once more, an arithmetic overflow occurs, and ``i`` becomes -2\ :sup:`31`\, which also is smaller than ``l``! Eventually, ``i`` will reach zero again, and the cycle repeats.
.. pull-quote::
More about overflow
All primitive numeric types have a maximum value, beyond which they will wrap around to their lowest possible value (called an "overflow"). For ``int``, this maximum value is 2\ :sup:`31`\ - 1. Type ``long`` can accommodate larger values up to a maximum of 2\ :sup:`63`\ - 1. In this example, this means that ``l`` can take on a value that is higher than the maximum for type ``int``; ``i`` will never be able to reach this value, instead overflowing and returning to a low value.

View File

@@ -14,6 +14,10 @@ The library is implemented as a set of QL modules, that is, files with the exten
The rest of this topic briefly summarizes the most important classes and predicates provided by this library.
.. pull-quote::
Note
The example queries in this topic illustrate the types of results returned by different library classes. The results themselves are not interesting but can be used as the basis for developing a more complex query. The tutorial topics show how you can take a simple query and fine-tune it to find precisely the results you're interested in.
Summary of the library classes
@@ -315,7 +319,11 @@ Class ``Javadoc`` represents an entire Javadoc comment as a tree of ``JavadocEle
`See this in the query console <https://lgtm.com/query/670490015/>`__. None of the LGTM.com demo projects uses the ``@author`` tag on private fields.
Note that on line 5 we used ``getParent+`` to capture tags that are nested at any depth within the Javadoc comment.
.. pull-quote::
Note
On line 5 we used ``getParent+`` to capture tags that are nested at any depth within the Javadoc comment.
For more information on working with Javadoc, see the :doc:`tutorial on Javadoc <javadoc>`.
@@ -369,7 +377,7 @@ Conversely, ``Callable.getAReference`` returns a ``Call`` that refers to it. So
where not exists(c.getAReference())
select c
`See this in the query console <https://lgtm.com/query/666680036/>`__. The LGTM.com demo projects all appear to have many methods that are not called directly, but this is unlikely to be the whole story. To explore this area further, see `Navigating the call graph <call-graph>`__.
`See this in the query console <https://lgtm.com/query/666680036/>`__. The LGTM.com demo projects all appear to have many methods that are not called directly, but this is unlikely to be the whole story. To explore this area further, see :doc:`Navigating the call graph <call-graph>`.
For more information about callables and calls, see the :doc:`call graph tutorial <call-graph>`.

View File

@@ -32,6 +32,8 @@ To determine ancestor types (including immediate super types, and also *their* s
`See this in the query console <https://lgtm.com/query/674620010/>`__. If this query were run on the example snippet above, the query would return ``A``, ``I``, and ``java.lang.Object``.
.. pull-quote::
Tip
If you want to see the location of ``B`` as well as ``A``, you can replace ``B.getASupertype+()`` with ``B.getASupertype*()`` and re-run the query.

View File

@@ -224,7 +224,7 @@ The `TopLevel <https://help.semmle.com/qldoc/javascript/semmle/javascript/AST.ql
.. pull-quote::
Note
Note
By default, LGTM filters out alerts in minified top-levels, since they are often hard to interpret. When writing your own queries in the LGTM query console, this filtering is *not* done automatically, so you may want to explicitly add a condition of the form ``and not e.getTopLevel().isMinified()`` or similar to your query to exclude results in minified code.

View File

@@ -10,6 +10,8 @@ In this example we look for all the "getters" in a program. Programmers moving t
Using the member predicate ``Function.getName()``, we can list all of the getter functions in a database:
.. pull-quote::
Tip
Instead of copying this query, try typing the code. As you start to write a name that matches a library class, a pop-up is displayed making it easy for you to select the class that you want.

View File

@@ -106,12 +106,12 @@ Examples
Each syntactic element in Python source is recorded in the CodeQL database. These can be queried via the corresponding class. Let us start with a couple of simple examples.
1. Finding all finally blocks
'''''''''''''''''''''''''''''
1. Finding all ``finally`` blocks
'''''''''''''''''''''''''''''''''
For our first example, we can find all ``finally`` blocks by using the ``Try`` class:
**Find all ``finally`` blocks**
**Find all** ``finally`` **blocks**
.. code-block:: ql
@@ -122,8 +122,8 @@ For our first example, we can find all ``finally`` blocks by using the ``Try`` c
`See this in the query console <https://lgtm.com/query/659662193/>`__. Many projects include examples of this pattern.
2. Finding 'except' blocks that do nothing
''''''''''''''''''''''''''''''''''''''''''
2. Finding ``except`` blocks that do nothing
''''''''''''''''''''''''''''''''''''''''''''
For our second example, we can use a simplified version of a query from the standard query set. We look for all ``except`` blocks that do nothing.
@@ -141,7 +141,7 @@ where ``ex`` is an ``ExceptStmt`` and ``Pass`` is the class representing ``pass`
Both forms are equivalent. Using the positive expression, the whole query looks like this:
**Find pass-only ``except`` blocks**
**Find pass-only** ``except`` **blocks**
.. code-block:: ql

View File

@@ -37,7 +37,8 @@ The predicate ``ControlFlowNode.pointsTo(...)`` shows which object a control flo
predicate pointsTo(Context context, Value object, ControlFlowNode origin)
``object`` is an object that the control flow node refers to, and ``origin`` is where the object comes from, which is useful for displaying meaningful results.
The third form includes the ``context`` in which the control flow node refers to the ``object``. This form can usually be ignored.
The third form includes the ``context`` in which the control flow node refers to the ``object``. This form can usually be ignored.
.. pull-quote::
@@ -62,7 +63,7 @@ We want to find ``except`` blocks in a ``try`` statement that are in the wrong o
First we can write a query to find ordered pairs of ``except`` blocks for a ``try`` statement.
**Ordered except blocks in same ``try`` statement**
**Ordered except blocks in same** ``try`` **statement**
.. code-block:: ql
@@ -81,7 +82,7 @@ Here ``ex1`` and ``ex2`` are both ``except`` handlers in the ``try`` statement `
The results of this query need to be filtered to return only results where ``ex1`` is more general than ``ex2``. We can use the fact that an ``except`` block is more general than another block if the class it handles is a superclass of the other.
**More general ``except`` block**
**More general** ``except`` **block**
.. code-block:: ql
@@ -102,7 +103,7 @@ ensures that ``cls1`` is a ``ClassValue`` that the ``except`` block would handle
Combining the parts of the query we get this:
**More general ``except`` block precedes more specific**
**More general** ``except`` **block precedes more specific**
.. code-block:: ql

View File

@@ -143,7 +143,7 @@ Python implementations commonly cache small integers and single character string
We can check for these as follows:
**Find comparisons to integer or string literals using ``is``**
**Find comparisons to integer or string literals using** ``is``
.. code-block:: ql
@@ -158,6 +158,8 @@ We can check for these as follows:
The clause ``cmp.getOp(0) instanceof Is and cmp.getComparator(0) = literal`` checks that the first comparison operator is "is" and that the first comparator is a literal.
.. pull-quote::
Tip
We have to use ``cmp.getOp(0)`` and ``cmp.getComparator(0)``\ as there is no ``cmp.getOp()`` or ``cmp.getComparator()``. The reason for this is that a ``Compare`` expression can have multiple operators. For example, the expression ``3 < x < 7`` has two operators and two comparators. You use ``cmp.getComparator(0)`` to get the first comparator (in this example the ``3``) and ``cmp.getComparator(1)`` to get the second comparator (in this example the ``7``).
@@ -253,9 +255,7 @@ checks that the value of the attribute (the expression to the left of the dot in
Class and function definitions
------------------------------
As Python is a dynamically typed language, class, and function definitions are executable statements. This means that a class statement is both a statement and a scope containing statements. To represent this cleanly the class definition is broken into a number of parts. At runtime, when a class definition is executed a class object is created and then assigned to a variable of the same name in the scope enclosing the class. This class is created from a code-object representing the source code for the body of the class. To represent this the ``ClassDef`` class (which represents a ``class`` statement) subclasses ``Assign``. The ``Class`` class, which represents the body of the class, can be accessed via the ``ClassDef.getDefinedClass()``
``FunctionDef``, ``Function`` are handled similarly.
As Python is a dynamically typed language, class, and function definitions are executable statements. This means that a class statement is both a statement and a scope containing statements. To represent this cleanly the class definition is broken into a number of parts. At runtime, when a class definition is executed a class object is created and then assigned to a variable of the same name in the scope enclosing the class. This class is created from a code-object representing the source code for the body of the class. To represent this the ``ClassDef`` class (which represents a ``class`` statement) subclasses ``Assign``. The ``Class`` class, which represents the body of the class, can be accessed via the ``ClassDef.getDefinedClass()``. ``FunctionDef`` and ``Function`` are handled similarly.
Here is the relevant part of the class hierarchy:

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
#
# QL and LGTM support info build configuration file, created
# CodeQL and LGTM support info build configuration file, created
# on Tuesday 19th February.
#
# This file is execfile()d with the current directory set to its

View File

@@ -1,7 +1,7 @@
Frameworks and libraries
########################
The QL libraries and queries in version |version| have been explicitly checked against the libraries and frameworks listed below.
The libraries and queries in version |version| have been explicitly checked against the libraries and frameworks listed below.
.. pull-quote::

View File

@@ -1,7 +1,7 @@
Supported languages and frameworks
##################################
These pages describe the languages and frameworks supported in the latest enterprise release of QL and LGTM.
These pages describe the languages and frameworks supported in the latest enterprise release of CodeQL and LGTM. (CodeQL was previously known as QL.)
Users of `LGTM.com <https://lgtm.com/>`_ may find that additional features are supported because it's updated more frequently.
For details see:
@@ -11,4 +11,4 @@ For details see:
language-support.rst
framework-support.rst
For details of the QL libraries, see `QL standard libraries <https://help.semmle.com/QL/ql-libraries.html>`_.
For details of the CodeQL libraries, see `CodeQL standard libraries <https://help.semmle.com/QL/ql-libraries.html>`_.

View File

@@ -1,7 +1,8 @@
Languages and compilers
#######################
QL and LGTM version |version| support analysis of the following languages compiled by the following compilers.
CodeQL and LGTM version |version| support analysis of the following languages compiled by the following compilers.
(CodeQL was previously known as QL.)
Note that where there are several versions or dialects of a language, the supported variants are listed.
If your code requires a particular version of a compiler, check that this version is included below.

View File

@@ -10,6 +10,7 @@ C#,C# up to 7.3. with .NET up to 4.8 [3]_.,"Microsoft Visual Studio up to 2019,
.NET Core up to 2.2","``.sln``, ``.csproj``, ``.cs``, ``.cshtml``, ``.xaml``"
COBOL,ANSI 85 or newer [4]_.,Not applicable,"``.cbl``, ``.CBL``, ``.cpy``, ``.CPY``, ``.copy``, ``.COPY``"
Go (aka Golang), "Go up to 1.13", "Go 1.11 or more recent", ``.go``
Java,"Java 6 to 12 [5]_.","javac (OpenJDK and Oracle JDK),
Eclipse compiler for Java (ECJ) [6]_.",``.java``
1 Language Variants Compilers Extensions
10
11
12
13
14
15
16

View File

@@ -1,18 +0,0 @@
/**
* @name Display strings of callables
* @kind display-string
* @metricType callable
* @id java/callable-display-strings
*/
import java
private string prefix(Callable c) {
if c instanceof Constructor and c.getDeclaringType() instanceof AnonymousClass
then result = "<anonymous constructor>"
else result = ""
}
from Callable c
where c.fromSource()
select c, prefix(c) + c.getStringSignature()

View File

@@ -1,13 +0,0 @@
/**
* @name Extents of callables
* @kind extent
* @metricType callable
* @id java/callable-extents
*/
import java
import Extents
from RangeCallable c
where c.fromSource()
select c.getLocation(), c

View File

@@ -1,12 +0,0 @@
/**
* @name Source links of callables
* @kind source-link
* @metricType callable
* @id java/callable-source-links
*/
import java
from Callable c
where c.fromSource()
select c, c.getFile()

View File

@@ -1,16 +0,0 @@
/**
* @name Display strings of reference types
* @kind display-string
* @metricType reftype
* @id java/reference-type-display-strings
*/
import java
private string suffix(RefType t) {
if t instanceof AnonymousClass then result = "<anonymous class>" else result = ""
}
from RefType t
where t.fromSource()
select t, t.nestedName() + suffix(t)

View File

@@ -1,13 +0,0 @@
/**
* @name Extents of reftypes
* @kind extent
* @metricType reftype
* @id java/reference-type-extents
*/
import java
import Extents
from RangeRefType t
where t.fromSource()
select t.getLocation(), t

View File

@@ -1,12 +0,0 @@
/**
* @name Source links of reference types
* @kind source-link
* @metricType reftype
* @id java/reference-type-source-links
*/
import java
from RefType t
where t.fromSource()
select t, t.getFile()

View File

@@ -29,7 +29,7 @@ leaving the website vulnerable to cross-site scripting.</p>
<li>
OWASP:
<a href="https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet">XSS
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html">XSS
(Cross Site Scripting) Prevention Cheat Sheet</a>.
</li>
<li>

View File

@@ -67,7 +67,7 @@ in the environment variable or user-supplied value are not given any special tre
<li>
OWASP:
<a href="https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet">SQL
<a href="https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html">SQL
Injection Prevention Cheat Sheet</a>.
</li>
<li>The CERT Oracle Secure Coding Standard for Java:

View File

@@ -39,7 +39,7 @@ treatment.</p>
<li>
OWASP:
<a href="https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet">SQL
<a href="https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html">SQL
Injection Prevention Cheat Sheet</a>.
</li>
<li>The CERT Oracle Secure Coding Standard for Java:

View File

@@ -37,7 +37,7 @@ connection is a secure SSL connection.</p>
Class HttpsURLConnection</a>.</li>
<li>
OWASP:
<a href="https://www.owasp.org/index.php/Transport_Layer_Protection_Cheat_Sheet">Transport Layer Protection Cheat Sheet</a>.
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Protection_Cheat_Sheet.html">Transport Layer Protection Cheat Sheet</a>.
</li>

View File

@@ -38,7 +38,7 @@ Class HttpsURLConnection</a>.</li>
Class SSLSocket</a>.</li>
<li>
OWASP:
<a href="https://www.owasp.org/index.php/Transport_Layer_Protection_Cheat_Sheet">Transport Layer Protection Cheat Sheet</a>.
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Protection_Cheat_Sheet.html">Transport Layer Protection Cheat Sheet</a>.
</li>

View File

@@ -33,7 +33,7 @@ uses explicit SSL factories, which are preferable.</p>
Class SSLSocketFactory</a>.</li>
<li>
OWASP:
<a href="https://www.owasp.org/index.php/Transport_Layer_Protection_Cheat_Sheet">Transport Layer Protection Cheat Sheet</a>.
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Protection_Cheat_Sheet.html">Transport Layer Protection Cheat Sheet</a>.
</li>

View File

@@ -58,7 +58,7 @@ OWASP vulnerability description:
</li>
<li>
OWASP guidance on deserializing objects:
<a href="https://www.owasp.org/index.php/Deserialization_Cheat_Sheet">Deserialization Cheat Sheet</a>.
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html">Deserialization Cheat Sheet</a>.
</li>
<li>
Talks by Chris Frohoff &amp; Gabriel Lawrence:

View File

@@ -12,7 +12,7 @@
import java
import semmle.code.java.dataflow.FlowSources
import UnsafeDeserialization
import semmle.code.java.security.UnsafeDeserialization
import DataFlow::PathGraph
class UnsafeDeserializationConfig extends TaintTracking::Configuration {

View File

@@ -52,7 +52,7 @@ OWASP vulnerability description:
</li>
<li>
OWASP guidance on parsing xml files:
<a href="https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#Java">XXE Prevention Cheat Sheet</a>.
<a href="https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#java">XXE Prevention Cheat Sheet</a>.
</li>
<li>
Paper by Timothy Morgen:

View File

@@ -49,7 +49,7 @@ abstract class ParserConfig extends MethodAccess {
}
/*
* https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#DocumentBuilder
* https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#jaxp-documentbuilderfactory-saxparserfactory-and-dom4j
*/
/** The class `javax.xml.parsers.DocumentBuilderFactory`. */
@@ -227,7 +227,7 @@ class SafeDocumentBuilder extends DocumentBuilderConstruction {
}
/*
* https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#XMLInputFactory_.28a_StAX_parser.29
* https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#xmlinputfactory-a-stax-parser
*/
/** The class `javax.xml.stream.XMLInputFactory`. */
@@ -353,7 +353,7 @@ class SafeXmlInputFactory extends VarAccess {
}
/*
* https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#SAXBuilder
* https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#saxbuilder
*/
/**
@@ -429,7 +429,7 @@ class SafeSAXBuilder extends VarAccess {
/*
* The case in
* https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#Unmarshaller
* https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#jaxb-unmarshaller
* will be split into two, one covers a SAXParser as a sink, the other the SAXSource as a sink.
*/
@@ -545,7 +545,7 @@ class SafeSAXParser extends MethodAccess {
}
}
/* SAXReader: https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#SAXReader */
/* SAXReader: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#saxreader */
/**
* The class `org.dom4j.io.SAXReader`.
*/
@@ -621,7 +621,7 @@ class SafeSAXReader extends VarAccess {
}
}
/* https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#XMLReader */
/* https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#xmlreader */
/** The class `org.xml.sax.XMLReader`. */
class XMLReader extends RefType {
XMLReader() { this.hasQualifiedName("org.xml.sax", "XMLReader") }
@@ -756,7 +756,7 @@ class CreatedSafeXMLReader extends Call {
/*
* SAXSource in
* https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#Unmarshaller
* https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#jaxb-unmarshaller
*/
/** The class `javax.xml.transform.sax.SAXSource` */
@@ -811,7 +811,7 @@ class SafeSAXSource extends Expr {
}
}
/* Transformer: https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#TransformerFactory */
/* Transformer: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#transformerfactory */
/** An access to a method use for configuring a transformer or schema. */
abstract class TransformerConfig extends MethodAccess {
/** Holds if the configuration is disabled */
@@ -975,7 +975,7 @@ class SafeTransformer extends MethodAccess {
}
/*
* SAXTransformer: https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#SAXTransformerFactory
* SAXTransformer: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#saxtransformerfactory
* Has an extra method called newFilter.
*/
@@ -996,7 +996,7 @@ class SAXTransformerFactoryNewXMLFilter extends XmlParserCall {
}
}
/* Schema: https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#SchemaFactory */
/* Schema: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#schemafactory */
/** The class `javax.xml.validation.SchemaFactory`. */
class SchemaFactory extends RefType {
SchemaFactory() { this.hasQualifiedName("javax.xml.validation", "SchemaFactory") }
@@ -1060,7 +1060,7 @@ class SafeSchemaFactory extends VarAccess {
}
}
/* Unmarshaller: https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#Unmarshaller */
/* Unmarshaller: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#jaxb-unmarshaller */
/** The class `javax.xml.bind.Unmarshaller`. */
class XmlUnmarshaller extends RefType {
XmlUnmarshaller() { this.hasQualifiedName("javax.xml.bind", "Unmarshaller") }
@@ -1081,7 +1081,7 @@ class XmlUnmarshal extends XmlParserCall {
override predicate isSafe() { none() }
}
/* XPathExpression: https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#XPathExpression */
/* XPathExpression: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#xpathexpression */
/** The class `javax.xml.xpath.XPathExpression`. */
class XPathExpression extends RefType {
XPathExpression() { this.hasQualifiedName("javax.xml.xpath", "XPathExpression") }

View File

@@ -68,6 +68,6 @@
<references>
<li>MDN: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions">Regular Expressions</a></li>
<li>OWASP: <a href="https://www.owasp.org/index.php/Server_Side_Request_Forgery">SSRF</a></li>
<li>OWASP: <a href="https://www.owasp.org/index.php/Unvalidated_Redirects_and_Forwards_Cheat_Sheet">XSS Unvalidated Redirects and Forwards Cheat Sheet</a>.</li>
<li>OWASP: <a href="https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html">XSS Unvalidated Redirects and Forwards Cheat Sheet</a>.</li>
</references>
</qhelp>

View File

@@ -83,6 +83,6 @@
<references>
<li>OWASP: <a href="https://www.owasp.org/index.php/Server_Side_Request_Forgery">SSRF</a></li>
<li>OWASP: <a href="https://www.owasp.org/index.php/Unvalidated_Redirects_and_Forwards_Cheat_Sheet">XSS Unvalidated Redirects and Forwards Cheat Sheet</a>.</li>
<li>OWASP: <a href="https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html">XSS Unvalidated Redirects and Forwards Cheat Sheet</a>.</li>
</references>
</qhelp>

View File

@@ -71,6 +71,6 @@
<references>
<li>MDN: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions">Regular Expressions</a></li>
<li>OWASP: <a href="https://www.owasp.org/index.php/Server_Side_Request_Forgery">SSRF</a></li>
<li>OWASP: <a href="https://www.owasp.org/index.php/Unvalidated_Redirects_and_Forwards_Cheat_Sheet">XSS Unvalidated Redirects and Forwards Cheat Sheet</a>.</li>
<li>OWASP: <a href="https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html">XSS Unvalidated Redirects and Forwards Cheat Sheet</a>.</li>
</references>
</qhelp>

View File

@@ -37,7 +37,7 @@ Sanitizing the user-controlled data prevents the vulnerability:
<references>
<li>
OWASP:
<a href="https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet">XSS
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html">XSS
(Cross Site Scripting) Prevention Cheat Sheet</a>.
</li>
<li>

View File

@@ -48,7 +48,7 @@
<references>
<li>
OWASP:
<a href="https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet">XSS
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html">XSS
(Cross Site Scripting) Prevention Cheat Sheet</a>.
</li>
<li>

View File

@@ -33,12 +33,12 @@ leaving the website vulnerable to cross-site scripting.
<references>
<li>
OWASP:
<a href="https://www.owasp.org/index.php/DOM_based_XSS_Prevention_Cheat_Sheet">DOM based
<a href="https://cheatsheetseries.owasp.org/cheatsheets/DOM_based_XSS_Prevention_Cheat_Sheet.html">DOM based
XSS Prevention Cheat Sheet</a>.
</li>
<li>
OWASP:
<a href="https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.md">XSS
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html">XSS
(Cross Site Scripting) Prevention Cheat Sheet</a>.
</li>
<li>

View File

@@ -45,7 +45,7 @@
<li>NIST, FIPS 140 Annex a: <a href="http://csrc.nist.gov/publications/fips/fips140-2/fips1402annexa.pdf"> Approved Security Functions</a>.</li>
<li>NIST, SP 800-131A: <a href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar1.pdf"> Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths</a>.</li>
<li>OWASP: <a
href="https://www.owasp.org/index.php/Cryptographic_Storage_Cheat_Sheet#Rule_-_Use_strong_approved_cryptographic_algorithms">Rule
href="https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#rule---use-strong-approved-authenticated-encryption">Rule
- Use strong approved cryptographic algorithms</a>.
</li>
</references>

View File

@@ -67,7 +67,7 @@
<li>
OWASP:
<a href="https://www.owasp.org/index.php/Clickjacking_Defense_Cheat_Sheet">Clickjacking Defense Cheat Sheet</a>.
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html">Clickjacking Defense Cheat Sheet</a>.
</li>
<li>
Mozilla:

View File

@@ -41,7 +41,7 @@ OWASP vulnerability description:
</li>
<li>
OWASP guidance on deserializing objects:
<a href="https://www.owasp.org/index.php/Deserialization_Cheat_Sheet">Deserialization Cheat Sheet</a>.
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html">Deserialization Cheat Sheet</a>.
</li>
<li>
Neal Poole:

View File

@@ -31,7 +31,7 @@ website of their choosing, which facilitates phishing attacks:
</example>
<references>
<li>OWASP: <a href="https://www.owasp.org/index.php/Unvalidated_Redirects_and_Forwards_Cheat_Sheet">
<li>OWASP: <a href="https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html">
XSS Unvalidated Redirects and Forwards Cheat Sheet</a>.</li>
</references>

View File

@@ -35,7 +35,7 @@ before doing the redirection:
</example>
<references>
<li>OWASP: <a href="https://www.owasp.org/index.php/Unvalidated_Redirects_and_Forwards_Cheat_Sheet">
<li>OWASP: <a href="https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html">
XSS Unvalidated Redirects and Forwards Cheat Sheet</a>.</li>
</references>

View File

@@ -36,7 +36,7 @@ can be used:
<references>
<li>
OWASP:
<a href="https://www.owasp.org/index.php/Denial_of_Service_Cheat_Sheet">Denial of Service Cheat Sheet</a>.
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Denial_of_Service_Cheat_Sheet.html">Denial of Service Cheat Sheet</a>.
</li>
<li>
Wikipedia: <a href="https://en.wikipedia.org/wiki/Denial-of-service_attack">Denial-of-service attack</a>.

View File

@@ -50,6 +50,6 @@
</example>
<references>
<li>OWASP: <a href="https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet">Password storage</a>.</li>
<li>OWASP: <a href="https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html">Password storage</a>.</li>
</references>
</qhelp>

View File

@@ -45,7 +45,7 @@ predicate benignContext(Expr e) {
or
// weeds out calls inside HTML-attributes.
e.getParent() instanceof CodeInAttribute or
e.getParent().(ExprStmt).getParent() instanceof CodeInAttribute or
// and JSX-attributes.
e = any(JSXAttribute attr).getValue() or

View File

@@ -265,6 +265,14 @@ module DataFlow {
/**
* An expression or a declaration of a function, class, namespace or enum,
* viewed as a node in the data flow graph.
*
* Examples:
* ```js
* x + y
* Math.abs(x)
* class C {}
* function f(x, y) {}
* ```
*/
class ValueNode extends Node, TValueNode {
AST::ValueNode astNode;
@@ -478,6 +486,8 @@ module DataFlow {
*
* The default subclasses do not model global variable references or variable
* references inside `with` statements as property references.
*
* See `PropWrite` and `PropRead` for concrete syntax examples.
*/
abstract class PropRef extends Node {
/**
@@ -512,6 +522,22 @@ module DataFlow {
/**
* A data flow node that writes to an object property.
*
* For example, all of the following are property writes:
* ```js
* obj.f = value; // assignment to a property
* obj[e] = value; // assignment to a computed property
* { f: value } // property initializer
* { g() {} } // object literal method
* { get g() {}, set g(v) {} } // accessor methods (have no rhs value)
* class C {
* constructor(public x: number); // parameter field (TypeScript only)
* static m() {} // static method
* g() {} // instance method
* }
* Object.defineProperty(obj, 'f', { value: 5} ) // call to defineProperty
* <View width={value}/> // JSX attribute
* ```
*/
abstract class PropWrite extends PropRef {
/**
@@ -724,6 +750,17 @@ module DataFlow {
/**
* A data flow node that reads an object property.
*
* For example, all the following are property reads:
* ```js
* obj.f // property access
* obj[e] // computed property access
* let { f } = obj; // destructuring object pattern
* let [x, y] = array; // destructuring array pattern
* function f({ f }) {} // destructuring pattern (in parameter)
* for (let elm of array) {} // element access in for..of loop
* import { join } from 'path'; // named import specifier
* ```
*/
abstract class PropRead extends PropRef, SourceNode { }

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