Skip to content

Commit 8701ce9

Browse files
committed
cpp: model BDE bdlbb::Blob byte-buffer taint flow
Add flow summaries for the BDE segmented byte buffer BloombergLP::bdlbb::Blob so taint reaches a blob's payload bytes: - Accessor chain: Blob::buffer taints the returned BlobBuffer, and BlobBuffer::data/buffer taint the bytes. - bdlbb::BlobUtil::copy and getContiguousRangeOrCopy propagate taint between a blob and a flat buffer in both directions. This unblocks blob-carried sources such as bmqa::Message::getData, whose payload was previously stranded on the opaque Blob object. Not a duplicate; the bdlbb namespace had no coverage. Verified with a BloombergLP::bdlbb-shaped stub in the dataflow external-models harness.
1 parent b756a08 commit 8701ce9

6 files changed

Lines changed: 183 additions & 2 deletions

File tree

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* Added flow summaries for the BDE `bdlbb::Blob` segmented byte buffer (`BloombergLP::bdlbb`). Taint now flows from a blob to its bytes through the `Blob::buffer`/`BlobBuffer::data` accessor chain and through the `bdlbb::BlobUtil::copy` and `getContiguousRangeOrCopy` helpers, so a blob populated from untrusted input (for example a BlazingMQ message body read via `bmqa::Message::getData`) is tracked into the payload bytes.

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Model of the BDE bdlbb::Blob segmented byte buffer (BloombergLP::bdlbb).
2+
# Lets taint reach a blob's payload bytes, e.g. a message body filled by bmqa::Message::getData.
3+
extensions:
4+
- addsTo:
5+
pack: codeql/cpp-all
6+
extensible: summaryModel
7+
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
8+
# Accessor chain: a tainted blob taints its buffers, and a tainted buffer taints its bytes.
9+
- ["BloombergLP::bdlbb", "Blob", true, "buffer", "", "", "Argument[-1]", "ReturnValue[*]", "taint", "manual"]
10+
- ["BloombergLP::bdlbb", "BlobBuffer", true, "data", "", "", "Argument[-1]", "ReturnValue[*]", "taint", "manual"]
11+
# BlobUtil read-out: the source blob (Argument[*1]) taints the destination buffer (and the
12+
# returned contiguous range).
13+
- ["BloombergLP::bdlbb", "BlobUtil", true, "copy", "(char *,const Blob &,int,int)", "", "Argument[*1]", "Argument[*0]", "taint", "manual"]
14+
- ["BloombergLP::bdlbb", "BlobUtil", true, "getContiguousRangeOrCopy", "", "", "Argument[*1]", "Argument[*0]", "taint", "manual"]
15+
- ["BloombergLP::bdlbb", "BlobUtil", true, "getContiguousRangeOrCopy", "", "", "Argument[*1]", "ReturnValue[*]", "taint", "manual"]
16+
# BlobUtil write-in: the source (Argument[*2]) taints the destination blob. `copy` has two
17+
# write-in overloads, one taking a raw byte buffer and one taking another blob as the source;
18+
# each row pins the exact signature so the int offset/length arguments are never tainted.
19+
- ["BloombergLP::bdlbb", "BlobUtil", true, "copy", "(Blob *,int,const char *,int)", "", "Argument[*2]", "Argument[*0]", "taint", "manual"]
20+
- ["BloombergLP::bdlbb", "BlobUtil", true, "copy", "(Blob *,int,const Blob &,int,int)", "", "Argument[*2]", "Argument[*0]", "taint", "manual"]
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
2+
// --- stub library headers ---
3+
4+
namespace bsl {
5+
typedef unsigned long size_t;
6+
template <class T> class allocator {};
7+
template<class charT> struct char_traits {};
8+
template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> >
9+
class basic_string {
10+
public:
11+
basic_string(const charT* s, const Allocator& a = Allocator());
12+
const charT* data() const;
13+
size_t size() const;
14+
};
15+
typedef basic_string<char> string;
16+
}
17+
18+
namespace BloombergLP {
19+
namespace bdlbb {
20+
class BlobBuffer {
21+
public:
22+
char *data() const;
23+
};
24+
25+
class Blob {
26+
public:
27+
const BlobBuffer &buffer(int index) const;
28+
};
29+
30+
struct BlobUtil {
31+
static void copy(char *dstBuffer, const Blob &srcBlob, int position, int length);
32+
static void copy(Blob *dstBlob, int dstOffset, const char *srcBuffer, int length);
33+
static void copy(Blob *dstBlob, int dstOffset, const Blob &srcBlob, int srcOffset,
34+
int length);
35+
static char *getContiguousRangeOrCopy(char *dstBuffer, const Blob &srcBlob, int position,
36+
int length, int alignment);
37+
};
38+
}
39+
}
40+
41+
// --- test code ---
42+
43+
char *source();
44+
void sink(char);
45+
46+
// A blob populated from a tainted buffer taints the bytes read back out of it.
47+
void test_BlobUtil_copy() {
48+
bsl::string s(source());
49+
BloombergLP::bdlbb::Blob blob;
50+
BloombergLP::bdlbb::BlobUtil::copy(&blob, 0, s.data(), s.size());
51+
char dst[16];
52+
BloombergLP::bdlbb::BlobUtil::copy(dst, blob, 0, 16);
53+
sink(*dst); // $ ir
54+
}
55+
56+
void test_accessor_chain() {
57+
bsl::string s(source());
58+
BloombergLP::bdlbb::Blob blob;
59+
BloombergLP::bdlbb::BlobUtil::copy(&blob, 0, s.data(), s.size());
60+
const char *p = blob.buffer(0).data();
61+
sink(*p); // $ ir
62+
}
63+
64+
void test_getContiguousRangeOrCopy() {
65+
bsl::string s(source());
66+
BloombergLP::bdlbb::Blob blob;
67+
BloombergLP::bdlbb::BlobUtil::copy(&blob, 0, s.data(), s.size());
68+
char dst[16];
69+
char *r = BloombergLP::bdlbb::BlobUtil::getContiguousRangeOrCopy(dst, blob, 0, 16, 1);
70+
sink(*r); // $ ir
71+
}
72+
73+
// A blob copied into another blob carries the taint across.
74+
void test_BlobUtil_copy_blob_to_blob() {
75+
bsl::string s(source());
76+
BloombergLP::bdlbb::Blob src;
77+
BloombergLP::bdlbb::BlobUtil::copy(&src, 0, s.data(), s.size());
78+
BloombergLP::bdlbb::Blob dst;
79+
BloombergLP::bdlbb::BlobUtil::copy(&dst, 0, src, 0, 16);
80+
char out[16];
81+
BloombergLP::bdlbb::BlobUtil::copy(out, dst, 0, 16);
82+
sink(*out); // $ ir
83+
}

