Skip to content

Commit 5deb900

Browse files
authored
Merge pull request github#16665 from geoffw0/yml
C++: Support for extension models (.yml)
2 parents 314eb5d + 8acb119 commit 5deb900

27 files changed

+595
-3
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* A partial model for the `Boost.Asio` network library has been added. This includes sources, sinks and summaries for certain functions in `Boost.Asio`, such as `read_until` and `write`.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: feature
3+
---
4+
* Data models can now be added with data extensions. In this way source, sink and summary models can be added in extension `.model.yml` files, rather than by writing classes in QL code. New models should be added in the `lib/ext` folder.

cpp/ql/lib/ext/Boost.Asio.model.yml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
extensions:
2+
# partial model of the Boost::Asio network library
3+
extensions:
4+
- addsTo:
5+
pack: codeql/cpp-all
6+
extensible: sourceModel
7+
data: # namespace, type, subtypes, name, signature, ext, output, kind, provenance
8+
- ["boost::asio", "", False, "read", "", "", "Argument[*1]", "remote", "manual"]
9+
- ["boost::asio", "", False, "read_at", "", "", "Argument[*2]", "remote", "manual"]
10+
- ["boost::asio", "", False, "read_until", "", "", "Argument[*1]", "remote", "manual"]
11+
- ["boost::asio", "", False, "async_read", "", "", "Argument[*1]", "remote", "manual"]
12+
- ["boost::asio", "", False, "async_read_at", "", "", "Argument[*2]", "remote", "manual"]
13+
- ["boost::asio", "", False, "async_read_until", "", "", "Argument[*1]", "remote", "manual"]
14+
- addsTo:
15+
pack: codeql/cpp-all
16+
extensible: sinkModel
17+
data: # namespace, type, subtypes, name, signature, ext, input, kind, provenance
18+
- ["boost::asio", "", False, "write", "", "", "Argument[*1]", "remote-sink", "manual"]
19+
- ["boost::asio", "", False, "write_at", "", "", "Argument[*2]", "remote-sink", "manual"]
20+
- ["boost::asio", "", False, "async_write", "", "", "Argument[*1]", "remote-sink", "manual"]
21+
- ["boost::asio", "", False, "async_write_at", "", "", "Argument[*2]", "remote-sink", "manual"]
22+
- addsTo:
23+
pack: codeql/cpp-all
24+
extensible: summaryModel
25+
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
26+
- ["boost::asio", "", False, "buffer", "", "", "Argument[*0]", "ReturnValue", "taint", "manual"]

cpp/ql/lib/ext/empty.model.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
extensions:
2+
# Make sure that the extensible model predicates have at least one definition
3+
# to avoid errors about undefined extensionals.
4+
- addsTo:
5+
pack: codeql/cpp-all
6+
extensible: sourceModel
7+
data: []
8+
- addsTo:
9+
pack: codeql/cpp-all
10+
extensible: sinkModel
11+
data: []
12+
- addsTo:
13+
pack: codeql/cpp-all
14+
extensible: summaryModel
15+
data: []

cpp/ql/lib/qlpack.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,6 @@ dependencies:
1414
codeql/tutorial: ${workspace}
1515
codeql/util: ${workspace}
1616
codeql/xml: ${workspace}
17+
dataExtensions:
18+
- ext/*.model.yml
1719
warnOnImplicitThis: true

cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ private import internal.FlowSummaryImpl
7878
private import internal.FlowSummaryImpl::Public
7979
private import internal.FlowSummaryImpl::Private
8080
private import internal.FlowSummaryImpl::Private::External
81+
private import internal.ExternalFlowExtensions as Extensions
8182
private import codeql.mad.ModelValidation as SharedModelVal
8283
private import codeql.util.Unit
8384

@@ -138,6 +139,9 @@ predicate sourceModel(
138139
row.splitAt(";", 7) = kind
139140
) and
140141
provenance = "manual"
142+
or
143+
Extensions::sourceModel(namespace, type, subtypes, name, signature, ext, output, kind, provenance,
144+
_)
141145
}
142146

143147
/** Holds if a sink model exists for the given parameters. */
@@ -158,6 +162,8 @@ predicate sinkModel(
158162
row.splitAt(";", 7) = kind
159163
) and
160164
provenance = "manual"
165+
or
166+
Extensions::sinkModel(namespace, type, subtypes, name, signature, ext, input, kind, provenance, _)
161167
}
162168

163169
/** Holds if a summary model exists for the given parameters. */
@@ -179,6 +185,9 @@ predicate summaryModel(
179185
row.splitAt(";", 8) = kind
180186
) and
181187
provenance = "manual"
188+
or
189+
Extensions::summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind,
190+
provenance, _)
182191
}
183192

