Skip to content

Commit 57c92ea

Browse files
committed
C++: Model BDE Base64 and hex pointer-buffer conversions
1 parent b9cb90c commit 57c92ea

7 files changed

Lines changed: 233 additions & 0 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 taint-flow models for direct pointer-buffer conversions using `BloombergLP::bdlde::Base64Encoder`, `Base64Decoder`, `HexEncoder`, and `HexDecoder`.

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Direct pointer-buffer conversion models for the public BDE bdlde API.
2+
# https://github.com/bloomberg/bde/tree/ec310b87e008199ecbdbc00a0b0264a53d806a0a/groups/bdl/bdlde
3+
# These summaries do not model retained data across calls or class-based iterators.
4+
extensions:
5+
- addsTo:
6+
pack: codeql/cpp-all
7+
extensible: summaryModel
8+
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
9+
# Only begin supplies input bytes. end is exclusive; numOut/numIn are outputs.
10+
# The longer overload has six parameters, including the defaulted maxNumOut.
11+
- ["BloombergLP::bdlde", "Base64Encoder", False, "convert<OUT,IN>", "(OUT,IN,IN)", "", "Argument[*1]", "Argument[*0]", "taint", "manual"]
12+
- ["BloombergLP::bdlde", "Base64Encoder", False, "convert<OUT,IN>", "(OUT,int *,int *,IN,IN,int)", "", "Argument[*3]", "Argument[*0]", "taint", "manual"]
13+
- ["BloombergLP::bdlde", "Base64Decoder", False, "convert<OUT,IN>", "(OUT,IN,IN)", "", "Argument[*1]", "Argument[*0]", "taint", "manual"]
14+
- ["BloombergLP::bdlde", "Base64Decoder", False, "convert<OUT,IN>", "(OUT,int *,int *,IN,IN,int)", "", "Argument[*3]", "Argument[*0]", "taint", "manual"]
15+
- ["BloombergLP::bdlde", "HexEncoder", False, "convert<OUT,IN>", "(OUT,IN,IN)", "", "Argument[*1]", "Argument[*0]", "taint", "manual"]
16+
- ["BloombergLP::bdlde", "HexEncoder", False, "convert<OUT,IN>", "(OUT,int *,int *,IN,IN,int)", "", "Argument[*3]", "Argument[*0]", "taint", "manual"]
17+
- ["BloombergLP::bdlde", "HexDecoder", False, "convert<OUT,IN>", "(OUT,IN,IN)", "", "Argument[*1]", "Argument[*0]", "taint", "manual"]
18+
- ["BloombergLP::bdlde", "HexDecoder", False, "convert<OUT,IN>", "(OUT,int *,int *,IN,IN,int)", "", "Argument[*3]", "Argument[*0]", "taint", "manual"]
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Minimal public declarations, with implementation bodies omitted to test the models.
2+
// https://github.com/bloomberg/bde/tree/ec310b87e008199ecbdbc00a0b0264a53d806a0a/groups/bdl/bdlde
3+
namespace BloombergLP {
4+
namespace bdlde {
5+
class Base64Encoder {
6+
public:
7+
template <class OUTPUT_ITERATOR, class INPUT_ITERATOR>
8+
int convert(OUTPUT_ITERATOR out, INPUT_ITERATOR begin, INPUT_ITERATOR end);
9+
template <class OUTPUT_ITERATOR, class INPUT_ITERATOR>
10+
int convert(OUTPUT_ITERATOR out, int *numOut, int *numIn,
11+
INPUT_ITERATOR begin, INPUT_ITERATOR end, int maxNumOut = -1);
12+
};
13+
class Base64Decoder {
14+
public:
15+
template <class OUTPUT_ITERATOR, class INPUT_ITERATOR>
16+
int convert(OUTPUT_ITERATOR out, INPUT_ITERATOR begin, INPUT_ITERATOR end);
17+
template <class OUTPUT_ITERATOR, class INPUT_ITERATOR>
18+
int convert(OUTPUT_ITERATOR out, int *numOut, int *numIn,
19+
INPUT_ITERATOR begin, INPUT_ITERATOR end, int maxNumOut = -1);
20+
};
21+
class HexEncoder {
22+
public:
23+
template <class OUTPUT_ITERATOR, class INPUT_ITERATOR>
24+
int convert(OUTPUT_ITERATOR out, INPUT_ITERATOR begin, INPUT_ITERATOR end);
25+
template <class OUTPUT_ITERATOR, class INPUT_ITERATOR>
26+
int convert(OUTPUT_ITERATOR out, int *numOut, int *numIn,
27+
INPUT_ITERATOR begin, INPUT_ITERATOR end, int maxNumOut = -1);
28+
};
29+
class HexDecoder {
30+
public:
31+
template <class OUTPUT_ITERATOR, class INPUT_ITERATOR>
32+
int convert(OUTPUT_ITERATOR out, INPUT_ITERATOR begin, INPUT_ITERATOR end);
33+
template <class OUTPUT_ITERATOR, class INPUT_ITERATOR>
34+
int convert(OUTPUT_ITERATOR out, int *numOut, int *numIn,
35+
INPUT_ITERATOR begin, INPUT_ITERATOR end, int maxNumOut = -1);
36+
};
37+
}
38+
}

