2.19.0 upgrade

This commit is contained in:
Dilan Bhalla
2024-09-18 14:28:42 -07:00
parent 8fd89829cc
commit 14ce258807
3011 changed files with 130171 additions and 76847 deletions

View File

@@ -1,3 +1,27 @@
## 2.0.0
### Breaking Changes
* Deleted many deprecated taint-tracking configurations based on `TaintTracking::Configuration`.
* Deleted many deprecated dataflow configurations based on `DataFlow::Configuration`.
* Deleted the deprecated `hasQualifiedName` and `isDefined` predicates from the `Declaration` class, use `hasGlobalName` and `hasDefinition` respectively instead.
* Deleted the `getFullSignature` predicate from the `Function` class, use `getIdentityString(Declaration)` from `semmle.code.cpp.Print` instead.
* Deleted the deprecated `freeCall` predicate from `Alloc.qll`. Use `DeallocationExpr` instead.
* Deleted the deprecated `explorationLimit` predicate from `DataFlow::Configuration`, use `FlowExploration<explorationLimit>` instead.
* Deleted the deprecated `getFieldExpr` predicate from `ClassAggregateLiteral`, use `getAFieldExpr` instead.
* Deleted the deprecated `getElementExpr` predicate from `ArrayOrVectorAggregateLiteral`, use `getAnElementExpr` instead.
### New Features
* Added a class `C11GenericExpr` to represent C11 generic selection expressions. The generic selection is represented as a `Conversion` on the expression that will be selected.
* Added subclasses of `BuiltInOperations` for the `__is_scoped_enum`, `__is_trivially_equality_comparable`, and `__is_trivially_relocatable` builtin operations.
* Added a subclass of `Expr` for `__datasizeof` expressions.
### Minor Analysis Improvements
* Added a data flow model for `swap` member functions, which were previously modeled as taint tracking functions. This change improves the precision of queries where flow through `swap` member functions might affect the results.
* Added a data flow model for `realloc`-like functions, which were previously modeled as a taint tracking functions. This change improves the precision of queries where flow through `realloc`-like functions might affect the results.
## 1.4.2
No user-facing changes.

View File

@@ -0,0 +1,23 @@
## 2.0.0
### Breaking Changes
* Deleted many deprecated taint-tracking configurations based on `TaintTracking::Configuration`.
* Deleted many deprecated dataflow configurations based on `DataFlow::Configuration`.
* Deleted the deprecated `hasQualifiedName` and `isDefined` predicates from the `Declaration` class, use `hasGlobalName` and `hasDefinition` respectively instead.
* Deleted the `getFullSignature` predicate from the `Function` class, use `getIdentityString(Declaration)` from `semmle.code.cpp.Print` instead.
* Deleted the deprecated `freeCall` predicate from `Alloc.qll`. Use `DeallocationExpr` instead.
* Deleted the deprecated `explorationLimit` predicate from `DataFlow::Configuration`, use `FlowExploration<explorationLimit>` instead.
* Deleted the deprecated `getFieldExpr` predicate from `ClassAggregateLiteral`, use `getAFieldExpr` instead.
* Deleted the deprecated `getElementExpr` predicate from `ArrayOrVectorAggregateLiteral`, use `getAnElementExpr` instead.
### New Features
* Added a class `C11GenericExpr` to represent C11 generic selection expressions. The generic selection is represented as a `Conversion` on the expression that will be selected.
* Added subclasses of `BuiltInOperations` for the `__is_scoped_enum`, `__is_trivially_equality_comparable`, and `__is_trivially_relocatable` builtin operations.
* Added a subclass of `Expr` for `__datasizeof` expressions.
### Minor Analysis Improvements
* Added a data flow model for `swap` member functions, which were previously modeled as taint tracking functions. This change improves the precision of queries where flow through `swap` member functions might affect the results.
* Added a data flow model for `realloc`-like functions, which were previously modeled as a taint tracking functions. This change improves the precision of queries where flow through `realloc`-like functions might affect the results.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.4.2
lastReleaseVersion: 2.0.0

View File

