Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit86322b8

Browse files
authored
Merge branch 'main' into jsinglet/slash-fixes
2 parentscf32460 +1821034 commit86322b8

File tree

38 files changed

+3120
-75
lines changed

38 files changed

+3120
-75
lines changed

‎.vscode/tasks.json‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@
244244
"Pointers",
245245
"Pointers1",
246246
"Pointers2",
247+
"Pointers3",
247248
"Scope",
248249
"SideEffects1",
249250
"SideEffects2",

‎c/cert/src/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.ql‎

Lines changed: 1 addition & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -13,50 +13,10 @@
1313

1414
import cpp
1515
import codingstandards.c.cert
16+
import codingstandards.c.Pointers
1617
import semmle.code.cpp.dataflow.TaintTracking
1718
import DataFlow::PathGraph
1819

19-
/**
20-
* An expression which performs pointer arithmetic
21-
*/
22-
abstractclassPointerArithmeticExprextendsExpr{
23-
abstractExprgetPointer();
24-
25-
abstractExprgetOperand();
26-
}
27-
28-
/**
29-
* A pointer arithmetic binary operation expression.
30-
*/
31-
classSimplePointerArithmeticExprextendsPointerArithmeticExpr,PointerArithmeticOperation{
32-
overrideExprgetPointer(){result=this.getLeftOperand()}
33-
34-
overrideExprgetOperand(){result=this.getRightOperand()}
35-
}
36-
37-
/**
38-
* A pointer arithmetic assignment expression.
39-
*/
40-
classAssignPointerArithmeticExprextendsPointerArithmeticExpr,AssignOperation{
41-
AssignPointerArithmeticExpr(){
42-
thisinstanceofAssignPointerAddExpror
43-
thisinstanceofAssignPointerSubExpr
44-
}
45-
46-
overrideExprgetPointer(){result=this.getLValue()}
47-
48-
overrideExprgetOperand(){result=this.getRValue()}
49-
}
50-
51-
/**
52-
* A pointer arithmetic array access expression.
53-
*/
54-
classArrayPointerArithmeticExprextendsPointerArithmeticExpr,ArrayExpr{
55-
overrideExprgetPointer(){result=this.getArrayBase()}
56-
57-
overrideExprgetOperand(){result=this.getArrayOffset()}
58-
}
59-
6020
/**
6121
* An expression which invokes the `offsetof` macro or `__builtin_offsetof` operation.
6222
*/
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
#EXP32-C: Do not access a volatile object through a nonvolatile reference
2+
3+
This query implements the CERT-C rule EXP32-C:
4+
5+
>Do not access a volatile object through a nonvolatile reference
6+
7+
8+
##Description
9+
10+
An object that has volatile-qualified type may be modified in ways unknown to the[implementation](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-implementation) or have other unknown[side effects](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-sideeffect). Referencing a volatile object by using a non-volatile lvalue is[undefined behavior](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-undefinedbehavior). The C Standard, 6.7.3\[[ISO/IEC 9899:2011](https://wiki.sei.cmu.edu/confluence/display/c/AA.+Bibliography#AA.Bibliography-ISO-IEC9899-2011)\], states
11+
12+
>If an attempt is made to refer to an object defined with a volatile-qualified type through use of an lvalue with non-volatile-qualified type, the behavior is undefined.
13+
14+
15+
See[undefined behavior 65](https://wiki.sei.cmu.edu/confluence/display/c/CC.+Undefined+Behavior#CC.UndefinedBehavior-ub_65).
16+
17+
##Noncompliant Code Example
18+
19+
In this noncompliant code example, a volatile object is accessed through a non-volatile-qualified reference, resulting in[undefined behavior](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-undefinedbehavior):
20+
21+
```cpp
22+
#include<stdio.h>
23+
24+
voidfunc(void) {
25+
static volatile int**ipp;
26+
static int*ip;
27+
static volatile int i = 0;
28+
29+
printf("i = %d.\n", i);
30+
31+
ipp = &ip; /* May produce a warning diagnostic*/
32+
ipp = (int**) &ip; /* Constraint violation; may produce a warning diagnostic*/
33+
*ipp = &i; /* Valid*/
34+
if (*ip != 0) { /* Valid*/
35+
/* ...*/
36+
}
37+
}
38+
```
39+
The assignment `ipp = &ip` is not safe because it allows the valid code that follows to reference the value of the volatile object `i` through the non-volatile-qualified reference `ip`. In this example, the compiler may optimize out the entire `if` block because `*ip != 0` must be false if the object to which `ip` points is not volatile.
40+
41+
**Implementation Details**
42+
43+
This example compiles without warning on Microsoft Visual Studio 2013 when compiled in C mode (`/TC`) but causes errors when compiled in C++ mode (`/TP`).
44+
45+
GCC 4.8.1 generates a warning but compiles successfully.
46+
47+
## Compliant Solution
48+
49+
In this compliant solution, `ip` is declared `volatile`:
50+
51+
```cpp
52+
#include <stdio.h>
53+
54+
void func(void) {
55+
static volatile int **ipp;
56+
static volatile int *ip;
57+
static volatile int i = 0;
58+
59+
printf("i = %d.\n", i);
60+
61+
ipp = &ip;
62+
*ipp = &i;
63+
if (*ip != 0) {
64+
/* ... */
65+
}
66+
67+
}
68+
```
69+
70+
##Risk Assessment
71+
72+
Accessing an object with a volatile-qualified type through a reference with a non-volatile-qualified type is[undefined behavior](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-undefinedbehavior).
73+
74+
<table> <tbody> <tr> <th> Rule </th> <th> Severity </th> <th> Likelihood </th> <th> Remediation Cost </th> <th> Priority </th> <th> Level </th> </tr> <tr> <td> EXP32-C </td> <td> Low </td> <td> Likely </td> <td> Medium </td> <td> <strong>P6</strong> </td> <td> <strong>L2</strong> </td> </tr> </tbody> </table>
75+
76+
77+
##Automated Detection
78+
79+
<table> <tbody> <tr> <th> Tool </th> <th> Version </th> <th> Checker </th> <th> Description </th> </tr> <tr> <td> <a> Astrée </a> </td> <td> 22.04 </td> <td> <strong>pointer-qualifier-cast-volatile</strong> <strong>pointer-qualifier-cast-volatile-implicit</strong> </td> <td> Supported indirectly via MISRA C 2012 Rule 11.8 </td> </tr> <tr> <td> <a> Axivion Bauhaus Suite </a> </td> <td> 7.2.0 </td> <td> <strong>CertC-EXP32</strong> </td> <td> Fully implemented </td> </tr> <tr> <td> <a> Clang </a> </td> <td> 3.9 </td> <td> <code>-Wincompatible-pointer-types-discards-qualifiers</code> </td> <td> </td> </tr> <tr> <td> <a> Compass/ROSE </a> </td> <td> </td> <td> </td> <td> </td> </tr> <tr> <td> <a> Coverity </a> </td> <td> 2017.07 </td> <td> <strong>MISRA C 2012 Rule 11.8</strong> </td> <td> Implemented </td> </tr> <tr> <td> <a> GCC </a> </td> <td> 4.3.5 </td> <td> </td> <td> Can detect violations of this rule when the <code>-Wcast-qual</code> flag is used </td> </tr> <tr> <td> <a> Helix QAC </a> </td> <td> 2022.4 </td> <td> <strong>C0312, C0562, C0563, C0673, C0674</strong> </td> <td> </td> </tr> <tr> <td> <a> Klocwork </a> </td> <td> 2022.4 </td> <td> <strong>CERT.EXPR.VOLATILE.ADDR</strong> <strong>CERT.EXPR.VOLATILE.ADDR.PARAM</strong> <strong>CERT.EXPR.VOLATILE.PTRPTR</strong> </td> <td> </td> </tr> <tr> <td> <a> LDRA tool suite </a> </td> <td> 9.7.1 </td> <td> <strong>344 S</strong> </td> <td> Partially implemented </td> </tr> <tr> <td> <a> Parasoft C/C++test </a> </td> <td> 2022.2 </td> <td> <strong>CERT_C-EXP32-a</strong> </td> <td> A cast shall not remove any 'const' or 'volatile' qualification from the type of a pointer or reference </td> </tr> <tr> <td> <a> Polyspace Bug Finder </a> </td> <td> </td> <td> <a> CERT C: Rule EXP32-C </a> </td> <td> Checks for cast to pointer that removes const or volatile qualification (rule fully covered) </td> </tr> <tr> <td> <a> PRQA QA-C </a> </td> <td> 9.7 </td> <td> <strong>0312,562,563,673,674</strong> </td> <td> Fully implemented </td> </tr> <tr> <td> <a> RuleChecker </a> </td> <td> 22.04 </td> <td> <strong>pointer-qualifier-cast-volatile</strong> <strong>pointer-qualifier-cast-volatile-implicit</strong> </td> <td> Supported indirectly via MISRA C 2012 Rule 11.8 </td> </tr> </tbody> </table>
80+
81+
82+
##Related Vulnerabilities
83+
84+
Search for[vulnerabilities](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-vulnerability) resulting from the violation of this rule on the[CERT website](https://www.kb.cert.org/vulnotes/bymetric?searchview&query=FIELD+KEYWORDS+contains+EXP32-C).
85+
86+
##Related Guidelines
87+
88+
[Key here](https://wiki.sei.cmu.edu/confluence/display/c/How+this+Coding+Standard+is+Organized#HowthisCodingStandardisOrganized-RelatedGuidelines) (explains table format and definitions)
89+
90+
<table> <tbody> <tr> <th> Taxonomy </th> <th> Taxonomy item </th> <th> Relationship </th> </tr> <tr> <td> <a> ISO/IEC TR 24772:2013 </a> </td> <td> Pointer Casting and Pointer Type Changes \[HFC\] </td> <td> Prior to 2018-01-12: CERT: Unspecified Relationship </td> </tr> <tr> <td> <a> ISO/IEC TR 24772:2013 </a> </td> <td> Type System \[IHN\] </td> <td> Prior to 2018-01-12: CERT: Unspecified Relationship </td> </tr> <tr> <td> <a> MISRA C:2012 </a> </td> <td> Rule 11.8 (required) </td> <td> Prior to 2018-01-12: CERT: Unspecified Relationship </td> </tr> <tr> <td> <a> CERT C </a> </td> <td> <a> EXP55-CPP. Do not access a cv-qualified object through a cv-unqualified type </a> </td> <td> Prior to 2018-01-12: CERT: Unspecified Relationship </td> </tr> </tbody> </table>
91+
92+
93+
##Bibliography
94+
95+
<table> <tbody> <tr> <td> \[ <a> ISO/IEC 9899:2011 </a> \] </td> <td> 6.7.3, "Type Qualifiers" </td> </tr> </tbody> </table>
96+
97+
98+
##Implementation notes
99+
100+
In limited cases, this query can raise false-positives for assignment of volatile objects and subsequent accesses of those objects via non-volatile pointers.
101+
102+
##References
103+
104+
* CERT-C:[EXP32-C: Do not access a volatile object through a nonvolatile reference](https://wiki.sei.cmu.edu/confluence/display/c)
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/**
2+
* @id c/cert/do-not-access-volatile-object-with-non-volatile-reference
3+
* @name EXP32-C: Do not access a volatile object through a nonvolatile reference
4+
* @description If an an object defined with a volatile-qualified type is referred to with an lvalue
5+
* of a non-volatile-qualified type, the behavior is undefined.
6+
* @kind problem
7+
* @precision high
8+
* @problem.severity error
9+
* @tags external/cert/id/exp32-c
10+
* correctness
11+
* external/cert/obligation/rule
12+
*/
13+
14+
import cpp
15+
import codingstandards.c.cert
16+
import semmle.code.cpp.controlflow.Dereferenced
17+
18+
/**
19+
* An expression involving volatile-qualified types that results in undefined behavior.
20+
*/
21+
abstractclassUndefinedVolatilePointerExprextendsExpr{
22+
/**
23+
* Gets a descriptive string describing the type of expression and undefined behavior.
24+
*/
25+
abstractstringgetMessage();
26+
}
27+
28+
/**
29+
* Gets the depth of a pointer's base type's volatile qualifier
30+
*/
31+
intgetAVolatileDepth(Typetype){
32+
type.isVolatile()andresult=1
33+
or
34+
result=getAVolatileDepth(type.(DerivedType).getBaseType())+1
35+
}
36+
37+
/**
38+
* A `Cast` which converts from a pointer to a volatile-qualified type
39+
* to a pointer to a non-volatile-qualified type.
40+
*/
41+
classCastFromVolatileToNonVolatileBaseTypeextendsCast,UndefinedVolatilePointerExpr{
42+
CastFromVolatileToNonVolatileBaseType(){
43+
exists(inti|
44+
i=getAVolatileDepth(this.getExpr().getType())and
45+
noti=getAVolatileDepth(this.getActualType())
46+
)
47+
}
48+
49+
overridestringgetMessage(){
50+
result="Cast of object with a volatile-qualified type to a non-volatile-qualified type."
51+
}
52+
}
53+
54+
/**
55+
* Holds if `va` has a subsequent `VariableAccess` which is dereferenced after access
56+
*/
57+
bindingset[va]
58+
predicatehasSubsequentDereference(VariableAccessva){
59+
dereferenced(pragma[only_bind_out](va).getASuccessor+())
60+
}
61+
62+
/**
63+
* An `AssignExpr` with an *lvalue* that is a pointer to a volatile base type and
64+
* and *rvalue* that is not also a pointer to a volatile base type.
65+
*/
66+
classNonVolatileObjectAssignedToVolatilePointerextendsAssignExpr,UndefinedVolatilePointerExpr{
67+
NonVolatileObjectAssignedToVolatilePointer(){
68+
exists(inti|
69+
noti=getAVolatileDepth(this.getRValue().getType())and
70+
i=getAVolatileDepth(this.getLValue().(VariableAccess).getTarget().getType())
71+
)and
72+
// Checks for subsequent accesses to the underlying object via the original non-volatile
73+
// pointer assigned to the volatile pointer. This heuristic can cause false-positives
74+
// in certain instances which require more advanced reachability analysis, e.g. loops and scope
75+
// considerations that this simple forward traversal of the control-flow graph does not account for.
76+
exists(VariableAccessva|
77+
va=this.getRValue().getAChild*().(VariableAccess).getTarget().getAnAccess()and
78+
hasSubsequentDereference(va)
79+
)
80+
}
81+
82+
overridestringgetMessage(){
83+
result=
84+
"Assignment indicates a volatile object, but a later access of the object occurs via a non-volatile pointer."
85+
}
86+
}
87+
88+
fromUndefinedVolatilePointerExpre
89+
wherenotisExcluded(e, Pointers3Package::doNotAccessVolatileObjectWithNonVolatileReferenceQuery())
90+
selecte,e.getMessage()

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp