Skip to content

Commit e276e26

Browse files
author
Dave Bartolomeo
authored
Merge pull request github#5986 from MathiasVP/side-effects-for-nonconst-smart-pointers
C++: Fix `hasDefaultSideEffect` for non-const smart pointers
2 parents eb04915 + 8e8c2e6 commit e276e26

File tree

4 files changed

+326
-1
lines changed

4 files changed

+326
-1
lines changed

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/SideEffects.qll

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,64 @@ private import semmle.code.cpp.ir.implementation.Opcode
1010
private import semmle.code.cpp.models.interfaces.PointerWrapper
1111
private import semmle.code.cpp.models.interfaces.SideEffect
1212

13+
private predicate isDeeplyConst(Type t) {
14+
t.isConst() and
15+
isDeeplyConstBelow(t)
16+
or
17+
isDeeplyConst(t.(Decltype).getBaseType())
18+
or
19+
isDeeplyConst(t.(ReferenceType).getBaseType())
20+
or
21+
exists(SpecifiedType specType | specType = t |
22+
specType.getASpecifier().getName() = "const" and
23+
isDeeplyConstBelow(specType.getBaseType())
24+
)
25+
or
26+
isDeeplyConst(t.(ArrayType).getBaseType())
27+
}
28+
29+
private predicate isDeeplyConstBelow(Type t) {
30+
t instanceof BuiltInType
31+
or
32+
not t instanceof PointerWrapper and
33+
t instanceof Class
34+
or
35+
t instanceof Enum
36+
or
37+
isDeeplyConstBelow(t.(Decltype).getBaseType())
38+
or
39+
isDeeplyConst(t.(PointerType).getBaseType())
40+
or
41+
isDeeplyConst(t.(ReferenceType).getBaseType())
42+
or
43+
isDeeplyConstBelow(t.(SpecifiedType).getBaseType())
44+
or
45+
isDeeplyConst(t.(ArrayType).getBaseType())
46+
or
47+
isDeeplyConst(t.(GNUVectorType).getBaseType())
48+
or
49+
isDeeplyConst(t.(FunctionPointerIshType).getBaseType())
50+
or
51+
isDeeplyConst(t.(PointerWrapper).getTemplateArgument(0))
52+
or
53+
isDeeplyConst(t.(PointerToMemberType).getBaseType())
54+
or
55+
isDeeplyConstBelow(t.(TypedefType).getBaseType())
56+
}
57+
58+
private predicate isConstPointerLike(Type t) {
59+
(
60+
t instanceof PointerWrapper
61+
or
62+
t instanceof PointerType
63+
or
64+
t instanceof ArrayType
65+
or
66+
t instanceof ReferenceType
67+
) and
68+
isDeeplyConstBelow(t)
69+
}
70+
1371
/**
1472
* Holds if the specified call has a side effect that does not come from a `SideEffectFunction`
1573
* model.
@@ -45,7 +103,7 @@ private predicate hasDefaultSideEffect(Call call, ParameterIndex i, boolean buff
45103
) and
46104
(
47105
isWrite = true and
48-
not call.getTarget().getParameter(i).getType().isDeeplyConstBelow()
106+
not isConstPointerLike(call.getTarget().getParameter(i).getUnderlyingType())
49107
or
50108
isWrite = false
51109
)

cpp/ql/test/library-tests/ir/ir/PrintAST.expected

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11445,6 +11445,145 @@ smart_ptr.cpp:
1144511445
# 19| Type = [ClassTemplateInstantiation] shared_ptr<float>
1144611446
# 19| ValueCategory = lvalue
1144711447
# 20| getStmt(2): [ReturnStmt] return ...
11448+
# 22| [TopLevelFunction] void shared_ptr_const_int(std::shared_ptr<int const>)
11449+
# 22| <params>:
11450+
# 22| getParameter(0): [Parameter] (unnamed parameter 0)
11451+
# 22| Type = [ClassTemplateInstantiation] shared_ptr<const int>
11452+
# 23| [TopLevelFunction] void shared_ptr_const_int_ptr(std::shared_ptr<int* const>)
11453+
# 23| <params>:
11454+
# 23| getParameter(0): [Parameter] (unnamed parameter 0)
11455+
# 23| Type = [ClassTemplateInstantiation] shared_ptr<int *const>
11456+
# 24| [TopLevelFunction] void shared_ptr_shared_ptr_const_int(std::shared_ptr<std::shared_ptr<int const>>)
11457+
# 24| <params>:
11458+
# 24| getParameter(0): [Parameter] (unnamed parameter 0)
11459+
# 24| Type = [ClassTemplateInstantiation] shared_ptr<shared_ptr<const int>>
11460+
# 25| [TopLevelFunction] void shared_ptr_const_shared_ptr_int(std::shared_ptr<std::shared_ptr<int> const>)
11461+
# 25| <params>:
11462+
# 25| getParameter(0): [Parameter] (unnamed parameter 0)
11463+
# 25| Type = [ClassTemplateInstantiation] shared_ptr<const shared_ptr<int>>
11464+
# 26| [TopLevelFunction] void shared_ptr_const_shared_ptr_const_int(std::shared_ptr<std::shared_ptr<int const> const>)
11465+
# 26| <params>:
11466+
# 26| getParameter(0): [Parameter] (unnamed parameter 0)
11467+
# 26| Type = [ClassTemplateInstantiation] shared_ptr<const shared_ptr<const int>>
11468+
# 28| [TopLevelFunction] void call_shared_ptr_consts()
11469+
# 28| <params>:
11470+
# 28| getEntryPoint(): [BlockStmt] { ... }
11471+
# 29| getStmt(0): [DeclStmt] declaration
11472+
# 29| getDeclarationEntry(0): [VariableDeclarationEntry] definition of sp_const_int
11473+
# 29| Type = [ClassTemplateInstantiation] shared_ptr<const int>
11474+
# 31| getStmt(1): [ExprStmt] ExprStmt
11475+
# 31| getExpr(): [FunctionCall] call to shared_ptr_const_int
11476+
# 31| Type = [VoidType] void
11477+
# 31| ValueCategory = prvalue
11478+
# 31| getArgument(0): [ConstructorCall] call to shared_ptr
11479+
# 31| Type = [VoidType] void
11480+
# 31| ValueCategory = prvalue
11481+
# 31| getArgument(0): [VariableAccess] sp_const_int
11482+
# 31| Type = [ClassTemplateInstantiation] shared_ptr<const int>
11483+
# 31| ValueCategory = lvalue
11484+
# 31| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
11485+
# 31| Type = [LValueReferenceType] const shared_ptr<const int> &
11486+
# 31| ValueCategory = prvalue
11487+
# 31| getExpr(): [CStyleCast] (const shared_ptr<const int>)...
11488+
# 31| Conversion = [GlvalueConversion] glvalue conversion
11489+
# 31| Type = [SpecifiedType] const shared_ptr<const int>
11490+
# 31| ValueCategory = lvalue
11491+
# 31| getArgument(0).getFullyConverted(): [TemporaryObjectExpr] temporary object
11492+
# 31| Type = [ClassTemplateInstantiation] shared_ptr<const int>
11493+
# 31| ValueCategory = lvalue
11494+
# 33| getStmt(2): [DeclStmt] declaration
11495+
# 33| getDeclarationEntry(0): [VariableDeclarationEntry] definition of sp_const_int_pointer
11496+
# 33| Type = [ClassTemplateInstantiation] shared_ptr<int *const>
11497+
# 35| getStmt(3): [ExprStmt] ExprStmt
11498+
# 35| getExpr(): [FunctionCall] call to shared_ptr_const_int_ptr
11499+
# 35| Type = [VoidType] void
11500+
# 35| ValueCategory = prvalue
11501+
# 35| getArgument(0): [ConstructorCall] call to shared_ptr
11502+
# 35| Type = [VoidType] void
11503+
# 35| ValueCategory = prvalue
11504+
# 35| getArgument(0): [VariableAccess] sp_const_int_pointer
11505+
# 35| Type = [ClassTemplateInstantiation] shared_ptr<int *const>
11506+
# 35| ValueCategory = lvalue
11507+
# 35| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
11508+
# 35| Type = [LValueReferenceType] const shared_ptr<int *const> &
11509+
# 35| ValueCategory = prvalue
11510+
# 35| getExpr(): [CStyleCast] (const shared_ptr<int *const>)...
11511+
# 35| Conversion = [GlvalueConversion] glvalue conversion
11512+
# 35| Type = [SpecifiedType] const shared_ptr<int *const>
11513+
# 35| ValueCategory = lvalue
11514+
# 35| getArgument(0).getFullyConverted(): [TemporaryObjectExpr] temporary object
11515+
# 35| Type = [ClassTemplateInstantiation] shared_ptr<int *const>
11516+
# 35| ValueCategory = lvalue
11517+
# 37| getStmt(4): [DeclStmt] declaration
11518+
# 37| getDeclarationEntry(0): [VariableDeclarationEntry] definition of sp_sp_const_int
11519+
# 37| Type = [ClassTemplateInstantiation] shared_ptr<shared_ptr<const int>>
11520+
# 39| getStmt(5): [ExprStmt] ExprStmt
11521+
# 39| getExpr(): [FunctionCall] call to shared_ptr_shared_ptr_const_int
11522+
# 39| Type = [VoidType] void
11523+
# 39| ValueCategory = prvalue
11524+
# 39| getArgument(0): [ConstructorCall] call to shared_ptr
11525+
# 39| Type = [VoidType] void
11526+
# 39| ValueCategory = prvalue
11527+
# 39| getArgument(0): [VariableAccess] sp_sp_const_int
11528+
# 39| Type = [ClassTemplateInstantiation] shared_ptr<shared_ptr<const int>>
11529+
# 39| ValueCategory = lvalue
11530+
# 39| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
11531+
# 39| Type = [LValueReferenceType] const shared_ptr<shared_ptr<const int>> &
11532+
# 39| ValueCategory = prvalue
11533+
# 39| getExpr(): [CStyleCast] (const shared_ptr<shared_ptr<const int>>)...
11534+
# 39| Conversion = [GlvalueConversion] glvalue conversion
11535+
# 39| Type = [SpecifiedType] const shared_ptr<shared_ptr<const int>>
11536+
# 39| ValueCategory = lvalue
11537+
# 39| getArgument(0).getFullyConverted(): [TemporaryObjectExpr] temporary object
11538+
# 39| Type = [ClassTemplateInstantiation] shared_ptr<shared_ptr<const int>>
11539+
# 39| ValueCategory = lvalue
11540+
# 41| getStmt(6): [DeclStmt] declaration
11541+
# 41| getDeclarationEntry(0): [VariableDeclarationEntry] definition of sp_const_sp_int
11542+
# 41| Type = [ClassTemplateInstantiation] shared_ptr<const shared_ptr<int>>
11543+
# 43| getStmt(7): [ExprStmt] ExprStmt
11544+
# 43| getExpr(): [FunctionCall] call to shared_ptr_const_shared_ptr_int
11545+
# 43| Type = [VoidType] void
11546+
# 43| ValueCategory = prvalue
11547+
# 43| getArgument(0): [ConstructorCall] call to shared_ptr
11548+
# 43| Type = [VoidType] void
11549+
# 43| ValueCategory = prvalue
11550+
# 43| getArgument(0): [VariableAccess] sp_const_sp_int
11551+
# 43| Type = [ClassTemplateInstantiation] shared_ptr<const shared_ptr<int>>
11552+
# 43| ValueCategory = lvalue
11553+
# 43| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
11554+
# 43| Type = [LValueReferenceType] const shared_ptr<const shared_ptr<int>> &
11555+
# 43| ValueCategory = prvalue
11556+
# 43| getExpr(): [CStyleCast] (const shared_ptr<const shared_ptr<int>>)...
11557+
# 43| Conversion = [GlvalueConversion] glvalue conversion
11558+
# 43| Type = [SpecifiedType] const shared_ptr<const shared_ptr<int>>
11559+
# 43| ValueCategory = lvalue
11560+
# 43| getArgument(0).getFullyConverted(): [TemporaryObjectExpr] temporary object
11561+
# 43| Type = [ClassTemplateInstantiation] shared_ptr<const shared_ptr<int>>
11562+
# 43| ValueCategory = lvalue
11563+
# 45| getStmt(8): [DeclStmt] declaration
11564+
# 45| getDeclarationEntry(0): [VariableDeclarationEntry] definition of sp_const_sp_const_int
11565+
# 45| Type = [ClassTemplateInstantiation] shared_ptr<const shared_ptr<const int>>
11566+
# 47| getStmt(9): [ExprStmt] ExprStmt
11567+
# 47| getExpr(): [FunctionCall] call to shared_ptr_const_shared_ptr_const_int
11568+
# 47| Type = [VoidType] void
11569+
# 47| ValueCategory = prvalue
11570+
# 47| getArgument(0): [ConstructorCall] call to shared_ptr
11571+
# 47| Type = [VoidType] void
11572+
# 47| ValueCategory = prvalue
11573+
# 47| getArgument(0): [VariableAccess] sp_const_sp_const_int
11574+
# 47| Type = [ClassTemplateInstantiation] shared_ptr<const shared_ptr<const int>>
11575+
# 47| ValueCategory = lvalue
11576+
# 47| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
11577+
# 47| Type = [LValueReferenceType] const shared_ptr<const shared_ptr<const int>> &
11578+
# 47| ValueCategory = prvalue
11579+
# 47| getExpr(): [CStyleCast] (const shared_ptr<const shared_ptr<const int>>)...
11580+
# 47| Conversion = [GlvalueConversion] glvalue conversion
11581+
# 47| Type = [SpecifiedType] const shared_ptr<const shared_ptr<const int>>
11582+
# 47| ValueCategory = lvalue
11583+
# 47| getArgument(0).getFullyConverted(): [TemporaryObjectExpr] temporary object
11584+
# 47| Type = [ClassTemplateInstantiation] shared_ptr<const shared_ptr<const int>>
11585+
# 47| ValueCategory = lvalue
11586+
# 48| getStmt(10): [ReturnStmt] return ...
1144811587
struct_init.cpp:
1144911588
# 1| [TopLevelFunction] int handler1(void*)
1145011589
# 1| <params>:

0 commit comments

Comments
 (0)