|
13 | 13 |
|
14 | 14 | import cpp
|
15 | 15 | import codingstandards.c.cert
|
| 16 | +import semmle.code.cpp.controlflow.Dereferenced |
| 17 | +import semmle.code.cpp.controlflow.StackVariableReachability |
| 18 | + |
| 19 | +abstract class UndefinedVolatilePointerExpr extends Expr { |
| 20 | + abstract string getMessage(); |
| 21 | +} |
| 22 | + |
| 23 | +/** |
| 24 | + * Gets the depth of a pointer's base type's volatile qualifier |
| 25 | + */ |
| 26 | +int getAVolatileDepth(PointerType pt) { |
| 27 | + pt.getBaseType().isVolatile() and result = 1 |
| 28 | + or |
| 29 | + result = getAVolatileDepth(pt.getBaseType()) + 1 |
| 30 | +} |
16 | 31 |
|
17 | 32 | /**
|
18 | 33 | * A `Cast` which converts from a pointer to a volatile-qualified type
|
19 | 34 | * to a pointer to a non-volatile-qualified type.
|
20 | 35 | */
|
21 |
| -class CastFromVolatileToNonVolatileBaseType extends Cast { |
| 36 | +class CastFromVolatileToNonVolatileBaseType extends Cast, UndefinedVolatilePointerExpr { |
22 | 37 | CastFromVolatileToNonVolatileBaseType() {
|
23 |
| - this.getExpr().getType().(PointerType).getBaseType*().isVolatile() and |
24 |
| - this.getActualType() instanceof PointerType and |
25 |
| - not this.getActualType().(PointerType).getBaseType*().isVolatile() |
| 38 | + exists(int i | |
| 39 | + i = getAVolatileDepth(this.getExpr().getType()) and |
| 40 | + not i = getAVolatileDepth(this.getActualType()) |
| 41 | + ) |
| 42 | + } |
| 43 | + |
| 44 | + override string getMessage() { |
| 45 | + result = "Cast of object with a volatile-qualified type to a non-volatile-qualified type." |
26 | 46 | }
|
27 | 47 | }
|
28 | 48 |
|
29 | 49 | /**
|
30 | 50 | * An `AssignExpr` with an *lvalue* that is a pointer to a volatile base type and
|
31 | 51 | * and *rvalue* that is not also a pointer to a volatile base type.
|
32 | 52 | */
|
33 |
| -class NonVolatileObjectAssignedToVolatilePointer extends AssignExpr { |
| 53 | +class NonVolatileObjectAssignedToVolatilePointer extends AssignExpr, UndefinedVolatilePointerExpr { |
34 | 54 | NonVolatileObjectAssignedToVolatilePointer() {
|
35 |
| - this.getLValue().getType().(DerivedType).getBaseType*().isVolatile() and |
36 |
| - not this.getRValue().getUnconverted().getType().(DerivedType).getBaseType*().isVolatile() |
| 55 | + exists(int i | |
| 56 | + not i = getAVolatileDepth(this.getRValue().getType()) and |
| 57 | + i = getAVolatileDepth(this.getLValue().(VariableAccess).getTarget().getType()) |
| 58 | + ) and |
| 59 | + exists(VariableAccess va | |
| 60 | + va = this.getRValue().getAChild*().(VariableAccess).getTarget().getAnAccess() and |
| 61 | + this.getASuccessor+() = va |
| 62 | + ) |
37 | 63 | }
|
38 | 64 |
|
39 |
| - /** |
40 |
| - * All `VariableAccess` expressions which are transitive successors of |
41 |
| - * this `Expr` and which access the variable accessed in the *rvalue* of this `Expr` |
42 |
| - */ |
43 |
| - Expr getASubsequentAccessOfAssignedObject() { |
| 65 | + override string getMessage() { |
44 | 66 | result =
|
45 |
| - any(VariableAccess va | |
46 |
| - va = this.getRValue().getAChild*().(VariableAccess).getTarget().getAnAccess() and |
47 |
| - this.getASuccessor+() = va |
48 |
| - | |
49 |
| - va |
50 |
| - ) |
| 67 | + "Assignment indicates a volatile object, but a later access of the object occurs via a non-volatile pointer." |
51 | 68 | }
|
52 | 69 | }
|
53 | 70 |
|
54 |
| -from Expr e, string message |
55 |
| -where |
56 |
| - not isExcluded(e, Pointers3Package::doNotAccessVolatileObjectWithNonVolatileReferenceQuery()) and |
57 |
| - ( |
58 |
| - e instanceof CastFromVolatileToNonVolatileBaseType and |
59 |
| - message = "Cast of object with a volatile-qualified type to a non-volatile-qualified type." |
60 |
| - or |
61 |
| - exists(e.(NonVolatileObjectAssignedToVolatilePointer).getASubsequentAccessOfAssignedObject()) and |
62 |
| - message = |
63 |
| - "Non-volatile object referenced via pointer to volatile type and later accessed via its original object of a non-volatile-qualified type." |
64 |
| - ) |
65 |
| -select e, message |
| 71 | +from UndefinedVolatilePointerExpr e |
| 72 | +where not isExcluded(e, Pointers3Package::doNotAccessVolatileObjectWithNonVolatileReferenceQuery()) |
| 73 | +select e, e.getMessage() |
0 commit comments