mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
C++: Hashcons for ?:, ExprCall, and weird stuff
This commit is contained in:
@@ -87,6 +87,9 @@ private cached newtype HCBase =
|
||||
HC_NonmemberFunctionCall(Function fcn, HC_Args args) {
|
||||
mk_NonmemberFunctionCall(fcn, args, _)
|
||||
}
|
||||
or HC_ExprCall(HashCons hc, HC_Args args) {
|
||||
mk_ExprCall(hc, args, _)
|
||||
}
|
||||
or
|
||||
HC_MemberFunctionCall(Function trg, HashCons qual, HC_Args args) {
|
||||
mk_MemberFunctionCall(trg, qual, args, _)
|
||||
@@ -107,6 +110,12 @@ private cached newtype HCBase =
|
||||
or
|
||||
HC_AlignofExpr(HashCons child) {mk_AlignofExpr(child, _)}
|
||||
or
|
||||
HC_UuidofOperator(Type t) {mk_UuidofOperator(t, _)}
|
||||
or
|
||||
HC_TypeidType(Type t) {mk_TypeidType(t, _)}
|
||||
or
|
||||
HC_TypeidExpr(HashCons child) {mk_TypeidExpr(child, _)}
|
||||
or
|
||||
HC_ClassAggregateLiteral(Class c, HC_Fields hcf) {
|
||||
mk_ClassAggregateLiteral(c, hcf, _)
|
||||
}
|
||||
@@ -123,6 +132,14 @@ private cached newtype HCBase =
|
||||
or
|
||||
HC_ReThrowExpr()
|
||||
or
|
||||
HC_ConditionalExpr(HashCons cond, HashCons trueHC, HashCons falseHC) {
|
||||
mk_ConditionalExpr(cond, trueHC, falseHC, _)
|
||||
}
|
||||
or
|
||||
HC_NoExceptExpr(HashCons child) {
|
||||
mk_NoExceptExpr(child, _)
|
||||
}
|
||||
or
|
||||
// Any expression that is not handled by the cases above is
|
||||
// given a unique number based on the expression itself.
|
||||
HC_Unanalyzable(Expr e) { not analyzableExpr(e,_) }
|
||||
@@ -153,11 +170,11 @@ private newtype HC_Align =
|
||||
|
||||
/** Used to implement hash-consing of argument lists */
|
||||
private newtype HC_Args =
|
||||
HC_EmptyArgs(Function fcn) {
|
||||
HC_EmptyArgs() {
|
||||
any()
|
||||
}
|
||||
or HC_ArgCons(Function fcn, HashCons hc, int i, HC_Args list) {
|
||||
mk_ArgCons(fcn, hc, i, list, _)
|
||||
or HC_ArgCons(HashCons hc, int i, HC_Args list) {
|
||||
mk_ArgCons(hc, i, list, _)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -228,12 +245,18 @@ class HashCons extends HCBase {
|
||||
if this instanceof HC_SizeofExpr then result = "SizeofExprOperator" else
|
||||
if this instanceof HC_AlignofType then result = "AlignofTypeOperator" else
|
||||
if this instanceof HC_AlignofExpr then result = "AlignofExprOperator" else
|
||||
if this instanceof HC_UuidofOperator then result = "UuidofOperator" else
|
||||
if this instanceof HC_TypeidType then result = "TypeidType" else
|
||||
if this instanceof HC_TypeidExpr then result = "TypeidExpr" else
|
||||
if this instanceof HC_ArrayAggregateLiteral then result = "ArrayAggregateLiteral" else
|
||||
if this instanceof HC_ClassAggregateLiteral then result = "ClassAggreagateLiteral" else
|
||||
if this instanceof HC_DeleteExpr then result = "DeleteExpr" else
|
||||
if this instanceof HC_DeleteArrayExpr then result = "DeleteArrayExpr" else
|
||||
if this instanceof HC_ThrowExpr then result = "ThrowExpr" else
|
||||
if this instanceof HC_ReThrowExpr then result = "ReThrowExpr" else
|
||||
if this instanceof HC_ExprCall then result = "ExprCall" else
|
||||
if this instanceof HC_ConditionalExpr then result = "ConditionalExpr" else
|
||||
if this instanceof HC_NoExceptExpr then result = "NoExceptExpr" else
|
||||
result = "error"
|
||||
}
|
||||
|
||||
@@ -473,19 +496,40 @@ private predicate mk_NonmemberFunctionCall(Function fcn, HC_Args args, FunctionC
|
||||
analyzableNonmemberFunctionCall(fc) and
|
||||
(
|
||||
exists(HashCons head, HC_Args tail |
|
||||
args = HC_ArgCons(fcn, head, fc.getNumberOfArguments() - 1, tail) and
|
||||
mk_ArgCons(fcn, head, fc.getNumberOfArguments() - 1, tail, fc)
|
||||
args = HC_ArgCons(head, fc.getNumberOfArguments() - 1, tail) and
|
||||
mk_ArgCons(head, fc.getNumberOfArguments() - 1, tail, fc)
|
||||
)
|
||||
or
|
||||
fc.getNumberOfArguments() = 0 and
|
||||
args = HC_EmptyArgs(fcn)
|
||||
args = HC_EmptyArgs()
|
||||
)
|
||||
}
|
||||
|
||||
private predicate analyzableExprCall(ExprCall ec) {
|
||||
forall(int i |
|
||||
exists(ec.getArgument(i)) |
|
||||
strictcount(ec.getArgument(i).getFullyConverted()) = 1
|
||||
) and
|
||||
strictcount(ec.getExpr().getFullyConverted()) = 1
|
||||
}
|
||||
|
||||
private predicate mk_ExprCall(HashCons hc, HC_Args args, ExprCall ec) {
|
||||
hc.getAnExpr() = ec.getExpr() and
|
||||
(
|
||||
exists(HashCons head, HC_Args tail |
|
||||
args = HC_ArgCons(head, ec.getNumberOfArguments() - 1, tail) and
|
||||
mk_ArgCons(head, ec.getNumberOfArguments() - 1, tail, ec)
|
||||
)
|
||||
or
|
||||
ec.getNumberOfArguments() = 0 and
|
||||
args = HC_EmptyArgs()
|
||||
)
|
||||
}
|
||||
|
||||
private predicate analyzableMemberFunctionCall(
|
||||
FunctionCall fc) {
|
||||
forall(int i |
|
||||
exists(fc.getArgument(i)) |
|
||||
exists(fc.getArgument(i)) |
|
||||
strictcount(fc.getArgument(i).getFullyConverted()) = 1
|
||||
) and
|
||||
strictcount(fc.getTarget()) = 1 and
|
||||
@@ -503,40 +547,39 @@ private predicate mk_MemberFunctionCall(
|
||||
hashCons(fc.getQualifier().getFullyConverted()) = qual and
|
||||
(
|
||||
exists(HashCons head, HC_Args tail |
|
||||
args = HC_ArgCons(fcn, head, fc.getNumberOfArguments() - 1, tail) and
|
||||
mk_ArgCons(fcn, head, fc.getNumberOfArguments() - 1, tail, fc)
|
||||
args = HC_ArgCons(head, fc.getNumberOfArguments() - 1, tail) and
|
||||
mk_ArgCons(head, fc.getNumberOfArguments() - 1, tail, fc)
|
||||
)
|
||||
or
|
||||
fc.getNumberOfArguments() = 0 and
|
||||
args = HC_EmptyArgs(fcn)
|
||||
args = HC_EmptyArgs()
|
||||
)
|
||||
}
|
||||
|
||||
private predicate analyzableFunctionCall(
|
||||
FunctionCall fc
|
||||
) {
|
||||
analyzableNonmemberFunctionCall(fc)
|
||||
private predicate analyzableCall(Call c) {
|
||||
analyzableNonmemberFunctionCall(c)
|
||||
or
|
||||
analyzableMemberFunctionCall(fc)
|
||||
analyzableMemberFunctionCall(c)
|
||||
or
|
||||
analyzableExprCall(c)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `fc` is a call to `fcn`, `fc`'s first `i` arguments have hash-cons
|
||||
* `list`, and `fc`'s argument at index `i` has hash-cons `hc`.
|
||||
*/
|
||||
private predicate mk_ArgCons(Function fcn, HashCons hc, int i, HC_Args list, FunctionCall fc) {
|
||||
analyzableFunctionCall(fc) and
|
||||
fc.getTarget() = fcn and
|
||||
hc = hashCons(fc.getArgument(i).getFullyConverted()) and
|
||||
private predicate mk_ArgCons(HashCons hc, int i, HC_Args list,Call c) {
|
||||
analyzableCall(c) and
|
||||
hc = hashCons(c.getArgument(i).getFullyConverted()) and
|
||||
(
|
||||
exists(HashCons head, HC_Args tail |
|
||||
list = HC_ArgCons(fcn, head, i - 1, tail) and
|
||||
mk_ArgCons(fcn, head, i - 1, tail, fc) and
|
||||
list = HC_ArgCons(head, i - 1, tail) and
|
||||
mk_ArgCons(head, i - 1, tail, c) and
|
||||
i > 0
|
||||
)
|
||||
or
|
||||
i = 0 and
|
||||
list = HC_EmptyArgs(fcn)
|
||||
list = HC_EmptyArgs()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -545,14 +588,15 @@ private predicate mk_ArgCons(Function fcn, HashCons hc, int i, HC_Args list, Fun
|
||||
* Holds if `fc` is a call to `fcn`, `fc`'s first `i` arguments have hash-cons
|
||||
* `list`, and `fc`'s argument at index `i` has hash-cons `hc`.
|
||||
*/
|
||||
private predicate mk_AllocArgCons(Function fcn, HashCons hc, int i, HC_Alloc list, boolean aligned, FunctionCall fc) {
|
||||
analyzableFunctionCall(fc) and
|
||||
fc.getTarget() = fcn and
|
||||
hc = hashCons(fc.getArgument(i).getFullyConverted()) and
|
||||
private predicate mk_AllocArgCons(Function fcn, HashCons hc, int i, HC_Alloc list, boolean aligned,
|
||||
Call c) {
|
||||
analyzableCall(c) and
|
||||
c.getTarget() = fcn and
|
||||
hc = hashCons(c.getArgument(i).getFullyConverted()) and
|
||||
(
|
||||
exists(HashCons head, HC_Alloc tail |
|
||||
list = HC_AllocArgCons(fcn, head, i - 1, tail, aligned) and
|
||||
mk_AllocArgCons(fcn, head, i - 1, tail, aligned, fc) and
|
||||
mk_AllocArgCons(fcn, head, i - 1, tail, aligned, c) and
|
||||
(
|
||||
aligned = true and
|
||||
i > 2
|
||||
@@ -735,6 +779,34 @@ private predicate mk_SizeofExpr(HashCons child, SizeofExprOperator e) {
|
||||
child = hashCons(e.getAChild())
|
||||
}
|
||||
|
||||
private predicate analyzableUuidofOperator(UuidofOperator e) {
|
||||
strictcount(e.getTypeOperand()) = 1
|
||||
}
|
||||
|
||||
private predicate mk_UuidofOperator(Type t, UuidofOperator e) {
|
||||
analyzableUuidofOperator(e) and
|
||||
t = e.getTypeOperand()
|
||||
}
|
||||
|
||||
private predicate analyzableTypeidType(TypeidOperator e) {
|
||||
strictcount(e.getAChild()) = 0
|
||||
}
|
||||
|
||||
private predicate mk_TypeidType(Type t, TypeidOperator e) {
|
||||
analyzableTypeidType(e) and
|
||||
t = e.getResultType()
|
||||
}
|
||||
|
||||
private predicate analyzableTypeidExpr(Expr e) {
|
||||
e instanceof TypeidOperator and
|
||||
strictcount(e.getAChild().getFullyConverted()) = 1
|
||||
}
|
||||
|
||||
private predicate mk_TypeidExpr(HashCons child, TypeidOperator e) {
|
||||
analyzableTypeidExpr(e) and
|
||||
child = hashCons(e.getAChild())
|
||||
}
|
||||
|
||||
private predicate analyzableAlignofType(AlignofTypeOperator e) {
|
||||
strictcount(e.getType().getUnspecifiedType()) = 1 and
|
||||
strictcount(e.getTypeOperand()) = 1
|
||||
@@ -851,6 +923,30 @@ private predicate mk_ReThrowExpr(ReThrowExpr te) {
|
||||
any()
|
||||
}
|
||||
|
||||
private predicate analyzableConditionalExpr(ConditionalExpr ce) {
|
||||
strictcount(ce.getCondition().getFullyConverted()) = 1 and
|
||||
strictcount(ce.getThen().getFullyConverted()) = 1 and
|
||||
strictcount(ce.getElse().getFullyConverted()) = 1
|
||||
}
|
||||
|
||||
private predicate mk_ConditionalExpr(HashCons cond, HashCons trueHc, HashCons falseHc,
|
||||
ConditionalExpr ce) {
|
||||
analyzableConditionalExpr(ce) and
|
||||
cond.getAnExpr() = ce.getCondition() and
|
||||
trueHc.getAnExpr() = ce.getThen() and
|
||||
falseHc.getAnExpr() = ce.getElse()
|
||||
}
|
||||
|
||||
private predicate analyzableNoExceptExpr(NoExceptExpr nee) {
|
||||
strictcount(nee.getAChild().getFullyConverted()) = 1
|
||||
}
|
||||
|
||||
private predicate mk_NoExceptExpr(HashCons child, NoExceptExpr nee) {
|
||||
analyzableNoExceptExpr(nee) and
|
||||
nee.getExpr() = child.getAnExpr().getFullyConverted()
|
||||
}
|
||||
|
||||
|
||||
/** Gets the hash-cons of expression `e`. */
|
||||
cached HashCons hashCons(Expr e) {
|
||||
exists (int val, Type t
|
||||
@@ -914,6 +1010,11 @@ cached HashCons hashCons(Expr e) {
|
||||
result = HC_NonmemberFunctionCall(fcn, args)
|
||||
)
|
||||
or
|
||||
exists(HashCons hc, HC_Args args
|
||||
| mk_ExprCall(hc, args, e) and
|
||||
result = HC_ExprCall(hc, args)
|
||||
)
|
||||
or
|
||||
exists(Function fcn, HashCons qual, HC_Args args
|
||||
| mk_MemberFunctionCall(fcn, qual, args, e) and
|
||||
result = HC_MemberFunctionCall(fcn, qual, args)
|
||||
@@ -940,6 +1041,16 @@ cached HashCons hashCons(Expr e) {
|
||||
)
|
||||
or
|
||||
exists(Type t
|
||||
| mk_TypeidType(t, e) and
|
||||
result = HC_TypeidType(t)
|
||||
)
|
||||
or
|
||||
exists(HashCons child
|
||||
| mk_TypeidExpr(child, e) and
|
||||
result = HC_TypeidExpr(child)
|
||||
)
|
||||
or
|
||||
exists(Type t
|
||||
| mk_AlignofType(t, e) and
|
||||
result = HC_AlignofType(t)
|
||||
)
|
||||
@@ -979,6 +1090,11 @@ cached HashCons hashCons(Expr e) {
|
||||
result = HC_ReThrowExpr()
|
||||
)
|
||||
or
|
||||
exists(HashCons cond, HashCons thenHC, HashCons elseHC
|
||||
| mk_ConditionalExpr(cond, thenHC, elseHC, e) and
|
||||
result = HC_ConditionalExpr(cond, thenHC, elseHC)
|
||||
)
|
||||
or
|
||||
(
|
||||
mk_Nullptr(e) and
|
||||
result = HC_Nullptr()
|
||||
@@ -1011,16 +1127,22 @@ predicate analyzableExpr(Expr e, string kind) {
|
||||
(analyzablePointerDereferenceExpr(e) and kind = "PointerDereferenceExpr") or
|
||||
(analyzableNonmemberFunctionCall(e) and kind = "NonmemberFunctionCall") or
|
||||
(analyzableMemberFunctionCall(e) and kind = "MemberFunctionCall") or
|
||||
(analyzableExprCall(e) and kind = "ExprCall") or
|
||||
(analyzableNewExpr(e) and kind = "NewExpr") or
|
||||
(analyzableNewArrayExpr(e) and kind = "NewArrayExpr") or
|
||||
(analyzableSizeofType(e) and kind = "SizeofTypeOperator") or
|
||||
(analyzableSizeofExpr(e) and kind = "SizeofExprOperator") or
|
||||
(analyzableAlignofType(e) and kind = "AlignofTypeOperator") or
|
||||
(analyzableAlignofExpr(e) and kind = "AlignofExprOperator") or
|
||||
(analyzableUuidofOperator(e) and kind = "UuidofOperator") or
|
||||
(analyzableTypeidType(e) and kind = "TypeidType") or
|
||||
(analyzableTypeidExpr(e) and kind = "TypeidExpr") or
|
||||
(analyzableClassAggregateLiteral(e) and kind = "ClassAggregateLiteral") or
|
||||
(analyzableArrayAggregateLiteral(e) and kind = "ArrayAggregateLiteral") or
|
||||
(analyzableDeleteExpr(e) and kind = "DeleteExpr") or
|
||||
(analyzableDeleteArrayExpr(e) and kind = "DeleteArrayExpr") or
|
||||
(analyzableThrowExpr(e) and kind = "ThrowExpr") or
|
||||
(analyzableReThrowExpr(e) and kind = "ReThrowExpr")
|
||||
(analyzableReThrowExpr(e) and kind = "ReThrowExpr") or
|
||||
(analyzableConditionalExpr(e) and kind = "ConditionalExpr") or
|
||||
(analyzableNoExceptExpr(e) and kind = "NoExceptExpr")
|
||||
}
|
||||
|
||||
@@ -111,3 +111,13 @@
|
||||
| test.cpp:311:5:311:5 | 0 | 311:c5-c5 312:c5-c5 315:c5-c5 44:c9-c9 51:c25-c25 88:c12-c12 |
|
||||
| test.cpp:313:3:313:6 | access to array | 313:c3-c6 314:c3-c6 |
|
||||
| test.cpp:315:3:315:3 | y | 315:c3-c3 316:c3-c3 |
|
||||
| test.cpp:323:3:323:11 | test_18_p | 323:c3-c11 324:c3-c11 |
|
||||
| test.cpp:323:3:323:13 | call to expression | 323:c3-c13 324:c3-c13 |
|
||||
| test.cpp:327:3:327:11 | test_19_p | 327:c3-c11 328:c3-c11 329:c3-c11 |
|
||||
| test.cpp:327:3:327:17 | call to expression | 327:c3-c17 328:c3-c17 |
|
||||
| test.cpp:327:13:327:13 | x | 327:c13-c13 328:c13-c13 329:c16-c16 |
|
||||
| test.cpp:327:16:327:16 | y | 327:c16-c16 328:c16-c16 329:c13-c13 |
|
||||
| test.cpp:333:3:333:8 | ... == ... | 333:c3-c8 334:c3-c8 336:c3-c8 |
|
||||
| test.cpp:333:3:333:16 | ... ? ... : ... | 333:c3-c16 334:c3-c16 |
|
||||
| test.cpp:333:12:333:12 | x | 333:c12-c12 333:c3-c3 334:c12-c12 334:c3-c3 335:c12-c12 335:c8-c8 336:c16-c16 336:c3-c3 |
|
||||
| test.cpp:333:16:333:16 | y | 333:c16-c16 333:c8-c8 334:c16-c16 334:c8-c8 335:c16-c16 335:c3-c3 336:c12-c12 336:c8-c8 |
|
||||
|
||||
@@ -315,3 +315,23 @@ void test19(int *x, int *y) {
|
||||
y[0];
|
||||
y[1];
|
||||
}
|
||||
|
||||
void test20(int *x, int *y) {
|
||||
void (*test_18_p)() = &test18;
|
||||
void (*test_17_p)() = &test17;
|
||||
void (*test_19_p)(int *, int *) = &test19;
|
||||
test_18_p();
|
||||
test_18_p();
|
||||
test_17_p();
|
||||
|
||||
test_19_p(x, y);
|
||||
test_19_p(x, y);
|
||||
test_19_p(y, x);
|
||||
}
|
||||
|
||||
void test21(int x, int y) {
|
||||
x == y ? x : y;
|
||||
x == y ? x : y;
|
||||
y == x ? x : y;
|
||||
x == y ? y : x;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user