cpp/ql/test/library-tests/dataflow/external-models/flow.expected

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,13 @@ models
9595
| 94 | Summary: Azure::Core::IO; BodyStream; true; ReadToCount; ; ; Argument[-1]; Argument[*0]; taint; manual |
9696
| 95 | Summary: Azure::Core::IO; BodyStream; true; ReadToEnd; ; ; Argument[-1]; ReturnValue.Element; taint; manual |
9797
| 96 | Summary: Azure; Nullable; true; Value; ; ; Argument[-1]; ReturnValue[*]; taint; manual |
98-
| 97 | Summary: boost::asio; ; false; buffer; ; ; Argument[*0]; ReturnValue; taint; manual |
98+
| 97 | Summary: BloombergLP::bdlbb; Blob; true; buffer; ; ; Argument[-1]; ReturnValue[*]; taint; manual |
99+
| 98 | Summary: BloombergLP::bdlbb; BlobBuffer; true; data; ; ; Argument[-1]; ReturnValue[*]; taint; manual |
100+
| 99 | Summary: BloombergLP::bdlbb; BlobUtil; true; copy; (Blob *,int,const Blob &,int,int); ; Argument[*2]; Argument[*0]; taint; manual |
101+
| 100 | Summary: BloombergLP::bdlbb; BlobUtil; true; copy; (Blob *,int,const char *,int); ; Argument[*2]; Argument[*0]; taint; manual |
102+
| 101 | Summary: BloombergLP::bdlbb; BlobUtil; true; copy; (char *,const Blob &,int,int); ; Argument[*1]; Argument[*0]; taint; manual |
103+
| 102 | Summary: BloombergLP::bdlbb; BlobUtil; true; getContiguousRangeOrCopy; ; ; Argument[*1]; ReturnValue[*]; taint; manual |
104+
| 103 | Summary: boost::asio; ; false; buffer; ; ; Argument[*0]; ReturnValue; taint; manual |
99105
edges
100106
| asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:91:7:91:17 | recv_buffer | provenance | Src:MaD:56 |
101107
| asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:93:29:93:39 | recv_buffer | provenance | Src:MaD:56 Sink:MaD:4 |
@@ -104,7 +110,7 @@ edges
104110
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | |
105111
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:101:7:101:17 | send_buffer | provenance | |
106112
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:103:29:103:39 | send_buffer | provenance | Sink:MaD:4 |
107-
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:97 |
113+
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:103 |
108114
| azure.cpp:253:48:253:60 | *call to GetBodyStream | azure.cpp:257:5:257:8 | *resp | provenance | |
109115
| azure.cpp:253:48:253:60 | *call to GetBodyStream | azure.cpp:262:5:262:8 | *resp | provenance | |
110116
| azure.cpp:253:48:253:60 | *call to GetBodyStream | azure.cpp:266:38:266:41 | *resp | provenance | |
@@ -144,6 +150,31 @@ edges
144150
| azure.cpp:294:38:294:53 | call to operator[] | azure.cpp:295:10:295:20 | contentType | provenance | |
145151
| azure.cpp:294:38:294:53 | call to operator[] | azure.cpp:295:10:295:20 | contentType | provenance | |
146152
| azure.cpp:295:10:295:20 | contentType | azure.cpp:295:10:295:20 | contentType | provenance | |
153+
| bdlbb.cpp:48:16:48:23 | call to source | bdlbb.cpp:50:49:50:52 | *call to data | provenance | TaintFunction |
154+
| bdlbb.cpp:50:37:50:41 | copy output argument | bdlbb.cpp:52:42:52:45 | *blob | provenance | |
155+
| bdlbb.cpp:50:49:50:52 | *call to data | bdlbb.cpp:50:37:50:41 | copy output argument | provenance | MaD:100 |
156+
| bdlbb.cpp:52:37:52:39 | copy output argument | bdlbb.cpp:53:7:53:10 | * ... | provenance | |
157+
| bdlbb.cpp:52:42:52:45 | *blob | bdlbb.cpp:52:37:52:39 | copy output argument | provenance | MaD:101 |
158+
| bdlbb.cpp:57:16:57:23 | call to source | bdlbb.cpp:59:49:59:52 | *call to data | provenance | TaintFunction |
159+
| bdlbb.cpp:59:37:59:41 | copy output argument | bdlbb.cpp:60:18:60:21 | *blob | provenance | |
160+
| bdlbb.cpp:59:49:59:52 | *call to data | bdlbb.cpp:59:37:59:41 | copy output argument | provenance | MaD:100 |
161+
| bdlbb.cpp:60:18:60:21 | *blob | bdlbb.cpp:60:29:60:32 | *call to buffer | provenance | MaD:97 |
162+
| bdlbb.cpp:60:18:60:38 | *call to data | bdlbb.cpp:60:18:60:38 | *call to data | provenance | |
163+
| bdlbb.cpp:60:18:60:38 | *call to data | bdlbb.cpp:61:7:61:8 | * ... | provenance | |
164+
| bdlbb.cpp:60:29:60:32 | *call to buffer | bdlbb.cpp:60:18:60:38 | *call to data | provenance | MaD:98 |
165+
| bdlbb.cpp:65:16:65:23 | call to source | bdlbb.cpp:67:49:67:52 | *call to data | provenance | TaintFunction |
166+
| bdlbb.cpp:67:37:67:41 | copy output argument | bdlbb.cpp:69:72:69:75 | *blob | provenance | |
167+
| bdlbb.cpp:67:49:67:52 | *call to data | bdlbb.cpp:67:37:67:41 | copy output argument | provenance | MaD:100 |
168+
| bdlbb.cpp:69:12:69:65 | *call to getContiguousRangeOrCopy | bdlbb.cpp:69:12:69:65 | *call to getContiguousRangeOrCopy | provenance | |
169+
| bdlbb.cpp:69:12:69:65 | *call to getContiguousRangeOrCopy | bdlbb.cpp:70:7:70:8 | * ... | provenance | |
170+
| bdlbb.cpp:69:72:69:75 | *blob | bdlbb.cpp:69:12:69:65 | *call to getContiguousRangeOrCopy | provenance | MaD:102 |
171+
| bdlbb.cpp:75:16:75:23 | call to source | bdlbb.cpp:77:48:77:51 | *call to data | provenance | TaintFunction |
172+
| bdlbb.cpp:77:37:77:40 | copy output argument | bdlbb.cpp:79:46:79:48 | *src | provenance | |
173+
| bdlbb.cpp:77:48:77:51 | *call to data | bdlbb.cpp:77:37:77:40 | copy output argument | provenance | MaD:100 |
174+
| bdlbb.cpp:79:37:79:40 | copy output argument | bdlbb.cpp:81:42:81:44 | *dst | provenance | |
175+
| bdlbb.cpp:79:46:79:48 | *src | bdlbb.cpp:79:37:79:40 | copy output argument | provenance | MaD:99 |
176+
| bdlbb.cpp:81:37:81:39 | copy output argument | bdlbb.cpp:82:7:82:10 | * ... | provenance | |
177+
| bdlbb.cpp:81:42:81:44 | *dst | bdlbb.cpp:81:37:81:39 | copy output argument | provenance | MaD:101 |
147178
| test.cpp:7:47:7:52 | value2 | test.cpp:7:64:7:69 | value2 | provenance | |
148179
| test.cpp:7:64:7:69 | value2 | test.cpp:7:5:7:30 | *ymlStepGenerated_with_body | provenance | |
149180
| test.cpp:10:10:10:18 | call to ymlSource | test.cpp:10:10:10:18 | call to ymlSource | provenance | Src:MaD:48 |
@@ -532,6 +563,35 @@ nodes
532563
| azure.cpp:295:10:295:20 | contentType | semmle.label | contentType |
533564
| azure.cpp:295:10:295:20 | contentType | semmle.label | contentType |
534565
| azure.cpp:295:10:295:20 | contentType | semmle.label | contentType |
566+
| bdlbb.cpp:48:16:48:23 | call to source | semmle.label | call to source |
567+
| bdlbb.cpp:50:37:50:41 | copy output argument | semmle.label | copy output argument |
568+
| bdlbb.cpp:50:49:50:52 | *call to data | semmle.label | *call to data |
569+
| bdlbb.cpp:52:37:52:39 | copy output argument | semmle.label | copy output argument |
570+
| bdlbb.cpp:52:42:52:45 | *blob | semmle.label | *blob |
571+
| bdlbb.cpp:53:7:53:10 | * ... | semmle.label | * ... |
572+
| bdlbb.cpp:57:16:57:23 | call to source | semmle.label | call to source |
573+
| bdlbb.cpp:59:37:59:41 | copy output argument | semmle.label | copy output argument |
574+
| bdlbb.cpp:59:49:59:52 | *call to data | semmle.label | *call to data |
575+
| bdlbb.cpp:60:18:60:21 | *blob | semmle.label | *blob |
576+
| bdlbb.cpp:60:18:60:38 | *call to data | semmle.label | *call to data |
577+
| bdlbb.cpp:60:18:60:38 | *call to data | semmle.label | *call to data |
578+
| bdlbb.cpp:60:29:60:32 | *call to buffer | semmle.label | *call to buffer |
579+
| bdlbb.cpp:61:7:61:8 | * ... | semmle.label | * ... |
580+
| bdlbb.cpp:65:16:65:23 | call to source | semmle.label | call to source |
581+
| bdlbb.cpp:67:37:67:41 | copy output argument | semmle.label | copy output argument |
582+
| bdlbb.cpp:67:49:67:52 | *call to data | semmle.label | *call to data |
583+
| bdlbb.cpp:69:12:69:65 | *call to getContiguousRangeOrCopy | semmle.label | *call to getContiguousRangeOrCopy |
584+
| bdlbb.cpp:69:12:69:65 | *call to getContiguousRangeOrCopy | semmle.label | *call to getContiguousRangeOrCopy |
585+
| bdlbb.cpp:69:72:69:75 | *blob | semmle.label | *blob |
586+
| bdlbb.cpp:70:7:70:8 | * ... | semmle.label | * ... |
587+
| bdlbb.cpp:75:16:75:23 | call to source | semmle.label | call to source |
588+
| bdlbb.cpp:77:37:77:40 | copy output argument | semmle.label | copy output argument |
589+
| bdlbb.cpp:77:48:77:51 | *call to data | semmle.label | *call to data |
590+
| bdlbb.cpp:79:37:79:40 | copy output argument | semmle.label | copy output argument |
591+
| bdlbb.cpp:79:46:79:48 | *src | semmle.label | *src |
592+
| bdlbb.cpp:81:37:81:39 | copy output argument | semmle.label | copy output argument |
593+
| bdlbb.cpp:81:42:81:44 | *dst | semmle.label | *dst |
594+
| bdlbb.cpp:82:7:82:10 | * ... | semmle.label | * ... |
535595
| test.cpp:7:5:7:30 | *ymlStepGenerated_with_body | semmle.label | *ymlStepGenerated_with_body |
536596
| test.cpp:7:47:7:52 | value2 | semmle.label | value2 |
537597
| test.cpp:7:64:7:69 | value2 | semmle.label | value2 |

