mirror of
https://github.com/github/codeql.git
synced 2026-04-23 07:45:17 +02:00
C++: Add a model for 'partial updating' and extend models appropriately.
This commit is contained in:
@@ -5,6 +5,7 @@ private import DataFlowImplCommon as DataFlowImplCommon
|
||||
private import semmle.code.cpp.models.interfaces.Allocation as Alloc
|
||||
private import semmle.code.cpp.models.interfaces.DataFlow as DataFlow
|
||||
private import semmle.code.cpp.models.interfaces.Taint as Taint
|
||||
private import semmle.code.cpp.models.interfaces.PartialFlow as PartialFlow
|
||||
private import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs as FIO
|
||||
private import semmle.code.cpp.ir.internal.IRCppLanguage
|
||||
private import semmle.code.cpp.ir.dataflow.internal.ModelUtil
|
||||
@@ -816,10 +817,15 @@ private predicate inOut(FIO::FunctionInput input, FIO::FunctionOutput output) {
|
||||
* flows to `n`).
|
||||
*/
|
||||
private predicate modeledFlowBarrier(Node n) {
|
||||
exists(FIO::FunctionInput input, FIO::FunctionOutput output, CallInstruction call |
|
||||
exists(
|
||||
FIO::FunctionInput input, FIO::FunctionOutput output, CallInstruction call,
|
||||
PartialFlow::PartialFlowFunction partialFlowFunc
|
||||
|
|
||||
n = callInput(call, input) and
|
||||
inOut(input, output) and
|
||||
exists(callOutput(call, output))
|
||||
exists(callOutput(call, output)) and
|
||||
partialFlowFunc = call.getStaticCallTarget() and
|
||||
not partialFlowFunc.isPartialWrite(output)
|
||||
|
|
||||
call.getStaticCallTarget().(DataFlow::DataFlowFunction).hasDataFlow(_, output)
|
||||
or
|
||||
|
||||
@@ -15,6 +15,8 @@ private class GetDelimFunction extends TaintFunction, AliasFunction, SideEffectF
|
||||
i.isParameter(3) and o.isParameterDeref(0)
|
||||
}
|
||||
|
||||
override predicate isPartialWrite(FunctionOutput o) { o.isParameterDeref(3) }
|
||||
|
||||
override predicate parameterNeverEscapes(int index) { index = [0, 1, 3] }
|
||||
|
||||
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||
|
||||
@@ -27,6 +27,8 @@ private class FgetsFunction extends DataFlowFunction, TaintFunction, ArrayFuncti
|
||||
output.isReturnValue()
|
||||
}
|
||||
|
||||
override predicate isPartialWrite(FunctionOutput output) { output.isParameterDeref(2) }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
input.isParameter(2) and
|
||||
output.isParameterDeref(0)
|
||||
|
||||
@@ -20,6 +20,8 @@ private class InetAton extends TaintFunction, ArrayFunction {
|
||||
output.isParameterDeref(1)
|
||||
}
|
||||
|
||||
override predicate isPartialWrite(FunctionOutput output) { output.isParameterDeref(1) }
|
||||
|
||||
override predicate hasArrayInput(int bufParam) { bufParam = 0 }
|
||||
|
||||
override predicate hasArrayOutput(int bufParam) { bufParam = 1 }
|
||||
|
||||
@@ -118,6 +118,8 @@ private class StdSequenceContainerData extends TaintFunction {
|
||||
input.isReturnValueDeref() and
|
||||
output.isQualifierObject()
|
||||
}
|
||||
|
||||
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -147,6 +149,8 @@ private class StdSequenceContainerPushModel extends StdSequenceContainerPush, Ta
|
||||
input.isParameterDeref(0) and
|
||||
output.isQualifierObject()
|
||||
}
|
||||
|
||||
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -207,6 +211,8 @@ private class StdSequenceContainerInsertModel extends StdSequenceContainerInsert
|
||||
output.isReturnValue()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -263,6 +269,8 @@ private class StdSequenceContainerAt extends TaintFunction {
|
||||
input.isReturnValueDeref() and
|
||||
output.isQualifierObject()
|
||||
}
|
||||
|
||||
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -297,6 +305,8 @@ private class StdSequenceEmplaceModel extends StdSequenceEmplace, TaintFunction
|
||||
output.isReturnValue()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -335,6 +345,8 @@ private class StdSequenceEmplaceBackModel extends StdSequenceEmplaceBack, TaintF
|
||||
input.isParameterDeref([0 .. this.getNumberOfParameters() - 1]) and
|
||||
output.isQualifierObject()
|
||||
}
|
||||
|
||||
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.models.interfaces.Taint
|
||||
import semmle.code.cpp.models.interfaces.DataFlow
|
||||
import semmle.code.cpp.models.interfaces.Iterator
|
||||
|
||||
/**
|
||||
@@ -53,6 +54,8 @@ private class StdMapInsert extends TaintFunction {
|
||||
output.isReturnValue()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,6 +78,8 @@ private class StdMapEmplace extends TaintFunction {
|
||||
input.isQualifierObject() and
|
||||
output.isReturnValue()
|
||||
}
|
||||
|
||||
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,6 +107,8 @@ private class StdMapTryEmplace extends TaintFunction {
|
||||
input.isQualifierObject() and
|
||||
output.isReturnValue()
|
||||
}
|
||||
|
||||
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -115,6 +122,8 @@ private class StdMapMerge extends TaintFunction {
|
||||
input.isParameterDeref(0) and
|
||||
output.isQualifierObject()
|
||||
}
|
||||
|
||||
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -132,6 +141,8 @@ private class StdMapAt extends TaintFunction {
|
||||
input.isReturnValueDeref() and
|
||||
output.isQualifierObject()
|
||||
}
|
||||
|
||||
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -61,6 +61,8 @@ private class StdSetInsert extends TaintFunction {
|
||||
output.isReturnValue()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,6 +84,8 @@ private class StdSetEmplace extends TaintFunction {
|
||||
input.isQualifierObject() and
|
||||
output.isReturnValue()
|
||||
}
|
||||
|
||||
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,6 +99,8 @@ private class StdSetMerge extends TaintFunction {
|
||||
input.isParameterDeref(0) and
|
||||
output.isQualifierObject()
|
||||
}
|
||||
|
||||
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -129,6 +129,8 @@ private class StdStringDataModel extends StdStringData, StdStringTaintFunction {
|
||||
input.isReturnValueDeref() and
|
||||
output.isQualifierObject()
|
||||
}
|
||||
|
||||
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -142,6 +144,8 @@ private class StdStringPush extends StdStringTaintFunction {
|
||||
input.isParameter(0) and
|
||||
output.isQualifierObject()
|
||||
}
|
||||
|
||||
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -204,6 +208,8 @@ private class StdStringAppend extends StdStringTaintFunction {
|
||||
input.isReturnValueDeref() and
|
||||
output.isQualifierObject()
|
||||
}
|
||||
|
||||
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -237,6 +243,8 @@ private class StdStringInsert extends StdStringTaintFunction {
|
||||
input.isReturnValueDeref() and
|
||||
output.isQualifierObject()
|
||||
}
|
||||
|
||||
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -305,6 +313,8 @@ private class StdStringAt extends StdStringTaintFunction {
|
||||
input.isReturnValueDeref() and
|
||||
output.isQualifierObject()
|
||||
}
|
||||
|
||||
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -338,6 +348,8 @@ private class StdIStreamIn extends DataFlowFunction, TaintFunction {
|
||||
input.isReturnValueDeref() and
|
||||
output.isQualifierObject()
|
||||
}
|
||||
|
||||
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -358,6 +370,8 @@ private class StdIStreamInNonMember extends DataFlowFunction, TaintFunction {
|
||||
output.isReturnValueDeref()
|
||||
}
|
||||
|
||||
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// flow from first parameter to second parameter
|
||||
input.isParameterDeref(0) and
|
||||
@@ -403,6 +417,8 @@ private class StdIStreamRead extends DataFlowFunction, TaintFunction {
|
||||
output.isReturnValueDeref()
|
||||
}
|
||||
|
||||
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// flow from qualifier to first parameter
|
||||
input.isQualifierObject() and
|
||||
@@ -442,6 +458,8 @@ private class StdIStreamPutBack extends DataFlowFunction, TaintFunction {
|
||||
output.isReturnValueDeref()
|
||||
}
|
||||
|
||||
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// flow from first parameter (value or pointer) to qualifier
|
||||
input.isParameter(0) and
|
||||
@@ -478,6 +496,8 @@ private class StdIStreamGetLine extends DataFlowFunction, TaintFunction {
|
||||
output.isReturnValueDeref()
|
||||
}
|
||||
|
||||
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// flow from qualifier to first parameter
|
||||
input.isQualifierObject() and
|
||||
@@ -540,6 +560,8 @@ private class StdOStreamOut extends DataFlowFunction, TaintFunction {
|
||||
output.isReturnValueDeref()
|
||||
}
|
||||
|
||||
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// flow from first parameter (value or pointer) to qualifier
|
||||
input.isParameter(0) and
|
||||
@@ -579,6 +601,8 @@ private class StdOStreamOutNonMember extends DataFlowFunction, TaintFunction {
|
||||
output.isReturnValueDeref()
|
||||
}
|
||||
|
||||
override predicate isPartialWrite(FunctionOutput output) { output.isParameterDeref(0) }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// flow from second parameter to first parameter
|
||||
input.isParameterDeref(1) and
|
||||
@@ -672,6 +696,8 @@ private class StdStreamFunction extends DataFlowFunction, TaintFunction {
|
||||
output.isReturnValueDeref()
|
||||
}
|
||||
|
||||
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// reverse flow from returned reference to the qualifier
|
||||
input.isReturnValueDeref() and
|
||||
|
||||
@@ -36,6 +36,8 @@ private class Strcrement extends ArrayFunction, TaintFunction, SideEffectFunctio
|
||||
input.isParameter(index) and output.isReturnValue()
|
||||
or
|
||||
input.isParameterDeref(index) and output.isReturnValueDeref()
|
||||
or
|
||||
input.isParameterDeref(index) and output.isParameterDeref(index)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
import semmle.code.cpp.Function
|
||||
import FunctionInputsAndOutputs
|
||||
import semmle.code.cpp.models.Models
|
||||
import PartialFlow
|
||||
|
||||
/**
|
||||
* A library function for which a value is or may be copied from a parameter
|
||||
@@ -18,7 +19,7 @@ import semmle.code.cpp.models.Models
|
||||
* Note that this does not include partial copying of values or partial writes
|
||||
* to destinations; that is covered by `TaintModel.qll`.
|
||||
*/
|
||||
abstract class DataFlowFunction extends Function {
|
||||
abstract class DataFlowFunction extends PartialFlowFunction {
|
||||
/**
|
||||
* Holds if data can be copied from the argument, qualifier, or buffer
|
||||
* represented by `input` to the return value or buffer represented by
|
||||
|
||||
15
cpp/ql/lib/semmle/code/cpp/models/interfaces/PartialFlow.qll
Normal file
15
cpp/ql/lib/semmle/code/cpp/models/interfaces/PartialFlow.qll
Normal file
@@ -0,0 +1,15 @@
|
||||
import semmle.code.cpp.Function
|
||||
import FunctionInputsAndOutputs
|
||||
import semmle.code.cpp.models.Models
|
||||
|
||||
/**
|
||||
* A function that may (but not always) updates (part of) a `FunctionOutput`.
|
||||
*/
|
||||
abstract class PartialFlowFunction extends Function {
|
||||
/**
|
||||
* Holds if the write to `output` either is:
|
||||
* - Only partially updating the `output`
|
||||
* - Is not unconditional
|
||||
*/
|
||||
predicate isPartialWrite(FunctionOutput output) { none() }
|
||||
}
|
||||
@@ -10,6 +10,7 @@
|
||||
import semmle.code.cpp.Function
|
||||
import FunctionInputsAndOutputs
|
||||
import semmle.code.cpp.models.Models
|
||||
import PartialFlow
|
||||
|
||||
/**
|
||||
* A library function for which a taint-tracking library should propagate taint
|
||||
@@ -23,7 +24,7 @@ import semmle.code.cpp.models.Models
|
||||
* altered (for example copying a string with `strncpy`), this is also considered
|
||||
* data flow.
|
||||
*/
|
||||
abstract class TaintFunction extends Function {
|
||||
abstract class TaintFunction extends PartialFlowFunction {
|
||||
/**
|
||||
* Holds if data passed into the argument, qualifier, or buffer represented by
|
||||
* `input` influences the return value or buffer represented by `output`
|
||||
|
||||
@@ -6490,6 +6490,7 @@ WARNING: Module TaintTracking has been deprecated and may be removed in future (
|
||||
| taint.cpp:607:10:607:16 | call to _strinc | taint.cpp:609:8:609:12 | dest1 | |
|
||||
| taint.cpp:607:18:607:23 | source | taint.cpp:607:10:607:16 | call to _strinc | TAINT |
|
||||
| taint.cpp:607:26:607:31 | locale | taint.cpp:607:10:607:16 | call to _strinc | TAINT |
|
||||
| taint.cpp:607:26:607:31 | locale | taint.cpp:607:26:607:31 | ref arg locale | TAINT |
|
||||
| taint.cpp:607:26:607:31 | ref arg locale | taint.cpp:606:82:606:87 | locale | |
|
||||
| taint.cpp:607:26:607:31 | ref arg locale | taint.cpp:611:25:611:30 | locale | |
|
||||
| taint.cpp:608:7:608:11 | ref arg dest1 | taint.cpp:606:52:606:56 | dest1 | |
|
||||
@@ -6501,6 +6502,7 @@ WARNING: Module TaintTracking has been deprecated and may be removed in future (
|
||||
| taint.cpp:611:10:611:16 | call to _strinc | taint.cpp:613:8:613:12 | dest2 | |
|
||||
| taint.cpp:611:18:611:22 | clean | taint.cpp:611:10:611:16 | call to _strinc | TAINT |
|
||||
| taint.cpp:611:25:611:30 | locale | taint.cpp:611:10:611:16 | call to _strinc | TAINT |
|
||||
| taint.cpp:611:25:611:30 | locale | taint.cpp:611:25:611:30 | ref arg locale | TAINT |
|
||||
| taint.cpp:611:25:611:30 | ref arg locale | taint.cpp:606:82:606:87 | locale | |
|
||||
| taint.cpp:612:7:612:11 | ref arg dest2 | taint.cpp:606:65:606:69 | dest2 | |
|
||||
| taint.cpp:612:7:612:11 | ref arg dest2 | taint.cpp:613:8:613:12 | dest2 | |
|
||||
|
||||
@@ -179,11 +179,11 @@ void test_map()
|
||||
m14.insert(std::make_pair("b", source()));
|
||||
m14.insert(std::make_pair("c", source()));
|
||||
m14.insert(std::make_pair("d", "d"));
|
||||
sink(m14.lower_bound("b")); // $ ast=179:33 ast=180:33 MISSING: ir=179:33 ir=180:33
|
||||
sink(m14.upper_bound("b")); // $ ast=179:33 ast=180:33 MISSING: ir=179:33 ir=180:33
|
||||
sink(m14.lower_bound("b")); // $ ast,ir=179:33 ast,ir=180:33
|
||||
sink(m14.upper_bound("b")); // $ ast,ir=179:33 ast,ir=180:33
|
||||
sink(m14.equal_range("b").first); // $ MISSING: ast,ir
|
||||
sink(m14.equal_range("b").second); // $ MISSING: ast,ir
|
||||
sink(m14.upper_bound("c")); // $ SPURIOUS: ast=179:33 ast=180:33
|
||||
sink(m14.upper_bound("c")); // $ SPURIOUS: ast,ir=179:33 ast,ir=180:33
|
||||
sink(m14.equal_range("c").second);
|
||||
|
||||
// swap
|
||||
@@ -213,7 +213,7 @@ void test_map()
|
||||
sink(m22); // $ ast,ir
|
||||
m19.merge(m20);
|
||||
m21.merge(m22);
|
||||
sink(m19); // $ ast
|
||||
sink(m19); // $ ast,ir
|
||||
sink(m20);
|
||||
sink(m21); // $ ast,ir
|
||||
sink(m22); // $ ast,ir
|
||||
@@ -222,11 +222,11 @@ void test_map()
|
||||
std::map<char *, char *> m23;
|
||||
m23.insert(std::pair<char *, char *>(source(), source()));
|
||||
m23.insert(std::pair<char *, char *>(source(), source()));
|
||||
sink(m23); // $ ast=223:49 ast=224:49 ir MISSING: ir=223:49 ir=224:49
|
||||
sink(m23.erase(m23.begin())); // $ ast=223:49 ast=224:49 ir MISSING: ir=223:49 ir=224:49
|
||||
sink(m23); // $ ast=223:49 ast=224:49 ir MISSING: ir=223:49 ir=224:49
|
||||
sink(m23); // $ ast,ir=223:49 ast,ir=224:49
|
||||
sink(m23.erase(m23.begin())); // $ ast,ir=223:49 ast,ir=224:49
|
||||
sink(m23); // $ ast,ir=223:49 ast,ir=224:49
|
||||
m23.clear();
|
||||
sink(m23); // $ SPURIOUS: ast=223:49 ast=224:49 ir
|
||||
sink(m23); // $ SPURIOUS: ast,ir=223:49 ast,ir=224:49
|
||||
|
||||
// emplace, emplace_hint
|
||||
std::map<char *, char *> m24, m25;
|
||||
@@ -362,7 +362,7 @@ void test_unordered_map()
|
||||
sink(m22); // $ ast,ir
|
||||
m19.merge(m20);
|
||||
m21.merge(m22);
|
||||
sink(m19); // $ ast MISSING: ir
|
||||
sink(m19); // $ ast,ir
|
||||
sink(m20);
|
||||
sink(m21); // $ ast,ir
|
||||
sink(m22); // $ ast,ir
|
||||
@@ -371,11 +371,11 @@ void test_unordered_map()
|
||||
std::unordered_map<char *, char *> m23;
|
||||
m23.insert(std::pair<char *, char *>(source(), source()));
|
||||
m23.insert(std::pair<char *, char *>(source(), source()));
|
||||
sink(m23); // $ ast=372:49 ast=373:49 ir MISSING: ir=372:49 ir=373:49
|
||||
sink(m23.erase(m23.begin())); // $ ast=372:49 ast=373:49 ir MISSING: ir=372:49 ir=373:49
|
||||
sink(m23); // $ ast=372:49 ast=373:49 ir MISSING: ir=372:49 ir=373:49
|
||||
sink(m23); // $ ast,ir=372:49 ast,ir=373:49
|
||||
sink(m23.erase(m23.begin())); // $ ast,ir=372:49 ast,ir=373:49
|
||||
sink(m23); // $ ast,ir=372:49 ast,ir=373:49
|
||||
m23.clear();
|
||||
sink(m23); // $ SPURIOUS: ast=372:49 ast=373:49 ir
|
||||
sink(m23); // $ SPURIOUS: ast,ir=372:49 ast,ir=373:49
|
||||
|
||||
// emplace, emplace_hint
|
||||
std::unordered_map<char *, char *> m24, m25;
|
||||
@@ -395,7 +395,7 @@ void test_unordered_map()
|
||||
sink(m26);
|
||||
sink(m26.try_emplace("abc", source()).first);
|
||||
sink(m26.try_emplace("abc", source()).second); // $ MISSING: ast,ir=396:30
|
||||
sink(m26); // $ ast=396:30 ir MISSING: ir=396:30 SPURIOUS: ast=397:30
|
||||
sink(m26); // $ ast,ir=396:30 SPURIOUS: ast,ir=397:30
|
||||
sink(m27.try_emplace(m27.begin(), "abc", "def"));
|
||||
sink(m27);
|
||||
sink(m27.try_emplace(m27.begin(), "abc", source())); // $ ast,ir
|
||||
|
||||
@@ -66,8 +66,8 @@ void test_set()
|
||||
s11.insert("a");
|
||||
s11.insert(source());
|
||||
s11.insert("c");
|
||||
sink(s11.lower_bound("b")); // $ ast MISSING: ir
|
||||
sink(s11.upper_bound("b")); // $ ast MISSING: ir
|
||||
sink(s11.lower_bound("b")); // $ ast,ir
|
||||
sink(s11.upper_bound("b")); // $ ast,ir
|
||||
sink(s11.equal_range("b").first); // $ MISSING: ast,ir
|
||||
sink(s11.equal_range("b").second); // $ MISSING: ast,ir
|
||||
|
||||
@@ -98,7 +98,7 @@ void test_set()
|
||||
sink(s19); // $ ast,ir
|
||||
s16.merge(s17);
|
||||
s18.merge(s19);
|
||||
sink(s16); // $ ast MISSING: ir
|
||||
sink(s16); // $ ast,ir
|
||||
sink(s17);
|
||||
sink(s18); // $ ast,ir
|
||||
sink(s19); // $ ast,ir
|
||||
@@ -107,11 +107,11 @@ void test_set()
|
||||
std::set<char *> s20;
|
||||
s20.insert(source());
|
||||
s20.insert(source());
|
||||
sink(s20); // $ ast=108:13 ast=109:13 ir MISSING: ir=108:13 ir=109:13
|
||||
sink(s20.erase(s20.begin())); // $ ast=108:13 ast=109:13 ir MISSING: ir=108:13 ir=109:13
|
||||
sink(s20); // $ ir ast=108:13 ast=109:13 MISSING: ir=108:13 ir=109:13
|
||||
sink(s20); // $ ast,ir=108:13 ast,ir=109:13
|
||||
sink(s20.erase(s20.begin())); // $ ast,ir=108:13 ast,ir=109:13
|
||||
sink(s20); // $ ast,ir=108:13 ast,ir=109:13
|
||||
s20.clear();
|
||||
sink(s20); // $ SPURIOUS: ir ast=108:13 ast=109:13
|
||||
sink(s20); // $ SPURIOUS: ast,ir=108:13 ast,ir=109:13
|
||||
|
||||
// emplace, emplace_hint
|
||||
std::set<char *> s21, s22;
|
||||
@@ -210,7 +210,7 @@ void test_unordered_set()
|
||||
sink(s19); // $ ast,ir
|
||||
s16.merge(s17);
|
||||
s18.merge(s19);
|
||||
sink(s16); // $ ast MISSING: ir
|
||||
sink(s16); // $ ast,ir
|
||||
sink(s17);
|
||||
sink(s18); // $ ast,ir
|
||||
sink(s19); // $ ast,ir
|
||||
@@ -219,11 +219,11 @@ void test_unordered_set()
|
||||
std::unordered_set<char *> s20;
|
||||
s20.insert(source());
|
||||
s20.insert(source());
|
||||
sink(s20); // $ ir ast=220:13 ast=221:13 MISSING: ir=220:13 ir=221:13
|
||||
sink(s20.erase(s20.begin())); // $ ast=220:13 ast=221:13 ir MISSING: ir=220:13 ir=221:13
|
||||
sink(s20); // $ ast=220:13 ast=221:13 ir MISSING: ir=220:13 ir=221:13
|
||||
sink(s20); // $ ast,ir=220:13 ast,ir=221:13
|
||||
sink(s20.erase(s20.begin())); // $ ast,ir=220:13 ast,ir=221:13
|
||||
sink(s20); // $ ast,ir=220:13 ast,ir=221:13
|
||||
s20.clear();
|
||||
sink(s20); // $ SPURIOUS: ast=220:13 ast=221:13 ir
|
||||
sink(s20); // $ SPURIOUS: ast,ir=220:13 ast,ir=221:13
|
||||
|
||||
// emplace, emplace_hint
|
||||
std::unordered_set<char *> s21, s22;
|
||||
|
||||
Reference in New Issue
Block a user