184193
private predicate relevantNamespace(string namespace) {
@@ -323,10 +332,10 @@ module CsvValidation {
323332
or
324333
summaryModel(namespace, type, _, name, signature, ext, _, _, _, _) and pred = "summary"
325334
|
326-
not namespace.regexpMatch("[a-zA-Z0-9_\\.]+") and
335+
not namespace.regexpMatch("[a-zA-Z0-9_\\.:]*") and
327336
result = "Dubious namespace \"" + namespace + "\" in " + pred + " model."
328337
or
329-
not type.regexpMatch("[a-zA-Z0-9_<>,\\+]+") and
338+
not type.regexpMatch("[a-zA-Z0-9_<>,\\+]*") and
330339
result = "Dubious type \"" + type + "\" in " + pred + " model."
331340
or
332341
not name.regexpMatch("[a-zA-Z0-9_<>,]*") and
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* This module provides extensible predicates for defining MaD models.
3+
*/
4+
5+
/**
6+
* Holds if an external source model exists for the given parameters.
7+
*/
8+
extensible predicate sourceModel(
9+
string namespace, string type, boolean subtypes, string name, string signature, string ext,
10+
string output, string kind, string provenance, QlBuiltins::ExtensionId madId
11+
);
12+
13+
/**
14+
* Holds if an external sink model exists for the given parameters.
15+
*/
16+
extensible predicate sinkModel(
17+
string namespace, string type, boolean subtypes, string name, string signature, string ext,
18+
string input, string kind, string provenance, QlBuiltins::ExtensionId madId
19+
);
20+
21+
/**
22+
* Holds if an external summary model exists for the given parameters.
23+
*/
24+
extensible predicate summaryModel(
25+
string namespace, string type, boolean subtypes, string name, string signature, string ext,
26+
string input, string output, string kind, string provenance, QlBuiltins::ExtensionId madId
27+
);
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
2+
// --- stub library headers ---
3+
4+
namespace std {
5+
typedef unsigned long size_t;
6+
#define SIZE_MAX 0xFFFFFFFF
7+
8+
template <class T> class allocator {
9+
};
10+
11+
template<class charT> struct char_traits {
12+
};
13+
14+
template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> >
15+
class basic_string {
16+
public:
17+
basic_string(const charT* s, const Allocator& a = Allocator());
18+
};
19+
20+
typedef basic_string<char> string;
21+
};
22+
23+
namespace boost {
24+
namespace system {
25+
class error_code {
26+
public:
27+
operator bool() const;
28+
};
29+
};
30+
31+
namespace asio {
32+
template<typename Protocol/*, typename Executor*/>
33+
class basic_stream_socket /*: public basic_socket<Protocol, Executor>*/ {
34+
};
35+
36+
namespace ip {
37+
class tcp {
38+
public:
39+
typedef basic_stream_socket<tcp> socket;
40+
};
41+
};
42+
43+
template<typename Allocator = std::allocator<char>> class basic_streambuf {
44+
public:
45+
basic_streambuf(
46+
std::size_t maximum_size = SIZE_MAX,
47+
const Allocator &allocator = Allocator());
48+
};
49+
50+
typedef basic_streambuf<> streambuf;
51+
52+
class mutable_buffer {
53+
};
54+
55+
template<typename Elem, typename Traits, typename Allocator>
56+
mutable_buffer buffer(std::basic_string<Elem, Traits, Allocator> & data);
57+
58+
template<typename SyncReadStream, typename Allocator> std::size_t read_until(
59+
SyncReadStream &s,
60+
asio::basic_streambuf<Allocator> &b,
61+
char delim,
62+
boost::system::error_code &ec);
63+
64+
template<typename SyncWriteStream, typename ConstBufferSequence> std::size_t write(
65+
SyncWriteStream &s,
66+
const ConstBufferSequence &buffers,
67+
boost::system::error_code &ec,
68+
int constraint = 0); // simplified
69+
};
70+
};
71+
72+
// --- test code ---
73+
74+
char *source();
75+
void sink(char *);
76+
void sink(std::string);
77+
void sink(boost::asio::streambuf);
78+
void sink(boost::asio::mutable_buffer);
79+
80+
char *getenv(const char *name);
81+
int send(int, const void*, int, int);
82+
83+
void test(boost::asio::ip::tcp::socket &socket) {
84+
boost::asio::streambuf recv_buffer;
85+
boost::system::error_code error;
86+
87+
boost::asio::read_until(socket, recv_buffer, '\0', error);
88+
if (error) {
89+
// ...
90+
}
91+
sink(recv_buffer); // $ ir
92+
93+
boost::asio::write(socket, recv_buffer, error); // $ ir
94+
95+
// ---
96+
97+
std::string send_str = std::string(source());
98+
sink(send_str); // $ ir
99+
100+
boost::asio::mutable_buffer send_buffer = boost::asio::buffer(send_str);
101+
sink(send_buffer); // $ ir
102+
103+
boost::asio::write(socket, send_buffer, error); // $ ir
104+
if (error) {
105+
// ...
106+
}
107+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
testFailures
2+
failures
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
extensions:
2+
- addsTo:
3+
pack: codeql/cpp-all
4+
extensible: sourceModel
5+
data: # namespace, type, subtypes, name, signature, ext, output, kind, provenance
6+
- ["", "", False, "ymlSource", "", "", "ReturnValue", "local", "manual"]
7+
- addsTo:
8+
pack: codeql/cpp-all
9+
extensible: sinkModel
10+
data: # namespace, type, subtypes, name, signature, ext, input, kind, provenance
11+
- ["", "", False, "ymlSink", "", "", "Argument[0]", "test-sink", "manual"]
12+
- addsTo:
13+
pack: codeql/cpp-all
14+
extensible: summaryModel
15+
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
16+
- ["", "", False, "ymlStep", "", "", "Argument[0]", "ReturnValue", "taint", "manual"]

0 commit comments

Comments
 (0)