Skip to content

Commit a79ad24

Browse files
authored
Merge pull request #338 from github/lcartey/final-compiler-compat-issues
Fixing the final compatibility issues
2 parents a03c176 + a24fca8 commit a79ad24

File tree

50 files changed

+501
-374
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+501
-374
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- `A8-4-13`
2+
- Address false positives caused by missing modelling of modifying operations for smart pointers for some standard libraries (such as libstdc++).
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
- `A20-8-1`/`MEM56-CPP`
2+
- Address false negatives caused by lack of modelling of flow through smart pointers.
3+
- Reduce flow paths through standard library headers to simplify results.
4+
- `A18-1-4`
5+
- Address false positives caused by missing modelling of modifying operations for smart pointers for some standard libraries (such as libstdc++).
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- `STR51-CPP`
2+
- Address false negatives caused by incomplete modelling of the `std::string::replace()` function.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
- `A15-5-1`
2+
- Rephrase alert message for `noalert(false)` special functions to clarify that this permits exceptions.
3+
- Additional results for implicit `noexcept(true)` special functions highlighting that the specification should be made explicit.

cpp/autosar/src/rules/A15-2-2/ConstructorErrorLeavesObjectInInvalidState.ql

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,18 @@ class DeleteWrapperFunction extends Function {
7878
class ExceptionThrownInConstructor extends ExceptionThrowingExpr {
7979
Constructor c;
8080

81-
ExceptionThrownInConstructor() { exists(getAFunctionThrownType(c, this)) }
81+
ExceptionThrownInConstructor() {
82+
exists(getAFunctionThrownType(c, this)) and
83+
// The constructor is within the users source code
84+
exists(c.getFile().getRelativePath())
85+
}
8286

8387
Constructor getConstructor() { result = c }
8488
}
8589

90+
/**
91+
* Add the `nodes` predicate to ensure results with an empty path are still reported.
92+
*/
8693
query predicate nodes(ExceptionFlowNode node) { any() }
8794

8895
from

cpp/autosar/src/rules/A15-5-1/SpecialFunctionMissingNoExceptSpecification.ql

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,25 @@ import codingstandards.cpp.exceptions.ExceptionSpecifications
2222
from SpecialFunction f, string message
2323
where
2424
not isExcluded(f, Exceptions2Package::specialFunctionMissingNoExceptSpecificationQuery()) and
25-
not isNoExceptTrue(f) and
25+
not isFDENoExceptTrue(f.getDefinition()) and
2626
not f.isCompilerGenerated() and
2727
not f.isDeleted() and
2828
not f.isDefaulted() and
2929
(
3030
isNoExceptExplicitlyFalse(f) and
31-
message = f.getQualifiedName() + " should not be noexcept(false)."
31+
message =
32+
"Special function " + f.getQualifiedName() +
33+
" has a noexcept(false) specification that permits exceptions."
3234
or
35+
isNoExceptTrue(f) and
36+
message =
37+
f.getQualifiedName() +
38+
" has an implicit noexcept(true) specification but should make that explicit."
39+
or
40+
not isNoExceptTrue(f) and
3341
not isNoExceptExplicitlyFalse(f) and
34-
message = f.getQualifiedName() + " is implicitly noexcept(false) and might throw."
42+
message =
43+
"Special function " + f.getQualifiedName() +
44+
" has an implicit noexcept(false) specification that permits exceptions."
3545
)
3646
select f, message

cpp/autosar/src/rules/A18-1-4/PointerToAnElementOfAnArrayPassedToASmartPointer.ql

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,28 @@ class SingleObjectSmartPointerArrayConstructionConfig extends TaintTracking::Con
4646
(
4747
sp.getAConstructorCallWithExternalObjectConstruction().getAnArgument() = sink.asExpr()
4848
or
49-
sink.asExpr() =
50-
any(FunctionCall fc, MemberFunction mf |
51-
mf = fc.getTarget() and
52-
mf.getDeclaringType() = sp and
53-
mf.getName() = "reset"
54-
|
55-
fc.getArgument(0)
56-
)
49+
sink.asExpr() = sp.getAResetCall().getArgument(0)
5750
)
5851
)
5952
}
53+
54+
override predicate isAdditionalTaintStep(DataFlow::Node source, DataFlow::Node sink) {
55+
exists(AutosarUniquePointer sp, FunctionCall fc |
56+
fc = sp.getAReleaseCall() and
57+
source.asExpr() = fc.getQualifier() and
58+
sink.asExpr() = fc
59+
)
60+
}
61+
62+
override predicate isSanitizerIn(DataFlow::Node node) {
63+
// Exclude flow into header files outside the source archive which are summarized by the
64+
// additional taint steps above.
65+
exists(AutosarUniquePointer sp |
66+
sp.getAReleaseCall().getTarget() = node.asExpr().(ThisExpr).getEnclosingFunction()
67+
|
68+
not exists(node.getLocation().getFile().getRelativePath())
69+
)
70+
}
6071
}
6172