cpp/ql/test/library-tests/dataflow/external-models/steps.expected

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,17 @@
44
| azure.cpp:262:5:262:8 | *resp | azure.cpp:262:23:262:28 | ReadToCount output argument |
55
| azure.cpp:287:79:287:98 | call to string | azure.cpp:287:62:287:99 | call to Url |
66
| azure.cpp:289:24:289:56 | call to GetHeader | azure.cpp:289:63:289:65 | call to Value |
7+
| bdlbb.cpp:50:49:50:52 | *call to data | bdlbb.cpp:50:37:50:41 | copy output argument |
8+
| bdlbb.cpp:52:42:52:45 | *blob | bdlbb.cpp:52:37:52:39 | copy output argument |
9+
| bdlbb.cpp:59:49:59:52 | *call to data | bdlbb.cpp:59:37:59:41 | copy output argument |
10+
| bdlbb.cpp:60:18:60:21 | *blob | bdlbb.cpp:60:29:60:32 | *call to buffer |
11+
| bdlbb.cpp:60:29:60:32 | *call to buffer | bdlbb.cpp:60:18:60:38 | *call to data |
12+
| bdlbb.cpp:67:49:67:52 | *call to data | bdlbb.cpp:67:37:67:41 | copy output argument |
13+
| bdlbb.cpp:69:72:69:75 | *blob | bdlbb.cpp:69:12:69:65 | *call to getContiguousRangeOrCopy |
14+
| bdlbb.cpp:69:72:69:75 | *blob | bdlbb.cpp:69:67:69:69 | getContiguousRangeOrCopy output argument |
15+
| bdlbb.cpp:77:48:77:51 | *call to data | bdlbb.cpp:77:37:77:40 | copy output argument |
16+
| bdlbb.cpp:79:46:79:48 | *src | bdlbb.cpp:79:37:79:40 | copy output argument |
17+
| bdlbb.cpp:81:42:81:44 | *dst | bdlbb.cpp:81:37:81:39 | copy output argument |
718
| test.cpp:17:24:17:24 | x | test.cpp:17:10:17:22 | call to ymlStepManual |
819
| test.cpp:21:27:21:27 | x | test.cpp:21:10:21:25 | call to ymlStepGenerated |
920
| test.cpp:25:35:25:35 | x | test.cpp:25:11:25:33 | call to ymlStepManual_with_body |

