merge upstream v2.22.2

This commit is contained in:
Josh Brown
2025-08-11 12:45:33 -07:00
1023 changed files with 94756 additions and 28226 deletions

View File

@@ -2,6 +2,9 @@ language: cpp
strategy: dca
destination: cpp/ql/lib/ext/generated
targets:
- name: glibc
with-sinks: false
with-sources: false
- name: zlib
with-sinks: false
with-sources: false

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: Uncomment cases in dbscheme
compatibility: full

View File

@@ -0,0 +1,9 @@
class Function extends @function {
string toString() { none() }
}
from Function f, string n, int k, int new_k
where
functions(f, n, k) and
if builtin_functions(f) then new_k = 6 else new_k = k
select f, n, new_k

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,4 @@
description: Move builtin function identification to its own table
compatibility: full
functions.rel: run functions.qlo
builtin_functions.rel: delete

View File

@@ -4,4 +4,3 @@
int main() {
return ONE + TWO + THREE + FOUR;
}
// semmle-extractor-options: --clang -include-pch ${testdir}/clang-pch.testproj/a.pch -Iextra_dummy_path

View File

@@ -1,3 +1,20 @@
## 5.3.0
### Deprecated APIs
* The `UnknownDefaultLocation`, `UnknownExprLocation`, and `UnknownStmtLocation` classes have been deprecated. Use `UnknownLocation` instead.
### New Features
* Added a `isFinalValueOfParameter` predicate to `DataFlow::Node` which holds when a dataflow node represents the final value of an output parameter of a function.
### Minor Analysis Improvements
* The `FunctionWithWrappers` library (`semmle.code.cpp.security.FunctionWithWrappers`) no longer considers calls through function pointers as wrapper functions.
* The analysis of C/C++ code targeting 64-bit Arm platforms has been improved. This includes support for the Arm-specific builtin functions, support for the `arm_neon.h` header and Neon vector types, and support for the `fp8` scalar type. The `arm_sve.h` header and scalable vectors are only partially supported at this point.
* Added support for `__fp16 _Complex` and `__bf16 _Complex` types
* Added `sql-injection` sink models for the Oracle Call Interface (OCI) database library functions `OCIStmtPrepare` and `OCIStmtPrepare2`.
## 5.2.0
### Deprecated APIs

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* Added `sql-injection` sink models for the Oracle Call Interface (OCI) database library functions `OCIStmtPrepare` and `OCIStmtPrepare2`.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* The analysis of C/C++ code targeting 64-bit Arm platforms has been improved. This includes support for the Arm-specific builtin functions, support for the `arm_neon.h` header and Neon vector types, and support for the `fp8` scalar type. The `arm_sve.h` header and scalable vectors are only partially supported at this point.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* Added support for `__fp16 _Complex` and `__bf16 _Complex` types

View File

@@ -1,4 +0,0 @@
---
category: deprecated
---
* The `UnknownDefaultLocation`, `UnknownExprLocation`, and `UnknownStmtLocation` classes have been deprecated. Use `UnknownLocation` instead.

View File

@@ -0,0 +1,16 @@
## 5.3.0
### Deprecated APIs
* The `UnknownDefaultLocation`, `UnknownExprLocation`, and `UnknownStmtLocation` classes have been deprecated. Use `UnknownLocation` instead.
### New Features
* Added a `isFinalValueOfParameter` predicate to `DataFlow::Node` which holds when a dataflow node represents the final value of an output parameter of a function.
### Minor Analysis Improvements
* The `FunctionWithWrappers` library (`semmle.code.cpp.security.FunctionWithWrappers`) no longer considers calls through function pointers as wrapper functions.
* The analysis of C/C++ code targeting 64-bit Arm platforms has been improved. This includes support for the Arm-specific builtin functions, support for the `arm_neon.h` header and Neon vector types, and support for the `fp8` scalar type. The `arm_sve.h` header and scalable vectors are only partially supported at this point.
* Added support for `__fp16 _Complex` and `__bf16 _Complex` types
* Added `sql-injection` sink models for the Oracle Call Interface (OCI) database library functions `OCIStmtPrepare` and `OCIStmtPrepare2`.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 5.2.0
lastReleaseVersion: 5.3.0

View File

@@ -32,4 +32,8 @@ extensions:
- ["", "", False, "CommandLineToArgvA", "", "", "Argument[*0]", "ReturnValue[**]", "taint", "manual"]
- ["", "", False, "CommandLineToArgvW", "", "", "Argument[*0]", "ReturnValue[**]", "taint", "manual"]
# fileapi.h
- ["", "", False, "ReadFileEx", "", "", "Argument[*3].Field[@hEvent]", "Argument[4].Parameter[*2].Field[@hEvent]", "value", "manual"]
- ["", "", False, "ReadFileEx", "", "", "Argument[*3].Field[@hEvent]", "Argument[4].Parameter[*2].Field[@hEvent]", "value", "manual"]
# processthreadsapi.h
- ["", "", False, "CreateThread", "", "", "Argument[@3]", "Argument[2].Parameter[@0]", "value", "manual"]
- ["", "", False, "CreateRemoteThread", "", "", "Argument[@4]", "Argument[3].Parameter[@0]", "value", "manual"]
- ["", "", False, "CreateRemoteThreadEx", "", "", "Argument[@4]", "Argument[3].Parameter[@0]", "value", "manual"]

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,6 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: summaryModel
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
- ["", "", False, "pthread_create", "", "", "Argument[@3]", "Argument[2].Parameter[@0]", "value", "manual"]

View File

@@ -0,0 +1,11 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: summaryModel
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
- ["std", "thread", True, "thread", "", "", "Argument[*@1]", "Argument[0].Parameter[@0]", "value", "manual"]
- ["std", "thread", True, "thread", "", "", "Argument[*@2]", "Argument[0].Parameter[@1]", "value", "manual"]
- ["std", "thread", True, "thread", "", "", "Argument[*@3]", "Argument[0].Parameter[@2]", "value", "manual"]
- ["std", "thread", True, "thread", "", "", "Argument[*@4]", "Argument[0].Parameter[@3]", "value", "manual"]
- ["std", "thread", True, "thread", "", "", "Argument[*@5]", "Argument[0].Parameter[@4]", "value", "manual"]

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-all
version: 5.2.1-dev
version: 5.3.0
groups: cpp
dbscheme: semmlecode.cpp.dbscheme
extractor: cpp

View File

