Merge pull request #935 from dave-bartolomeo/dave/PointerDecay

C++: Handle pointer decay and inferred array sizes
This commit is contained in:
Robert Marsh
2019-02-12 15:03:21 -08:00
committed by GitHub
9 changed files with 115 additions and 9 deletions

View File

@@ -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() {

View File

@@ -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() {

View File

@@ -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() {

View File

@@ -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
)
}

View File

@@ -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() {

View 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
)
)
}

View File

@@ -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

View File

@@ -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

View File

@@ -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 :