cpp/ql/test/library-tests/dataflow/external-models/validatemodels.expected

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,8 @@
370370
| Dubious signature "(BN_MONT_CTX *,const BIGNUM *,int,const unsigned char *,size_t,uint32_t,uint32_t)" in summary model. |
371371
| Dubious signature "(BN_RECP_CTX *,const BIGNUM *,BN_CTX *)" in summary model. |
372372
| Dubious signature "(BUF_MEM *,size_t)" in summary model. |
373+
| Dubious signature "(Blob *,int,const Blob &,int,int)" in summary model. |
374+
| Dubious signature "(Blob *,int,const char *,int)" in summary model. |
373375
| Dubious signature "(BrotliBitReader *const,uint64_t,uint64_t *)" in summary model. |
374376
| Dubious signature "(BrotliDecoderState *,BrotliDecoderStateInternal *,BrotliSharedDictionaryType,size_t,const uint8_t[])" in summary model. |
375377
| Dubious signature "(BrotliDecoderState *,BrotliDecoderStateInternal *,brotli_decoder_metadata_start_func,brotli_decoder_metadata_chunk_func,void *)" in summary model. |
@@ -2948,6 +2950,7 @@
29482950
| Dubious signature "(char *,char *__restrict__,int,FILE *,FILE *__restrict__)" in summary model. |
29492951
| Dubious signature "(char *,char *__restrict__,size_t,const char *,const char *__restrict__,const tm *,const tm *__restrict__,locale_t)" in summary model. |
29502952
| Dubious signature "(char *,char,char **)" in summary model. |
2953+
| Dubious signature "(char *,const Blob &,int,int)" in summary model. |
29512954
| Dubious signature "(char *,const char *)" in summary model. |
29522955
| Dubious signature "(char *,const char **,const char **,const char **,const char **,const char **)" in summary model. |
29532956
| Dubious signature "(char *,const char *,char **)" in summary model. |

0 commit comments

Comments
 (0)