|
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