Skip to content

Commit 51c27de

Browse files
committed
Merge branch 'main' into revert-import-change
2 parents 92e0e19 + b9788eb commit 51c27de

File tree

91 files changed

+933
-1350
lines changed

Some content is hidden

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

91 files changed

+933
-1350
lines changed
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
2+
namespace std {
3+
namespace detail {
4+
template<typename T>
5+
class compressed_pair_element {
6+
T element;
7+
8+
public:
9+
compressed_pair_element() = default;
10+
compressed_pair_element(const T& t) : element(t) {}
11+
12+
T& get() { return element; }
13+
14+
const T& get() const { return element; }
15+
};
16+
17+
template<typename T, typename U>
18+
struct compressed_pair : private compressed_pair_element<T>, private compressed_pair_element<U> {
19+
compressed_pair() = default;
20+
compressed_pair(T& t) : compressed_pair_element<T>(t), compressed_pair_element<U>() {}
21+
compressed_pair(const compressed_pair&) = delete;
22+
compressed_pair(compressed_pair<T, U>&&) noexcept = default;
23+
24+
T& first() { return static_cast<compressed_pair_element<T>&>(*this).get(); }
25+
U& second() { return static_cast<compressed_pair_element<U>&>(*this).get(); }
26+
27+
const T& first() const { return static_cast<const compressed_pair_element<T>&>(*this).get(); }
28+
const U& second() const { return static_cast<const compressed_pair_element<U>&>(*this).get(); }
29+
};
30+
}
31+
32+
template<class T>
33+
struct default_delete {
34+
void operator()(T* ptr) const { delete ptr; }
35+
};
36+
37+
template<class T>
38+
struct default_delete<T[]> {
39+
template<class U>
40+
void operator()(U* ptr) const { delete[] ptr; }
41+
};
42+
43+
template<class T, class Deleter = default_delete<T> >
44+
class unique_ptr {
45+
private:
46+
detail::compressed_pair<T*, Deleter> data;
47+
public:
48+
constexpr unique_ptr() noexcept {}
49+
explicit unique_ptr(T* ptr) noexcept : data(ptr) {}
50+
unique_ptr(const unique_ptr& ptr) = delete;
51+
unique_ptr(unique_ptr&& ptr) noexcept = default;
52+
53+
unique_ptr& operator=(unique_ptr&& ptr) noexcept = default;
54+
55+
T& operator*() const { return *get(); }
56+
T* operator->() const noexcept { return get(); }
57+
58+
T* get() const noexcept { return data.first(); }
59+
60+
~unique_ptr() {
61+
Deleter& d = data.second();
62+
d(data.first());
63+
}
64+
};
65+
66+
template<typename T, class... Args> unique_ptr<T> make_unique(Args&&... args) {
67+
return unique_ptr<T>(new T(args...)); // std::forward calls elided for simplicity.
68+
}
69+
70+
class ctrl_block {
71+
unsigned uses;
72+
73+
public:
74+
ctrl_block() : uses(1) {}
75+
76+
void inc() { ++uses; }
77+
bool dec() { return --uses == 0; }
78+
79+
virtual void destroy() = 0;
80+
virtual ~ctrl_block() {}
81+
};
82+
83+
template<typename T, class Deleter = default_delete<T> >
84+
struct ctrl_block_impl: public ctrl_block {
85+
T* ptr;
86+
Deleter d;
87+
88+
ctrl_block_impl(T* ptr, Deleter d) : ptr(ptr), d(d) {}
89+
virtual void destroy() override { d(ptr); }
90+
};
91+
92+
template<class T>
93+
class shared_ptr {
94+
private:
95+
ctrl_block* ctrl;
96+
T* ptr;
97+
98+
void dec() {
99+
if(ctrl->dec()) {
100+
ctrl->destroy();
101+
delete ctrl;
102+
}
103+
}
104+
105+
void inc() {
106+
ctrl->inc();
107+
}
108+
109+
public:
110+
constexpr shared_ptr() noexcept = default;
111+
shared_ptr(T* ptr) : ctrl(new ctrl_block_impl<T>(ptr, default_delete<T>())) {}
112+
shared_ptr(const shared_ptr& s) noexcept : ptr(s.ptr), ctrl(s.ctrl) {
113+
inc();
114+
}
115+
shared_ptr(shared_ptr&& s) noexcept = default;
116+
117+
T* operator->() const { return ptr; }
118+
119+
T& operator*() const { return *ptr; }
120+
121+
~shared_ptr() { dec(); }
122+
};
123+
124+
template<typename T, class... Args> shared_ptr<T> make_shared(Args&&... args) {
125+
return shared_ptr<T>(new T(args...)); // std::forward calls elided for simplicity.
126+
}
127+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import TestUtilities.dataflow.FlowTestCommon
2+
3+
module ASTTest {
4+
private import semmle.code.cpp.dataflow.TaintTracking
5+
6+
class ASTSmartPointerTaintConfig extends TaintTracking::Configuration {
7+
ASTSmartPointerTaintConfig() { this = "ASTSmartPointerTaintConfig" }
8+
9+
override predicate isSource(DataFlow::Node source) {
10+
source.asExpr().(FunctionCall).getTarget().getName() = "source"
11+
}
12+
13+
override predicate isSink(DataFlow::Node sink) {
14+
exists(FunctionCall call |
15+
call.getTarget().getName() = "sink" and
16+
sink.asExpr() = call.getAnArgument()
17+
)
18+
}
19+
}
20+
}
21+
22+
module IRTest {
23+
private import semmle.code.cpp.ir.dataflow.TaintTracking
24+
25+
class IRSmartPointerTaintConfig extends TaintTracking::Configuration {
26+
IRSmartPointerTaintConfig() { this = "IRSmartPointerTaintConfig" }
27+
28+
override predicate isSource(DataFlow::Node source) {
29+
source.asExpr().(FunctionCall).getTarget().getName() = "source"
30+
}
31+
32+
override predicate isSink(DataFlow::Node sink) {
33+
exists(FunctionCall call |
34+
call.getTarget().getName() = "sink" and
35+
sink.asExpr() = call.getAnArgument()
36+
)
37+
}
38+
}
39+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#include "memory.h"
2+
3+
int source();
4+
void sink(int);
5+
6+
void test_unique_ptr_int() {
7+
std::unique_ptr<int> p1(new int(source()));
8+
std::unique_ptr<int> p2 = std::make_unique<int>(source());
9+
10+
sink(*p1); // $ MISSING: ast,ir
11+
sink(*p2); // $ ast ir=8:50
12+
}
13+
14+
struct A {
15+
int x, y;
16+
17+
A(int x, int y) : x(x), y(y) {}
18+
};
19+
20+
void test_unique_ptr_struct() {
21+
std::unique_ptr<A> p1(new A{source(), 0});
22+
std::unique_ptr<A> p2 = std::make_unique<A>(source(), 0);
23+
24+
sink(p1->x); // $ MISSING: ast,ir
25+
sink(p1->y);
26+
sink(p2->x); // $ MISSING: ast,ir
27+
sink(p2->y);
28+
}
29+
30+
void test_shared_ptr_int() {
31+
std::shared_ptr<int> p1(new int(source()));
32+
std::shared_ptr<int> p2 = std::make_shared<int>(source());
33+
34+
sink(*p1); // $ ast
35+
sink(*p2); // $ ast ir=32:50
36+
}
37+
38+
void test_shared_ptr_struct() {
39+
std::shared_ptr<A> p1(new A{source(), 0});
40+
std::shared_ptr<A> p2 = std::make_shared<A>(source(), 0);
41+
42+
sink(p1->x); // $ MISSING: ast,ir
43+
sink(p1->y);
44+
sink(p2->x); // $ MISSING: ast,ir
45+
sink(p2->y);
46+
}

cpp/ql/test/query-tests/Critical/MemoryFreed/MemoryNeverFreed.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@
1010
| test.cpp:89:18:89:23 | call to malloc | This memory is never freed |
1111
| test.cpp:156:3:156:26 | new | This memory is never freed |
1212
| test.cpp:157:3:157:26 | new[] | This memory is never freed |
13+
| test.cpp:167:14:167:19 | call to strdup | This memory is never freed |

cpp/ql/test/query-tests/Critical/MemoryFreed/test.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,3 +156,15 @@ int overloadedNew() {
156156
new(std::nothrow) int(3); // BAD
157157
new(std::nothrow) int[2]; // BAD
158158
}
159+
160+
// --- strdup ---
161+
162+
char *strdup(const char *s1);
163+
void output_msg(const char *msg);
164+
165+
void test_strdup() {
166+
char msg[] = "OctoCat";
167+
char *cpy = strdup(msg); // BAD
168+
169+
output_msg(cpy);
170+
}

cpp/ql/test/query-tests/Security/CWE/CWE-764/semmle/tests/UnreleasedLock.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@
77
| test.cpp:303:11:303:18 | call to try_lock | This lock might not be unlocked or might be locked more times than it is unlocked. |
88
| test.cpp:313:11:313:18 | call to try_lock | This lock might not be unlocked or might be locked more times than it is unlocked. |
99
| test.cpp:442:8:442:17 | call to mutex_lock | This lock might not be unlocked or might be locked more times than it is unlocked. |
10+
| test.cpp:482:2:482:19 | call to pthread_mutex_lock | This lock might not be unlocked or might be locked more times than it is unlocked. |

cpp/ql/test/query-tests/Security/CWE/CWE-764/semmle/tests/test.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,3 +445,46 @@ bool test_mutex(data_t *data)
445445

446446
return true;
447447
}
448+
449+
// ---
450+
451+
struct pthread_mutex
452+
{
453+
// ...
454+
};
455+
456+
void pthread_mutex_lock(pthread_mutex *m);
457+
void pthread_mutex_unlock(pthread_mutex *m);
458+
459+
class MyClass
460+
{
461+
public:
462+
pthread_mutex lock;
463+
};
464+
465+
bool maybe();
466+
467+
int test_MyClass_good(MyClass *obj)
468+
{
469+
pthread_mutex_lock(&obj->lock);
470+
471+
if (maybe()) {
472+
pthread_mutex_unlock(&obj->lock);
473+
return -1; // GOOD
474+
}
475+
476+
pthread_mutex_unlock(&obj->lock); // GOOD
477+
return 0;
478+
}
479+
480+
int test_MyClass_bad(MyClass *obj)
481+
{
482+
pthread_mutex_lock(&obj->lock);
483+
484+
if (maybe()) {
485+
return -1; // BAD
486+
}
487+
488+
pthread_mutex_unlock(&obj->lock); // GOOD
489+
return 0;
490+
}

cpp/ql/test/query-tests/jsf/4.10 Classes/AV Rule 79/AV Rule 79.expected

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@
1818
| NoDestructor.cpp:23:3:23:20 | ... = ... | Resource n is acquired by class MyClass5 but not released anywhere in this class. |
1919
| PlacementNew.cpp:36:3:36:36 | ... = ... | Resource p1 is acquired by class MyTestForPlacementNew but not released anywhere in this class. |
2020
| SelfRegistering.cpp:25:3:25:24 | ... = ... | Resource side is acquired by class MyOwner but not released anywhere in this class. |
21-
| Variants.cpp:25:3:25:13 | ... = ... | Resource f is acquired by class MyClass4 but not released anywhere in this class. |
22-
| Variants.cpp:65:3:65:17 | ... = ... | Resource a is acquired by class MyClass6 but not released anywhere in this class. |
23-
| Variants.cpp:66:3:66:36 | ... = ... | Resource b is acquired by class MyClass6 but not released anywhere in this class. |
24-
| Variants.cpp:67:3:67:41 | ... = ... | Resource c is acquired by class MyClass6 but not released anywhere in this class. |
21+
| Variants.cpp:26:3:26:13 | ... = ... | Resource f is acquired by class MyClass4 but not released anywhere in this class. |
22+
| Variants.cpp:69:3:69:17 | ... = ... | Resource a is acquired by class MyClass6 but not released anywhere in this class. |
23+
| Variants.cpp:70:3:70:36 | ... = ... | Resource b is acquired by class MyClass6 but not released anywhere in this class. |
24+
| Variants.cpp:71:3:71:41 | ... = ... | Resource c is acquired by class MyClass6 but not released anywhere in this class. |
25+
| Variants.cpp:72:3:72:22 | ... = ... | Resource d is acquired by class MyClass6 but not released anywhere in this class. |
2526
| Wrapped.cpp:46:3:46:22 | ... = ... | Resource ptr2 is acquired by class Wrapped2 but not released anywhere in this class. |
2627
| Wrapped.cpp:59:3:59:22 | ... = ... | Resource ptr4 is acquired by class Wrapped2 but not released anywhere in this class. |

cpp/ql/test/query-tests/jsf/4.10 Classes/AV Rule 79/Variants.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ void *malloc(size_t size);
55
void *calloc(size_t nmemb, size_t size);
66
void *realloc(void *ptr, size_t size);
77
void free(void* ptr);
8+
char *strdup(const char *s1);
89

910
int *ID(int *x)
1011
{
@@ -45,16 +46,19 @@ class MyClass5
4546
a = new int[10]; // GOOD
4647
b = (int *)calloc(10, sizeof(int)); // GOOD
4748
c = (int *)realloc(0, 10 * sizeof(int)); // GOOD
49+
d = strdup("string");
4850
}
4951

5052
~MyClass5()
5153
{
5254
delete [] a;
5355
free(b);
5456
free(c);
57+
free(d);
5558
}
5659

5760
int *a, *b, *c;
61+
char *d;
5862
};
5963

6064
class MyClass6
@@ -65,13 +69,15 @@ class MyClass6
6569
a = new int[10]; // BAD
6670
b = (int *)calloc(10, sizeof(int)); // BAD
6771
c = (int *)realloc(0, 10 * sizeof(int)); // BAD
72+
d = strdup("string"); // BAD
6873
}
6974

7075
~MyClass6()
7176
{
7277
}
7378

7479
int *a, *b, *c;
80+
char *d;
7581
};
7682

7783
class MyClass7

0 commit comments

Comments
 (0)