mirror of
https://github.com/github/codeql.git
synced 2026-05-02 12:15:17 +02:00
Merge pull request #935 from dave-bartolomeo/dave/PointerDecay
C++: Handle pointer decay and inferred array sizes
This commit is contained in:
@@ -2,6 +2,7 @@ private import internal.IRInternal
|
||||
import FunctionIR
|
||||
import cpp
|
||||
import semmle.code.cpp.ir.implementation.TempVariableTag
|
||||
private import semmle.code.cpp.ir.internal.IRUtilities
|
||||
private import semmle.code.cpp.ir.internal.TempVariableTag
|
||||
private import semmle.code.cpp.ir.internal.TIRVariable
|
||||
|
||||
@@ -70,7 +71,7 @@ abstract class IRUserVariable extends IRVariable {
|
||||
}
|
||||
|
||||
override final Type getType() {
|
||||
result = var.getType().getUnspecifiedType()
|
||||
result = getVariableType(var)
|
||||
}
|
||||
|
||||
override final Locatable getAST() {
|
||||
|
||||
@@ -2,6 +2,7 @@ private import internal.IRInternal
|
||||
import FunctionIR
|
||||
import cpp
|
||||
import semmle.code.cpp.ir.implementation.TempVariableTag
|
||||
private import semmle.code.cpp.ir.internal.IRUtilities
|
||||
private import semmle.code.cpp.ir.internal.TempVariableTag
|
||||
private import semmle.code.cpp.ir.internal.TIRVariable
|
||||
|
||||
@@ -70,7 +71,7 @@ abstract class IRUserVariable extends IRVariable {
|
||||
}
|
||||
|
||||
override final Type getType() {
|
||||
result = var.getType().getUnspecifiedType()
|
||||
result = getVariableType(var)
|
||||
}
|
||||
|
||||
override final Locatable getAST() {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import cpp
|
||||
private import semmle.code.cpp.ir.implementation.Opcode
|
||||
private import semmle.code.cpp.ir.internal.IRUtilities
|
||||
private import semmle.code.cpp.ir.internal.OperandTag
|
||||
private import InstructionTag
|
||||
private import TranslatedElement
|
||||
@@ -104,14 +105,14 @@ abstract class TranslatedVariableDeclaration extends TranslatedElement, Initiali
|
||||
(
|
||||
tag = InitializerVariableAddressTag() and
|
||||
opcode instanceof Opcode::VariableAddress and
|
||||
resultType = getVariable().getType().getUnspecifiedType() and
|
||||
resultType = getVariableType(getVariable()) and
|
||||
isGLValue = true
|
||||
) or
|
||||
(
|
||||
hasUninitializedInstruction() and
|
||||
tag = InitializerStoreTag() and
|
||||
opcode instanceof Opcode::Uninitialized and
|
||||
resultType = getVariable().getType().getUnspecifiedType() and
|
||||
resultType = getVariableType(getVariable()) and
|
||||
isGLValue = false
|
||||
)
|
||||
}
|
||||
@@ -161,7 +162,7 @@ abstract class TranslatedVariableDeclaration extends TranslatedElement, Initiali
|
||||
}
|
||||
|
||||
override Type getTargetType() {
|
||||
result = getVariable().getType().getUnspecifiedType()
|
||||
result = getVariableType(getVariable())
|
||||
}
|
||||
|
||||
private TranslatedInitialization getInitialization() {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import cpp
|
||||
import semmle.code.cpp.ir.implementation.raw.IR
|
||||
private import semmle.code.cpp.ir.implementation.Opcode
|
||||
private import semmle.code.cpp.ir.internal.IRUtilities
|
||||
private import semmle.code.cpp.ir.internal.OperandTag
|
||||
private import semmle.code.cpp.ir.internal.TempVariableTag
|
||||
private import InstructionTag
|
||||
@@ -377,13 +378,13 @@ class TranslatedParameter extends TranslatedElement, TTranslatedParameter {
|
||||
(
|
||||
tag = InitializerVariableAddressTag() and
|
||||
opcode instanceof Opcode::VariableAddress and
|
||||
resultType = param.getType().getUnspecifiedType() and
|
||||
resultType = getVariableType(param) and
|
||||
isGLValue = true
|
||||
) or
|
||||
(
|
||||
tag = InitializerStoreTag() and
|
||||
opcode instanceof Opcode::InitializeParameter and
|
||||
resultType = param.getType().getUnspecifiedType() and
|
||||
resultType = getVariableType(param) and
|
||||
isGLValue = false
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ private import internal.IRInternal
|
||||
import FunctionIR
|
||||
import cpp
|
||||
import semmle.code.cpp.ir.implementation.TempVariableTag
|
||||
private import semmle.code.cpp.ir.internal.IRUtilities
|
||||
private import semmle.code.cpp.ir.internal.TempVariableTag
|
||||
private import semmle.code.cpp.ir.internal.TIRVariable
|
||||
|
||||
@@ -70,7 +71,7 @@ abstract class IRUserVariable extends IRVariable {
|
||||
}
|
||||
|
||||
override final Type getType() {
|
||||
result = var.getType().getUnspecifiedType()
|
||||
result = getVariableType(var)
|
||||
}
|
||||
|
||||
override final Locatable getAST() {
|
||||
|
||||
34
cpp/ql/src/semmle/code/cpp/ir/internal/IRUtilities.qll
Normal file
34
cpp/ql/src/semmle/code/cpp/ir/internal/IRUtilities.qll
Normal file
@@ -0,0 +1,34 @@
|
||||
import cpp
|
||||
|
||||
/**
|
||||
* Given a type, get the type that would result by applying "pointer decay".
|
||||
* A function type becomes a pointer to that function type, and an array type
|
||||
* becomes a pointer to the element type of the array. If the specified type
|
||||
* is not subject to pointer decay, this predicate does not hold.
|
||||
*/
|
||||
private Type getDecayedType(Type type) {
|
||||
result.(FunctionPointerType).getBaseType() = type.(RoutineType) or
|
||||
result.(PointerType).getBaseType() = type.(ArrayType).getBaseType()
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the actual type of the specified variable, as opposed to the declared type.
|
||||
* This returns the type of the variable after any pointer decay is applied, and
|
||||
* after any unsized array type has its size inferred from the initializer.
|
||||
*/
|
||||
Type getVariableType(Variable v) {
|
||||
exists(Type declaredType |
|
||||
declaredType = v.getType().getUnspecifiedType() and
|
||||
if v instanceof Parameter then (
|
||||
result = getDecayedType(declaredType) or
|
||||
not exists(getDecayedType(declaredType)) and result = declaredType
|
||||
)
|
||||
else if declaredType instanceof ArrayType and not declaredType.(ArrayType).hasArraySize() then (
|
||||
result = v.getInitializer().getExpr().getType().getUnspecifiedType() or
|
||||
not exists(v.getInitializer()) and result = declaredType
|
||||
)
|
||||
else (
|
||||
result = declaredType
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -6591,3 +6591,39 @@ ir.cpp:
|
||||
# 983| ValueCategory = prvalue(load)
|
||||
# 983| 1: { ... }
|
||||
# 985| 3: return ...
|
||||
# 987| int PointerDecay(int[], int(float))
|
||||
# 987| params:
|
||||
# 987| 0: a
|
||||
# 987| Type = int[]
|
||||
# 987| 1: fn
|
||||
# 987| Type = ..()(..)
|
||||
# 987| body: { ... }
|
||||
# 988| 0: return ...
|
||||
# 988| 0: ... + ...
|
||||
# 988| Type = int
|
||||
# 988| ValueCategory = prvalue
|
||||
# 988| 0: access to array
|
||||
# 988| Type = int
|
||||
# 988| ValueCategory = prvalue(load)
|
||||
# 988| 0: a
|
||||
# 988| Type = int *
|
||||
# 988| ValueCategory = prvalue(load)
|
||||
# 988| 1: 0
|
||||
# 988| Type = int
|
||||
# 988| Value = 0
|
||||
# 988| ValueCategory = prvalue
|
||||
# 988| 1: call to expression
|
||||
# 988| Type = int
|
||||
# 988| ValueCategory = prvalue
|
||||
# 988| 0: fn
|
||||
# 988| Type = ..(*)(..)
|
||||
# 988| ValueCategory = prvalue(load)
|
||||
# 988| 1: (float)...
|
||||
# 988| Conversion = floating point conversion
|
||||
# 988| Type = float
|
||||
# 988| Value = 1.0
|
||||
# 988| ValueCategory = prvalue
|
||||
# 988| expr: 1.0
|
||||
# 988| Type = double
|
||||
# 988| Value = 1.0
|
||||
# 988| ValueCategory = prvalue
|
||||
|
||||
@@ -984,6 +984,10 @@ void WhileStmtWithDeclaration(int x, int y) {
|
||||
}
|
||||
}
|
||||
|
||||
int PointerDecay(int a[], int fn(float)) {
|
||||
return a[0] + fn(1.0);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void OperatorDelete() {
|
||||
delete static_cast<int*>(nullptr); // No destructor
|
||||
|
||||
@@ -2579,7 +2579,7 @@ ir.cpp:
|
||||
# 573| r0_12(glval<char[4]>) = StringConstant["foo"] :
|
||||
# 573| r0_13(char[4]) = Load : r0_12, mu0_2
|
||||
# 573| mu0_14(char[4]) = Store : r0_11, r0_13
|
||||
# 574| r0_15(glval<char[]>) = VariableAddress[a_infer] :
|
||||
# 574| r0_15(glval<char[5]>) = VariableAddress[a_infer] :
|
||||
# 574| r0_16(glval<char[5]>) = StringConstant["blah"] :
|
||||
# 574| r0_17(char[5]) = Load : r0_16, mu0_2
|
||||
# 574| mu0_18(char[5]) = Store : r0_15, r0_17
|
||||
@@ -4339,3 +4339,30 @@ ir.cpp:
|
||||
# 979| v7_9(void) = ConditionalBranch : r7_8
|
||||
#-----| False -> Block 2
|
||||
#-----| True -> Block 1
|
||||
|
||||
# 987| int PointerDecay(int[], int(float))
|
||||
# 987| Block 0
|
||||
# 987| v0_0(void) = EnterFunction :
|
||||
# 987| mu0_1(unknown) = AliasedDefinition :
|
||||
# 987| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 987| r0_3(glval<int *>) = VariableAddress[a] :
|
||||
# 987| mu0_4(int *) = InitializeParameter[a] : r0_3
|
||||
# 987| r0_5(glval<..(*)(..)>) = VariableAddress[fn] :
|
||||
# 987| mu0_6(..(*)(..)) = InitializeParameter[fn] : r0_5
|
||||
# 988| r0_7(glval<int>) = VariableAddress[#return] :
|
||||
# 988| r0_8(glval<int *>) = VariableAddress[a] :
|
||||
# 988| r0_9(int *) = Load : r0_8, mu0_2
|
||||
# 988| r0_10(int) = Constant[0] :
|
||||
# 988| r0_11(int *) = PointerAdd[4] : r0_9, r0_10
|
||||
# 988| r0_12(int) = Load : r0_11, mu0_2
|
||||
# 988| r0_13(glval<..(*)(..)>) = VariableAddress[fn] :
|
||||
# 988| r0_14(..(*)(..)) = Load : r0_13, mu0_2
|
||||
# 988| r0_15(float) = Constant[1.0] :
|
||||
# 988| r0_16(int) = Call : r0_14, r0_15
|
||||
# 988| mu0_17(unknown) = ^CallSideEffect : mu0_2
|
||||
# 988| r0_18(int) = Add : r0_12, r0_16
|
||||
# 988| mu0_19(int) = Store : r0_7, r0_18
|
||||
# 987| r0_20(glval<int>) = VariableAddress[#return] :
|
||||
# 987| v0_21(void) = ReturnValue : r0_20, mu0_2
|
||||
# 987| v0_22(void) = UnmodeledUse : mu*
|
||||
# 987| v0_23(void) = ExitFunction :
|
||||
|
||||
Reference in New Issue
Block a user