mirror of
https://github.com/github/codeql.git
synced 2026-05-04 21:25:44 +02:00
C++: Add annoying case in SSA.qll related to 'NewExpr' and accept test changes.
This commit is contained in:
@@ -324,6 +324,30 @@ private module Cached {
|
||||
use.hasRankInBlock(bb2, i2) and
|
||||
flowOutOfAddressStep(use.getOperand(), nodeTo)
|
||||
)
|
||||
or
|
||||
// This final case is a bit annoying. The write side effect on an expression like `a = new A;` writes
|
||||
// to a fresh address returned by `operator new`, and there's no easy way to use the shared SSA
|
||||
// library to hook that up to the assignment to `a`. So instead we flow to the _first_ use of the
|
||||
// value computed by `operator new` that occurs after `nodeFrom` (to avoid a loop in the
|
||||
// dataflow graph).
|
||||
exists(WriteSideEffectInstruction write, IRBlock bb, int i1, int i2, Operand op |
|
||||
nodeFrom.getInstruction().(CallInstruction).getStaticCallTarget() instanceof
|
||||
Alloc::OperatorNewAllocationFunction and
|
||||
write = nodeFrom.getStoreInstruction() and
|
||||
bb.getInstruction(i1) = write and
|
||||
bb.getInstruction(i2) = op.getUse() and
|
||||
// Flow to an instruction that occurs later in the block.
|
||||
valueFlow*(nodeFrom.getInstruction(), op.getDef()) and
|
||||
nodeTo.asOperand() = op and
|
||||
i2 > i1 and
|
||||
// There is no previous instruction that also occurs after `nodeFrom`.
|
||||
not exists(Instruction instr, int i |
|
||||
bb.getInstruction(i) = instr and
|
||||
valueFlow(instr, op.getDef()) and
|
||||
i1 < i and
|
||||
i < i2
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate fromReadNode(ReadNode nodeFrom, Node nodeTo) {
|
||||
@@ -402,6 +426,16 @@ private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate valueFlow(Instruction iFrom, Instruction iTo) {
|
||||
iTo.(CopyValueInstruction).getSourceValue() = iFrom
|
||||
or
|
||||
iTo.(ConvertInstruction).getUnary() = iFrom
|
||||
or
|
||||
iTo.(CheckedConvertOrNullInstruction).getUnary() = iFrom
|
||||
or
|
||||
iTo.(InheritanceConversionInstruction).getUnary() = iFrom
|
||||
}
|
||||
|
||||
private predicate flowOutOfAddressStep(Operand operand, Node nTo) {
|
||||
// Flow into a read node
|
||||
exists(ReadNode readNode | readNode = nTo |
|
||||
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
{
|
||||
C *c = new C();
|
||||
B *b = B::make(c);
|
||||
sink(b->c); // $ast MISSING: ir
|
||||
sink(b->c); // $ast,ir
|
||||
}
|
||||
|
||||
void f2()
|
||||
@@ -54,7 +54,7 @@ public:
|
||||
B *b = new B();
|
||||
b->set(new C1());
|
||||
sink(b->get()); // $ ast ir=55:12
|
||||
sink((new B(new C()))->get()); // $ ast MISSING: ir
|
||||
sink((new B(new C()))->get()); // $ ast,ir
|
||||
}
|
||||
|
||||
void f3()
|
||||
@@ -149,8 +149,8 @@ public:
|
||||
{
|
||||
B *b = new B();
|
||||
D *d = new D(b, r());
|
||||
sink(d->b); // $ ast MISSING: ir
|
||||
sink(d->b->c); // $ ast MISSING: ir
|
||||
sink(d->b); // $ ast,ir=143:25 ast,ir=150:12
|
||||
sink(d->b->c); // $ ast,ir
|
||||
sink(b->c); // $ ast,ir
|
||||
}
|
||||
|
||||
@@ -162,11 +162,11 @@ public:
|
||||
MyList *l3 = new MyList(nullptr, l2);
|
||||
sink(l3->head); // no flow, b is nested beneath at least one ->next
|
||||
sink(l3->next->head); // no flow
|
||||
sink(l3->next->next->head); // $ ast MISSING: ir
|
||||
sink(l3->next->next->head); // $ ast,ir
|
||||
sink(l3->next->next->next->head); // no flow
|
||||
for (MyList *l = l3; l != nullptr; l = l->next)
|
||||
{
|
||||
sink(l->head); // $ ast MISSING: ir
|
||||
sink(l->head); // $ ast,ir
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ class B
|
||||
Elem *e = new Elem();
|
||||
Box1 *b1 = new Box1(e, nullptr);
|
||||
Box2 *b2 = new Box2(b1);
|
||||
sink(b2->box1->elem1); // $ ast MISSING: ir
|
||||
sink(b2->box1->elem1); // $ ast,ir
|
||||
sink(b2->box1->elem2); // no flow
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ class B
|
||||
Box1 *b1 = new B::Box1(nullptr, e);
|
||||
Box2 *b2 = new Box2(b1);
|
||||
sink(b2->box1->elem1); // no flow
|
||||
sink(b2->box1->elem2); // $ ast MISSING: ir
|
||||
sink(b2->box1->elem2); // $ ast,ir
|
||||
}
|
||||
|
||||
static void sink(void *o) {}
|
||||
|
||||
@@ -26,7 +26,7 @@ public:
|
||||
|
||||
void func()
|
||||
{
|
||||
sink(s1); // $ast MISSING: ir
|
||||
sink(s1); // $ast,ir
|
||||
sink(s2); // $ MISSING: ast,ir
|
||||
sink(s3); // $ast MISSING: ir
|
||||
sink(s4); // $ MISSING: ast,ir
|
||||
|
||||
@@ -21,9 +21,9 @@ void test_unique_ptr_struct() {
|
||||
std::unique_ptr<A> p1(new A{source(), 0});
|
||||
std::unique_ptr<A> p2 = std::make_unique<A>(source(), 0);
|
||||
|
||||
sink(p1->x); // $ MISSING: ast,ir
|
||||
sink(p1->x); // $ ir MISSING: ast
|
||||
sink(p1->y);
|
||||
sink(p2->x); // $ MISSING: ast,ir
|
||||
sink(p2->x); // $ ir=22:46 MISSING: ast
|
||||
sink(p2->y);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user