6273
from

cpp/autosar/src/rules/A8-4-13/SharedPtrPassedToFunctionWithImproperSemantics.ql

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,15 @@ import cpp
1919
import codingstandards.cpp.autosar
2020
import codingstandards.cpp.SmartPointers
2121

22-
Expr underlyingObjectAffectingSharedPointerExpr(Function f) {
23-
result =
24-
any(VariableAccess va, FunctionCall fc |
25-
va.getEnclosingFunction() = f and
26-
// strip the type so as to include reference parameter types
27-
va.getType().stripType() instanceof AutosarSharedPointer and
28-
fc.getTarget().getDeclaringType().stripType() instanceof AutosarSharedPointer and
29-
fc.getQualifier() = va and
30-
// include only calls to methods which modify the underlying object
31-
fc.getTarget().hasName(["operator=", "reset", "swap"])
32-
|
33-
va
34-
)
22+
VariableAccess underlyingObjectAffectingSharedPointerExpr(Function f) {
23+
exists(FunctionCall fc |
24+
// Find a call in the function
25+
fc.getEnclosingFunction() = f and
26+
// include only calls to methods which modify the underlying object
27+
fc = any(AutosarSharedPointer s).getAModifyingCall() and
28+
// Report the qualifier
29+
fc.getQualifier() = result
30+
)
3531
}
3632

3733
predicate flowsToUnderlyingObjectAffectingExpr(Parameter p) {
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-w

cpp/autosar/test/rules/A12-0-2/test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#include <cstdlib>
2-
#include <string>
2+
#include <cstring>
33

44
class A {
55
public:
Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
| test.cpp:5:3:5:9 | ~ClassA | ClassA::~ClassA should not be noexcept(false). |
2-
| test.cpp:9:3:9:9 | ~ClassB | ClassB::~ClassB should not be noexcept(false). |
3-
| test.cpp:38:6:38:20 | operator delete | operator delete is implicitly noexcept(false) and might throw. |
4-
| test.cpp:43:6:43:20 | operator delete | operator delete is implicitly noexcept(false) and might throw. |
5-
| test.cpp:53:11:53:19 | operator= | ClassF::operator= should not be noexcept(false). |
6-
| test.cpp:63:3:63:8 | ClassH | ClassH::ClassH should not be noexcept(false). |
7-
| test.cpp:68:6:68:9 | swap | swap is implicitly noexcept(false) and might throw. |
8-
| test.cpp:72:6:72:9 | swap | swap should not be noexcept(false). |
9-
| test.cpp:77:8:77:11 | swap | ClassI::swap is implicitly noexcept(false) and might throw. |
10-
| test.cpp:82:8:82:11 | swap | ClassJ::swap is implicitly noexcept(false) and might throw. |
11-
| test.cpp:88:6:88:6 | swap | swap is implicitly noexcept(false) and might throw. |
1+
| test.cpp:5:3:5:9 | ~ClassA | Special function ClassA::~ClassA has a noexcept(false) specification that permits exceptions. |
2+
| test.cpp:9:3:9:9 | ~ClassB | Special function ClassB::~ClassB has a noexcept(false) specification that permits exceptions. |
3+
| test.cpp:38:6:38:20 | operator delete | operator delete has an implicit noexcept(true) specification but should make that explicit. |
4+
| test.cpp:43:6:43:20 | operator delete | operator delete has an implicit noexcept(true) specification but should make that explicit. |
5+
| test.cpp:53:11:53:19 | operator= | Special function ClassF::operator= has a noexcept(false) specification that permits exceptions. |
6+
| test.cpp:63:3:63:8 | ClassH | Special function ClassH::ClassH has a noexcept(false) specification that permits exceptions. |
7+
| test.cpp:68:6:68:9 | swap | Special function swap has an implicit noexcept(false) specification that permits exceptions. |
8+
| test.cpp:72:6:72:9 | swap | Special function swap has a noexcept(false) specification that permits exceptions. |
9+
| test.cpp:77:8:77:11 | swap | Special function ClassI::swap has an implicit noexcept(false) specification that permits exceptions. |
10+
| test.cpp:82:8:82:11 | swap | Special function ClassJ::swap has an implicit noexcept(false) specification that permits exceptions. |
11+
| test.cpp:88:6:88:6 | swap | Special function swap has an implicit noexcept(false) specification that permits exceptions. |

cpp/autosar/test/rules/A15-5-1/test.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#include "stddef.h"
2+
#include <new>
23
#include <stdexcept>
3-
44
class ClassA {
55
~ClassA() noexcept(false) { throw std::exception(); } // NON_COMPLIANT
66
};
@@ -36,12 +36,12 @@ class ClassD {
3636
};
3737

3838
void operator delete(void *ptr) { // NON_COMPLIANT
39-
// NOTE: cannot be declared noexcept(false)
39+
// NOTE: defaults to noexcept(true)
4040
throw std::exception();
4141
}
4242

4343
void operator delete(void *ptr, size_t size) { // NON_COMPLIANT
44-
// NOTE: cannot be declared noexcept(false)
44+
// NOTE: defaults to noexcept(true)
4545
throw std::exception();
4646
}
4747

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
| test.cpp:1:1:1:19 | #include "test.hpp" | Nothing in this file uses anything from "test.hpp" |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
| test.cpp:1:1:1:19 | #include "test.hpp" | Nothing in this file uses anything from "test.hpp" |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
| test.cpp:1:1:1:19 | #include "test.hpp" | Nothing in this file uses anything from "test.hpp" |
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
#include "test.hpp" //NON_COMPLIANT
2-
#include <algorithm> //NON_COMPLIANT
1+
#include "test.hpp" //NON_COMPLIANT
2+
#include <algorithm> //NON_COMPLIANT - redundant but not useless on real compilers
33
#include <vector> //COMPLIANT
44

55
std::vector<int> v;

cpp/autosar/test/rules/A18-5-5/test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ void *malloc1(int b) { // NON_COMPLIANT - recursion
1111
return malloc1(b - 1);
1212
}
1313

14-
void *malloc2(int b) __attribute__((no_caller_saved_registers, __malloc__));
14+
void *malloc2(int b) __attribute__((__malloc__));
1515
void *malloc2(int b) { // NON_COMPLIANT - execution doesn't depend on b
1616

1717
for (int i = 0; i < 10; i++) {

cpp/autosar/test/rules/A18-5-6/test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ void *malloc1(int b) __attribute__((malloc));
44

55
void *malloc1(int b) { return nullptr; } // NON_COMPLIANT
66

7-
void *malloc3(int b) __attribute__((no_caller_saved_registers, __malloc__));
7+
void *malloc3(int b) __attribute__((__malloc__));
88
void *malloc3(int b) { return nullptr; } // NON_COMPLIANT
99

1010
void h1() {} // NON_COMPLIANT

cpp/autosar/test/rules/M18-0-5/test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#include <string>
1+
#include <cstring>
22

33
void test_unbounded_str_funs() {
44
char str1[] = "Sample string";

cpp/cert/test/rules/EXP62-CPP/test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#include <string>
1+
#include <cstring>
22

33
struct S1 {
44
int i, j, k;

cpp/cert/test/rules/OOP57-CPP/test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#include <string>
1+
#include <cstring>
22

33
class trivial {};
44

cpp/common/src/codingstandards/cpp/Concurrency.qll

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,10 @@ class CPPMutexFunctionCall extends MutexFunctionCall {
114114
/**
115115
* Holds if this `CPPMutexFunctionCall` is a lock.
116116
*/
117-
override predicate isLock() { getTarget().getName() = "lock" }
117+
override predicate isLock() {
118+
not isLockingOperationWithinLockingOperation(this) and
119+
getTarget().getName() = "lock"
120+
}
118121

119122
/**
120123
* Holds if this `CPPMutexFunctionCall` is a speculative lock, defined as calling
@@ -172,6 +175,7 @@ class CMutexFunctionCall extends MutexFunctionCall {
172175
* Holds if this `CMutexFunctionCall` is a lock.
173176
*/
174177
override predicate isLock() {
178+
not isLockingOperationWithinLockingOperation(this) and
175179
getTarget().getName() = ["mtx_lock", "mtx_timedlock", "mtx_trylock"]
176180
}
177181

@@ -296,6 +300,16 @@ abstract class LockingOperation extends FunctionCall {
296300
* Holds if this is an unlock operation
297301
*/
298302
abstract predicate isUnlock();
303+
304+
/**
305+
* Holds if this locking operation is really a locking operation within a
306+
* designated locking operation. This library assumes the underlying locking
307+
* operations are implemented correctly in that calling a `LockingOperation`
308+
* results in the creation of a singular lock.
309+
*/
310+
predicate isLockingOperationWithinLockingOperation(LockingOperation inner) {
311+
exists(LockingOperation outer | outer.getTarget() = inner.getEnclosingFunction())
312+
}
299313
}
300314

301315
/**
@@ -317,6 +331,7 @@ class RAIIStyleLock extends LockingOperation {
317331
* Holds if this is a lock operation
318332
*/
319333
override predicate isLock() {
334+
not isLockingOperationWithinLockingOperation(this) and
320335
this instanceof ConstructorCall and
321336
lock = getArgument(0).getAChild*() and
322337
// defer_locks don't cause a lock

cpp/common/src/codingstandards/cpp/SmartPointers.qll

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ abstract class AutosarSmartPointer extends Class {
2929
)
3030
}
3131

32+
FunctionCall getAGetCall() {
33+
result.getTarget().hasName("get") and
34+
result.getQualifier().getType().stripType() = this
35+
}
36+
3237
FunctionCall getAnInitializerExpr() {
3338
result =
3439
any(FunctionCall fc |
@@ -51,10 +56,25 @@ abstract class AutosarSmartPointer extends Class {
5156
AutosarSmartPointer
5257
)
5358
}
59+
60+
FunctionCall getAResetCall() {
61+
result.getTarget().hasName("reset") and
62+
result.getQualifier().getType().stripType() = this
63+
}
64+
65+
FunctionCall getAModifyingCall() {
66+
result.getTarget().hasName(["operator=", "reset", "swap"]) and
67+
result.getQualifier().getType().stripType() = this
68+
}
5469
}
5570

5671
class AutosarUniquePointer extends AutosarSmartPointer {
5772
AutosarUniquePointer() { this.hasQualifiedName("std", "unique_ptr") }
73+
74+
FunctionCall getAReleaseCall() {
75+
result.getTarget().hasName("release") and
76+
result.getQualifier().getType().stripType() = this
77+
}
5878
}
5979

6080
class AutosarSharedPointer extends AutosarSmartPointer {

cpp/common/src/codingstandards/cpp/rules/ownedpointervaluestoredinunrelatedsmartpointer/OwnedPointerValueStoredInUnrelatedSmartPointer.qll

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,34 @@ private class PointerToSmartPointerConstructorFlowConfig extends TaintTracking::
2929
cc.getArgument(0) = sink.asExpr()
3030
)
3131
}
32+
33+
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
34+
// Summarize flow through constructor calls
35+
exists(AutosarSmartPointer sp, ConstructorCall cc |
36+
sp.getAConstructorCall() = cc and
37+
cc = node2.asExpr() and
38+
cc.getArgument(0) = node1.asExpr()
39+
)
40+
or
41+
// Summarize flow through get() calls
42+
exists(AutosarSmartPointer sp, FunctionCall fc |
43+
sp.getAGetCall() = fc and
44+
fc = node2.asExpr() and
45+
fc.getQualifier() = node1.asExpr()
46+
)
47+
}
48+
49+
override predicate isSanitizerIn(DataFlow::Node node) {
50+
// Exclude flow into header files outside the source archive which are summarized by the
51+
// additional taint steps above.
52+
exists(AutosarSmartPointer sp |
53+
sp.getAConstructorCall().getTarget().getAParameter() = node.asParameter()
54+
or
55+
sp.getAGetCall().getTarget().getAParameter() = node.asParameter()
56+
|
57+
not exists(node.getLocation().getFile().getRelativePath())
58+
)
59+
}
3260
}
3361

3462
query predicate problems(

cpp/common/src/codingstandards/cpp/rules/preventdeadlockbylockinginpredefinedorder/PreventDeadlockByLockingInPredefinedOrder.qll

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@ predicate getAnOrderedLockPair(
2424
lock1 = node.coveredByLock() and
2525
lock2 = node.coveredByLock() and
2626
not lock1 = lock2 and
27-
lock1.getEnclosingFunction() = lock2.getEnclosingFunction() and
27+
exists(Function f |
28+
lock1.getEnclosingFunction() = f and
29+
lock2.getEnclosingFunction() = f and
30+
node.getBasicBlock().getEnclosingFunction() = f
31+
) and
2832
exists(Location l1Loc, Location l2Loc |
2933
l1Loc = lock1.getLocation() and
3034
l2Loc = lock2.getLocation()

cpp/common/src/codingstandards/cpp/standardlibrary/String.qll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ class StdBasicString extends ClassTemplateInstantiation {
4545
Type getConstIteratorType() {
4646
exists(TypedefType t |
4747
t.getDeclaringType() = this and
48-
t.getName() = "const_iterator" and
48+
// Certain compilers user __const_iterator instead of const_iterator.
49+
t.getName() = ["const_iterator", "__const_iterator"] and
4950
result = t
5051
)
5152
}

cpp/common/test/includes/standard-library/array

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#ifndef _GHLIBCPP_ARRAY
22
#define _GHLIBCPP_ARRAY
3-
#include "iterator.h"
4-
#include "string.h"
3+
#include <iterator>
4+
#include <string>
55

66
// Note: a few features currently unused by tests are commented out
77
namespace std {
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
int __errno;
2-
#define errno __errno
1+
#include <errno.h>

0 commit comments

Comments
 (0)