@@ -57,7 +57,9 @@ class RequiresExpr extends Expr, @requires_expr {
/**
* A C++ requirement in a requires expression.
*/
class RequirementExpr extends Expr { }
class RequirementExpr extends Expr {
RequirementExpr() { this.getParent() instanceof RequiresExpr }
}
/**
* A C++ simple requirement in a requires expression.
@@ -70,7 +72,6 @@ class RequirementExpr extends Expr { }
*/
class SimpleRequirementExpr extends RequirementExpr {
SimpleRequirementExpr() {
this.getParent() instanceof RequiresExpr and
not this instanceof TypeRequirementExpr and
not this instanceof CompoundRequirementExpr and
not this instanceof NestedRequirementExpr
@@ -89,8 +90,6 @@ class SimpleRequirementExpr extends RequirementExpr {
* with `T` a template parameter, then `typename T::a_field;` is a type requirement.
*/
class TypeRequirementExpr extends RequirementExpr, TypeName {
TypeRequirementExpr() { this.getParent() instanceof RequiresExpr }
override string getAPrimaryQlClass() { result = "TypeRequirementExpr" }
}
@@ -140,7 +139,7 @@ class CompoundRequirementExpr extends RequirementExpr, @compound_requirement {
* with `T` a template parameter, then `requires std::is_same<T, int>::value;` is
* a nested requirement.
*/
class NestedRequirementExpr extends Expr, @nested_requirement {
class NestedRequirementExpr extends RequirementExpr, @nested_requirement {
override string toString() { result = "requires ..." }
override string getAPrimaryQlClass() { result = "NestedRequirementExpr" }
@@ -163,7 +162,7 @@ class NestedRequirementExpr extends Expr, @nested_requirement {
* then `C<int, 1>` is a concept id expression that refers to
* the concept `C`.
*/
class ConceptIdExpr extends RequirementExpr, @concept_id {
class ConceptIdExpr extends Expr, @concept_id {
override string toString() {
result = this.getConcept().getName() + "<...>"
or

View File

@@ -282,9 +282,12 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
* definition, if possible.)
*/
override Location getLocation() {
if exists(this.getDefinition())
then result = this.getDefinitionLocation()
else result = this.getADeclarationLocation()
if this instanceof BuiltInFunction
then result instanceof UnknownLocation // a dummy location for the built-in function
else
if exists(this.getDefinition())
then result = this.getDefinitionLocation()
else result = this.getADeclarationLocation()
}
/** Gets a child declaration of this function. */
@@ -896,17 +899,9 @@ class FunctionTemplateSpecialization extends Function {
* A GCC built-in function. For example: `__builtin___memcpy_chk`.
*/
class BuiltInFunction extends Function {
BuiltInFunction() { functions(underlyingElement(this), _, 6) }
/** Gets a dummy location for the built-in function. */
override Location getLocation() {
suppressUnusedThis(this) and
result instanceof UnknownLocation
}
BuiltInFunction() { builtin_functions(underlyingElement(this)) }
}
private predicate suppressUnusedThis(Function f) { any() }
/**
* A C++ user-defined literal [N4140 13.5.8].
*/

View File

@@ -1382,16 +1382,89 @@ predicate neverSkipInPathGraph(Node n) {
exists(n.asIndirectDefinition())
}
class LambdaCallKind = Unit;
private newtype TLambdaCallKind =
TFunctionPointer() or
TFunctor()
class LambdaCallKind extends TLambdaCallKind {
predicate isFunctionPointer() { this = TFunctionPointer() }
predicate isFunctor() { this = TFunctor() }
string toString() {
this.isFunctionPointer() and
result = "Function pointer kind"
or
this.isFunctor() and
result = "Functor kind"
}
}
private class ConstructorCallInstruction extends CallInstruction {
Cpp::Class constructedType;
ConstructorCallInstruction() {
this.getStaticCallTarget().(Cpp::Constructor).getDeclaringType() = constructedType
}
Cpp::Class getConstructedType() { result = constructedType }
}
private class OperatorCall extends Cpp::MemberFunction {
OperatorCall() { this.hasName("operator()") }
}
private predicate isFunctorCreationWithoutConstructor(Node creation, OperatorCall operator) {
exists(UninitializedInstruction init, Instruction dest |
// A construction of an object with no constructor. In this case we use
// the `UninitializedInstruction` as the creation node.
init = creation.asInstruction() and
dest = init.getDestinationAddress() and
not any(ConstructorCallInstruction constructorCall).getThisArgument() = dest and
operator.getDeclaringType() = init.getResultType()
)
or
// Workaround for an extractor bug. In this snippet:
// ```
// struct S { };
// void f(S);
// f(S());
// ```
// The expression `S()` is represented as a 0 literal in the database.
exists(ConstantValueInstruction constant |
constant.getValue() = "0" and
creation.asInstruction() = constant and
constant.getResultType() = operator.getDeclaringType()
)
}
private predicate isFunctorCreationWithConstructor(Node creation, OperatorCall operator) {
exists(DataFlowCall constructorCall, IndirectionPosition pos |
// A construction of an object with a constructor. In this case we use
// the post-update node of the qualifier
pos.getArgumentIndex() = -1 and
isArgumentNode(creation.(PostUpdateNode).getPreUpdateNode(), constructorCall, pos) and
operator.getDeclaringType() =
constructorCall.asCallInstruction().(ConstructorCallInstruction).getConstructedType()
)
}
/** Holds if `creation` is an expression that creates a lambda of kind `kind` for `c`. */
predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c) {
creation.asInstruction().(FunctionAddressInstruction).getFunctionSymbol() = c.asSourceCallable() and
exists(kind)
kind.isFunctionPointer() and
creation.asInstruction().(FunctionAddressInstruction).getFunctionSymbol() = c.asSourceCallable()
or
kind.isFunctor() and
exists(OperatorCall operator | operator = c.asSourceCallable() |
isFunctorCreationWithoutConstructor(creation, operator)
or
isFunctorCreationWithConstructor(creation, operator)
)
}
/** Holds if `call` is a lambda call of kind `kind` where `receiver` is the lambda expression. */
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
kind.isFunctionPointer() and
(
call.(SummaryCall).getReceiver() = receiver.(FlowSummaryNode).getSummaryNode()
or
@@ -1400,8 +1473,15 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
// has a result for `getStaticCallTarget`.
not exists(call.getStaticCallTarget()) and
call.asCallInstruction().getCallTargetOperand() = receiver.asOperand()
) and
exists(kind)
)
or
kind.isFunctor() and
(
call.(SummaryCall).getReceiver() = receiver.(FlowSummaryNode).getSummaryNode()
or
not exists(call.getStaticCallTarget()) and
call.asCallInstruction().getThisArgumentOperand() = receiver.asOperand()
)
}
/** Extra data-flow steps needed for lambda flow analysis. */

View File

@@ -488,6 +488,23 @@ class Node extends TIRDataFlowNode {
result = this.(IndirectParameterNode).getParameter()
}
/**
* Holds if this node represents the `indirectionIndex`'th indirection of
* the value of an output parameter `p` just before reaching the end of a function.
*/
predicate isFinalValueOfParameter(Parameter p, int indirectionIndex) {
exists(FinalParameterNode n | n = this |
p = n.getParameter() and
indirectionIndex = n.getIndirectionIndex()
)
}
/**
* Holds if this node represents the value of an output parameter `p`
* just before reaching the end of a function.
*/
predicate isFinalValueOfParameter(Parameter p) { this.isFinalValueOfParameter(p, _) }
/**
* Gets the variable corresponding to this node, if any. This can be used for
* modeling flow in and out of global variables.
@@ -1225,7 +1242,7 @@ import RawIndirectNodes
/**
* INTERNAL: do not use.
*
* A node representing the value of an update parameter
* A node representing the value of an output parameter
* just before reaching the end of a function.
*/
class FinalParameterNode extends Node, TFinalParameterNode {

View File

@@ -151,7 +151,7 @@ private module Cached {
)
or
// Similarly for `i++` and `++i` we pretend that the generated
// `StoreInstruction` is contains the result of the expression even though
// `StoreInstruction` contains the result of the expression even though
// this isn't totally aligned with the C/C++ standard.
exists(TranslatedCrementOperation tco |
store = tco.getInstruction(CrementStoreTag()) and

View File

@@ -153,6 +153,10 @@ private predicate isGlobalDefImpl(
GlobalLikeVariable v, IRFunction f, int indirection, int indirectionIndex
) {
exists(VariableAddressInstruction vai |
// The right-hand side of an initialization of a global variable
// creates its own `IRFunction`. We don't want flow into that `IRFunction`
// since the variable is only initialized once.
not vai.getEnclosingFunction() = v and
vai.getEnclosingIRFunction() = f and
vai.getAstVariable() = v and
isUse(_, _, vai, indirection, indirectionIndex) and

View File

@@ -42,6 +42,7 @@ private newtype TOpcode =
TCompareGT() or
TCompareLE() or
TCompareGE() or
TSpaceship() or
TPointerAdd() or
TPointerSub() or
TPointerDiff() or
@@ -92,7 +93,9 @@ private newtype TOpcode =
TUninitializedGroup() or
TInlineAsm() or
TUnreached() or
TNewObj()
TNewObj() or
TTypeidExpr() or
TTypeidType()
/**
* An opcode that specifies the operation performed by an `Instruction`.
@@ -763,6 +766,15 @@ module Opcode {
final override string toString() { result = "CompareGE" }
}
/**
* The `Opcode` for a `SpaceshipInstruction`.
*
* See the `SpaceshipInstruction` documentation for more details.
*/
class Spaceship extends BinaryOpcode, TSpaceship {
final override string toString() { result = "Spaceship" }
}
/**
* The `Opcode` for a `PointerAddInstruction`.
*
@@ -1281,4 +1293,29 @@ module Opcode {
class NewObj extends Opcode, TNewObj {
final override string toString() { result = "NewObj" }
}
/**
* The `Opcode` for a `TypeidInstruction`.
*
* See the `TypeidInstruction` documentation for more details.
*/
abstract class Typeid extends Opcode { }
/**
* The `Opcode` for a `TypeidExprInstruction`.
*
* See the `TypeidExprInstruction` documentation for more details.
*/
class TypeidExpr extends Typeid, UnaryOpcode, TTypeidExpr {
final override string toString() { result = "TypeidExpr" }
}
/**
* The `Opcode` for a `TypeidTypeInstruction`.
*
* See the `TypeidTypeInstruction` documentation for more details.
*/
class TypeidType extends Typeid, TTypeidType {
final override string toString() { result = "TypeidType" }
}
}

View File

@@ -725,6 +725,20 @@ class UninitializedInstruction extends VariableInstruction {
* Gets the variable that is uninitialized.
*/
final Language::Variable getLocalVariable() { result = var.(IRUserVariable).getVariable() }
/**
* Gets the operand that provides the address of the location to which the
* uninitialized value will be stored.
*/
final AddressOperand getDestinationAddressOperand() { result = this.getAnOperand() }
/**
* Gets the instruction whose result provides the address of the location to
* which the value will be stored, if an exact definition is available.
*/
final Instruction getDestinationAddress() {
result = this.getDestinationAddressOperand().getDef()
}
}
/**
@@ -1590,6 +1604,13 @@ class CompareGEInstruction extends RelationalInstruction {
override predicate isStrict() { none() }
}
/**
* An instruction that represents a three-way comparison operator.
*/
class SpaceshipInstruction extends BinaryInstruction {
SpaceshipInstruction() { this.getOpcode() instanceof Opcode::Spaceship }
}
/**
* An instruction that branches to one of multiple successor instructions based on the value of an
* integer operand.
@@ -2279,3 +2300,26 @@ class NextVarArgInstruction extends UnaryInstruction {
class NewObjInstruction extends Instruction {
NewObjInstruction() { this.getOpcode() instanceof Opcode::NewObj }
}
/**
* An instruction that returns the type info for its operand.
*/
class TypeidInstruction extends Instruction {
TypeidInstruction() { this.getOpcode() instanceof Opcode::Typeid }
}
/**
* An instruction that returns the type info for its operand, where the
* operand occurs as an expression in the AST.
*/
class TypeidExprInstruction extends TypeidInstruction, UnaryInstruction {
TypeidExprInstruction() { this.getOpcode() instanceof Opcode::TypeidExpr }
}
/**
* An instruction that returns the type info for its operand, where the
* operand occurs as a type in the AST.
*/
class TypeidTypeInstruction extends TypeidInstruction {
TypeidTypeInstruction() { this.getOpcode() instanceof Opcode::TypeidType }
}

View File

@@ -725,6 +725,20 @@ class UninitializedInstruction extends VariableInstruction {
* Gets the variable that is uninitialized.
*/
final Language::Variable getLocalVariable() { result = var.(IRUserVariable).getVariable() }
/**
* Gets the operand that provides the address of the location to which the
* uninitialized value will be stored.
*/
final AddressOperand getDestinationAddressOperand() { result = this.getAnOperand() }
/**
* Gets the instruction whose result provides the address of the location to
* which the value will be stored, if an exact definition is available.
*/
final Instruction getDestinationAddress() {
result = this.getDestinationAddressOperand().getDef()
}
}
/**
@@ -1590,6 +1604,13 @@ class CompareGEInstruction extends RelationalInstruction {
override predicate isStrict() { none() }
}
/**
* An instruction that represents a three-way comparison operator.
*/
class SpaceshipInstruction extends BinaryInstruction {
SpaceshipInstruction() { this.getOpcode() instanceof Opcode::Spaceship }
}
/**
* An instruction that branches to one of multiple successor instructions based on the value of an
* integer operand.
@@ -2279,3 +2300,26 @@ class NextVarArgInstruction extends UnaryInstruction {
class NewObjInstruction extends Instruction {
NewObjInstruction() { this.getOpcode() instanceof Opcode::NewObj }
}
/**
* An instruction that returns the type info for its operand.
*/
class TypeidInstruction extends Instruction {
TypeidInstruction() { this.getOpcode() instanceof Opcode::Typeid }
}
/**
* An instruction that returns the type info for its operand, where the
* operand occurs as an expression in the AST.
*/
class TypeidExprInstruction extends TypeidInstruction, UnaryInstruction {
TypeidExprInstruction() { this.getOpcode() instanceof Opcode::TypeidExpr }
}
/**
* An instruction that returns the type info for its operand, where the
* operand occurs as a type in the AST.
*/
class TypeidTypeInstruction extends TypeidInstruction {
TypeidTypeInstruction() { this.getOpcode() instanceof Opcode::TypeidType }
}

View File

@@ -1808,6 +1808,11 @@ private Opcode comparisonOpcode(ComparisonOperation expr) {
expr instanceof GEExpr and result instanceof Opcode::CompareGE
}
private Opcode spaceShipOpcode(SpaceshipExpr expr) {
exists(expr) and
result instanceof Opcode::Spaceship
}
/**
* IR translation of a simple binary operation.
*/
@@ -1867,7 +1872,8 @@ class TranslatedBinaryOperation extends TranslatedSingleInstructionExpr {
override Opcode getOpcode() {
result = binaryArithmeticOpcode(expr) or
result = binaryBitwiseOpcode(expr) or
result = comparisonOpcode(expr)
result = comparisonOpcode(expr) or
result = spaceShipOpcode(expr)
}
override Type getExprType() {
@@ -4146,7 +4152,8 @@ predicate exprNeedsCopyIfNotLoaded(Expr expr) {
private predicate exprImmediatelyDiscarded(Expr expr) {
exists(ExprStmt s |
s = expr.getParent() and
not exists(StmtExpr se | s = se.getStmt().(BlockStmt).getLastStmt())
not exists(StmtExpr se | s = se.getStmt().(BlockStmt).getLastStmt()) and
not exists(expr.getConversion())
)
or
exists(CommaExpr c | c.getLeftOperand() = expr)
@@ -4184,3 +4191,52 @@ class TranslatedAssumeExpr extends TranslatedSingleInstructionExpr {
none()
}
}
class TranslatedTypeidExpr extends TranslatedSingleInstructionExpr {
override TypeidOperator expr;
final override Opcode getOpcode() {
exists(this.getOperand()) and
result instanceof Opcode::TypeidExpr
or
not exists(this.getOperand()) and
result instanceof Opcode::TypeidType
}
final override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getOperand().getFirstInstruction(kind)
or
not exists(this.getOperand()) and
result = this.getInstruction(OnlyInstructionTag()) and
kind instanceof GotoEdge
}
override Instruction getALastInstructionInternal() {
result = this.getInstruction(OnlyInstructionTag())
}
final override TranslatedElement getChildInternal(int id) {
id = 0 and result = this.getOperand()
}
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
tag = OnlyInstructionTag() and
result = this.getParent().getChildSuccessor(this, kind)
}
final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
child = this.getOperand() and
result = this.getInstruction(OnlyInstructionTag()) and
kind instanceof GotoEdge
}
final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
tag = OnlyInstructionTag() and
result = this.getOperand().getResult() and
operandTag instanceof UnaryOperandTag
}
private TranslatedExpr getOperand() {
result = getTranslatedExpr(expr.getExpr().getFullyConverted())
}
}

View File

@@ -725,6 +725,20 @@ class UninitializedInstruction extends VariableInstruction {
* Gets the variable that is uninitialized.
*/
final Language::Variable getLocalVariable() { result = var.(IRUserVariable).getVariable() }
/**
* Gets the operand that provides the address of the location to which the
* uninitialized value will be stored.
*/
final AddressOperand getDestinationAddressOperand() { result = this.getAnOperand() }
/**
* Gets the instruction whose result provides the address of the location to
* which the value will be stored, if an exact definition is available.
*/
final Instruction getDestinationAddress() {
result = this.getDestinationAddressOperand().getDef()
}
}
/**
@@ -1590,6 +1604,13 @@ class CompareGEInstruction extends RelationalInstruction {
override predicate isStrict() { none() }
}
/**
* An instruction that represents a three-way comparison operator.
*/
class SpaceshipInstruction extends BinaryInstruction {
SpaceshipInstruction() { this.getOpcode() instanceof Opcode::Spaceship }
}
/**
* An instruction that branches to one of multiple successor instructions based on the value of an
* integer operand.
@@ -2279,3 +2300,26 @@ class NextVarArgInstruction extends UnaryInstruction {
class NewObjInstruction extends Instruction {
NewObjInstruction() { this.getOpcode() instanceof Opcode::NewObj }
}
/**
* An instruction that returns the type info for its operand.
*/
class TypeidInstruction extends Instruction {
TypeidInstruction() { this.getOpcode() instanceof Opcode::Typeid }
}
/**
* An instruction that returns the type info for its operand, where the
* operand occurs as an expression in the AST.
*/
class TypeidExprInstruction extends TypeidInstruction, UnaryInstruction {
TypeidExprInstruction() { this.getOpcode() instanceof Opcode::TypeidExpr }
}
/**
* An instruction that returns the type info for its operand, where the
* operand occurs as a type in the AST.
*/
class TypeidTypeInstruction extends TypeidInstruction {
TypeidTypeInstruction() { this.getOpcode() instanceof Opcode::TypeidType }
}

View File

@@ -17,7 +17,6 @@
import cpp
import PrintfLike
private import semmle.code.cpp.ir.dataflow.ResolveCall
bindingset[index]
private string toCause(Function func, int index) {
@@ -37,9 +36,9 @@ private predicate wrapperFunctionStep(
not target.isVirtual() and
not source.isVirtual() and
source.hasDefinition() and
exists(Call call, Expr arg, Parameter sourceParam |
exists(FunctionCall call, Expr arg, Parameter sourceParam |
// there is a 'call' to 'target' with argument 'arg' at index 'targetParamIndex'
target = resolveCall(call) and
target = call.getTarget() and
arg = call.getArgument(targetParamIndex) and
// 'call' is enclosed in 'source'
source = call.getEnclosingFunction() and
@@ -154,8 +153,8 @@ abstract class FunctionWithWrappers extends Function {
* Whether 'arg' is an argument in a call to an outermost wrapper function of 'this' function.
*/
predicate outermostWrapperFunctionCall(Expr arg, string callChain) {
exists(Function targetFunc, Call call, int argIndex |
targetFunc = resolveCall(call) and
exists(Function targetFunc, FunctionCall call, int argIndex |
targetFunc = call.getTarget() and
this.wrapperFunction(targetFunc, argIndex, callChain) and
(
exists(Function sourceFunc | sourceFunc = call.getEnclosingFunction() |

View File

@@ -217,10 +217,6 @@ diagnostics(
/*- C++ dbscheme -*/
/*
* C++ dbscheme
*/
extractor_version(
string codeql_version: string ref,
string frontend_version: string ref
@@ -286,18 +282,17 @@ macro_argument_expanded(
string text: string ref
);
/*
case @function.kind of
1 = @normal_function
0 = @unknown_function
| 1 = @normal_function
| 2 = @constructor
| 3 = @destructor
| 4 = @conversion_function
| 5 = @operator
| 6 = @builtin_function // GCC built-in functions, e.g. __builtin___memcpy_chk
// ... 6 = @builtin_function deprecated // GCC built-in functions, e.g. __builtin___memcpy_chk
| 7 = @user_defined_literal
| 8 = @deduction_guide
;
*/
functions(
unique int id: @function,
@@ -305,6 +300,10 @@ functions(
int kind: int ref
);
builtin_functions(
int id: @function ref
)
function_entry_point(
int id: @function ref,
unique int entry_point: @stmt ref
@@ -713,9 +712,8 @@ decltypes(
boolean parentheses_would_change_meaning: boolean ref
);
/*
case @type_operator.kind of
| 0 = @typeof // The frontend does not differentiate between typeof and typeof_unqual
0 = @typeof // The frontend does not differentiate between typeof and typeof_unqual
| 1 = @underlying_type
| 2 = @bases
| 3 = @direct_bases
@@ -736,7 +734,6 @@ case @type_operator.kind of
| 18 = @remove_volatile
| 19 = @remove_reference
;
*/
type_operators(
unique int id: @type_operator,
@@ -745,9 +742,8 @@ type_operators(
int base_type: @type ref
)
/*
case @usertype.kind of
| 0 = @unknown_usertype
0 = @unknown_usertype
| 1 = @struct
| 2 = @class
| 3 = @union
@@ -767,7 +763,6 @@ case @usertype.kind of
| 17 = @template_union
| 18 = @alias
;
*/
usertypes(
unique int id: @usertype,

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
class Function extends @function {
string toString() { none() }
}
from Function f
where functions(f, _, 6)
select f

View File

@@ -0,0 +1,9 @@
class Function extends @function {
string toString() { none() }
}
from Function f, string n, int k, int new_k
where
functions(f, n, k) and
if k = 6 then new_k = 1 else new_k = k
select f, n, new_k

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,4 @@
description: Move builtin function identification to its own table
compatibility: full
functions.rel: run functions.qlo
builtin_functions.rel: run builtin_functions.qlo

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Uncomment cases in dbscheme
compatibility: full

View File

@@ -1,8 +1,21 @@
## 1.4.4
### Minor Analysis Improvements
* Due to changes in the `FunctionWithWrappers` library (`semmle.code.cpp.security.FunctionWithWrappers`) the primary alert location generated by the queries `cpp/path-injection`, `cpp/sql-injection`, `cpp/tainted-format-string`, and `cpp/command-line-injection` may have changed.
* Added flow models for the Win32 API functions `CreateThread`, `CreateRemoteThread`, and `CreateRemoteThreadEx`.
* Improved support for dataflow through function objects and lambda expressions.
* Added flow models for `pthread_create` and `std::thread`.
* The `cpp/incorrect-string-type-conversion` query no longer alerts on incorrect type conversions that occur in unreachable code.
* Added flow models for the GNU C Library.
* Fixed a number of false positives and false negatives in `cpp/global-use-before-init`. Note that this query is not part of any of the default query suites.
* The query `cpp/sql-injection` now can be extended using the `sql-injection` Models as Data (MaD) sink kind.
## 1.4.3
### Minor Analysis Improvements
* Added flow model for the following libraries: `madler/zlib`, `google/brotli`, `libidn/libidn2`, `libssh2/libssh2/`, `nghttp2/nghttp2`, `libuv/libuv/`, and `curl/curl`. This may result in more alerts when running queries on codebases that use these libraries.
* Added flow models for the following libraries: `madler/zlib`, `google/brotli`, `libidn/libidn2`, `libssh2/libssh2`, `nghttp2/nghttp2`, `libuv/libuv`, and `curl/curl`. This may result in more alerts when running queries on codebases that use these libraries.
## 1.4.2
@@ -12,7 +25,7 @@ No user-facing changes.
### Minor Analysis Improvements
* Added flow model for the `SQLite` and `OpenSSL` libraries. This may result in more alerts when running queries on codebases that use these libraries.
* Added flow models for the `SQLite` and `OpenSSL` libraries. This may result in more alerts when running queries on codebases that use these libraries.
## 1.4.0

View File

@@ -23,7 +23,7 @@ predicate isProcessOperationExplanation(DataFlow::Node arg, string processOperat
exists(int processOperationArg, FunctionCall call |
isProcessOperationArgument(processOperation, processOperationArg) and
call.getTarget().getName() = processOperation and
call.getArgument(processOperationArg) = [arg.asExpr(), arg.asIndirectExpr()]
call.getArgument(processOperationArg) = arg.asIndirectExpr()
)
}

View File

@@ -14,6 +14,7 @@
import cpp
import semmle.code.cpp.controlflow.Guards
import semmle.code.cpp.ir.IR
class WideCharPointerType extends PointerType {
WideCharPointerType() { this.getBaseType() instanceof WideCharType }
@@ -108,7 +109,9 @@ where
// Avoid cases where the cast is guarded by a check to determine if
// unicode encoding is enabled in such a way to disallow the dangerous cast
// at runtime.
not isLikelyDynamicallyChecked(e1)
not isLikelyDynamicallyChecked(e1) and
// Avoid cases in unreachable blocks.
any(EnterFunctionInstruction e).getASuccessor+().getAst() = e1
select e1,
"Conversion from " + e1.getType().toString() + " to " + e2.getType().toString() +
". Use of invalid string can lead to undefined behavior."

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* The query `cpp/sql-injection` now can be extended using the `sql-injection` Models as Data (MaD) sink kind.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* Fixed a number of false positives and false negatives in `cpp/global-use-before-init`. Note that this query is not part of any of the default query suites.

View File

@@ -2,4 +2,4 @@
### Minor Analysis Improvements
* Added flow model for the `SQLite` and `OpenSSL` libraries. This may result in more alerts when running queries on codebases that use these libraries.
* Added flow models for the `SQLite` and `OpenSSL` libraries. This may result in more alerts when running queries on codebases that use these libraries.

View File

@@ -2,4 +2,4 @@
### Minor Analysis Improvements
* Added flow model for the following libraries: `madler/zlib`, `google/brotli`, `libidn/libidn2`, `libssh2/libssh2/`, `nghttp2/nghttp2`, `libuv/libuv/`, and `curl/curl`. This may result in more alerts when running queries on codebases that use these libraries.
* Added flow models for the following libraries: `madler/zlib`, `google/brotli`, `libidn/libidn2`, `libssh2/libssh2`, `nghttp2/nghttp2`, `libuv/libuv`, and `curl/curl`. This may result in more alerts when running queries on codebases that use these libraries.

View File

@@ -0,0 +1,12 @@
## 1.4.4
### Minor Analysis Improvements
* Due to changes in the `FunctionWithWrappers` library (`semmle.code.cpp.security.FunctionWithWrappers`) the primary alert location generated by the queries `cpp/path-injection`, `cpp/sql-injection`, `cpp/tainted-format-string`, and `cpp/command-line-injection` may have changed.
* Added flow models for the Win32 API functions `CreateThread`, `CreateRemoteThread`, and `CreateRemoteThreadEx`.
* Improved support for dataflow through function objects and lambda expressions.
* Added flow models for `pthread_create` and `std::thread`.
* The `cpp/incorrect-string-type-conversion` query no longer alerts on incorrect type conversions that occur in unreachable code.
* Added flow models for the GNU C Library.
* Fixed a number of false positives and false negatives in `cpp/global-use-before-init`. Note that this query is not part of any of the default query suites.
* The query `cpp/sql-injection` now can be extended using the `sql-injection` Models as Data (MaD) sink kind.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.4.3
lastReleaseVersion: 1.4.4

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries
version: 1.4.4-dev
version: 1.4.4
groups:
- cpp
- queries

View File

@@ -37,4 +37,21 @@ void test_aggregate_literal() {
int xs[] = {1, 2, 3}; // $ asExpr=1 asExpr=2 asExpr=3 asExpr={...}
const int ys[] = {[0] = 4, [1] = 5, [0] = 6}; // $ asExpr=4 asExpr=5 asExpr=6 asExpr={...}
}
}
void test_postfix_crement(int *p, int q) {
p++; // $ asExpr="... ++" asIndirectExpr="... ++" asExpr=p asIndirectExpr=p
q++; // $ asExpr="... ++" asExpr=q
(p++); // $ asExpr="... ++" asIndirectExpr="... ++" asExpr="p(... ++)" asIndirectExpr="p(*... ++)"
(q++); // $ asExpr="... ++" asExpr="q(... ++)"
(void)(p++); // $ asExpr="p(... ++)" asIndirectExpr="p(*... ++)"
(void)(q++); // $ asExpr="q(... ++)"
(void)p++; // $ asExpr="p(... ++)" asIndirectExpr="p(*... ++)"
(void)q++; // $ asExpr="q(... ++)"
int *p1 = p++; // $ asExpr="... ++" asIndirectExpr="... ++" asExpr="p(... ++)" asIndirectExpr="p(*... ++)"
int q1 = q++; // $ asExpr="... ++" asExpr="q(... ++)"
(int*)(p++); // $ asExpr="... ++" asIndirectExpr="... ++" asExpr="p(... ++)" asIndirectExpr="p(*... ++)"
(int)(q++); // $ asExpr="... ++" asExpr="q(... ++)"
int *p2 = (int*)(p++); // $ asExpr="... ++" asIndirectExpr="... ++" asExpr="p(... ++)" asIndirectExpr="p(*... ++)"
int q2 = (int)(q++); // $ asExpr="... ++" asExpr="q(... ++)"
}

View File

@@ -6,9 +6,15 @@ uniqueEnclosingCallable
| test.cpp:1126:33:1129:1 | {...} | Node should have one enclosing callable but has 0. |
| test.cpp:1127:3:1127:13 | reads_input | Node should have one enclosing callable but has 0. |
| test.cpp:1128:3:1128:21 | not_does_read_input | Node should have one enclosing callable but has 0. |
| test.cpp:1158:18:1158:21 | call to sink | Node should have one enclosing callable but has 0. |
| test.cpp:1158:18:1158:42 | ... , ... | Node should have one enclosing callable but has 0. |
| test.cpp:1158:23:1158:31 | recursion | Node should have one enclosing callable but has 0. |
| test.cpp:1158:35:1158:40 | call to source | Node should have one enclosing callable but has 0. |
uniqueCallEnclosingCallable
| test.cpp:864:47:864:54 | call to source | Call should have one enclosing callable but has 0. |
| test.cpp:872:46:872:51 | call to source | Call should have one enclosing callable but has 0. |
| test.cpp:1158:18:1158:21 | call to sink | Call should have one enclosing callable but has 0. |
| test.cpp:1158:35:1158:40 | call to source | Call should have one enclosing callable but has 0. |
uniqueType
uniqueNodeLocation
missingLocation

View File

@@ -24,10 +24,9 @@ module AstTest {
module IRTest {
private import semmle.code.cpp.ir.dataflow.DataFlow
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
private string stars(int k) {
k = [0 .. max(FinalParameterNode n | | n.getIndirectionIndex())] and
k = [0 .. max(DataFlow::Node n, int i | n.isFinalValueOfParameter(_, i) | i)] and
(if k = 0 then result = "" else result = "*" + stars(k - 1))
}
@@ -35,14 +34,14 @@ module IRTest {
string getARelevantTag() { result = "ir-def" }
predicate hasActualResult(Location location, string element, string tag, string value) {
exists(Function f, Parameter p, FinalParameterNode n |
exists(Function f, Parameter p, DataFlow::Node n, int i |
p.isNamed() and
n.getParameter() = p and
n.isFinalValueOfParameter(p, i) and
n.getFunction() = f and
location = f.getLocation() and
element = p.toString() and
tag = "ir-def" and
value = stars(n.getIndirectionIndex()) + p.getName()
value = stars(i) + p.getName()
)
}
}

View File

@@ -1153,4 +1153,6 @@ namespace conflation_regression {
*p = source(0);
read_deref_deref(p);
}
}
}
int recursion = (sink(recursion), source()); // clean

View File

@@ -17,13 +17,18 @@ models
| 16 | Source: ; ; false; ymlSource; ; ; ReturnValue; local; manual |
| 17 | Source: boost::asio; ; false; read_until; ; ; Argument[*1]; remote; manual |
| 18 | Summary: ; ; false; CommandLineToArgvA; ; ; Argument[*0]; ReturnValue[**]; taint; manual |
| 19 | Summary: ; ; false; ReadFileEx; ; ; Argument[*3].Field[@hEvent]; Argument[4].Parameter[*2].Field[@hEvent]; value; manual |
| 20 | Summary: ; ; false; ymlStepGenerated; ; ; Argument[0]; ReturnValue; taint; df-generated |
| 21 | Summary: ; ; false; ymlStepManual; ; ; Argument[0]; ReturnValue; taint; manual |
| 22 | Summary: ; ; false; ymlStepManual_with_body; ; ; Argument[0]; ReturnValue; taint; manual |
| 23 | Summary: boost::asio; ; false; buffer; ; ; Argument[*0]; ReturnValue; taint; manual |
| 19 | Summary: ; ; false; CreateRemoteThread; ; ; Argument[@4]; Argument[3].Parameter[@0]; value; manual |
| 20 | Summary: ; ; false; CreateRemoteThreadEx; ; ; Argument[@4]; Argument[3].Parameter[@0]; value; manual |
| 21 | Summary: ; ; false; CreateThread; ; ; Argument[@3]; Argument[2].Parameter[@0]; value; manual |
| 22 | Summary: ; ; false; ReadFileEx; ; ; Argument[*3].Field[@hEvent]; Argument[4].Parameter[*2].Field[@hEvent]; value; manual |
| 23 | Summary: ; ; false; callWithArgument; ; ; Argument[1]; Argument[0].Parameter[0]; value; manual |
| 24 | Summary: ; ; false; pthread_create; ; ; Argument[@3]; Argument[2].Parameter[@0]; value; manual |
| 25 | Summary: ; ; false; ymlStepGenerated; ; ; Argument[0]; ReturnValue; taint; df-generated |
| 26 | Summary: ; ; false; ymlStepManual; ; ; Argument[0]; ReturnValue; taint; manual |
| 27 | Summary: ; ; false; ymlStepManual_with_body; ; ; Argument[0]; ReturnValue; taint; manual |
| 28 | Summary: boost::asio; ; false; buffer; ; ; Argument[*0]; ReturnValue; taint; manual |
edges
| asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | provenance | MaD:23 |
| asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | provenance | MaD:28 |
| asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:91:7:91:17 | recv_buffer | provenance | Src:MaD:17 |
| asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:93:29:93:39 | *recv_buffer | provenance | Src:MaD:17 Sink:MaD:2 |
| asio_streams.cpp:97:37:97:44 | call to source | asio_streams.cpp:98:7:98:14 | send_str | provenance | TaintFunction |
@@ -32,10 +37,10 @@ edges
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:101:7:101:17 | send_buffer | provenance | |
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:103:29:103:39 | *send_buffer | provenance | Sink:MaD:2 |
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | provenance | |
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:23 |
| test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | test.cpp:4:5:4:17 | [summary] to write: ReturnValue in ymlStepManual | provenance | MaD:21 |
| test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | test.cpp:5:5:5:20 | [summary] to write: ReturnValue in ymlStepGenerated | provenance | MaD:20 |
| test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | test.cpp:6:5:6:27 | [summary] to write: ReturnValue in ymlStepManual_with_body | provenance | MaD:22 |
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:28 |
| test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | test.cpp:4:5:4:17 | [summary] to write: ReturnValue in ymlStepManual | provenance | MaD:26 |
| test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | test.cpp:5:5:5:20 | [summary] to write: ReturnValue in ymlStepGenerated | provenance | MaD:25 |
| test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | test.cpp:6:5:6:27 | [summary] to write: ReturnValue in ymlStepManual_with_body | provenance | MaD:27 |
| test.cpp:7:47:7:52 | value2 | test.cpp:7:64:7:69 | value2 | provenance | |
| test.cpp:7:64:7:69 | value2 | test.cpp:7:5:7:30 | *ymlStepGenerated_with_body | provenance | |
| test.cpp:10:10:10:18 | call to ymlSource | test.cpp:10:10:10:18 | call to ymlSource | provenance | Src:MaD:16 |
@@ -47,19 +52,49 @@ edges
| test.cpp:17:10:17:22 | call to ymlStepManual | test.cpp:17:10:17:22 | call to ymlStepManual | provenance | |
| test.cpp:17:10:17:22 | call to ymlStepManual | test.cpp:18:10:18:10 | y | provenance | Sink:MaD:1 |
| test.cpp:17:24:17:24 | x | test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | provenance | |
| test.cpp:17:24:17:24 | x | test.cpp:17:10:17:22 | call to ymlStepManual | provenance | MaD:21 |
| test.cpp:17:24:17:24 | x | test.cpp:17:10:17:22 | call to ymlStepManual | provenance | MaD:26 |
| test.cpp:21:10:21:25 | call to ymlStepGenerated | test.cpp:21:10:21:25 | call to ymlStepGenerated | provenance | |
| test.cpp:21:10:21:25 | call to ymlStepGenerated | test.cpp:22:10:22:10 | z | provenance | Sink:MaD:1 |
| test.cpp:21:27:21:27 | x | test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | provenance | |
| test.cpp:21:27:21:27 | x | test.cpp:21:10:21:25 | call to ymlStepGenerated | provenance | MaD:20 |
| test.cpp:21:27:21:27 | x | test.cpp:21:10:21:25 | call to ymlStepGenerated | provenance | MaD:25 |
| test.cpp:25:11:25:33 | call to ymlStepManual_with_body | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | provenance | |
| test.cpp:25:11:25:33 | call to ymlStepManual_with_body | test.cpp:26:10:26:11 | y2 | provenance | Sink:MaD:1 |
| test.cpp:25:35:25:35 | x | test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | provenance | |
| test.cpp:25:35:25:35 | x | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | provenance | MaD:22 |
| test.cpp:25:35:25:35 | x | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | provenance | MaD:27 |
| test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | provenance | |
| test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | test.cpp:33:10:33:11 | z2 | provenance | Sink:MaD:1 |
| test.cpp:32:41:32:41 | x | test.cpp:7:47:7:52 | value2 | provenance | |
| test.cpp:32:41:32:41 | x | test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | provenance | |
| test.cpp:46:30:46:32 | *arg [x] | test.cpp:47:12:47:19 | *arg [x] | provenance | |
| test.cpp:47:12:47:19 | *arg [x] | test.cpp:48:13:48:13 | *s [x] | provenance | |
| test.cpp:48:13:48:13 | *s [x] | test.cpp:48:16:48:16 | x | provenance | Sink:MaD:1 |
| test.cpp:52:5:52:18 | [summary param] *3 in pthread_create [x] | test.cpp:52:5:52:18 | [summary] to write: Argument[2].Parameter[*0] in pthread_create [x] | provenance | MaD:24 |
| test.cpp:52:5:52:18 | [summary] to write: Argument[2].Parameter[*0] in pthread_create [x] | test.cpp:46:30:46:32 | *arg [x] | provenance | |
| test.cpp:56:2:56:2 | *s [post update] [x] | test.cpp:59:55:59:64 | *& ... [x] | provenance | |
| test.cpp:56:2:56:18 | ... = ... | test.cpp:56:2:56:2 | *s [post update] [x] | provenance | |
| test.cpp:56:8:56:16 | call to ymlSource | test.cpp:56:2:56:18 | ... = ... | provenance | Src:MaD:16 |
| test.cpp:59:55:59:64 | *& ... [x] | test.cpp:52:5:52:18 | [summary param] *3 in pthread_create [x] | provenance | |
| test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | provenance | MaD:23 |
| test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | provenance | MaD:23 |
| test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | provenance | MaD:23 |
| test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | provenance | MaD:23 |
| test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | test.cpp:68:22:68:22 | y | provenance | |
| test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | test.cpp:74:22:74:22 | y | provenance | |
| test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | test.cpp:82:22:82:22 | y | provenance | |
| test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | test.cpp:88:22:88:22 | y | provenance | |
| test.cpp:68:22:68:22 | y | test.cpp:69:11:69:11 | y | provenance | Sink:MaD:1 |
| test.cpp:74:22:74:22 | y | test.cpp:75:11:75:11 | y | provenance | Sink:MaD:1 |
| test.cpp:82:22:82:22 | y | test.cpp:83:11:83:11 | y | provenance | Sink:MaD:1 |
| test.cpp:88:22:88:22 | y | test.cpp:89:11:89:11 | y | provenance | Sink:MaD:1 |
| test.cpp:94:10:94:18 | call to ymlSource | test.cpp:94:10:94:18 | call to ymlSource | provenance | Src:MaD:16 |
| test.cpp:94:10:94:18 | call to ymlSource | test.cpp:97:26:97:26 | x | provenance | |
| test.cpp:94:10:94:18 | call to ymlSource | test.cpp:101:26:101:26 | x | provenance | |
| test.cpp:94:10:94:18 | call to ymlSource | test.cpp:103:63:103:63 | x | provenance | |
| test.cpp:94:10:94:18 | call to ymlSource | test.cpp:104:62:104:62 | x | provenance | |
| test.cpp:97:26:97:26 | x | test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | provenance | |
| test.cpp:101:26:101:26 | x | test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | provenance | |
| test.cpp:103:63:103:63 | x | test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | provenance | |
| test.cpp:104:62:104:62 | x | test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | provenance | |
| windows.cpp:17:8:17:25 | [summary param] *0 in CommandLineToArgvA | windows.cpp:17:8:17:25 | [summary] to write: ReturnValue[**] in CommandLineToArgvA | provenance | MaD:18 |
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | windows.cpp:22:15:22:29 | *call to GetCommandLineA | provenance | Src:MaD:3 |
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | windows.cpp:24:8:24:11 | * ... | provenance | |
@@ -73,8 +108,8 @@ edges
| windows.cpp:39:36:39:38 | GetEnvironmentVariableA output argument | windows.cpp:41:10:41:13 | * ... | provenance | Src:MaD:5 |
| windows.cpp:90:6:90:15 | [summary param] *3 in ReadFileEx [*hEvent] | windows.cpp:90:6:90:15 | [summary] read: Argument[*3].Field[*hEvent] in ReadFileEx | provenance | |
| windows.cpp:90:6:90:15 | [summary param] *3 in ReadFileEx [hEvent] | windows.cpp:90:6:90:15 | [summary] read: Argument[*3].Field[hEvent] in ReadFileEx | provenance | |
| windows.cpp:90:6:90:15 | [summary] read: Argument[*3].Field[*hEvent] in ReadFileEx | windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2].Field[*hEvent] in ReadFileEx | provenance | MaD:19 |
| windows.cpp:90:6:90:15 | [summary] read: Argument[*3].Field[hEvent] in ReadFileEx | windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2].Field[hEvent] in ReadFileEx | provenance | MaD:19 |
| windows.cpp:90:6:90:15 | [summary] read: Argument[*3].Field[*hEvent] in ReadFileEx | windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2].Field[*hEvent] in ReadFileEx | provenance | MaD:22 |
| windows.cpp:90:6:90:15 | [summary] read: Argument[*3].Field[hEvent] in ReadFileEx | windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2].Field[hEvent] in ReadFileEx | provenance | MaD:22 |
| windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2] in ReadFileEx [*hEvent] | windows.cpp:147:16:147:27 | *lpOverlapped [*hEvent] | provenance | |
| windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2] in ReadFileEx [hEvent] | windows.cpp:157:16:157:27 | *lpOverlapped [hEvent] | provenance | |
| windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2].Field[*hEvent] in ReadFileEx | windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2] in ReadFileEx [*hEvent] | provenance | |
@@ -122,6 +157,29 @@ edges
| windows.cpp:332:23:332:40 | *call to MapViewOfFileNuma2 | windows.cpp:332:23:332:40 | *call to MapViewOfFileNuma2 | provenance | Src:MaD:12 |
| windows.cpp:332:23:332:40 | *call to MapViewOfFileNuma2 | windows.cpp:333:20:333:52 | *pMapView | provenance | |
| windows.cpp:333:20:333:52 | *pMapView | windows.cpp:335:10:335:16 | * ... | provenance | |
| windows.cpp:349:8:349:19 | [summary param] *3 in CreateThread [x] | windows.cpp:349:8:349:19 | [summary] to write: Argument[2].Parameter[*0] in CreateThread [x] | provenance | MaD:21 |
| windows.cpp:349:8:349:19 | [summary] to write: Argument[2].Parameter[*0] in CreateThread [x] | windows.cpp:403:26:403:36 | *lpParameter [x] | provenance | |
| windows.cpp:357:8:357:25 | [summary param] *4 in CreateRemoteThread [x] | windows.cpp:357:8:357:25 | [summary] to write: Argument[3].Parameter[*0] in CreateRemoteThread [x] | provenance | MaD:19 |
| windows.cpp:357:8:357:25 | [summary] to write: Argument[3].Parameter[*0] in CreateRemoteThread [x] | windows.cpp:410:26:410:36 | *lpParameter [x] | provenance | |
| windows.cpp:387:8:387:27 | [summary param] *4 in CreateRemoteThreadEx [x] | windows.cpp:387:8:387:27 | [summary] to write: Argument[3].Parameter[*0] in CreateRemoteThreadEx [x] | provenance | MaD:20 |
| windows.cpp:387:8:387:27 | [summary] to write: Argument[3].Parameter[*0] in CreateRemoteThreadEx [x] | windows.cpp:417:26:417:36 | *lpParameter [x] | provenance | |
| windows.cpp:403:26:403:36 | *lpParameter [x] | windows.cpp:405:10:405:25 | *lpParameter [x] | provenance | |
| windows.cpp:405:10:405:25 | *lpParameter [x] | windows.cpp:406:8:406:8 | *s [x] | provenance | |
| windows.cpp:406:8:406:8 | *s [x] | windows.cpp:406:8:406:11 | x | provenance | |
| windows.cpp:410:26:410:36 | *lpParameter [x] | windows.cpp:412:10:412:25 | *lpParameter [x] | provenance | |
| windows.cpp:412:10:412:25 | *lpParameter [x] | windows.cpp:413:8:413:8 | *s [x] | provenance | |
| windows.cpp:413:8:413:8 | *s [x] | windows.cpp:413:8:413:11 | x | provenance | |
| windows.cpp:417:26:417:36 | *lpParameter [x] | windows.cpp:419:10:419:25 | *lpParameter [x] | provenance | |
| windows.cpp:419:10:419:25 | *lpParameter [x] | windows.cpp:420:8:420:8 | *s [x] | provenance | |
| windows.cpp:420:8:420:8 | *s [x] | windows.cpp:420:8:420:11 | x | provenance | |
| windows.cpp:431:3:431:3 | *s [post update] [x] | windows.cpp:439:7:439:8 | *& ... [x] | provenance | |
| windows.cpp:431:3:431:3 | *s [post update] [x] | windows.cpp:451:7:451:8 | *& ... [x] | provenance | |
| windows.cpp:431:3:431:3 | *s [post update] [x] | windows.cpp:464:7:464:8 | *& ... [x] | provenance | |
| windows.cpp:431:3:431:16 | ... = ... | windows.cpp:431:3:431:3 | *s [post update] [x] | provenance | |
| windows.cpp:431:9:431:14 | call to source | windows.cpp:431:3:431:16 | ... = ... | provenance | |
| windows.cpp:439:7:439:8 | *& ... [x] | windows.cpp:349:8:349:19 | [summary param] *3 in CreateThread [x] | provenance | |
| windows.cpp:451:7:451:8 | *& ... [x] | windows.cpp:357:8:357:25 | [summary param] *4 in CreateRemoteThread [x] | provenance | |
| windows.cpp:464:7:464:8 | *& ... [x] | windows.cpp:387:8:387:27 | [summary param] *4 in CreateRemoteThreadEx [x] | provenance | |
nodes
| asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | semmle.label | [summary param] *0 in buffer |
| asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | semmle.label | [summary] to write: ReturnValue in buffer |
@@ -163,6 +221,38 @@ nodes
| test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | semmle.label | call to ymlStepGenerated_with_body |
| test.cpp:32:41:32:41 | x | semmle.label | x |
| test.cpp:33:10:33:11 | z2 | semmle.label | z2 |
| test.cpp:46:30:46:32 | *arg [x] | semmle.label | *arg [x] |
| test.cpp:47:12:47:19 | *arg [x] | semmle.label | *arg [x] |
| test.cpp:48:13:48:13 | *s [x] | semmle.label | *s [x] |
| test.cpp:48:16:48:16 | x | semmle.label | x |
| test.cpp:52:5:52:18 | [summary param] *3 in pthread_create [x] | semmle.label | [summary param] *3 in pthread_create [x] |
| test.cpp:52:5:52:18 | [summary] to write: Argument[2].Parameter[*0] in pthread_create [x] | semmle.label | [summary] to write: Argument[2].Parameter[*0] in pthread_create [x] |
| test.cpp:56:2:56:2 | *s [post update] [x] | semmle.label | *s [post update] [x] |
| test.cpp:56:2:56:18 | ... = ... | semmle.label | ... = ... |
| test.cpp:56:8:56:16 | call to ymlSource | semmle.label | call to ymlSource |
| test.cpp:59:55:59:64 | *& ... [x] | semmle.label | *& ... [x] |
| test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | semmle.label | [summary param] 1 in callWithArgument |
| test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | semmle.label | [summary param] 1 in callWithArgument |
| test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | semmle.label | [summary param] 1 in callWithArgument |
| test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | semmle.label | [summary param] 1 in callWithArgument |
| test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | semmle.label | [summary] to write: Argument[0].Parameter[0] in callWithArgument |
| test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | semmle.label | [summary] to write: Argument[0].Parameter[0] in callWithArgument |
| test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | semmle.label | [summary] to write: Argument[0].Parameter[0] in callWithArgument |
| test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | semmle.label | [summary] to write: Argument[0].Parameter[0] in callWithArgument |
| test.cpp:68:22:68:22 | y | semmle.label | y |
| test.cpp:69:11:69:11 | y | semmle.label | y |
| test.cpp:74:22:74:22 | y | semmle.label | y |
| test.cpp:75:11:75:11 | y | semmle.label | y |
| test.cpp:82:22:82:22 | y | semmle.label | y |
| test.cpp:83:11:83:11 | y | semmle.label | y |
| test.cpp:88:22:88:22 | y | semmle.label | y |
| test.cpp:89:11:89:11 | y | semmle.label | y |
| test.cpp:94:10:94:18 | call to ymlSource | semmle.label | call to ymlSource |
| test.cpp:94:10:94:18 | call to ymlSource | semmle.label | call to ymlSource |
| test.cpp:97:26:97:26 | x | semmle.label | x |
| test.cpp:101:26:101:26 | x | semmle.label | x |
| test.cpp:103:63:103:63 | x | semmle.label | x |
| test.cpp:104:62:104:62 | x | semmle.label | x |
| windows.cpp:17:8:17:25 | [summary param] *0 in CommandLineToArgvA | semmle.label | [summary param] *0 in CommandLineToArgvA |
| windows.cpp:17:8:17:25 | [summary] to write: ReturnValue[**] in CommandLineToArgvA | semmle.label | [summary] to write: ReturnValue[**] in CommandLineToArgvA |
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | semmle.label | *call to GetCommandLineA |
@@ -238,6 +328,30 @@ nodes
| windows.cpp:332:23:332:40 | *call to MapViewOfFileNuma2 | semmle.label | *call to MapViewOfFileNuma2 |
| windows.cpp:333:20:333:52 | *pMapView | semmle.label | *pMapView |
| windows.cpp:335:10:335:16 | * ... | semmle.label | * ... |
| windows.cpp:349:8:349:19 | [summary param] *3 in CreateThread [x] | semmle.label | [summary param] *3 in CreateThread [x] |
| windows.cpp:349:8:349:19 | [summary] to write: Argument[2].Parameter[*0] in CreateThread [x] | semmle.label | [summary] to write: Argument[2].Parameter[*0] in CreateThread [x] |
| windows.cpp:357:8:357:25 | [summary param] *4 in CreateRemoteThread [x] | semmle.label | [summary param] *4 in CreateRemoteThread [x] |
| windows.cpp:357:8:357:25 | [summary] to write: Argument[3].Parameter[*0] in CreateRemoteThread [x] | semmle.label | [summary] to write: Argument[3].Parameter[*0] in CreateRemoteThread [x] |
| windows.cpp:387:8:387:27 | [summary param] *4 in CreateRemoteThreadEx [x] | semmle.label | [summary param] *4 in CreateRemoteThreadEx [x] |
| windows.cpp:387:8:387:27 | [summary] to write: Argument[3].Parameter[*0] in CreateRemoteThreadEx [x] | semmle.label | [summary] to write: Argument[3].Parameter[*0] in CreateRemoteThreadEx [x] |
| windows.cpp:403:26:403:36 | *lpParameter [x] | semmle.label | *lpParameter [x] |
| windows.cpp:405:10:405:25 | *lpParameter [x] | semmle.label | *lpParameter [x] |
| windows.cpp:406:8:406:8 | *s [x] | semmle.label | *s [x] |
| windows.cpp:406:8:406:11 | x | semmle.label | x |
| windows.cpp:410:26:410:36 | *lpParameter [x] | semmle.label | *lpParameter [x] |
| windows.cpp:412:10:412:25 | *lpParameter [x] | semmle.label | *lpParameter [x] |
| windows.cpp:413:8:413:8 | *s [x] | semmle.label | *s [x] |
| windows.cpp:413:8:413:11 | x | semmle.label | x |
| windows.cpp:417:26:417:36 | *lpParameter [x] | semmle.label | *lpParameter [x] |
| windows.cpp:419:10:419:25 | *lpParameter [x] | semmle.label | *lpParameter [x] |
| windows.cpp:420:8:420:8 | *s [x] | semmle.label | *s [x] |
| windows.cpp:420:8:420:11 | x | semmle.label | x |
| windows.cpp:431:3:431:3 | *s [post update] [x] | semmle.label | *s [post update] [x] |
| windows.cpp:431:3:431:16 | ... = ... | semmle.label | ... = ... |
| windows.cpp:431:9:431:14 | call to source | semmle.label | call to source |
| windows.cpp:439:7:439:8 | *& ... [x] | semmle.label | *& ... [x] |
| windows.cpp:451:7:451:8 | *& ... [x] | semmle.label | *& ... [x] |
| windows.cpp:464:7:464:8 | *& ... [x] | semmle.label | *& ... [x] |
subpaths
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | asio_streams.cpp:100:44:100:62 | call to buffer |
| test.cpp:17:24:17:24 | x | test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | test.cpp:4:5:4:17 | [summary] to write: ReturnValue in ymlStepManual | test.cpp:17:10:17:22 | call to ymlStepManual |

View File

@@ -16,4 +16,5 @@ extensions:
- ["", "", False, "ymlStepManual", "", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["", "", False, "ymlStepGenerated", "", "", "Argument[0]", "ReturnValue", "taint", "df-generated"]
- ["", "", False, "ymlStepManual_with_body", "", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["", "", False, "ymlStepGenerated_with_body", "", "", "Argument[0]", "ReturnValue", "taint", "df-generated"]
- ["", "", False, "ymlStepGenerated_with_body", "", "", "Argument[0]", "ReturnValue", "taint", "df-generated"]
- ["", "", False, "callWithArgument", "", "", "Argument[1]", "Argument[0].Parameter[0]", "value", "manual"]

View File

@@ -8,3 +8,8 @@
| test.cpp:29:10:29:11 | y3 | test-sink |
| test.cpp:33:10:33:11 | z2 | test-sink |
| test.cpp:36:10:36:11 | z3 | test-sink |
| test.cpp:48:16:48:16 | x | test-sink |
| test.cpp:69:11:69:11 | y | test-sink |
| test.cpp:75:11:75:11 | y | test-sink |
| test.cpp:83:11:83:11 | y | test-sink |
| test.cpp:89:11:89:11 | y | test-sink |

View File

@@ -1,5 +1,7 @@
| asio_streams.cpp:87:34:87:44 | read_until output argument | remote |
| test.cpp:10:10:10:18 | call to ymlSource | local |
| test.cpp:56:8:56:16 | call to ymlSource | local |
| test.cpp:94:10:94:18 | call to ymlSource | local |
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | local |
| windows.cpp:34:17:34:38 | *call to GetEnvironmentStringsA | local |
| windows.cpp:39:36:39:38 | GetEnvironmentVariableA output argument | local |

View File

@@ -35,3 +35,71 @@ void test() {
int z3 = ymlStepGenerated_with_body(x, 0);
ymlSink(z3); // clean
}
struct S {
int x;
};
using pthread_t = unsigned long;
using pthread_attr_t = void*;
void *myThreadFunction(void *arg) {
S* s = (S *)arg;
ymlSink(s->x); // $ ir
return nullptr;
}
int pthread_create(pthread_t *thread, const pthread_attr_t * attr, void *(*start_routine)(void*), void *arg);
int test_pthread_create() {
S s;
s.x = ymlSource();
pthread_t threadId;
pthread_create(&threadId, nullptr, myThreadFunction, (void *)&s);
}
template<typename F>
void callWithArgument(F f, int x);
struct StructWithOperatorCall_has_constructor {
StructWithOperatorCall_has_constructor();
void operator()(int y) {
ymlSink(y); // $ ir
}
};
struct StructWithOperatorCall_no_constructor {
void operator()(int y) {
ymlSink(y); // $ ir
}
};
struct StructWithOperatorCall_has_constructor_2 {
StructWithOperatorCall_has_constructor_2();
void operator()(int y) {
ymlSink(y); // $ ir
}
};
struct StructWithOperatorCall_no_constructor_2 {
void operator()(int y) {
ymlSink(y); // $ ir
}
};
void test_callWithArgument() {
int x = ymlSource();
{
StructWithOperatorCall_has_constructor func;
callWithArgument(func, x);
}
{
StructWithOperatorCall_no_constructor func;
callWithArgument(func, x);
}
callWithArgument(StructWithOperatorCall_has_constructor_2(), x);
callWithArgument(StructWithOperatorCall_no_constructor_2(), x);
}

View File

@@ -335,3 +335,135 @@ void mapViewOfFile(HANDLE hMapFile) {
sink(*buffer); // $ ir
}
}
typedef struct _SECURITY_ATTRIBUTES
{
DWORD nLength;
LPVOID lpSecurityDescriptor;
BOOL bInheritHandle;
} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;
typedef DWORD (*LPTHREAD_START_ROUTINE)(
LPVOID lpThreadParameter);
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId);
HANDLE CreateRemoteThread(
HANDLE hProcess,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
);
typedef ULONG_PTR DWORD_PTR;
typedef struct _PROC_THREAD_ATTRIBUTE_ENTRY
{
DWORD_PTR Attribute;
SIZE_T cbSize;
PVOID lpValue;
} PROC_THREAD_ATTRIBUTE_ENTRY, *LPPROC_THREAD_ATTRIBUTE_ENTRY;
// This structure contains a list of attributes that have been added using UpdateProcThreadAttribute
typedef struct _PROC_THREAD_ATTRIBUTE_LIST
{
DWORD dwFlags;
ULONG Size;
ULONG Count;
ULONG Reserved;
PULONG Unknown;
PROC_THREAD_ATTRIBUTE_ENTRY Entries[1];
} PROC_THREAD_ATTRIBUTE_LIST, *LPPROC_THREAD_ATTRIBUTE_LIST;
HANDLE CreateRemoteThreadEx(
HANDLE hProcess,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList,
LPDWORD lpThreadId
);
struct S
{
int x;
};
DWORD ThreadProc1(LPVOID lpParameter)
{
S *s = (S *)lpParameter;
sink(s->x); // $ ir
return 0;
}
DWORD ThreadProc2(LPVOID lpParameter)
{
S *s = (S *)lpParameter;
sink(s->x); // $ ir
return 0;
}
DWORD ThreadProc3(LPVOID lpParameter)
{
S *s = (S *)lpParameter;
sink(s->x); // $ ir
return 0;
}
int source();
void test_create_thread()
{
SECURITY_ATTRIBUTES sa;
S s;
s.x = source();
{
DWORD threadId;
HANDLE threadHandle = CreateThread(
&sa,
0,
ThreadProc1,
&s,
0,
&threadId);
}
{
DWORD threadId;
HANDLE threadHandle = CreateRemoteThread(
nullptr,
&sa,
0,
ThreadProc2,
&s,
0,
&threadId);
}
{
DWORD threadId;
PROC_THREAD_ATTRIBUTE_LIST attrList;
HANDLE threadHandle = CreateRemoteThreadEx(
nullptr,
&sa,
0,
ThreadProc3,
&s,
0,
&attrList,
&threadId);
}
}

View File

@@ -7767,6 +7767,34 @@ WARNING: module 'TaintTracking' has been deprecated and may be removed in future
| taint.cpp:830:20:830:34 | call to indirect_source | taint.cpp:832:23:832:24 | in | |
| taint.cpp:831:15:831:17 | out | taint.cpp:832:18:832:20 | out | |
| taint.cpp:831:15:831:17 | out | taint.cpp:833:8:833:10 | out | |
| thread.cpp:10:27:10:27 | s | thread.cpp:10:27:10:27 | s | |
| thread.cpp:10:27:10:27 | s | thread.cpp:11:8:11:8 | s | |
| thread.cpp:14:26:14:26 | s | thread.cpp:15:8:15:8 | s | |
| thread.cpp:18:27:18:27 | s | thread.cpp:18:27:18:27 | s | |
| thread.cpp:18:27:18:27 | s | thread.cpp:19:8:19:8 | s | |
| thread.cpp:18:34:18:34 | y | thread.cpp:20:8:20:8 | y | |
| thread.cpp:24:5:24:5 | s | thread.cpp:25:3:25:3 | s | |
| thread.cpp:24:5:24:5 | s | thread.cpp:26:38:26:38 | s | |
| thread.cpp:24:5:24:5 | s | thread.cpp:27:37:27:37 | s | |
| thread.cpp:24:5:24:5 | s | thread.cpp:28:38:28:38 | s | |
| thread.cpp:24:5:24:5 | s | thread.cpp:32:7:32:7 | s | |
| thread.cpp:25:3:25:3 | s [post update] | thread.cpp:26:38:26:38 | s | |
| thread.cpp:25:3:25:3 | s [post update] | thread.cpp:27:37:27:37 | s | |
| thread.cpp:25:3:25:3 | s [post update] | thread.cpp:28:38:28:38 | s | |
| thread.cpp:25:3:25:3 | s [post update] | thread.cpp:32:7:32:7 | s | |
| thread.cpp:25:3:25:16 | ... = ... | thread.cpp:25:5:25:5 | x [post update] | |
| thread.cpp:25:9:25:14 | call to source | thread.cpp:25:3:25:16 | ... = ... | |
| thread.cpp:26:18:26:39 | call to thread | thread.cpp:33:1:33:1 | t1 | |
| thread.cpp:26:38:26:38 | s | thread.cpp:26:37:26:38 | & ... | |
| thread.cpp:27:18:27:38 | call to thread | thread.cpp:33:1:33:1 | t2 | |
| thread.cpp:27:37:27:37 | ref arg s | thread.cpp:28:38:28:38 | s | |
| thread.cpp:27:37:27:37 | ref arg s | thread.cpp:32:7:32:7 | s | |
| thread.cpp:28:18:28:43 | call to thread | thread.cpp:33:1:33:1 | t3 | |
| thread.cpp:28:38:28:38 | s | thread.cpp:28:37:28:38 | & ... | |
| thread.cpp:30:18:32:8 | call to thread | thread.cpp:33:1:33:1 | t4 | |
| thread.cpp:30:24:30:24 | p | thread.cpp:30:24:30:24 | p | |
| thread.cpp:30:24:30:24 | p | thread.cpp:31:10:31:10 | p | |
| thread.cpp:32:7:32:7 | s | thread.cpp:32:6:32:7 | & ... | |
| vector.cpp:16:43:16:49 | source1 | vector.cpp:17:26:17:32 | source1 | |
| vector.cpp:16:43:16:49 | source1 | vector.cpp:31:38:31:44 | source1 | |
| vector.cpp:17:21:17:33 | call to vector | vector.cpp:19:14:19:14 | v | |

View File

@@ -681,4 +681,17 @@ namespace std {
// the model for `format`.
template <typename... Args>
int same_signature_as_format_but_different_name(format_string, Args &&...args);
}
namespace std {
class thread {
public:
template<class F, class... Args>
explicit thread(F&&, Args&&...);
~thread();
void join();
void detach();
};
}

View File

@@ -0,0 +1,33 @@
#include "stl.h"
int source();
void sink(int);
struct S {
int x;
};
void thread_function_1(S* s) {
sink(s->x); // $ ir
}
void thread_function_2(S s) {
sink(s.x); // $ ir
}
void thread_function_3(S* s, int y) {
sink(s->x); // $ ir
sink(y); // clean
}
void test_thread() {
S s;
s.x = source();
std::thread t1(thread_function_1, &s);
std::thread t2(thread_function_2, s);
std::thread t3(thread_function_3, &s, 42);
std::thread t4([](S* p) {
sink(p->x); // $ ir
}, &s);
}

View File

@@ -24262,6 +24262,281 @@ ir.cpp:
# 2725| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 2725| Type = [PlainCharType] char
# 2725| ValueCategory = prvalue(load)
# 2728| [TopLevelFunction] void test_postfix_crement(int*, int)
# 2728| <params>:
# 2728| getParameter(0): [Parameter] p
# 2728| Type = [IntPointerType] int *
# 2728| getParameter(1): [Parameter] q
# 2728| Type = [IntType] int
# 2728| getEntryPoint(): [BlockStmt] { ... }
# 2729| getStmt(0): [ExprStmt] ExprStmt
# 2729| getExpr(): [PostfixIncrExpr] ... ++
# 2729| Type = [IntPointerType] int *
# 2729| ValueCategory = prvalue
# 2729| getOperand(): [VariableAccess] p
# 2729| Type = [IntPointerType] int *
# 2729| ValueCategory = lvalue
# 2730| getStmt(1): [ExprStmt] ExprStmt
# 2730| getExpr(): [PostfixIncrExpr] ... ++
# 2730| Type = [IntType] int
# 2730| ValueCategory = prvalue
# 2730| getOperand(): [VariableAccess] q
# 2730| Type = [IntType] int
# 2730| ValueCategory = lvalue
# 2731| getStmt(2): [ExprStmt] ExprStmt
# 2731| getExpr(): [PostfixIncrExpr] ... ++
# 2731| Type = [IntPointerType] int *
# 2731| ValueCategory = prvalue
# 2731| getOperand(): [VariableAccess] p
# 2731| Type = [IntPointerType] int *
# 2731| ValueCategory = lvalue
# 2731| getExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 2731| Type = [IntPointerType] int *
# 2731| ValueCategory = prvalue
# 2732| getStmt(3): [ExprStmt] ExprStmt
# 2732| getExpr(): [PostfixIncrExpr] ... ++
# 2732| Type = [IntType] int
# 2732| ValueCategory = prvalue
# 2732| getOperand(): [VariableAccess] q
# 2732| Type = [IntType] int
# 2732| ValueCategory = lvalue
# 2732| getExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 2732| Type = [IntType] int
# 2732| ValueCategory = prvalue
# 2733| getStmt(4): [ExprStmt] ExprStmt
# 2733| getExpr(): [PostfixIncrExpr] ... ++
# 2733| Type = [IntPointerType] int *
# 2733| ValueCategory = prvalue
# 2733| getOperand(): [VariableAccess] p
# 2733| Type = [IntPointerType] int *
# 2733| ValueCategory = lvalue
# 2733| getExpr().getFullyConverted(): [CStyleCast] (void)...
# 2733| Conversion = [VoidConversion] conversion to void
# 2733| Type = [VoidType] void
# 2733| ValueCategory = prvalue
# 2733| getExpr(): [ParenthesisExpr] (...)
# 2733| Type = [IntPointerType] int *
# 2733| ValueCategory = prvalue
# 2734| getStmt(5): [ExprStmt] ExprStmt
# 2734| getExpr(): [PostfixIncrExpr] ... ++
# 2734| Type = [IntType] int
# 2734| ValueCategory = prvalue
# 2734| getOperand(): [VariableAccess] q
# 2734| Type = [IntType] int
# 2734| ValueCategory = lvalue
# 2734| getExpr().getFullyConverted(): [CStyleCast] (void)...
# 2734| Conversion = [VoidConversion] conversion to void
# 2734| Type = [VoidType] void
# 2734| ValueCategory = prvalue
# 2734| getExpr(): [ParenthesisExpr] (...)
# 2734| Type = [IntType] int
# 2734| ValueCategory = prvalue
# 2735| getStmt(6): [ExprStmt] ExprStmt
# 2735| getExpr(): [PostfixIncrExpr] ... ++
# 2735| Type = [IntPointerType] int *
# 2735| ValueCategory = prvalue
# 2735| getOperand(): [VariableAccess] p
# 2735| Type = [IntPointerType] int *
# 2735| ValueCategory = lvalue
# 2735| getExpr().getFullyConverted(): [CStyleCast] (void)...
# 2735| Conversion = [VoidConversion] conversion to void
# 2735| Type = [VoidType] void
# 2735| ValueCategory = prvalue
# 2736| getStmt(7): [ExprStmt] ExprStmt
# 2736| getExpr(): [PostfixIncrExpr] ... ++
# 2736| Type = [IntType] int
# 2736| ValueCategory = prvalue
# 2736| getOperand(): [VariableAccess] q
# 2736| Type = [IntType] int
# 2736| ValueCategory = lvalue
# 2736| getExpr().getFullyConverted(): [CStyleCast] (void)...
# 2736| Conversion = [VoidConversion] conversion to void
# 2736| Type = [VoidType] void
# 2736| ValueCategory = prvalue
# 2737| getStmt(8): [DeclStmt] declaration
# 2737| getDeclarationEntry(0): [VariableDeclarationEntry] definition of p1
# 2737| Type = [IntPointerType] int *
# 2737| getVariable().getInitializer(): [Initializer] initializer for p1
# 2737| getExpr(): [PostfixIncrExpr] ... ++
# 2737| Type = [IntPointerType] int *
# 2737| ValueCategory = prvalue
# 2737| getOperand(): [VariableAccess] p
# 2737| Type = [IntPointerType] int *
# 2737| ValueCategory = lvalue
# 2738| getStmt(9): [DeclStmt] declaration
# 2738| getDeclarationEntry(0): [VariableDeclarationEntry] definition of q1
# 2738| Type = [IntType] int
# 2738| getVariable().getInitializer(): [Initializer] initializer for q1
# 2738| getExpr(): [PostfixIncrExpr] ... ++
# 2738| Type = [IntType] int
# 2738| ValueCategory = prvalue
# 2738| getOperand(): [VariableAccess] q
# 2738| Type = [IntType] int
# 2738| ValueCategory = lvalue
# 2739| getStmt(10): [ExprStmt] ExprStmt
# 2739| getExpr(): [PostfixIncrExpr] ... ++
# 2739| Type = [IntPointerType] int *
# 2739| ValueCategory = prvalue
# 2739| getOperand(): [VariableAccess] p
# 2739| Type = [IntPointerType] int *
# 2739| ValueCategory = lvalue
# 2739| getExpr().getFullyConverted(): [CStyleCast] (int *)...
# 2739| Conversion = [PointerConversion] pointer conversion
# 2739| Type = [IntPointerType] int *
# 2739| ValueCategory = prvalue
# 2739| getExpr(): [ParenthesisExpr] (...)
# 2739| Type = [IntPointerType] int *
# 2739| ValueCategory = prvalue
# 2740| getStmt(11): [ExprStmt] ExprStmt
# 2740| getExpr(): [PostfixIncrExpr] ... ++
# 2740| Type = [IntType] int
# 2740| ValueCategory = prvalue
# 2740| getOperand(): [VariableAccess] q
# 2740| Type = [IntType] int
# 2740| ValueCategory = lvalue
# 2740| getExpr().getFullyConverted(): [CStyleCast] (int)...
# 2740| Conversion = [IntegralConversion] integral conversion
# 2740| Type = [IntType] int
# 2740| ValueCategory = prvalue
# 2740| getExpr(): [ParenthesisExpr] (...)
# 2740| Type = [IntType] int
# 2740| ValueCategory = prvalue
# 2741| getStmt(12): [DeclStmt] declaration
# 2741| getDeclarationEntry(0): [VariableDeclarationEntry] definition of p2
# 2741| Type = [IntPointerType] int *
# 2741| getVariable().getInitializer(): [Initializer] initializer for p2
# 2741| getExpr(): [PostfixIncrExpr] ... ++
# 2741| Type = [IntPointerType] int *
# 2741| ValueCategory = prvalue
# 2741| getOperand(): [VariableAccess] p
# 2741| Type = [IntPointerType] int *
# 2741| ValueCategory = lvalue
# 2741| getExpr().getFullyConverted(): [CStyleCast] (int *)...
# 2741| Conversion = [PointerConversion] pointer conversion
# 2741| Type = [IntPointerType] int *
# 2741| ValueCategory = prvalue
# 2741| getExpr(): [ParenthesisExpr] (...)
# 2741| Type = [IntPointerType] int *
# 2741| ValueCategory = prvalue
# 2742| getStmt(13): [DeclStmt] declaration
# 2742| getDeclarationEntry(0): [VariableDeclarationEntry] definition of q2
# 2742| Type = [IntType] int
# 2742| getVariable().getInitializer(): [Initializer] initializer for q2
# 2742| getExpr(): [PostfixIncrExpr] ... ++
# 2742| Type = [IntType] int
# 2742| ValueCategory = prvalue
# 2742| getOperand(): [VariableAccess] q
# 2742| Type = [IntType] int
# 2742| ValueCategory = lvalue
# 2742| getExpr().getFullyConverted(): [CStyleCast] (int)...
# 2742| Conversion = [IntegralConversion] integral conversion
# 2742| Type = [IntType] int
# 2742| ValueCategory = prvalue
# 2742| getExpr(): [ParenthesisExpr] (...)
# 2742| Type = [IntType] int
# 2742| ValueCategory = prvalue
# 2743| getStmt(14): [ReturnStmt] return ...
# 2747| [CopyAssignmentOperator] std::strong_ordering& std::strong_ordering::operator=(std::strong_ordering const&)
# 2747| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const strong_ordering &
# 2747| [MoveAssignmentOperator] std::strong_ordering& std::strong_ordering::operator=(std::strong_ordering&&)
# 2747| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] strong_ordering &&
# 2747| [CopyConstructor] void std::strong_ordering::strong_ordering(std::strong_ordering const&)
# 2747| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const strong_ordering &
# 2747| [MoveConstructor] void std::strong_ordering::strong_ordering(std::strong_ordering&&)
# 2747| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] strong_ordering &&
# 2747| <initializations>:
# 2747| getEntryPoint(): [BlockStmt] { ... }
# 2747| getStmt(0): [ReturnStmt] return ...
# 2748| [Constructor] void std::strong_ordering::strong_ordering(std::_Order)
# 2748| <params>:
# 2748| getParameter(0): [Parameter] v
# 2748| Type = [ScopedEnum] _Order
# 2748| <initializations>:
# 2748| getEntryPoint(): [BlockStmt] { ... }
# 2748| getStmt(0): [ReturnStmt] return ...
# 2763| [CopyAssignmentOperator] ThreeWay& ThreeWay::operator=(ThreeWay const&)
# 2763| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const ThreeWay &
# 2763| [MoveAssignmentOperator] ThreeWay& ThreeWay::operator=(ThreeWay&&)
# 2763| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] ThreeWay &&
# 2763| [Constructor] void ThreeWay::ThreeWay()
# 2763| <params>:
# 2766| [MemberFunction] std::strong_ordering ThreeWay::operator<=>(ThreeWay&)
# 2766| <params>:
# 2766| getParameter(0): [Parameter] y
# 2766| Type = [LValueReferenceType] ThreeWay &
# 2766| getEntryPoint(): [BlockStmt] { ... }
# 2766| getStmt(0): [ReturnStmt] return ...
# 2766| getExpr(): [SpaceshipExpr] ... <=> ...
# 2766| Type = [Class] strong_ordering
# 2766| ValueCategory = prvalue
# 2766| getChild(0): [PointerFieldAccess] x
# 2766| Type = [IntType] int
# 2766| ValueCategory = prvalue(load)
# 2766| getQualifier(): [ThisExpr] this
# 2766| Type = [PointerType] ThreeWay *
# 2766| ValueCategory = prvalue(load)
# 2766| getChild(1): [ReferenceFieldAccess] x
# 2766| Type = [IntType] int
# 2766| ValueCategory = prvalue(load)
# 2766| getQualifier(): [VariableAccess] y
# 2766| Type = [LValueReferenceType] ThreeWay &
# 2766| ValueCategory = prvalue(load)
# 2766| getQualifier().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 2766| Type = [Class] ThreeWay
# 2766| ValueCategory = lvalue
# 2769| [TopLevelFunction] void test_three_way(int, int, ThreeWay, ThreeWay)
# 2769| <params>:
# 2769| getParameter(0): [Parameter] a
# 2769| Type = [IntType] int
# 2769| getParameter(1): [Parameter] b
# 2769| Type = [IntType] int
# 2769| getParameter(2): [Parameter] c
# 2769| Type = [Class] ThreeWay
# 2769| getParameter(3): [Parameter] d
# 2769| Type = [Class] ThreeWay
# 2769| getEntryPoint(): [BlockStmt] { ... }
# 2770| getStmt(0): [DeclStmt] declaration
# 2770| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
# 2770| Type = [Class] strong_ordering
# 2770| getVariable().getInitializer(): [Initializer] initializer for x
# 2770| getExpr(): [SpaceshipExpr] ... <=> ...
# 2770| Type = [Class] strong_ordering
# 2770| ValueCategory = prvalue
# 2770| getChild(0): [VariableAccess] a
# 2770| Type = [IntType] int
# 2770| ValueCategory = prvalue(load)
# 2770| getChild(1): [VariableAccess] b
# 2770| Type = [IntType] int
# 2770| ValueCategory = prvalue(load)
# 2771| getStmt(1): [DeclStmt] declaration
# 2771| getDeclarationEntry(0): [VariableDeclarationEntry] definition of y
# 2771| Type = [Class] strong_ordering
# 2771| getVariable().getInitializer(): [Initializer] initializer for y
# 2771| getExpr(): [FunctionCall] call to operator<=>
# 2771| Type = [Class] strong_ordering
# 2771| ValueCategory = prvalue
# 2771| getQualifier(): [VariableAccess] c
# 2771| Type = [Class] ThreeWay
# 2771| ValueCategory = lvalue
# 2771| getArgument(0): [VariableAccess] d
# 2771| Type = [Class] ThreeWay
# 2771| ValueCategory = lvalue
# 2771| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
# 2771| Type = [LValueReferenceType] ThreeWay &
# 2771| ValueCategory = prvalue
# 2772| getStmt(2): [ReturnStmt] return ...
ir23.cpp:
# 1| [TopLevelFunction] bool consteval_1()
# 1| <params>:
@@ -50000,3 +50275,42 @@ try_except.cpp:
# 52| Type = [IntType] int
# 52| ValueCategory = prvalue(load)
# 54| getStmt(2): [ReturnStmt] return ...
type_info_test.cpp:
# 3| [TopLevelFunction] void type_info_test(int)
# 3| <params>:
# 3| getParameter(0): [Parameter] x
# 3| Type = [IntType] int
# 3| getEntryPoint(): [BlockStmt] { ... }
# 4| getStmt(0): [DeclStmt] declaration
# 4| getDeclarationEntry(0): [VariableDeclarationEntry] definition of t1
# 4| Type = [LValueReferenceType] const type_info &
# 4| getVariable().getInitializer(): [Initializer] initializer for t1
# 4| getExpr(): [TypeidOperator] typeid ...
# 4| Type = [SpecifiedType] const type_info
# 4| ValueCategory = lvalue
# 4| getExpr(): [VariableAccess] x
# 4| Type = [IntType] int
# 4| ValueCategory = lvalue
# 4| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 4| Type = [LValueReferenceType] const type_info &
# 4| ValueCategory = prvalue
# 5| getStmt(1): [DeclStmt] declaration
# 5| getDeclarationEntry(0): [VariableDeclarationEntry] definition of t2
# 5| Type = [LValueReferenceType] const type_info &
# 5| getVariable().getInitializer(): [Initializer] initializer for t2
# 5| getExpr(): [TypeidOperator] typeid ...
# 5| Type = [SpecifiedType] const type_info
# 5| ValueCategory = lvalue
# 5| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 5| Type = [LValueReferenceType] const type_info &
# 5| ValueCategory = prvalue
# 6| getStmt(2): [ReturnStmt] return ...
typeinfo:
# 4| [CopyAssignmentOperator] std::type_info& std::type_info::operator=(std::type_info const&)
# 4| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const type_info &
# 4| [MoveAssignmentOperator] std::type_info& std::type_info::operator=(std::type_info&&)
# 4| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] type_info &&

View File

@@ -20156,6 +20156,236 @@ ir.cpp:
# 2724| v2724_12(void) = AliasedUse : ~m2725_8
# 2724| v2724_13(void) = ExitFunction :
# 2728| void test_postfix_crement(int*, int)
# 2728| Block 0
# 2728| v2728_1(void) = EnterFunction :
# 2728| m2728_2(unknown) = AliasedDefinition :
# 2728| m2728_3(unknown) = InitializeNonLocal :
# 2728| m2728_4(unknown) = Chi : total:m2728_2, partial:m2728_3
# 2728| r2728_5(glval<int *>) = VariableAddress[p] :
# 2728| m2728_6(int *) = InitializeParameter[p] : &:r2728_5
# 2728| r2728_7(int *) = Load[p] : &:r2728_5, m2728_6
# 2728| m2728_8(unknown) = InitializeIndirection[p] : &:r2728_7
# 2728| m2728_9(unknown) = Chi : total:m2728_4, partial:m2728_8
# 2728| r2728_10(glval<int>) = VariableAddress[q] :
# 2728| m2728_11(int) = InitializeParameter[q] : &:r2728_10
# 2729| r2729_1(glval<int *>) = VariableAddress[p] :
# 2729| r2729_2(int *) = Load[p] : &:r2729_1, m2728_6
# 2729| r2729_3(int) = Constant[1] :
# 2729| r2729_4(int *) = PointerAdd[4] : r2729_2, r2729_3
# 2729| m2729_5(int *) = Store[p] : &:r2729_1, r2729_4
# 2730| r2730_1(glval<int>) = VariableAddress[q] :
# 2730| r2730_2(int) = Load[q] : &:r2730_1, m2728_11
# 2730| r2730_3(int) = Constant[1] :
# 2730| r2730_4(int) = Add : r2730_2, r2730_3
# 2730| m2730_5(int) = Store[q] : &:r2730_1, r2730_4
# 2731| r2731_1(glval<int *>) = VariableAddress[p] :
# 2731| r2731_2(int *) = Load[p] : &:r2731_1, m2729_5
# 2731| r2731_3(int) = Constant[1] :
# 2731| r2731_4(int *) = PointerAdd[4] : r2731_2, r2731_3
# 2731| m2731_5(int *) = Store[p] : &:r2731_1, r2731_4
# 2731| r2731_6(int *) = CopyValue : r2731_2
# 2732| r2732_1(glval<int>) = VariableAddress[q] :
# 2732| r2732_2(int) = Load[q] : &:r2732_1, m2730_5
# 2732| r2732_3(int) = Constant[1] :
# 2732| r2732_4(int) = Add : r2732_2, r2732_3
# 2732| m2732_5(int) = Store[q] : &:r2732_1, r2732_4
# 2732| r2732_6(int) = CopyValue : r2732_2
# 2733| r2733_1(glval<int *>) = VariableAddress[p] :
# 2733| r2733_2(int *) = Load[p] : &:r2733_1, m2731_5
# 2733| r2733_3(int) = Constant[1] :
# 2733| r2733_4(int *) = PointerAdd[4] : r2733_2, r2733_3
# 2733| m2733_5(int *) = Store[p] : &:r2733_1, r2733_4
# 2733| r2733_6(int *) = CopyValue : r2733_2
# 2733| v2733_7(void) = Convert : r2733_6
# 2734| r2734_1(glval<int>) = VariableAddress[q] :
# 2734| r2734_2(int) = Load[q] : &:r2734_1, m2732_5
# 2734| r2734_3(int) = Constant[1] :
# 2734| r2734_4(int) = Add : r2734_2, r2734_3
# 2734| m2734_5(int) = Store[q] : &:r2734_1, r2734_4
# 2734| r2734_6(int) = CopyValue : r2734_2
# 2734| v2734_7(void) = Convert : r2734_6
# 2735| r2735_1(glval<int *>) = VariableAddress[p] :
# 2735| r2735_2(int *) = Load[p] : &:r2735_1, m2733_5
# 2735| r2735_3(int) = Constant[1] :
# 2735| r2735_4(int *) = PointerAdd[4] : r2735_2, r2735_3
# 2735| m2735_5(int *) = Store[p] : &:r2735_1, r2735_4
# 2735| r2735_6(int *) = CopyValue : r2735_2
# 2735| v2735_7(void) = Convert : r2735_6
# 2736| r2736_1(glval<int>) = VariableAddress[q] :
# 2736| r2736_2(int) = Load[q] : &:r2736_1, m2734_5
# 2736| r2736_3(int) = Constant[1] :
# 2736| r2736_4(int) = Add : r2736_2, r2736_3
# 2736| m2736_5(int) = Store[q] : &:r2736_1, r2736_4
# 2736| r2736_6(int) = CopyValue : r2736_2
# 2736| v2736_7(void) = Convert : r2736_6
# 2737| r2737_1(glval<int *>) = VariableAddress[p1] :
# 2737| r2737_2(glval<int *>) = VariableAddress[p] :
# 2737| r2737_3(int *) = Load[p] : &:r2737_2, m2735_5
# 2737| r2737_4(int) = Constant[1] :
# 2737| r2737_5(int *) = PointerAdd[4] : r2737_3, r2737_4
# 2737| m2737_6(int *) = Store[p] : &:r2737_2, r2737_5
# 2737| r2737_7(int *) = CopyValue : r2737_3
# 2737| m2737_8(int *) = Store[p1] : &:r2737_1, r2737_7
# 2738| r2738_1(glval<int>) = VariableAddress[q1] :
# 2738| r2738_2(glval<int>) = VariableAddress[q] :
# 2738| r2738_3(int) = Load[q] : &:r2738_2, m2736_5
# 2738| r2738_4(int) = Constant[1] :
# 2738| r2738_5(int) = Add : r2738_3, r2738_4
# 2738| m2738_6(int) = Store[q] : &:r2738_2, r2738_5
# 2738| r2738_7(int) = CopyValue : r2738_3
# 2738| m2738_8(int) = Store[q1] : &:r2738_1, r2738_7
# 2739| r2739_1(glval<int *>) = VariableAddress[p] :
# 2739| r2739_2(int *) = Load[p] : &:r2739_1, m2737_6
# 2739| r2739_3(int) = Constant[1] :
# 2739| r2739_4(int *) = PointerAdd[4] : r2739_2, r2739_3
# 2739| m2739_5(int *) = Store[p] : &:r2739_1, r2739_4
# 2739| r2739_6(int *) = CopyValue : r2739_2
# 2739| r2739_7(int *) = Convert : r2739_6
# 2740| r2740_1(glval<int>) = VariableAddress[q] :
# 2740| r2740_2(int) = Load[q] : &:r2740_1, m2738_6
# 2740| r2740_3(int) = Constant[1] :
# 2740| r2740_4(int) = Add : r2740_2, r2740_3
# 2740| m2740_5(int) = Store[q] : &:r2740_1, r2740_4
# 2740| r2740_6(int) = CopyValue : r2740_2
# 2740| r2740_7(int) = Convert : r2740_6
# 2741| r2741_1(glval<int *>) = VariableAddress[p2] :
# 2741| r2741_2(glval<int *>) = VariableAddress[p] :
# 2741| r2741_3(int *) = Load[p] : &:r2741_2, m2739_5
# 2741| r2741_4(int) = Constant[1] :
# 2741| r2741_5(int *) = PointerAdd[4] : r2741_3, r2741_4
# 2741| m2741_6(int *) = Store[p] : &:r2741_2, r2741_5
# 2741| r2741_7(int *) = CopyValue : r2741_3
# 2741| r2741_8(int *) = Convert : r2741_7
# 2741| m2741_9(int *) = Store[p2] : &:r2741_1, r2741_8
# 2742| r2742_1(glval<int>) = VariableAddress[q2] :
# 2742| r2742_2(glval<int>) = VariableAddress[q] :
# 2742| r2742_3(int) = Load[q] : &:r2742_2, m2740_5
# 2742| r2742_4(int) = Constant[1] :
# 2742| r2742_5(int) = Add : r2742_3, r2742_4
# 2742| m2742_6(int) = Store[q] : &:r2742_2, r2742_5
# 2742| r2742_7(int) = CopyValue : r2742_3
# 2742| r2742_8(int) = Convert : r2742_7
# 2742| m2742_9(int) = Store[q2] : &:r2742_1, r2742_8
# 2743| v2743_1(void) = NoOp :
# 2728| v2728_12(void) = ReturnIndirection[p] : &:r2728_7, m2728_8
# 2728| v2728_13(void) = ReturnVoid :
# 2728| v2728_14(void) = AliasedUse : ~m2728_9
# 2728| v2728_15(void) = ExitFunction :
# 2747| void std::strong_ordering::strong_ordering(std::strong_ordering&&)
# 2747| Block 0
# 2747| v2747_1(void) = EnterFunction :
# 2747| m2747_2(unknown) = AliasedDefinition :
# 2747| m2747_3(unknown) = InitializeNonLocal :
# 2747| m2747_4(unknown) = Chi : total:m2747_2, partial:m2747_3
# 2747| r2747_5(glval<unknown>) = VariableAddress[#this] :
# 2747| m2747_6(glval<strong_ordering>) = InitializeParameter[#this] : &:r2747_5
# 2747| r2747_7(glval<strong_ordering>) = Load[#this] : &:r2747_5, m2747_6
# 2747| m2747_8(strong_ordering) = InitializeIndirection[#this] : &:r2747_7
#-----| r0_1(glval<strong_ordering &&>) = VariableAddress[(unnamed parameter 0)] :
#-----| m0_2(strong_ordering &&) = InitializeParameter[(unnamed parameter 0)] : &:r0_1
#-----| r0_3(strong_ordering &&) = Load[(unnamed parameter 0)] : &:r0_1, m0_2
#-----| m0_4(unknown) = InitializeIndirection[(unnamed parameter 0)] : &:r0_3
# 2747| v2747_9(void) = NoOp :
# 2747| v2747_10(void) = ReturnIndirection[#this] : &:r2747_7, m2747_8
#-----| v0_5(void) = ReturnIndirection[(unnamed parameter 0)] : &:r0_3, m0_4
# 2747| v2747_11(void) = ReturnVoid :
# 2747| v2747_12(void) = AliasedUse : m2747_3
# 2747| v2747_13(void) = ExitFunction :
# 2748| void std::strong_ordering::strong_ordering(std::_Order)
# 2748| Block 0
# 2748| v2748_1(void) = EnterFunction :
# 2748| m2748_2(unknown) = AliasedDefinition :
# 2748| m2748_3(unknown) = InitializeNonLocal :
# 2748| m2748_4(unknown) = Chi : total:m2748_2, partial:m2748_3
# 2748| r2748_5(glval<unknown>) = VariableAddress[#this] :
# 2748| m2748_6(glval<strong_ordering>) = InitializeParameter[#this] : &:r2748_5
# 2748| r2748_7(glval<strong_ordering>) = Load[#this] : &:r2748_5, m2748_6
# 2748| m2748_8(strong_ordering) = InitializeIndirection[#this] : &:r2748_7
# 2748| r2748_9(glval<_Order>) = VariableAddress[v] :
# 2748| m2748_10(_Order) = InitializeParameter[v] : &:r2748_9
# 2748| v2748_11(void) = NoOp :
# 2748| v2748_12(void) = ReturnIndirection[#this] : &:r2748_7, m2748_8
# 2748| v2748_13(void) = ReturnVoid :
# 2748| v2748_14(void) = AliasedUse : m2748_3
# 2748| v2748_15(void) = ExitFunction :
# 2766| std::strong_ordering ThreeWay::operator<=>(ThreeWay&)
# 2766| Block 0
# 2766| v2766_1(void) = EnterFunction :
# 2766| m2766_2(unknown) = AliasedDefinition :
# 2766| m2766_3(unknown) = InitializeNonLocal :
# 2766| m2766_4(unknown) = Chi : total:m2766_2, partial:m2766_3
# 2766| r2766_5(glval<unknown>) = VariableAddress[#this] :
# 2766| m2766_6(glval<ThreeWay>) = InitializeParameter[#this] : &:r2766_5
# 2766| r2766_7(glval<ThreeWay>) = Load[#this] : &:r2766_5, m2766_6
# 2766| m2766_8(ThreeWay) = InitializeIndirection[#this] : &:r2766_7
# 2766| r2766_9(glval<ThreeWay &>) = VariableAddress[y] :
# 2766| m2766_10(ThreeWay &) = InitializeParameter[y] : &:r2766_9
# 2766| r2766_11(ThreeWay &) = Load[y] : &:r2766_9, m2766_10
# 2766| m2766_12(unknown) = InitializeIndirection[y] : &:r2766_11
# 2766| r2766_13(glval<strong_ordering>) = VariableAddress[#return] :
# 2766| r2766_14(glval<unknown>) = VariableAddress[#this] :
# 2766| r2766_15(ThreeWay *) = Load[#this] : &:r2766_14, m2766_6
# 2766| r2766_16(glval<int>) = FieldAddress[x] : r2766_15
# 2766| r2766_17(int) = Load[?] : &:r2766_16, ~m2766_8
# 2766| r2766_18(glval<ThreeWay &>) = VariableAddress[y] :
# 2766| r2766_19(ThreeWay &) = Load[y] : &:r2766_18, m2766_10
# 2766| r2766_20(glval<ThreeWay>) = CopyValue : r2766_19
# 2766| r2766_21(glval<int>) = FieldAddress[x] : r2766_20
# 2766| r2766_22(int) = Load[?] : &:r2766_21, ~m2766_12
# 2766| r2766_23(strong_ordering) = Spaceship : r2766_17, r2766_22
# 2766| m2766_24(strong_ordering) = Store[#return] : &:r2766_13, r2766_23
# 2766| v2766_25(void) = ReturnIndirection[#this] : &:r2766_7, m2766_8
# 2766| v2766_26(void) = ReturnIndirection[y] : &:r2766_11, m2766_12
# 2766| r2766_27(glval<strong_ordering>) = VariableAddress[#return] :
# 2766| v2766_28(void) = ReturnValue : &:r2766_27, m2766_24
# 2766| v2766_29(void) = AliasedUse : m2766_3
# 2766| v2766_30(void) = ExitFunction :
# 2769| void test_three_way(int, int, ThreeWay, ThreeWay)
# 2769| Block 0
# 2769| v2769_1(void) = EnterFunction :
# 2769| m2769_2(unknown) = AliasedDefinition :
# 2769| m2769_3(unknown) = InitializeNonLocal :
# 2769| m2769_4(unknown) = Chi : total:m2769_2, partial:m2769_3
# 2769| r2769_5(glval<int>) = VariableAddress[a] :
# 2769| m2769_6(int) = InitializeParameter[a] : &:r2769_5
# 2769| r2769_7(glval<int>) = VariableAddress[b] :
# 2769| m2769_8(int) = InitializeParameter[b] : &:r2769_7
# 2769| r2769_9(glval<ThreeWay>) = VariableAddress[c] :
# 2769| m2769_10(ThreeWay) = InitializeParameter[c] : &:r2769_9
# 2769| r2769_11(glval<ThreeWay>) = VariableAddress[d] :
# 2769| m2769_12(ThreeWay) = InitializeParameter[d] : &:r2769_11
# 2770| r2770_1(glval<strong_ordering>) = VariableAddress[x] :
# 2770| r2770_2(glval<int>) = VariableAddress[a] :
# 2770| r2770_3(int) = Load[a] : &:r2770_2, m2769_6
# 2770| r2770_4(glval<int>) = VariableAddress[b] :
# 2770| r2770_5(int) = Load[b] : &:r2770_4, m2769_8
# 2770| r2770_6(strong_ordering) = Spaceship : r2770_3, r2770_5
# 2770| m2770_7(strong_ordering) = Store[x] : &:r2770_1, r2770_6
# 2771| r2771_1(glval<strong_ordering>) = VariableAddress[y] :
# 2771| r2771_2(glval<ThreeWay>) = VariableAddress[c] :
# 2771| r2771_3(glval<unknown>) = FunctionAddress[operator<=>] :
# 2771| r2771_4(glval<ThreeWay>) = VariableAddress[d] :
# 2771| r2771_5(ThreeWay &) = CopyValue : r2771_4
# 2771| r2771_6(strong_ordering) = Call[operator<=>] : func:r2771_3, this:r2771_2, 0:r2771_5
# 2771| m2771_7(unknown) = ^CallSideEffect : ~m2769_4
# 2771| m2771_8(unknown) = Chi : total:m2769_4, partial:m2771_7
# 2771| v2771_9(void) = ^IndirectReadSideEffect[-1] : &:r2771_2, m2769_10
# 2771| v2771_10(void) = ^BufferReadSideEffect[0] : &:r2771_5, ~m2769_12
# 2771| m2771_11(ThreeWay) = ^IndirectMayWriteSideEffect[-1] : &:r2771_2
# 2771| m2771_12(ThreeWay) = Chi : total:m2769_10, partial:m2771_11
# 2771| m2771_13(unknown) = ^BufferMayWriteSideEffect[0] : &:r2771_5
# 2771| m2771_14(ThreeWay) = Chi : total:m2769_12, partial:m2771_13
# 2771| m2771_15(strong_ordering) = Store[y] : &:r2771_1, r2771_6
# 2772| v2772_1(void) = NoOp :
# 2769| v2769_13(void) = ReturnVoid :
# 2769| v2769_14(void) = AliasedUse : ~m2771_8
# 2769| v2769_15(void) = ExitFunction :
ir23.cpp:
# 1| bool consteval_1()
# 1| Block 0
@@ -39856,3 +40086,27 @@ try_except.cpp:
# 44| Block 7
# 44| v44_10(void) = Unreached :
type_info_test.cpp:
# 3| void type_info_test(int)
# 3| Block 0
# 3| v3_1(void) = EnterFunction :
# 3| m3_2(unknown) = AliasedDefinition :
# 3| m3_3(unknown) = InitializeNonLocal :
# 3| m3_4(unknown) = Chi : total:m3_2, partial:m3_3
# 3| r3_5(glval<int>) = VariableAddress[x] :
# 3| m3_6(int) = InitializeParameter[x] : &:r3_5
# 3| m3_7(unknown) = Chi : total:m3_4, partial:m3_6
# 4| r4_1(glval<type_info &>) = VariableAddress[t1] :
# 4| r4_2(glval<int>) = VariableAddress[x] :
# 4| r4_3(glval<type_info>) = TypeidExpr : r4_2
# 4| r4_4(type_info &) = CopyValue : r4_3
# 4| m4_5(type_info &) = Store[t1] : &:r4_1, r4_4
# 5| r5_1(glval<type_info &>) = VariableAddress[t2] :
# 5| r5_2(glval<type_info>) = TypeidType :
# 5| r5_3(type_info &) = CopyValue : r5_2
# 5| m5_4(type_info &) = Store[t2] : &:r5_1, r5_3
# 6| v6_1(void) = NoOp :
# 3| v3_8(void) = ReturnVoid :
# 3| v3_9(void) = AliasedUse : m3_3
# 3| v3_10(void) = ExitFunction :

View File

@@ -2725,4 +2725,50 @@ char UseBracketOperator(const WithBracketOperator x, int i) {
return x[i];
}
void test_postfix_crement(int *p, int q) {
p++;
q++;
(p++);
(q++);
(void)(p++);
(void)(q++);
(void)p++;
(void)q++;
int *p1 = p++;
int q1 = q++;
(int*)(p++);
(int)(q++);
int *p2 = (int*)(p++);
int q2 = (int)(q++);
}
namespace std {
enum class _Order : signed char { __less = -1, __equiv = 0, __greater = 1 };
class strong_ordering {
explicit constexpr strong_ordering(_Order v) {}
public:
static const strong_ordering less;
static const strong_ordering equal;
static const strong_ordering equivalent;
static const strong_ordering greater;
};
inline constexpr strong_ordering strong_ordering::less(_Order::__less);
inline constexpr strong_ordering strong_ordering::equal(_Order::__equiv);
inline constexpr strong_ordering strong_ordering::equivalent(_Order::__equiv);
inline constexpr strong_ordering strong_ordering::greater(_Order::__greater);
}
class ThreeWay {
int x;
public:
std::strong_ordering operator<=>(ThreeWay &y) { return this->x <=> y.x; }
};
void test_three_way(int a, int b, ThreeWay c, ThreeWay d) {
auto x = a <=> b;
auto y = c <=> d;
}
// semmle-extractor-options: -std=c++20 --clang

View File

@@ -18317,6 +18317,227 @@ ir.cpp:
# 2724| v2724_10(void) = AliasedUse : ~m?
# 2724| v2724_11(void) = ExitFunction :
# 2728| void test_postfix_crement(int*, int)
# 2728| Block 0
# 2728| v2728_1(void) = EnterFunction :
# 2728| mu2728_2(unknown) = AliasedDefinition :
# 2728| mu2728_3(unknown) = InitializeNonLocal :
# 2728| r2728_4(glval<int *>) = VariableAddress[p] :
# 2728| mu2728_5(int *) = InitializeParameter[p] : &:r2728_4
# 2728| r2728_6(int *) = Load[p] : &:r2728_4, ~m?
# 2728| mu2728_7(unknown) = InitializeIndirection[p] : &:r2728_6
# 2728| r2728_8(glval<int>) = VariableAddress[q] :
# 2728| mu2728_9(int) = InitializeParameter[q] : &:r2728_8
# 2729| r2729_1(glval<int *>) = VariableAddress[p] :
# 2729| r2729_2(int *) = Load[p] : &:r2729_1, ~m?
# 2729| r2729_3(int) = Constant[1] :
# 2729| r2729_4(int *) = PointerAdd[4] : r2729_2, r2729_3
# 2729| mu2729_5(int *) = Store[p] : &:r2729_1, r2729_4
# 2730| r2730_1(glval<int>) = VariableAddress[q] :
# 2730| r2730_2(int) = Load[q] : &:r2730_1, ~m?
# 2730| r2730_3(int) = Constant[1] :
# 2730| r2730_4(int) = Add : r2730_2, r2730_3
# 2730| mu2730_5(int) = Store[q] : &:r2730_1, r2730_4
# 2731| r2731_1(glval<int *>) = VariableAddress[p] :
# 2731| r2731_2(int *) = Load[p] : &:r2731_1, ~m?
# 2731| r2731_3(int) = Constant[1] :
# 2731| r2731_4(int *) = PointerAdd[4] : r2731_2, r2731_3
# 2731| mu2731_5(int *) = Store[p] : &:r2731_1, r2731_4
# 2731| r2731_6(int *) = CopyValue : r2731_2
# 2732| r2732_1(glval<int>) = VariableAddress[q] :
# 2732| r2732_2(int) = Load[q] : &:r2732_1, ~m?
# 2732| r2732_3(int) = Constant[1] :
# 2732| r2732_4(int) = Add : r2732_2, r2732_3
# 2732| mu2732_5(int) = Store[q] : &:r2732_1, r2732_4
# 2732| r2732_6(int) = CopyValue : r2732_2
# 2733| r2733_1(glval<int *>) = VariableAddress[p] :
# 2733| r2733_2(int *) = Load[p] : &:r2733_1, ~m?
# 2733| r2733_3(int) = Constant[1] :
# 2733| r2733_4(int *) = PointerAdd[4] : r2733_2, r2733_3
# 2733| mu2733_5(int *) = Store[p] : &:r2733_1, r2733_4
# 2733| r2733_6(int *) = CopyValue : r2733_2
# 2733| v2733_7(void) = Convert : r2733_6
# 2734| r2734_1(glval<int>) = VariableAddress[q] :
# 2734| r2734_2(int) = Load[q] : &:r2734_1, ~m?
# 2734| r2734_3(int) = Constant[1] :
# 2734| r2734_4(int) = Add : r2734_2, r2734_3
# 2734| mu2734_5(int) = Store[q] : &:r2734_1, r2734_4
# 2734| r2734_6(int) = CopyValue : r2734_2
# 2734| v2734_7(void) = Convert : r2734_6
# 2735| r2735_1(glval<int *>) = VariableAddress[p] :
# 2735| r2735_2(int *) = Load[p] : &:r2735_1, ~m?
# 2735| r2735_3(int) = Constant[1] :
# 2735| r2735_4(int *) = PointerAdd[4] : r2735_2, r2735_3
# 2735| mu2735_5(int *) = Store[p] : &:r2735_1, r2735_4
# 2735| r2735_6(int *) = CopyValue : r2735_2
# 2735| v2735_7(void) = Convert : r2735_6
# 2736| r2736_1(glval<int>) = VariableAddress[q] :
# 2736| r2736_2(int) = Load[q] : &:r2736_1, ~m?
# 2736| r2736_3(int) = Constant[1] :
# 2736| r2736_4(int) = Add : r2736_2, r2736_3
# 2736| mu2736_5(int) = Store[q] : &:r2736_1, r2736_4
# 2736| r2736_6(int) = CopyValue : r2736_2
# 2736| v2736_7(void) = Convert : r2736_6
# 2737| r2737_1(glval<int *>) = VariableAddress[p1] :
# 2737| r2737_2(glval<int *>) = VariableAddress[p] :
# 2737| r2737_3(int *) = Load[p] : &:r2737_2, ~m?
# 2737| r2737_4(int) = Constant[1] :
# 2737| r2737_5(int *) = PointerAdd[4] : r2737_3, r2737_4
# 2737| mu2737_6(int *) = Store[p] : &:r2737_2, r2737_5
# 2737| r2737_7(int *) = CopyValue : r2737_3
# 2737| mu2737_8(int *) = Store[p1] : &:r2737_1, r2737_7
# 2738| r2738_1(glval<int>) = VariableAddress[q1] :
# 2738| r2738_2(glval<int>) = VariableAddress[q] :
# 2738| r2738_3(int) = Load[q] : &:r2738_2, ~m?
# 2738| r2738_4(int) = Constant[1] :
# 2738| r2738_5(int) = Add : r2738_3, r2738_4
# 2738| mu2738_6(int) = Store[q] : &:r2738_2, r2738_5
# 2738| r2738_7(int) = CopyValue : r2738_3
# 2738| mu2738_8(int) = Store[q1] : &:r2738_1, r2738_7
# 2739| r2739_1(glval<int *>) = VariableAddress[p] :
# 2739| r2739_2(int *) = Load[p] : &:r2739_1, ~m?
# 2739| r2739_3(int) = Constant[1] :
# 2739| r2739_4(int *) = PointerAdd[4] : r2739_2, r2739_3
# 2739| mu2739_5(int *) = Store[p] : &:r2739_1, r2739_4
# 2739| r2739_6(int *) = CopyValue : r2739_2
# 2739| r2739_7(int *) = Convert : r2739_6
# 2740| r2740_1(glval<int>) = VariableAddress[q] :
# 2740| r2740_2(int) = Load[q] : &:r2740_1, ~m?
# 2740| r2740_3(int) = Constant[1] :
# 2740| r2740_4(int) = Add : r2740_2, r2740_3
# 2740| mu2740_5(int) = Store[q] : &:r2740_1, r2740_4
# 2740| r2740_6(int) = CopyValue : r2740_2
# 2740| r2740_7(int) = Convert : r2740_6
# 2741| r2741_1(glval<int *>) = VariableAddress[p2] :
# 2741| r2741_2(glval<int *>) = VariableAddress[p] :
# 2741| r2741_3(int *) = Load[p] : &:r2741_2, ~m?
# 2741| r2741_4(int) = Constant[1] :
# 2741| r2741_5(int *) = PointerAdd[4] : r2741_3, r2741_4
# 2741| mu2741_6(int *) = Store[p] : &:r2741_2, r2741_5
# 2741| r2741_7(int *) = CopyValue : r2741_3
# 2741| r2741_8(int *) = Convert : r2741_7
# 2741| mu2741_9(int *) = Store[p2] : &:r2741_1, r2741_8
# 2742| r2742_1(glval<int>) = VariableAddress[q2] :
# 2742| r2742_2(glval<int>) = VariableAddress[q] :
# 2742| r2742_3(int) = Load[q] : &:r2742_2, ~m?
# 2742| r2742_4(int) = Constant[1] :
# 2742| r2742_5(int) = Add : r2742_3, r2742_4
# 2742| mu2742_6(int) = Store[q] : &:r2742_2, r2742_5
# 2742| r2742_7(int) = CopyValue : r2742_3
# 2742| r2742_8(int) = Convert : r2742_7
# 2742| mu2742_9(int) = Store[q2] : &:r2742_1, r2742_8
# 2743| v2743_1(void) = NoOp :
# 2728| v2728_10(void) = ReturnIndirection[p] : &:r2728_6, ~m?
# 2728| v2728_11(void) = ReturnVoid :
# 2728| v2728_12(void) = AliasedUse : ~m?
# 2728| v2728_13(void) = ExitFunction :
# 2747| void std::strong_ordering::strong_ordering(std::strong_ordering&&)
# 2747| Block 0
# 2747| v2747_1(void) = EnterFunction :
# 2747| mu2747_2(unknown) = AliasedDefinition :
# 2747| mu2747_3(unknown) = InitializeNonLocal :
# 2747| r2747_4(glval<unknown>) = VariableAddress[#this] :
# 2747| mu2747_5(glval<strong_ordering>) = InitializeParameter[#this] : &:r2747_4
# 2747| r2747_6(glval<strong_ordering>) = Load[#this] : &:r2747_4, ~m?
# 2747| mu2747_7(strong_ordering) = InitializeIndirection[#this] : &:r2747_6
#-----| r0_1(glval<strong_ordering &&>) = VariableAddress[(unnamed parameter 0)] :
#-----| mu0_2(strong_ordering &&) = InitializeParameter[(unnamed parameter 0)] : &:r0_1
#-----| r0_3(strong_ordering &&) = Load[(unnamed parameter 0)] : &:r0_1, ~m?
#-----| mu0_4(unknown) = InitializeIndirection[(unnamed parameter 0)] : &:r0_3
# 2747| v2747_8(void) = NoOp :
# 2747| v2747_9(void) = ReturnIndirection[#this] : &:r2747_6, ~m?
#-----| v0_5(void) = ReturnIndirection[(unnamed parameter 0)] : &:r0_3, ~m?
# 2747| v2747_10(void) = ReturnVoid :
# 2747| v2747_11(void) = AliasedUse : ~m?
# 2747| v2747_12(void) = ExitFunction :
# 2748| void std::strong_ordering::strong_ordering(std::_Order)
# 2748| Block 0
# 2748| v2748_1(void) = EnterFunction :
# 2748| mu2748_2(unknown) = AliasedDefinition :
# 2748| mu2748_3(unknown) = InitializeNonLocal :
# 2748| r2748_4(glval<unknown>) = VariableAddress[#this] :
# 2748| mu2748_5(glval<strong_ordering>) = InitializeParameter[#this] : &:r2748_4
# 2748| r2748_6(glval<strong_ordering>) = Load[#this] : &:r2748_4, ~m?
# 2748| mu2748_7(strong_ordering) = InitializeIndirection[#this] : &:r2748_6
# 2748| r2748_8(glval<_Order>) = VariableAddress[v] :
# 2748| mu2748_9(_Order) = InitializeParameter[v] : &:r2748_8
# 2748| v2748_10(void) = NoOp :
# 2748| v2748_11(void) = ReturnIndirection[#this] : &:r2748_6, ~m?
# 2748| v2748_12(void) = ReturnVoid :
# 2748| v2748_13(void) = AliasedUse : ~m?
# 2748| v2748_14(void) = ExitFunction :
# 2766| std::strong_ordering ThreeWay::operator<=>(ThreeWay&)
# 2766| Block 0
# 2766| v2766_1(void) = EnterFunction :
# 2766| mu2766_2(unknown) = AliasedDefinition :
# 2766| mu2766_3(unknown) = InitializeNonLocal :
# 2766| r2766_4(glval<unknown>) = VariableAddress[#this] :
# 2766| mu2766_5(glval<ThreeWay>) = InitializeParameter[#this] : &:r2766_4
# 2766| r2766_6(glval<ThreeWay>) = Load[#this] : &:r2766_4, ~m?
# 2766| mu2766_7(ThreeWay) = InitializeIndirection[#this] : &:r2766_6
# 2766| r2766_8(glval<ThreeWay &>) = VariableAddress[y] :
# 2766| mu2766_9(ThreeWay &) = InitializeParameter[y] : &:r2766_8
# 2766| r2766_10(ThreeWay &) = Load[y] : &:r2766_8, ~m?
# 2766| mu2766_11(unknown) = InitializeIndirection[y] : &:r2766_10
# 2766| r2766_12(glval<strong_ordering>) = VariableAddress[#return] :
# 2766| r2766_13(glval<unknown>) = VariableAddress[#this] :
# 2766| r2766_14(ThreeWay *) = Load[#this] : &:r2766_13, ~m?
# 2766| r2766_15(glval<int>) = FieldAddress[x] : r2766_14
# 2766| r2766_16(int) = Load[?] : &:r2766_15, ~m?
# 2766| r2766_17(glval<ThreeWay &>) = VariableAddress[y] :
# 2766| r2766_18(ThreeWay &) = Load[y] : &:r2766_17, ~m?
# 2766| r2766_19(glval<ThreeWay>) = CopyValue : r2766_18
# 2766| r2766_20(glval<int>) = FieldAddress[x] : r2766_19
# 2766| r2766_21(int) = Load[?] : &:r2766_20, ~m?
# 2766| r2766_22(strong_ordering) = Spaceship : r2766_16, r2766_21
# 2766| mu2766_23(strong_ordering) = Store[#return] : &:r2766_12, r2766_22
# 2766| v2766_24(void) = ReturnIndirection[#this] : &:r2766_6, ~m?
# 2766| v2766_25(void) = ReturnIndirection[y] : &:r2766_10, ~m?
# 2766| r2766_26(glval<strong_ordering>) = VariableAddress[#return] :
# 2766| v2766_27(void) = ReturnValue : &:r2766_26, ~m?
# 2766| v2766_28(void) = AliasedUse : ~m?
# 2766| v2766_29(void) = ExitFunction :
# 2769| void test_three_way(int, int, ThreeWay, ThreeWay)
# 2769| Block 0
# 2769| v2769_1(void) = EnterFunction :
# 2769| mu2769_2(unknown) = AliasedDefinition :
# 2769| mu2769_3(unknown) = InitializeNonLocal :
# 2769| r2769_4(glval<int>) = VariableAddress[a] :
# 2769| mu2769_5(int) = InitializeParameter[a] : &:r2769_4
# 2769| r2769_6(glval<int>) = VariableAddress[b] :
# 2769| mu2769_7(int) = InitializeParameter[b] : &:r2769_6
# 2769| r2769_8(glval<ThreeWay>) = VariableAddress[c] :
# 2769| mu2769_9(ThreeWay) = InitializeParameter[c] : &:r2769_8
# 2769| r2769_10(glval<ThreeWay>) = VariableAddress[d] :
# 2769| mu2769_11(ThreeWay) = InitializeParameter[d] : &:r2769_10
# 2770| r2770_1(glval<strong_ordering>) = VariableAddress[x] :
# 2770| r2770_2(glval<int>) = VariableAddress[a] :
# 2770| r2770_3(int) = Load[a] : &:r2770_2, ~m?
# 2770| r2770_4(glval<int>) = VariableAddress[b] :
# 2770| r2770_5(int) = Load[b] : &:r2770_4, ~m?
# 2770| r2770_6(strong_ordering) = Spaceship : r2770_3, r2770_5
# 2770| mu2770_7(strong_ordering) = Store[x] : &:r2770_1, r2770_6
# 2771| r2771_1(glval<strong_ordering>) = VariableAddress[y] :
# 2771| r2771_2(glval<ThreeWay>) = VariableAddress[c] :
# 2771| r2771_3(glval<unknown>) = FunctionAddress[operator<=>] :
# 2771| r2771_4(glval<ThreeWay>) = VariableAddress[d] :
# 2771| r2771_5(ThreeWay &) = CopyValue : r2771_4
# 2771| r2771_6(strong_ordering) = Call[operator<=>] : func:r2771_3, this:r2771_2, 0:r2771_5
# 2771| mu2771_7(unknown) = ^CallSideEffect : ~m?
# 2771| v2771_8(void) = ^IndirectReadSideEffect[-1] : &:r2771_2, ~m?
# 2771| v2771_9(void) = ^BufferReadSideEffect[0] : &:r2771_5, ~m?
# 2771| mu2771_10(ThreeWay) = ^IndirectMayWriteSideEffect[-1] : &:r2771_2
# 2771| mu2771_11(unknown) = ^BufferMayWriteSideEffect[0] : &:r2771_5
# 2771| mu2771_12(strong_ordering) = Store[y] : &:r2771_1, r2771_6
# 2772| v2772_1(void) = NoOp :
# 2769| v2769_12(void) = ReturnVoid :
# 2769| v2769_13(void) = AliasedUse : ~m?
# 2769| v2769_14(void) = ExitFunction :
ir23.cpp:
# 1| bool consteval_1()
# 1| Block 0
@@ -37987,3 +38208,25 @@ try_except.cpp:
# 54| v54_1(void) = NoOp :
# 44| v44_9(void) = ReturnVoid :
#-----| Goto -> Block 1
type_info_test.cpp:
# 3| void type_info_test(int)
# 3| Block 0
# 3| v3_1(void) = EnterFunction :
# 3| mu3_2(unknown) = AliasedDefinition :
# 3| mu3_3(unknown) = InitializeNonLocal :
# 3| r3_4(glval<int>) = VariableAddress[x] :
# 3| mu3_5(int) = InitializeParameter[x] : &:r3_4
# 4| r4_1(glval<type_info &>) = VariableAddress[t1] :
# 4| r4_2(glval<int>) = VariableAddress[x] :
# 4| r4_3(glval<type_info>) = TypeidExpr : r4_2
# 4| r4_4(type_info &) = CopyValue : r4_3
# 4| mu4_5(type_info &) = Store[t1] : &:r4_1, r4_4
# 5| r5_1(glval<type_info &>) = VariableAddress[t2] :
# 5| r5_2(glval<type_info>) = TypeidType :
# 5| r5_3(type_info &) = CopyValue : r5_2
# 5| mu5_4(type_info &) = Store[t2] : &:r5_1, r5_3
# 6| v6_1(void) = NoOp :
# 3| v3_6(void) = ReturnVoid :
# 3| v3_7(void) = AliasedUse : ~m?
# 3| v3_8(void) = ExitFunction :

View File

@@ -0,0 +1,8 @@
#include <typeinfo>
void type_info_test(int x) {
const std::type_info &t1 = typeid(x);
const std::type_info &t2 = typeid(int);
}
// semmle-extractor-options: -I.

View File

@@ -0,0 +1,5 @@
#pragma once
namespace std{
class type_info {};
}

View File

@@ -1,9 +1,6 @@
edges
| consts.cpp:24:7:24:9 | **gv1 | consts.cpp:25:2:25:4 | *a | provenance | |
| consts.cpp:24:7:24:9 | **gv1 | consts.cpp:30:9:30:14 | *access to array | provenance | |
| consts.cpp:24:7:24:9 | **gv1 | consts.cpp:123:2:123:12 | *... = ... | provenance | |
| consts.cpp:25:2:25:4 | *a | consts.cpp:26:2:26:4 | *{...} | provenance | |
| consts.cpp:26:2:26:4 | *{...} | consts.cpp:24:7:24:9 | **gv1 | provenance | |
| consts.cpp:29:7:29:25 | **nonConstFuncToArray | consts.cpp:126:9:126:30 | *call to nonConstFuncToArray | provenance | |
| consts.cpp:30:9:30:14 | *access to array | consts.cpp:29:7:29:25 | **nonConstFuncToArray | provenance | |
| consts.cpp:85:7:85:8 | gets output argument | consts.cpp:86:9:86:10 | *v1 | provenance | |
@@ -38,8 +35,6 @@ edges
| consts.cpp:144:16:144:18 | readStringRef output argument | consts.cpp:145:9:145:11 | *v12 | provenance | |
nodes
| consts.cpp:24:7:24:9 | **gv1 | semmle.label | **gv1 |
| consts.cpp:25:2:25:4 | *a | semmle.label | *a |
| consts.cpp:26:2:26:4 | *{...} | semmle.label | *{...} |
| consts.cpp:29:7:29:25 | **nonConstFuncToArray | semmle.label | **nonConstFuncToArray |
| consts.cpp:30:9:30:14 | *access to array | semmle.label | *access to array |
| consts.cpp:85:7:85:8 | gets output argument | semmle.label | gets output argument |

View File

@@ -18,13 +18,13 @@ void Test()
wchar_t *lpWchar = NULL;
LPCSTR lpcstr = "b";
lpWchar = (LPWSTR)"a"; // BUG
lpWchar = (LPWSTR)lpcstr; // BUG
lpWchar = (LPWSTR)"a"; // $ Alert
lpWchar = (LPWSTR)lpcstr; // $ Alert
lpWchar = (wchar_t*)lpChar; // BUG
lpWchar = (wchar_t*)lpChar; // $ Alert
fconstWChar((LPCWSTR)lpChar); // BUG
fWChar((LPWSTR)lpChar); // BUG
fconstWChar((LPCWSTR)lpChar); // $ Alert
fWChar((LPWSTR)lpChar); // $ Alert
lpChar = (LPSTR)"a"; // Valid
lpWchar = (LPWSTR)L"a"; // Valid
@@ -79,33 +79,64 @@ void CheckedConversionFalsePositiveTest3(unsigned short flags, LPTSTR buffer)
if(flags & UNICODE)
lpWchar = (LPWSTR)buffer; // GOOD
else
lpWchar = (LPWSTR)buffer; // BUG
lpWchar = (LPWSTR)buffer; // $ Alert
if((flags & UNICODE) == 0x8)
lpWchar = (LPWSTR)buffer; // GOOD
else
lpWchar = (LPWSTR)buffer; // BUG
lpWchar = (LPWSTR)buffer; // $ Alert
if((flags & UNICODE) != 0x8)
lpWchar = (LPWSTR)buffer; // BUG
lpWchar = (LPWSTR)buffer; // $ Alert
else
lpWchar = (LPWSTR)buffer; // GOOD
// Bad operator precedence
if(flags & UNICODE == 0x8)
lpWchar = (LPWSTR)buffer; // BUG
lpWchar = (LPWSTR)buffer; // $ Alert
else
lpWchar = (LPWSTR)buffer; // BUG
lpWchar = (LPWSTR)buffer; // $ Alert
if((flags & UNICODE) != 0)
lpWchar = (LPWSTR)buffer; // GOOD
else
lpWchar = (LPWSTR)buffer; // BUG
lpWchar = (LPWSTR)buffer; // $ Alert
if((flags & UNICODE) == 0)
lpWchar = (LPWSTR)buffer; // BUG
lpWchar = (LPWSTR)buffer; // $ Alert
else
lpWchar = (LPWSTR)buffer; // GOOD
lpWchar = (LPWSTR)buffer; // BUG
lpWchar = (LPWSTR)buffer; // $ Alert
}
typedef unsigned long long size_t;
size_t wcslen(const wchar_t *str);
size_t strlen(const char* str);
template<typename C>
size_t str_len(const C *str) {
if (sizeof(C) != 1) {
return wcslen((const wchar_t *)str); // GOOD -- unreachable code
}
return strlen((const char *)str);
}
template<typename C>
size_t wrong_str_len(const C *str) {
if (sizeof(C) == 1) {
return wcslen((const wchar_t *)str); // $ Alert
}
return strlen((const char *)str);
}
void test_str_len(const wchar_t *wstr, const char *str) {
size_t len =
str_len(wstr) +
str_len(str) +
wrong_str_len(wstr) +
wrong_str_len(str);
}

View File

@@ -11,3 +11,4 @@
| WcharCharConversion.cpp:103:21:103:26 | buffer | Conversion from LPTSTR to LPWSTR. Use of invalid string can lead to undefined behavior. |
| WcharCharConversion.cpp:106:21:106:26 | buffer | Conversion from LPTSTR to LPWSTR. Use of invalid string can lead to undefined behavior. |
| WcharCharConversion.cpp:110:20:110:25 | buffer | Conversion from LPTSTR to LPWSTR. Use of invalid string can lead to undefined behavior. |
| WcharCharConversion.cpp:130:34:130:36 | str | Conversion from const char * to const wchar_t *. Use of invalid string can lead to undefined behavior. |

View File

@@ -1 +1,2 @@
Security/CWE/CWE-704/WcharCharConversion.ql
query: Security/CWE/CWE-704/WcharCharConversion.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql