mirror of
https://github.com/github/codeql.git
synced 2026-04-28 10:15:14 +02:00
C++: Handle pointer decay and inferred array sizes
For function parameters that are subject to "pointer decay", the database contains the type as originally declared (e.g. `T[]` instead of `T*`). The IR needs the actual type. Similarly, for variable declared as an array of unknown size, the actual size needs to be inferred from the initializer (e.g. `char a[] = "blah";` needs to have the type `char[5]`). I've opened a ticket to have the extractor emit the actual type alongside the declared type, but for now, this workaround is enough to unblock progress for typical code.
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
|
||||
)
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user