Skip to content

Commit 24947f2

Browse files
authored
Merge pull request #4750 from geoffw0/modelclasses
C++: Model classes in StdString.qll.
2 parents fbab8f8 + cff5635 commit 24947f2

File tree

4 files changed

+64
-36
lines changed

4 files changed

+64
-36
lines changed

cpp/ql/src/semmle/code/cpp/Function.qll

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,18 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
334334
)
335335
}
336336

337+
/**
338+
* Gets the class of which this function, called `memberName`, is a member.
339+
*
340+
* Prefer to use `getDeclaringType()` or `getName()` directly if you do not
341+
* need to reason about both.
342+
*/
343+
pragma[nomagic]
344+
Class getClassAndName(string memberName) {
345+
this.hasName(memberName) and
346+
this.getDeclaringType() = result
347+
}
348+
337349
/**
338350
* Implements `ControlFlowNode.getControlFlowScope`. The `Function` is
339351
* used to represent the exit node of the control flow graph, so it is

cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll

Lines changed: 50 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ import semmle.code.cpp.models.interfaces.Iterator
99
import semmle.code.cpp.models.interfaces.DataFlow
1010

1111
/**
12-
* The `std::basic_string` template class.
12+
* The `std::basic_string` template class instantiations.
1313
*/
14-
private class StdBasicString extends TemplateClass {
14+
private class StdBasicString extends ClassTemplateInstantiation {
1515
StdBasicString() { this.hasQualifiedName("std", "basic_string") }
1616
}
1717

@@ -24,7 +24,7 @@ private class StdBasicString extends TemplateClass {
2424
* ```
2525
*/
2626
private class StdStringConstructor extends Constructor, TaintFunction {
27-
StdStringConstructor() { this.getDeclaringType().hasQualifiedName("std", "basic_string") }
27+
StdStringConstructor() { this.getDeclaringType() instanceof StdBasicString }
2828

2929
/**
3030
* Gets the index of a parameter to this function that is a string (or
@@ -69,7 +69,7 @@ private class StdStringConstructor extends Constructor, TaintFunction {
6969
* The `std::string` function `c_str`.
7070
*/
7171
private class StdStringCStr extends TaintFunction {
72-
StdStringCStr() { this.hasQualifiedName("std", "basic_string", "c_str") }
72+
StdStringCStr() { this.getClassAndName("c_str") instanceof StdBasicString }
7373

7474
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
7575
// flow from string itself (qualifier) to return value
@@ -82,7 +82,7 @@ private class StdStringCStr extends TaintFunction {
8282
* The `std::string` function `data`.
8383
*/
8484
private class StdStringData extends TaintFunction {
85-
StdStringData() { this.hasQualifiedName("std", "basic_string", "data") }
85+
StdStringData() { this.getClassAndName("data") instanceof StdBasicString }
8686

8787
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
8888
// flow from string itself (qualifier) to return value
@@ -100,7 +100,7 @@ private class StdStringData extends TaintFunction {
100100
* The `std::string` function `push_back`.
101101
*/
102102
private class StdStringPush extends TaintFunction {
103-
StdStringPush() { this.hasQualifiedName("std", "basic_string", "push_back") }
103+
StdStringPush() { this.getClassAndName("push_back") instanceof StdBasicString }
104104

105105
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
106106
// flow from parameter to qualifier
@@ -113,7 +113,7 @@ private class StdStringPush extends TaintFunction {
113113
* The `std::string` functions `front` and `back`.
114114
*/
115115
private class StdStringFrontBack extends TaintFunction {
116-
StdStringFrontBack() { this.hasQualifiedName("std", "basic_string", ["front", "back"]) }
116+
StdStringFrontBack() { this.getClassAndName(["front", "back"]) instanceof StdBasicString }
117117

118118
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
119119
// flow from object to returned reference
@@ -123,12 +123,12 @@ private class StdStringFrontBack extends TaintFunction {
123123
}
124124

125125
/**
126-
* The `std::string` function `operator+`.
126+
* The (non-member) `std::string` function `operator+`.
127127
*/
128128
private class StdStringPlus extends TaintFunction {
129129
StdStringPlus() {
130130
this.hasQualifiedName("std", "operator+") and
131-
this.getUnspecifiedType() = any(StdBasicString s).getAnInstantiation()
131+
this.getUnspecifiedType() instanceof StdBasicString
132132
}
133133

134134
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
@@ -148,7 +148,7 @@ private class StdStringPlus extends TaintFunction {
148148
*/
149149
private class StdStringAppend extends TaintFunction {
150150
StdStringAppend() {
151-
this.hasQualifiedName("std", "basic_string", ["operator+=", "append", "insert", "replace"])
151+
this.getClassAndName(["operator+=", "append", "insert", "replace"]) instanceof StdBasicString
152152
}
153153

154154
/**
@@ -190,7 +190,7 @@ private class StdStringAppend extends TaintFunction {
190190
* The standard function `std::string.assign`.
191191
*/
192192
private class StdStringAssign extends TaintFunction {
193-
StdStringAssign() { this.hasQualifiedName("std", "basic_string", "assign") }
193+
StdStringAssign() { this.getClassAndName("assign") instanceof StdBasicString }
194194

195195
/**
196196
* Gets the index of a parameter to this function that is a string (or
@@ -230,7 +230,7 @@ private class StdStringAssign extends TaintFunction {
230230
* The standard function `std::string.copy`.
231231
*/
232232
private class StdStringCopy extends TaintFunction {
233-
StdStringCopy() { this.hasQualifiedName("std", "basic_string", "copy") }
233+
StdStringCopy() { this.getClassAndName("copy") instanceof StdBasicString }
234234

235235
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
236236
// copy(dest, num, pos)
@@ -243,7 +243,7 @@ private class StdStringCopy extends TaintFunction {
243243
* The standard function `std::string.substr`.
244244
*/
245245
private class StdStringSubstr extends TaintFunction {
246-
StdStringSubstr() { this.hasQualifiedName("std", "basic_string", "substr") }
246+
StdStringSubstr() { this.getClassAndName("substr") instanceof StdBasicString }
247247

248248
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
249249
// substr(pos, num)
@@ -252,11 +252,18 @@ private class StdStringSubstr extends TaintFunction {
252252
}
253253
}
254254

255+
/**
256+
* The `std::basic_stringstream` template class instantiations.
257+
*/
258+
private class StdBasicStringStream extends ClassTemplateInstantiation {
259+
StdBasicStringStream() { this.hasQualifiedName("std", "basic_stringstream") }
260+
}
261+
255262
/**
256263
* The `std::string` functions `at` and `operator[]`.
257264
*/
258265
private class StdStringAt extends TaintFunction {
259-
StdStringAt() { this.hasQualifiedName("std", "basic_string", ["at", "operator[]"]) }
266+
StdStringAt() { this.getClassAndName(["at", "operator[]"]) instanceof StdBasicString }
260267

261268
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
262269
// flow from qualifier to referenced return value
@@ -270,17 +277,17 @@ private class StdStringAt extends TaintFunction {
270277
}
271278

272279
/**
273-
* The `std::basic_istream` template class.
280+
* The `std::basic_istream` template class instantiations.
274281
*/
275-
private class StdBasicIStream extends TemplateClass {
282+
private class StdBasicIStream extends ClassTemplateInstantiation {
276283
StdBasicIStream() { this.hasQualifiedName("std", "basic_istream") }
277284
}
278285

279286
/**
280287
* The `std::istream` function `operator>>` (defined as a member function).
281288
*/
282289
private class StdIStreamIn extends DataFlowFunction, TaintFunction {
283-
StdIStreamIn() { this.hasQualifiedName("std", "basic_istream", "operator>>") }
290+
StdIStreamIn() { this.getClassAndName("operator>>") instanceof StdBasicIStream }
284291

285292
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
286293
// returns reference to `*this`
@@ -305,8 +312,7 @@ private class StdIStreamIn extends DataFlowFunction, TaintFunction {
305312
private class StdIStreamInNonMember extends DataFlowFunction, TaintFunction {
306313
StdIStreamInNonMember() {
307314
this.hasQualifiedName("std", "operator>>") and
308-
this.getUnspecifiedType().(ReferenceType).getBaseType() =
309-
any(StdBasicIStream s).getAnInstantiation()
315+
this.getUnspecifiedType().(ReferenceType).getBaseType() instanceof StdBasicIStream
310316
}
311317

312318
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
@@ -331,7 +337,7 @@ private class StdIStreamInNonMember extends DataFlowFunction, TaintFunction {
331337
*/
332338
private class StdIStreamGet extends TaintFunction {
333339
StdIStreamGet() {
334-
this.hasQualifiedName("std", "basic_istream", ["get", "peek"]) and
340+
this.getClassAndName(["get", "peek"]) instanceof StdBasicIStream and
335341
this.getNumberOfParameters() = 0
336342
}
337343

@@ -347,7 +353,7 @@ private class StdIStreamGet extends TaintFunction {
347353
*/
348354
private class StdIStreamRead extends DataFlowFunction, TaintFunction {
349355
StdIStreamRead() {
350-
this.hasQualifiedName("std", "basic_istream", ["get", "read"]) and
356+
this.getClassAndName(["get", "read"]) instanceof StdBasicIStream and
351357
this.getNumberOfParameters() > 0
352358
}
353359

@@ -372,7 +378,7 @@ private class StdIStreamRead extends DataFlowFunction, TaintFunction {
372378
* The `std::istream` function `readsome`.
373379
*/
374380
private class StdIStreamReadSome extends TaintFunction {
375-
StdIStreamReadSome() { this.hasQualifiedName("std", "basic_istream", "readsome") }
381+
StdIStreamReadSome() { this.getClassAndName("readsome") instanceof StdBasicIStream }
376382

377383
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
378384
// flow from qualifier to first parameter
@@ -385,7 +391,7 @@ private class StdIStreamReadSome extends TaintFunction {
385391
* The `std::istream` function `putback`.
386392
*/
387393
private class StdIStreamPutBack extends DataFlowFunction, TaintFunction {
388-
StdIStreamPutBack() { this.hasQualifiedName("std", "basic_istream", "putback") }
394+
StdIStreamPutBack() { this.getClassAndName("putback") instanceof StdBasicIStream }
389395

390396
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
391397
// returns reference to `*this`
@@ -418,7 +424,7 @@ private class StdIStreamPutBack extends DataFlowFunction, TaintFunction {
418424
* The `std::istream` function `getline`.
419425
*/
420426
private class StdIStreamGetLine extends DataFlowFunction, TaintFunction {
421-
StdIStreamGetLine() { this.hasQualifiedName("std", "basic_istream", "getline") }
427+
StdIStreamGetLine() { this.getClassAndName("getline") instanceof StdBasicIStream }
422428

423429
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
424430
// returns reference to `*this`
@@ -461,9 +467,9 @@ private class StdGetLine extends DataFlowFunction, TaintFunction {
461467
}
462468

463469
/**
464-
* The `std::basic_ostream` template class.
470+
* The `std::basic_ostream` template class instantiations.
465471
*/
466-
private class StdBasicOStream extends TemplateClass {
472+
private class StdBasicOStream extends ClassTemplateInstantiation {
467473
StdBasicOStream() { this.hasQualifiedName("std", "basic_ostream") }
468474
}
469475

@@ -472,7 +478,9 @@ private class StdBasicOStream extends TemplateClass {
472478
* `put` and `write`.
473479
*/
474480
private class StdOStreamOut extends DataFlowFunction, TaintFunction {
475-
StdOStreamOut() { this.hasQualifiedName("std", "basic_ostream", ["operator<<", "put", "write"]) }
481+
StdOStreamOut() {
482+
this.getClassAndName(["operator<<", "put", "write"]) instanceof StdBasicOStream
483+
}
476484

477485
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
478486
// returns reference to `*this`
@@ -507,8 +515,7 @@ private class StdOStreamOut extends DataFlowFunction, TaintFunction {
507515
private class StdOStreamOutNonMember extends DataFlowFunction, TaintFunction {
508516
StdOStreamOutNonMember() {
509517
this.hasQualifiedName("std", "operator<<") and
510-
this.getUnspecifiedType().(ReferenceType).getBaseType() =
511-
any(StdBasicOStream s).getAnInstantiation()
518+
this.getUnspecifiedType().(ReferenceType).getBaseType() instanceof StdBasicOStream
512519
}
513520

514521
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
@@ -537,9 +544,7 @@ private class StdOStreamOutNonMember extends DataFlowFunction, TaintFunction {
537544
* input parameter.
538545
*/
539546
private class StdStringStreamConstructor extends Constructor, TaintFunction {
540-
StdStringStreamConstructor() {
541-
this.getDeclaringType().hasQualifiedName("std", "basic_stringstream")
542-
}
547+
StdStringStreamConstructor() { this.getDeclaringType() instanceof StdBasicStringStream }
543548

544549
/**
545550
* Gets the index of a parameter to this function that is a string.
@@ -563,7 +568,7 @@ private class StdStringStreamConstructor extends Constructor, TaintFunction {
563568
* The `std::stringstream` function `str`.
564569
*/
565570
private class StdStringStreamStr extends TaintFunction {
566-
StdStringStreamStr() { this.hasQualifiedName("std", "basic_stringstream", "str") }
571+
StdStringStreamStr() { this.getClassAndName("str") instanceof StdBasicStringStream }
567572

568573
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
569574
// flow from qualifier to return value (if any)
@@ -576,15 +581,24 @@ private class StdStringStreamStr extends TaintFunction {
576581
}
577582
}
578583

584+
/**
585+
* The `std::basic_ios` template class instantiations.
586+
*/
587+
private class StdBasicIOS extends ClassTemplateInstantiation {
588+
StdBasicIOS() { this.hasQualifiedName("std", "basic_ios") }
589+
}
590+
579591
/**
580592
* A `std::` stream function that does not require a model, except that it
581593
* returns a reference to `*this` and thus could be used in a chain.
582594
*/
583595
private class StdStreamFunction extends DataFlowFunction, TaintFunction {
584596
StdStreamFunction() {
585-
this.hasQualifiedName("std", "basic_istream", ["ignore", "unget", "seekg"]) or
586-
this.hasQualifiedName("std", "basic_ostream", ["seekp", "flush"]) or
587-
this.hasQualifiedName("std", "basic_ios", "copyfmt")
597+
this.getClassAndName(["ignore", "unget", "seekg"]) instanceof StdBasicIStream
598+
or
599+
this.getClassAndName(["seekp", "flush"]) instanceof StdBasicOStream
600+
or
601+
this.getClassAndName("copyfmt") instanceof StdBasicIOS
588602
}
589603

590604
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {

cpp/ql/src/semmle/code/cpp/models/interfaces/DataFlow.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,6 @@ abstract class DataFlowFunction extends Function {
2424
* represented by `input` to the return value or buffer represented by
2525
* `output`
2626
*/
27+
pragma[nomagic]
2728
abstract predicate hasDataFlow(FunctionInput input, FunctionOutput output);
2829
}

cpp/ql/src/semmle/code/cpp/models/interfaces/Taint.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,6 @@ abstract class TaintFunction extends Function {
2828
* Holds if data passed into the argument, qualifier, or buffer represented by
2929
* `input` influences the return value or buffer represented by `output`
3030
*/
31+
pragma[nomagic]
3132
abstract predicate hasTaintFlow(FunctionInput input, FunctionOutput output);
3233
}

0 commit comments

Comments
 (0)