Skip to content

Commit 26f36e0

Browse files
committed
Binary: Identify parameters as those variables for which we have a read without a prior def.
1 parent 7b8c084 commit 26f36e0

1 file changed

Lines changed: 192 additions & 9 deletions

File tree

binary/ql/lib/semmle/code/binary/ast/ir/internal/Instruction2/Instruction2.qll

Lines changed: 192 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ private import codeql.util.Unit
99
private import codeql.util.Void
1010
private import semmle.code.binary.ast.ir.internal.TransformInstruction.TransformInstruction
1111
private import semmle.code.binary.ast.ir.internal.Instruction1.Instruction1
12+
private import codeql.ssa.Ssa as SsaImpl
1213

1314
private signature module ControlFlowReachableInputSig {
1415
class FlowState;
@@ -149,6 +150,8 @@ private module ControlFlowReachable<ControlFlowReachableInputSig Input> {
149150
* sub rax, rbx
150151
* jz label
151152
* ```
153+
*
154+
* It also synthesises parameter instructions.
152155
*/
153156
private module InstructionInput implements Transform<Instruction1>::TransformInputSig {
154157
// ------------------------------------------------
@@ -174,10 +177,10 @@ private module InstructionInput implements Transform<Instruction1>::TransformInp
174177

175178
class LocalVariableTag = Void;
176179

177-
private newtype TVariableTag = ZeroVarTag()
180+
private newtype TTempVariableTag = ZeroVarTag()
178181

179-
class VariableTag extends TVariableTag {
180-
VariableTag() { this = ZeroVarTag() }
182+
class TempVariableTag extends TTempVariableTag {
183+
TempVariableTag() { this = ZeroVarTag() }
181184

182185
string toString() { result = "ZeroVarTag" }
183186
}
@@ -191,6 +194,11 @@ private module InstructionInput implements Transform<Instruction1>::TransformInp
191194
this = CmpDefTag(k) and
192195
result = "CmpDefTag(" + stringOfConditionKind(k) + ")"
193196
)
197+
or
198+
exists(Instruction1::Variable v |
199+
this = InitializeParameterTag(v) and
200+
result = "InitializeParameterTag(" + v.toString() + ")"
201+
)
194202
}
195203
}
196204

@@ -213,21 +221,21 @@ private module InstructionInput implements Transform<Instruction1>::TransformInp
213221
}
214222

215223
private newtype TTranslatedElementVariablePair =
216-
MkTranslatedElementVariablePair(TranslatedElement te, VariableTag tag) {
224+
MkTranslatedElementVariablePair(TranslatedElement te, TempVariableTag tag) {
217225
te.hasTempVariable(tag)
218226
}
219227

220228
class TranslatedElementVariablePair extends TTranslatedElementVariablePair {
221229
TranslatedElement te;
222-
VariableTag tag;
230+
TempVariableTag tag;
223231

224232
TranslatedElementVariablePair() { this = MkTranslatedElementVariablePair(te, tag) }
225233

226234
string toString() { none() }
227235

228236
TranslatedElement getTranslatedElement() { result = te }
229237

230-
VariableTag getVariableTag() { result = tag }
238+
TempVariableTag getVariableTag() { result = tag }
231239
}
232240

233241
private newtype TFunctionLocalVariablePair =
@@ -328,13 +336,106 @@ private module InstructionInput implements Transform<Instruction1>::TransformInp
328336
cjump.getKind() = kind
329337
}
330338

339+
private module SsaInput implements SsaImpl::InputSig<Location, Instruction1::BasicBlock> {
340+
class SourceVariable = Instruction1::Variable;
341+
342+
predicate variableWrite(Instruction1::BasicBlock bb, int i, SourceVariable v, boolean certain) {
343+
bb.getNode(i).asInstruction().getResultVariable() = v and
344+
certain = true
345+
}
346+
347+
predicate variableRead(Instruction1::BasicBlock bb, int i, SourceVariable v, boolean certain) {
348+
bb.getNode(i).asOperand().getVariable() = v and
349+
certain = true
350+
}
351+
}
352+
353+
private module Ssa {
354+
private module Ssa = SsaImpl::Make<Location, Instruction1::BinaryCfg, SsaInput>;
355+
356+
class Definition extends Ssa::Definition {
357+
Instruction1::Instruction getInstruction() {
358+
exists(Instruction1::BasicBlock bb, int i |
359+
this.definesAt(_, bb, i) and
360+
bb.getNode(i).asInstruction() = result
361+
)
362+
}
363+
364+
Instruction1::Operand getARead() {
365+
exists(Instruction1::BasicBlock bb, int i |
366+
Ssa::ssaDefReachesRead(_, this, bb, i) and
367+
result = bb.getNode(i).asOperand()
368+
)
369+
}
370+
371+
override string toString() {
372+
result = "SSA def(" + this.getInstruction() + ")"
373+
or
374+
not exists(this.getInstruction()) and
375+
result = super.toString()
376+
}
377+
}
378+
379+
class PhiNode extends Definition, Ssa::PhiNode {
380+
override string toString() { result = Ssa::PhiNode.super.toString() }
381+
382+
Definition getInput(Instruction1::BasicBlock bb) {
383+
Ssa::phiHasInputFromBlock(this, result, bb)
384+
}
385+
386+
Definition getAnInput() { result = this.getInput(_) }
387+
}
388+
389+
class SourceVariable = SsaInput::SourceVariable;
390+
391+
pragma[nomagic]
392+
predicate ssaDefReachesRead(
393+
Instruction1::Variable v, Definition def, Instruction1::BasicBlock bb, int i
394+
) {
395+
Ssa::ssaDefReachesRead(v, def, bb, i)
396+
}
397+
398+
pragma[nomagic]
399+
predicate phiHasInputFromBlock(PhiNode phi, Definition input, Instruction1::BasicBlock bb) {
400+
Ssa::phiHasInputFromBlock(phi, input, bb)
401+
}
402+
403+
pragma[nomagic]
404+
Instruction1::Instruction getADef(Instruction1::Operand op) {
405+
exists(Instruction1::Variable v, Ssa::Definition def, Instruction1::BasicBlock bb, int i |
406+
def = getDef(op) and
407+
def.definesAt(v, bb, i) and
408+
result = bb.getNode(i).asInstruction()
409+
)
410+
}
411+
412+
pragma[nomagic]
413+
Ssa::Definition getDef(Instruction1::Operand op) {
414+
exists(Instruction1::Variable v, Instruction1::BasicBlock bbRead, int iRead |
415+
ssaDefReachesRead(v, result, bbRead, iRead) and
416+
op = bbRead.getNode(iRead).asOperand()
417+
)
418+
}
419+
}
420+
421+
private predicate isReadBeforeInitialization(
422+
Instruction1::LocalVariable v, Instruction1::Function f
423+
) {
424+
exists(Instruction1::Operand op |
425+
op.getVariable() = v and
426+
op.getEnclosingFunction() = f and
427+
not any(Ssa::Definition def).getARead() = op
428+
)
429+
}
430+
331431
// ------------------------------------------------
332432
private newtype TTranslatedElement =
333433
TTranslatedComparisonInstruction(
334434
Instruction1::Instruction i, Instruction1::CJumpInstruction cjump, ConditionKind kind
335435
) {
336436
controlFlowsToCmp(i, cjump, kind)
337-
}
437+
} or
438+
TTranslatedInitializeParameters(Instruction1::Function f) { isReadBeforeInitialization(_, f) }
338439

339440
abstract class TranslatedElement extends TTranslatedElement {
340441
abstract EitherInstructionTranslatedElementTagPair getSuccessor(
@@ -359,7 +460,7 @@ private module InstructionInput implements Transform<Instruction1>::TransformInp
359460

360461
predicate hasJumpCondition(InstructionTag tag, ConditionKind kind) { none() }
361462

362-
predicate hasTempVariable(VariableTag tag) { none() }
463+
predicate hasTempVariable(TempVariableTag tag) { none() }
363464

364465
predicate hasLocalVariable(LocalVariableTag tag) { none() }
365466

@@ -423,7 +524,7 @@ private module InstructionInput implements Transform<Instruction1>::TransformInp
423524

424525
override predicate producesResult() { none() }
425526

426-
override predicate hasTempVariable(VariableTag tag) { tag = ZeroVarTag() }
527+
override predicate hasTempVariable(TempVariableTag tag) { tag = ZeroVarTag() }
427528

428529
override EitherVariableOrTranslatedElementVariablePair getVariableOperand(
429530
InstructionTag tag, OperandTag operandTag
@@ -467,6 +568,88 @@ private module InstructionInput implements Transform<Instruction1>::TransformInp
467568
override EitherInstructionTranslatedElementTagPair getEntry() { result.asLeft() = instr }
468569
}
469570

571+
private predicate parameterHasIndex(Instruction1::Variable v, Instruction1::Function f, int index) {
572+
v =
573+
rank[index + 1](Instruction1::LocalVariable cand |
574+
cand.getEnclosingFunction() = f and
575+
isReadBeforeInitialization(cand, f)
576+
|
577+
cand order by cand.toString() // TODO: Use the right argument ordering. This depends on the calling conventions.
578+
)
579+
}
580+
581+
private Instruction1::Variable getFirstParameter(Instruction1::Function f) {
582+
parameterHasIndex(result, f, 0)
583+
}
584+
585+
private Instruction1::InitInstruction getStackPointerInitialize(Instruction1::Function f) {
586+
result.getResultVariable() instanceof Instruction1::StackPointer and
587+
result.getEnclosingFunction() = f
588+
}
589+
590+
private class TranslatedInitializeParameters extends TranslatedInstruction,
591+
TTranslatedInitializeParameters
592+
{
593+
Instruction1::Function func;
594+
595+
TranslatedInitializeParameters() { this = TTranslatedInitializeParameters(func) }
596+
597+
final override Instruction1::Function getEnclosingFunction() { result = func }
598+
599+
override EitherInstructionTranslatedElementTagPair getInstructionSuccessor(
600+
Instruction1::Instruction i, SuccessorType succType
601+
) {
602+
i = getStackPointerInitialize(func) and
603+
succType instanceof DirectSuccessor and
604+
result.asRight().getTranslatedElement() = this and
605+
result.asRight().getInstructionTag() = InitializeParameterTag(getFirstParameter(func))
606+
}
607+
608+
override EitherInstructionTranslatedElementTagPair getSuccessor(
609+
InstructionTag tag, SuccessorType succType
610+
) {
611+
succType instanceof DirectSuccessor and
612+
exists(Instruction1::Variable v, int index |
613+
tag = InitializeParameterTag(v) and
614+
parameterHasIndex(v, func, index)
615+
|
616+
exists(Instruction1::Variable u |
617+
parameterHasIndex(u, func, index + 1) and
618+
result.asRight().getTranslatedElement() = this and
619+
result.asRight().getInstructionTag() = InitializeParameterTag(u)
620+
)
621+
or
622+
not parameterHasIndex(_, func, index + 1) and
623+
result.asLeft() = getStackPointerInitialize(func).getSuccessor(succType)
624+
)
625+
}
626+
627+
override predicate producesResult() { none() }
628+
629+
override predicate hasTempVariable(TempVariableTag tag) { none() }
630+
631+
override EitherVariableOrTranslatedElementVariablePair getVariableOperand(
632+
InstructionTag tag, OperandTag operandTag
633+
) {
634+
none()
635+
}
636+
637+
override predicate hasInstruction(
638+
Opcode opcode, InstructionTag tag, OptionEitherVariableOrTranslatedElementPair v
639+
) {
640+
opcode instanceof Init and
641+
exists(Instruction1::Variable var |
642+
isReadBeforeInitialization(var, func) and
643+
tag = InitializeParameterTag(var) and
644+
v.asSome().asLeft() = var
645+
)
646+
}
647+
648+
override string toString() { result = "Initialize parameters in " + func.toString() }
649+
650+
override EitherInstructionTranslatedElementTagPair getEntry() { none() }
651+
}
652+
470653
class TranslatedOperand extends TranslatedElement {
471654
TranslatedOperand() { none() }
472655

0 commit comments

Comments
 (0)