Skip to content

Commit d0b4e9d

Browse files
committed
C++: Support sizeof VLAs nin the IR
1 parent f23316d commit d0b4e9d

File tree

3 files changed

+109
-4
lines changed

3 files changed

+109
-4
lines changed

cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/InstructionTag.qll

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,12 @@ newtype TInstructionTag =
9797
exists(Stmt s | exists(s.getImplicitDestructorCall(index)))
9898
} or
9999
CoAwaitBranchTag() or
100-
BoolToIntConversionTag()
100+
BoolToIntConversionTag() or
101+
SizeofVlaDimensionTag(int index) {
102+
index = -1
103+
or
104+
exists(VlaDeclStmt v | exists(v.getVlaDimensionStmt(index)))
105+
}
101106

102107
class InstructionTag extends TInstructionTag {
103108
final string toString() { result = getInstructionTagId(this) }

cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,13 +123,16 @@ private predicate ignoreExprAndDescendants(Expr expr) {
123123
// or
124124
ignoreExprAndDescendants(getRealParent(expr)) // recursive case
125125
or
126-
// va_start doesn't evaluate its argument, so we don't need to translate it.
126+
// va_start does not evaluate its argument, so we do not need to translate it.
127127
exists(BuiltInVarArgsStart vaStartExpr |
128128
vaStartExpr.getLastNamedParameter().getFullyConverted() = expr
129129
)
130130
or
131+
// sizeof does not evaluate its argument, so we do not need to translate it.
132+
exists(SizeofExprOperator sizeofExpr | sizeofExpr.getExprOperand().getFullyConverted() = expr)
133+
or
131134
// The children of C11 _Generic expressions are just surface syntax.
132-
exists(C11GenericExpr generic | generic.getAChild() = expr)
135+
exists(C11GenericExpr generic | generic.getAChild().getFullyConverted() = expr)
133136
or
134137
// Do not translate implicit destructor calls for unnamed temporary variables that are
135138
// conditionally constructed (until we have a mechanism for calling these only when the

cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ Variable getEnclosingVariable(Expr e) {
187187
}
188188

189189
/**
190-
* The IR translation of the "core" part of an expression. This is the part of
190+
* The IR translation of the "core" part of an expression. This is the part of
191191
* the expression that produces the result value of the expression, before any
192192
* lvalue-to-rvalue conversion on the result. Every expression has a single
193193
* `TranslatedCoreExpr`.
@@ -4094,6 +4094,103 @@ class TranslatedStmtExpr extends TranslatedNonConstantExpr {
40944094
TranslatedStmt getStmt() { result = getTranslatedStmt(expr.getStmt()) }
40954095
}
40964096

4097+
private VlaDeclStmt getVlaDeclStmt(Expr expr, int pointerDerefCount) {
4098+
expr.(VariableAccess).getTarget() = result.getVariable() and
4099+
pointerDerefCount = 0
4100+
or
4101+
result = getVlaDeclStmt(expr.(PointerDereferenceExpr).getOperand(), pointerDerefCount - 1)
4102+
}
4103+
4104+
class TranslatedSizeofExpr extends TranslatedNonConstantExpr {
4105+
override SizeofExprOperator expr;
4106+
VlaDeclStmt vlaDeclStmt;
4107+
int pointerDerefCount;
4108+
4109+
TranslatedSizeofExpr() {
4110+
vlaDeclStmt = getVlaDeclStmt(expr.getExprOperand(), pointerDerefCount) and
4111+
pointerDerefCount < vlaDeclStmt.getNumberOfVlaDimensionStmts()
4112+
}
4113+
4114+
final override Instruction getFirstInstruction(EdgeKind kind) {
4115+
result = this.getInstruction(SizeofVlaDimensionTag(-1)) and
4116+
kind instanceof GotoEdge
4117+
}
4118+
4119+
override Instruction getALastInstructionInternal() {
4120+
result =
4121+
this.getInstruction(SizeofVlaDimensionTag(vlaDeclStmt.getNumberOfVlaDimensionStmts() - 1))
4122+
}
4123+
4124+
final override TranslatedElement getChildInternal(int id) { none() }
4125+
4126+
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
4127+
opcode instanceof Opcode::Constant and
4128+
tag = SizeofVlaDimensionTag(-1) and
4129+
resultType = this.getResultType()
4130+
or
4131+
opcode instanceof Opcode::Mul and
4132+
exists(int n | pointerDerefCount <= n and n < vlaDeclStmt.getNumberOfVlaDimensionStmts() |
4133+
tag = SizeofVlaDimensionTag(n)
4134+
) and
4135+
resultType = this.getResultType()
4136+
}
4137+
4138+
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
4139+
tag = SizeofVlaDimensionTag(-1) and
4140+
result = this.getInstruction(SizeofVlaDimensionTag(pointerDerefCount)) and
4141+
kind instanceof GotoEdge
4142+
or
4143+
exists(int n | pointerDerefCount <= n and n < vlaDeclStmt.getNumberOfVlaDimensionStmts() - 1 |
4144+
tag = SizeofVlaDimensionTag(n) and
4145+
result = this.getInstruction(SizeofVlaDimensionTag(n + 1))
4146+
) and
4147+
kind instanceof GotoEdge
4148+
or
4149+
tag = SizeofVlaDimensionTag(vlaDeclStmt.getNumberOfVlaDimensionStmts() - 1) and
4150+
result = this.getParent().getChildSuccessor(this, kind)
4151+
}
4152+
4153+
override string getInstructionConstantValue(InstructionTag tag) {
4154+
tag = SizeofVlaDimensionTag(-1) and
4155+
result =
4156+
this.getBaseSize(vlaDeclStmt.getVariable().getType(),
4157+
vlaDeclStmt.getNumberOfVlaDimensionStmts() - 1).toString()
4158+
}
4159+
4160+
private int getBaseSize(DerivedType type, int n) {
4161+
n = 0 and
4162+
result = type.getBaseType().getSize()
4163+
or
4164+
n = [1 .. vlaDeclStmt.getNumberOfVlaDimensionStmts() - 1] and
4165+
result = this.getBaseSize(type.getBaseType(), n - 1)
4166+
}
4167+
4168+
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
4169+
exists(int n | pointerDerefCount <= n and n < vlaDeclStmt.getNumberOfVlaDimensionStmts() |
4170+
tag = SizeofVlaDimensionTag(n) and
4171+
(
4172+
operandTag instanceof LeftOperandTag and
4173+
(
4174+
n - 1 >= pointerDerefCount and
4175+
result = this.getInstruction(SizeofVlaDimensionTag(n - 1))
4176+
or
4177+
n - 1 < pointerDerefCount and
4178+
result = this.getInstruction(SizeofVlaDimensionTag(-1))
4179+
)
4180+
or
4181+
operandTag instanceof RightOperandTag and
4182+
result =
4183+
getTranslatedExpr(vlaDeclStmt.getVlaDimensionStmt(n).getDimensionExpr()).getResult()
4184+
)
4185+
)
4186+
}
4187+
4188+
final override Instruction getResult() {
4189+
result =
4190+
this.getInstruction(SizeofVlaDimensionTag(vlaDeclStmt.getNumberOfVlaDimensionStmts() - 1))
4191+
}
4192+
}
4193+
40974194
class TranslatedErrorExpr extends TranslatedSingleInstructionExpr {
40984195
override ErrorExpr expr;
40994196

0 commit comments

Comments
 (0)