@@ -36,16 +36,6 @@ module PrivateCleartextWrite {
}
}
deprecated class WriteConfig extends TaintTracking::Configuration {
WriteConfig() { this = "Write configuration" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
}
private module WriteConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-all
version: 1.4.2
version: 2.0.0
groups: cpp
dbscheme: semmlecode.cpp.dbscheme
extractor: cpp

View File

@@ -60,18 +60,6 @@ class Declaration extends Locatable, @declaration {
*/
string getQualifiedName() { result = underlyingElement(this).(Q::Declaration).getQualifiedName() }
/**
* DEPRECATED: Prefer `hasGlobalName` or the 2-argument or 3-argument
* `hasQualifiedName` predicates. To get the exact same results as this
* predicate in all edge cases, use `getQualifiedName()`.
*
* Holds if this declaration has the fully-qualified name `qualifiedName`.
* See `getQualifiedName`.
*/
deprecated predicate hasQualifiedName(string qualifiedName) {
this.getQualifiedName() = qualifiedName
}
/**
* Holds if this declaration has a fully-qualified name with a name-space
* component of `namespaceQualifier`, a declaring type of `typeQualifier`,
@@ -185,9 +173,6 @@ class Declaration extends Locatable, @declaration {
/** Holds if the declaration has a definition. */
predicate hasDefinition() { exists(this.getDefinition()) }
/** DEPRECATED: Use `hasDefinition` instead. */
deprecated predicate isDefined() { this.hasDefinition() }
/** Gets the preferred location of this declaration, if any. */
override Location getLocation() { none() }

View File

@@ -30,46 +30,6 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
override string getName() { functions(underlyingElement(this), result, _) }
/**
* DEPRECATED: Use `getIdentityString(Declaration)` from `semmle.code.cpp.Print` instead.
* Gets the full signature of this function, including return type, parameter
* types, and template arguments.
*
* For example, in the following code:
* ```
* template<typename T> T min(T x, T y);
* int z = min(5, 7);
* ```
* The full signature of the function called on the last line would be
* `min<int>(int, int) -> int`, and the full signature of the uninstantiated
* template on the first line would be `min<T>(T, T) -> T`.
*/
deprecated string getFullSignature() {
exists(string name, string templateArgs, string args |
result = name + templateArgs + args + " -> " + this.getType().toString() and
name = this.getQualifiedName() and
(
if exists(this.getATemplateArgument())
then
templateArgs =
"<" +
concat(int i |
exists(this.getTemplateArgument(i))
|
this.getTemplateArgument(i).toString(), ", " order by i
) + ">"
else templateArgs = ""
) and
args =
"(" +
concat(int i |
exists(this.getParameter(i))
|
this.getParameter(i).getType().toString(), ", " order by i
) + ")"
)
}
/** Gets a specifier of this function. */
override Specifier getASpecifier() {
funspecifiers(underlyingElement(this), unresolveElement(result)) or

View File

@@ -286,9 +286,6 @@ abstract class BaseAstNode extends PrintAstNode {
* Gets the AST represented by this node.
*/
final Locatable getAst() { result = ast }
/** DEPRECATED: Alias for getAst */
deprecated Locatable getAST() { result = this.getAst() }
}
/**
@@ -385,6 +382,21 @@ class CastNode extends ConversionNode {
}
}
/**
* A node representing a `C11GenericExpr`.
*/
class C11GenericNode extends ConversionNode {
C11GenericExpr generic;
C11GenericNode() { generic = conv }
override AstNode getChildInternal(int childIndex) {
result = super.getChildInternal(childIndex - count(generic.getAChild()))
or
result.getAst() = generic.getChild(childIndex)
}
}
/**
* A node representing a `StmtExpr`.
*/
@@ -860,6 +872,15 @@ private predicate namedExprChildPredicates(Expr expr, Element ele, string pred)
or
expr.(BuiltInVarArgsStart).getLastNamedParameter() = ele and pred = "getLastNamedParameter()"
or
expr.(C11GenericExpr).getControllingExpr() = ele and pred = "getControllingExpr()"
or
exists(int n |
expr.(C11GenericExpr).getAssociationType(n) = ele.(TypeName).getType() and
pred = "getAssociationType(" + n + ")"
or
expr.(C11GenericExpr).getAssociationExpr(n) = ele and pred = "getAssociationExpr(" + n + ")"
)
or
expr.(Call).getQualifier() = ele and pred = "getQualifier()"
or
exists(int n | expr.(Call).getArgument(n) = ele and pred = "getArgument(" + n.toString() + ")")

View File

@@ -409,11 +409,18 @@ class LocalVariable extends LocalScopeVariable, @localvariable {
exists(ConditionDeclExpr e | e.getVariable() = this and e.getEnclosingFunction() = result)
or
orphaned_variables(underlyingElement(this), unresolveElement(result))
or
coroutine_placeholder_variable(underlyingElement(this), _, unresolveElement(result))
}
override predicate isStatic() {
super.isStatic() or orphaned_variables(underlyingElement(this), _)
}
override predicate isCompilerGenerated() {
super.isCompilerGenerated() or
coroutine_placeholder_variable(underlyingElement(this), _, _)
}
}
/**

View File

@@ -7,15 +7,6 @@ import semmle.code.cpp.models.interfaces.Deallocation
*/
predicate freeFunction(Function f, int argNum) { argNum = f.(DeallocationFunction).getFreedArg() }
/**
* A call to a library routine that frees memory.
*
* DEPRECATED: Use `DeallocationExpr` instead (this also includes `delete` expressions).
*/
deprecated predicate freeCall(FunctionCall fc, Expr arg) {
arg = fc.(DeallocationExpr).getFreedExpr()
}
/**
* Is e some kind of allocation or deallocation (`new`, `alloc`, `realloc`, `delete`, `free` etc)?
*/

View File

@@ -168,14 +168,6 @@ abstract deprecated class Configuration extends string {
*/
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/**
* DEPRECATED: Use `FlowExploration<explorationLimit>` instead.
*
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
* measured in approximate number of interprocedural steps.
*/
deprecated int explorationLimit() { none() }
/**
* Holds if hidden nodes should be included in the data flow graph.
*

View File

@@ -168,14 +168,6 @@ abstract deprecated class Configuration extends string {
*/
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/**
* DEPRECATED: Use `FlowExploration<explorationLimit>` instead.
*
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
* measured in approximate number of interprocedural steps.
*/
deprecated int explorationLimit() { none() }
/**
* Holds if hidden nodes should be included in the data flow graph.
*

View File

@@ -168,14 +168,6 @@ abstract deprecated class Configuration extends string {
*/
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/**
* DEPRECATED: Use `FlowExploration<explorationLimit>` instead.
*
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
* measured in approximate number of interprocedural steps.
*/
deprecated int explorationLimit() { none() }
/**
* Holds if hidden nodes should be included in the data flow graph.
*

View File

@@ -168,14 +168,6 @@ abstract deprecated class Configuration extends string {
*/
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/**
* DEPRECATED: Use `FlowExploration<explorationLimit>` instead.
*
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
* measured in approximate number of interprocedural steps.
*/
deprecated int explorationLimit() { none() }
/**
* Holds if hidden nodes should be included in the data flow graph.
*

View File

@@ -168,14 +168,6 @@ abstract deprecated class Configuration extends string {
*/
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/**
* DEPRECATED: Use `FlowExploration<explorationLimit>` instead.
*
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
* measured in approximate number of interprocedural steps.
*/
deprecated int explorationLimit() { none() }
/**
* Holds if hidden nodes should be included in the data flow graph.
*

View File

@@ -1885,3 +1885,59 @@ class BuiltInOperationIsWinInterface extends BuiltInOperation, @iswininterface {
override string getAPrimaryQlClass() { result = "BuiltInOperationIsWinInterface" }
}
/**
* A C++ `__is_trivially_equality_comparable` built-in operation.
*
* Returns `true` if comparing two objects of type `_Tp` is equivalent to
* comparing their object representations.
*
* ```
* template<typename _Tp>
* struct is_trivially_equality_comparable
* : public integral_constant<bool, __is_trivially_equality_comparable(_Tp)>
* {};
* ```
*/
class BuiltInOperationIsTriviallyEqualityComparable extends BuiltInOperation,
@istriviallyequalitycomparable
{
override string toString() { result = "__is_trivially_equality_comparable" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsTriviallyEqualityComparable" }
}
/**
* A C++ `__is_scoped_enum` built-in operation (used by some implementations
* of the `<type_traits>` header).
*
* Returns `true` if a type is a scoped enum.
* ```
* template<typename _Tp>
* constexpr bool is_scoped_enum = __is_scoped_enum(_Tp);
* ```
*/
class BuiltInOperationIsScopedEnum extends BuiltInOperation, @isscopedenum {
override string toString() { result = "__is_scoped_enum" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsScopedEnum" }
}
/**
* A C++ `__is_trivially_relocatable` built-in operation.
*
* Returns `true` if moving an object of type `_Tp` is equivalent to
* copying the underlying bytes.
*
* ```
* template<typename _Tp>
* struct is_trivially_relocatable
* : public integral_constant<bool, __is_trivially_relocatable(_Tp)>
* {};
* ```
*/
class BuiltInOperationIsTriviallyRelocatable extends BuiltInOperation, @istriviallyrelocatable {
override string toString() { result = "__is_trivially_relocatable" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsTriviallyRelocatable" }
}

View File

@@ -791,6 +791,53 @@ class AlignofTypeOperator extends AlignofOperator {
override string toString() { result = "alignof(" + this.getTypeOperand().getName() + ")" }
}
/**
* A C++ `__datasizeof` expression (used by some implementations
* of the `<type_traits>` header).
*
* The `__datasizeof` expression behaves identically to `sizeof` except
* that the result ignores tail padding.
*/
class DatasizeofOperator extends Expr, @datasizeof {
override int getPrecedence() { result = 16 }
}
/**
* A C++ `__datasizeof` expression whose operand is an expression.
*/
class DatasizeofExprOperator extends DatasizeofOperator {
DatasizeofExprOperator() { exists(this.getChild(0)) }
override string getAPrimaryQlClass() { result = "DatasizeofExprOperator" }
/** Gets the contained expression. */
Expr getExprOperand() { result = this.getChild(0) }
override string toString() { result = "__datasizeof(<expr>)" }
override predicate mayBeImpure() { this.getExprOperand().mayBeImpure() }
override predicate mayBeGloballyImpure() { this.getExprOperand().mayBeGloballyImpure() }
}
/**
* A C++ `__datasizeof` expression whose operand is a type name.
*/
class DatasizeofTypeOperator extends DatasizeofOperator {
DatasizeofTypeOperator() { sizeof_bind(underlyingElement(this), _) }
override string getAPrimaryQlClass() { result = "DatasizeofTypeOperator" }
/** Gets the contained type. */
Type getTypeOperand() { sizeof_bind(underlyingElement(this), unresolveElement(result)) }
override string toString() { result = "__datasizeof(" + this.getTypeOperand().getName() + ")" }
override predicate mayBeImpure() { none() }
override predicate mayBeGloballyImpure() { none() }
}
/**
* A C/C++ array to pointer conversion.
*

View File

@@ -304,6 +304,8 @@ class Expr extends StmtParent, @expr {
e instanceof NoExceptExpr
or
e instanceof AlignofOperator
or
e instanceof DatasizeofOperator
)
or
exists(Decltype d | d.getExpr() = this.getParentWithConversions*())
@@ -630,6 +632,106 @@ class ParenthesisExpr extends Conversion, @parexpr {
override string getAPrimaryQlClass() { result = "ParenthesisExpr" }
}
/**
* A node representing a C11 `_Generic` selection expression.
*
* For example:
* ```
* _Generic(e, int: "int", default: "unknown")
* ```
*/
class C11GenericExpr extends Conversion, @c11_generic {
int associationCount;
C11GenericExpr() { associationCount = (count(this.getAChild()) - 1) / 2 }
override string toString() { result = "_Generic" }
override string getAPrimaryQlClass() { result = "C11GenericExpr" }
/**
* Gets the controlling expression of the generic selection.
*
* For example, for
* ```
* _Generic(e, int: "a", default: "b")
* ```
* the result is `e`.
*/
Expr getControllingExpr() { result = this.getChild(0) }
/**
* Gets the type of the `n`th element in the association list of the generic selection.
*
* For example, for
* ```
* _Generic(e, int: "a", default: "b")
* ```
* the type of the 0th element is `int`. In the case of the default element the
* type will an instance of `VoidType`.
*/
Type getAssociationType(int n) {
n in [0 .. associationCount - 1] and
result = this.getChild(n * 2 + 1).(TypeName).getType()
}
/**
* Gets the type of an element in the association list of the generic selection.
*/
Type getAnAssociationType() { result = this.getAssociationType(_) }
/**
* Gets the expression of the `n`th element in the association list of
* the generic selection.
*
* For example, for
* ```
* _Generic(e, int: "a", default: "b")
* ```
* the expression for 0th element is `"a"`, and the expression for the
* 1st element is `"b"`. For the selected expression, this predicate
* will yield a `ReuseExpr`, such that
* ```
* this.getAssociationExpr(n).(ReuseExpr).getReusedExpr() = this.getExpr()
* ```
*/
Expr getAssociationExpr(int n) {
n in [0 .. associationCount - 1] and
result = this.getChild(n * 2 + 2)
}
/**
* Gets the expression of an element in the association list of the generic selection.
*/
Expr getAnAssociationExpr() { result = this.getAssociationExpr(_) }
/**
* Holds if the `n`th element of the association list of the generic selection is the
* default element.
*
* For example, for
* ```
* _Generic(e, int: "a", default: "b")
* ```
* this holds for 1.
*/
predicate isDefaultAssociation(int n) { this.getAssociationType(n) instanceof VoidType }
/**
* Holds if the `n`th element of the association list of the generic selection is the
* one whose expression was selected.
*
* For example, with `e` of type `int` and
* ```
* _Generic(e, int: "a", default: "b")
* ```
* this holds for 0.
*/
predicate isSelectedAssociation(int n) {
this.getAssociationExpr(n).(ReuseExpr).getReusedExpr() = this.getExpr()
}
}
/**
* A C/C++ expression that could not be resolved, or that can no longer be
* represented due to a database upgrade or downgrade.
@@ -666,6 +768,8 @@ class AssumeExpr extends Expr, @assume {
/**
* A C/C++ comma expression.
*
* For example:
* ```
* int c = compute1(), compute2(), resulting_value;
* ```

View File

@@ -195,17 +195,6 @@ class ClassAggregateLiteral extends AggregateLiteral {
*/
Expr getAFieldExpr(Field field) { result = this.getFieldExpr(field, _) }
/**
* DEPRECATED: Use `getAFieldExpr` instead.
*
* Gets the expression within the aggregate literal that is used to initialize
* field `field`, if present.
*
* This predicate may have multiple results since a field can be initialized
* multiple times in the same initializer.
*/
deprecated Expr getFieldExpr(Field field) { result = this.getFieldExpr(field, _) }
/**
* Gets the expression within the aggregate literal that is used to initialize
* field `field`, if present. The expression is the `position`'th entry in the
@@ -300,17 +289,6 @@ class ArrayOrVectorAggregateLiteral extends AggregateLiteral {
*/
Expr getAnElementExpr(int elementIndex) { result = this.getElementExpr(elementIndex, _) }
/**
* DEPRECATED: Use `getAnElementExpr` instead.
*
* Gets the expression within the aggregate literal that is used to initialize
* element `elementIndex`, if present.
*
* This predicate may have multiple results since an element can be initialized
* multiple times in the same initializer.
*/
deprecated Expr getElementExpr(int elementIndex) { result = this.getElementExpr(elementIndex, _) }
/**
* Gets the expression within the aggregate literal that is used to initialize
* element `elementIndex`, if present. The expression is the `position`'th entry

View File

@@ -168,14 +168,6 @@ abstract deprecated class Configuration extends string {
*/
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/**
* DEPRECATED: Use `FlowExploration<explorationLimit>` instead.
*
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
* measured in approximate number of interprocedural steps.
*/
deprecated int explorationLimit() { none() }
/**
* Holds if hidden nodes should be included in the data flow graph.
*

View File

@@ -168,14 +168,6 @@ abstract deprecated class Configuration extends string {
*/
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/**
* DEPRECATED: Use `FlowExploration<explorationLimit>` instead.
*
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
* measured in approximate number of interprocedural steps.
*/
deprecated int explorationLimit() { none() }
/**
* Holds if hidden nodes should be included in the data flow graph.
*

View File

@@ -168,14 +168,6 @@ abstract deprecated class Configuration extends string {
*/
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/**
* DEPRECATED: Use `FlowExploration<explorationLimit>` instead.
*
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
* measured in approximate number of interprocedural steps.
*/
deprecated int explorationLimit() { none() }
/**
* Holds if hidden nodes should be included in the data flow graph.
*

View File

@@ -168,14 +168,6 @@ abstract deprecated class Configuration extends string {
*/
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/**
* DEPRECATED: Use `FlowExploration<explorationLimit>` instead.
*
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
* measured in approximate number of interprocedural steps.
*/
deprecated int explorationLimit() { none() }
/**
* Holds if hidden nodes should be included in the data flow graph.
*

View File

@@ -50,9 +50,6 @@ abstract private class AbstractIRVariable extends TIRVariable {
*/
abstract Language::AST getAst();
/** DEPRECATED: Alias for getAst */
deprecated Language::AST getAST() { result = this.getAst() }
/**
* Gets an identifier string for the variable. This identifier is unique
* within the function.
@@ -96,9 +93,6 @@ class IRUserVariable extends AbstractIRVariable, TIRUserVariable {
final override Language::AST getAst() { result = var }
/** DEPRECATED: Alias for getAst */
deprecated override Language::AST getAST() { result = this.getAst() }
final override string getUniqueId() {
result = this.getVariable().toString() + " " + this.getVariable().getLocation().toString()
}
@@ -163,9 +157,6 @@ abstract private class AbstractIRGeneratedVariable extends AbstractIRVariable {
final override Language::AST getAst() { result = ast }
/** DEPRECATED: Alias for getAst */
deprecated override Language::AST getAST() { result = this.getAst() }
override string toString() { result = this.getBaseString() + this.getLocationString() }
override string getUniqueId() { none() }

View File

@@ -285,9 +285,6 @@ abstract private class MemoryLocation0 extends TMemoryLocation {
predicate isAlwaysAllocatedOnStack() { none() }
final predicate canReuseSsa() { none() }
/** DEPRECATED: Alias for canReuseSsa */
deprecated predicate canReuseSSA() { this.canReuseSsa() }
}
/**

View File

@@ -50,9 +50,6 @@ abstract private class AbstractIRVariable extends TIRVariable {
*/
abstract Language::AST getAst();
/** DEPRECATED: Alias for getAst */
deprecated Language::AST getAST() { result = this.getAst() }
/**
* Gets an identifier string for the variable. This identifier is unique
* within the function.
@@ -96,9 +93,6 @@ class IRUserVariable extends AbstractIRVariable, TIRUserVariable {
final override Language::AST getAst() { result = var }
/** DEPRECATED: Alias for getAst */
deprecated override Language::AST getAST() { result = this.getAst() }
final override string getUniqueId() {
result = this.getVariable().toString() + " " + this.getVariable().getLocation().toString()
}
@@ -163,9 +157,6 @@ abstract private class AbstractIRGeneratedVariable extends AbstractIRVariable {
final override Language::AST getAst() { result = ast }
/** DEPRECATED: Alias for getAst */
deprecated override Language::AST getAST() { result = this.getAst() }
override string toString() { result = this.getBaseString() + this.getLocationString() }
override string getUniqueId() { none() }

View File

@@ -216,9 +216,6 @@ abstract class TranslatedSideEffects extends TranslatedElement {
final override Locatable getAst() { result = this.getExpr() }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
final override Declaration getFunction() { result = getEnclosingDeclaration(this.getExpr()) }
final override TranslatedElement getChild(int i) {
@@ -616,9 +613,6 @@ class TranslatedArgumentExprSideEffect extends TranslatedArgumentSideEffect,
final override Locatable getAst() { result = arg }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
final override Type getIndirectionType() {
result = arg.getUnspecifiedType().(DerivedType).getBaseType()
or
@@ -651,9 +645,6 @@ class TranslatedStructorQualifierSideEffect extends TranslatedArgumentSideEffect
final override Locatable getAst() { result = call }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
final override Type getIndirectionType() { result = call.getTarget().getDeclaringType() }
final override string getArgString() { result = "this" }
@@ -675,9 +666,6 @@ class TranslatedCallSideEffect extends TranslatedSideEffect, TTranslatedCallSide
override Locatable getAst() { result = expr }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
override Expr getPrimaryExpr() { result = expr }
override predicate sortOrder(int group, int indexInGroup) {
@@ -716,9 +704,6 @@ class TranslatedAllocationSideEffect extends TranslatedSideEffect, TTranslatedAl
override Locatable getAst() { result = expr }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
override Expr getPrimaryExpr() { result = expr }
override predicate sortOrder(int group, int indexInGroup) {

View File

@@ -29,9 +29,6 @@ abstract class TranslatedCondition extends TranslatedElement {
final override Locatable getAst() { result = expr }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
final ConditionContext getConditionContext() { result = this.getParent() }
final Expr getExpr() { result = expr }

View File

@@ -45,9 +45,6 @@ abstract class TranslatedDeclarationEntry extends TranslatedElement, TTranslated
final override string toString() { result = entry.toString() }
final override Locatable getAst() { result = entry.getAst() }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
}
/**
@@ -248,9 +245,6 @@ class TranslatedStaticLocalVariableInitialization extends TranslatedElement,
final override Locatable getAst() { result = entry.getAst() }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
final override LocalVariable getVariable() { result = var }
final override Declaration getFunction() { result = var.getFunction() }
@@ -277,9 +271,6 @@ class TranslatedConditionDecl extends TranslatedLocalVariableDeclaration, TTrans
override Locatable getAst() { result = conditionDeclExpr }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
override Declaration getFunction() { result = getEnclosingFunction(conditionDeclExpr) }
override LocalVariable getVariable() { result = conditionDeclExpr.getVariable() }

View File

@@ -128,6 +128,9 @@ private predicate ignoreExprAndDescendants(Expr expr) {
vaStartExpr.getLastNamedParameter().getFullyConverted() = expr
)
or
// The children of C11 _Generic expressions are just surface syntax.
exists(C11GenericExpr generic | generic.getAChild() = expr)
or
// Do not translate implicit destructor calls for unnamed temporary variables that are
// conditionally constructed (until we have a mechanism for calling these only when the
// temporary's constructor was run)
@@ -432,6 +435,9 @@ predicate ignoreLoad(Expr expr) {
// The load is duplicated from the right operand.
isExtractorFrontendVersion65OrHigher() and expr instanceof CommaExpr
or
// The load is duplicated from the chosen expression.
expr instanceof C11GenericExpr
or
expr.(PointerDereferenceExpr).getOperand().getFullyConverted().getType().getUnspecifiedType()
instanceof FunctionPointerType
or
@@ -761,7 +767,10 @@ newtype TTranslatedElement =
} or
// A statement
TTranslatedStmt(Stmt stmt) { translateStmt(stmt) } or
// The `__except` block of a `__try __except` statement
TTranslatedMicrosoftTryExceptHandler(MicrosoftTryExceptStmt stmt) or
// The `__finally` block of a `__try __finally` statement
TTranslatedMicrosoftTryFinallyHandler(MicrosoftTryFinallyStmt stmt) or
// A function
TTranslatedFunction(Function func) { translateFunction(func) } or
// A constructor init list
@@ -920,9 +929,6 @@ abstract class TranslatedElement extends TTranslatedElement {
*/
abstract Locatable getAst();
/** DEPRECATED: Alias for getAst */
deprecated Locatable getAST() { result = this.getAst() }
/** Gets the location of this element. */
Location getLocation() { result = this.getAst().getLocation() }

View File

@@ -893,7 +893,8 @@ class TranslatedTransparentConversion extends TranslatedTransparentExpr {
(
expr instanceof ParenthesisExpr or
expr instanceof ReferenceDereferenceExpr or
expr instanceof ReferenceToExpr
expr instanceof ReferenceToExpr or
expr instanceof C11GenericExpr
)
}

View File

@@ -67,9 +67,6 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
final override Locatable getAst() { result = func }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
/**
* Gets the function being translated.
*/
@@ -212,8 +209,13 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
(
// Only generate the `Unwind` instruction if there is any exception
// handling present in the function.
exists(TryStmt try | try.getEnclosingFunction() = func) or
exists(TryOrMicrosoftTryStmt try | try.getEnclosingFunction() = func)
or
exists(ThrowExpr throw | throw.getEnclosingFunction() = func)
or
exists(FunctionCall call | call.getEnclosingFunction() = func |
getTranslatedExpr(call).(TranslatedCallExpr).mayThrowException()
)
)
or
tag = AliasedUseTag() and
@@ -483,9 +485,6 @@ class TranslatedThisParameter extends TranslatedParameter, TTranslatedThisParame
final override Locatable getAst() { result = func }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
final override Function getFunction() { result = func }
final override predicate hasIndirection() { any() }
@@ -518,9 +517,6 @@ class TranslatedPositionalParameter extends TranslatedParameter, TTranslatedPara
final override Locatable getAst() { result = param }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
final override Function getFunction() {
result = param.getFunction() or
result = param.getCatchBlock().getEnclosingFunction()
@@ -558,9 +554,6 @@ class TranslatedEllipsisParameter extends TranslatedParameter, TTranslatedEllips
final override Locatable getAst() { result = func }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
final override Function getFunction() { result = func }
final override predicate hasIndirection() { any() }
@@ -597,9 +590,6 @@ class TranslatedConstructorInitList extends TranslatedElement, InitializationCon
override Locatable getAst() { result = func }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
override TranslatedElement getChild(int id) {
exists(ConstructorFieldInit fieldInit |
fieldInit = func.(Constructor).getInitializer(id) and
@@ -677,9 +667,6 @@ class TranslatedDestructorDestructionList extends TranslatedElement,
override Locatable getAst() { result = func }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
override TranslatedElement getChild(int id) {
exists(DestructorFieldDestruction fieldDestruction |
fieldDestruction = func.(Destructor).getDestruction(id) and
@@ -733,9 +720,6 @@ class TranslatedReadEffects extends TranslatedElement, TTranslatedReadEffects {
override Locatable getAst() { result = func }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
override Function getFunction() { result = func }
override string toString() { result = "read effects: " + func.toString() }
@@ -839,9 +823,6 @@ class TranslatedThisReadEffect extends TranslatedReadEffect, TTranslatedThisRead
override Locatable getAst() { result = func }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
override Function getFunction() { result = func }
override string toString() { result = "read effect: this" }
@@ -865,9 +846,6 @@ class TranslatedParameterReadEffect extends TranslatedReadEffect, TTranslatedPar
override Locatable getAst() { result = param }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
override string toString() { result = "read effect: " + param.toString() }
override Function getFunction() { result = param.getFunction() }

View File

@@ -153,9 +153,6 @@ abstract class TranslatedInitialization extends TranslatedElement, TTranslatedIn
final override Locatable getAst() { result = expr }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
/**
* Gets the expression that is doing the initialization.
*/
@@ -528,9 +525,6 @@ abstract class TranslatedFieldInitialization extends TranslatedElement {
final override Locatable getAst() { result = ast }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
final override Declaration getFunction() {
result = getEnclosingFunction(ast) or
result = getEnclosingVariable(ast).(GlobalOrNamespaceVariable) or
@@ -701,9 +695,6 @@ abstract class TranslatedElementInitialization extends TranslatedElement {
final override Locatable getAst() { result = initList }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
final override Declaration getFunction() {
result = getEnclosingFunction(initList)
or
@@ -912,9 +903,6 @@ abstract class TranslatedStructorCallFromStructor extends TranslatedElement, Str
final override Locatable getAst() { result = call }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
final override TranslatedElement getChild(int id) {
id = 0 and
result = this.getStructorCall()
@@ -1058,9 +1046,6 @@ class TranslatedConstructorBareInit extends TranslatedElement, TTranslatedConstr
override Locatable getAst() { result = init }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
final override string toString() { result = "construct base (no constructor)" }
override Instruction getFirstInstruction(EdgeKind kind) {

View File

@@ -79,11 +79,6 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
tag = TryExceptCompareOneBranch() and
opcode instanceof Opcode::ConditionalBranch and
resultType = getVoidType()
or
// unwind stack
tag = UnwindTag() and
opcode instanceof Opcode::Unwind and
resultType = getVoidType()
}
final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
@@ -156,7 +151,7 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
// TODO: This is not really correct. The semantics of `EXCEPTION_CONTINUE_EXECUTION` is that
// we should continue execution at the point where the exception occurred. But we don't have
// any instruction to model this behavior.
result = this.getInstruction(UnwindTag())
result = this.getExceptionSuccessorInstruction(any(GotoEdge edge))
or
kind instanceof FalseEdge and
result = this.getInstruction(TryExceptGenerateZero())
@@ -176,7 +171,7 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
tag = TryExceptCompareZeroBranch() and
(
kind instanceof TrueEdge and
result = this.getInstruction(UnwindTag())
result = this.getExceptionSuccessorInstruction(any(GotoEdge edge))
or
kind instanceof FalseEdge and
result = this.getInstruction(TryExceptGenerateOne())
@@ -196,10 +191,6 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
tag = TryExceptCompareOneBranch() and
kind instanceof TrueEdge and
result = this.getTranslatedHandler().getFirstInstruction(any(GotoEdge edge))
or
// Unwind -> Parent
tag = UnwindTag() and
result = this.getParent().getChildSuccessor(this, kind)
}
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
@@ -215,8 +206,6 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
override Instruction getALastInstructionInternal() {
result = this.getTranslatedHandler().getALastInstruction()
or
result = this.getInstruction(UnwindTag())
}
private TranslatedExpr getTranslatedCondition() {
@@ -236,6 +225,68 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
}
final override Function getFunction() { result = tryExcept.getEnclosingFunction() }
override Instruction getExceptionSuccessorInstruction(EdgeKind kind) {
// A throw from within a `__except` block flows to the handler for the parent of
// the `__try`.
result = this.getParent().getParent().getExceptionSuccessorInstruction(kind)
}
}
TranslatedMicrosoftTryFinallyHandler getTranslatedMicrosoftTryFinallyHandler(
MicrosoftTryFinallyStmt tryFinally
) {
result.getAst() = tryFinally.getFinally()
}
class TranslatedMicrosoftTryFinallyHandler extends TranslatedElement,
TTranslatedMicrosoftTryFinallyHandler
{
MicrosoftTryFinallyStmt tryFinally;
TranslatedMicrosoftTryFinallyHandler() {
this = TTranslatedMicrosoftTryFinallyHandler(tryFinally)
}
final override string toString() { result = tryFinally.toString() }
final override Locatable getAst() { result = tryFinally.getFinally() }
override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getTranslatedFinally().getFirstInstruction(kind)
}
override Instruction getALastInstructionInternal() {
result = this.getTranslatedFinally().getALastInstruction()
}
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
child = this.getTranslatedFinally() and
result = this.getParent().getChildSuccessor(this, kind)
}
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
override TranslatedElement getChild(int id) {
id = 0 and
result = this.getTranslatedFinally()
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
none()
}
final override Function getFunction() { result = tryFinally.getEnclosingFunction() }
private TranslatedStmt getTranslatedFinally() {
result = getTranslatedStmt(tryFinally.getFinally())
}
override Instruction getExceptionSuccessorInstruction(EdgeKind kind) {
// A throw from within a `__finally` block flows to the handler for the parent of
// the `__try`.
result = this.getParent().getParent().getExceptionSuccessorInstruction(kind)
}
}
abstract class TranslatedStmt extends TranslatedElement, TTranslatedStmt {
@@ -268,9 +319,6 @@ abstract class TranslatedStmt extends TranslatedElement, TTranslatedStmt {
final override Locatable getAst() { result = stmt }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
final override Function getFunction() { result = stmt.getEnclosingFunction() }
}
@@ -586,7 +634,7 @@ class TranslatedNoValueReturnStmt extends TranslatedReturnStmt, TranslatedVariab
/**
* A C/C++ `try` statement, or a `__try __except` or `__try __finally` statement.
*/
private class TryOrMicrosoftTryStmt extends Stmt {
class TryOrMicrosoftTryStmt extends Stmt {
TryOrMicrosoftTryStmt() {
this instanceof TryStmt or
this instanceof MicrosoftTryStmt
@@ -619,7 +667,9 @@ private class TryOrMicrosoftTryStmt extends Stmt {
}
/** Gets the `finally` statement (usually a BlockStmt), if any. */
Stmt getFinally() { result = this.(MicrosoftTryFinallyStmt).getFinally() }
TranslatedElement getTranslatedFinally() {
result = getTranslatedMicrosoftTryFinallyHandler(this)
}
}
/**
@@ -689,11 +739,14 @@ class TranslatedTryStmt extends TranslatedStmt {
final override Instruction getExceptionSuccessorInstruction(EdgeKind kind) {
result = this.getHandler(0).getFirstInstruction(kind)
or
not exists(this.getHandler(_)) and
result = this.getFinally().getFirstInstruction(kind)
}
private TranslatedElement getHandler(int index) { result = stmt.getTranslatedHandler(index) }
private TranslatedStmt getFinally() { result = getTranslatedStmt(stmt.getFinally()) }
private TranslatedElement getFinally() { result = stmt.getTranslatedFinally() }
private TranslatedStmt getBody() { result = getTranslatedStmt(stmt.getStmt()) }
}

View File

@@ -50,9 +50,6 @@ abstract private class AbstractIRVariable extends TIRVariable {
*/
abstract Language::AST getAst();
/** DEPRECATED: Alias for getAst */
deprecated Language::AST getAST() { result = this.getAst() }
/**
* Gets an identifier string for the variable. This identifier is unique
* within the function.
@@ -96,9 +93,6 @@ class IRUserVariable extends AbstractIRVariable, TIRUserVariable {
final override Language::AST getAst() { result = var }
/** DEPRECATED: Alias for getAst */
deprecated override Language::AST getAST() { result = this.getAst() }
final override string getUniqueId() {
result = this.getVariable().toString() + " " + this.getVariable().getLocation().toString()
}
@@ -163,9 +157,6 @@ abstract private class AbstractIRGeneratedVariable extends AbstractIRVariable {
final override Language::AST getAst() { result = ast }
/** DEPRECATED: Alias for getAst */
deprecated override Language::AST getAST() { result = this.getAst() }
override string toString() { result = this.getBaseString() + this.getLocationString() }
override string getUniqueId() { none() }

View File

@@ -71,9 +71,6 @@ class MemoryLocation extends TMemoryLocation {
final string getUniqueId() { result = var.getUniqueId() }
final predicate canReuseSsa() { canReuseSsaForVariable(var) }
/** DEPRECATED: Alias for canReuseSsa */
deprecated predicate canReuseSSA() { this.canReuseSsa() }
}
predicate canReuseSsaForOldResult(Instruction instr) { none() }

View File

@@ -42,6 +42,7 @@ private import implementations.Accept
private import implementations.Poll
private import implementations.Select
private import implementations.MySql
private import implementations.NoexceptFunction
private import implementations.ODBC
private import implementations.SqLite3
private import implementations.PostgreSql

View File

@@ -5,13 +5,13 @@
*/
import semmle.code.cpp.models.interfaces.Allocation
import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.DataFlow
/**
* An allocation function (such as `realloc`) that has an argument for the size
* in bytes, and an argument for an existing pointer that is to be reallocated.
*/
private class ReallocAllocationFunction extends AllocationFunction, TaintFunction {
private class ReallocAllocationFunction extends AllocationFunction, DataFlowFunction {
int sizeArg;
int reallocArg;
@@ -44,7 +44,7 @@ private class ReallocAllocationFunction extends AllocationFunction, TaintFunctio
override int getReallocPtrArg() { result = reallocArg }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
input.isParameterDeref(this.getReallocPtrArg()) and output.isReturnValueDeref()
}
}

View File

@@ -9,13 +9,14 @@ import semmle.code.cpp.models.interfaces.DataFlow
import semmle.code.cpp.models.interfaces.Alias
import semmle.code.cpp.models.interfaces.SideEffect
import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.NonThrowing
/**
* The standard functions `memcpy`, `memmove` and `bcopy`; and the gcc variant
* `__builtin___memcpy_chk`.
*/
private class MemcpyFunction extends ArrayFunction, DataFlowFunction, SideEffectFunction,
AliasFunction
AliasFunction, NonThrowingFunction
{
MemcpyFunction() {
// memcpy(dest, src, num)

View File

@@ -8,9 +8,10 @@ import semmle.code.cpp.models.interfaces.ArrayFunction
import semmle.code.cpp.models.interfaces.DataFlow
import semmle.code.cpp.models.interfaces.Alias
import semmle.code.cpp.models.interfaces.SideEffect
import semmle.code.cpp.models.interfaces.NonThrowing
private class MemsetFunctionModel extends ArrayFunction, DataFlowFunction, AliasFunction,
SideEffectFunction
SideEffectFunction, NonThrowingFunction
{
MemsetFunctionModel() {
this.hasGlobalOrStdOrBslName("memset")

View File

@@ -0,0 +1,11 @@
import semmle.code.cpp.models.interfaces.NonThrowing
/**
* A function that is annotated with a `noexcept` specifier (or the equivalent
* `throw()` specifier) guaranteeing that the function can not throw exceptions.
*
* Note: The `throw` specifier was deprecated in C++11 and removed in C++17.
*/
class NoexceptFunction extends NonThrowingFunction {
NoexceptFunction() { this.isNoExcept() or this.isNoThrow() }
}

View File

@@ -8,11 +8,12 @@
import semmle.code.cpp.models.interfaces.FormattingFunction
import semmle.code.cpp.models.interfaces.Alias
import semmle.code.cpp.models.interfaces.SideEffect
import semmle.code.cpp.models.interfaces.NonThrowing
/**
* The standard functions `printf`, `wprintf` and their glib variants.
*/
private class Printf extends FormattingFunction, AliasFunction {
private class Printf extends FormattingFunction, AliasFunction, NonThrowingFunction {
Printf() {
this instanceof TopLevelFunction and
(
@@ -36,7 +37,7 @@ private class Printf extends FormattingFunction, AliasFunction {
/**
* The standard functions `fprintf`, `fwprintf` and their glib variants.
*/
private class Fprintf extends FormattingFunction {
private class Fprintf extends FormattingFunction, NonThrowingFunction {
Fprintf() {
this instanceof TopLevelFunction and
(
@@ -54,7 +55,7 @@ private class Fprintf extends FormattingFunction {
/**
* The standard function `sprintf` and its Microsoft and glib variants.
*/
private class Sprintf extends FormattingFunction {
private class Sprintf extends FormattingFunction, NonThrowingFunction {
Sprintf() {
this instanceof TopLevelFunction and
(
@@ -97,7 +98,7 @@ private class Sprintf extends FormattingFunction {
/**
* Implements `Snprintf`.
*/
private class SnprintfImpl extends Snprintf, AliasFunction, SideEffectFunction {
private class SnprintfImpl extends Snprintf, AliasFunction, SideEffectFunction, NonThrowingFunction {
SnprintfImpl() {
this instanceof TopLevelFunction and
(
@@ -204,7 +205,7 @@ private class StringCchPrintf extends FormattingFunction {
/**
* The standard function `syslog`.
*/
private class Syslog extends FormattingFunction {
private class Syslog extends FormattingFunction, NonThrowingFunction {
Syslog() {
this instanceof TopLevelFunction and
this.hasGlobalName("syslog") and

View File

@@ -7,13 +7,16 @@ import semmle.code.cpp.models.interfaces.ArrayFunction
import semmle.code.cpp.models.interfaces.DataFlow
import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.SideEffect
import semmle.code.cpp.models.interfaces.NonThrowing
/**
* The standard function `strcat` and its wide, sized, and Microsoft variants.
*
* Does not include `strlcat`, which is covered by `StrlcatFunction`
*/
class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, SideEffectFunction {
class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, SideEffectFunction,
NonThrowingFunction
{
StrcatFunction() {
this.hasGlobalOrStdOrBslName([
"strcat", // strcat(dst, src)

View File

@@ -7,11 +7,14 @@ import semmle.code.cpp.models.interfaces.ArrayFunction
import semmle.code.cpp.models.interfaces.DataFlow
import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.SideEffect
import semmle.code.cpp.models.interfaces.NonThrowing
/**
* The standard function `strcpy` and its wide, sized, and Microsoft variants.
*/
class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, SideEffectFunction {
class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, SideEffectFunction,
NonThrowingFunction
{
StrcpyFunction() {
this.hasGlobalOrStdOrBslName([
"strcpy", // strcpy(dst, src)

View File

@@ -26,7 +26,7 @@ private class Swap extends DataFlowFunction {
* obj1.swap(obj2)
* ```
*/
private class MemberSwap extends TaintFunction, MemberFunction, AliasFunction {
private class MemberSwap extends DataFlowFunction, MemberFunction, AliasFunction {
MemberSwap() {
this.hasName("swap") and
this.getNumberOfParameters() = 1 and
@@ -34,7 +34,7 @@ private class MemberSwap extends TaintFunction, MemberFunction, AliasFunction {
this.getDeclaringType()
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
input.isQualifierObject() and
output.isParameterDeref(0)
or

View File

@@ -0,0 +1,11 @@
/**
* Provides an abstract class for modeling functions that never throw.
*/
import semmle.code.cpp.Function
import semmle.code.cpp.models.Models
/**
* A function that is guaranteed to never throw.
*/
abstract class NonThrowingFunction extends Function { }

View File

@@ -19,6 +19,11 @@ abstract class BufferAccess extends Expr {
//A buffer access must be reachable (not in dead code)
reachable(this)
}
BufferAccess() {
not this.isUnevaluated() and
//A buffer access must be reachable (not in dead code)
reachable(this)
}
abstract string getName();
@@ -30,6 +35,8 @@ abstract class BufferAccess extends Expr {
* - 1 = buffer range [0, getSize) is accessed entirely.
* - 2 = buffer range [0, getSize) may be accessed partially or entirely.
* - 3 = buffer is accessed at offset getSize - 1.
* - 4 = buffer is accessed with null terminator read protections
* (does not read past null terminator, regardless of access size)
*/
abstract Expr getBuffer(string bufferDesc, int accessType);

View File

@@ -353,22 +353,6 @@ module BoostorgAsio {
}
//////////////////////// Dataflow /////////////////////
/**
* Abstract class for flows of protocol values to the first argument of a context
* constructor.
*/
abstract deprecated class SslContextCallAbstractConfig extends DataFlow::Configuration {
bindingset[this]
SslContextCallAbstractConfig() { any() }
override predicate isSink(DataFlow::Node sink) {
exists(ConstructorCall cc, SslContextClass c, Expr e | e = sink.asExpr() |
c.getAContructorCall() = cc and
cc.getArgument(0) = e
)
}
}
/**
* Signature for flows of protocol values to the first argument of a context
* constructor.
@@ -402,20 +386,6 @@ module BoostorgAsio {
import DataFlow::Global<C>
}
/**
* Any protocol value that flows to the first argument of a context constructor.
*/
deprecated class SslContextCallConfig extends SslContextCallAbstractConfig {
SslContextCallConfig() { this = "SslContextCallConfig" }
override predicate isSource(DataFlow::Node source) {
exists(Expr e | e = source.asExpr() |
e.fromSource() and
not e.getLocation().getFile().toString().matches("%/boost/asio/%")
)
}
}
/**
* Any protocol value that flows to the first argument of a context constructor.
*/
@@ -430,21 +400,6 @@ module BoostorgAsio {
module SslContextCallFlow = SslContextCallGlobal<SslContextCallConfig>;
/**
* A banned protocol value that flows to the first argument of a context constructor.
*/
deprecated class SslContextCallBannedProtocolConfig extends SslContextCallAbstractConfig {
SslContextCallBannedProtocolConfig() { this = "SslContextCallBannedProtocolConfig" }
override predicate isSource(DataFlow::Node source) {
exists(Expr e | e = source.asExpr() |
e.fromSource() and
not e.getLocation().getFile().toString().matches("%/boost/asio/%") and
isExprBannedBoostProtocol(e)
)
}
}
/**
* A banned protocol value that flows to the first argument of a context constructor.
*/
@@ -461,21 +416,6 @@ module BoostorgAsio {
module SslContextCallBannedProtocolFlow =
SslContextCallGlobal<SslContextCallBannedProtocolConfig>;
/**
* A TLS 1.2 protocol value that flows to the first argument of a context constructor.
*/
deprecated class SslContextCallTls12ProtocolConfig extends SslContextCallAbstractConfig {
SslContextCallTls12ProtocolConfig() { this = "SslContextCallTls12ProtocolConfig" }
override predicate isSource(DataFlow::Node source) {
exists(Expr e | e = source.asExpr() |
e.fromSource() and
not e.getLocation().getFile().toString().matches("%/boost/asio/%") and
isExprTls12BoostProtocol(e)
)
}
}
/**
* A TLS 1.2 protocol value that flows to the first argument of a context constructor.
*/
@@ -491,21 +431,6 @@ module BoostorgAsio {
module SslContextCallTls12ProtocolFlow = SslContextCallGlobal<SslContextCallTls12ProtocolConfig>;
/**
* A TLS 1.3 protocol value that flows to the first argument of a context constructor.
*/
deprecated class SslContextCallTls13ProtocolConfig extends SslContextCallAbstractConfig {
SslContextCallTls13ProtocolConfig() { this = "SslContextCallTls12ProtocolConfig" }
override predicate isSource(DataFlow::Node source) {
exists(Expr e | e = source.asExpr() |
e.fromSource() and
not e.getLocation().getFile().toString().matches("%/boost/asio/%") and
isExprTls13BoostProtocol(e)
)
}
}
/**
* A TLS 1.3 protocol value that flows to the first argument of a context constructor.
*/
@@ -521,21 +446,6 @@ module BoostorgAsio {
module SslContextCallTls13ProtocolFlow = SslContextCallGlobal<SslContextCallTls13ProtocolConfig>;
/**
* A generic TLS protocol value that flows to the first argument of a context constructor.
*/
deprecated class SslContextCallTlsProtocolConfig extends SslContextCallAbstractConfig {
SslContextCallTlsProtocolConfig() { this = "SslContextCallTlsProtocolConfig" }
override predicate isSource(DataFlow::Node source) {
exists(Expr e | e = source.asExpr() |
e.fromSource() and
not e.getLocation().getFile().toString().matches("%/boost/asio/%") and
isExprTlsBoostProtocol(e)
)
}
}
/**
* A generic TLS protocol value that flows to the first argument of a context constructor.
*/
@@ -551,30 +461,6 @@ module BoostorgAsio {
module SslContextCallTlsProtocolFlow = SslContextCallGlobal<SslContextCallTlsProtocolConfig>;
/**
* A context constructor call that flows to a call to `SetOptions()`.
*/
deprecated class SslContextFlowsToSetOptionConfig extends DataFlow::Configuration {
SslContextFlowsToSetOptionConfig() { this = "SslContextFlowsToSetOptionConfig" }
override predicate isSource(DataFlow::Node source) {
exists(SslContextClass c, ConstructorCall cc |
cc = source.asExpr() and
c.getAContructorCall() = cc
)
}
override predicate isSink(DataFlow::Node sink) {
exists(FunctionCall fc, SslSetOptionsFunction f, Variable v, VariableAccess va |
va = sink.asExpr()
|
f.getACallToThisFunction() = fc and
v.getAnAccess() = va and
va = fc.getQualifier()
)
}
}
/**
* A context constructor call that flows to a call to `SetOptions()`.
*/
@@ -599,28 +485,6 @@ module BoostorgAsio {
module SslContextFlowsToSetOptionFlow = DataFlow::Global<SslContextFlowsToSetOptionConfig>;
/**
* An option value that flows to the first parameter of a call to `SetOptions()`.
*/
deprecated class SslOptionConfig extends DataFlow::Configuration {
SslOptionConfig() { this = "SslOptionConfig" }
override predicate isSource(DataFlow::Node source) {
exists(Expr e | e = source.asExpr() |
e.fromSource() and
not e.getLocation().getFile().toString().matches("%/boost/asio/%")
)
}
override predicate isSink(DataFlow::Node sink) {
exists(SslSetOptionsFunction f, FunctionCall call |
sink.asExpr() = call.getArgument(0) and
f.getACallToThisFunction() = call and
not sink.getLocation().getFile().toString().matches("%/boost/asio/%")
)
}
}
/**
* An option value that flows to the first parameter of a call to `SetOptions()`.
*/

View File

@@ -384,11 +384,23 @@ function_return_type(
*/
coroutine(
unique int function: @function ref,
int traits: @type ref,
int handle: @variable ref,
int promise: @variable ref
int traits: @type ref
);
/*
case @coroutine_placeholder_variable.kind of
1 = @handle
| 2 = @promise
| 3 = @init_await_resume
;
*/
coroutine_placeholder_variable(
unique int placeholder_variable: @variable ref,
int kind: int ref,
int function: @function ref
)
/** The `new` function used for allocating the coroutine state, if any. */
coroutine_new(
unique int function: @function ref,
@@ -829,22 +841,6 @@ variable_template_argument_value(
int arg_value: @expr ref
);
/*
Fixed point types
precision(1) = short, precision(2) = default, precision(3) = long
is_unsigned(1) = unsigned is_unsigned(2) = signed
is_fract_type(1) = declared with _Fract
saturating(1) = declared with _Sat
*/
/* TODO
fixedpointtypes(
unique int id: @fixedpointtype,
int precision: int ref,
int is_unsigned: int ref,
int is_fract_type: int ref,
int saturating: int ref);
*/
routinetypes(
unique int id: @routinetype,
int return_type: @type ref
@@ -1210,6 +1206,7 @@ conversionkinds(
| @reference_to
| @ref_indirect
| @temp_init
| @c11_generic
;
/*
@@ -1788,6 +1785,11 @@ case @expr.kind of
| 382 = @isvalidwinrttype
| 383 = @iswinclass
| 384 = @iswininterface
| 385 = @istriviallyequalitycomparable
| 386 = @isscopedenum
| 387 = @istriviallyrelocatable
| 388 = @datasizeof
| 389 = @c11_generic
;
@var_args_expr = @vastartexpr
@@ -1901,6 +1903,9 @@ case @expr.kind of
| @isvalidwinrttype
| @iswinclass
| @iswininterface
| @istriviallyequalitycomparable
| @isscopedenum
| @istriviallyrelocatable
;
new_allocated_type(
@@ -1961,7 +1966,7 @@ uuidof_bind(
int type_id: @type ref
);
@runtime_sizeof_or_alignof = @runtime_sizeof | @runtime_alignof;
@runtime_sizeof_or_alignof = @runtime_sizeof | @runtime_alignof | @datasizeof;
sizeof_bind(
unique int expr: @runtime_sizeof_or_alignof ref,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Expose C11 _Generics
compatibility: backwards

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,4 @@
description: Improve handling of coroutine placeholder variables
compatibility: partial
coroutine.rel: run upgrades.qlo new_coroutine
coroutine_placeholder_variable.rel: run upgrades.qlo new_coroutine_placeholder_variable

View File

@@ -0,0 +1,19 @@
class Function extends @function {
string toString() { none() }
}
class Type extends @type {
string toString() { none() }
}
class Variable extends @variable {
string toString() { none() }
}
query predicate new_coroutine(Function func, Type traits) { coroutine(func, traits, _, _) }
query predicate new_coroutine_placeholder_variable(Variable var, int kind, Function func) {
coroutine(func, _, var, _) and kind = 1
or
coroutine(func, _, _, var) and kind = 2
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Add new builtin operations
compatibility: backwards

View File

@@ -1,3 +1,11 @@
## 1.2.3
### Minor Analysis Improvements
* Removed false positives caused by buffer accesses in unreachable code.
* Removed false positives caused by inconsistent type checking.
* Add modeling of C functions that don't throw, thereby increasing the precision of the `cpp/incorrect-allocation-error-handling` ("Incorrect allocation-error handling") query. The query now produces additional true positives.
## 1.2.2
No user-facing changes.

View File

@@ -42,7 +42,9 @@ class BufferAccess extends ArrayExpr {
not exists(Macro m |
m.getName() = "strcmp" and
m.getAnInvocation().getAnExpandedElement() = this
)
) and
//A buffer access must be reachable (not in dead code)
reachable(this)
}
int bufferSize() { staticBuffer(this.getArrayBase(), _, result) }

View File

@@ -205,20 +205,6 @@ class ChecksForLeapYearFunctionCall extends FunctionCall {
ChecksForLeapYearFunctionCall() { this.getTarget() instanceof ChecksForLeapYearFunction }
}
/**
* Data flow configuration for finding a variable access that would flow into
* a function call that includes an operation to check for leap year.
*/
deprecated class LeapYearCheckConfiguration extends DataFlow::Configuration {
LeapYearCheckConfiguration() { this = "LeapYearCheckConfiguration" }
override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof VariableAccess }
override predicate isSink(DataFlow::Node sink) {
exists(ChecksForLeapYearFunctionCall fc | sink.asExpr() = fc.getAnArgument())
}
}
/**
* Data flow configuration for finding a variable access that would flow into
* a function call that includes an operation to check for leap year.
@@ -233,33 +219,6 @@ private module LeapYearCheckConfig implements DataFlow::ConfigSig {
module LeapYearCheckFlow = DataFlow::Global<LeapYearCheckConfig>;
/**
* Data flow configuration for finding an operation with hardcoded 365 that will flow into
* a `FILEINFO` field.
*/
deprecated class FiletimeYearArithmeticOperationCheckConfiguration extends DataFlow::Configuration {
FiletimeYearArithmeticOperationCheckConfiguration() {
this = "FiletimeYearArithmeticOperationCheckConfiguration"
}
override predicate isSource(DataFlow::Node source) {
exists(Expr e, Operation op | e = source.asExpr() |
op.getAChild*().getValue().toInt() = 365 and
op.getAChild*() = e
)
}
override predicate isSink(DataFlow::Node sink) {
exists(StructLikeClass dds, FieldAccess fa, AssignExpr aexpr, Expr e | e = sink.asExpr() |
dds instanceof PackedTimeType and
fa.getQualifier().getUnderlyingType() = dds and
fa.isModified() and
aexpr.getAChild() = fa and
aexpr.getChild(1).getAChild*() = e
)
}
}
/**
* Data flow configuration for finding an operation with hardcoded 365 that will flow into
* a `FILEINFO` field.
@@ -286,51 +245,6 @@ private module FiletimeYearArithmeticOperationCheckConfig implements DataFlow::C
module FiletimeYearArithmeticOperationCheckFlow =
DataFlow::Global<FiletimeYearArithmeticOperationCheckConfig>;
/**
* Taint configuration for finding an operation with hardcoded 365 that will flow into any known date/time field.
*/
deprecated class PossibleYearArithmeticOperationCheckConfiguration extends TaintTracking::Configuration
{
PossibleYearArithmeticOperationCheckConfiguration() {
this = "PossibleYearArithmeticOperationCheckConfiguration"
}
override predicate isSource(DataFlow::Node source) {
exists(Operation op | op = source.asExpr() |
op.getAChild*().getValue().toInt() = 365 and
(
not op.getParent() instanceof Expr or
op.getParent() instanceof Assignment
)
)
}
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
// flow from anything on the RHS of an assignment to a time/date structure to that
// assignment.
exists(StructLikeClass dds, FieldAccess fa, Assignment aexpr, Expr e |
e = node1.asExpr() and
fa = node2.asExpr()
|
(dds instanceof PackedTimeType or dds instanceof UnpackedTimeType) and
fa.getQualifier().getUnderlyingType() = dds and
aexpr.getLValue() = fa and
aexpr.getRValue().getAChild*() = e
)
}
override predicate isSink(DataFlow::Node sink) {
exists(StructLikeClass dds, FieldAccess fa, AssignExpr aexpr |
aexpr.getRValue() = sink.asExpr()
|
(dds instanceof PackedTimeType or dds instanceof UnpackedTimeType) and
fa.getQualifier().getUnderlyingType() = dds and
fa.isModified() and
aexpr.getLValue() = fa
)
}
}
/**
* Taint configuration for finding an operation with hardcoded 365 that will flow into any known date/time field.
*/

View File

@@ -129,24 +129,6 @@ class NetworkFunctionCall extends FunctionCall {
NetworkFunctionCall() { this.getTarget().hasName(["ntohd", "ntohf", "ntohl", "ntohll", "ntohs"]) }
}
deprecated class NetworkToBufferSizeConfiguration extends DataFlow::Configuration {
NetworkToBufferSizeConfiguration() { this = "NetworkToBufferSizeConfiguration" }
override predicate isSource(DataFlow::Node node) { node.asExpr() instanceof NetworkFunctionCall }
override predicate isSink(DataFlow::Node node) {
node.asExpr() = any(BufferAccess ba).getAccessedLength()
}
override predicate isBarrier(DataFlow::Node node) {
exists(GuardCondition gc, GVN gvn |
gc.getAChild*() = gvn.getAnExpr() and
globalValueNumber(node.asExpr()) = gvn and
gc.controls(node.asExpr().getBasicBlock(), _)
)
}
}
private module NetworkToBufferSizeConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) { node.asExpr() instanceof NetworkFunctionCall }

View File

@@ -41,20 +41,6 @@ class ExternalApiDataNode extends DataFlow::Node {
string getFunctionDescription() { result = this.getExternalFunction().toString() }
}
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */
deprecated class UntrustedDataToExternalApiConfig extends TaintTracking::Configuration {
UntrustedDataToExternalApiConfig() { this = "UntrustedDataToExternalAPIConfig" }
override predicate isSource(DataFlow::Node source) {
exists(RemoteFlowSourceFunction remoteFlow |
remoteFlow = source.asExpr().(Call).getTarget() and
remoteFlow.hasRemoteFlowSource(_, _)
)
}
override predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode }
}
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */
private module UntrustedDataToExternalApiConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {

View File

@@ -41,15 +41,6 @@ class ExternalApiDataNode extends DataFlow::Node {
string getFunctionDescription() { result = this.getExternalFunction().toString() }
}
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */
deprecated class UntrustedDataToExternalApiConfig extends TaintTracking::Configuration {
UntrustedDataToExternalApiConfig() { this = "UntrustedDataToExternalAPIConfigIR" }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode }
}
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */
private module UntrustedDataToExternalApiConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }

View File

@@ -26,6 +26,7 @@ from
BufferAccess ba, string bufferDesc, int accessSize, int accessType, Element bufferAlloc,
int bufferSize, string message
where
accessType != 4 and
accessSize = ba.getSize() and
bufferSize = getBufferSize(ba.getBuffer(bufferDesc, accessType), bufferAlloc) and
(

View File

@@ -1,6 +1,6 @@
/**
* This file provides the `bounded` predicate that is used in both `cpp/uncontrolled-arithmetic`
* and `cpp/tainted-arithmetic`.
* This file provides the `bounded` predicate that is used in `cpp/uncontrolled-arithmetic`,
* `cpp/tainted-arithmetic` and `cpp/uncontrolled-allocation-size`.
*/
private import cpp
@@ -8,20 +8,18 @@ private import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
private import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils
/**
* An operand `e` of a bitwise and expression `andExpr` (i.e., `andExpr` is either an `BitwiseAndExpr`
* or an `AssignAndExpr`) with operands `operand1` and `operand2` is the operand that is not `e` is upper
* bounded by some number that is less than the maximum integer allowed by the result type of `andExpr`.
* An operand `operand` of a bitwise and expression `andExpr` (i.e., `andExpr` is either a
* `BitwiseAndExpr` or an `AssignAndExpr`) is upper bounded by some number that is less than the
* maximum integer allowed by the result type of `andExpr`.
*/
pragma[inline]
private predicate boundedBitwiseAnd(Expr e, Expr andExpr, Expr operand1, Expr operand2) {
operand1 != operand2 and
e = operand1 and
upperBound(operand2.getFullyConverted()) < exprMaxVal(andExpr.getFullyConverted())
private predicate boundedBitwiseAnd(Expr operand, Expr andExpr) {
upperBound(operand.getFullyConverted()) < exprMaxVal(andExpr.getFullyConverted())
}
/**
* Holds if `e` is an arithmetic expression that cannot overflow, or if `e` is an operand of an
* operation that may greatly reduce the range of possible values.
* Holds if `e` is an arithmetic expression that cannot overflow, or if `e` is an operation that
* may greatly reduce the range of possible values.
*/
predicate bounded(Expr e) {
// There can be two separate reasons for `convertedExprMightOverflow` not holding:
@@ -35,25 +33,25 @@ predicate bounded(Expr e) {
) and
not convertedExprMightOverflow(e)
or
// Optimistically assume that a remainder expression always yields a much smaller value.
e = any(RemExpr rem).getLeftOperand()
// Optimistically assume that the following operations always yields a much smaller value.
e instanceof RemExpr
or
e = any(AssignRemExpr rem).getLValue()
e instanceof DivExpr
or
e instanceof RShiftExpr
or
exists(BitwiseAndExpr andExpr |
boundedBitwiseAnd(e, andExpr, andExpr.getAnOperand(), andExpr.getAnOperand())
e = andExpr and boundedBitwiseAnd(andExpr.getAnOperand(), andExpr)
)
or
exists(AssignAndExpr andExpr |
boundedBitwiseAnd(e, andExpr, andExpr.getAnOperand(), andExpr.getAnOperand())
)
or
// Optimistically assume that a division always yields a much smaller value.
e = any(DivExpr div).getLeftOperand()
// For the assignment variant of the operations we place the barrier on the assigned lvalue.
e = any(AssignRemExpr rem).getLValue()
or
e = any(AssignDivExpr div).getLValue()
or
e = any(RShiftExpr shift).getLeftOperand()
or
e = any(AssignRShiftExpr div).getLValue()
or
exists(AssignAndExpr andExpr |
e = andExpr.getLValue() and boundedBitwiseAnd(andExpr.getRValue(), andExpr)
)
}

View File

@@ -16,6 +16,7 @@
import cpp
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
import semmle.code.cpp.controlflow.Guards
import semmle.code.cpp.models.implementations.NoexceptFunction
/** Gets the `Constructor` invoked when `newExpr` allocates memory. */
Constructor getConstructorForAllocation(NewOrNewArrayExpr newExpr) {
@@ -44,9 +45,8 @@ predicate deleteMayThrow(DeleteOrDeleteArrayExpr deleteExpr) {
* like it might throw an exception, and the function does not have a `noexcept` or `throw()` specifier.
*/
predicate functionMayThrow(Function f) {
(not exists(f.getBlock()) or stmtMayThrow(f.getBlock())) and
not f.isNoExcept() and
not f.isNoThrow()
not f instanceof NonThrowingFunction and
(not exists(f.getBlock()) or stmtMayThrow(f.getBlock()))
}
/** Holds if the evaluation of `stmt` may throw an exception. */
@@ -172,8 +172,7 @@ class ThrowingAllocator extends Function {
not exists(Parameter p | p = this.getAParameter() |
p.getUnspecifiedType().stripType() instanceof NoThrowType
) and
not this.isNoExcept() and
not this.isNoThrow()
not this instanceof NoexceptFunction
)
}
}

View File

@@ -0,0 +1,7 @@
## 1.2.3
### Minor Analysis Improvements
* Removed false positives caused by buffer accesses in unreachable code
* Removed false positives caused by inconsistent type checking
* Add modeling of C functions that don't throw, thereby increasing the precision of the `cpp/incorrect-allocation-error-handling` ("Incorrect allocation-error handling") query. The query now produces additional true positives.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.2.2
lastReleaseVersion: 1.2.3

View File

@@ -0,0 +1,26 @@
/**
* https://github.com/google/brotli
*/
import cpp
import DecompressionBomb
/**
* The `BrotliDecoderDecompress` function is used in flow sink.
* See https://www.brotli.org/decode.html.
*/
class BrotliDecoderDecompressFunction extends DecompressionFunction {
BrotliDecoderDecompressFunction() { this.hasGlobalName("BrotliDecoderDecompress") }
override int getArchiveParameterIndex() { result = 1 }
}
/**
* The `BrotliDecoderDecompressStream` function is used in flow sink.
* See https://www.brotli.org/decode.html.
*/
class BrotliDecoderDecompressStreamFunction extends DecompressionFunction {
BrotliDecoderDecompressStreamFunction() { this.hasGlobalName("BrotliDecoderDecompressStream") }
override int getArchiveParameterIndex() { result = 2 }
}

View File

@@ -0,0 +1,26 @@
import cpp
import semmle.code.cpp.ir.dataflow.TaintTracking
import MiniZip
import ZlibGzopen
import ZlibInflator
import ZlibUncompress
import LibArchive
import ZSTD
import Brotli
/**
* The Decompression Sink instances, extend this class to define new decompression sinks.
*/
abstract class DecompressionFunction extends Function {
abstract int getArchiveParameterIndex();
}
/**
* The Decompression Flow Steps, extend this class to define new decompression sinks.
*/
abstract class DecompressionFlowStep extends string {
bindingset[this]
DecompressionFlowStep() { any() }
abstract predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2);
}

View File

@@ -0,0 +1,39 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>Extracting Compressed files with any compression algorithm like gzip can cause denial of service attacks.</p>
<p>Attackers can compress a huge file consisting of repeated similiar bytes into a small compressed file.</p>
</overview>
<recommendation>
<p>When you want to decompress a user-provided compressed file you must be careful about the decompression ratio or read these files within a loop byte by byte to be able to manage the decompressed size in each cycle of the loop.</p>
</recommendation>
<example>
<p>
Reading an uncompressed Gzip file within a loop and check for a threshold size in each cycle.
</p>
<sample src="example_good.cpp"/>
<p>
The following example is unsafe, as we do not check the uncompressed size.
</p>
<sample src="example_bad.cpp" />
</example>
<references>
<li>
<a href="https://zlib.net/manual.html">Zlib documentation</a>
</li>
<li>
<a href="https://www.bamsoftware.com/hacks/zipbomb/">An explanation of the attack</a>
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,40 @@
/**
* @name User-controlled file decompression
* @description User-controlled data that flows into decompression library APIs without checking the compression rate is dangerous
* @kind path-problem
* @problem.severity error
* @precision low
* @id cpp/data-decompression-bomb
* @tags security
* experimental
* external/cwe/cwe-409
*/
import cpp
import semmle.code.cpp.security.FlowSources
import DecompressionBomb
predicate isSink(FunctionCall fc, DataFlow::Node sink) {
exists(DecompressionFunction f | fc.getTarget() = f |
fc.getArgument(f.getArchiveParameterIndex()) = [sink.asExpr(), sink.asIndirectExpr()]
)
}
module DecompressionTaintConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof FlowSource }
predicate isSink(DataFlow::Node sink) { isSink(_, sink) }
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
any(DecompressionFlowStep s).isAdditionalFlowStep(node1, node2)
}
}
module DecompressionTaint = TaintTracking::Global<DecompressionTaintConfig>;
import DecompressionTaint::PathGraph
from DecompressionTaint::PathNode source, DecompressionTaint::PathNode sink, FunctionCall fc
where DecompressionTaint::flowPath(source, sink) and isSink(fc, sink.getNode())
select sink.getNode(), source, sink, "The decompression output of $@ is not limited", fc,
fc.getTarget().getName()

View File

@@ -0,0 +1,32 @@
/**
* https://github.com/libarchive/libarchive/wiki
*/
import cpp
import DecompressionBomb
/**
* The `archive_read_data*` functions are used in flow sink.
* See https://github.com/libarchive/libarchive/wiki/Examples.
*/
class Archive_read_data_block extends DecompressionFunction {
Archive_read_data_block() {
this.hasGlobalName(["archive_read_data_block", "archive_read_data", "archive_read_data_into_fd"])
}
override int getArchiveParameterIndex() { result = 0 }
}
/**
* The `archive_read_open_filename` function as a flow step.
*/
class ReadOpenFunctionStep extends DecompressionFlowStep {
ReadOpenFunctionStep() { this = "ReadOpenFunction" }
override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(FunctionCall fc | fc.getTarget().hasGlobalName("archive_read_open_filename") |
node1.asIndirectExpr() = fc.getArgument(1) and
node2.asIndirectExpr() = fc.getArgument(0)
)
}
}

View File

@@ -0,0 +1,56 @@
/**
* https://github.com/zlib-ng/minizip-ng
*/
import cpp
import DecompressionBomb
/**
* The `mz_zip_entry` function is used in flow sink.
* See https://github.com/zlib-ng/minizip-ng/blob/master/doc/mz_zip.md.
*/
class Mz_zip_entry extends DecompressionFunction {
Mz_zip_entry() { this.hasGlobalName("mz_zip_entry_read") }
override int getArchiveParameterIndex() { result = 1 }
}
/**
* The `mz_zip_reader_entry_*` and `mz_zip_reader_save_all` functions are used in flow sink.
* See https://github.com/zlib-ng/minizip-ng/blob/master/doc/mz_zip_rw.md.
*/
class Mz_zip_reader_entry extends DecompressionFunction {
Mz_zip_reader_entry() {
this.hasGlobalName([
"mz_zip_reader_entry_save", "mz_zip_reader_entry_read", "mz_zip_reader_entry_save_process",
"mz_zip_reader_entry_save_file", "mz_zip_reader_entry_save_buffer", "mz_zip_reader_save_all"
])
}
override int getArchiveParameterIndex() { result = 0 }
}
/**
* The `UnzOpen*` functions are used in flow sink.
*/
class UnzOpenFunction extends DecompressionFunction {
UnzOpenFunction() { this.hasGlobalName(["UnzOpen", "unzOpen64", "unzOpen2", "unzOpen2_64"]) }
override int getArchiveParameterIndex() { result = 0 }
}
/**
* The `mz_zip_reader_open_file` and `mz_zip_reader_open_file_in_memory` functions as a flow step.
*/
class ReaderOpenFunctionStep extends DecompressionFlowStep {
ReaderOpenFunctionStep() { this = "ReaderOpenFunctionStep" }
override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(FunctionCall fc |
fc.getTarget().hasGlobalName(["mz_zip_reader_open_file_in_memory", "mz_zip_reader_open_file"])
|
node1.asIndirectExpr() = fc.getArgument(1) and
node2.asIndirectExpr() = fc.getArgument(0)
)
}
}

View File

@@ -0,0 +1,88 @@
/**
* https://github.com/facebook/zstd/blob/dev/examples/streaming_decompression.c
*/
import cpp
import DecompressionBomb
/**
* The `ZSTD_decompress` function is used in flow sink.
*/
class ZstdDecompressFunction extends DecompressionFunction {
ZstdDecompressFunction() { this.hasGlobalName("ZSTD_decompress") }
override int getArchiveParameterIndex() { result = 2 }
}
/**
* The `ZSTD_decompressDCtx` function is used in flow sink.
*/
class ZstdDecompressDctxFunction extends DecompressionFunction {
ZstdDecompressDctxFunction() { this.hasGlobalName("ZSTD_decompressDCtx") }
override int getArchiveParameterIndex() { result = 3 }
}
/**
* The `ZSTD_decompressStream` function is used in flow sink.
*/
class ZstdDecompressStreamFunction extends DecompressionFunction {
ZstdDecompressStreamFunction() { this.hasGlobalName("ZSTD_decompressStream") }
override int getArchiveParameterIndex() { result = 2 }
}
/**
* The `ZSTD_decompress_usingDDict` function is used in flow sink.
*/
class ZstdDecompressUsingDdictFunction extends DecompressionFunction {
ZstdDecompressUsingDdictFunction() { this.hasGlobalName("ZSTD_decompress_usingDDict") }
override int getArchiveParameterIndex() { result = 3 }
}
/**
* The `fopen_orDie` function as a flow step.
*/
class FopenOrDieFunctionStep extends DecompressionFlowStep {
FopenOrDieFunctionStep() { this = "FopenOrDieFunctionStep" }
override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(FunctionCall fc | fc.getTarget().hasGlobalName("fopen_orDie") |
node1.asIndirectExpr() = fc.getArgument(0) and
node2.asExpr() = fc
)
}
}
/**
* The `fread_orDie` function as a flow step.
*/
class FreadOrDieFunctionStep extends DecompressionFlowStep {
FreadOrDieFunctionStep() { this = "FreadOrDieFunctionStep" }
override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(FunctionCall fc | fc.getTarget().hasGlobalName("fread_orDie") |
node1.asExpr() = fc.getArgument(2) and
node2.asIndirectExpr() = fc.getArgument(0)
)
}
}
/**
* The `src` member of a `ZSTD_inBuffer` variable is used in a flow steps.
*/
class SrcMember extends DecompressionFlowStep {
SrcMember() { this = "SrcMember" }
override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(VariableAccess inBufferAccess, Field srcField, ClassAggregateLiteral c |
inBufferAccess.getType().hasName("ZSTD_inBuffer") and
srcField.hasName("src")
|
node2.asExpr() = inBufferAccess and
inBufferAccess.getTarget().getInitializer().getExpr() = c and
node1.asIndirectExpr() = c.getFieldExpr(srcField, _)
)
}
}

View File

@@ -0,0 +1,71 @@
/**
* https://www.zlib.net/
*/
import cpp
import DecompressionBomb
/**
* The `gzfread` function is used in flow sink.
*
* `gzfread(voidp buf, z_size_t size, z_size_t nitems, gzFile file)`
*/
class GzFreadFunction extends DecompressionFunction {
GzFreadFunction() { this.hasGlobalName("gzfread") }
override int getArchiveParameterIndex() { result = 3 }
}
/**
* The `gzgets` function is used in flow sink.
*
* `gzgets(gzFile file, char *buf, int len)`
*/
class GzGetsFunction extends DecompressionFunction {
GzGetsFunction() { this.hasGlobalName("gzgets") }
override int getArchiveParameterIndex() { result = 0 }
}
/**
* The `gzread` function is used in flow sink.
*
* `gzread(gzFile file, voidp buf, unsigned len)`
*/
class GzReadFunction extends DecompressionFunction {
GzReadFunction() { this.hasGlobalName("gzread") }
override int getArchiveParameterIndex() { result = 0 }
}
/**
* The `gzdopen` function is used in flow steps.
*
* `gzdopen(int fd, const char *mode)`
*/
class GzdopenFunctionStep extends DecompressionFlowStep {
GzdopenFunctionStep() { this = "GzdopenFunctionStep" }
override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(FunctionCall fc | fc.getTarget().hasGlobalName("gzdopen") |
node1.asExpr() = fc.getArgument(0) and
node2.asExpr() = fc
)
}
}
/**
* The `gzopen` function is used in flow steps.
*
* `gzopen(const char *path, const char *mode)`
*/
class GzopenFunctionStep extends DecompressionFlowStep {
GzopenFunctionStep() { this = "GzopenFunctionStep" }
override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(FunctionCall fc | fc.getTarget().hasGlobalName("gzopen") |
node1.asIndirectExpr() = fc.getArgument(0) and
node2.asExpr() = fc
)
}
}

View File

@@ -0,0 +1,37 @@
/**
* https://www.zlib.net/
*/
import cpp
import DecompressionBomb
/**
* The `inflate` and `inflateSync` functions are used in flow sink.
*
* `inflate(z_stream strm, int flush)`
*
* `inflateSync(z_stream strm)`
*/
class InflateFunction extends DecompressionFunction {
InflateFunction() { this.hasGlobalName(["inflate", "inflateSync"]) }
override int getArchiveParameterIndex() { result = 0 }
}
/**
* The `next_in` member of a `z_stream` variable is used in a flow steps.
*/
class NextInMemberStep extends DecompressionFlowStep {
NextInMemberStep() { this = "NextInMemberStep" }
override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(Variable nextInVar |
nextInVar.getDeclaringType().hasName("z_stream") and
nextInVar.hasName("next_in")
|
node1.asIndirectExpr() = nextInVar.getAnAssignedValue() and
node2.asExpr() =
nextInVar.getAnAccess().getQualifier().(VariableAccess).getTarget().getAnAccess()
)
}
}

View File

@@ -0,0 +1,15 @@
/**
* https://www.zlib.net/
*/
import cpp
import DecompressionBomb
/**
* The `uncompress`/`uncompress2` function is used in flow sink.
*/
class UncompressFunction extends DecompressionFunction {
UncompressFunction() { this.hasGlobalName(["uncompress", "uncompress2"]) }
override int getArchiveParameterIndex() { result = 2 }
}

View File

@@ -0,0 +1,15 @@
#include "zlib.h"
void UnsafeGzread(gzFile inFileZ) {
const int BUFFER_SIZE = 8192;
unsigned char unzipBuffer[BUFFER_SIZE];
unsigned int unzippedBytes;
while (true) {
unzippedBytes = gzread(inFileZ, unzipBuffer, BUFFER_SIZE);
if (unzippedBytes <= 0) {
break;
}
// process buffer
}
}

View File

@@ -0,0 +1,23 @@
#include "zlib.h"
void SafeGzread(gzFile inFileZ) {
const int MAX_READ = 1024 * 1024 * 4;
const int BUFFER_SIZE = 8192;
unsigned char unzipBuffer[BUFFER_SIZE];
unsigned int unzippedBytes;
unsigned int totalRead = 0;
while (true) {
unzippedBytes = gzread(inFileZ, unzipBuffer, BUFFER_SIZE);
totalRead += unzippedBytes;
if (unzippedBytes <= 0) {
break;
}
if (totalRead > MAX_READ) {
// Possible decompression bomb, stop processing.
break;
} else {
// process buffer
}
}
}

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries
version: 1.2.2
version: 1.2.3
groups:
- cpp
- queries

View File

@@ -0,0 +1,239 @@
edges
| brotliTest.cpp:15:41:15:44 | **argv | brotliTest.cpp:15:41:15:44 | **argv | provenance | |
| brotliTest.cpp:15:41:15:44 | **argv | brotliTest.cpp:18:35:18:53 | *access to array | provenance | |
| brotliTest.cpp:15:41:15:44 | **argv | brotliTest.cpp:21:30:21:52 | *access to array | provenance | |
| brotliTest.cpp:21:30:21:52 | *access to array | brotliTest.cpp:24:51:24:58 | **& ... | provenance | |
| libarchiveTests.cpp:16:31:16:32 | *ar | libarchiveTests.cpp:16:31:16:32 | *ar | provenance | |
| libarchiveTests.cpp:16:31:16:32 | *ar | libarchiveTests.cpp:22:41:22:42 | *ar | provenance | |
| libarchiveTests.cpp:30:45:30:48 | **argv | libarchiveTests.cpp:30:45:30:48 | **argv | provenance | |
| libarchiveTests.cpp:30:45:30:48 | **argv | libarchiveTests.cpp:34:35:34:41 | *access to array | provenance | |
| libarchiveTests.cpp:34:32:34:32 | *a | libarchiveTests.cpp:38:27:38:27 | *a | provenance | |
| libarchiveTests.cpp:34:35:34:41 | *access to array | libarchiveTests.cpp:34:32:34:32 | *a | provenance | Config |
| libarchiveTests.cpp:38:27:38:27 | *a | libarchiveTests.cpp:16:31:16:32 | *ar | provenance | |
| libarchiveTests.cpp:38:27:38:27 | *a | libarchiveTests.cpp:38:27:38:27 | read_data output argument | provenance | |
| libarchiveTests.cpp:38:27:38:27 | read_data output argument | libarchiveTests.cpp:38:27:38:27 | *a | provenance | |
| main.cpp:7:33:7:36 | **argv | main.cpp:8:23:8:26 | **argv | provenance | |
| main.cpp:7:33:7:36 | **argv | main.cpp:9:27:9:30 | **argv | provenance | |
| main.cpp:7:33:7:36 | **argv | main.cpp:10:24:10:27 | **argv | provenance | |
| main.cpp:7:33:7:36 | **argv | main.cpp:11:21:11:24 | **argv | provenance | |
| main.cpp:7:33:7:36 | **argv | main.cpp:12:21:12:24 | **argv | provenance | |
| main.cpp:8:23:8:26 | **argv | brotliTest.cpp:15:41:15:44 | **argv | provenance | |
| main.cpp:8:23:8:26 | **argv | main.cpp:8:23:8:26 | brotli_test output argument | provenance | |
| main.cpp:8:23:8:26 | brotli_test output argument | main.cpp:9:27:9:30 | **argv | provenance | |
| main.cpp:8:23:8:26 | brotli_test output argument | main.cpp:10:24:10:27 | **argv | provenance | |
| main.cpp:8:23:8:26 | brotli_test output argument | main.cpp:11:21:11:24 | **argv | provenance | |
| main.cpp:8:23:8:26 | brotli_test output argument | main.cpp:12:21:12:24 | **argv | provenance | |
| main.cpp:9:27:9:30 | **argv | libarchiveTests.cpp:30:45:30:48 | **argv | provenance | |
| main.cpp:9:27:9:30 | **argv | main.cpp:9:27:9:30 | libarchive_test output argument | provenance | |
| main.cpp:9:27:9:30 | libarchive_test output argument | main.cpp:10:24:10:27 | **argv | provenance | |
| main.cpp:9:27:9:30 | libarchive_test output argument | main.cpp:11:21:11:24 | **argv | provenance | |
| main.cpp:9:27:9:30 | libarchive_test output argument | main.cpp:12:21:12:24 | **argv | provenance | |
| main.cpp:10:24:10:27 | **argv | main.cpp:10:24:10:27 | minizip_test output argument | provenance | |
| main.cpp:10:24:10:27 | **argv | minizipTest.cpp:12:42:12:45 | **argv | provenance | |
| main.cpp:10:24:10:27 | minizip_test output argument | main.cpp:11:21:11:24 | **argv | provenance | |
| main.cpp:10:24:10:27 | minizip_test output argument | main.cpp:12:21:12:24 | **argv | provenance | |
| main.cpp:11:21:11:24 | **argv | main.cpp:11:21:11:24 | zlib_test output argument | provenance | |
| main.cpp:11:21:11:24 | **argv | main.cpp:11:21:11:24 | zlib_test output argument | provenance | |
| main.cpp:11:21:11:24 | **argv | zlibTest.cpp:80:33:80:36 | **argv | provenance | |
| main.cpp:11:21:11:24 | zlib_test output argument | main.cpp:12:21:12:24 | **argv | provenance | |
| main.cpp:11:21:11:24 | zlib_test output argument | main.cpp:12:21:12:24 | *argv | provenance | |
| main.cpp:12:21:12:24 | **argv | zstdTest.cpp:26:39:26:42 | **argv | provenance | |
| main.cpp:12:21:12:24 | *argv | zstdTest.cpp:26:39:26:42 | **argv | provenance | |
| main.cpp:12:21:12:24 | *argv | zstdTest.cpp:26:39:26:42 | *argv | provenance | |
| minizipTest.cpp:12:42:12:45 | **argv | minizipTest.cpp:12:42:12:45 | **argv | provenance | |
| minizipTest.cpp:12:42:12:45 | **argv | minizipTest.cpp:17:52:17:67 | *access to array | provenance | |
| minizipTest.cpp:12:42:12:45 | **argv | minizipTest.cpp:24:41:24:47 | *access to array | provenance | |
| minizipTest.cpp:12:42:12:45 | **argv | minizipTest.cpp:28:13:28:19 | *access to array | provenance | |
| minizipTest.cpp:24:29:24:38 | **zip_reader | minizipTest.cpp:26:30:26:39 | **zip_reader | provenance | |
| minizipTest.cpp:24:29:24:38 | *zip_reader | minizipTest.cpp:26:30:26:39 | *zip_reader | provenance | |
| minizipTest.cpp:24:41:24:47 | *access to array | minizipTest.cpp:24:29:24:38 | **zip_reader | provenance | Config |
| minizipTest.cpp:24:41:24:47 | *access to array | minizipTest.cpp:24:29:24:38 | *zip_reader | provenance | Config |
| zlibTest.cpp:16:26:16:30 | *input | zlibTest.cpp:20:25:20:39 | *input | provenance | |
| zlibTest.cpp:20:25:20:39 | *input | zlibTest.cpp:16:26:16:30 | *input | provenance | |
| zlibTest.cpp:20:25:20:39 | *input | zlibTest.cpp:24:17:24:26 | & ... | provenance | Config |
| zlibTest.cpp:20:25:20:39 | *input | zlibTest.cpp:25:13:25:22 | & ... | provenance | Config |
| zlibTest.cpp:24:17:24:26 | & ... | zlibTest.cpp:25:13:25:22 | & ... | provenance | |
| zlibTest.cpp:37:25:37:32 | *fileName | zlibTest.cpp:38:29:38:36 | *fileName | provenance | |
| zlibTest.cpp:38:22:38:27 | call to gzopen | zlibTest.cpp:38:22:38:27 | call to gzopen | provenance | |
| zlibTest.cpp:38:22:38:27 | call to gzopen | zlibTest.cpp:41:20:41:26 | inFileZ | provenance | |
| zlibTest.cpp:38:29:38:36 | *fileName | zlibTest.cpp:37:25:37:32 | *fileName | provenance | |
| zlibTest.cpp:38:29:38:36 | *fileName | zlibTest.cpp:38:22:38:27 | call to gzopen | provenance | Config |
| zlibTest.cpp:47:26:47:33 | *fileName | zlibTest.cpp:48:29:48:36 | *fileName | provenance | |
| zlibTest.cpp:48:22:48:27 | call to gzopen | zlibTest.cpp:48:22:48:27 | call to gzopen | provenance | |
| zlibTest.cpp:48:22:48:27 | call to gzopen | zlibTest.cpp:51:38:51:44 | inFileZ | provenance | |
| zlibTest.cpp:48:29:48:36 | *fileName | zlibTest.cpp:47:26:47:33 | *fileName | provenance | |
| zlibTest.cpp:48:29:48:36 | *fileName | zlibTest.cpp:48:22:48:27 | call to gzopen | provenance | Config |
| zlibTest.cpp:57:25:57:32 | *fileName | zlibTest.cpp:58:29:58:36 | *fileName | provenance | |
| zlibTest.cpp:58:22:58:27 | call to gzopen | zlibTest.cpp:58:22:58:27 | call to gzopen | provenance | |
| zlibTest.cpp:58:22:58:27 | call to gzopen | zlibTest.cpp:62:25:62:31 | inFileZ | provenance | |
| zlibTest.cpp:58:29:58:36 | *fileName | zlibTest.cpp:57:25:57:32 | *fileName | provenance | |
| zlibTest.cpp:58:29:58:36 | *fileName | zlibTest.cpp:58:22:58:27 | call to gzopen | provenance | Config |
| zlibTest.cpp:71:26:71:30 | *input | zlibTest.cpp:71:26:71:30 | *input | provenance | |
| zlibTest.cpp:71:26:71:30 | *input | zlibTest.cpp:77:45:77:59 | *input | provenance | |
| zlibTest.cpp:80:33:80:36 | **argv | zlibTest.cpp:80:33:80:36 | **argv | provenance | |
| zlibTest.cpp:80:33:80:36 | **argv | zlibTest.cpp:81:19:81:25 | *access to array | provenance | |
| zlibTest.cpp:80:33:80:36 | **argv | zlibTest.cpp:82:18:82:24 | *access to array | provenance | |
| zlibTest.cpp:80:33:80:36 | **argv | zlibTest.cpp:83:19:83:25 | *access to array | provenance | |
| zlibTest.cpp:80:33:80:36 | **argv | zlibTest.cpp:84:18:84:24 | *access to array | provenance | |
| zlibTest.cpp:80:33:80:36 | **argv | zlibTest.cpp:85:19:85:25 | *access to array | provenance | |
| zlibTest.cpp:81:19:81:25 | *access to array | zlibTest.cpp:47:26:47:33 | *fileName | provenance | |
| zlibTest.cpp:81:19:81:25 | *access to array | zlibTest.cpp:81:19:81:25 | UnsafeGzfread output argument | provenance | |
| zlibTest.cpp:81:19:81:25 | UnsafeGzfread output argument | zlibTest.cpp:80:33:80:36 | **argv | provenance | |
| zlibTest.cpp:81:19:81:25 | UnsafeGzfread output argument | zlibTest.cpp:80:33:80:36 | **argv [Return] | provenance | |
| zlibTest.cpp:81:19:81:25 | UnsafeGzfread output argument | zlibTest.cpp:82:18:82:24 | *access to array | provenance | |
| zlibTest.cpp:81:19:81:25 | UnsafeGzfread output argument | zlibTest.cpp:83:19:83:25 | *access to array | provenance | |
| zlibTest.cpp:81:19:81:25 | UnsafeGzfread output argument | zlibTest.cpp:84:18:84:24 | *access to array | provenance | |
| zlibTest.cpp:81:19:81:25 | UnsafeGzfread output argument | zlibTest.cpp:85:19:85:25 | *access to array | provenance | |
| zlibTest.cpp:82:18:82:24 | *access to array | zlibTest.cpp:57:25:57:32 | *fileName | provenance | |
| zlibTest.cpp:82:18:82:24 | *access to array | zlibTest.cpp:82:18:82:24 | UnsafeGzgets output argument | provenance | |
| zlibTest.cpp:82:18:82:24 | UnsafeGzgets output argument | zlibTest.cpp:80:33:80:36 | **argv | provenance | |
| zlibTest.cpp:82:18:82:24 | UnsafeGzgets output argument | zlibTest.cpp:80:33:80:36 | **argv [Return] | provenance | |
| zlibTest.cpp:82:18:82:24 | UnsafeGzgets output argument | zlibTest.cpp:83:19:83:25 | *access to array | provenance | |
| zlibTest.cpp:82:18:82:24 | UnsafeGzgets output argument | zlibTest.cpp:84:18:84:24 | *access to array | provenance | |
| zlibTest.cpp:82:18:82:24 | UnsafeGzgets output argument | zlibTest.cpp:85:19:85:25 | *access to array | provenance | |
| zlibTest.cpp:83:19:83:25 | *access to array | zlibTest.cpp:16:26:16:30 | *input | provenance | |
| zlibTest.cpp:83:19:83:25 | *access to array | zlibTest.cpp:83:19:83:25 | UnsafeInflate output argument | provenance | |
| zlibTest.cpp:83:19:83:25 | UnsafeInflate output argument | zlibTest.cpp:80:33:80:36 | **argv | provenance | |
| zlibTest.cpp:83:19:83:25 | UnsafeInflate output argument | zlibTest.cpp:80:33:80:36 | **argv [Return] | provenance | |
| zlibTest.cpp:83:19:83:25 | UnsafeInflate output argument | zlibTest.cpp:84:18:84:24 | *access to array | provenance | |
| zlibTest.cpp:83:19:83:25 | UnsafeInflate output argument | zlibTest.cpp:85:19:85:25 | *access to array | provenance | |
| zlibTest.cpp:84:18:84:24 | *access to array | zlibTest.cpp:37:25:37:32 | *fileName | provenance | |
| zlibTest.cpp:84:18:84:24 | *access to array | zlibTest.cpp:84:18:84:24 | UnsafeGzread output argument | provenance | |
| zlibTest.cpp:84:18:84:24 | UnsafeGzread output argument | zlibTest.cpp:80:33:80:36 | **argv | provenance | |
| zlibTest.cpp:84:18:84:24 | UnsafeGzread output argument | zlibTest.cpp:80:33:80:36 | **argv [Return] | provenance | |
| zlibTest.cpp:84:18:84:24 | UnsafeGzread output argument | zlibTest.cpp:85:19:85:25 | *access to array | provenance | |
| zlibTest.cpp:85:19:85:25 | *access to array | zlibTest.cpp:71:26:71:30 | *input | provenance | |
| zlibTest.cpp:85:19:85:25 | *access to array | zlibTest.cpp:85:19:85:25 | InflateString output argument | provenance | |
| zlibTest.cpp:85:19:85:25 | InflateString output argument | zlibTest.cpp:80:33:80:36 | **argv | provenance | |
| zlibTest.cpp:85:19:85:25 | InflateString output argument | zlibTest.cpp:80:33:80:36 | **argv [Return] | provenance | |
| zstdTest.cpp:26:39:26:42 | **argv | zstdTest.cpp:27:35:27:41 | *access to array | provenance | |
| zstdTest.cpp:26:39:26:42 | *argv | zstdTest.cpp:27:35:27:41 | *access to array | provenance | |
| zstdTest.cpp:27:23:27:33 | call to fopen_orDie | zstdTest.cpp:27:23:27:33 | call to fopen_orDie | provenance | |
| zstdTest.cpp:27:23:27:33 | call to fopen_orDie | zstdTest.cpp:35:52:35:54 | fin | provenance | |
| zstdTest.cpp:27:35:27:41 | *access to array | zstdTest.cpp:27:23:27:33 | call to fopen_orDie | provenance | Config |
| zstdTest.cpp:35:32:35:37 | **buffIn | zstdTest.cpp:36:32:36:37 | **buffIn | provenance | |
| zstdTest.cpp:35:32:35:37 | *buffIn | zstdTest.cpp:36:32:36:37 | *buffIn | provenance | |
| zstdTest.cpp:35:52:35:54 | fin | zstdTest.cpp:35:32:35:37 | **buffIn | provenance | Config |
| zstdTest.cpp:35:52:35:54 | fin | zstdTest.cpp:35:32:35:37 | *buffIn | provenance | Config |
| zstdTest.cpp:36:32:36:37 | **buffIn | zstdTest.cpp:35:32:35:37 | **buffIn | provenance | |
| zstdTest.cpp:36:32:36:37 | **buffIn | zstdTest.cpp:39:69:39:74 | & ... | provenance | Config |
| zstdTest.cpp:36:32:36:37 | **buffIn | zstdTest.cpp:39:69:39:74 | & ... | provenance | Config |
| zstdTest.cpp:36:32:36:37 | *buffIn | zstdTest.cpp:35:32:35:37 | *buffIn | provenance | |
| zstdTest.cpp:36:32:36:37 | *buffIn | zstdTest.cpp:39:69:39:74 | & ... | provenance | Config |
| zstdTest.cpp:36:32:36:37 | *buffIn | zstdTest.cpp:39:69:39:74 | & ... | provenance | Config |
| zstdTest.cpp:39:69:39:74 | & ... | zstdTest.cpp:39:69:39:74 | & ... | provenance | |
| zstdTest.cpp:39:69:39:74 | & ... | zstdTest.cpp:39:69:39:74 | & ... | provenance | |
nodes
| brotliTest.cpp:15:41:15:44 | **argv | semmle.label | **argv |
| brotliTest.cpp:15:41:15:44 | **argv | semmle.label | **argv |
| brotliTest.cpp:18:35:18:53 | *access to array | semmle.label | *access to array |
| brotliTest.cpp:21:30:21:52 | *access to array | semmle.label | *access to array |
| brotliTest.cpp:24:51:24:58 | **& ... | semmle.label | **& ... |
| libarchiveTests.cpp:16:31:16:32 | *ar | semmle.label | *ar |
| libarchiveTests.cpp:16:31:16:32 | *ar | semmle.label | *ar |
| libarchiveTests.cpp:22:41:22:42 | *ar | semmle.label | *ar |
| libarchiveTests.cpp:30:45:30:48 | **argv | semmle.label | **argv |
| libarchiveTests.cpp:30:45:30:48 | **argv | semmle.label | **argv |
| libarchiveTests.cpp:34:32:34:32 | *a | semmle.label | *a |
| libarchiveTests.cpp:34:35:34:41 | *access to array | semmle.label | *access to array |
| libarchiveTests.cpp:38:27:38:27 | *a | semmle.label | *a |
| libarchiveTests.cpp:38:27:38:27 | read_data output argument | semmle.label | read_data output argument |
| main.cpp:7:33:7:36 | **argv | semmle.label | **argv |
| main.cpp:8:23:8:26 | **argv | semmle.label | **argv |
| main.cpp:8:23:8:26 | brotli_test output argument | semmle.label | brotli_test output argument |
| main.cpp:9:27:9:30 | **argv | semmle.label | **argv |
| main.cpp:9:27:9:30 | libarchive_test output argument | semmle.label | libarchive_test output argument |
| main.cpp:10:24:10:27 | **argv | semmle.label | **argv |
| main.cpp:10:24:10:27 | minizip_test output argument | semmle.label | minizip_test output argument |
| main.cpp:11:21:11:24 | **argv | semmle.label | **argv |
| main.cpp:11:21:11:24 | zlib_test output argument | semmle.label | zlib_test output argument |
| main.cpp:11:21:11:24 | zlib_test output argument | semmle.label | zlib_test output argument |
| main.cpp:12:21:12:24 | **argv | semmle.label | **argv |
| main.cpp:12:21:12:24 | *argv | semmle.label | *argv |
| minizipTest.cpp:12:42:12:45 | **argv | semmle.label | **argv |
| minizipTest.cpp:12:42:12:45 | **argv | semmle.label | **argv |
| minizipTest.cpp:17:52:17:67 | *access to array | semmle.label | *access to array |
| minizipTest.cpp:24:29:24:38 | **zip_reader | semmle.label | **zip_reader |
| minizipTest.cpp:24:29:24:38 | *zip_reader | semmle.label | *zip_reader |
| minizipTest.cpp:24:41:24:47 | *access to array | semmle.label | *access to array |
| minizipTest.cpp:26:30:26:39 | **zip_reader | semmle.label | **zip_reader |
| minizipTest.cpp:26:30:26:39 | *zip_reader | semmle.label | *zip_reader |
| minizipTest.cpp:28:13:28:19 | *access to array | semmle.label | *access to array |
| zlibTest.cpp:16:26:16:30 | *input | semmle.label | *input |
| zlibTest.cpp:16:26:16:30 | *input | semmle.label | *input |
| zlibTest.cpp:20:25:20:39 | *input | semmle.label | *input |
| zlibTest.cpp:24:17:24:26 | & ... | semmle.label | & ... |
| zlibTest.cpp:25:13:25:22 | & ... | semmle.label | & ... |
| zlibTest.cpp:37:25:37:32 | *fileName | semmle.label | *fileName |
| zlibTest.cpp:37:25:37:32 | *fileName | semmle.label | *fileName |
| zlibTest.cpp:38:22:38:27 | call to gzopen | semmle.label | call to gzopen |
| zlibTest.cpp:38:22:38:27 | call to gzopen | semmle.label | call to gzopen |
| zlibTest.cpp:38:29:38:36 | *fileName | semmle.label | *fileName |
| zlibTest.cpp:41:20:41:26 | inFileZ | semmle.label | inFileZ |
| zlibTest.cpp:47:26:47:33 | *fileName | semmle.label | *fileName |
| zlibTest.cpp:47:26:47:33 | *fileName | semmle.label | *fileName |
| zlibTest.cpp:48:22:48:27 | call to gzopen | semmle.label | call to gzopen |
| zlibTest.cpp:48:22:48:27 | call to gzopen | semmle.label | call to gzopen |
| zlibTest.cpp:48:29:48:36 | *fileName | semmle.label | *fileName |
| zlibTest.cpp:51:38:51:44 | inFileZ | semmle.label | inFileZ |
| zlibTest.cpp:57:25:57:32 | *fileName | semmle.label | *fileName |
| zlibTest.cpp:57:25:57:32 | *fileName | semmle.label | *fileName |
| zlibTest.cpp:58:22:58:27 | call to gzopen | semmle.label | call to gzopen |
| zlibTest.cpp:58:22:58:27 | call to gzopen | semmle.label | call to gzopen |
| zlibTest.cpp:58:29:58:36 | *fileName | semmle.label | *fileName |
| zlibTest.cpp:62:25:62:31 | inFileZ | semmle.label | inFileZ |
| zlibTest.cpp:71:26:71:30 | *input | semmle.label | *input |
| zlibTest.cpp:71:26:71:30 | *input | semmle.label | *input |
| zlibTest.cpp:77:45:77:59 | *input | semmle.label | *input |
| zlibTest.cpp:80:33:80:36 | **argv | semmle.label | **argv |
| zlibTest.cpp:80:33:80:36 | **argv | semmle.label | **argv |
| zlibTest.cpp:80:33:80:36 | **argv [Return] | semmle.label | **argv [Return] |
| zlibTest.cpp:81:19:81:25 | *access to array | semmle.label | *access to array |
| zlibTest.cpp:81:19:81:25 | UnsafeGzfread output argument | semmle.label | UnsafeGzfread output argument |
| zlibTest.cpp:82:18:82:24 | *access to array | semmle.label | *access to array |
| zlibTest.cpp:82:18:82:24 | UnsafeGzgets output argument | semmle.label | UnsafeGzgets output argument |
| zlibTest.cpp:83:19:83:25 | *access to array | semmle.label | *access to array |
| zlibTest.cpp:83:19:83:25 | UnsafeInflate output argument | semmle.label | UnsafeInflate output argument |
| zlibTest.cpp:84:18:84:24 | *access to array | semmle.label | *access to array |
| zlibTest.cpp:84:18:84:24 | UnsafeGzread output argument | semmle.label | UnsafeGzread output argument |
| zlibTest.cpp:85:19:85:25 | *access to array | semmle.label | *access to array |
| zlibTest.cpp:85:19:85:25 | InflateString output argument | semmle.label | InflateString output argument |
| zstdTest.cpp:26:39:26:42 | **argv | semmle.label | **argv |
| zstdTest.cpp:26:39:26:42 | *argv | semmle.label | *argv |
| zstdTest.cpp:27:23:27:33 | call to fopen_orDie | semmle.label | call to fopen_orDie |
| zstdTest.cpp:27:23:27:33 | call to fopen_orDie | semmle.label | call to fopen_orDie |
| zstdTest.cpp:27:35:27:41 | *access to array | semmle.label | *access to array |
| zstdTest.cpp:35:32:35:37 | **buffIn | semmle.label | **buffIn |
| zstdTest.cpp:35:32:35:37 | *buffIn | semmle.label | *buffIn |
| zstdTest.cpp:35:52:35:54 | fin | semmle.label | fin |
| zstdTest.cpp:36:32:36:37 | **buffIn | semmle.label | **buffIn |
| zstdTest.cpp:36:32:36:37 | *buffIn | semmle.label | *buffIn |
| zstdTest.cpp:39:69:39:74 | & ... | semmle.label | & ... |
| zstdTest.cpp:39:69:39:74 | & ... | semmle.label | & ... |
subpaths
| libarchiveTests.cpp:38:27:38:27 | *a | libarchiveTests.cpp:16:31:16:32 | *ar | libarchiveTests.cpp:16:31:16:32 | *ar | libarchiveTests.cpp:38:27:38:27 | read_data output argument |
| main.cpp:8:23:8:26 | **argv | brotliTest.cpp:15:41:15:44 | **argv | brotliTest.cpp:15:41:15:44 | **argv | main.cpp:8:23:8:26 | brotli_test output argument |
| main.cpp:9:27:9:30 | **argv | libarchiveTests.cpp:30:45:30:48 | **argv | libarchiveTests.cpp:30:45:30:48 | **argv | main.cpp:9:27:9:30 | libarchive_test output argument |
| main.cpp:10:24:10:27 | **argv | minizipTest.cpp:12:42:12:45 | **argv | minizipTest.cpp:12:42:12:45 | **argv | main.cpp:10:24:10:27 | minizip_test output argument |
| main.cpp:11:21:11:24 | **argv | zlibTest.cpp:80:33:80:36 | **argv | zlibTest.cpp:80:33:80:36 | **argv | main.cpp:11:21:11:24 | zlib_test output argument |
| main.cpp:11:21:11:24 | **argv | zlibTest.cpp:80:33:80:36 | **argv | zlibTest.cpp:80:33:80:36 | **argv [Return] | main.cpp:11:21:11:24 | zlib_test output argument |
| main.cpp:11:21:11:24 | **argv | zlibTest.cpp:80:33:80:36 | **argv | zlibTest.cpp:80:33:80:36 | **argv [Return] | main.cpp:11:21:11:24 | zlib_test output argument |
| zlibTest.cpp:81:19:81:25 | *access to array | zlibTest.cpp:47:26:47:33 | *fileName | zlibTest.cpp:47:26:47:33 | *fileName | zlibTest.cpp:81:19:81:25 | UnsafeGzfread output argument |
| zlibTest.cpp:82:18:82:24 | *access to array | zlibTest.cpp:57:25:57:32 | *fileName | zlibTest.cpp:57:25:57:32 | *fileName | zlibTest.cpp:82:18:82:24 | UnsafeGzgets output argument |
| zlibTest.cpp:83:19:83:25 | *access to array | zlibTest.cpp:16:26:16:30 | *input | zlibTest.cpp:16:26:16:30 | *input | zlibTest.cpp:83:19:83:25 | UnsafeInflate output argument |
| zlibTest.cpp:84:18:84:24 | *access to array | zlibTest.cpp:37:25:37:32 | *fileName | zlibTest.cpp:37:25:37:32 | *fileName | zlibTest.cpp:84:18:84:24 | UnsafeGzread output argument |
| zlibTest.cpp:85:19:85:25 | *access to array | zlibTest.cpp:71:26:71:30 | *input | zlibTest.cpp:71:26:71:30 | *input | zlibTest.cpp:85:19:85:25 | InflateString output argument |
#select
| brotliTest.cpp:18:35:18:53 | *access to array | main.cpp:7:33:7:36 | **argv | brotliTest.cpp:18:35:18:53 | *access to array | The decompression output of $@ is not limited | brotliTest.cpp:18:5:18:27 | call to BrotliDecoderDecompress | BrotliDecoderDecompress |
| brotliTest.cpp:24:51:24:58 | **& ... | main.cpp:7:33:7:36 | **argv | brotliTest.cpp:24:51:24:58 | **& ... | The decompression output of $@ is not limited | brotliTest.cpp:24:5:24:33 | call to BrotliDecoderDecompressStream | BrotliDecoderDecompressStream |
| libarchiveTests.cpp:22:41:22:42 | *ar | main.cpp:7:33:7:36 | **argv | libarchiveTests.cpp:22:41:22:42 | *ar | The decompression output of $@ is not limited | libarchiveTests.cpp:22:17:22:39 | call to archive_read_data_block | archive_read_data_block |
| minizipTest.cpp:17:52:17:67 | *access to array | main.cpp:7:33:7:36 | **argv | minizipTest.cpp:17:52:17:67 | *access to array | The decompression output of $@ is not limited | minizipTest.cpp:17:22:17:38 | call to mz_zip_entry_read | mz_zip_entry_read |
| minizipTest.cpp:26:30:26:39 | **zip_reader | main.cpp:7:33:7:36 | **argv | minizipTest.cpp:26:30:26:39 | **zip_reader | The decompression output of $@ is not limited | minizipTest.cpp:26:5:26:28 | call to mz_zip_reader_entry_save | mz_zip_reader_entry_save |
| minizipTest.cpp:26:30:26:39 | *zip_reader | main.cpp:7:33:7:36 | **argv | minizipTest.cpp:26:30:26:39 | *zip_reader | The decompression output of $@ is not limited | minizipTest.cpp:26:5:26:28 | call to mz_zip_reader_entry_save | mz_zip_reader_entry_save |
| minizipTest.cpp:28:13:28:19 | *access to array | main.cpp:7:33:7:36 | **argv | minizipTest.cpp:28:13:28:19 | *access to array | The decompression output of $@ is not limited | minizipTest.cpp:28:5:28:11 | call to UnzOpen | UnzOpen |
| zlibTest.cpp:25:13:25:22 | & ... | main.cpp:7:33:7:36 | **argv | zlibTest.cpp:25:13:25:22 | & ... | The decompression output of $@ is not limited | zlibTest.cpp:25:5:25:11 | call to inflate | inflate |
| zlibTest.cpp:41:20:41:26 | inFileZ | main.cpp:7:33:7:36 | **argv | zlibTest.cpp:41:20:41:26 | inFileZ | The decompression output of $@ is not limited | zlibTest.cpp:41:13:41:18 | call to gzread | gzread |
| zlibTest.cpp:51:38:51:44 | inFileZ | main.cpp:7:33:7:36 | **argv | zlibTest.cpp:51:38:51:44 | inFileZ | The decompression output of $@ is not limited | zlibTest.cpp:51:14:51:20 | call to gzfread | gzfread |
| zlibTest.cpp:62:25:62:31 | inFileZ | main.cpp:7:33:7:36 | **argv | zlibTest.cpp:62:25:62:31 | inFileZ | The decompression output of $@ is not limited | zlibTest.cpp:62:18:62:23 | call to gzgets | gzgets |
| zlibTest.cpp:77:45:77:59 | *input | main.cpp:7:33:7:36 | **argv | zlibTest.cpp:77:45:77:59 | *input | The decompression output of $@ is not limited | zlibTest.cpp:77:5:77:14 | call to uncompress | uncompress |
| zstdTest.cpp:39:69:39:74 | & ... | main.cpp:7:33:7:36 | **argv | zstdTest.cpp:39:69:39:74 | & ... | The decompression output of $@ is not limited | zstdTest.cpp:39:32:39:52 | call to ZSTD_decompressStream | ZSTD_decompressStream |

View File

@@ -0,0 +1 @@
experimental/Security/CWE/CWE-409/DecompressionBombs.ql

View File

@@ -0,0 +1,26 @@
typedef long unsigned int size_t;
typedef unsigned char uint8_t;
enum BrotliDecoderResult {};
struct BrotliDecoderState;
BrotliDecoderResult BrotliDecoderDecompress(
size_t encoded_size, const uint8_t encoded_buffer[],
size_t *decoded_size, uint8_t decoded_buffer[]);
BrotliDecoderResult BrotliDecoderDecompressStream(
BrotliDecoderState *state, size_t *available_in, const uint8_t **next_in,
size_t *available_out, uint8_t **next_out, size_t *total_out);
void brotli_test(int argc, const char **argv) {
uint8_t output[1024];
size_t output_size = sizeof(output);
BrotliDecoderDecompress(1024, (uint8_t *) argv[2], &output_size, output); // BAD
size_t input_size = 1024;
const uint8_t *input_p = (const uint8_t*)argv[2];
uint8_t *output_p = output;
size_t out_size;
BrotliDecoderDecompressStream(0, &input_size, &input_p, &output_size, // BAD
&output_p, &out_size);
}

View File

@@ -0,0 +1,42 @@
#define ARCHIVE_EOF 1
#define ARCHIVE_OK 0
#define ARCHIVE_WARN (-20)
struct archive;
struct archive_entry;
typedef int size_t;
typedef int la_int64_t;
archive *archive_read_new();
int archive_read_open_filename(archive *pArchive, const char *filename, int i);
int archive_read_next_header(archive *a, archive_entry **entry);
int archive_entry_size(archive_entry *pEntry);
int archive_read_data_block(archive *pArchive, const void **pVoid, size_t *pInt, la_int64_t *pInt1);
static int read_data(archive *ar) {
for (;;) {
const void *buff;
size_t size;
la_int64_t offset;
int r = archive_read_data_block(ar, &buff, &size, &offset); // BAD
if (r == ARCHIVE_EOF)
return ARCHIVE_OK;
if (r < ARCHIVE_OK)
return r;
}
}
void libarchive_test(int argc, const char **argv) {
archive *a = archive_read_new();
archive_entry *entry;
archive_read_open_filename(a, argv[1], 10240);
for (;;) {
archive_read_next_header(a, &entry);
if (archive_entry_size(entry) > 0) {
if (read_data(a) < ARCHIVE_WARN)
break;
}
}
}

View File

@@ -0,0 +1,14 @@
void brotli_test(int argc, const char **argv);
void libarchive_test(int argc, const char **argv);
void minizip_test(int argc, const char **argv);
void zlib_test(int argc, const char **argv);
void zstd_test(int argc, const char **argv);
int main(int argc, const char **argv) {
brotli_test(argc, argv);
libarchive_test(argc, argv);
minizip_test(argc, argv);
zlib_test(argc, argv);
zstd_test(argc, argv);
return 0;
}

View File

@@ -0,0 +1,29 @@
typedef signed int int32_t;
void *mz_zip_reader_create();
int32_t mz_zip_reader_open_file(void *handle, const char *path);
int32_t mz_zip_reader_goto_first_entry(void *pVoid);
int32_t mz_zip_reader_entry_save(void *pVoid, int stream, int write);
int32_t mz_zip_entry_read(void *pVoid, void *buf, int32_t i);
void UnzOpen(const char *string);
void *mz_zip_create();
void minizip_test(int argc, const char **argv) {
void *zip_handle = mz_zip_create();
int32_t bytes_read;
char buf[4096];
while(true) {
bytes_read = mz_zip_entry_read(zip_handle, (char *) argv[1], sizeof(buf)); // BAD
if (bytes_read <= 0) {
break;
}
}
void *zip_reader = mz_zip_reader_create();
mz_zip_reader_open_file(zip_reader, argv[1]);
mz_zip_reader_goto_first_entry(zip_reader);
mz_zip_reader_entry_save(zip_reader, 0, 0); // BAD
UnzOpen(argv[3]); // BAD
}

View File

@@ -0,0 +1,86 @@
typedef unsigned char Bytef;
typedef unsigned long uLong;
typedef uLong uLongf;
typedef unsigned int uInt;
struct z_stream {
Bytef *next_in;
Bytef *next_out;
uInt avail_out;
};
void inflateInit(z_stream *infstream);
void inflate(z_stream *infstream, int i);
void inflateEnd(z_stream *infstream);
void UnsafeInflate(char *input) {
unsigned char output[1024];
z_stream infstream;
infstream.next_in = (Bytef *) input; // input char array
infstream.avail_out = sizeof(output); // size of output
infstream.next_out = output; // output char array
inflateInit(&infstream);
inflate(&infstream, 0); // BAD
}
struct gzFile {
};
gzFile gzopen(char *str, const char *rb);
unsigned int gzread(gzFile gz_file, unsigned char *str, int i);
bool gzfread(char *str, int i, int i1, gzFile gz_file);
char *gzgets(gzFile gz_file, char *buffer, int i);
void UnsafeGzread(char *fileName) {
gzFile inFileZ = gzopen(fileName, "rb");
unsigned char unzipBuffer[8192];
while (true) {
if (gzread(inFileZ, unzipBuffer, 8192) <= 0) { // BAD
break;
}
}
}
void UnsafeGzfread(char *fileName) {
gzFile inFileZ = gzopen(fileName, "rb");
while (true) {
char buffer[1000];
if (!gzfread(buffer, 999, 1, inFileZ)) { // BAD
break;
}
}
}
void UnsafeGzgets(char *fileName) {
gzFile inFileZ = gzopen(fileName, "rb");
char *buffer = new char[4000000000];
char *result;
while (true) {
result = gzgets(inFileZ, buffer, 1000000000); // BAD
if (result == nullptr) {
break;
}
}
}
int uncompress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen);
void InflateString(char *input) {
unsigned char output[1024];
uLong source_length = 500;
uLong destination_length = sizeof(output);
uncompress(output, &destination_length, (Bytef *) input, source_length); // BAD
}
void zlib_test(int argc, char **argv) {
UnsafeGzfread(argv[2]);
UnsafeGzgets(argv[2]);
UnsafeInflate(argv[2]);
UnsafeGzread(argv[2]);
InflateString(argv[2]);
}

View File

@@ -0,0 +1,43 @@
typedef long unsigned int size_t;
struct FILE;
FILE *fopen_orDie(const char *filename, const char *instruction);
size_t fread_orDie(void *const pVoid, const size_t read, FILE *const pFile);
void *const malloc_orDie(const size_t size);
struct ZSTD_DCtx;
typedef struct ZSTD_inBuffer_s {
const void *src;
size_t size;
size_t pos;
} ZSTD_inBuffer;
typedef struct ZSTD_outBuffer_s {
void *dst;
size_t size;
size_t pos;
} ZSTD_outBuffer;
const size_t ZSTD_DStreamInSize();
const size_t ZSTD_DStreamOutSize();
ZSTD_DCtx *const ZSTD_createDCtx();
const size_t ZSTD_decompressStream(ZSTD_DCtx *const pCtx, ZSTD_outBuffer *pS, ZSTD_inBuffer *pS1);
void CHECK_ZSTD(const size_t ret);
void zstd_test(int argc, const char **argv) {
FILE *const fin = fopen_orDie(argv[1], "rb");
size_t const buffInSize = ZSTD_DStreamInSize();
void *const buffIn = malloc_orDie(buffInSize);
size_t const buffOutSize = ZSTD_DStreamOutSize();
void *const buffOut = malloc_orDie(buffOutSize);
ZSTD_DCtx *const dctx = ZSTD_createDCtx();
size_t read;
while ((read = fread_orDie(buffIn, buffInSize, fin))) {
ZSTD_inBuffer input = {buffIn, read, 0};
while (input.pos < input.size) {
ZSTD_outBuffer output = {buffOut, buffOutSize, 0};
size_t const ret = ZSTD_decompressStream(dctx, &output, &input); // BAD
CHECK_ZSTD(ret);
}
}
}

View File

@@ -5,6 +5,5 @@
| main1.cpp:7:1:7:26 | #include "defines_issue.h" | Include | defines_issue.h | 1 |
| main2.cpp:3:1:3:19 | #include "common.h" | Include | common.h | 1 |
| main2.cpp:7:1:7:26 | #include "defines_issue.h" | Include | defines_issue.h | 1 |
| nameclash.h:3:1:3:27 | #include_next "nameclash.h" | IncludeNext | nameclash.h | 1 |
| nameclash.h:3:1:3:27 | #include_next "nameclash.h" | IncludeNext | subdir1/nameclash.h | 1 |
| nameclash.h:3:1:3:27 | #include_next "nameclash.h" | IncludeNext | subdir2/nameclash.h | 1 |

View File

@@ -1,4 +1,4 @@
// semmle-extractor-options: --clang --clang_version 180000
// semmle-extractor-options: --clang --edg --clang_version --edg 190000
struct S {
void f() {}
@@ -108,3 +108,16 @@ bool b_is_unbounded_array2 = __is_unbounded_array(int[42]);
bool b_is_referenceable1 = __is_referenceable(int);
bool b_is_referenceable2 = __is_referenceable(void);
bool b_is_trivially_equality_comparable1 = __is_trivially_equality_comparable(int);
bool b_is_trivially_equality_comparable2 = __is_trivially_equality_comparable(void);
enum class E {
a, b
};
bool b_is_scoped_enum1 = __is_scoped_enum(E);
bool b_is_scoped_enum2 = __is_scoped_enum(int);
bool b_is_trivially_relocatable1 = __is_trivially_relocatable(int);
bool b_is_trivially_relocatable2 = __is_trivially_relocatable(void);

View File

@@ -153,7 +153,21 @@
| clang.cpp:109:28:109:50 | int | | <none> |
| clang.cpp:110:28:110:51 | __is_referenceable | void | 0 |
| clang.cpp:110:28:110:51 | void | | <none> |
| clang.cpp:112:44:112:82 | __is_trivially_equality_comparable | int | 1 |
| clang.cpp:112:44:112:82 | int | | <none> |
| clang.cpp:113:44:113:83 | __is_trivially_equality_comparable | void | 0 |
| clang.cpp:113:44:113:83 | void | | <none> |
| clang.cpp:119:26:119:44 | E | | <none> |
| clang.cpp:119:26:119:44 | __is_scoped_enum | E | 1 |
| clang.cpp:120:26:120:46 | __is_scoped_enum | int | 0 |
| clang.cpp:120:26:120:46 | int | | <none> |
| clang.cpp:122:36:122:66 | __is_trivially_relocatable | int | 1 |
| clang.cpp:122:36:122:66 | int | | <none> |
| clang.cpp:123:36:123:67 | __is_trivially_relocatable | void | 0 |
| clang.cpp:123:36:123:67 | void | | <none> |
| file://:0:0:0:0 | 0 | | 0 |
| file://:0:0:0:0 | 0 | | 0 |
| file://:0:0:0:0 | 1 | | 1 |
| file://:0:0:0:0 | 1 | | 1 |
| file://:0:0:0:0 | 2 | | 2 |
| gcc.cpp:3:25:3:25 | 8 | | 8 |

View File

@@ -0,0 +1,458 @@
#-----| [CopyAssignmentOperator] __va_list_tag& __va_list_tag::operator=(__va_list_tag const&)
#-----| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const __va_list_tag &
#-----| [MoveAssignmentOperator] __va_list_tag& __va_list_tag::operator=(__va_list_tag&&)
#-----| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] __va_list_tag &&
generic.c:
# 3| [FormattingFunction,TopLevelFunction] int printf(char const*)
# 3| <params>:
# 3| getParameter(0): [Parameter] format
# 3| Type = [PointerType] const char *
# 14| [TopLevelFunction] int main()
# 14| <params>:
# 15| getEntryPoint(): [BlockStmt] { ... }
# 16| getStmt(0): [DeclStmt] declaration
# 16| getDeclarationEntry(0): [VariableDeclarationEntry] definition of i
# 16| Type = [IntType] int
# 17| getStmt(1): [DeclStmt] declaration
# 17| getDeclarationEntry(0): [VariableDeclarationEntry] definition of m
# 17| Type = [CTypedefType] MYINT
# 18| getStmt(2): [DeclStmt] declaration
# 18| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s
# 18| Type = [PointerType] const char *
# 19| getStmt(3): [DeclStmt] declaration
# 19| getDeclarationEntry(0): [VariableDeclarationEntry] definition of f
# 19| Type = [PointerType] float ***
# 21| getStmt(4): [ExprStmt] ExprStmt
# 21| getExpr(): [FormattingFunctionCall,FunctionCall] call to printf
# 21| Type = [IntType] int
# 21| ValueCategory = prvalue
# 21| getArgument(0): i is %s\n
# 21| Type = [ArrayType] char[9]
# 21| Value = [StringLiteral] "i is %s\n"
# 21| ValueCategory = lvalue
# 21| getArgument(1): int
# 21| Type = [ArrayType] char[4]
# 21| Value = [StringLiteral] "int"
# 21| ValueCategory = lvalue
# 21| getArgument(0).getFullyConverted(): [CStyleCast] (const char *)...
# 21| Conversion = [PointerConversion] pointer conversion
# 21| Type = [PointerType] const char *
# 21| ValueCategory = prvalue
# 21| getExpr(): [ArrayToPointerConversion] array to pointer conversion
# 21| Type = [CharPointerType] char *
# 21| ValueCategory = prvalue
# 21| getArgument(1).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 21| Type = [CharPointerType] char *
# 21| ValueCategory = prvalue
# 21| getExpr(): [C11GenericExpr] _Generic
# 21| Type = [ArrayType] char[4]
# 21| Value = [C11GenericExpr] int
# 21| ValueCategory = lvalue
# 21| getControllingExpr(): [VariableAccess] i
# 21| Type = [IntType] int
# 21| ValueCategory = prvalue(load)
# 21| getAssociationType(0): [TypeName] int
# 21| Type = [IntType] int
# 21| ValueCategory = prvalue
# 21| getAssociationExpr(0): [ReuseExpr] reuse of int
# 21| Type = [ArrayType] char[4]
# 21| ValueCategory = lvalue
# 21| getAssociationType(1): [TypeName] const char *
# 21| Type = [PointerType] const char *
# 21| ValueCategory = prvalue
# 21| getAssociationExpr(1): string
# 21| Type = [ArrayType] char[7]
# 21| Value = [StringLiteral] "string"
# 21| ValueCategory = lvalue
# 21| getAssociationType(2): [TypeName] void
# 21| Type = [VoidType] void
# 21| ValueCategory = prvalue
# 21| getAssociationExpr(2): unknown
# 21| Type = [ArrayType] char[8]
# 21| Value = [StringLiteral] "unknown"
# 21| ValueCategory = lvalue
# 21| getControllingExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 21| Type = [IntType] int
# 21| ValueCategory = prvalue(load)
# 22| getStmt(5): [ExprStmt] ExprStmt
# 22| getExpr(): [FormattingFunctionCall,FunctionCall] call to printf
# 22| Type = [IntType] int
# 22| ValueCategory = prvalue
# 22| getArgument(0): c is %s\n
# 22| Type = [ArrayType] char[9]
# 22| Value = [StringLiteral] "c is %s\n"
# 22| ValueCategory = lvalue
# 22| getArgument(1): int
# 22| Type = [ArrayType] char[4]
# 22| Value = [StringLiteral] "int"
# 22| ValueCategory = lvalue
# 22| getArgument(0).getFullyConverted(): [CStyleCast] (const char *)...
# 22| Conversion = [PointerConversion] pointer conversion
# 22| Type = [PointerType] const char *
# 22| ValueCategory = prvalue
# 22| getExpr(): [ArrayToPointerConversion] array to pointer conversion
# 22| Type = [CharPointerType] char *
# 22| ValueCategory = prvalue
# 22| getArgument(1).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 22| Type = [CharPointerType] char *
# 22| ValueCategory = prvalue
# 22| getExpr(): [C11GenericExpr] _Generic
# 22| Type = [ArrayType] char[4]
# 22| Value = [C11GenericExpr] int
# 22| ValueCategory = lvalue
# 22| getControllingExpr(): [VariableAccess] m
# 22| Type = [CTypedefType] MYINT
# 22| ValueCategory = prvalue(load)
# 22| getAssociationType(0): [TypeName] int
# 22| Type = [IntType] int
# 22| ValueCategory = prvalue
# 22| getAssociationExpr(0): [ReuseExpr] reuse of int
# 22| Type = [ArrayType] char[4]
# 22| ValueCategory = lvalue
# 22| getAssociationType(1): [TypeName] const char *
# 22| Type = [PointerType] const char *
# 22| ValueCategory = prvalue
# 22| getAssociationExpr(1): string
# 22| Type = [ArrayType] char[7]
# 22| Value = [StringLiteral] "string"
# 22| ValueCategory = lvalue
# 22| getAssociationType(2): [TypeName] void
# 22| Type = [VoidType] void
# 22| ValueCategory = prvalue
# 22| getAssociationExpr(2): unknown
# 22| Type = [ArrayType] char[8]
# 22| Value = [StringLiteral] "unknown"
# 22| ValueCategory = lvalue
# 22| getControllingExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 22| Type = [CTypedefType] MYINT
# 22| ValueCategory = prvalue(load)
# 23| getStmt(6): [ExprStmt] ExprStmt
# 23| getExpr(): [FormattingFunctionCall,FunctionCall] call to printf
# 23| Type = [IntType] int
# 23| ValueCategory = prvalue
# 23| getArgument(0): s is %s\n
# 23| Type = [ArrayType] char[9]
# 23| Value = [StringLiteral] "s is %s\n"
# 23| ValueCategory = lvalue
# 23| getArgument(1): string
# 23| Type = [ArrayType] char[7]
# 23| Value = [StringLiteral] "string"
# 23| ValueCategory = lvalue
# 23| getArgument(0).getFullyConverted(): [CStyleCast] (const char *)...
# 23| Conversion = [PointerConversion] pointer conversion
# 23| Type = [PointerType] const char *
# 23| ValueCategory = prvalue
# 23| getExpr(): [ArrayToPointerConversion] array to pointer conversion
# 23| Type = [CharPointerType] char *
# 23| ValueCategory = prvalue
# 23| getArgument(1).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 23| Type = [CharPointerType] char *
# 23| ValueCategory = prvalue
# 23| getExpr(): [C11GenericExpr] _Generic
# 23| Type = [ArrayType] char[7]
# 23| Value = [C11GenericExpr] string
# 23| ValueCategory = lvalue
# 23| getControllingExpr(): [VariableAccess] s
# 23| Type = [PointerType] const char *
# 23| ValueCategory = prvalue(load)
# 23| getAssociationType(0): [TypeName] int
# 23| Type = [IntType] int
# 23| ValueCategory = prvalue
# 23| getAssociationExpr(0): int
# 23| Type = [ArrayType] char[4]
# 23| Value = [StringLiteral] "int"
# 23| ValueCategory = lvalue
# 23| getAssociationType(1): [TypeName] const char *
# 23| Type = [PointerType] const char *
# 23| ValueCategory = prvalue
# 23| getAssociationExpr(1): [ReuseExpr] reuse of string
# 23| Type = [ArrayType] char[7]
# 23| ValueCategory = lvalue
# 23| getAssociationType(2): [TypeName] void
# 23| Type = [VoidType] void
# 23| ValueCategory = prvalue
# 23| getAssociationExpr(2): unknown
# 23| Type = [ArrayType] char[8]
# 23| Value = [StringLiteral] "unknown"
# 23| ValueCategory = lvalue
# 23| getControllingExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 23| Type = [PointerType] const char *
# 23| ValueCategory = prvalue(load)
# 24| getStmt(7): [ExprStmt] ExprStmt
# 24| getExpr(): [FormattingFunctionCall,FunctionCall] call to printf
# 24| Type = [IntType] int
# 24| ValueCategory = prvalue
# 24| getArgument(0): f is %s\n
# 24| Type = [ArrayType] char[9]
# 24| Value = [StringLiteral] "f is %s\n"
# 24| ValueCategory = lvalue
# 24| getArgument(1): unknown
# 24| Type = [ArrayType] char[8]
# 24| Value = [StringLiteral] "unknown"
# 24| ValueCategory = lvalue
# 24| getArgument(0).getFullyConverted(): [CStyleCast] (const char *)...
# 24| Conversion = [PointerConversion] pointer conversion
# 24| Type = [PointerType] const char *
# 24| ValueCategory = prvalue
# 24| getExpr(): [ArrayToPointerConversion] array to pointer conversion
# 24| Type = [CharPointerType] char *
# 24| ValueCategory = prvalue
# 24| getArgument(1).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 24| Type = [CharPointerType] char *
# 24| ValueCategory = prvalue
# 24| getExpr(): [C11GenericExpr] _Generic
# 24| Type = [ArrayType] char[8]
# 24| Value = [C11GenericExpr] unknown
# 24| ValueCategory = lvalue
# 24| getControllingExpr(): [VariableAccess] f
# 24| Type = [PointerType] float ***
# 24| ValueCategory = prvalue(load)
# 24| getAssociationType(0): [TypeName] int
# 24| Type = [IntType] int
# 24| ValueCategory = prvalue
# 24| getAssociationExpr(0): int
# 24| Type = [ArrayType] char[4]
# 24| Value = [StringLiteral] "int"
# 24| ValueCategory = lvalue
# 24| getAssociationType(1): [TypeName] const char *
# 24| Type = [PointerType] const char *
# 24| ValueCategory = prvalue
# 24| getAssociationExpr(1): string
# 24| Type = [ArrayType] char[7]
# 24| Value = [StringLiteral] "string"
# 24| ValueCategory = lvalue
# 24| getAssociationType(2): [TypeName] void
# 24| Type = [VoidType] void
# 24| ValueCategory = prvalue
# 24| getAssociationExpr(2): [ReuseExpr] reuse of unknown
# 24| Type = [ArrayType] char[8]
# 24| ValueCategory = lvalue
# 24| getControllingExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 24| Type = [PointerType] float ***
# 24| ValueCategory = prvalue(load)
# 25| getStmt(8): [ReturnStmt] return ...
#-----| getExpr(): [Literal] 0
#-----| Type = [IntType] int
#-----| Value = [Literal] 0
#-----| ValueCategory = prvalue
generic.cpp:
# 4| [FormattingFunction,TopLevelFunction] int printf(char const*)
# 4| <params>:
# 4| getParameter(0): [Parameter] format
# 4| Type = [PointerType] const char *
# 15| [TopLevelFunction] int main()
# 15| <params>:
# 16| getEntryPoint(): [BlockStmt] { ... }
# 17| getStmt(0): [DeclStmt] declaration
# 17| getDeclarationEntry(0): [VariableDeclarationEntry] definition of i
# 17| Type = [IntType] int
# 18| getStmt(1): [DeclStmt] declaration
# 18| getDeclarationEntry(0): [VariableDeclarationEntry] definition of m
# 18| Type = [CTypedefType] MYINT
# 19| getStmt(2): [DeclStmt] declaration
# 19| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s
# 19| Type = [PointerType] const char *
# 20| getStmt(3): [DeclStmt] declaration
# 20| getDeclarationEntry(0): [VariableDeclarationEntry] definition of f
# 20| Type = [PointerType] float ***
# 22| getStmt(4): [ExprStmt] ExprStmt
# 22| getExpr(): [FormattingFunctionCall,FunctionCall] call to printf
# 22| Type = [IntType] int
# 22| ValueCategory = prvalue
# 22| getArgument(0): i is %s\n
# 22| Type = [ArrayType] const char[9]
# 22| Value = [StringLiteral] "i is %s\n"
# 22| ValueCategory = lvalue
# 22| getArgument(1): int
# 22| Type = [ArrayType] const char[4]
# 22| Value = [StringLiteral] "int"
# 22| ValueCategory = lvalue
# 22| getArgument(0).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 22| Type = [PointerType] const char *
# 22| ValueCategory = prvalue
# 22| getArgument(1).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 22| Type = [PointerType] const char *
# 22| ValueCategory = prvalue
# 22| getExpr(): [C11GenericExpr] _Generic
# 22| Type = [ArrayType] const char[4]
# 22| Value = [C11GenericExpr] int
# 22| ValueCategory = lvalue
# 22| getControllingExpr(): [VariableAccess] i
# 22| Type = [IntType] int
# 22| ValueCategory = lvalue
# 22| getAssociationType(0): [TypeName] int
# 22| Type = [IntType] int
# 22| ValueCategory = prvalue
# 22| getAssociationExpr(0): [ReuseExpr] reuse of int
# 22| Type = [ArrayType] const char[4]
# 22| ValueCategory = lvalue
# 22| getAssociationType(1): [TypeName] const char *
# 22| Type = [PointerType] const char *
# 22| ValueCategory = prvalue
# 22| getAssociationExpr(1): string
# 22| Type = [ArrayType] const char[7]
# 22| Value = [StringLiteral] "string"
# 22| ValueCategory = lvalue
# 22| getAssociationType(2): [TypeName] void
# 22| Type = [VoidType] void
# 22| ValueCategory = prvalue
# 22| getAssociationExpr(2): unknown
# 22| Type = [ArrayType] const char[8]
# 22| Value = [StringLiteral] "unknown"
# 22| ValueCategory = lvalue
# 22| getControllingExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 22| Type = [IntType] int
# 22| ValueCategory = lvalue
# 23| getStmt(5): [ExprStmt] ExprStmt
# 23| getExpr(): [FormattingFunctionCall,FunctionCall] call to printf
# 23| Type = [IntType] int
# 23| ValueCategory = prvalue
# 23| getArgument(0): c is %s\n
# 23| Type = [ArrayType] const char[9]
# 23| Value = [StringLiteral] "c is %s\n"
# 23| ValueCategory = lvalue
# 23| getArgument(1): int
# 23| Type = [ArrayType] const char[4]
# 23| Value = [StringLiteral] "int"
# 23| ValueCategory = lvalue
# 23| getArgument(0).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 23| Type = [PointerType] const char *
# 23| ValueCategory = prvalue
# 23| getArgument(1).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 23| Type = [PointerType] const char *
# 23| ValueCategory = prvalue
# 23| getExpr(): [C11GenericExpr] _Generic
# 23| Type = [ArrayType] const char[4]
# 23| Value = [C11GenericExpr] int
# 23| ValueCategory = lvalue
# 23| getControllingExpr(): [VariableAccess] m
# 23| Type = [CTypedefType] MYINT
# 23| ValueCategory = lvalue
# 23| getAssociationType(0): [TypeName] int
# 23| Type = [IntType] int
# 23| ValueCategory = prvalue
# 23| getAssociationExpr(0): [ReuseExpr] reuse of int
# 23| Type = [ArrayType] const char[4]
# 23| ValueCategory = lvalue
# 23| getAssociationType(1): [TypeName] const char *
# 23| Type = [PointerType] const char *
# 23| ValueCategory = prvalue
# 23| getAssociationExpr(1): string
# 23| Type = [ArrayType] const char[7]
# 23| Value = [StringLiteral] "string"
# 23| ValueCategory = lvalue
# 23| getAssociationType(2): [TypeName] void
# 23| Type = [VoidType] void
# 23| ValueCategory = prvalue
# 23| getAssociationExpr(2): unknown
# 23| Type = [ArrayType] const char[8]
# 23| Value = [StringLiteral] "unknown"
# 23| ValueCategory = lvalue
# 23| getControllingExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 23| Type = [CTypedefType] MYINT
# 23| ValueCategory = lvalue
# 24| getStmt(6): [ExprStmt] ExprStmt
# 24| getExpr(): [FormattingFunctionCall,FunctionCall] call to printf
# 24| Type = [IntType] int
# 24| ValueCategory = prvalue
# 24| getArgument(0): s is %s\n
# 24| Type = [ArrayType] const char[9]
# 24| Value = [StringLiteral] "s is %s\n"
# 24| ValueCategory = lvalue
# 24| getArgument(1): string
# 24| Type = [ArrayType] const char[7]
# 24| Value = [StringLiteral] "string"
# 24| ValueCategory = lvalue
# 24| getArgument(0).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 24| Type = [PointerType] const char *
# 24| ValueCategory = prvalue
# 24| getArgument(1).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 24| Type = [PointerType] const char *
# 24| ValueCategory = prvalue
# 24| getExpr(): [C11GenericExpr] _Generic
# 24| Type = [ArrayType] const char[7]
# 24| Value = [C11GenericExpr] string
# 24| ValueCategory = lvalue
# 24| getControllingExpr(): [VariableAccess] s
# 24| Type = [PointerType] const char *
# 24| ValueCategory = lvalue
# 24| getAssociationType(0): [TypeName] int
# 24| Type = [IntType] int
# 24| ValueCategory = prvalue
# 24| getAssociationExpr(0): int
# 24| Type = [ArrayType] const char[4]
# 24| Value = [StringLiteral] "int"
# 24| ValueCategory = lvalue
# 24| getAssociationType(1): [TypeName] const char *
# 24| Type = [PointerType] const char *
# 24| ValueCategory = prvalue
# 24| getAssociationExpr(1): [ReuseExpr] reuse of string
# 24| Type = [ArrayType] const char[7]
# 24| ValueCategory = lvalue
# 24| getAssociationType(2): [TypeName] void
# 24| Type = [VoidType] void
# 24| ValueCategory = prvalue
# 24| getAssociationExpr(2): unknown
# 24| Type = [ArrayType] const char[8]
# 24| Value = [StringLiteral] "unknown"
# 24| ValueCategory = lvalue
# 24| getControllingExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 24| Type = [PointerType] const char *
# 24| ValueCategory = lvalue
# 25| getStmt(7): [ExprStmt] ExprStmt
# 25| getExpr(): [FormattingFunctionCall,FunctionCall] call to printf
# 25| Type = [IntType] int
# 25| ValueCategory = prvalue
# 25| getArgument(0): f is %s\n
# 25| Type = [ArrayType] const char[9]
# 25| Value = [StringLiteral] "f is %s\n"
# 25| ValueCategory = lvalue
# 25| getArgument(1): unknown
# 25| Type = [ArrayType] const char[8]
# 25| Value = [StringLiteral] "unknown"
# 25| ValueCategory = lvalue
# 25| getArgument(0).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 25| Type = [PointerType] const char *
# 25| ValueCategory = prvalue
# 25| getArgument(1).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 25| Type = [PointerType] const char *
# 25| ValueCategory = prvalue
# 25| getExpr(): [C11GenericExpr] _Generic
# 25| Type = [ArrayType] const char[8]
# 25| Value = [C11GenericExpr] unknown
# 25| ValueCategory = lvalue
# 25| getControllingExpr(): [VariableAccess] f
# 25| Type = [PointerType] float ***
# 25| ValueCategory = lvalue
# 25| getAssociationType(0): [TypeName] int
# 25| Type = [IntType] int
# 25| ValueCategory = prvalue
# 25| getAssociationExpr(0): int
# 25| Type = [ArrayType] const char[4]
# 25| Value = [StringLiteral] "int"
# 25| ValueCategory = lvalue
# 25| getAssociationType(1): [TypeName] const char *
# 25| Type = [PointerType] const char *
# 25| ValueCategory = prvalue
# 25| getAssociationExpr(1): string
# 25| Type = [ArrayType] const char[7]
# 25| Value = [StringLiteral] "string"
# 25| ValueCategory = lvalue
# 25| getAssociationType(2): [TypeName] void
# 25| Type = [VoidType] void
# 25| ValueCategory = prvalue
# 25| getAssociationExpr(2): [ReuseExpr] reuse of unknown
# 25| Type = [ArrayType] const char[8]
# 25| ValueCategory = lvalue
# 25| getControllingExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 25| Type = [PointerType] float ***
# 25| ValueCategory = lvalue
# 26| getStmt(8): [ReturnStmt] return ...
#-----| getExpr(): [Literal] 0
#-----| Type = [IntType] int
#-----| Value = [Literal] 0
#-----| ValueCategory = prvalue

View File

@@ -0,0 +1 @@
semmle/code/cpp/PrintAST.ql

View File

@@ -0,0 +1,8 @@
| generic.c:21:22:21:32 | _Generic | generic.c:21:22:21:32 | describe(val) |
| generic.c:22:22:22:32 | _Generic | generic.c:22:22:22:32 | describe(val) |
| generic.c:23:22:23:32 | _Generic | generic.c:23:22:23:32 | describe(val) |
| generic.c:24:22:24:32 | _Generic | generic.c:24:22:24:32 | describe(val) |
| generic.cpp:22:22:22:32 | _Generic | generic.cpp:22:22:22:32 | describe(val) |
| generic.cpp:23:22:23:32 | _Generic | generic.cpp:23:22:23:32 | describe(val) |
| generic.cpp:24:22:24:32 | _Generic | generic.cpp:24:22:24:32 | describe(val) |
| generic.cpp:25:22:25:32 | _Generic | generic.cpp:25:22:25:32 | describe(val) |

View File

@@ -0,0 +1,5 @@
import cpp
from C11GenericExpr g, MacroInvocation m
where m.getAnExpandedElement() = g
select g, m

View File

@@ -33,7 +33,7 @@ argHasPostUpdate
| test.cpp:67:29:67:35 | source1 | ArgumentNode is missing PostUpdateNode. |
| test.cpp:813:19:813:35 | * ... | ArgumentNode is missing PostUpdateNode. |
| test.cpp:848:23:848:25 | rpx | ArgumentNode is missing PostUpdateNode. |
| test.cpp:1057:19:1057:21 | * ... | ArgumentNode is missing PostUpdateNode. |
| test.cpp:1093:19:1093:21 | * ... | ArgumentNode is missing PostUpdateNode. |
postWithInFlow
| BarrierGuard.cpp:49:6:49:6 | x [post update] | PostUpdateNode should not be the target of local flow. |
| BarrierGuard.cpp:60:7:60:7 | x [post update] | PostUpdateNode should not be the target of local flow. |
@@ -167,15 +167,17 @@ postWithInFlow
| test.cpp:932:5:932:19 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:932:6:932:19 | global_pointer [inner post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:1045:9:1045:11 | ref arg buf | PostUpdateNode should not be the target of local flow. |
| test.cpp:1051:5:1051:11 | content [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:1052:9:1052:9 | a [inner post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:1056:5:1056:7 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:1056:6:1056:7 | pp [inner post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:1062:53:1062:53 | p [inner post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:1072:3:1072:4 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:1072:4:1072:4 | p [inner post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:1073:3:1073:4 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:1073:4:1073:4 | p [inner post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:1066:5:1066:5 | i [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:1069:5:1069:5 | i [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:1087:5:1087:11 | content [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:1088:9:1088:9 | a [inner post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:1092:5:1092:7 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:1092:6:1092:7 | pp [inner post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:1098:53:1098:53 | p [inner post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:1108:3:1108:4 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:1108:4:1108:4 | p [inner post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:1109:3:1109:4 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:1109:4:1109:4 | p [inner post update] | PostUpdateNode should not be the target of local flow. |
viableImplInCallContextTooLarge
uniqueParameterNodeAtPosition
uniqueParameterNodePosition

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