cpp/ql/test/library-tests/dataflow/bdlde/flow.expected

Whitespace-only changes.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import cpp
2+
import utils.test.dataflow.FlowTestCommon
3+
import semmle.code.cpp.ir.dataflow.TaintTracking
4+
5+
module Config implements DataFlow::ConfigSig {
6+
predicate isSource(DataFlow::Node node) {
7+
node.asExpr().(FunctionCall).getTarget().hasName("source")
8+
}
9+
10+
predicate isSink(DataFlow::Node node) {
11+
exists(FunctionCall call |
12+
call.getTarget().hasName("sink") and node.asExpr() = call.getArgument(0)
13+
)
14+
}
15+
}
16+
17+
module Flow = TaintTracking::Global<Config>;
18+
19+
import MakeTest<IRFlowTest<Flow>>
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
#include "bdlde.h"
2+
3+
char source();
4+
void sink(char);
5+
6+
void testBase64Encoder() {
7+
BloombergLP::bdlde::Base64Encoder converter;
8+
char input[] = {source(), 'A', 'A', 'A'};
9+
const char *begin = input;
10+
char shortOutput[32] = {};
11+
converter.convert(shortOutput, input, input + 4);
12+
sink(shortOutput[0]); // $ ir
13+
14+
int numOut = 0, numIn = 0;
15+
char defaultLimitOutput[32] = {};
16+
converter.convert(defaultLimitOutput, &numOut, &numIn, begin, begin + 4);
17+
sink(defaultLimitOutput[0]); // $ ir
18+
19+
char explicitLimitOutput[32] = {};
20+
converter.convert(explicitLimitOutput, &numOut, &numIn, begin, begin + 4, 32);
21+
sink(explicitLimitOutput[0]); // $ ir
22+
}
23+
24+
void testBase64EncoderNonInputs() {
25+
BloombergLP::bdlde::Base64Encoder converter;
26+
const char input[] = "AAAA";
27+
int numOut = source(), numIn = source();
28+
char output[32] = {};
29+
converter.convert(output, &numOut, &numIn, input, input + 4);
30+
sink(output[0]); // No flow from the pre-call values of the output counters.
31+
32+
char limitedOutput[32] = {};
33+
converter.convert(limitedOutput, &numOut, &numIn, input, input + 4, source());
34+
sink(limitedOutput[0]); // The output limit does not supply output bytes.
35+
}
36+
37+
void testBase64Decoder() {
38+
BloombergLP::bdlde::Base64Decoder converter;
39+
char input[] = {source(), 'A', 'A', 'A'};
40+
const char *begin = input;
41+
char shortOutput[32] = {};
42+
converter.convert(shortOutput, input, input + 4);
43+
sink(shortOutput[0]); // $ ir
44+
45+
int numOut = 0, numIn = 0;
46+
char defaultLimitOutput[32] = {};
47+
converter.convert(defaultLimitOutput, &numOut, &numIn, begin, begin + 4);
48+
sink(defaultLimitOutput[0]); // $ ir
49+
50+
char explicitLimitOutput[32] = {};
51+
converter.convert(explicitLimitOutput, &numOut, &numIn, begin, begin + 4, 32);
52+
sink(explicitLimitOutput[0]); // $ ir
53+
}
54+
55+
void testBase64DecoderNonInputs() {
56+
BloombergLP::bdlde::Base64Decoder converter;
57+
const char input[] = "AAAA";
58+
int numOut = source(), numIn = source();
59+
char output[32] = {};
60+
converter.convert(output, &numOut, &numIn, input, input + 4);
61+
sink(output[0]); // No flow from the pre-call values of the output counters.
62+
63+
char limitedOutput[32] = {};
64+
converter.convert(limitedOutput, &numOut, &numIn, input, input + 4, source());
65+
sink(limitedOutput[0]); // The output limit does not supply output bytes.
66+
}
67+
68+
void testHexEncoder() {
69+
BloombergLP::bdlde::HexEncoder converter;
70+
char input[] = {source(), 'A', 'A', 'A'};
71+
const char *begin = input;
72+
char shortOutput[32] = {};
73+
converter.convert(shortOutput, input, input + 4);
74+
sink(shortOutput[0]); // $ ir
75+
76+
int numOut = 0, numIn = 0;
77+
char defaultLimitOutput[32] = {};
78+
converter.convert(defaultLimitOutput, &numOut, &numIn, begin, begin + 4);
79+
sink(defaultLimitOutput[0]); // $ ir
80+
81+
char explicitLimitOutput[32] = {};
82+
converter.convert(explicitLimitOutput, &numOut, &numIn, begin, begin + 4, 32);
83+
sink(explicitLimitOutput[0]); // $ ir
84+
}
85+
86+
void testHexEncoderNonInputs() {
87+
BloombergLP::bdlde::HexEncoder converter;
88+
const char input[] = "AAAA";
89+
int numOut = source(), numIn = source();
90+
char output[32] = {};
91+
converter.convert(output, &numOut, &numIn, input, input + 4);
92+
sink(output[0]); // No flow from the pre-call values of the output counters.
93+
94+
char limitedOutput[32] = {};
95+
converter.convert(limitedOutput, &numOut, &numIn, input, input + 4, source());
96+
sink(limitedOutput[0]); // The output limit does not supply output bytes.
97+
}
98+
99+
void testHexDecoder() {
100+
BloombergLP::bdlde::HexDecoder converter;
101+
char input[] = {source(), 'A', 'A', 'A'};
102+
const char *begin = input;
103+
char shortOutput[32] = {};
104+
converter.convert(shortOutput, input, input + 4);
105+
sink(shortOutput[0]); // $ ir
106+
107+
int numOut = 0, numIn = 0;
108+
char defaultLimitOutput[32] = {};
109+
converter.convert(defaultLimitOutput, &numOut, &numIn, begin, begin + 4);
110+
sink(defaultLimitOutput[0]); // $ ir
111+
112+
char explicitLimitOutput[32] = {};
113+
converter.convert(explicitLimitOutput, &numOut, &numIn, begin, begin + 4, 32);
114+
sink(explicitLimitOutput[0]); // $ ir
115+
}
116+
117+
void testHexDecoderNonInputs() {
118+
BloombergLP::bdlde::HexDecoder converter;
119+
const char input[] = "AAAA";
120+
int numOut = source(), numIn = source();
121+
char output[32] = {};
122+
converter.convert(output, &numOut, &numIn, input, input + 4);
123+
sink(output[0]); // No flow from the pre-call values of the output counters.
124+
125+
char limitedOutput[32] = {};
126+
converter.convert(limitedOutput, &numOut, &numIn, input, input + 4, source());
127+
sink(limitedOutput[0]); // The output limit does not supply output bytes.
128+
}
129+
130+
// Inherited calls still target the method declared in Base64Encoder.
131+
struct DerivedEncoder : BloombergLP::bdlde::Base64Encoder {};
132+
133+
void testInheritedConvert() {
134+
DerivedEncoder converter;
135+
char input[] = {source()};
136+
char output[32] = {};
137+
converter.convert(output, input, input + 1);
138+
sink(output[0]); // $ ir
139+
}
140+
141+
// A different method that hides convert must not inherit the summary.
142+
struct HidingEncoder : BloombergLP::bdlde::Base64Encoder {
143+
template <class OUTPUT_ITERATOR, class INPUT_ITERATOR>
144+
int convert(OUTPUT_ITERATOR out, INPUT_ITERATOR begin, INPUT_ITERATOR end);
145+
};
146+
147+
void testHiddenConvert() {
148+
HidingEncoder converter;
149+
char input[] = {source()};
150+
char output[32] = {};
151+
converter.convert(output, input, input + 1);
152+
sink(output[0]); // No modeled flow for the hiding method.
153+
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1873,6 +1873,7 @@
18731873
| Dubious signature "(OTHERNAME *)" in summary model. |
18741874
| Dubious signature "(OTHERNAME **,const unsigned char **,long)" in summary model. |
18751875
| Dubious signature "(OTHERNAME *,OTHERNAME *)" in summary model. |
1876+
| Dubious signature "(OUT,int *,int *,IN,IN,int)" in summary model. |
18761877
| Dubious signature "(OperationConfig *)" in summary model. |
18771878
| Dubious signature "(OperationConfig *,HttpReq,HttpReq *)" in summary model. |
18781879
| Dubious signature "(OperationConfig *,const char *,tool_mime **,tool_mime **,bool)" in summary model. |

0 commit comments

Comments
 (0)