From fa8b278332f4d1fb22e9bdd8c6c361678666ae3d Mon Sep 17 00:00:00 2001 From: Jonathan Leitschuh Date: Tue, 30 Jun 2020 11:57:17 -0400 Subject: [PATCH 001/133] Add jOOQ methods as SQL Injection Sinks --- .../Security/CWE/CWE-089/SqlInjectionLib.qll | 3 +++ .../src/semmle/code/java/frameworks/jOOQ.qll | 25 +++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 java/ql/src/semmle/code/java/frameworks/jOOQ.qll diff --git a/java/ql/src/Security/CWE/CWE-089/SqlInjectionLib.qll b/java/ql/src/Security/CWE/CWE-089/SqlInjectionLib.qll index 2572d91cb99..215a2c78759 100644 --- a/java/ql/src/Security/CWE/CWE-089/SqlInjectionLib.qll +++ b/java/ql/src/Security/CWE/CWE-089/SqlInjectionLib.qll @@ -7,6 +7,7 @@ import semmle.code.java.frameworks.javaee.Persistence import semmle.code.java.frameworks.SpringJdbc import semmle.code.java.frameworks.MyBatis import semmle.code.java.frameworks.Hibernate +import semmle.code.java.frameworks.jOOQ /** A sink for database query language injection vulnerabilities. */ abstract class QueryInjectionSink extends DataFlow::ExprNode { } @@ -29,6 +30,8 @@ class SqlInjectionSink extends QueryInjectionSink { index = 0 and mybatisSqlMethod(m) or index = 0 and hibernateSqlMethod(m) + or + index = 0 and jOOQSqlMethod(m) ) } } diff --git a/java/ql/src/semmle/code/java/frameworks/jOOQ.qll b/java/ql/src/semmle/code/java/frameworks/jOOQ.qll new file mode 100644 index 00000000000..2eb1284ab70 --- /dev/null +++ b/java/ql/src/semmle/code/java/frameworks/jOOQ.qll @@ -0,0 +1,25 @@ +/** + * Provides classes and predicates for working with the jOOQ framework. + */ + +import java + +/** + * Methods annotated with this allow for generation of "plain SQL" + * and is prone to SQL injection. + * https://www.jooq.org/doc/current/manual/sql-building/plain-sql/ + */ +private class PlainSQLType extends Annotation { + PlainSQLType() { + this.getType().hasQualifiedName("org.jooq", "PlainSQL") + } +} + +/** + * Holds if `m` is a jOOQ SQL method taking an SQL string as its + * first argument. + */ +predicate jOOQSqlMethod(Method m) { + m.getAnAnnotation() instanceof PlainSQLType and + m.getParameterType(0) instanceof TypeString +} From 5c1275ec5deb6b689de4bd991335886a593037dd Mon Sep 17 00:00:00 2001 From: "lcartey@github.com" Date: Wed, 8 Jul 2020 16:00:07 +0100 Subject: [PATCH 002/133] C++: Add an interface for exprs that can contribute to range analysis --- .../cpp/models/interfaces/RangeAnalysisExpr.qll | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 cpp/ql/src/semmle/code/cpp/models/interfaces/RangeAnalysisExpr.qll diff --git a/cpp/ql/src/semmle/code/cpp/models/interfaces/RangeAnalysisExpr.qll b/cpp/ql/src/semmle/code/cpp/models/interfaces/RangeAnalysisExpr.qll new file mode 100644 index 00000000000..ac1ba558c09 --- /dev/null +++ b/cpp/ql/src/semmle/code/cpp/models/interfaces/RangeAnalysisExpr.qll @@ -0,0 +1,16 @@ +/** + * Provides a class for modeling `Expr`s with a restricted range. + */ +import cpp + +/** + * An expression for which a range can be deduced. + */ +abstract class RangeAnalysisExpr extends Expr { + /** Gets the lower bound of the expression. */ + abstract float getLowerBounds(); + /** Gets the upper bound of the expression. */ + abstract float getUpperBounds(); + /** Holds if this expression depends on the definition `srcDef` for StackVariable `srcVar`. */ + predicate dependsOnDef(RangeSsaDefinition srcDef, StackVariable srcVar) { none() } +} \ No newline at end of file From b4929dbb97e5a0f4e096de4608eb77543c21ef21 Mon Sep 17 00:00:00 2001 From: "lcartey@github.com" Date: Wed, 8 Jul 2020 16:00:44 +0100 Subject: [PATCH 003/133] C++: Adopt range analysis interface in the SimpleRangeAnalysis library --- .../cpp/rangeanalysis/SimpleRangeAnalysis.qll | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll index 867d96b804c..5ecaafbeeda 100644 --- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll @@ -44,6 +44,7 @@ import cpp private import RangeAnalysisUtils +private import semmle.code.cpp.models.interfaces.RangeAnalysisExpr import RangeSSA import SimpleRangeAnalysisCached private import NanAnalysis @@ -207,6 +208,9 @@ private predicate analyzableExpr(Expr e) { or // `>>` by a constant exists(e.(RShiftExpr).getRightOperand().getValue()) + or + // A modeled expression for range analysis + e instanceof RangeAnalysisExpr ) } @@ -318,6 +322,11 @@ private predicate exprDependsOnDef(Expr e, RangeSsaDefinition srcDef, StackVaria ) or e = srcDef.getAUse(srcVar) + or + // A modeled expression for range analysis + exists(RangeAnalysisExpr rae | + rae.dependsOnDef(srcDef, srcVar) + ) } /** @@ -438,7 +447,7 @@ private float addRoundingDownSmall(float x, float small) { /** * Gets the truncated lower bounds of the fully converted expression. */ -private float getFullyConvertedLowerBounds(Expr expr) { +float getFullyConvertedLowerBounds(Expr expr) { result = getTruncatedLowerBounds(expr.getFullyConverted()) } @@ -491,7 +500,7 @@ private float getTruncatedLowerBounds(Expr expr) { /** * Gets the truncated upper bounds of the fully converted expression. */ -private float getFullyConvertedUpperBounds(Expr expr) { +float getFullyConvertedUpperBounds(Expr expr) { result = getTruncatedUpperBounds(expr.getFullyConverted()) } @@ -727,6 +736,12 @@ private float getLowerBoundsImpl(Expr expr) { right = rsExpr.getRightOperand().getValue().toInt() and result = safeFloor(left / 2.pow(right)) ) + or + // A modeled expression for range analysis + exists(RangeAnalysisExpr rangeAnalysisExpr | + rangeAnalysisExpr = expr and + result = rangeAnalysisExpr.getLowerBounds() + ) } /** Only to be called by `getTruncatedUpperBounds`. */ @@ -896,6 +911,12 @@ private float getUpperBoundsImpl(Expr expr) { right = rsExpr.getRightOperand().getValue().toInt() and result = safeFloor(left / 2.pow(right)) ) + or + // A modeled expression for range analysis + exists(RangeAnalysisExpr rangeAnalysisExpr | + rangeAnalysisExpr = expr and + result = rangeAnalysisExpr.getUpperBounds() + ) } /** From 0638b512bcf02ed39e43ad1fa65665d4ed6b510d Mon Sep 17 00:00:00 2001 From: "lcartey@github.com" Date: Wed, 8 Jul 2020 17:56:31 +0100 Subject: [PATCH 004/133] C++: Support custom range expression modeling for variable accesses --- .../semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll index 5ecaafbeeda..469c5deaac6 100644 --- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll @@ -720,7 +720,9 @@ private float getLowerBoundsImpl(Expr expr) { or // Use SSA to get the lower bounds for a variable use. exists(RangeSsaDefinition def, StackVariable v | expr = def.getAUse(v) | - result = getDefLowerBounds(def, v) + result = getDefLowerBounds(def, v) and + // Not explicitly modeled by a RangeAnalysisExpr + not expr instanceof RangeAnalysisExpr ) or // unsigned `&` (tighter bounds may exist) @@ -893,7 +895,9 @@ private float getUpperBoundsImpl(Expr expr) { or // Use SSA to get the upper bounds for a variable use. exists(RangeSsaDefinition def, StackVariable v | expr = def.getAUse(v) | - result = getDefUpperBounds(def, v) + result = getDefUpperBounds(def, v) and + // Not explicitly modeled by a RangeAnalysisExpr + not expr instanceof RangeAnalysisExpr ) or // unsigned `&` (tighter bounds may exist) From 38acea633fefe1dae5d54ca1ef2d39d846e276c9 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Mon, 27 Jul 2020 17:58:21 +0200 Subject: [PATCH 005/133] Python: Dataflow, expand callable to classes --- .../dataflow/internal/DataFlowPrivate.qll | 58 ++++++++++++++++++- .../consistency/dataflow-consistency.expected | 2 + 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/python/ql/src/experimental/dataflow/internal/DataFlowPrivate.qll b/python/ql/src/experimental/dataflow/internal/DataFlowPrivate.qll index 95c72ef7e14..4221c90cf74 100644 --- a/python/ql/src/experimental/dataflow/internal/DataFlowPrivate.qll +++ b/python/ql/src/experimental/dataflow/internal/DataFlowPrivate.qll @@ -97,8 +97,64 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) { //-------- // Global flow //-------- +/** + * IPA type for DataFlowCallable. + * A callable is either a callable value or a class. + */ +newtype TDataFlowCallable = + TCallableValue(CallableValue callable) or + TClassValue(ClassValue c) + /** Represents a callable */ -class DataFlowCallable = CallableValue; +abstract class DataFlowCallable extends TDataFlowCallable { + /** Gets a textual representation of this element. */ + abstract string toString(); + + /** Gets a call to this callable. */ + abstract CallNode getACall(); + + /** Gets the scope of this callable */ + abstract Scope getScope(); + + /** Gets the specified parameter of this callable */ + abstract NameNode getParameter(int n); + + /** Gets the name of this callable. */ + abstract string getName(); +} + +class DataFlowCallableValue extends DataFlowCallable, TCallableValue { + CallableValue callable; + + DataFlowCallableValue() { this = TCallableValue(callable) } + + override string toString() { result = callable.toString() } + + override CallNode getACall() { result = callable.getACall() } + + override Scope getScope() { result = callable.getScope() } + + override NameNode getParameter(int n) { result = callable.getParameter(n) } + + override string getName() { result = callable.getName() } +} + +class DataFlowClassValue extends DataFlowCallable, TClassValue { + ClassValue c; + + DataFlowClassValue() { this = TClassValue(c) } + + override string toString() { result = c.toString() } + + override CallNode getACall() { result = c.getACall() } + + override Scope getScope() { result = c.getScope() } + + override NameNode getParameter(int n) { result.getNode() = c.getScope().getInitMethod().getArg(n+1).asName() } + + override string getName() { result = c.getName() } +} + /** Represents a call to a callable */ class DataFlowCall extends CallNode { diff --git a/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.expected b/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.expected index eaf7a166e23..2ae31eb1126 100644 --- a/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.expected +++ b/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.expected @@ -101,3 +101,5 @@ argHasPostUpdate | test.py:74:17:74:17 | ControlFlowNode for t | ArgumentNode is missing PostUpdateNode. | | test.py:81:13:81:13 | ControlFlowNode for t | ArgumentNode is missing PostUpdateNode. | | test.py:86:13:86:13 | ControlFlowNode for t | ArgumentNode is missing PostUpdateNode. | +| test.py:158:15:158:15 | ControlFlowNode for l | ArgumentNode is missing PostUpdateNode. | +| test.py:159:15:159:15 | ControlFlowNode for d | ArgumentNode is missing PostUpdateNode. | From eab64f125b52a9684229da37ee55a21accdaab8a Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Tue, 28 Jul 2020 20:32:12 +0200 Subject: [PATCH 006/133] Python: Dataflow, start on test for classes --- .../experimental/dataflow/coverage/classes.py | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 python/ql/test/experimental/dataflow/coverage/classes.py diff --git a/python/ql/test/experimental/dataflow/coverage/classes.py b/python/ql/test/experimental/dataflow/coverage/classes.py new file mode 100644 index 00000000000..fef83372176 --- /dev/null +++ b/python/ql/test/experimental/dataflow/coverage/classes.py @@ -0,0 +1,72 @@ +# These are included so that we can easily evaluate the test code +SOURCE = "source" +def SINK(x): + print(x) + +# Callable types +# These are the types to which the function call operation (see section Calls) can be applied: + +# User-defined functions +# A user-defined function object is created by a function definition (see section Function definitions). It should be called with an argument list containing the same number of items as the function's formal parameter list. +def f(a, b): + return a + +SINK(f(SOURCE, 3)) + +# Instance methods +# An instance method object combines a class, a class instance and any callable object (normally a user-defined function). +class C(object): + + def method(self, a, cls): + assert cls is self.__class__ + return a + + @classmethod + def classmethod(cls, a): + return a + + @staticmethod + def staticmethod(): + return a + +c = C() + +# When an instance method object is created by retrieving a user-defined function object from a class via one of its instances, its __self__ attribute is the instance, and the method object is said to be bound. The new method’s __func__ attribute is the original function object. +func_obj = c.method.__func__ + +# When an instance method object is called, the underlying function (__func__) is called, inserting the class instance (__self__) in front of the argument list. For instance, when C is a class which contains a definition for a function f(), and x is an instance of C, calling x.f(1) is equivalent to calling C.f(x, 1). +SINK(c.method(SOURCE, C)) +SINK(C.method(c, SOURCE, C)) +SINK(func_obj(c, SOURCE, C)) + + +# When an instance method object is created by retrieving a class method object from a class or instance, its __self__ attribute is the class itself, and its __func__ attribute is the function object underlying the class method. +c_func_obj = C.classmethod.__func__ + +# When an instance method object is derived from a class method object, the “class instance” stored in __self__ will actually be the class itself, so that calling either x.f(1) or C.f(1) is equivalent to calling f(C,1) where f is the underlying function. +SINK(c.classmethod(SOURCE)) +SINK(C.classmethod(SOURCE)) +SINK(c_func_obj(C, SOURCE)) + +# Generator functions +# A function or method which uses the yield statement (see section The yield statement) is called a generator function. Such a function, when called, always returns an iterator object which can be used to execute the body of the function: calling the iterator’s iterator.__next__() method will cause the function to execute until it provides a value using the yield statement. When the function executes a return statement or falls off the end, a StopIteration exception is raised and the iterator will have reached the end of the set of values to be returned. + +# Coroutine functions +# A function or method which is defined using async def is called a coroutine function. Such a function, when called, returns a coroutine object. It may contain await expressions, as well as async with and async for statements. See also the Coroutine Objects section. + +# Asynchronous generator functions +# A function or method which is defined using async def and which uses the yield statement is called a asynchronous generator function. Such a function, when called, returns an asynchronous iterator object which can be used in an async for statement to execute the body of the function. + +# Calling the asynchronous iterator’s aiterator.__anext__() method will return an awaitable which when awaited will execute until it provides a value using the yield expression. When the function executes an empty return statement or falls off the end, a StopAsyncIteration exception is raised and the asynchronous iterator will have reached the end of the set of values to be yielded. + +# Built-in functions +# A built-in function object is a wrapper around a C function. Examples of built-in functions are len() and math.sin() (math is a standard built-in module). The number and type of the arguments are determined by the C function. Special read-only attributes: __doc__ is the function’s documentation string, or None if unavailable; __name__ is the function’s name; __self__ is set to None (but see the next item); __module__ is the name of the module the function was defined in or None if unavailable. + +# Built-in methods +# This is really a different disguise of a built-in function, this time containing an object passed to the C function as an implicit extra argument. An example of a built-in method is alist.append(), assuming alist is a list object. In this case, the special read-only attribute __self__ is set to the object denoted by alist. + +# Classes +# Classes are callable. These objects normally act as factories for new instances of themselves, but variations are possible for class types that override __new__(). The arguments of the call are passed to __new__() and, in the typical case, to __init__() to initialize the new instance. + +# Class Instances +# Instances of arbitrary classes can be made callable by defining a __call__() method in their class. From 488a7f4d0142d1f4b2d48a8afb5cc422e572e8a2 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Tue, 28 Jul 2020 21:46:45 +0200 Subject: [PATCH 007/133] Python: update test expectations --- .../test/experimental/dataflow/coverage/classes.py | 4 ++-- .../experimental/dataflow/coverage/dataflow.expected | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/python/ql/test/experimental/dataflow/coverage/classes.py b/python/ql/test/experimental/dataflow/coverage/classes.py index fef83372176..e16d1d89179 100644 --- a/python/ql/test/experimental/dataflow/coverage/classes.py +++ b/python/ql/test/experimental/dataflow/coverage/classes.py @@ -37,7 +37,7 @@ func_obj = c.method.__func__ # When an instance method object is called, the underlying function (__func__) is called, inserting the class instance (__self__) in front of the argument list. For instance, when C is a class which contains a definition for a function f(), and x is an instance of C, calling x.f(1) is equivalent to calling C.f(x, 1). SINK(c.method(SOURCE, C)) SINK(C.method(c, SOURCE, C)) -SINK(func_obj(c, SOURCE, C)) +SINK(func_obj(c, SOURCE, C)) # Path not found # When an instance method object is created by retrieving a class method object from a class or instance, its __self__ attribute is the class itself, and its __func__ attribute is the function object underlying the class method. @@ -46,7 +46,7 @@ c_func_obj = C.classmethod.__func__ # When an instance method object is derived from a class method object, the “class instance” stored in __self__ will actually be the class itself, so that calling either x.f(1) or C.f(1) is equivalent to calling f(C,1) where f is the underlying function. SINK(c.classmethod(SOURCE)) SINK(C.classmethod(SOURCE)) -SINK(c_func_obj(C, SOURCE)) +SINK(c_func_obj(C, SOURCE)) # Path not found # Generator functions # A function or method which uses the yield statement (see section The yield statement) is called a generator function. Such a function, when called, always returns an iterator object which can be used to execute the body of the function: calling the iterator’s iterator.__next__() method will cause the function to execute until it provides a value using the yield statement. When the function executes a return statement or falls off the end, a StopIteration exception is raised and the iterator will have reached the end of the set of values to be returned. diff --git a/python/ql/test/experimental/dataflow/coverage/dataflow.expected b/python/ql/test/experimental/dataflow/coverage/dataflow.expected index 26384d0e28c..3dd049be724 100644 --- a/python/ql/test/experimental/dataflow/coverage/dataflow.expected +++ b/python/ql/test/experimental/dataflow/coverage/dataflow.expected @@ -1,3 +1,15 @@ +| classes.py:2:10:2:17 | ControlFlowNode for Str | classes.py:14:6:14:17 | ControlFlowNode for f() | +| classes.py:2:10:2:17 | ControlFlowNode for Str | classes.py:38:6:38:24 | ControlFlowNode for Attribute() | +| classes.py:2:10:2:17 | ControlFlowNode for Str | classes.py:39:6:39:27 | ControlFlowNode for Attribute() | +| classes.py:2:10:2:17 | ControlFlowNode for Str | classes.py:40:6:40:27 | ControlFlowNode for func_obj() | +| classes.py:2:10:2:17 | ControlFlowNode for Str | classes.py:47:6:47:26 | ControlFlowNode for Attribute() | +| classes.py:2:10:2:17 | ControlFlowNode for Str | classes.py:48:6:48:26 | ControlFlowNode for Attribute() | +| classes.py:2:10:2:17 | ControlFlowNode for Str | classes.py:49:6:49:26 | ControlFlowNode for c_func_obj() | +| classes.py:14:8:14:13 | ControlFlowNode for SOURCE | classes.py:14:6:14:17 | ControlFlowNode for f() | +| classes.py:38:15:38:20 | ControlFlowNode for SOURCE | classes.py:38:6:38:24 | ControlFlowNode for Attribute() | +| classes.py:39:18:39:23 | ControlFlowNode for SOURCE | classes.py:39:6:39:27 | ControlFlowNode for Attribute() | +| classes.py:47:20:47:25 | ControlFlowNode for SOURCE | classes.py:47:6:47:26 | ControlFlowNode for Attribute() | +| classes.py:48:20:48:25 | ControlFlowNode for SOURCE | classes.py:48:6:48:26 | ControlFlowNode for Attribute() | | test.py:20:9:20:14 | ControlFlowNode for SOURCE | test.py:21:10:21:10 | ControlFlowNode for x | | test.py:25:9:25:16 | ControlFlowNode for Str | test.py:26:10:26:10 | ControlFlowNode for x | | test.py:29:9:29:17 | ControlFlowNode for Str | test.py:30:10:30:10 | ControlFlowNode for x | From d32e2772a0bcebdd7bcaf54905574888a4706361 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Wed, 29 Jul 2020 15:52:56 +0200 Subject: [PATCH 008/133] Python: some doc, a generator, and a corotuine --- .../experimental/dataflow/coverage/classes.py | 64 +++++++++++++++++-- .../dataflow/coverage/dataflow.expected | 31 +++++---- 2 files changed, 76 insertions(+), 19 deletions(-) diff --git a/python/ql/test/experimental/dataflow/coverage/classes.py b/python/ql/test/experimental/dataflow/coverage/classes.py index e16d1d89179..d7b7b1f6b73 100644 --- a/python/ql/test/experimental/dataflow/coverage/classes.py +++ b/python/ql/test/experimental/dataflow/coverage/classes.py @@ -1,4 +1,15 @@ -# These are included so that we can easily evaluate the test code +# User-defined methods, both instance methods and class methods, can be called in many non-standard ways +# i.e. differently from simply `c.f()` or `C.f()`. For example, a user-defined `__await__` function will +# be called by the syntactic constru +# This should cover all the class calls that we hope to support. It is based on https://docs.python.org/3/reference/datamodel.html. +# +# Intended sources should be the variable `SOURCE` and intended sinks should be. +# arguments to the function `SINK` (see python/ql/test/experimental/dataflow/testConfig.qll). +# +# Functions whose name ends with "_with_local_flow" will also be tested for local flow. + + +# These are included so that we can easily evaluate the test code. SOURCE = "source" def SINK(x): print(x) @@ -17,17 +28,26 @@ SINK(f(SOURCE, 3)) # An instance method object combines a class, a class instance and any callable object (normally a user-defined function). class C(object): - def method(self, a, cls): + def method(self, x, cls): assert cls is self.__class__ - return a + return x @classmethod - def classmethod(cls, a): - return a + def classmethod(cls, x): + return x @staticmethod - def staticmethod(): - return a + def staticmethod(x): + return x + + def gen(self, x, count): + n = count + while n > 0: + yield x + n -= 1 + + async def coro(self, x): + return x c = C() @@ -50,9 +70,39 @@ SINK(c_func_obj(C, SOURCE)) # Path not found # Generator functions # A function or method which uses the yield statement (see section The yield statement) is called a generator function. Such a function, when called, always returns an iterator object which can be used to execute the body of the function: calling the iterator’s iterator.__next__() method will cause the function to execute until it provides a value using the yield statement. When the function executes a return statement or falls off the end, a StopIteration exception is raised and the iterator will have reached the end of the set of values to be returned. +def gen(x, count): + n = count + while n > 0: + yield x + n -= 1 + +iter = gen(SOURCE, 1) +SINK(iter.__next__()) # Returns SOURCE, path not found +SINK(iter.__next__()) # throws StopIteration + +oiter = c.gen(SOURCE, 1) +SINK(oiter.__next__()) +SINK(oiter.__next__()) # Coroutine functions # A function or method which is defined using async def is called a coroutine function. Such a function, when called, returns a coroutine object. It may contain await expressions, as well as async with and async for statements. See also the Coroutine Objects section. +async def coro(x): + return x + +import asyncio +SINK(asyncio.run(coro(SOURCE))) +SINK(asyncio.run(c.coro(SOURCE))) + +class A: + + def __await__(self, x): + yield x + +async def agen(x): + a = A() + return await a(SOURCE) + +SINK(asyncio.run(agen(SOURCE))) # fails with TypeError: 'A' object is not callable (possible query?) # Asynchronous generator functions # A function or method which is defined using async def and which uses the yield statement is called a asynchronous generator function. Such a function, when called, returns an asynchronous iterator object which can be used in an async for statement to execute the body of the function. diff --git a/python/ql/test/experimental/dataflow/coverage/dataflow.expected b/python/ql/test/experimental/dataflow/coverage/dataflow.expected index 3dd049be724..cb8822df9b3 100644 --- a/python/ql/test/experimental/dataflow/coverage/dataflow.expected +++ b/python/ql/test/experimental/dataflow/coverage/dataflow.expected @@ -1,15 +1,22 @@ -| classes.py:2:10:2:17 | ControlFlowNode for Str | classes.py:14:6:14:17 | ControlFlowNode for f() | -| classes.py:2:10:2:17 | ControlFlowNode for Str | classes.py:38:6:38:24 | ControlFlowNode for Attribute() | -| classes.py:2:10:2:17 | ControlFlowNode for Str | classes.py:39:6:39:27 | ControlFlowNode for Attribute() | -| classes.py:2:10:2:17 | ControlFlowNode for Str | classes.py:40:6:40:27 | ControlFlowNode for func_obj() | -| classes.py:2:10:2:17 | ControlFlowNode for Str | classes.py:47:6:47:26 | ControlFlowNode for Attribute() | -| classes.py:2:10:2:17 | ControlFlowNode for Str | classes.py:48:6:48:26 | ControlFlowNode for Attribute() | -| classes.py:2:10:2:17 | ControlFlowNode for Str | classes.py:49:6:49:26 | ControlFlowNode for c_func_obj() | -| classes.py:14:8:14:13 | ControlFlowNode for SOURCE | classes.py:14:6:14:17 | ControlFlowNode for f() | -| classes.py:38:15:38:20 | ControlFlowNode for SOURCE | classes.py:38:6:38:24 | ControlFlowNode for Attribute() | -| classes.py:39:18:39:23 | ControlFlowNode for SOURCE | classes.py:39:6:39:27 | ControlFlowNode for Attribute() | -| classes.py:47:20:47:25 | ControlFlowNode for SOURCE | classes.py:47:6:47:26 | ControlFlowNode for Attribute() | -| classes.py:48:20:48:25 | ControlFlowNode for SOURCE | classes.py:48:6:48:26 | ControlFlowNode for Attribute() | +| classes.py:13:10:13:17 | ControlFlowNode for Str | classes.py:25:6:25:17 | ControlFlowNode for f() | +| classes.py:13:10:13:17 | ControlFlowNode for Str | classes.py:58:6:58:24 | ControlFlowNode for Attribute() | +| classes.py:13:10:13:17 | ControlFlowNode for Str | classes.py:59:6:59:27 | ControlFlowNode for Attribute() | +| classes.py:13:10:13:17 | ControlFlowNode for Str | classes.py:60:6:60:27 | ControlFlowNode for func_obj() | +| classes.py:13:10:13:17 | ControlFlowNode for Str | classes.py:67:6:67:26 | ControlFlowNode for Attribute() | +| classes.py:13:10:13:17 | ControlFlowNode for Str | classes.py:68:6:68:26 | ControlFlowNode for Attribute() | +| classes.py:13:10:13:17 | ControlFlowNode for Str | classes.py:69:6:69:26 | ControlFlowNode for c_func_obj() | +| classes.py:13:10:13:17 | ControlFlowNode for Str | classes.py:80:6:80:20 | ControlFlowNode for Attribute() | +| classes.py:13:10:13:17 | ControlFlowNode for Str | classes.py:81:6:81:20 | ControlFlowNode for Attribute() | +| classes.py:13:10:13:17 | ControlFlowNode for Str | classes.py:84:6:84:21 | ControlFlowNode for Attribute() | +| classes.py:13:10:13:17 | ControlFlowNode for Str | classes.py:85:6:85:21 | ControlFlowNode for Attribute() | +| classes.py:13:10:13:17 | ControlFlowNode for Str | classes.py:93:6:93:30 | ControlFlowNode for Attribute() | +| classes.py:13:10:13:17 | ControlFlowNode for Str | classes.py:94:6:94:32 | ControlFlowNode for Attribute() | +| classes.py:13:10:13:17 | ControlFlowNode for Str | classes.py:105:6:105:30 | ControlFlowNode for Attribute() | +| classes.py:25:8:25:13 | ControlFlowNode for SOURCE | classes.py:25:6:25:17 | ControlFlowNode for f() | +| classes.py:58:15:58:20 | ControlFlowNode for SOURCE | classes.py:58:6:58:24 | ControlFlowNode for Attribute() | +| classes.py:59:18:59:23 | ControlFlowNode for SOURCE | classes.py:59:6:59:27 | ControlFlowNode for Attribute() | +| classes.py:67:20:67:25 | ControlFlowNode for SOURCE | classes.py:67:6:67:26 | ControlFlowNode for Attribute() | +| classes.py:68:20:68:25 | ControlFlowNode for SOURCE | classes.py:68:6:68:26 | ControlFlowNode for Attribute() | | test.py:20:9:20:14 | ControlFlowNode for SOURCE | test.py:21:10:21:10 | ControlFlowNode for x | | test.py:25:9:25:16 | ControlFlowNode for Str | test.py:26:10:26:10 | ControlFlowNode for x | | test.py:29:9:29:17 | ControlFlowNode for Str | test.py:30:10:30:10 | ControlFlowNode for x | From 81ad4552c9e2567c9177079f1411587de3eb85a7 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Wed, 5 Aug 2020 13:30:30 +0200 Subject: [PATCH 009/133] Python: full list of magic methods to be tested --- .../experimental/dataflow/coverage/classes.py | 191 +++++++++++- .../dataflow/coverage/dataflow.expected | 286 +++++++++--------- 2 files changed, 325 insertions(+), 152 deletions(-) diff --git a/python/ql/test/experimental/dataflow/coverage/classes.py b/python/ql/test/experimental/dataflow/coverage/classes.py index 8315602c152..e543bede80c 100644 --- a/python/ql/test/experimental/dataflow/coverage/classes.py +++ b/python/ql/test/experimental/dataflow/coverage/classes.py @@ -1,7 +1,9 @@ # User-defined methods, both instance methods and class methods, can be called in many non-standard ways -# i.e. differently from simply `c.f()` or `C.f()`. For example, a user-defined `__await__` function will -# be called by the syntactic constru -# This should cover all the class calls that we hope to support. It is based on https://docs.python.org/3/reference/datamodel.html. +# i.e. differently from simply `c.f()` or `C.f()`. For example, a user-defined `__await__` function on a +# class `C` will be called by the syntactic construct `await c` when `c` is an instance of `C`. +# +# These tests should cover all the class calls that we hope to support. +# It is based on https://docs.python.org/3/reference/datamodel.html, and headings refer there. # # Intended sources should be the variable `SOURCE` and intended sinks should be. # arguments to the function `SINK` (see python/ql/test/experimental/dataflow/testConfig.qll). @@ -10,10 +12,14 @@ # These are included so that we can easily evaluate the test code. +NONSOURCE = "not a source" SOURCE = "source" def SINK(x): print(x) +def SINK_F(x): + print("Unexpected flow: ", x) + # Callable types # These are the types to which the function call operation (see section Calls) can be applied: @@ -78,11 +84,11 @@ def gen(x, count): iter = gen(SOURCE, 1) SINK(iter.__next__()) -SINK(iter.__next__()) # throws StopIteration, FP +SINK_F(iter.__next__()) # throws StopIteration, FP oiter = c.gen(SOURCE, 1) SINK(oiter.__next__()) -SINK(oiter.__next__()) # throws StopIteration, FP +SINK_F(oiter.__next__()) # throws StopIteration, FP # Coroutine functions # A function or method which is defined using async def is called a coroutine function. Such a function, when called, returns a coroutine object. It may contain await expressions, as well as async with and async for statements. See also the Coroutine Objects section. @@ -95,14 +101,15 @@ SINK(asyncio.run(c.coro(SOURCE))) class A: - def __await__(self, x): - yield x + def __await__(self): + # yield SOURCE -- see https://groups.google.com/g/dev-python/c/_lrrc-vp9TI?pli=1 + return (yield from asyncio.coroutine(lambda: SOURCE)()) async def agen(x): a = A() - return await a(SOURCE) + return await a -SINK(asyncio.run(agen(SOURCE))) # fails with TypeError: 'A' object is not callable (possible query?) +SINK(asyncio.run(agen(SOURCE))) # Asynchronous generator functions # A function or method which is defined using async def and which uses the yield statement is called a asynchronous generator function. Such a function, when called, returns an asynchronous iterator object which can be used in an async for statement to execute the body of the function. @@ -120,3 +127,169 @@ SINK(asyncio.run(agen(SOURCE))) # fails with TypeError: 'A' object is not callab # Class Instances # Instances of arbitrary classes can be made callable by defining a __call__() method in their class. + +class Customized: + + a = NONSOURCE + b = NONSOURCE + + def __new__(cls): + cls.a = SOURCE + return super().__new__(cls) + + def __init__(self): + self.b = SOURCE + +customized = Customized() +SINK(Customized.a) +SINK_F(Customized.b) +SINK(customized.a) +SINK(customized.b) + +# def __del__(self): + +# If a class sets __iter__() to None, calling iter() on its instances will raise a TypeError (without falling back to __getitem__()). + +# 3.3.1. Basic customization +# object.__new__(cls[, ...]) +# object.__init__(self[, ...]) +# object.__del__(self) +# object.__repr__(self) +# object.__str__(self)¶ +# object.__bytes__(self) +# object.__format__(self, format_spec) +# object.__lt__(self, other) +# object.__le__(self, other) +# object.__eq__(self, other) +# object.__ne__(self, other) +# object.__gt__(self, other) +# object.__ge__(self, other) +# object.__hash__(self) +# object.__bool__(self) +# len + +# 3.3.2. Customizing attribute access +# object.__getattr__(self, name) +# object.__getattribute__(self, name) +# object.__setattr__(self, name, value) +# object.__delattr__(self, name) +# object.__dir__(self) + +# 3.3.2.2. Implementing Descriptors +# object.__get__(self, instance, owner=None) +# object.__set__(self, instance, value) +# object.__delete__(self, instance) +# object.__set_name__(self, owner, name) + +# 3.3.2.4. __slots__ +# object.__slots__ +# __weakref__ +# __dict__ + +# 3.3.3. Customizing class creation +# classmethod object.__init_subclass__(cls) + +# 3.3.3.1. Metaclasses +# By default, classes are constructed using type(). The class body is executed in a new namespace and the class name is bound locally to the result of type(name, bases, namespace). + +# 3.3.3.2. Resolving MRO entries +# __mro_entries__ + +# 3.3.3.4. Preparing the class namespace +# metaclass.__prepare__(name, bases, **kwds) + +# 3.3.4. Customizing instance and subclass checks +# class.__instancecheck__(self, instance) +# class.__subclasscheck__(self, subclass) + +# 3.3.5. Emulating generic types +# classmethod object.__class_getitem__(cls, key) + +# 3.3.6. Emulating callable objects +# object.__call__(self[, args...]) + +# 3.3.7. Emulating container types +# object.__len__(self) +# object.__length_hint__(self) +# object.__getitem__(self, key) +# object.__setitem__(self, key, value) +# object.__delitem__(self, key) +# object.__missing__(self, key) +# object.__iter__(self) +# object.__reversed__(self) +# object.__contains__(self, item) + +# 3.3.8. Emulating numeric types +# object.__add__(self, other) +# object.__sub__(self, other) +# object.__mul__(self, other) +# object.__matmul__(self, other) +# object.__truediv__(self, other) +# object.__floordiv__(self, other) +# object.__mod__(self, other) +# object.__divmod__(self, other) +# object.__pow__(self, other[, modulo]) +# object.__lshift__(self, other) +# object.__rshift__(self, other) +# object.__and__(self, other) +# object.__xor__(self, other) +# object.__or__(self, other) +# object.__radd__(self, other) +# object.__rsub__(self, other) +# object.__rmul__(self, other) +# object.__rmatmul__(self, other) +# object.__rtruediv__(self, other) +# object.__rfloordiv__(self, other) +# object.__rmod__(self, other) +# object.__rdivmod__(self, other) +# object.__rpow__(self, other[, modulo]) +# object.__rlshift__(self, other) +# object.__rrshift__(self, other) +# object.__rand__(self, other) +# object.__rxor__(self, other) +# object.__ror__(self, other) +# object.__iadd__(self, other) +# object.__isub__(self, other) +# object.__imul__(self, other) +# object.__imatmul__(self, other) +# object.__itruediv__(self, other) +# object.__ifloordiv__(self, other) +# object.__imod__(self, other) +# object.__ipow__(self, other[, modulo]) +# object.__ilshift__(self, other) +# object.__irshift__(self, other) +# object.__iand__(self, other) +# object.__ixor__(self, other) +# object.__ior__(self, other) +# object.__neg__(self) +# object.__pos__(self) +# object.__abs__(self) +# object.__invert__(self) +# object.__complex__(self) +# object.__int__(self) +# object.__float__(self) +# object.__index__(self) +# object.__round__(self[, ndigits]) +# object.__trunc__(self) +# object.__floor__(self) +# object.__ceil__(self) + +# 3.3.9. With Statement Context Managers +# object.__enter__(self) +# object.__exit__(self, exc_type, exc_value, traceback) + +# 3.4.1. Awaitable Objects +# object.__await__(self) + +# 3.4.2. Coroutine Objects +# coroutine.send(value) +# coroutine.throw(type[, value[, traceback]]) +# coroutine.close() + +# 3.4.3. Asynchronous Iterators +# object.__aiter__(self) +# object.__anext__(self) + +# 3.4.4. Asynchronous Context Managers +# object.__aenter__(self) +# object.__aexit__(self, exc_type, exc_value, traceback) diff --git a/python/ql/test/experimental/dataflow/coverage/dataflow.expected b/python/ql/test/experimental/dataflow/coverage/dataflow.expected index e1bc2ea2d07..6713969a2e4 100644 --- a/python/ql/test/experimental/dataflow/coverage/dataflow.expected +++ b/python/ql/test/experimental/dataflow/coverage/dataflow.expected @@ -1,82 +1,82 @@ edges -| classes.py:13:1:13:6 | GSSA Variable SOURCE | classes.py:25:6:25:17 | ControlFlowNode for f() | -| classes.py:13:1:13:6 | GSSA Variable SOURCE | classes.py:25:6:25:17 | GSSA Variable SOURCE | -| classes.py:13:1:13:6 | GSSA Variable SOURCE | classes.py:25:8:25:13 | ControlFlowNode for SOURCE | -| classes.py:13:10:13:17 | ControlFlowNode for Str | classes.py:13:1:13:6 | GSSA Variable SOURCE | -| classes.py:25:6:25:17 | GSSA Variable SOURCE | classes.py:52:5:52:7 | ControlFlowNode for C() | -| classes.py:25:6:25:17 | GSSA Variable SOURCE | classes.py:58:6:58:24 | ControlFlowNode for Attribute() | -| classes.py:25:6:25:17 | GSSA Variable SOURCE | classes.py:58:6:58:24 | GSSA Variable SOURCE | -| classes.py:25:6:25:17 | GSSA Variable SOURCE | classes.py:58:15:58:20 | ControlFlowNode for SOURCE | -| classes.py:25:8:25:13 | ControlFlowNode for SOURCE | classes.py:25:6:25:17 | ControlFlowNode for f() | -| classes.py:52:1:52:1 | GSSA Variable c | classes.py:58:6:58:24 | ControlFlowNode for Attribute() | -| classes.py:52:1:52:1 | GSSA Variable c | classes.py:58:6:58:24 | GSSA Variable c | -| classes.py:52:5:52:7 | ControlFlowNode for C() | classes.py:52:1:52:1 | GSSA Variable c | -| classes.py:58:6:58:24 | GSSA Variable SOURCE | classes.py:59:6:59:27 | ControlFlowNode for Attribute() | -| classes.py:58:6:58:24 | GSSA Variable SOURCE | classes.py:59:18:59:23 | ControlFlowNode for SOURCE | -| classes.py:58:6:58:24 | GSSA Variable SOURCE | classes.py:60:6:60:27 | ControlFlowNode for func_obj() | -| classes.py:58:6:58:24 | GSSA Variable SOURCE | classes.py:67:6:67:26 | ControlFlowNode for Attribute() | -| classes.py:58:6:58:24 | GSSA Variable SOURCE | classes.py:67:6:67:26 | GSSA Variable SOURCE | -| classes.py:58:6:58:24 | GSSA Variable SOURCE | classes.py:67:20:67:25 | ControlFlowNode for SOURCE | -| classes.py:58:6:58:24 | GSSA Variable c | classes.py:59:6:59:27 | ControlFlowNode for Attribute() | -| classes.py:58:6:58:24 | GSSA Variable c | classes.py:59:6:59:27 | GSSA Variable c | -| classes.py:58:15:58:20 | ControlFlowNode for SOURCE | classes.py:58:6:58:24 | ControlFlowNode for Attribute() | -| classes.py:59:6:59:27 | GSSA Variable c | classes.py:60:6:60:27 | ControlFlowNode for func_obj() | -| classes.py:59:6:59:27 | GSSA Variable c | classes.py:60:6:60:27 | GSSA Variable c | -| classes.py:59:18:59:23 | ControlFlowNode for SOURCE | classes.py:59:6:59:27 | ControlFlowNode for Attribute() | -| classes.py:60:6:60:27 | GSSA Variable c | classes.py:67:6:67:26 | ControlFlowNode for Attribute() | -| classes.py:60:6:60:27 | GSSA Variable c | classes.py:67:6:67:26 | GSSA Variable c | -| classes.py:67:6:67:26 | GSSA Variable SOURCE | classes.py:68:6:68:26 | ControlFlowNode for Attribute() | -| classes.py:67:6:67:26 | GSSA Variable SOURCE | classes.py:68:6:68:26 | GSSA Variable SOURCE | -| classes.py:67:6:67:26 | GSSA Variable SOURCE | classes.py:68:20:68:25 | ControlFlowNode for SOURCE | -| classes.py:67:6:67:26 | GSSA Variable c | classes.py:68:6:68:26 | ControlFlowNode for Attribute() | -| classes.py:67:6:67:26 | GSSA Variable c | classes.py:69:6:69:26 | ControlFlowNode for c_func_obj() | -| classes.py:67:6:67:26 | GSSA Variable c | classes.py:79:8:79:21 | ControlFlowNode for gen() | -| classes.py:67:6:67:26 | GSSA Variable c | classes.py:80:6:80:20 | ControlFlowNode for Attribute() | -| classes.py:67:6:67:26 | GSSA Variable c | classes.py:81:6:81:20 | ControlFlowNode for Attribute() | -| classes.py:67:6:67:26 | GSSA Variable c | classes.py:83:9:83:24 | ControlFlowNode for Attribute() | -| classes.py:67:6:67:26 | GSSA Variable c | classes.py:83:9:83:24 | GSSA Variable c | -| classes.py:67:20:67:25 | ControlFlowNode for SOURCE | classes.py:67:6:67:26 | ControlFlowNode for Attribute() | -| classes.py:68:6:68:26 | GSSA Variable SOURCE | classes.py:69:6:69:26 | ControlFlowNode for c_func_obj() | -| classes.py:68:6:68:26 | GSSA Variable SOURCE | classes.py:79:8:79:21 | ControlFlowNode for gen() | -| classes.py:68:6:68:26 | GSSA Variable SOURCE | classes.py:79:8:79:21 | GSSA Variable SOURCE | -| classes.py:68:20:68:25 | ControlFlowNode for SOURCE | classes.py:68:6:68:26 | ControlFlowNode for Attribute() | -| classes.py:79:1:79:4 | GSSA Variable iter | classes.py:80:6:80:20 | ControlFlowNode for Attribute() | -| classes.py:79:1:79:4 | GSSA Variable iter | classes.py:80:6:80:20 | GSSA Variable iter | -| classes.py:79:8:79:21 | ControlFlowNode for gen() | classes.py:79:1:79:4 | GSSA Variable iter | -| classes.py:79:8:79:21 | GSSA Variable SOURCE | classes.py:80:6:80:20 | ControlFlowNode for Attribute() | -| classes.py:79:8:79:21 | GSSA Variable SOURCE | classes.py:81:6:81:20 | ControlFlowNode for Attribute() | -| classes.py:79:8:79:21 | GSSA Variable SOURCE | classes.py:83:9:83:24 | ControlFlowNode for Attribute() | -| classes.py:79:8:79:21 | GSSA Variable SOURCE | classes.py:83:9:83:24 | GSSA Variable SOURCE | -| classes.py:80:6:80:20 | GSSA Variable iter | classes.py:81:6:81:20 | ControlFlowNode for Attribute() | -| classes.py:80:6:80:20 | GSSA Variable iter | classes.py:81:6:81:20 | GSSA Variable iter | -| classes.py:81:6:81:20 | GSSA Variable iter | classes.py:83:9:83:24 | ControlFlowNode for Attribute() | -| classes.py:81:6:81:20 | GSSA Variable iter | classes.py:84:6:84:21 | ControlFlowNode for Attribute() | -| classes.py:81:6:81:20 | GSSA Variable iter | classes.py:85:6:85:21 | ControlFlowNode for Attribute() | -| classes.py:81:6:81:20 | GSSA Variable iter | classes.py:93:6:93:30 | ControlFlowNode for Attribute() | -| classes.py:81:6:81:20 | GSSA Variable iter | classes.py:94:6:94:32 | ControlFlowNode for Attribute() | -| classes.py:81:6:81:20 | GSSA Variable iter | classes.py:105:6:105:30 | ControlFlowNode for Attribute() | -| classes.py:83:1:83:5 | GSSA Variable oiter | classes.py:84:6:84:21 | ControlFlowNode for Attribute() | -| classes.py:83:1:83:5 | GSSA Variable oiter | classes.py:84:6:84:21 | GSSA Variable oiter | -| classes.py:83:9:83:24 | ControlFlowNode for Attribute() | classes.py:83:1:83:5 | GSSA Variable oiter | -| classes.py:83:9:83:24 | GSSA Variable SOURCE | classes.py:84:6:84:21 | ControlFlowNode for Attribute() | -| classes.py:83:9:83:24 | GSSA Variable SOURCE | classes.py:85:6:85:21 | ControlFlowNode for Attribute() | -| classes.py:83:9:83:24 | GSSA Variable SOURCE | classes.py:93:18:93:29 | GSSA Variable SOURCE | -| classes.py:83:9:83:24 | GSSA Variable c | classes.py:84:6:84:21 | ControlFlowNode for Attribute() | -| classes.py:83:9:83:24 | GSSA Variable c | classes.py:85:6:85:21 | ControlFlowNode for Attribute() | -| classes.py:83:9:83:24 | GSSA Variable c | classes.py:93:6:93:30 | ControlFlowNode for Attribute() | -| classes.py:83:9:83:24 | GSSA Variable c | classes.py:94:18:94:31 | GSSA Variable c | -| classes.py:84:6:84:21 | GSSA Variable oiter | classes.py:85:6:85:21 | ControlFlowNode for Attribute() | -| classes.py:84:6:84:21 | GSSA Variable oiter | classes.py:85:6:85:21 | GSSA Variable oiter | -| classes.py:85:6:85:21 | GSSA Variable oiter | classes.py:93:6:93:30 | ControlFlowNode for Attribute() | -| classes.py:85:6:85:21 | GSSA Variable oiter | classes.py:94:6:94:32 | ControlFlowNode for Attribute() | -| classes.py:85:6:85:21 | GSSA Variable oiter | classes.py:105:6:105:30 | ControlFlowNode for Attribute() | -| classes.py:93:18:93:29 | GSSA Variable SOURCE | classes.py:93:6:93:30 | ControlFlowNode for Attribute() | -| classes.py:93:18:93:29 | GSSA Variable SOURCE | classes.py:94:18:94:31 | GSSA Variable SOURCE | -| classes.py:94:18:94:31 | GSSA Variable SOURCE | classes.py:94:6:94:32 | ControlFlowNode for Attribute() | -| classes.py:94:18:94:31 | GSSA Variable SOURCE | classes.py:105:18:105:29 | GSSA Variable SOURCE | -| classes.py:94:18:94:31 | GSSA Variable c | classes.py:94:6:94:32 | ControlFlowNode for Attribute() | -| classes.py:94:18:94:31 | GSSA Variable c | classes.py:105:6:105:30 | ControlFlowNode for Attribute() | -| classes.py:105:18:105:29 | GSSA Variable SOURCE | classes.py:105:6:105:30 | ControlFlowNode for Attribute() | +| classes.py:16:1:16:6 | GSSA Variable SOURCE | classes.py:31:6:31:17 | ControlFlowNode for f() | +| classes.py:16:1:16:6 | GSSA Variable SOURCE | classes.py:31:6:31:17 | GSSA Variable SOURCE | +| classes.py:16:1:16:6 | GSSA Variable SOURCE | classes.py:31:8:31:13 | ControlFlowNode for SOURCE | +| classes.py:16:10:16:17 | ControlFlowNode for Str | classes.py:16:1:16:6 | GSSA Variable SOURCE | +| classes.py:31:6:31:17 | GSSA Variable SOURCE | classes.py:58:5:58:7 | ControlFlowNode for C() | +| classes.py:31:6:31:17 | GSSA Variable SOURCE | classes.py:64:6:64:24 | ControlFlowNode for Attribute() | +| classes.py:31:6:31:17 | GSSA Variable SOURCE | classes.py:64:6:64:24 | GSSA Variable SOURCE | +| classes.py:31:6:31:17 | GSSA Variable SOURCE | classes.py:64:15:64:20 | ControlFlowNode for SOURCE | +| classes.py:31:8:31:13 | ControlFlowNode for SOURCE | classes.py:31:6:31:17 | ControlFlowNode for f() | +| classes.py:58:1:58:1 | GSSA Variable c | classes.py:64:6:64:24 | ControlFlowNode for Attribute() | +| classes.py:58:1:58:1 | GSSA Variable c | classes.py:64:6:64:24 | GSSA Variable c | +| classes.py:58:5:58:7 | ControlFlowNode for C() | classes.py:58:1:58:1 | GSSA Variable c | +| classes.py:64:6:64:24 | GSSA Variable SOURCE | classes.py:65:6:65:27 | ControlFlowNode for Attribute() | +| classes.py:64:6:64:24 | GSSA Variable SOURCE | classes.py:65:18:65:23 | ControlFlowNode for SOURCE | +| classes.py:64:6:64:24 | GSSA Variable SOURCE | classes.py:66:6:66:27 | ControlFlowNode for func_obj() | +| classes.py:64:6:64:24 | GSSA Variable SOURCE | classes.py:73:6:73:26 | ControlFlowNode for Attribute() | +| classes.py:64:6:64:24 | GSSA Variable SOURCE | classes.py:73:6:73:26 | GSSA Variable SOURCE | +| classes.py:64:6:64:24 | GSSA Variable SOURCE | classes.py:73:20:73:25 | ControlFlowNode for SOURCE | +| classes.py:64:6:64:24 | GSSA Variable c | classes.py:65:6:65:27 | ControlFlowNode for Attribute() | +| classes.py:64:6:64:24 | GSSA Variable c | classes.py:65:6:65:27 | GSSA Variable c | +| classes.py:64:15:64:20 | ControlFlowNode for SOURCE | classes.py:64:6:64:24 | ControlFlowNode for Attribute() | +| classes.py:65:6:65:27 | GSSA Variable c | classes.py:66:6:66:27 | ControlFlowNode for func_obj() | +| classes.py:65:6:65:27 | GSSA Variable c | classes.py:66:6:66:27 | GSSA Variable c | +| classes.py:65:18:65:23 | ControlFlowNode for SOURCE | classes.py:65:6:65:27 | ControlFlowNode for Attribute() | +| classes.py:66:6:66:27 | GSSA Variable c | classes.py:73:6:73:26 | ControlFlowNode for Attribute() | +| classes.py:66:6:66:27 | GSSA Variable c | classes.py:73:6:73:26 | GSSA Variable c | +| classes.py:73:6:73:26 | GSSA Variable SOURCE | classes.py:74:6:74:26 | ControlFlowNode for Attribute() | +| classes.py:73:6:73:26 | GSSA Variable SOURCE | classes.py:74:6:74:26 | GSSA Variable SOURCE | +| classes.py:73:6:73:26 | GSSA Variable SOURCE | classes.py:74:20:74:25 | ControlFlowNode for SOURCE | +| classes.py:73:6:73:26 | GSSA Variable c | classes.py:74:6:74:26 | ControlFlowNode for Attribute() | +| classes.py:73:6:73:26 | GSSA Variable c | classes.py:75:6:75:26 | ControlFlowNode for c_func_obj() | +| classes.py:73:6:73:26 | GSSA Variable c | classes.py:85:8:85:21 | ControlFlowNode for gen() | +| classes.py:73:6:73:26 | GSSA Variable c | classes.py:86:6:86:20 | ControlFlowNode for Attribute() | +| classes.py:73:6:73:26 | GSSA Variable c | classes.py:87:8:87:22 | ControlFlowNode for Attribute() | +| classes.py:73:6:73:26 | GSSA Variable c | classes.py:89:9:89:24 | ControlFlowNode for Attribute() | +| classes.py:73:6:73:26 | GSSA Variable c | classes.py:89:9:89:24 | GSSA Variable c | +| classes.py:73:20:73:25 | ControlFlowNode for SOURCE | classes.py:73:6:73:26 | ControlFlowNode for Attribute() | +| classes.py:74:6:74:26 | GSSA Variable SOURCE | classes.py:75:6:75:26 | ControlFlowNode for c_func_obj() | +| classes.py:74:6:74:26 | GSSA Variable SOURCE | classes.py:85:8:85:21 | ControlFlowNode for gen() | +| classes.py:74:6:74:26 | GSSA Variable SOURCE | classes.py:85:8:85:21 | GSSA Variable SOURCE | +| classes.py:74:20:74:25 | ControlFlowNode for SOURCE | classes.py:74:6:74:26 | ControlFlowNode for Attribute() | +| classes.py:85:1:85:4 | GSSA Variable iter | classes.py:86:6:86:20 | ControlFlowNode for Attribute() | +| classes.py:85:1:85:4 | GSSA Variable iter | classes.py:86:6:86:20 | GSSA Variable iter | +| classes.py:85:8:85:21 | ControlFlowNode for gen() | classes.py:85:1:85:4 | GSSA Variable iter | +| classes.py:85:8:85:21 | GSSA Variable SOURCE | classes.py:86:6:86:20 | ControlFlowNode for Attribute() | +| classes.py:85:8:85:21 | GSSA Variable SOURCE | classes.py:87:8:87:22 | ControlFlowNode for Attribute() | +| classes.py:85:8:85:21 | GSSA Variable SOURCE | classes.py:89:9:89:24 | ControlFlowNode for Attribute() | +| classes.py:85:8:85:21 | GSSA Variable SOURCE | classes.py:89:9:89:24 | GSSA Variable SOURCE | +| classes.py:86:6:86:20 | GSSA Variable iter | classes.py:87:8:87:22 | ControlFlowNode for Attribute() | +| classes.py:86:6:86:20 | GSSA Variable iter | classes.py:87:8:87:22 | GSSA Variable iter | +| classes.py:87:8:87:22 | GSSA Variable iter | classes.py:89:9:89:24 | ControlFlowNode for Attribute() | +| classes.py:87:8:87:22 | GSSA Variable iter | classes.py:90:6:90:21 | ControlFlowNode for Attribute() | +| classes.py:87:8:87:22 | GSSA Variable iter | classes.py:91:8:91:23 | ControlFlowNode for Attribute() | +| classes.py:87:8:87:22 | GSSA Variable iter | classes.py:99:6:99:30 | ControlFlowNode for Attribute() | +| classes.py:87:8:87:22 | GSSA Variable iter | classes.py:100:6:100:32 | ControlFlowNode for Attribute() | +| classes.py:87:8:87:22 | GSSA Variable iter | classes.py:112:6:112:30 | ControlFlowNode for Attribute() | +| classes.py:89:1:89:5 | GSSA Variable oiter | classes.py:90:6:90:21 | ControlFlowNode for Attribute() | +| classes.py:89:1:89:5 | GSSA Variable oiter | classes.py:90:6:90:21 | GSSA Variable oiter | +| classes.py:89:9:89:24 | ControlFlowNode for Attribute() | classes.py:89:1:89:5 | GSSA Variable oiter | +| classes.py:89:9:89:24 | GSSA Variable SOURCE | classes.py:90:6:90:21 | ControlFlowNode for Attribute() | +| classes.py:89:9:89:24 | GSSA Variable SOURCE | classes.py:91:8:91:23 | ControlFlowNode for Attribute() | +| classes.py:89:9:89:24 | GSSA Variable SOURCE | classes.py:99:18:99:29 | GSSA Variable SOURCE | +| classes.py:89:9:89:24 | GSSA Variable c | classes.py:90:6:90:21 | ControlFlowNode for Attribute() | +| classes.py:89:9:89:24 | GSSA Variable c | classes.py:91:8:91:23 | ControlFlowNode for Attribute() | +| classes.py:89:9:89:24 | GSSA Variable c | classes.py:99:6:99:30 | ControlFlowNode for Attribute() | +| classes.py:89:9:89:24 | GSSA Variable c | classes.py:100:18:100:31 | GSSA Variable c | +| classes.py:90:6:90:21 | GSSA Variable oiter | classes.py:91:8:91:23 | ControlFlowNode for Attribute() | +| classes.py:90:6:90:21 | GSSA Variable oiter | classes.py:91:8:91:23 | GSSA Variable oiter | +| classes.py:91:8:91:23 | GSSA Variable oiter | classes.py:99:6:99:30 | ControlFlowNode for Attribute() | +| classes.py:91:8:91:23 | GSSA Variable oiter | classes.py:100:6:100:32 | ControlFlowNode for Attribute() | +| classes.py:91:8:91:23 | GSSA Variable oiter | classes.py:112:6:112:30 | ControlFlowNode for Attribute() | +| classes.py:99:18:99:29 | GSSA Variable SOURCE | classes.py:99:6:99:30 | ControlFlowNode for Attribute() | +| classes.py:99:18:99:29 | GSSA Variable SOURCE | classes.py:100:18:100:31 | GSSA Variable SOURCE | +| classes.py:100:18:100:31 | GSSA Variable SOURCE | classes.py:100:6:100:32 | ControlFlowNode for Attribute() | +| classes.py:100:18:100:31 | GSSA Variable SOURCE | classes.py:112:18:112:29 | GSSA Variable SOURCE | +| classes.py:100:18:100:31 | GSSA Variable c | classes.py:100:6:100:32 | ControlFlowNode for Attribute() | +| classes.py:100:18:100:31 | GSSA Variable c | classes.py:112:6:112:30 | ControlFlowNode for Attribute() | +| classes.py:112:18:112:29 | GSSA Variable SOURCE | classes.py:112:6:112:30 | ControlFlowNode for Attribute() | | test.py:35:9:35:14 | ControlFlowNode for SOURCE | test.py:36:10:36:10 | ControlFlowNode for x | | test.py:40:9:40:16 | ControlFlowNode for Str | test.py:41:10:41:10 | ControlFlowNode for x | | test.py:44:9:44:17 | ControlFlowNode for Str | test.py:45:10:45:10 | ControlFlowNode for x | @@ -87,52 +87,52 @@ edges | test.py:297:12:297:17 | ControlFlowNode for SOURCE | test.py:297:10:297:18 | ControlFlowNode for f() | | test.py:301:28:301:33 | ControlFlowNode for SOURCE | test.py:301:10:301:34 | ControlFlowNode for second() | nodes -| classes.py:13:1:13:6 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | -| classes.py:13:10:13:17 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str | -| classes.py:25:6:25:17 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() | -| classes.py:25:6:25:17 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | -| classes.py:25:8:25:13 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| classes.py:52:1:52:1 | GSSA Variable c | semmle.label | GSSA Variable c | -| classes.py:52:5:52:7 | ControlFlowNode for C() | semmle.label | ControlFlowNode for C() | -| classes.py:58:6:58:24 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| classes.py:58:6:58:24 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | -| classes.py:58:6:58:24 | GSSA Variable c | semmle.label | GSSA Variable c | -| classes.py:58:15:58:20 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| classes.py:59:6:59:27 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| classes.py:59:6:59:27 | GSSA Variable c | semmle.label | GSSA Variable c | -| classes.py:59:18:59:23 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| classes.py:60:6:60:27 | ControlFlowNode for func_obj() | semmle.label | ControlFlowNode for func_obj() | -| classes.py:60:6:60:27 | GSSA Variable c | semmle.label | GSSA Variable c | -| classes.py:67:6:67:26 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| classes.py:67:6:67:26 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | -| classes.py:67:6:67:26 | GSSA Variable c | semmle.label | GSSA Variable c | -| classes.py:67:20:67:25 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| classes.py:68:6:68:26 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| classes.py:68:6:68:26 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | -| classes.py:68:20:68:25 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| classes.py:69:6:69:26 | ControlFlowNode for c_func_obj() | semmle.label | ControlFlowNode for c_func_obj() | -| classes.py:79:1:79:4 | GSSA Variable iter | semmle.label | GSSA Variable iter | -| classes.py:79:8:79:21 | ControlFlowNode for gen() | semmle.label | ControlFlowNode for gen() | -| classes.py:79:8:79:21 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | -| classes.py:80:6:80:20 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| classes.py:80:6:80:20 | GSSA Variable iter | semmle.label | GSSA Variable iter | -| classes.py:81:6:81:20 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| classes.py:81:6:81:20 | GSSA Variable iter | semmle.label | GSSA Variable iter | -| classes.py:83:1:83:5 | GSSA Variable oiter | semmle.label | GSSA Variable oiter | -| classes.py:83:9:83:24 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| classes.py:83:9:83:24 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | -| classes.py:83:9:83:24 | GSSA Variable c | semmle.label | GSSA Variable c | -| classes.py:84:6:84:21 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| classes.py:84:6:84:21 | GSSA Variable oiter | semmle.label | GSSA Variable oiter | -| classes.py:85:6:85:21 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| classes.py:85:6:85:21 | GSSA Variable oiter | semmle.label | GSSA Variable oiter | -| classes.py:93:6:93:30 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| classes.py:93:18:93:29 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | -| classes.py:94:6:94:32 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| classes.py:94:18:94:31 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | -| classes.py:94:18:94:31 | GSSA Variable c | semmle.label | GSSA Variable c | -| classes.py:105:6:105:30 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| classes.py:105:18:105:29 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| classes.py:16:1:16:6 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| classes.py:16:10:16:17 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str | +| classes.py:31:6:31:17 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() | +| classes.py:31:6:31:17 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| classes.py:31:8:31:13 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| classes.py:58:1:58:1 | GSSA Variable c | semmle.label | GSSA Variable c | +| classes.py:58:5:58:7 | ControlFlowNode for C() | semmle.label | ControlFlowNode for C() | +| classes.py:64:6:64:24 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| classes.py:64:6:64:24 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| classes.py:64:6:64:24 | GSSA Variable c | semmle.label | GSSA Variable c | +| classes.py:64:15:64:20 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| classes.py:65:6:65:27 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| classes.py:65:6:65:27 | GSSA Variable c | semmle.label | GSSA Variable c | +| classes.py:65:18:65:23 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| classes.py:66:6:66:27 | ControlFlowNode for func_obj() | semmle.label | ControlFlowNode for func_obj() | +| classes.py:66:6:66:27 | GSSA Variable c | semmle.label | GSSA Variable c | +| classes.py:73:6:73:26 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| classes.py:73:6:73:26 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| classes.py:73:6:73:26 | GSSA Variable c | semmle.label | GSSA Variable c | +| classes.py:73:20:73:25 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| classes.py:74:6:74:26 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| classes.py:74:6:74:26 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| classes.py:74:20:74:25 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| classes.py:75:6:75:26 | ControlFlowNode for c_func_obj() | semmle.label | ControlFlowNode for c_func_obj() | +| classes.py:85:1:85:4 | GSSA Variable iter | semmle.label | GSSA Variable iter | +| classes.py:85:8:85:21 | ControlFlowNode for gen() | semmle.label | ControlFlowNode for gen() | +| classes.py:85:8:85:21 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| classes.py:86:6:86:20 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| classes.py:86:6:86:20 | GSSA Variable iter | semmle.label | GSSA Variable iter | +| classes.py:87:8:87:22 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| classes.py:87:8:87:22 | GSSA Variable iter | semmle.label | GSSA Variable iter | +| classes.py:89:1:89:5 | GSSA Variable oiter | semmle.label | GSSA Variable oiter | +| classes.py:89:9:89:24 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| classes.py:89:9:89:24 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| classes.py:89:9:89:24 | GSSA Variable c | semmle.label | GSSA Variable c | +| classes.py:90:6:90:21 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| classes.py:90:6:90:21 | GSSA Variable oiter | semmle.label | GSSA Variable oiter | +| classes.py:91:8:91:23 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| classes.py:91:8:91:23 | GSSA Variable oiter | semmle.label | GSSA Variable oiter | +| classes.py:99:6:99:30 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| classes.py:99:18:99:29 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| classes.py:100:6:100:32 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| classes.py:100:18:100:31 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| classes.py:100:18:100:31 | GSSA Variable c | semmle.label | GSSA Variable c | +| classes.py:112:6:112:30 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| classes.py:112:18:112:29 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | | test.py:35:9:35:14 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:36:10:36:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | | test.py:40:9:40:16 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str | @@ -152,25 +152,25 @@ nodes | test.py:301:10:301:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | | test.py:301:28:301:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | #select -| classes.py:25:6:25:17 | ControlFlowNode for f() | classes.py:13:10:13:17 | ControlFlowNode for Str | classes.py:25:6:25:17 | ControlFlowNode for f() | | -| classes.py:25:6:25:17 | ControlFlowNode for f() | classes.py:25:8:25:13 | ControlFlowNode for SOURCE | classes.py:25:6:25:17 | ControlFlowNode for f() | | -| classes.py:58:6:58:24 | ControlFlowNode for Attribute() | classes.py:13:10:13:17 | ControlFlowNode for Str | classes.py:58:6:58:24 | ControlFlowNode for Attribute() | | -| classes.py:58:6:58:24 | ControlFlowNode for Attribute() | classes.py:58:15:58:20 | ControlFlowNode for SOURCE | classes.py:58:6:58:24 | ControlFlowNode for Attribute() | | -| classes.py:59:6:59:27 | ControlFlowNode for Attribute() | classes.py:13:10:13:17 | ControlFlowNode for Str | classes.py:59:6:59:27 | ControlFlowNode for Attribute() | | -| classes.py:59:6:59:27 | ControlFlowNode for Attribute() | classes.py:59:18:59:23 | ControlFlowNode for SOURCE | classes.py:59:6:59:27 | ControlFlowNode for Attribute() | | -| classes.py:60:6:60:27 | ControlFlowNode for func_obj() | classes.py:13:10:13:17 | ControlFlowNode for Str | classes.py:60:6:60:27 | ControlFlowNode for func_obj() | | -| classes.py:67:6:67:26 | ControlFlowNode for Attribute() | classes.py:13:10:13:17 | ControlFlowNode for Str | classes.py:67:6:67:26 | ControlFlowNode for Attribute() | | -| classes.py:67:6:67:26 | ControlFlowNode for Attribute() | classes.py:67:20:67:25 | ControlFlowNode for SOURCE | classes.py:67:6:67:26 | ControlFlowNode for Attribute() | | -| classes.py:68:6:68:26 | ControlFlowNode for Attribute() | classes.py:13:10:13:17 | ControlFlowNode for Str | classes.py:68:6:68:26 | ControlFlowNode for Attribute() | | -| classes.py:68:6:68:26 | ControlFlowNode for Attribute() | classes.py:68:20:68:25 | ControlFlowNode for SOURCE | classes.py:68:6:68:26 | ControlFlowNode for Attribute() | | -| classes.py:69:6:69:26 | ControlFlowNode for c_func_obj() | classes.py:13:10:13:17 | ControlFlowNode for Str | classes.py:69:6:69:26 | ControlFlowNode for c_func_obj() | | -| classes.py:80:6:80:20 | ControlFlowNode for Attribute() | classes.py:13:10:13:17 | ControlFlowNode for Str | classes.py:80:6:80:20 | ControlFlowNode for Attribute() | | -| classes.py:81:6:81:20 | ControlFlowNode for Attribute() | classes.py:13:10:13:17 | ControlFlowNode for Str | classes.py:81:6:81:20 | ControlFlowNode for Attribute() | | -| classes.py:84:6:84:21 | ControlFlowNode for Attribute() | classes.py:13:10:13:17 | ControlFlowNode for Str | classes.py:84:6:84:21 | ControlFlowNode for Attribute() | | -| classes.py:85:6:85:21 | ControlFlowNode for Attribute() | classes.py:13:10:13:17 | ControlFlowNode for Str | classes.py:85:6:85:21 | ControlFlowNode for Attribute() | | -| classes.py:93:6:93:30 | ControlFlowNode for Attribute() | classes.py:13:10:13:17 | ControlFlowNode for Str | classes.py:93:6:93:30 | ControlFlowNode for Attribute() | | -| classes.py:94:6:94:32 | ControlFlowNode for Attribute() | classes.py:13:10:13:17 | ControlFlowNode for Str | classes.py:94:6:94:32 | ControlFlowNode for Attribute() | | -| classes.py:105:6:105:30 | ControlFlowNode for Attribute() | classes.py:13:10:13:17 | ControlFlowNode for Str | classes.py:105:6:105:30 | ControlFlowNode for Attribute() | | +| classes.py:31:6:31:17 | ControlFlowNode for f() | classes.py:16:10:16:17 | ControlFlowNode for Str | classes.py:31:6:31:17 | ControlFlowNode for f() | | +| classes.py:31:6:31:17 | ControlFlowNode for f() | classes.py:31:8:31:13 | ControlFlowNode for SOURCE | classes.py:31:6:31:17 | ControlFlowNode for f() | | +| classes.py:64:6:64:24 | ControlFlowNode for Attribute() | classes.py:16:10:16:17 | ControlFlowNode for Str | classes.py:64:6:64:24 | ControlFlowNode for Attribute() | | +| classes.py:64:6:64:24 | ControlFlowNode for Attribute() | classes.py:64:15:64:20 | ControlFlowNode for SOURCE | classes.py:64:6:64:24 | ControlFlowNode for Attribute() | | +| classes.py:65:6:65:27 | ControlFlowNode for Attribute() | classes.py:16:10:16:17 | ControlFlowNode for Str | classes.py:65:6:65:27 | ControlFlowNode for Attribute() | | +| classes.py:65:6:65:27 | ControlFlowNode for Attribute() | classes.py:65:18:65:23 | ControlFlowNode for SOURCE | classes.py:65:6:65:27 | ControlFlowNode for Attribute() | | +| classes.py:66:6:66:27 | ControlFlowNode for func_obj() | classes.py:16:10:16:17 | ControlFlowNode for Str | classes.py:66:6:66:27 | ControlFlowNode for func_obj() | | +| classes.py:73:6:73:26 | ControlFlowNode for Attribute() | classes.py:16:10:16:17 | ControlFlowNode for Str | classes.py:73:6:73:26 | ControlFlowNode for Attribute() | | +| classes.py:73:6:73:26 | ControlFlowNode for Attribute() | classes.py:73:20:73:25 | ControlFlowNode for SOURCE | classes.py:73:6:73:26 | ControlFlowNode for Attribute() | | +| classes.py:74:6:74:26 | ControlFlowNode for Attribute() | classes.py:16:10:16:17 | ControlFlowNode for Str | classes.py:74:6:74:26 | ControlFlowNode for Attribute() | | +| classes.py:74:6:74:26 | ControlFlowNode for Attribute() | classes.py:74:20:74:25 | ControlFlowNode for SOURCE | classes.py:74:6:74:26 | ControlFlowNode for Attribute() | | +| classes.py:75:6:75:26 | ControlFlowNode for c_func_obj() | classes.py:16:10:16:17 | ControlFlowNode for Str | classes.py:75:6:75:26 | ControlFlowNode for c_func_obj() | | +| classes.py:86:6:86:20 | ControlFlowNode for Attribute() | classes.py:16:10:16:17 | ControlFlowNode for Str | classes.py:86:6:86:20 | ControlFlowNode for Attribute() | | +| classes.py:87:8:87:22 | ControlFlowNode for Attribute() | classes.py:16:10:16:17 | ControlFlowNode for Str | classes.py:87:8:87:22 | ControlFlowNode for Attribute() | | +| classes.py:90:6:90:21 | ControlFlowNode for Attribute() | classes.py:16:10:16:17 | ControlFlowNode for Str | classes.py:90:6:90:21 | ControlFlowNode for Attribute() | | +| classes.py:91:8:91:23 | ControlFlowNode for Attribute() | classes.py:16:10:16:17 | ControlFlowNode for Str | classes.py:91:8:91:23 | ControlFlowNode for Attribute() | | +| classes.py:99:6:99:30 | ControlFlowNode for Attribute() | classes.py:16:10:16:17 | ControlFlowNode for Str | classes.py:99:6:99:30 | ControlFlowNode for Attribute() | | +| classes.py:100:6:100:32 | ControlFlowNode for Attribute() | classes.py:16:10:16:17 | ControlFlowNode for Str | classes.py:100:6:100:32 | ControlFlowNode for Attribute() | | +| classes.py:112:6:112:30 | ControlFlowNode for Attribute() | classes.py:16:10:16:17 | ControlFlowNode for Str | classes.py:112:6:112:30 | ControlFlowNode for Attribute() | | | test.py:36:10:36:10 | ControlFlowNode for x | test.py:35:9:35:14 | ControlFlowNode for SOURCE | test.py:36:10:36:10 | ControlFlowNode for x | | | test.py:41:10:41:10 | ControlFlowNode for x | test.py:40:9:40:16 | ControlFlowNode for Str | test.py:41:10:41:10 | ControlFlowNode for x | | | test.py:45:10:45:10 | ControlFlowNode for x | test.py:44:9:44:17 | ControlFlowNode for Str | test.py:45:10:45:10 | ControlFlowNode for x | | From a89624698d3fccffa34b4cab8c819f7ad0bc0764 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Wed, 5 Aug 2020 14:28:28 +0200 Subject: [PATCH 010/133] Python: format ql --- .../src/experimental/dataflow/internal/DataFlowPrivate.qll | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/python/ql/src/experimental/dataflow/internal/DataFlowPrivate.qll b/python/ql/src/experimental/dataflow/internal/DataFlowPrivate.qll index 4221c90cf74..1f46fd341e9 100644 --- a/python/ql/src/experimental/dataflow/internal/DataFlowPrivate.qll +++ b/python/ql/src/experimental/dataflow/internal/DataFlowPrivate.qll @@ -150,12 +150,13 @@ class DataFlowClassValue extends DataFlowCallable, TClassValue { override Scope getScope() { result = c.getScope() } - override NameNode getParameter(int n) { result.getNode() = c.getScope().getInitMethod().getArg(n+1).asName() } + override NameNode getParameter(int n) { + result.getNode() = c.getScope().getInitMethod().getArg(n + 1).asName() + } override string getName() { result = c.getName() } } - /** Represents a call to a callable */ class DataFlowCall extends CallNode { DataFlowCallable callable; From e642808a7576ec49226932bce70d55f84e53b9a5 Mon Sep 17 00:00:00 2001 From: yoff Date: Wed, 5 Aug 2020 15:12:27 +0200 Subject: [PATCH 011/133] Update python/ql/test/experimental/dataflow/coverage/classes.py Co-authored-by: intrigus-lgtm <60750685+intrigus-lgtm@users.noreply.github.com> --- python/ql/test/experimental/dataflow/coverage/classes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/test/experimental/dataflow/coverage/classes.py b/python/ql/test/experimental/dataflow/coverage/classes.py index e543bede80c..d94a5922199 100644 --- a/python/ql/test/experimental/dataflow/coverage/classes.py +++ b/python/ql/test/experimental/dataflow/coverage/classes.py @@ -5,7 +5,7 @@ # These tests should cover all the class calls that we hope to support. # It is based on https://docs.python.org/3/reference/datamodel.html, and headings refer there. # -# Intended sources should be the variable `SOURCE` and intended sinks should be. +# Intended sources should be the variable `SOURCE` and intended sinks should be # arguments to the function `SINK` (see python/ql/test/experimental/dataflow/testConfig.qll). # # Functions whose name ends with "_with_local_flow" will also be tested for local flow. From 614103c3b6bcea797cdeaeda2733862fa5cad0ec Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Thu, 6 Aug 2020 15:40:41 +0200 Subject: [PATCH 012/133] Python: Test calls rather than flows --- .../experimental/dataflow/basic/callGraph.ql | 2 +- .../dataflow/{basic => }/callGraphConfig.qll | 0 .../experimental/dataflow/coverage/classes.py | 12 +-- .../coverage/classesCallGraph.expected | 81 +++++++++++++++++++ .../dataflow/coverage/classesCallGraph.ql | 10 +++ 5 files changed, 98 insertions(+), 7 deletions(-) rename python/ql/test/experimental/dataflow/{basic => }/callGraphConfig.qll (100%) create mode 100644 python/ql/test/experimental/dataflow/coverage/classesCallGraph.expected create mode 100644 python/ql/test/experimental/dataflow/coverage/classesCallGraph.ql diff --git a/python/ql/test/experimental/dataflow/basic/callGraph.ql b/python/ql/test/experimental/dataflow/basic/callGraph.ql index 53747b31739..2e8d6956c70 100644 --- a/python/ql/test/experimental/dataflow/basic/callGraph.ql +++ b/python/ql/test/experimental/dataflow/basic/callGraph.ql @@ -1,4 +1,4 @@ -import callGraphConfig +import experimental.dataflow.callGraphConfig from DataFlow::Node source, DataFlow::Node sink where exists(CallGraphConfig cfg | cfg.hasFlow(source, sink)) diff --git a/python/ql/test/experimental/dataflow/basic/callGraphConfig.qll b/python/ql/test/experimental/dataflow/callGraphConfig.qll similarity index 100% rename from python/ql/test/experimental/dataflow/basic/callGraphConfig.qll rename to python/ql/test/experimental/dataflow/callGraphConfig.qll diff --git a/python/ql/test/experimental/dataflow/coverage/classes.py b/python/ql/test/experimental/dataflow/coverage/classes.py index d94a5922199..424ff1dcdb4 100644 --- a/python/ql/test/experimental/dataflow/coverage/classes.py +++ b/python/ql/test/experimental/dataflow/coverage/classes.py @@ -128,6 +128,10 @@ SINK(asyncio.run(agen(SOURCE))) # Class Instances # Instances of arbitrary classes can be made callable by defining a __call__() method in their class. +# If a class sets __iter__() to None, calling iter() on its instances will raise a TypeError (without falling back to __getitem__()). + +# 3.3.1. Basic customization + class Customized: a = NONSOURCE @@ -140,19 +144,15 @@ class Customized: def __init__(self): self.b = SOURCE +# object.__new__(cls[, ...]) +# object.__init__(self[, ...]) customized = Customized() SINK(Customized.a) SINK_F(Customized.b) SINK(customized.a) SINK(customized.b) -# def __del__(self): -# If a class sets __iter__() to None, calling iter() on its instances will raise a TypeError (without falling back to __getitem__()). - -# 3.3.1. Basic customization -# object.__new__(cls[, ...]) -# object.__init__(self[, ...]) # object.__del__(self) # object.__repr__(self) # object.__str__(self)¶ diff --git a/python/ql/test/experimental/dataflow/coverage/classesCallGraph.expected b/python/ql/test/experimental/dataflow/coverage/classesCallGraph.expected new file mode 100644 index 00000000000..83773c878c7 --- /dev/null +++ b/python/ql/test/experimental/dataflow/coverage/classesCallGraph.expected @@ -0,0 +1,81 @@ +| classes.py:29:10:29:10 | ControlFlowNode for a | classes.py:17:10:17:10 | SSA variable x | +| classes.py:29:10:29:10 | ControlFlowNode for a | classes.py:31:6:31:17 | ControlFlowNode for f() | +| classes.py:31:6:31:17 | ControlFlowNode for f() | classes.py:17:10:17:10 | SSA variable x | +| classes.py:31:6:31:17 | ControlFlowNode for f() | classes.py:31:6:31:17 | ControlFlowNode for f() | +| classes.py:31:8:31:13 | ControlFlowNode for SOURCE | classes.py:17:10:17:10 | SSA variable x | +| classes.py:31:8:31:13 | ControlFlowNode for SOURCE | classes.py:28:7:28:7 | SSA variable a | +| classes.py:31:8:31:13 | ControlFlowNode for SOURCE | classes.py:31:6:31:17 | ControlFlowNode for f() | +| classes.py:31:16:31:16 | ControlFlowNode for IntegerLiteral | classes.py:28:10:28:10 | SSA variable b | +| classes.py:39:16:39:16 | ControlFlowNode for x | classes.py:17:10:17:10 | SSA variable x | +| classes.py:39:16:39:16 | ControlFlowNode for x | classes.py:64:6:64:24 | ControlFlowNode for Attribute() | +| classes.py:39:16:39:16 | ControlFlowNode for x | classes.py:65:6:65:27 | ControlFlowNode for Attribute() | +| classes.py:43:16:43:16 | ControlFlowNode for x | classes.py:17:10:17:10 | SSA variable x | +| classes.py:43:16:43:16 | ControlFlowNode for x | classes.py:73:6:73:26 | ControlFlowNode for Attribute() | +| classes.py:43:16:43:16 | ControlFlowNode for x | classes.py:74:6:74:26 | ControlFlowNode for Attribute() | +| classes.py:56:14:56:14 | ControlFlowNode for x | classes.py:100:18:100:31 | ControlFlowNode for Attribute() | +| classes.py:64:6:64:24 | ControlFlowNode for Attribute() | classes.py:17:10:17:10 | SSA variable x | +| classes.py:64:6:64:24 | ControlFlowNode for Attribute() | classes.py:64:6:64:24 | ControlFlowNode for Attribute() | +| classes.py:64:15:64:20 | ControlFlowNode for SOURCE | classes.py:17:10:17:10 | SSA variable x | +| classes.py:64:15:64:20 | ControlFlowNode for SOURCE | classes.py:37:16:37:19 | SSA variable self | +| classes.py:64:15:64:20 | ControlFlowNode for SOURCE | classes.py:37:22:37:22 | SSA variable x | +| classes.py:64:15:64:20 | ControlFlowNode for SOURCE | classes.py:64:6:64:24 | ControlFlowNode for Attribute() | +| classes.py:64:23:64:23 | ControlFlowNode for C | classes.py:17:10:17:10 | SSA variable x | +| classes.py:64:23:64:23 | ControlFlowNode for C | classes.py:37:22:37:22 | SSA variable x | +| classes.py:64:23:64:23 | ControlFlowNode for C | classes.py:37:25:37:27 | SSA variable cls | +| classes.py:64:23:64:23 | ControlFlowNode for C | classes.py:64:6:64:24 | ControlFlowNode for Attribute() | +| classes.py:65:6:65:27 | ControlFlowNode for Attribute() | classes.py:17:10:17:10 | SSA variable x | +| classes.py:65:6:65:27 | ControlFlowNode for Attribute() | classes.py:65:6:65:27 | ControlFlowNode for Attribute() | +| classes.py:65:15:65:15 | ControlFlowNode for c | classes.py:37:16:37:19 | SSA variable self | +| classes.py:65:18:65:23 | ControlFlowNode for SOURCE | classes.py:17:10:17:10 | SSA variable x | +| classes.py:65:18:65:23 | ControlFlowNode for SOURCE | classes.py:37:22:37:22 | SSA variable x | +| classes.py:65:18:65:23 | ControlFlowNode for SOURCE | classes.py:65:6:65:27 | ControlFlowNode for Attribute() | +| classes.py:65:26:65:26 | ControlFlowNode for C | classes.py:37:25:37:27 | SSA variable cls | +| classes.py:66:6:66:27 | ControlFlowNode for func_obj() | classes.py:17:10:17:10 | SSA variable x | +| classes.py:66:6:66:27 | ControlFlowNode for func_obj() | classes.py:66:6:66:27 | ControlFlowNode for func_obj() | +| classes.py:73:6:73:26 | ControlFlowNode for Attribute() | classes.py:17:10:17:10 | SSA variable x | +| classes.py:73:6:73:26 | ControlFlowNode for Attribute() | classes.py:73:6:73:26 | ControlFlowNode for Attribute() | +| classes.py:73:20:73:25 | ControlFlowNode for SOURCE | classes.py:17:10:17:10 | SSA variable x | +| classes.py:73:20:73:25 | ControlFlowNode for SOURCE | classes.py:42:21:42:23 | SSA variable cls | +| classes.py:73:20:73:25 | ControlFlowNode for SOURCE | classes.py:42:26:42:26 | SSA variable x | +| classes.py:73:20:73:25 | ControlFlowNode for SOURCE | classes.py:73:6:73:26 | ControlFlowNode for Attribute() | +| classes.py:74:6:74:26 | ControlFlowNode for Attribute() | classes.py:17:10:17:10 | SSA variable x | +| classes.py:74:6:74:26 | ControlFlowNode for Attribute() | classes.py:74:6:74:26 | ControlFlowNode for Attribute() | +| classes.py:74:20:74:25 | ControlFlowNode for SOURCE | classes.py:17:10:17:10 | SSA variable x | +| classes.py:74:20:74:25 | ControlFlowNode for SOURCE | classes.py:42:21:42:23 | SSA variable cls | +| classes.py:74:20:74:25 | ControlFlowNode for SOURCE | classes.py:42:26:42:26 | SSA variable x | +| classes.py:74:20:74:25 | ControlFlowNode for SOURCE | classes.py:74:6:74:26 | ControlFlowNode for Attribute() | +| classes.py:75:6:75:26 | ControlFlowNode for c_func_obj() | classes.py:17:10:17:10 | SSA variable x | +| classes.py:75:6:75:26 | ControlFlowNode for c_func_obj() | classes.py:75:6:75:26 | ControlFlowNode for c_func_obj() | +| classes.py:85:12:85:17 | ControlFlowNode for SOURCE | classes.py:79:9:79:9 | SSA variable x | +| classes.py:85:20:85:20 | ControlFlowNode for IntegerLiteral | classes.py:79:12:79:16 | SSA variable count | +| classes.py:86:6:86:20 | ControlFlowNode for Attribute() | classes.py:17:10:17:10 | SSA variable x | +| classes.py:86:6:86:20 | ControlFlowNode for Attribute() | classes.py:86:6:86:20 | ControlFlowNode for Attribute() | +| classes.py:87:8:87:22 | ControlFlowNode for Attribute() | classes.py:20:12:20:12 | SSA variable x | +| classes.py:87:8:87:22 | ControlFlowNode for Attribute() | classes.py:87:8:87:22 | ControlFlowNode for Attribute() | +| classes.py:89:15:89:20 | ControlFlowNode for SOURCE | classes.py:49:13:49:16 | SSA variable self | +| classes.py:89:15:89:20 | ControlFlowNode for SOURCE | classes.py:49:19:49:19 | SSA variable x | +| classes.py:89:23:89:23 | ControlFlowNode for IntegerLiteral | classes.py:49:19:49:19 | SSA variable x | +| classes.py:89:23:89:23 | ControlFlowNode for IntegerLiteral | classes.py:49:22:49:26 | SSA variable count | +| classes.py:90:6:90:21 | ControlFlowNode for Attribute() | classes.py:17:10:17:10 | SSA variable x | +| classes.py:90:6:90:21 | ControlFlowNode for Attribute() | classes.py:90:6:90:21 | ControlFlowNode for Attribute() | +| classes.py:91:8:91:23 | ControlFlowNode for Attribute() | classes.py:20:12:20:12 | SSA variable x | +| classes.py:91:8:91:23 | ControlFlowNode for Attribute() | classes.py:91:8:91:23 | ControlFlowNode for Attribute() | +| classes.py:96:10:96:10 | ControlFlowNode for x | classes.py:99:18:99:29 | ControlFlowNode for coro() | +| classes.py:99:6:99:30 | ControlFlowNode for Attribute() | classes.py:17:10:17:10 | SSA variable x | +| classes.py:99:6:99:30 | ControlFlowNode for Attribute() | classes.py:99:6:99:30 | ControlFlowNode for Attribute() | +| classes.py:99:23:99:28 | ControlFlowNode for SOURCE | classes.py:95:16:95:16 | SSA variable x | +| classes.py:99:23:99:28 | ControlFlowNode for SOURCE | classes.py:99:18:99:29 | ControlFlowNode for coro() | +| classes.py:100:6:100:32 | ControlFlowNode for Attribute() | classes.py:17:10:17:10 | SSA variable x | +| classes.py:100:6:100:32 | ControlFlowNode for Attribute() | classes.py:100:6:100:32 | ControlFlowNode for Attribute() | +| classes.py:100:25:100:30 | ControlFlowNode for SOURCE | classes.py:55:20:55:23 | SSA variable self | +| classes.py:100:25:100:30 | ControlFlowNode for SOURCE | classes.py:55:26:55:26 | SSA variable x | +| classes.py:100:25:100:30 | ControlFlowNode for SOURCE | classes.py:100:18:100:31 | ControlFlowNode for Attribute() | +| classes.py:110:10:110:16 | ControlFlowNode for Await | classes.py:112:18:112:29 | ControlFlowNode for agen() | +| classes.py:112:6:112:30 | ControlFlowNode for Attribute() | classes.py:17:10:17:10 | SSA variable x | +| classes.py:112:6:112:30 | ControlFlowNode for Attribute() | classes.py:112:6:112:30 | ControlFlowNode for Attribute() | +| classes.py:112:23:112:28 | ControlFlowNode for SOURCE | classes.py:108:16:108:16 | SSA variable x | +| classes.py:142:12:142:31 | ControlFlowNode for Attribute() | classes.py:142:12:142:31 | ControlFlowNode for Attribute() | +| classes.py:150:6:150:17 | ControlFlowNode for Attribute | classes.py:17:10:17:10 | SSA variable x | +| classes.py:151:8:151:19 | ControlFlowNode for Attribute | classes.py:20:12:20:12 | SSA variable x | +| classes.py:152:6:152:17 | ControlFlowNode for Attribute | classes.py:17:10:17:10 | SSA variable x | +| classes.py:153:6:153:17 | ControlFlowNode for Attribute | classes.py:17:10:17:10 | SSA variable x | diff --git a/python/ql/test/experimental/dataflow/coverage/classesCallGraph.ql b/python/ql/test/experimental/dataflow/coverage/classesCallGraph.ql new file mode 100644 index 00000000000..240085be57f --- /dev/null +++ b/python/ql/test/experimental/dataflow/coverage/classesCallGraph.ql @@ -0,0 +1,10 @@ +import experimental.dataflow.callGraphConfig + +from DataFlow::Node source, DataFlow::Node sink +where + source.getLocation().getFile().getBaseName() = "classes.py" and + sink.getLocation().getFile().getBaseName() = "classes.py" and + exists(CallGraphConfig cfg | cfg.hasFlow(source, sink)) +select source, sink + +// Rewrite this to just have 1-step paths? From 3db1ceeb70cbe8dc04dfa90ecd222d9f16f8df73 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Thu, 6 Aug 2020 15:42:14 +0200 Subject: [PATCH 013/133] Python: format ql --- .../ql/test/experimental/dataflow/coverage/classesCallGraph.ql | 1 - 1 file changed, 1 deletion(-) diff --git a/python/ql/test/experimental/dataflow/coverage/classesCallGraph.ql b/python/ql/test/experimental/dataflow/coverage/classesCallGraph.ql index 240085be57f..0416cc7f6ea 100644 --- a/python/ql/test/experimental/dataflow/coverage/classesCallGraph.ql +++ b/python/ql/test/experimental/dataflow/coverage/classesCallGraph.ql @@ -6,5 +6,4 @@ where sink.getLocation().getFile().getBaseName() = "classes.py" and exists(CallGraphConfig cfg | cfg.hasFlow(source, sink)) select source, sink - // Rewrite this to just have 1-step paths? From d84294df3d0253d588736868c4d18b316c4b7711 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Fri, 7 Aug 2020 20:07:02 +0200 Subject: [PATCH 014/133] Python: Check that tests are valid --- .../experimental/dataflow/coverage/classes.py | 1145 +++++++++++++++-- .../experimental/dataflow/coverage/test.py | 20 +- .../dataflow/coverage/validTest.py | 33 + 3 files changed, 1105 insertions(+), 93 deletions(-) create mode 100644 python/ql/test/experimental/dataflow/coverage/validTest.py diff --git a/python/ql/test/experimental/dataflow/coverage/classes.py b/python/ql/test/experimental/dataflow/coverage/classes.py index 424ff1dcdb4..3cbe6e97791 100644 --- a/python/ql/test/experimental/dataflow/coverage/classes.py +++ b/python/ql/test/experimental/dataflow/coverage/classes.py @@ -9,16 +9,28 @@ # arguments to the function `SINK` (see python/ql/test/experimental/dataflow/testConfig.qll). # # Functions whose name ends with "_with_local_flow" will also be tested for local flow. +# +# All functions starting with "test_" should run and print `"OK"`. +# This can be checked by running validTest.py. - -# These are included so that we can easily evaluate the test code. +# These are defined so that we can evaluate the test code. NONSOURCE = "not a source" SOURCE = "source" + +def is_source(x): + return x == "source" or x == b"source" or x == 42 or x == 42.0 or x == 42j + def SINK(x): - print(x) + if is_source(x): + print("OK") + else: + print("Unexpected flow", x) def SINK_F(x): - print("Unexpected flow: ", x) + if is_source(x): + print("Unexpected flow", x) + else: + print("OK") # Callable types # These are the types to which the function call operation (see section Calls) can be applied: @@ -84,11 +96,11 @@ def gen(x, count): iter = gen(SOURCE, 1) SINK(iter.__next__()) -SINK_F(iter.__next__()) # throws StopIteration, FP +# SINK_F(iter.__next__()) # throws StopIteration, FP oiter = c.gen(SOURCE, 1) SINK(oiter.__next__()) -SINK_F(oiter.__next__()) # throws StopIteration, FP +# SINK_F(oiter.__next__()) # throws StopIteration, FP # Coroutine functions # A function or method which is defined using async def is called a coroutine function. Such a function, when called, returns a coroutine object. It may contain await expressions, as well as async with and async for statements. See also the Coroutine Objects section. @@ -144,42 +156,305 @@ class Customized: def __init__(self): self.b = SOURCE -# object.__new__(cls[, ...]) -# object.__init__(self[, ...]) +# testing __new__ and __init__ customized = Customized() SINK(Customized.a) SINK_F(Customized.b) SINK(customized.a) SINK(customized.b) +def OK(): + print("OK") + +# object.__new__(cls[, ...]) +class With_new: + + def __new__(cls): + OK() + return super().__new__(cls) + +def test_new(): + with_new = With_new() + +# object.__init__(self[, ...]) +class With_init: + + def __init__(self): + OK() + +def test_init(): + with_init = With_init() # object.__del__(self) +class With_del: + + def __del__(self): + OK() + +def test_del(): + with_del = With_del() + del with_del + # object.__repr__(self) -# object.__str__(self)¶ +class With_repr: + + def __repr__(self): + OK() + return "With_repr()" + +def test_repr(): + with_repr = With_repr() + repr(with_repr) + +# object.__str__(self) +class With_str: + + def __str__(self): + OK() + return "Awesome" + +def test_str(): + with_str = With_str() + str(with_str) + # object.__bytes__(self) +class With_bytes: + + def __bytes__(self): + OK() + return b"Awesome" + +def test_bytes(): + with_bytes = With_bytes() + bytes(with_bytes) + # object.__format__(self, format_spec) +class With_format: + + def __format__(self, format_spec): + OK() + return "Awesome" + +def test_format(): + with_format = With_format() + format(with_format) + +def test_format_str(): + with_format = With_format() + "{0}".format(with_format) + +def test_format_fstr(): + with_format = With_format() + f"{with_format}" + # object.__lt__(self, other) +class With_lt: + + def __lt__(self, other): + OK() + return "" + +def test_lt(): + with_lt = With_lt() + with_lt < with_lt + # object.__le__(self, other) +class With_le: + + def __le__(self, other): + OK() + return "" + +def test_le(): + with_le = With_le() + with_le <= with_le + # object.__eq__(self, other) +class With_eq: + + def __eq__(self, other): + OK() + return "" + +def test_eq(): + with_eq = With_eq() + with_eq == with_eq + # object.__ne__(self, other) +class With_ne: + + def __ne__(self, other): + OK() + return "" + +def test_ne(): + with_ne = With_ne() + with_ne != with_ne + # object.__gt__(self, other) +class With_gt: + + def __gt__(self, other): + OK() + return "" + +def test_gt(): + with_gt = With_gt() + with_gt > with_gt + # object.__ge__(self, other) +class With_ge: + + def __ge__(self, other): + OK() + return "" + +def test_ge(): + with_ge = With_ge() + with_ge >= with_ge + # object.__hash__(self) +class With_hash: + + def __hash__(self): + OK() + return 0 + +def test_hash(): + with_hash = With_hash() + hash(with_hash) + +def test_hash_set(): + with_hash = With_hash() + len(set([with_hash])) + +def test_hash_frozenset(): + with_hash = With_hash() + len(frozenset([with_hash])) + +def test_hash_dict(): + with_hash = With_hash() + len(dict({with_hash: 0})) + # object.__bool__(self) -# len +class With_bool: + + def __bool__(self): + OK() + return True + +def test_bool(): + with_bool = With_bool() + bool(with_bool) + +def test_bool_if(): + with_bool = With_bool() + if with_bool: + pass # 3.3.2. Customizing attribute access # object.__getattr__(self, name) +class With_getattr: + + def __getattr__(self, name): + OK() + return "" + +def test_getattr(): + with_getattr = With_getattr() + with_getattr.foo + # object.__getattribute__(self, name) +class With_getattribute: + + def __getattribute__(self, name): + OK() + return "" + +def test_getattribute(): + with_getattribute = With_getattribute() + with_getattribute.foo + # object.__setattr__(self, name, value) +class With_setattr: + + def __setattr__(self, name, value): + OK() + +def test_setattr(): + with_setattr = With_setattr() + with_setattr.foo = "" + # object.__delattr__(self, name) +class With_delattr: + + def __delattr__(self, name): + OK() + +def test_delattr(): + with_delattr = With_delattr() + del with_delattr.foo + # object.__dir__(self) +class With_dir: + + def __dir__(self): + OK() + return [] + +def test_dir(): + with_dir = With_dir() + dir(with_dir) + # 3.3.2.2. Implementing Descriptors +class Owner: + pass + # object.__get__(self, instance, owner=None) +class With_get: + + def __get__(self, instance, owner=None): + OK() + return "" + +def ftest_get(): + with_get = With_get() + Owner.foo = "" + Owner.attr = with_get + Owner.foo + # object.__set__(self, instance, value) +class With_set: + + def __set__(self, instance, value): + OK() + +def ftest_set(): + with_set = With_set() + with_set.foo = "" + # object.__delete__(self, instance) +class With_delete: + + def __delete__(self, instance): + OK() + +def ftest_delete(): + with_delete = With_delete() + with_delete.foo = "" + del with_delete.foo + # object.__set_name__(self, owner, name) +class With_set_name: + + def __set_name__(self, instance): + OK() + +def ftest_set_name(): + with_set_name = With_set_name() + with_set_name.foo = "" + del with_set_name.foo # 3.3.2.4. __slots__ # object.__slots__ @@ -207,89 +482,785 @@ SINK(customized.b) # 3.3.6. Emulating callable objects # object.__call__(self[, args...]) +class With_call: + + def __call__(self): + OK() + +def test_call(): + with_call = With_call() + with_call() # 3.3.7. Emulating container types # object.__len__(self) -# object.__length_hint__(self) -# object.__getitem__(self, key) -# object.__setitem__(self, key, value) -# object.__delitem__(self, key) -# object.__missing__(self, key) -# object.__iter__(self) -# object.__reversed__(self) -# object.__contains__(self, item) +class With_len: -# 3.3.8. Emulating numeric types -# object.__add__(self, other) -# object.__sub__(self, other) -# object.__mul__(self, other) -# object.__matmul__(self, other) -# object.__truediv__(self, other) -# object.__floordiv__(self, other) -# object.__mod__(self, other) -# object.__divmod__(self, other) -# object.__pow__(self, other[, modulo]) -# object.__lshift__(self, other) -# object.__rshift__(self, other) -# object.__and__(self, other) -# object.__xor__(self, other) -# object.__or__(self, other) -# object.__radd__(self, other) -# object.__rsub__(self, other) -# object.__rmul__(self, other) -# object.__rmatmul__(self, other) -# object.__rtruediv__(self, other) -# object.__rfloordiv__(self, other) -# object.__rmod__(self, other) -# object.__rdivmod__(self, other) -# object.__rpow__(self, other[, modulo]) -# object.__rlshift__(self, other) -# object.__rrshift__(self, other) -# object.__rand__(self, other) -# object.__rxor__(self, other) -# object.__ror__(self, other) -# object.__iadd__(self, other) -# object.__isub__(self, other) -# object.__imul__(self, other) -# object.__imatmul__(self, other) -# object.__itruediv__(self, other) -# object.__ifloordiv__(self, other) -# object.__imod__(self, other) -# object.__ipow__(self, other[, modulo]) -# object.__ilshift__(self, other) -# object.__irshift__(self, other) -# object.__iand__(self, other) -# object.__ixor__(self, other) -# object.__ior__(self, other) -# object.__neg__(self) -# object.__pos__(self) -# object.__abs__(self) -# object.__invert__(self) -# object.__complex__(self) -# object.__int__(self) -# object.__float__(self) -# object.__index__(self) -# object.__round__(self[, ndigits]) -# object.__trunc__(self) -# object.__floor__(self) -# object.__ceil__(self) + def __len__(self): + OK() + return 0 -# 3.3.9. With Statement Context Managers -# object.__enter__(self) -# object.__exit__(self, exc_type, exc_value, traceback) +def test_len(): + with_len = With_len() + len(with_len) -# 3.4.1. Awaitable Objects -# object.__await__(self) +def test_len_bool(): + with_len = With_len() + bool(with_len) -# 3.4.2. Coroutine Objects -# coroutine.send(value) -# coroutine.throw(type[, value[, traceback]]) -# coroutine.close() +def test_len_if(): + with_len = With_len() + if with_len: + pass -# 3.4.3. Asynchronous Iterators -# object.__aiter__(self) -# object.__anext__(self) +# # object.__length_hint__(self) +# # object.__getitem__(self, key) +# class With_getitem: -# 3.4.4. Asynchronous Context Managers -# object.__aenter__(self) -# object.__aexit__(self, exc_type, exc_value, traceback) +# def __getitem__(self, key): +# OK() +# return "" # edit to match type + +# def test_getitem(): +# with_getitem = With_getitem() +# getitem(with_getitem) # edit to effect call + +# # object.__setitem__(self, key, value) +# class With_setitem: + +# def __setitem__(self, key, value): +# OK() +# return "" # edit to match type + +# def test_setitem(): +# with_setitem = With_setitem() +# setitem(with_setitem) # edit to effect call + +# # object.__delitem__(self, key) +# class With_delitem: + +# def __delitem__(self, key): +# OK() +# return "" # edit to match type + +# def test_delitem(): +# with_delitem = With_delitem() +# delitem(with_delitem) # edit to effect call + +# # object.__missing__(self, key) +# class With_missing: + +# def __missing__(self, key): +# OK() +# return "" # edit to match type + +# def test_missing(): +# with_missing = With_missing() +# missing(with_missing) # edit to effect call + +# # object.__iter__(self) +# class With_iter: + +# def __iter__(self): +# OK() +# return "" # edit to match type + +# def test_iter(): +# with_iter = With_iter() +# iter(with_iter) # edit to effect call + +# # object.__reversed__(self) +# class With_reversed: + +# def __reversed__(self): +# OK() +# return "" # edit to match type + +# def test_reversed(): +# with_reversed = With_reversed() +# reversed(with_reversed) # edit to effect call + +# # object.__contains__(self, item) +# class With_contains: + +# def __contains__(self, item): +# OK() +# return "" # edit to match type + +# def test_contains(): +# with_contains = With_contains() +# contains(with_contains) # edit to effect call + + +# # 3.3.8. Emulating numeric types +# # object.__add__(self, other) +# class With_add: + +# def __add__(self, other): +# OK() +# return self + +# def test_add(): +# with_add = With_add() +# with_add + with_add + +# # object.__sub__(self, other) +# class With_sub: + +# def __sub__(self, other): +# OK() +# return "" # edit to match type + +# def test_sub(): +# with_sub = With_sub() +# sub(with_sub) # edit to effect call + +# # object.__mul__(self, other) +# class With_mul: + +# def __mul__(self, other): +# OK() +# return "" # edit to match type + +# def test_mul(): +# with_mul = With_mul() +# mul(with_mul) # edit to effect call + +# # object.__matmul__(self, other) +# class With_matmul: + +# def __matmul__(self, other): +# OK() +# return "" # edit to match type + +# def test_matmul(): +# with_matmul = With_matmul() +# matmul(with_matmul) # edit to effect call + +# # object.__truediv__(self, other) +# class With_truediv: + +# def __truediv__(self, other): +# OK() +# return "" # edit to match type + +# def test_truediv(): +# with_truediv = With_truediv() +# truediv(with_truediv) # edit to effect call + +# # object.__floordiv__(self, other) +# class With_floordiv: + +# def __floordiv__(self, other): +# OK() +# return "" # edit to match type + +# def test_floordiv(): +# with_floordiv = With_floordiv() +# floordiv(with_floordiv) # edit to effect call + +# # object.__mod__(self, other) +# class With_mod: + +# def __mod__(self, other): +# OK() +# return "" # edit to match type + +# def test_mod(): +# with_mod = With_mod() +# mod(with_mod) # edit to effect call + +# # object.__divmod__(self, other) +# class With_divmod: + +# def __divmod__(self, other): +# OK() +# return "" # edit to match type + +# def test_divmod(): +# with_divmod = With_divmod() +# divmod(with_divmod) # edit to effect call + +# # object.__pow__(self, other[, modulo]) +# class With_pow: + +# def __pow__(self, other): +# OK() +# return "" # edit to match type + +# def test_pow(): +# with_pow = With_pow() +# pow(with_pow) # edit to effect call + +# # object.__lshift__(self, other) +# class With_lshift: + +# def __lshift__(self, other): +# OK() +# return "" # edit to match type + +# def test_lshift(): +# with_lshift = With_lshift() +# lshift(with_lshift) # edit to effect call + +# # object.__rshift__(self, other) +# class With_rshift: + +# def __rshift__(self, other): +# OK() +# return "" # edit to match type + +# def test_rshift(): +# with_rshift = With_rshift() +# rshift(with_rshift) # edit to effect call + +# # object.__and__(self, other) +# class With_and: + +# def __and__(self, other): +# OK() +# return "" # edit to match type + +# def test_and(): +# with_and = With_and() +# with_and & with_and + +# # object.__xor__(self, other) +# class With_xor: + +# def __xor__(self, other): +# OK() +# return "" # edit to match type + +# def test_xor(): +# with_xor = With_xor() +# xor(with_xor) # edit to effect call + +# # object.__or__(self, other) +# class With_or: + +# def __or__(self, other): +# OK() +# return "" # edit to match type + +# def test_or(): +# with_or = With_or() +# with_or | with_or + +# # object.__radd__(self, other) +# class With_radd: + +# def __radd__(self, other): +# OK() +# return "" # edit to match type + +# def test_radd(): +# with_radd = With_radd() +# radd(with_radd) # edit to effect call + +# # object.__rsub__(self, other) +# class With_rsub: + +# def __rsub__(self, other): +# OK() +# return "" # edit to match type + +# def test_rsub(): +# with_rsub = With_rsub() +# rsub(with_rsub) # edit to effect call + +# # object.__rmul__(self, other) +# class With_rmul: + +# def __rmul__(self, other): +# OK() +# return "" # edit to match type + +# def test_rmul(): +# with_rmul = With_rmul() +# rmul(with_rmul) # edit to effect call + +# # object.__rmatmul__(self, other) +# class With_rmatmul: + +# def __rmatmul__(self, other): +# OK() +# return "" # edit to match type + +# def test_rmatmul(): +# with_rmatmul = With_rmatmul() +# rmatmul(with_rmatmul) # edit to effect call + +# # object.__rtruediv__(self, other) +# class With_rtruediv: + +# def __rtruediv__(self, other): +# OK() +# return "" # edit to match type + +# def test_rtruediv(): +# with_rtruediv = With_rtruediv() +# rtruediv(with_rtruediv) # edit to effect call + +# # object.__rfloordiv__(self, other) +# class With_rfloordiv: + +# def __rfloordiv__(self, other): +# OK() +# return "" # edit to match type + +# def test_rfloordiv(): +# with_rfloordiv = With_rfloordiv() +# rfloordiv(with_rfloordiv) # edit to effect call + +# # object.__rmod__(self, other) +# class With_rmod: + +# def __rmod__(self, other): +# OK() +# return "" # edit to match type + +# def test_rmod(): +# with_rmod = With_rmod() +# rmod(with_rmod) # edit to effect call + +# # object.__rdivmod__(self, other) +# class With_rdivmod: + +# def __rdivmod__(self, other): +# OK() +# return "" # edit to match type + +# def test_rdivmod(): +# with_rdivmod = With_rdivmod() +# rdivmod(with_rdivmod) # edit to effect call + +# # object.__rpow__(self, other[, modulo]) +# class With_rpow: + +# def __rpow__(self, other): +# OK() +# return "" # edit to match type + +# def test_rpow(): +# with_rpow = With_rpow() +# rpow(with_rpow) # edit to effect call + +# # object.__rlshift__(self, other) +# class With_rlshift: + +# def __rlshift__(self, other): +# OK() +# return "" # edit to match type + +# def test_rlshift(): +# with_rlshift = With_rlshift() +# rlshift(with_rlshift) # edit to effect call + +# # object.__rrshift__(self, other) +# class With_rrshift: + +# def __rrshift__(self, other): +# OK() +# return "" # edit to match type + +# def test_rrshift(): +# with_rrshift = With_rrshift() +# rrshift(with_rrshift) # edit to effect call + +# # object.__rand__(self, other) +# class With_rand: + +# def __rand__(self, other): +# OK() +# return "" # edit to match type + +# def test_rand(): +# with_rand = With_rand() +# rand(with_rand) # edit to effect call + +# # object.__rxor__(self, other) +# class With_rxor: + +# def __rxor__(self, other): +# OK() +# return "" # edit to match type + +# def test_rxor(): +# with_rxor = With_rxor() +# rxor(with_rxor) # edit to effect call + +# # object.__ror__(self, other) +# class With_ror: + +# def __ror__(self, other): +# OK() +# return "" # edit to match type + +# def test_ror(): +# with_ror = With_ror() +# ror(with_ror) # edit to effect call + +# # object.__iadd__(self, other) +# class With_iadd: + +# def __iadd__(self, other): +# OK() +# return "" # edit to match type + +# def test_iadd(): +# with_iadd = With_iadd() +# iadd(with_iadd) # edit to effect call + +# # object.__isub__(self, other) +# class With_isub: + +# def __isub__(self, other): +# OK() +# return "" # edit to match type + +# def test_isub(): +# with_isub = With_isub() +# isub(with_isub) # edit to effect call + +# # object.__imul__(self, other) +# class With_imul: + +# def __imul__(self, other): +# OK() +# return "" # edit to match type + +# def test_imul(): +# with_imul = With_imul() +# imul(with_imul) # edit to effect call + +# # object.__imatmul__(self, other) +# class With_imatmul: + +# def __imatmul__(self, other): +# OK() +# return "" # edit to match type + +# def test_imatmul(): +# with_imatmul = With_imatmul() +# imatmul(with_imatmul) # edit to effect call + +# # object.__itruediv__(self, other) +# class With_itruediv: + +# def __itruediv__(self, other): +# OK() +# return "" # edit to match type + +# def test_itruediv(): +# with_itruediv = With_itruediv() +# itruediv(with_itruediv) # edit to effect call + +# # object.__ifloordiv__(self, other) +# class With_ifloordiv: + +# def __ifloordiv__(self, other): +# OK() +# return "" # edit to match type + +# def test_ifloordiv(): +# with_ifloordiv = With_ifloordiv() +# ifloordiv(with_ifloordiv) # edit to effect call + +# # object.__imod__(self, other) +# class With_imod: + +# def __imod__(self, other): +# OK() +# return "" # edit to match type + +# def test_imod(): +# with_imod = With_imod() +# imod(with_imod) # edit to effect call + +# # object.__ipow__(self, other[, modulo]) +# class With_ipow: + +# def __ipow__(self, other): +# OK() +# return "" # edit to match type + +# def test_ipow(): +# with_ipow = With_ipow() +# ipow(with_ipow) # edit to effect call + +# # object.__ilshift__(self, other) +# class With_ilshift: + +# def __ilshift__(self, other): +# OK() +# return "" # edit to match type + +# def test_ilshift(): +# with_ilshift = With_ilshift() +# ilshift(with_ilshift) # edit to effect call + +# # object.__irshift__(self, other) +# class With_irshift: + +# def __irshift__(self, other): +# OK() +# return "" # edit to match type + +# def test_irshift(): +# with_irshift = With_irshift() +# irshift(with_irshift) # edit to effect call + +# # object.__iand__(self, other) +# class With_iand: + +# def __iand__(self, other): +# OK() +# return "" # edit to match type + +# def test_iand(): +# with_iand = With_iand() +# iand(with_iand) # edit to effect call + +# # object.__ixor__(self, other) +# class With_ixor: + +# def __ixor__(self, other): +# OK() +# return "" # edit to match type + +# def test_ixor(): +# with_ixor = With_ixor() +# ixor(with_ixor) # edit to effect call + +# # object.__ior__(self, other) +# class With_ior: + +# def __ior__(self, other): +# OK() +# return "" # edit to match type + +# def test_ior(): +# with_ior = With_ior() +# ior(with_ior) # edit to effect call + +# # object.__neg__(self) +# class With_neg: + +# def __neg__(self): +# OK() +# return "" # edit to match type + +# def test_neg(): +# with_neg = With_neg() +# neg(with_neg) # edit to effect call + +# # object.__pos__(self) +# class With_pos: + +# def __pos__(self): +# OK() +# return "" # edit to match type + +# def test_pos(): +# with_pos = With_pos() +# pos(with_pos) # edit to effect call + +# # object.__abs__(self) +# class With_abs: + +# def __abs__(self): +# OK() +# return "" # edit to match type + +# def test_abs(): +# with_abs = With_abs() +# abs(with_abs) # edit to effect call + +# # object.__invert__(self) +# class With_invert: + +# def __invert__(self): +# OK() +# return "" # edit to match type + +# def test_invert(): +# with_invert = With_invert() +# invert(with_invert) # edit to effect call + +# # object.__complex__(self) +# class With_complex: + +# def __complex__(self): +# OK() +# return "" # edit to match type + +# def test_complex(): +# with_complex = With_complex() +# complex(with_complex) # edit to effect call + +# # object.__int__(self) +# class With_int: + +# def __int__(self): +# OK() +# return "" # edit to match type + +# def test_int(): +# with_int = With_int() +# int(with_int) # edit to effect call + +# # object.__float__(self) +# class With_float: + +# def __float__(self): +# OK() +# return "" # edit to match type + +# def test_float(): +# with_float = With_float() +# float(with_float) # edit to effect call + +# # object.__index__(self) +# class With_index: + +# def __index__(self): +# OK() +# return "" # edit to match type + +# def test_index(): +# with_index = With_index() +# index(with_index) # edit to effect call + +# # object.__round__(self[, ndigits]) +# class With_round: + +# def __round__(self): +# OK() +# return "" # edit to match type + +# def test_round(): +# with_round = With_round() +# round(with_round) # edit to effect call + +# # object.__trunc__(self) +# class With_trunc: + +# def __trunc__(self): +# OK() +# return "" # edit to match type + +# def test_trunc(): +# with_trunc = With_trunc() +# trunc(with_trunc) # edit to effect call + +# # object.__floor__(self) +# class With_floor: + +# def __floor__(self): +# OK() +# return "" # edit to match type + +# def test_floor(): +# with_floor = With_floor() +# floor(with_floor) # edit to effect call + +# # object.__ceil__(self) +# class With_ceil: + +# def __ceil__(self): +# OK() +# return "" # edit to match type + +# def test_ceil(): +# with_ceil = With_ceil() +# ceil(with_ceil) # edit to effect call + + +# # 3.3.9. With Statement Context Managers +# # object.__enter__(self) +# class With_enter: + +# def __enter__(self): +# OK() +# return "" # edit to match type + +# def test_enter(): +# with_enter = With_enter() +# enter(with_enter) # edit to effect call + +# # object.__exit__(self, exc_type, exc_value, traceback) +# class With_exit: + +# def __exit__(self, exc_type, exc_value, traceback): +# OK() +# return "" # edit to match type + +# def test_exit(): +# with_exit = With_exit() +# exit(with_exit) # edit to effect call + + +# # 3.4.1. Awaitable Objects +# # object.__await__(self) +# class With_await: + +# def __await__(self): +# OK() +# return "" # edit to match type + +# async def test_await(): +# with_await = With_await() +# await(with_await) # edit to effect call + + +# # 3.4.2. Coroutine Objects +# # coroutine.send(value) +# # coroutine.throw(type[, value[, traceback]]) +# # coroutine.close() + +# # 3.4.3. Asynchronous Iterators +# # object.__aiter__(self) +# class With_aiter: + +# def __aiter__(self): +# OK() +# return "" # edit to match type + +# def test_aiter(): +# with_aiter = With_aiter() +# aiter(with_aiter) # edit to effect call + +# # object.__anext__(self) +# class With_anext: + +# def __anext__(self): +# OK() +# return "" # edit to match type + +# def test_anext(): +# with_anext = With_anext() +# anext(with_anext) # edit to effect call + + +# # 3.4.4. Asynchronous Context Managers +# # object.__aenter__(self) +# class With_aenter: + +# def __aenter__(self): +# OK() +# return "" # edit to match type + +# def test_aenter(): +# with_aenter = With_aenter() +# aenter(with_aenter) # edit to effect call + +# # object.__aexit__(self, exc_type, exc_value, traceback) +# class With_aexit: + +# def __aexit__(self, exc_type, exc_value, traceback): +# OK() +# return "" # edit to match type + +# def test_aexit(): +# with_aexit = With_aexit() +# aexit(with_aexit) # edit to effect call diff --git a/python/ql/test/experimental/dataflow/coverage/test.py b/python/ql/test/experimental/dataflow/coverage/test.py index 0324fd6a7f9..c3c0702f1a8 100644 --- a/python/ql/test/experimental/dataflow/coverage/test.py +++ b/python/ql/test/experimental/dataflow/coverage/test.py @@ -6,19 +6,27 @@ # # Functions whose name ends with "_with_local_flow" will also be tested for local flow. # -# All functions starting with "test_" should run and either -# - print a source (sources are defined in testConfig.qll). -# - print "Unexpected flow: " and a non-source -# (The idea is to later write a script to autimatically confirm this.) +# All functions starting with "test_" should run and print `"OK"`. +# This can be checked by running validTest.py. # These are defined so that we can evaluate the test code. NONSOURCE = "not a source" SOURCE = "source" + +def is_source(x): + return x == "source" or x == b"source" or x == 42 or x == 42.0 or x == 42j + def SINK(x): - print(x) + if is_source(x): + print("OK") + else: + print("Unexpected flow", x) def SINK_F(x): - print("Unexpected flow: ", x) + if is_source(x): + print("Unexpected flow", x) + else: + print("OK") def test_tuple_with_local_flow(): x = (NONSOURCE, SOURCE) diff --git a/python/ql/test/experimental/dataflow/coverage/validTest.py b/python/ql/test/experimental/dataflow/coverage/validTest.py new file mode 100644 index 00000000000..97ba6be8cdb --- /dev/null +++ b/python/ql/test/experimental/dataflow/coverage/validTest.py @@ -0,0 +1,33 @@ +def check_output(s, f): + if s == "OK\n": + pass + else: + raise RuntimeError("Function failed", s, f) + +def check_test_function(f): + from io import StringIO + import sys + + capturer = StringIO() + old_stdout = sys.stdout + sys.stdout = capturer + f() + sys.stdout = old_stdout + check_output(capturer.getvalue(), f) + +def check_classes_valid(testFile): + # import python.ql.test.experimental.dataflow.coverage.classes as tests + # import classes as tests + import importlib + tests = importlib.import_module(testFile) + for i in dir(tests): + # print("Considering", i) + if i.startswith("test_"): + item = getattr(tests,i) + if callable(item): + print("Checking", testFile, item) + check_test_function(item) + +if __name__ == '__main__': + check_classes_valid("classes") + check_classes_valid("test") From aff4535965d4cc70b79a45307ebbc7d1bb38122c Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Fri, 7 Aug 2020 23:07:58 +0200 Subject: [PATCH 015/133] Python: fix tests for descriptors --- .../experimental/dataflow/coverage/classes.py | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/python/ql/test/experimental/dataflow/coverage/classes.py b/python/ql/test/experimental/dataflow/coverage/classes.py index 3cbe6e97791..154e40ec365 100644 --- a/python/ql/test/experimental/dataflow/coverage/classes.py +++ b/python/ql/test/experimental/dataflow/coverage/classes.py @@ -418,11 +418,10 @@ class With_get: OK() return "" -def ftest_get(): +def test_get(): with_get = With_get() - Owner.foo = "" Owner.attr = with_get - Owner.foo + Owner.attr # object.__set__(self, instance, value) class With_set: @@ -430,9 +429,11 @@ class With_set: def __set__(self, instance, value): OK() -def ftest_set(): +def test_set(): with_set = With_set() - with_set.foo = "" + Owner.attr = with_set + owner = Owner() + owner.attr = "" # object.__delete__(self, instance) class With_delete: @@ -440,21 +441,21 @@ class With_delete: def __delete__(self, instance): OK() -def ftest_delete(): +def test_delete(): with_delete = With_delete() - with_delete.foo = "" - del with_delete.foo + Owner.attr = with_delete + owner = Owner() + del owner.attr # object.__set_name__(self, owner, name) class With_set_name: - def __set_name__(self, instance): + def __set_name__(self, owner, name): OK() -def ftest_set_name(): +def test_set_name(): with_set_name = With_set_name() - with_set_name.foo = "" - del with_set_name.foo + type("Owner", (object,), dict(attr=with_set_name)) # 3.3.2.4. __slots__ # object.__slots__ From f6d6f91a42429be198e7417153c1f3f59ada611a Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Fri, 7 Aug 2020 23:39:42 +0200 Subject: [PATCH 016/133] Python: tests for containers --- .../experimental/dataflow/coverage/classes.py | 123 ++++++++++-------- 1 file changed, 66 insertions(+), 57 deletions(-) diff --git a/python/ql/test/experimental/dataflow/coverage/classes.py b/python/ql/test/experimental/dataflow/coverage/classes.py index 154e40ec365..b1dcecb1e63 100644 --- a/python/ql/test/experimental/dataflow/coverage/classes.py +++ b/python/ql/test/experimental/dataflow/coverage/classes.py @@ -513,83 +513,92 @@ def test_len_if(): if with_len: pass -# # object.__length_hint__(self) -# # object.__getitem__(self, key) -# class With_getitem: +# object.__length_hint__(self) +class With_length_hint: -# def __getitem__(self, key): -# OK() -# return "" # edit to match type + def __length_hint__(self): + OK() + return 0 -# def test_getitem(): -# with_getitem = With_getitem() -# getitem(with_getitem) # edit to effect call +def test_length_hint(): + import operator + with_length_hint = With_length_hint() + operator.length_hint(with_length_hint) -# # object.__setitem__(self, key, value) -# class With_setitem: +# object.__getitem__(self, key) +class With_getitem: -# def __setitem__(self, key, value): -# OK() -# return "" # edit to match type + def __getitem__(self, key): + OK() + return "" -# def test_setitem(): -# with_setitem = With_setitem() -# setitem(with_setitem) # edit to effect call +def test_getitem(): + with_getitem = With_getitem() + with_getitem[0] -# # object.__delitem__(self, key) -# class With_delitem: +# object.__setitem__(self, key, value) +class With_setitem: -# def __delitem__(self, key): -# OK() -# return "" # edit to match type + def __setitem__(self, key, value): + OK() -# def test_delitem(): -# with_delitem = With_delitem() -# delitem(with_delitem) # edit to effect call +def test_setitem(): + with_setitem = With_setitem() + with_setitem[0] = "" -# # object.__missing__(self, key) -# class With_missing: +# object.__delitem__(self, key) +class With_delitem: -# def __missing__(self, key): -# OK() -# return "" # edit to match type + def __delitem__(self, key): + OK() -# def test_missing(): -# with_missing = With_missing() -# missing(with_missing) # edit to effect call +def test_delitem(): + with_delitem = With_delitem() + del with_delitem[0] -# # object.__iter__(self) -# class With_iter: +# object.__missing__(self, key) +class With_missing(dict): -# def __iter__(self): -# OK() -# return "" # edit to match type + def __missing__(self, key): + OK() + return "" -# def test_iter(): -# with_iter = With_iter() -# iter(with_iter) # edit to effect call +def test_missing(): + with_missing = With_missing() + with_missing[""] -# # object.__reversed__(self) -# class With_reversed: +# object.__iter__(self) +class With_iter: -# def __reversed__(self): -# OK() -# return "" # edit to match type + def __iter__(self): + OK() + return [].__iter__() -# def test_reversed(): -# with_reversed = With_reversed() -# reversed(with_reversed) # edit to effect call +def test_iter(): + with_iter = With_iter() + [x for x in with_iter] -# # object.__contains__(self, item) -# class With_contains: +# object.__reversed__(self) +class With_reversed: -# def __contains__(self, item): -# OK() -# return "" # edit to match type + def __reversed__(self): + OK() + return [].__iter__ -# def test_contains(): -# with_contains = With_contains() -# contains(with_contains) # edit to effect call +def test_reversed(): + with_reversed = With_reversed() + reversed(with_reversed) + +# object.__contains__(self, item) +class With_contains: + + def __contains__(self, item): + OK() + return True + +def test_contains(): + with_contains = With_contains() + 0 in with_contains # # 3.3.8. Emulating numeric types From 5b7c7f933cc98a949b75e8840e9d6e6ec2930fe4 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Sat, 8 Aug 2020 00:31:29 +0200 Subject: [PATCH 017/133] Python: tests for numeric classes --- .../experimental/dataflow/coverage/classes.py | 888 +++++++++--------- 1 file changed, 463 insertions(+), 425 deletions(-) diff --git a/python/ql/test/experimental/dataflow/coverage/classes.py b/python/ql/test/experimental/dataflow/coverage/classes.py index b1dcecb1e63..81ef52d093c 100644 --- a/python/ql/test/experimental/dataflow/coverage/classes.py +++ b/python/ql/test/experimental/dataflow/coverage/classes.py @@ -601,589 +601,627 @@ def test_contains(): 0 in with_contains -# # 3.3.8. Emulating numeric types -# # object.__add__(self, other) -# class With_add: +# 3.3.8. Emulating numeric types +# object.__add__(self, other) +class With_add: -# def __add__(self, other): -# OK() -# return self + def __add__(self, other): + OK() + return self -# def test_add(): -# with_add = With_add() -# with_add + with_add +def test_add(): + with_add = With_add() + with_add + with_add -# # object.__sub__(self, other) -# class With_sub: +# object.__sub__(self, other) +class With_sub: -# def __sub__(self, other): -# OK() -# return "" # edit to match type + def __sub__(self, other): + OK() + return self -# def test_sub(): -# with_sub = With_sub() -# sub(with_sub) # edit to effect call +def test_sub(): + with_sub = With_sub() + with_sub - with_sub -# # object.__mul__(self, other) -# class With_mul: +# object.__mul__(self, other) +class With_mul: -# def __mul__(self, other): -# OK() -# return "" # edit to match type + def __mul__(self, other): + OK() + return self -# def test_mul(): -# with_mul = With_mul() -# mul(with_mul) # edit to effect call +def test_mul(): + with_mul = With_mul() + with_mul * with_mul -# # object.__matmul__(self, other) -# class With_matmul: +# object.__matmul__(self, other) +class With_matmul: -# def __matmul__(self, other): -# OK() -# return "" # edit to match type + def __matmul__(self, other): + OK() + return self -# def test_matmul(): -# with_matmul = With_matmul() -# matmul(with_matmul) # edit to effect call +def test_matmul(): + with_matmul = With_matmul() + with_matmul @ with_matmul -# # object.__truediv__(self, other) -# class With_truediv: +# object.__truediv__(self, other) +class With_truediv: -# def __truediv__(self, other): -# OK() -# return "" # edit to match type + def __truediv__(self, other): + OK() + return self -# def test_truediv(): -# with_truediv = With_truediv() -# truediv(with_truediv) # edit to effect call +def test_truediv(): + with_truediv = With_truediv() + with_truediv / with_truediv -# # object.__floordiv__(self, other) -# class With_floordiv: +# object.__floordiv__(self, other) +class With_floordiv: -# def __floordiv__(self, other): -# OK() -# return "" # edit to match type + def __floordiv__(self, other): + OK() + return self -# def test_floordiv(): -# with_floordiv = With_floordiv() -# floordiv(with_floordiv) # edit to effect call +def test_floordiv(): + with_floordiv = With_floordiv() + with_floordiv // with_floordiv -# # object.__mod__(self, other) -# class With_mod: +# object.__mod__(self, other) +class With_mod: -# def __mod__(self, other): -# OK() -# return "" # edit to match type + def __mod__(self, other): + OK() + return self -# def test_mod(): -# with_mod = With_mod() -# mod(with_mod) # edit to effect call +def test_mod(): + with_mod = With_mod() + with_mod % with_mod -# # object.__divmod__(self, other) -# class With_divmod: +# object.__divmod__(self, other) +class With_divmod: -# def __divmod__(self, other): -# OK() -# return "" # edit to match type + def __divmod__(self, other): + OK() + return self -# def test_divmod(): -# with_divmod = With_divmod() -# divmod(with_divmod) # edit to effect call +def test_divmod(): + with_divmod = With_divmod() + divmod(with_divmod, with_divmod) -# # object.__pow__(self, other[, modulo]) -# class With_pow: +# object.__pow__(self, other[, modulo]) +class With_pow: -# def __pow__(self, other): -# OK() -# return "" # edit to match type + def __pow__(self, other): + OK() + return self -# def test_pow(): -# with_pow = With_pow() -# pow(with_pow) # edit to effect call +def test_pow(): + with_pow = With_pow() + pow(with_pow, with_pow) -# # object.__lshift__(self, other) -# class With_lshift: +def test_pow_op(): + with_pow = With_pow() + with_pow ** with_pow -# def __lshift__(self, other): -# OK() -# return "" # edit to match type +# object.__lshift__(self, other) +class With_lshift: -# def test_lshift(): -# with_lshift = With_lshift() -# lshift(with_lshift) # edit to effect call + def __lshift__(self, other): + OK() + return self -# # object.__rshift__(self, other) -# class With_rshift: +def test_lshift(): + with_lshift = With_lshift() + with_lshift << with_lshift -# def __rshift__(self, other): -# OK() -# return "" # edit to match type +# object.__rshift__(self, other) +class With_rshift: -# def test_rshift(): -# with_rshift = With_rshift() -# rshift(with_rshift) # edit to effect call + def __rshift__(self, other): + OK() + return self -# # object.__and__(self, other) -# class With_and: +def test_rshift(): + with_rshift = With_rshift() + with_rshift >> with_rshift -# def __and__(self, other): -# OK() -# return "" # edit to match type +# object.__and__(self, other) +class With_and: -# def test_and(): -# with_and = With_and() -# with_and & with_and + def __and__(self, other): + OK() + return self -# # object.__xor__(self, other) -# class With_xor: +def test_and(): + with_and = With_and() + with_and & with_and -# def __xor__(self, other): -# OK() -# return "" # edit to match type +# object.__xor__(self, other) +class With_xor: -# def test_xor(): -# with_xor = With_xor() -# xor(with_xor) # edit to effect call + def __xor__(self, other): + OK() + return self -# # object.__or__(self, other) -# class With_or: +def test_xor(): + with_xor = With_xor() + with_xor ^ with_xor -# def __or__(self, other): -# OK() -# return "" # edit to match type +# object.__or__(self, other) +class With_or: -# def test_or(): -# with_or = With_or() -# with_or | with_or + def __or__(self, other): + OK() + return self -# # object.__radd__(self, other) -# class With_radd: +def test_or(): + with_or = With_or() + with_or | with_or -# def __radd__(self, other): -# OK() -# return "" # edit to match type +# object.__radd__(self, other) +class With_radd: -# def test_radd(): -# with_radd = With_radd() -# radd(with_radd) # edit to effect call + def __radd__(self, other): + OK() + return self -# # object.__rsub__(self, other) -# class With_rsub: +def test_radd(): + with_radd = With_radd() + f"" + with_radd -# def __rsub__(self, other): -# OK() -# return "" # edit to match type +# object.__rsub__(self, other) +class With_rsub: -# def test_rsub(): -# with_rsub = With_rsub() -# rsub(with_rsub) # edit to effect call + def __rsub__(self, other): + OK() + return self -# # object.__rmul__(self, other) -# class With_rmul: +def test_rsub(): + with_rsub = With_rsub() + f"" - with_rsub -# def __rmul__(self, other): -# OK() -# return "" # edit to match type +# object.__rmul__(self, other) +class With_rmul: -# def test_rmul(): -# with_rmul = With_rmul() -# rmul(with_rmul) # edit to effect call + def __rmul__(self, other): + OK() + return self -# # object.__rmatmul__(self, other) -# class With_rmatmul: +def test_rmul(): + with_rmul = With_rmul() + f"" * with_rmul -# def __rmatmul__(self, other): -# OK() -# return "" # edit to match type +# object.__rmatmul__(self, other) +class With_rmatmul: -# def test_rmatmul(): -# with_rmatmul = With_rmatmul() -# rmatmul(with_rmatmul) # edit to effect call + def __rmatmul__(self, other): + OK() + return self -# # object.__rtruediv__(self, other) -# class With_rtruediv: +def test_rmatmul(): + with_rmatmul = With_rmatmul() + f"" @ with_rmatmul -# def __rtruediv__(self, other): -# OK() -# return "" # edit to match type +# object.__rtruediv__(self, other) +class With_rtruediv: -# def test_rtruediv(): -# with_rtruediv = With_rtruediv() -# rtruediv(with_rtruediv) # edit to effect call + def __rtruediv__(self, other): + OK() + return self -# # object.__rfloordiv__(self, other) -# class With_rfloordiv: +def test_rtruediv(): + with_rtruediv = With_rtruediv() + f"" / with_rtruediv -# def __rfloordiv__(self, other): -# OK() -# return "" # edit to match type +# object.__rfloordiv__(self, other) +class With_rfloordiv: -# def test_rfloordiv(): -# with_rfloordiv = With_rfloordiv() -# rfloordiv(with_rfloordiv) # edit to effect call + def __rfloordiv__(self, other): + OK() + return self -# # object.__rmod__(self, other) -# class With_rmod: +def test_rfloordiv(): + with_rfloordiv = With_rfloordiv() + f"" // with_rfloordiv -# def __rmod__(self, other): -# OK() -# return "" # edit to match type +# object.__rmod__(self, other) +class With_rmod: -# def test_rmod(): -# with_rmod = With_rmod() -# rmod(with_rmod) # edit to effect call + def __rmod__(self, other): + OK() + return self -# # object.__rdivmod__(self, other) -# class With_rdivmod: +def test_rmod(): + with_rmod = With_rmod() + {} % with_rmod -# def __rdivmod__(self, other): -# OK() -# return "" # edit to match type +# object.__rdivmod__(self, other) +class With_rdivmod: -# def test_rdivmod(): -# with_rdivmod = With_rdivmod() -# rdivmod(with_rdivmod) # edit to effect call + def __rdivmod__(self, other): + OK() + return self -# # object.__rpow__(self, other[, modulo]) -# class With_rpow: +def test_rdivmod(): + with_rdivmod = With_rdivmod() + divmod(f"", with_rdivmod) -# def __rpow__(self, other): -# OK() -# return "" # edit to match type +# object.__rpow__(self, other[, modulo]) +class With_rpow: -# def test_rpow(): -# with_rpow = With_rpow() -# rpow(with_rpow) # edit to effect call + def __rpow__(self, other): + OK() + return self -# # object.__rlshift__(self, other) -# class With_rlshift: +def test_rpow(): + with_rpow = With_rpow() + pow(f"", with_rpow) -# def __rlshift__(self, other): -# OK() -# return "" # edit to match type +def test_rpow_op(): + with_rpow = With_rpow() + f"" ** with_rpow -# def test_rlshift(): -# with_rlshift = With_rlshift() -# rlshift(with_rlshift) # edit to effect call +# object.__rlshift__(self, other) +class With_rlshift: -# # object.__rrshift__(self, other) -# class With_rrshift: + def __rlshift__(self, other): + OK() + return self -# def __rrshift__(self, other): -# OK() -# return "" # edit to match type +def ftest_rlshift(): # TypeError: unsupported operand type(s) for >>: 'str' and 'With_rlshift' + with_rlshift = With_rlshift() + f"" >> with_rlshift -# def test_rrshift(): -# with_rrshift = With_rrshift() -# rrshift(with_rrshift) # edit to effect call +# object.__rrshift__(self, other) +class With_rrshift: -# # object.__rand__(self, other) -# class With_rand: + def __rrshift__(self, other): + OK() + return self -# def __rand__(self, other): -# OK() -# return "" # edit to match type +def ftest_rrshift(): # TypeError: unsupported operand type(s) for <<: 'str' and 'With_rrshift' + with_rrshift = With_rrshift() + f"" << with_rrshift -# def test_rand(): -# with_rand = With_rand() -# rand(with_rand) # edit to effect call +# object.__rand__(self, other) +class With_rand: -# # object.__rxor__(self, other) -# class With_rxor: + def __rand__(self, other): + OK() + return self -# def __rxor__(self, other): -# OK() -# return "" # edit to match type +def test_rand(): + with_rand = With_rand() + f"" & with_rand -# def test_rxor(): -# with_rxor = With_rxor() -# rxor(with_rxor) # edit to effect call +# object.__rxor__(self, other) +class With_rxor: -# # object.__ror__(self, other) -# class With_ror: + def __rxor__(self, other): + OK() + return self -# def __ror__(self, other): -# OK() -# return "" # edit to match type +def test_rxor(): + with_rxor = With_rxor() + f"" ^ with_rxor -# def test_ror(): -# with_ror = With_ror() -# ror(with_ror) # edit to effect call +# object.__ror__(self, other) +class With_ror: -# # object.__iadd__(self, other) -# class With_iadd: + def __ror__(self, other): + OK() + return self -# def __iadd__(self, other): -# OK() -# return "" # edit to match type +def test_ror(): + with_ror = With_ror() + f"" | with_ror -# def test_iadd(): -# with_iadd = With_iadd() -# iadd(with_iadd) # edit to effect call +# object.__iadd__(self, other) +class With_iadd: -# # object.__isub__(self, other) -# class With_isub: + def __iadd__(self, other): + OK() + return self -# def __isub__(self, other): -# OK() -# return "" # edit to match type +def test_iadd(): + with_iadd = With_iadd() + with_iadd += with_iadd -# def test_isub(): -# with_isub = With_isub() -# isub(with_isub) # edit to effect call +# object.__isub__(self, other) +class With_isub: -# # object.__imul__(self, other) -# class With_imul: + def __isub__(self, other): + OK() + return self -# def __imul__(self, other): -# OK() -# return "" # edit to match type +def test_isub(): + with_isub = With_isub() + with_isub -= with_isub -# def test_imul(): -# with_imul = With_imul() -# imul(with_imul) # edit to effect call +# object.__imul__(self, other) +class With_imul: -# # object.__imatmul__(self, other) -# class With_imatmul: + def __imul__(self, other): + OK() + return self -# def __imatmul__(self, other): -# OK() -# return "" # edit to match type +def test_imul(): + with_imul = With_imul() + with_imul *= with_imul -# def test_imatmul(): -# with_imatmul = With_imatmul() -# imatmul(with_imatmul) # edit to effect call +# object.__imatmul__(self, other) +class With_imatmul: -# # object.__itruediv__(self, other) -# class With_itruediv: + def __imatmul__(self, other): + OK() + return self -# def __itruediv__(self, other): -# OK() -# return "" # edit to match type +def test_imatmul(): + with_imatmul = With_imatmul() + with_imatmul @= with_imatmul -# def test_itruediv(): -# with_itruediv = With_itruediv() -# itruediv(with_itruediv) # edit to effect call +# object.__itruediv__(self, other) +class With_itruediv: -# # object.__ifloordiv__(self, other) -# class With_ifloordiv: + def __itruediv__(self, other): + OK() + return self -# def __ifloordiv__(self, other): -# OK() -# return "" # edit to match type +def test_itruediv(): + with_itruediv = With_itruediv() + with_itruediv /= with_itruediv -# def test_ifloordiv(): -# with_ifloordiv = With_ifloordiv() -# ifloordiv(with_ifloordiv) # edit to effect call +# object.__ifloordiv__(self, other) +class With_ifloordiv: -# # object.__imod__(self, other) -# class With_imod: + def __ifloordiv__(self, other): + OK() + return self -# def __imod__(self, other): -# OK() -# return "" # edit to match type +def test_ifloordiv(): + with_ifloordiv = With_ifloordiv() + with_ifloordiv //= with_ifloordiv -# def test_imod(): -# with_imod = With_imod() -# imod(with_imod) # edit to effect call +# object.__imod__(self, other) +class With_imod: -# # object.__ipow__(self, other[, modulo]) -# class With_ipow: + def __imod__(self, other): + OK() + return self -# def __ipow__(self, other): -# OK() -# return "" # edit to match type +def test_imod(): + with_imod = With_imod() + with_imod %= with_imod -# def test_ipow(): -# with_ipow = With_ipow() -# ipow(with_ipow) # edit to effect call +# object.__ipow__(self, other[, modulo]) +class With_ipow: -# # object.__ilshift__(self, other) -# class With_ilshift: + def __ipow__(self, other): + OK() + return self -# def __ilshift__(self, other): -# OK() -# return "" # edit to match type +def test_ipow(): + with_ipow = With_ipow() + with_ipow **= with_ipow -# def test_ilshift(): -# with_ilshift = With_ilshift() -# ilshift(with_ilshift) # edit to effect call +# object.__ilshift__(self, other) +class With_ilshift: -# # object.__irshift__(self, other) -# class With_irshift: + def __ilshift__(self, other): + OK() + return self -# def __irshift__(self, other): -# OK() -# return "" # edit to match type +def test_ilshift(): + with_ilshift = With_ilshift() + with_ilshift <<= with_ilshift -# def test_irshift(): -# with_irshift = With_irshift() -# irshift(with_irshift) # edit to effect call +# object.__irshift__(self, other) +class With_irshift: -# # object.__iand__(self, other) -# class With_iand: + def __irshift__(self, other): + OK() + return self -# def __iand__(self, other): -# OK() -# return "" # edit to match type +def test_irshift(): + with_irshift = With_irshift() + with_irshift >>= with_irshift -# def test_iand(): -# with_iand = With_iand() -# iand(with_iand) # edit to effect call +# object.__iand__(self, other) +class With_iand: -# # object.__ixor__(self, other) -# class With_ixor: + def __iand__(self, other): + OK() + return self -# def __ixor__(self, other): -# OK() -# return "" # edit to match type +def test_iand(): + with_iand = With_iand() + with_iand &= with_iand -# def test_ixor(): -# with_ixor = With_ixor() -# ixor(with_ixor) # edit to effect call +# object.__ixor__(self, other) +class With_ixor: -# # object.__ior__(self, other) -# class With_ior: + def __ixor__(self, other): + OK() + return self -# def __ior__(self, other): -# OK() -# return "" # edit to match type +def test_ixor(): + with_ixor = With_ixor() + with_ixor ^= with_ixor -# def test_ior(): -# with_ior = With_ior() -# ior(with_ior) # edit to effect call +# object.__ior__(self, other) +class With_ior: -# # object.__neg__(self) -# class With_neg: + def __ior__(self, other): + OK() + return self -# def __neg__(self): -# OK() -# return "" # edit to match type +def test_ior(): + with_ior = With_ior() + with_ior |= with_ior -# def test_neg(): -# with_neg = With_neg() -# neg(with_neg) # edit to effect call +# object.__neg__(self) +class With_neg: -# # object.__pos__(self) -# class With_pos: + def __neg__(self): + OK() + return self -# def __pos__(self): -# OK() -# return "" # edit to match type +def test_neg(): + with_neg = With_neg() + -with_neg -# def test_pos(): -# with_pos = With_pos() -# pos(with_pos) # edit to effect call +# object.__pos__(self) +class With_pos: -# # object.__abs__(self) -# class With_abs: + def __pos__(self): + OK() + return self -# def __abs__(self): -# OK() -# return "" # edit to match type +def test_pos(): + with_pos = With_pos() + +with_pos -# def test_abs(): -# with_abs = With_abs() -# abs(with_abs) # edit to effect call +# object.__abs__(self) +class With_abs: -# # object.__invert__(self) -# class With_invert: + def __abs__(self): + OK() + return self -# def __invert__(self): -# OK() -# return "" # edit to match type +def test_abs(): + with_abs = With_abs() + abs(with_abs) -# def test_invert(): -# with_invert = With_invert() -# invert(with_invert) # edit to effect call +# object.__invert__(self) +class With_invert: -# # object.__complex__(self) -# class With_complex: + def __invert__(self): + OK() + return self -# def __complex__(self): -# OK() -# return "" # edit to match type +def test_invert(): + with_invert = With_invert() + ~with_invert -# def test_complex(): -# with_complex = With_complex() -# complex(with_complex) # edit to effect call +# object.__complex__(self) +class With_complex: -# # object.__int__(self) -# class With_int: + def __complex__(self): + OK() + return 0j -# def __int__(self): -# OK() -# return "" # edit to match type +def test_complex(): + with_complex = With_complex() + complex(with_complex) -# def test_int(): -# with_int = With_int() -# int(with_int) # edit to effect call +# object.__int__(self) +class With_int: -# # object.__float__(self) -# class With_float: + def __int__(self): + OK() + return 0 -# def __float__(self): -# OK() -# return "" # edit to match type +def test_int(): + with_int = With_int() + int(with_int) -# def test_float(): -# with_float = With_float() -# float(with_float) # edit to effect call +# object.__float__(self) +class With_float: -# # object.__index__(self) -# class With_index: + def __float__(self): + OK() + return 0.0 -# def __index__(self): -# OK() -# return "" # edit to match type +def test_float(): + with_float = With_float() + float(with_float) -# def test_index(): -# with_index = With_index() -# index(with_index) # edit to effect call +# object.__index__(self) +class With_index: -# # object.__round__(self[, ndigits]) -# class With_round: + def __index__(self): + OK() + return 0 -# def __round__(self): -# OK() -# return "" # edit to match type +def test_index(): + import operator + with_index = With_index() + operator.index(with_index) -# def test_round(): -# with_round = With_round() -# round(with_round) # edit to effect call +# make With_index subscriptable to test slicing -# # object.__trunc__(self) -# class With_trunc: +def test_index_bin(): + with_index = With_index() + bin(with_index) -# def __trunc__(self): -# OK() -# return "" # edit to match type +def test_index_hex(): + with_index = With_index() + hex(with_index) -# def test_trunc(): -# with_trunc = With_trunc() -# trunc(with_trunc) # edit to effect call +def test_index_oct(): + with_index = With_index() + oct(with_index) -# # object.__floor__(self) -# class With_floor: +def test_index_int(): + with_index = With_index() + int(with_index) -# def __floor__(self): -# OK() -# return "" # edit to match type +def test_index_float(): + with_index = With_index() + float(with_index) -# def test_floor(): -# with_floor = With_floor() -# floor(with_floor) # edit to effect call +def test_index_complex(): + with_index = With_index() + complex(with_index) -# # object.__ceil__(self) -# class With_ceil: +# object.__round__(self[, ndigits]) +class With_round: -# def __ceil__(self): -# OK() -# return "" # edit to match type + def __round__(self): + OK() + return 0 -# def test_ceil(): -# with_ceil = With_ceil() -# ceil(with_ceil) # edit to effect call +def test_round(): + with_round = With_round() + round(with_round) + +# object.__trunc__(self) +class With_trunc: + + def __trunc__(self): + OK() + return 0 + +def test_trunc(): + with_trunc = With_trunc() + import math + math.trunc(with_trunc) # edit to effect call + +# object.__floor__(self) +class With_floor: + + def __floor__(self): + OK() + return 0 + +def test_floor(): + with_floor = With_floor() + import math + math.floor(with_floor) # edit to effect call + +# object.__ceil__(self) +class With_ceil: + + def __ceil__(self): + OK() + return 0 + +def test_ceil(): + with_ceil = With_ceil() + import math + math.ceil(with_ceil) # edit to effect call # # 3.3.9. With Statement Context Managers From 02478774c3f829f4318b205003e5a18d7cf3fbea Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Mon, 10 Aug 2020 08:11:25 +0200 Subject: [PATCH 018/133] Python: tests for context managers --- .../experimental/dataflow/coverage/classes.py | 39 +++++++++++-------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/python/ql/test/experimental/dataflow/coverage/classes.py b/python/ql/test/experimental/dataflow/coverage/classes.py index 81ef52d093c..6f9a53076ed 100644 --- a/python/ql/test/experimental/dataflow/coverage/classes.py +++ b/python/ql/test/experimental/dataflow/coverage/classes.py @@ -1224,29 +1224,34 @@ def test_ceil(): math.ceil(with_ceil) # edit to effect call -# # 3.3.9. With Statement Context Managers -# # object.__enter__(self) -# class With_enter: +# 3.3.9. With Statement Context Managers +# object.__enter__(self) +class With_enter: -# def __enter__(self): -# OK() -# return "" # edit to match type + def __enter__(self): + OK() + return -# def test_enter(): -# with_enter = With_enter() -# enter(with_enter) # edit to effect call + def __exit__(self, exc_type, exc_value, traceback): + return -# # object.__exit__(self, exc_type, exc_value, traceback) -# class With_exit: +def test_enter(): + with With_enter(): + pass -# def __exit__(self, exc_type, exc_value, traceback): -# OK() -# return "" # edit to match type +# object.__exit__(self, exc_type, exc_value, traceback) +class With_exit: -# def test_exit(): -# with_exit = With_exit() -# exit(with_exit) # edit to effect call + def __enter__(self): + return + def __exit__(self, exc_type, exc_value, traceback): + OK() + return + +def test_exit(): + with With_exit(): + pass # # 3.4.1. Awaitable Objects # # object.__await__(self) From 639d914a47e014513b82e6d67bac673df518caec Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Mon, 10 Aug 2020 08:58:16 +0200 Subject: [PATCH 019/133] Python: test Awaitable, framework for async test --- .../experimental/dataflow/coverage/classes.py | 18 +++++++++--------- .../dataflow/coverage/validTest.py | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/python/ql/test/experimental/dataflow/coverage/classes.py b/python/ql/test/experimental/dataflow/coverage/classes.py index 6f9a53076ed..ef40e546f7e 100644 --- a/python/ql/test/experimental/dataflow/coverage/classes.py +++ b/python/ql/test/experimental/dataflow/coverage/classes.py @@ -1253,17 +1253,17 @@ def test_exit(): with With_exit(): pass -# # 3.4.1. Awaitable Objects -# # object.__await__(self) -# class With_await: +# 3.4.1. Awaitable Objects +# object.__await__(self) +class With_await: -# def __await__(self): -# OK() -# return "" # edit to match type + def __await__(self): + OK() + return (yield from asyncio.coroutine(lambda: "")()) -# async def test_await(): -# with_await = With_await() -# await(with_await) # edit to effect call +async def atest_await(): + with_await = With_await() + await(with_await) # # 3.4.2. Coroutine Objects diff --git a/python/ql/test/experimental/dataflow/coverage/validTest.py b/python/ql/test/experimental/dataflow/coverage/validTest.py index 97ba6be8cdb..dbede541e82 100644 --- a/python/ql/test/experimental/dataflow/coverage/validTest.py +++ b/python/ql/test/experimental/dataflow/coverage/validTest.py @@ -15,6 +15,18 @@ def check_test_function(f): sys.stdout = old_stdout check_output(capturer.getvalue(), f) +def check_async_test_function(f): + from io import StringIO + import sys + import asyncio + + capturer = StringIO() + old_stdout = sys.stdout + sys.stdout = capturer + asyncio.run(f()) + sys.stdout = old_stdout + check_output(capturer.getvalue(), f) + def check_classes_valid(testFile): # import python.ql.test.experimental.dataflow.coverage.classes as tests # import classes as tests @@ -28,6 +40,12 @@ def check_classes_valid(testFile): print("Checking", testFile, item) check_test_function(item) + elif i.startswith("atest_"): + item = getattr(tests,i) + if callable(item): + print("Checking", testFile, item) + check_async_test_function(item) + if __name__ == '__main__': check_classes_valid("classes") check_classes_valid("test") From 959c6315c41ae2dfa9a3445d3ee6ca863ad8a1f3 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Mon, 10 Aug 2020 09:24:45 +0200 Subject: [PATCH 020/133] Python: update reference to fix tests --- python/ql/test/experimental/dataflow/basic/callGraphSinks.ql | 2 +- python/ql/test/experimental/dataflow/basic/callGraphSources.ql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/ql/test/experimental/dataflow/basic/callGraphSinks.ql b/python/ql/test/experimental/dataflow/basic/callGraphSinks.ql index 020ea245cfd..7d15b353274 100644 --- a/python/ql/test/experimental/dataflow/basic/callGraphSinks.ql +++ b/python/ql/test/experimental/dataflow/basic/callGraphSinks.ql @@ -1,4 +1,4 @@ -import callGraphConfig +import experimental.dataflow.callGraphConfig from DataFlow::Node sink where exists(CallGraphConfig cfg | cfg.isSink(sink)) diff --git a/python/ql/test/experimental/dataflow/basic/callGraphSources.ql b/python/ql/test/experimental/dataflow/basic/callGraphSources.ql index a6bd5538866..21c3a5a9ace 100644 --- a/python/ql/test/experimental/dataflow/basic/callGraphSources.ql +++ b/python/ql/test/experimental/dataflow/basic/callGraphSources.ql @@ -1,4 +1,4 @@ -import callGraphConfig +import experimental.dataflow.callGraphConfig from DataFlow::Node source where exists(CallGraphConfig cfg | cfg.isSource(source)) From a963f15100f2fdd5b5d0b217091fb29d2cf6bf0e Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Mon, 10 Aug 2020 11:54:24 +0200 Subject: [PATCH 021/133] Python: format strings are unnecessary and mess up For some reason, we got no results when format strings were present. --- .../experimental/dataflow/coverage/classes.py | 28 +-- .../coverage/classesCallGraph.expected | 193 ++++++++++-------- .../dataflow/coverage/localFlow.expected | 14 +- 3 files changed, 133 insertions(+), 102 deletions(-) diff --git a/python/ql/test/experimental/dataflow/coverage/classes.py b/python/ql/test/experimental/dataflow/coverage/classes.py index ef40e546f7e..f3b3e013b22 100644 --- a/python/ql/test/experimental/dataflow/coverage/classes.py +++ b/python/ql/test/experimental/dataflow/coverage/classes.py @@ -769,7 +769,7 @@ class With_radd: def test_radd(): with_radd = With_radd() - f"" + with_radd + "" + with_radd # object.__rsub__(self, other) class With_rsub: @@ -780,7 +780,7 @@ class With_rsub: def test_rsub(): with_rsub = With_rsub() - f"" - with_rsub + "" - with_rsub # object.__rmul__(self, other) class With_rmul: @@ -791,7 +791,7 @@ class With_rmul: def test_rmul(): with_rmul = With_rmul() - f"" * with_rmul + "" * with_rmul # object.__rmatmul__(self, other) class With_rmatmul: @@ -802,7 +802,7 @@ class With_rmatmul: def test_rmatmul(): with_rmatmul = With_rmatmul() - f"" @ with_rmatmul + "" @ with_rmatmul # object.__rtruediv__(self, other) class With_rtruediv: @@ -813,7 +813,7 @@ class With_rtruediv: def test_rtruediv(): with_rtruediv = With_rtruediv() - f"" / with_rtruediv + "" / with_rtruediv # object.__rfloordiv__(self, other) class With_rfloordiv: @@ -824,7 +824,7 @@ class With_rfloordiv: def test_rfloordiv(): with_rfloordiv = With_rfloordiv() - f"" // with_rfloordiv + "" // with_rfloordiv # object.__rmod__(self, other) class With_rmod: @@ -846,7 +846,7 @@ class With_rdivmod: def test_rdivmod(): with_rdivmod = With_rdivmod() - divmod(f"", with_rdivmod) + divmod("", with_rdivmod) # object.__rpow__(self, other[, modulo]) class With_rpow: @@ -857,11 +857,11 @@ class With_rpow: def test_rpow(): with_rpow = With_rpow() - pow(f"", with_rpow) + pow("", with_rpow) def test_rpow_op(): with_rpow = With_rpow() - f"" ** with_rpow + "" ** with_rpow # object.__rlshift__(self, other) class With_rlshift: @@ -872,7 +872,7 @@ class With_rlshift: def ftest_rlshift(): # TypeError: unsupported operand type(s) for >>: 'str' and 'With_rlshift' with_rlshift = With_rlshift() - f"" >> with_rlshift + "" >> with_rlshift # object.__rrshift__(self, other) class With_rrshift: @@ -883,7 +883,7 @@ class With_rrshift: def ftest_rrshift(): # TypeError: unsupported operand type(s) for <<: 'str' and 'With_rrshift' with_rrshift = With_rrshift() - f"" << with_rrshift + "" << with_rrshift # object.__rand__(self, other) class With_rand: @@ -894,7 +894,7 @@ class With_rand: def test_rand(): with_rand = With_rand() - f"" & with_rand + "" & with_rand # object.__rxor__(self, other) class With_rxor: @@ -905,7 +905,7 @@ class With_rxor: def test_rxor(): with_rxor = With_rxor() - f"" ^ with_rxor + "" ^ with_rxor # object.__ror__(self, other) class With_ror: @@ -916,7 +916,7 @@ class With_ror: def test_ror(): with_ror = With_ror() - f"" | with_ror + "" | with_ror # object.__iadd__(self, other) class With_iadd: diff --git a/python/ql/test/experimental/dataflow/coverage/classesCallGraph.expected b/python/ql/test/experimental/dataflow/coverage/classesCallGraph.expected index 83773c878c7..23d7c73ac30 100644 --- a/python/ql/test/experimental/dataflow/coverage/classesCallGraph.expected +++ b/python/ql/test/experimental/dataflow/coverage/classesCallGraph.expected @@ -1,81 +1,112 @@ -| classes.py:29:10:29:10 | ControlFlowNode for a | classes.py:17:10:17:10 | SSA variable x | -| classes.py:29:10:29:10 | ControlFlowNode for a | classes.py:31:6:31:17 | ControlFlowNode for f() | -| classes.py:31:6:31:17 | ControlFlowNode for f() | classes.py:17:10:17:10 | SSA variable x | -| classes.py:31:6:31:17 | ControlFlowNode for f() | classes.py:31:6:31:17 | ControlFlowNode for f() | -| classes.py:31:8:31:13 | ControlFlowNode for SOURCE | classes.py:17:10:17:10 | SSA variable x | -| classes.py:31:8:31:13 | ControlFlowNode for SOURCE | classes.py:28:7:28:7 | SSA variable a | -| classes.py:31:8:31:13 | ControlFlowNode for SOURCE | classes.py:31:6:31:17 | ControlFlowNode for f() | -| classes.py:31:16:31:16 | ControlFlowNode for IntegerLiteral | classes.py:28:10:28:10 | SSA variable b | -| classes.py:39:16:39:16 | ControlFlowNode for x | classes.py:17:10:17:10 | SSA variable x | -| classes.py:39:16:39:16 | ControlFlowNode for x | classes.py:64:6:64:24 | ControlFlowNode for Attribute() | -| classes.py:39:16:39:16 | ControlFlowNode for x | classes.py:65:6:65:27 | ControlFlowNode for Attribute() | -| classes.py:43:16:43:16 | ControlFlowNode for x | classes.py:17:10:17:10 | SSA variable x | -| classes.py:43:16:43:16 | ControlFlowNode for x | classes.py:73:6:73:26 | ControlFlowNode for Attribute() | -| classes.py:43:16:43:16 | ControlFlowNode for x | classes.py:74:6:74:26 | ControlFlowNode for Attribute() | -| classes.py:56:14:56:14 | ControlFlowNode for x | classes.py:100:18:100:31 | ControlFlowNode for Attribute() | -| classes.py:64:6:64:24 | ControlFlowNode for Attribute() | classes.py:17:10:17:10 | SSA variable x | -| classes.py:64:6:64:24 | ControlFlowNode for Attribute() | classes.py:64:6:64:24 | ControlFlowNode for Attribute() | -| classes.py:64:15:64:20 | ControlFlowNode for SOURCE | classes.py:17:10:17:10 | SSA variable x | -| classes.py:64:15:64:20 | ControlFlowNode for SOURCE | classes.py:37:16:37:19 | SSA variable self | -| classes.py:64:15:64:20 | ControlFlowNode for SOURCE | classes.py:37:22:37:22 | SSA variable x | -| classes.py:64:15:64:20 | ControlFlowNode for SOURCE | classes.py:64:6:64:24 | ControlFlowNode for Attribute() | -| classes.py:64:23:64:23 | ControlFlowNode for C | classes.py:17:10:17:10 | SSA variable x | -| classes.py:64:23:64:23 | ControlFlowNode for C | classes.py:37:22:37:22 | SSA variable x | -| classes.py:64:23:64:23 | ControlFlowNode for C | classes.py:37:25:37:27 | SSA variable cls | -| classes.py:64:23:64:23 | ControlFlowNode for C | classes.py:64:6:64:24 | ControlFlowNode for Attribute() | -| classes.py:65:6:65:27 | ControlFlowNode for Attribute() | classes.py:17:10:17:10 | SSA variable x | -| classes.py:65:6:65:27 | ControlFlowNode for Attribute() | classes.py:65:6:65:27 | ControlFlowNode for Attribute() | -| classes.py:65:15:65:15 | ControlFlowNode for c | classes.py:37:16:37:19 | SSA variable self | -| classes.py:65:18:65:23 | ControlFlowNode for SOURCE | classes.py:17:10:17:10 | SSA variable x | -| classes.py:65:18:65:23 | ControlFlowNode for SOURCE | classes.py:37:22:37:22 | SSA variable x | -| classes.py:65:18:65:23 | ControlFlowNode for SOURCE | classes.py:65:6:65:27 | ControlFlowNode for Attribute() | -| classes.py:65:26:65:26 | ControlFlowNode for C | classes.py:37:25:37:27 | SSA variable cls | -| classes.py:66:6:66:27 | ControlFlowNode for func_obj() | classes.py:17:10:17:10 | SSA variable x | -| classes.py:66:6:66:27 | ControlFlowNode for func_obj() | classes.py:66:6:66:27 | ControlFlowNode for func_obj() | -| classes.py:73:6:73:26 | ControlFlowNode for Attribute() | classes.py:17:10:17:10 | SSA variable x | -| classes.py:73:6:73:26 | ControlFlowNode for Attribute() | classes.py:73:6:73:26 | ControlFlowNode for Attribute() | -| classes.py:73:20:73:25 | ControlFlowNode for SOURCE | classes.py:17:10:17:10 | SSA variable x | -| classes.py:73:20:73:25 | ControlFlowNode for SOURCE | classes.py:42:21:42:23 | SSA variable cls | -| classes.py:73:20:73:25 | ControlFlowNode for SOURCE | classes.py:42:26:42:26 | SSA variable x | -| classes.py:73:20:73:25 | ControlFlowNode for SOURCE | classes.py:73:6:73:26 | ControlFlowNode for Attribute() | -| classes.py:74:6:74:26 | ControlFlowNode for Attribute() | classes.py:17:10:17:10 | SSA variable x | -| classes.py:74:6:74:26 | ControlFlowNode for Attribute() | classes.py:74:6:74:26 | ControlFlowNode for Attribute() | -| classes.py:74:20:74:25 | ControlFlowNode for SOURCE | classes.py:17:10:17:10 | SSA variable x | -| classes.py:74:20:74:25 | ControlFlowNode for SOURCE | classes.py:42:21:42:23 | SSA variable cls | -| classes.py:74:20:74:25 | ControlFlowNode for SOURCE | classes.py:42:26:42:26 | SSA variable x | -| classes.py:74:20:74:25 | ControlFlowNode for SOURCE | classes.py:74:6:74:26 | ControlFlowNode for Attribute() | -| classes.py:75:6:75:26 | ControlFlowNode for c_func_obj() | classes.py:17:10:17:10 | SSA variable x | -| classes.py:75:6:75:26 | ControlFlowNode for c_func_obj() | classes.py:75:6:75:26 | ControlFlowNode for c_func_obj() | -| classes.py:85:12:85:17 | ControlFlowNode for SOURCE | classes.py:79:9:79:9 | SSA variable x | -| classes.py:85:20:85:20 | ControlFlowNode for IntegerLiteral | classes.py:79:12:79:16 | SSA variable count | -| classes.py:86:6:86:20 | ControlFlowNode for Attribute() | classes.py:17:10:17:10 | SSA variable x | -| classes.py:86:6:86:20 | ControlFlowNode for Attribute() | classes.py:86:6:86:20 | ControlFlowNode for Attribute() | -| classes.py:87:8:87:22 | ControlFlowNode for Attribute() | classes.py:20:12:20:12 | SSA variable x | -| classes.py:87:8:87:22 | ControlFlowNode for Attribute() | classes.py:87:8:87:22 | ControlFlowNode for Attribute() | -| classes.py:89:15:89:20 | ControlFlowNode for SOURCE | classes.py:49:13:49:16 | SSA variable self | -| classes.py:89:15:89:20 | ControlFlowNode for SOURCE | classes.py:49:19:49:19 | SSA variable x | -| classes.py:89:23:89:23 | ControlFlowNode for IntegerLiteral | classes.py:49:19:49:19 | SSA variable x | -| classes.py:89:23:89:23 | ControlFlowNode for IntegerLiteral | classes.py:49:22:49:26 | SSA variable count | -| classes.py:90:6:90:21 | ControlFlowNode for Attribute() | classes.py:17:10:17:10 | SSA variable x | -| classes.py:90:6:90:21 | ControlFlowNode for Attribute() | classes.py:90:6:90:21 | ControlFlowNode for Attribute() | -| classes.py:91:8:91:23 | ControlFlowNode for Attribute() | classes.py:20:12:20:12 | SSA variable x | -| classes.py:91:8:91:23 | ControlFlowNode for Attribute() | classes.py:91:8:91:23 | ControlFlowNode for Attribute() | -| classes.py:96:10:96:10 | ControlFlowNode for x | classes.py:99:18:99:29 | ControlFlowNode for coro() | -| classes.py:99:6:99:30 | ControlFlowNode for Attribute() | classes.py:17:10:17:10 | SSA variable x | -| classes.py:99:6:99:30 | ControlFlowNode for Attribute() | classes.py:99:6:99:30 | ControlFlowNode for Attribute() | -| classes.py:99:23:99:28 | ControlFlowNode for SOURCE | classes.py:95:16:95:16 | SSA variable x | -| classes.py:99:23:99:28 | ControlFlowNode for SOURCE | classes.py:99:18:99:29 | ControlFlowNode for coro() | -| classes.py:100:6:100:32 | ControlFlowNode for Attribute() | classes.py:17:10:17:10 | SSA variable x | -| classes.py:100:6:100:32 | ControlFlowNode for Attribute() | classes.py:100:6:100:32 | ControlFlowNode for Attribute() | -| classes.py:100:25:100:30 | ControlFlowNode for SOURCE | classes.py:55:20:55:23 | SSA variable self | -| classes.py:100:25:100:30 | ControlFlowNode for SOURCE | classes.py:55:26:55:26 | SSA variable x | -| classes.py:100:25:100:30 | ControlFlowNode for SOURCE | classes.py:100:18:100:31 | ControlFlowNode for Attribute() | -| classes.py:110:10:110:16 | ControlFlowNode for Await | classes.py:112:18:112:29 | ControlFlowNode for agen() | -| classes.py:112:6:112:30 | ControlFlowNode for Attribute() | classes.py:17:10:17:10 | SSA variable x | -| classes.py:112:6:112:30 | ControlFlowNode for Attribute() | classes.py:112:6:112:30 | ControlFlowNode for Attribute() | -| classes.py:112:23:112:28 | ControlFlowNode for SOURCE | classes.py:108:16:108:16 | SSA variable x | -| classes.py:142:12:142:31 | ControlFlowNode for Attribute() | classes.py:142:12:142:31 | ControlFlowNode for Attribute() | -| classes.py:150:6:150:17 | ControlFlowNode for Attribute | classes.py:17:10:17:10 | SSA variable x | -| classes.py:151:8:151:19 | ControlFlowNode for Attribute | classes.py:20:12:20:12 | SSA variable x | -| classes.py:152:6:152:17 | ControlFlowNode for Attribute | classes.py:17:10:17:10 | SSA variable x | -| classes.py:153:6:153:17 | ControlFlowNode for Attribute | classes.py:17:10:17:10 | SSA variable x | +| classes.py:21:12:21:78 | ControlFlowNode for BoolExpr | classes.py:24:8:24:19 | ControlFlowNode for is_source() | +| classes.py:21:12:21:78 | ControlFlowNode for BoolExpr | classes.py:30:8:30:19 | ControlFlowNode for is_source() | +| classes.py:24:18:24:18 | ControlFlowNode for x | classes.py:20:15:20:15 | SSA variable x | +| classes.py:30:18:30:18 | ControlFlowNode for x | classes.py:20:15:20:15 | SSA variable x | +| classes.py:41:10:41:10 | ControlFlowNode for a | classes.py:20:15:20:15 | SSA variable x | +| classes.py:41:10:41:10 | ControlFlowNode for a | classes.py:23:10:23:10 | SSA variable x | +| classes.py:41:10:41:10 | ControlFlowNode for a | classes.py:43:6:43:17 | ControlFlowNode for f() | +| classes.py:43:6:43:17 | ControlFlowNode for f() | classes.py:20:15:20:15 | SSA variable x | +| classes.py:43:6:43:17 | ControlFlowNode for f() | classes.py:23:10:23:10 | SSA variable x | +| classes.py:43:6:43:17 | ControlFlowNode for f() | classes.py:43:6:43:17 | ControlFlowNode for f() | +| classes.py:43:8:43:13 | ControlFlowNode for SOURCE | classes.py:20:15:20:15 | SSA variable x | +| classes.py:43:8:43:13 | ControlFlowNode for SOURCE | classes.py:23:10:23:10 | SSA variable x | +| classes.py:43:8:43:13 | ControlFlowNode for SOURCE | classes.py:40:7:40:7 | SSA variable a | +| classes.py:43:8:43:13 | ControlFlowNode for SOURCE | classes.py:43:6:43:17 | ControlFlowNode for f() | +| classes.py:43:16:43:16 | ControlFlowNode for IntegerLiteral | classes.py:40:10:40:10 | SSA variable b | +| classes.py:51:16:51:16 | ControlFlowNode for x | classes.py:20:15:20:15 | SSA variable x | +| classes.py:51:16:51:16 | ControlFlowNode for x | classes.py:23:10:23:10 | SSA variable x | +| classes.py:51:16:51:16 | ControlFlowNode for x | classes.py:76:6:76:24 | ControlFlowNode for Attribute() | +| classes.py:51:16:51:16 | ControlFlowNode for x | classes.py:77:6:77:27 | ControlFlowNode for Attribute() | +| classes.py:55:16:55:16 | ControlFlowNode for x | classes.py:20:15:20:15 | SSA variable x | +| classes.py:55:16:55:16 | ControlFlowNode for x | classes.py:23:10:23:10 | SSA variable x | +| classes.py:55:16:55:16 | ControlFlowNode for x | classes.py:85:6:85:26 | ControlFlowNode for Attribute() | +| classes.py:55:16:55:16 | ControlFlowNode for x | classes.py:86:6:86:26 | ControlFlowNode for Attribute() | +| classes.py:68:14:68:14 | ControlFlowNode for x | classes.py:112:18:112:31 | ControlFlowNode for Attribute() | +| classes.py:76:6:76:24 | ControlFlowNode for Attribute() | classes.py:20:15:20:15 | SSA variable x | +| classes.py:76:6:76:24 | ControlFlowNode for Attribute() | classes.py:23:10:23:10 | SSA variable x | +| classes.py:76:6:76:24 | ControlFlowNode for Attribute() | classes.py:76:6:76:24 | ControlFlowNode for Attribute() | +| classes.py:76:15:76:20 | ControlFlowNode for SOURCE | classes.py:20:15:20:15 | SSA variable x | +| classes.py:76:15:76:20 | ControlFlowNode for SOURCE | classes.py:23:10:23:10 | SSA variable x | +| classes.py:76:15:76:20 | ControlFlowNode for SOURCE | classes.py:49:16:49:19 | SSA variable self | +| classes.py:76:15:76:20 | ControlFlowNode for SOURCE | classes.py:49:22:49:22 | SSA variable x | +| classes.py:76:15:76:20 | ControlFlowNode for SOURCE | classes.py:76:6:76:24 | ControlFlowNode for Attribute() | +| classes.py:76:23:76:23 | ControlFlowNode for C | classes.py:20:15:20:15 | SSA variable x | +| classes.py:76:23:76:23 | ControlFlowNode for C | classes.py:23:10:23:10 | SSA variable x | +| classes.py:76:23:76:23 | ControlFlowNode for C | classes.py:49:22:49:22 | SSA variable x | +| classes.py:76:23:76:23 | ControlFlowNode for C | classes.py:49:25:49:27 | SSA variable cls | +| classes.py:76:23:76:23 | ControlFlowNode for C | classes.py:76:6:76:24 | ControlFlowNode for Attribute() | +| classes.py:77:6:77:27 | ControlFlowNode for Attribute() | classes.py:20:15:20:15 | SSA variable x | +| classes.py:77:6:77:27 | ControlFlowNode for Attribute() | classes.py:23:10:23:10 | SSA variable x | +| classes.py:77:6:77:27 | ControlFlowNode for Attribute() | classes.py:77:6:77:27 | ControlFlowNode for Attribute() | +| classes.py:77:15:77:15 | ControlFlowNode for c | classes.py:49:16:49:19 | SSA variable self | +| classes.py:77:18:77:23 | ControlFlowNode for SOURCE | classes.py:20:15:20:15 | SSA variable x | +| classes.py:77:18:77:23 | ControlFlowNode for SOURCE | classes.py:23:10:23:10 | SSA variable x | +| classes.py:77:18:77:23 | ControlFlowNode for SOURCE | classes.py:49:22:49:22 | SSA variable x | +| classes.py:77:18:77:23 | ControlFlowNode for SOURCE | classes.py:77:6:77:27 | ControlFlowNode for Attribute() | +| classes.py:77:26:77:26 | ControlFlowNode for C | classes.py:49:25:49:27 | SSA variable cls | +| classes.py:78:6:78:27 | ControlFlowNode for func_obj() | classes.py:20:15:20:15 | SSA variable x | +| classes.py:78:6:78:27 | ControlFlowNode for func_obj() | classes.py:23:10:23:10 | SSA variable x | +| classes.py:78:6:78:27 | ControlFlowNode for func_obj() | classes.py:78:6:78:27 | ControlFlowNode for func_obj() | +| classes.py:85:6:85:26 | ControlFlowNode for Attribute() | classes.py:20:15:20:15 | SSA variable x | +| classes.py:85:6:85:26 | ControlFlowNode for Attribute() | classes.py:23:10:23:10 | SSA variable x | +| classes.py:85:6:85:26 | ControlFlowNode for Attribute() | classes.py:85:6:85:26 | ControlFlowNode for Attribute() | +| classes.py:85:20:85:25 | ControlFlowNode for SOURCE | classes.py:20:15:20:15 | SSA variable x | +| classes.py:85:20:85:25 | ControlFlowNode for SOURCE | classes.py:23:10:23:10 | SSA variable x | +| classes.py:85:20:85:25 | ControlFlowNode for SOURCE | classes.py:54:21:54:23 | SSA variable cls | +| classes.py:85:20:85:25 | ControlFlowNode for SOURCE | classes.py:54:26:54:26 | SSA variable x | +| classes.py:85:20:85:25 | ControlFlowNode for SOURCE | classes.py:85:6:85:26 | ControlFlowNode for Attribute() | +| classes.py:86:6:86:26 | ControlFlowNode for Attribute() | classes.py:20:15:20:15 | SSA variable x | +| classes.py:86:6:86:26 | ControlFlowNode for Attribute() | classes.py:23:10:23:10 | SSA variable x | +| classes.py:86:6:86:26 | ControlFlowNode for Attribute() | classes.py:86:6:86:26 | ControlFlowNode for Attribute() | +| classes.py:86:20:86:25 | ControlFlowNode for SOURCE | classes.py:20:15:20:15 | SSA variable x | +| classes.py:86:20:86:25 | ControlFlowNode for SOURCE | classes.py:23:10:23:10 | SSA variable x | +| classes.py:86:20:86:25 | ControlFlowNode for SOURCE | classes.py:54:21:54:23 | SSA variable cls | +| classes.py:86:20:86:25 | ControlFlowNode for SOURCE | classes.py:54:26:54:26 | SSA variable x | +| classes.py:86:20:86:25 | ControlFlowNode for SOURCE | classes.py:86:6:86:26 | ControlFlowNode for Attribute() | +| classes.py:87:6:87:26 | ControlFlowNode for c_func_obj() | classes.py:20:15:20:15 | SSA variable x | +| classes.py:87:6:87:26 | ControlFlowNode for c_func_obj() | classes.py:23:10:23:10 | SSA variable x | +| classes.py:87:6:87:26 | ControlFlowNode for c_func_obj() | classes.py:87:6:87:26 | ControlFlowNode for c_func_obj() | +| classes.py:97:12:97:17 | ControlFlowNode for SOURCE | classes.py:91:9:91:9 | SSA variable x | +| classes.py:97:20:97:20 | ControlFlowNode for IntegerLiteral | classes.py:91:12:91:16 | SSA variable count | +| classes.py:98:6:98:20 | ControlFlowNode for Attribute() | classes.py:20:15:20:15 | SSA variable x | +| classes.py:98:6:98:20 | ControlFlowNode for Attribute() | classes.py:23:10:23:10 | SSA variable x | +| classes.py:98:6:98:20 | ControlFlowNode for Attribute() | classes.py:98:6:98:20 | ControlFlowNode for Attribute() | +| classes.py:101:15:101:20 | ControlFlowNode for SOURCE | classes.py:61:13:61:16 | SSA variable self | +| classes.py:101:15:101:20 | ControlFlowNode for SOURCE | classes.py:61:19:61:19 | SSA variable x | +| classes.py:101:23:101:23 | ControlFlowNode for IntegerLiteral | classes.py:61:19:61:19 | SSA variable x | +| classes.py:101:23:101:23 | ControlFlowNode for IntegerLiteral | classes.py:61:22:61:26 | SSA variable count | +| classes.py:102:6:102:21 | ControlFlowNode for Attribute() | classes.py:20:15:20:15 | SSA variable x | +| classes.py:102:6:102:21 | ControlFlowNode for Attribute() | classes.py:23:10:23:10 | SSA variable x | +| classes.py:102:6:102:21 | ControlFlowNode for Attribute() | classes.py:102:6:102:21 | ControlFlowNode for Attribute() | +| classes.py:108:10:108:10 | ControlFlowNode for x | classes.py:111:18:111:29 | ControlFlowNode for coro() | +| classes.py:111:6:111:30 | ControlFlowNode for Attribute() | classes.py:20:15:20:15 | SSA variable x | +| classes.py:111:6:111:30 | ControlFlowNode for Attribute() | classes.py:23:10:23:10 | SSA variable x | +| classes.py:111:6:111:30 | ControlFlowNode for Attribute() | classes.py:111:6:111:30 | ControlFlowNode for Attribute() | +| classes.py:111:23:111:28 | ControlFlowNode for SOURCE | classes.py:107:16:107:16 | SSA variable x | +| classes.py:111:23:111:28 | ControlFlowNode for SOURCE | classes.py:111:18:111:29 | ControlFlowNode for coro() | +| classes.py:112:6:112:32 | ControlFlowNode for Attribute() | classes.py:20:15:20:15 | SSA variable x | +| classes.py:112:6:112:32 | ControlFlowNode for Attribute() | classes.py:23:10:23:10 | SSA variable x | +| classes.py:112:6:112:32 | ControlFlowNode for Attribute() | classes.py:112:6:112:32 | ControlFlowNode for Attribute() | +| classes.py:112:25:112:30 | ControlFlowNode for SOURCE | classes.py:67:20:67:23 | SSA variable self | +| classes.py:112:25:112:30 | ControlFlowNode for SOURCE | classes.py:67:26:67:26 | SSA variable x | +| classes.py:112:25:112:30 | ControlFlowNode for SOURCE | classes.py:112:18:112:31 | ControlFlowNode for Attribute() | +| classes.py:122:10:122:16 | ControlFlowNode for Await | classes.py:124:18:124:29 | ControlFlowNode for agen() | +| classes.py:124:6:124:30 | ControlFlowNode for Attribute() | classes.py:20:15:20:15 | SSA variable x | +| classes.py:124:6:124:30 | ControlFlowNode for Attribute() | classes.py:23:10:23:10 | SSA variable x | +| classes.py:124:6:124:30 | ControlFlowNode for Attribute() | classes.py:124:6:124:30 | ControlFlowNode for Attribute() | +| classes.py:124:23:124:28 | ControlFlowNode for SOURCE | classes.py:120:16:120:16 | SSA variable x | +| classes.py:154:12:154:31 | ControlFlowNode for Attribute() | classes.py:154:12:154:31 | ControlFlowNode for Attribute() | +| classes.py:161:6:161:17 | ControlFlowNode for Attribute | classes.py:20:15:20:15 | SSA variable x | +| classes.py:161:6:161:17 | ControlFlowNode for Attribute | classes.py:23:10:23:10 | SSA variable x | +| classes.py:162:8:162:19 | ControlFlowNode for Attribute | classes.py:20:15:20:15 | SSA variable x | +| classes.py:162:8:162:19 | ControlFlowNode for Attribute | classes.py:29:12:29:12 | SSA variable x | +| classes.py:163:6:163:17 | ControlFlowNode for Attribute | classes.py:20:15:20:15 | SSA variable x | +| classes.py:163:6:163:17 | ControlFlowNode for Attribute | classes.py:23:10:23:10 | SSA variable x | +| classes.py:164:6:164:17 | ControlFlowNode for Attribute | classes.py:20:15:20:15 | SSA variable x | +| classes.py:164:6:164:17 | ControlFlowNode for Attribute | classes.py:23:10:23:10 | SSA variable x | +| classes.py:174:12:174:31 | ControlFlowNode for Attribute() | classes.py:174:12:174:31 | ControlFlowNode for Attribute() | +| classes.py:329:7:329:22 | ControlFlowNode for set() | classes.py:329:7:329:22 | ControlFlowNode for set() | +| classes.py:333:7:333:28 | ControlFlowNode for frozenset() | classes.py:333:7:333:28 | ControlFlowNode for frozenset() | +| classes.py:337:7:337:26 | ControlFlowNode for dict() | classes.py:337:7:337:26 | ControlFlowNode for dict() | +| classes.py:458:28:458:51 | ControlFlowNode for dict() | classes.py:458:28:458:51 | ControlFlowNode for dict() | +| classes.py:575:12:575:24 | ControlFlowNode for Attribute() | classes.py:575:12:575:24 | ControlFlowNode for Attribute() | diff --git a/python/ql/test/experimental/dataflow/coverage/localFlow.expected b/python/ql/test/experimental/dataflow/coverage/localFlow.expected index eee5e093f5e..9e4dc40eafc 100644 --- a/python/ql/test/experimental/dataflow/coverage/localFlow.expected +++ b/python/ql/test/experimental/dataflow/coverage/localFlow.expected @@ -1,7 +1,7 @@ -| test.py:24:5:24:5 | SSA variable x | test.py:23:1:23:33 | Exit node for Function test_tuple_with_local_flow | -| test.py:24:5:24:5 | SSA variable x | test.py:25:9:25:9 | ControlFlowNode for x | -| test.py:24:10:24:26 | ControlFlowNode for Tuple | test.py:24:5:24:5 | SSA variable x | -| test.py:25:5:25:5 | SSA variable y | test.py:26:5:26:11 | SSA variable y | -| test.py:25:5:25:5 | SSA variable y | test.py:26:10:26:10 | ControlFlowNode for y | -| test.py:25:9:25:12 | ControlFlowNode for Subscript | test.py:25:5:25:5 | SSA variable y | -| test.py:26:5:26:11 | SSA variable y | test.py:23:1:23:33 | Exit node for Function test_tuple_with_local_flow | +| test.py:32:5:32:5 | SSA variable x | test.py:31:1:31:33 | Exit node for Function test_tuple_with_local_flow | +| test.py:32:5:32:5 | SSA variable x | test.py:33:9:33:9 | ControlFlowNode for x | +| test.py:32:10:32:26 | ControlFlowNode for Tuple | test.py:32:5:32:5 | SSA variable x | +| test.py:33:5:33:5 | SSA variable y | test.py:34:5:34:11 | SSA variable y | +| test.py:33:5:33:5 | SSA variable y | test.py:34:10:34:10 | ControlFlowNode for y | +| test.py:33:9:33:12 | ControlFlowNode for Subscript | test.py:33:5:33:5 | SSA variable y | +| test.py:34:5:34:11 | SSA variable y | test.py:31:1:31:33 | Exit node for Function test_tuple_with_local_flow | From 5da37f5cf4c0797feb8b1394d425c30e1309e4c7 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Mon, 10 Aug 2020 17:07:00 +0200 Subject: [PATCH 022/133] Python: Update test expectations --- .../experimental/dataflow/coverage/classes.py | 6 +- .../dataflow/coverage/dataflow.expected | 339 +++++++++--------- 2 files changed, 165 insertions(+), 180 deletions(-) diff --git a/python/ql/test/experimental/dataflow/coverage/classes.py b/python/ql/test/experimental/dataflow/coverage/classes.py index f3b3e013b22..3f47b69c943 100644 --- a/python/ql/test/experimental/dataflow/coverage/classes.py +++ b/python/ql/test/experimental/dataflow/coverage/classes.py @@ -1197,7 +1197,7 @@ class With_trunc: def test_trunc(): with_trunc = With_trunc() import math - math.trunc(with_trunc) # edit to effect call + math.trunc(with_trunc) # object.__floor__(self) class With_floor: @@ -1209,7 +1209,7 @@ class With_floor: def test_floor(): with_floor = With_floor() import math - math.floor(with_floor) # edit to effect call + math.floor(with_floor) # object.__ceil__(self) class With_ceil: @@ -1221,7 +1221,7 @@ class With_ceil: def test_ceil(): with_ceil = With_ceil() import math - math.ceil(with_ceil) # edit to effect call + math.ceil(with_ceil) # 3.3.9. With Statement Context Managers diff --git a/python/ql/test/experimental/dataflow/coverage/dataflow.expected b/python/ql/test/experimental/dataflow/coverage/dataflow.expected index 6713969a2e4..700da23c5ef 100644 --- a/python/ql/test/experimental/dataflow/coverage/dataflow.expected +++ b/python/ql/test/experimental/dataflow/coverage/dataflow.expected @@ -1,182 +1,167 @@ edges -| classes.py:16:1:16:6 | GSSA Variable SOURCE | classes.py:31:6:31:17 | ControlFlowNode for f() | -| classes.py:16:1:16:6 | GSSA Variable SOURCE | classes.py:31:6:31:17 | GSSA Variable SOURCE | -| classes.py:16:1:16:6 | GSSA Variable SOURCE | classes.py:31:8:31:13 | ControlFlowNode for SOURCE | -| classes.py:16:10:16:17 | ControlFlowNode for Str | classes.py:16:1:16:6 | GSSA Variable SOURCE | -| classes.py:31:6:31:17 | GSSA Variable SOURCE | classes.py:58:5:58:7 | ControlFlowNode for C() | -| classes.py:31:6:31:17 | GSSA Variable SOURCE | classes.py:64:6:64:24 | ControlFlowNode for Attribute() | -| classes.py:31:6:31:17 | GSSA Variable SOURCE | classes.py:64:6:64:24 | GSSA Variable SOURCE | -| classes.py:31:6:31:17 | GSSA Variable SOURCE | classes.py:64:15:64:20 | ControlFlowNode for SOURCE | -| classes.py:31:8:31:13 | ControlFlowNode for SOURCE | classes.py:31:6:31:17 | ControlFlowNode for f() | -| classes.py:58:1:58:1 | GSSA Variable c | classes.py:64:6:64:24 | ControlFlowNode for Attribute() | -| classes.py:58:1:58:1 | GSSA Variable c | classes.py:64:6:64:24 | GSSA Variable c | -| classes.py:58:5:58:7 | ControlFlowNode for C() | classes.py:58:1:58:1 | GSSA Variable c | -| classes.py:64:6:64:24 | GSSA Variable SOURCE | classes.py:65:6:65:27 | ControlFlowNode for Attribute() | -| classes.py:64:6:64:24 | GSSA Variable SOURCE | classes.py:65:18:65:23 | ControlFlowNode for SOURCE | -| classes.py:64:6:64:24 | GSSA Variable SOURCE | classes.py:66:6:66:27 | ControlFlowNode for func_obj() | -| classes.py:64:6:64:24 | GSSA Variable SOURCE | classes.py:73:6:73:26 | ControlFlowNode for Attribute() | -| classes.py:64:6:64:24 | GSSA Variable SOURCE | classes.py:73:6:73:26 | GSSA Variable SOURCE | -| classes.py:64:6:64:24 | GSSA Variable SOURCE | classes.py:73:20:73:25 | ControlFlowNode for SOURCE | -| classes.py:64:6:64:24 | GSSA Variable c | classes.py:65:6:65:27 | ControlFlowNode for Attribute() | -| classes.py:64:6:64:24 | GSSA Variable c | classes.py:65:6:65:27 | GSSA Variable c | -| classes.py:64:15:64:20 | ControlFlowNode for SOURCE | classes.py:64:6:64:24 | ControlFlowNode for Attribute() | -| classes.py:65:6:65:27 | GSSA Variable c | classes.py:66:6:66:27 | ControlFlowNode for func_obj() | -| classes.py:65:6:65:27 | GSSA Variable c | classes.py:66:6:66:27 | GSSA Variable c | -| classes.py:65:18:65:23 | ControlFlowNode for SOURCE | classes.py:65:6:65:27 | ControlFlowNode for Attribute() | -| classes.py:66:6:66:27 | GSSA Variable c | classes.py:73:6:73:26 | ControlFlowNode for Attribute() | -| classes.py:66:6:66:27 | GSSA Variable c | classes.py:73:6:73:26 | GSSA Variable c | -| classes.py:73:6:73:26 | GSSA Variable SOURCE | classes.py:74:6:74:26 | ControlFlowNode for Attribute() | -| classes.py:73:6:73:26 | GSSA Variable SOURCE | classes.py:74:6:74:26 | GSSA Variable SOURCE | -| classes.py:73:6:73:26 | GSSA Variable SOURCE | classes.py:74:20:74:25 | ControlFlowNode for SOURCE | -| classes.py:73:6:73:26 | GSSA Variable c | classes.py:74:6:74:26 | ControlFlowNode for Attribute() | -| classes.py:73:6:73:26 | GSSA Variable c | classes.py:75:6:75:26 | ControlFlowNode for c_func_obj() | -| classes.py:73:6:73:26 | GSSA Variable c | classes.py:85:8:85:21 | ControlFlowNode for gen() | -| classes.py:73:6:73:26 | GSSA Variable c | classes.py:86:6:86:20 | ControlFlowNode for Attribute() | -| classes.py:73:6:73:26 | GSSA Variable c | classes.py:87:8:87:22 | ControlFlowNode for Attribute() | -| classes.py:73:6:73:26 | GSSA Variable c | classes.py:89:9:89:24 | ControlFlowNode for Attribute() | -| classes.py:73:6:73:26 | GSSA Variable c | classes.py:89:9:89:24 | GSSA Variable c | -| classes.py:73:20:73:25 | ControlFlowNode for SOURCE | classes.py:73:6:73:26 | ControlFlowNode for Attribute() | -| classes.py:74:6:74:26 | GSSA Variable SOURCE | classes.py:75:6:75:26 | ControlFlowNode for c_func_obj() | -| classes.py:74:6:74:26 | GSSA Variable SOURCE | classes.py:85:8:85:21 | ControlFlowNode for gen() | -| classes.py:74:6:74:26 | GSSA Variable SOURCE | classes.py:85:8:85:21 | GSSA Variable SOURCE | -| classes.py:74:20:74:25 | ControlFlowNode for SOURCE | classes.py:74:6:74:26 | ControlFlowNode for Attribute() | -| classes.py:85:1:85:4 | GSSA Variable iter | classes.py:86:6:86:20 | ControlFlowNode for Attribute() | -| classes.py:85:1:85:4 | GSSA Variable iter | classes.py:86:6:86:20 | GSSA Variable iter | -| classes.py:85:8:85:21 | ControlFlowNode for gen() | classes.py:85:1:85:4 | GSSA Variable iter | -| classes.py:85:8:85:21 | GSSA Variable SOURCE | classes.py:86:6:86:20 | ControlFlowNode for Attribute() | -| classes.py:85:8:85:21 | GSSA Variable SOURCE | classes.py:87:8:87:22 | ControlFlowNode for Attribute() | -| classes.py:85:8:85:21 | GSSA Variable SOURCE | classes.py:89:9:89:24 | ControlFlowNode for Attribute() | -| classes.py:85:8:85:21 | GSSA Variable SOURCE | classes.py:89:9:89:24 | GSSA Variable SOURCE | -| classes.py:86:6:86:20 | GSSA Variable iter | classes.py:87:8:87:22 | ControlFlowNode for Attribute() | -| classes.py:86:6:86:20 | GSSA Variable iter | classes.py:87:8:87:22 | GSSA Variable iter | -| classes.py:87:8:87:22 | GSSA Variable iter | classes.py:89:9:89:24 | ControlFlowNode for Attribute() | -| classes.py:87:8:87:22 | GSSA Variable iter | classes.py:90:6:90:21 | ControlFlowNode for Attribute() | -| classes.py:87:8:87:22 | GSSA Variable iter | classes.py:91:8:91:23 | ControlFlowNode for Attribute() | -| classes.py:87:8:87:22 | GSSA Variable iter | classes.py:99:6:99:30 | ControlFlowNode for Attribute() | -| classes.py:87:8:87:22 | GSSA Variable iter | classes.py:100:6:100:32 | ControlFlowNode for Attribute() | -| classes.py:87:8:87:22 | GSSA Variable iter | classes.py:112:6:112:30 | ControlFlowNode for Attribute() | -| classes.py:89:1:89:5 | GSSA Variable oiter | classes.py:90:6:90:21 | ControlFlowNode for Attribute() | -| classes.py:89:1:89:5 | GSSA Variable oiter | classes.py:90:6:90:21 | GSSA Variable oiter | -| classes.py:89:9:89:24 | ControlFlowNode for Attribute() | classes.py:89:1:89:5 | GSSA Variable oiter | -| classes.py:89:9:89:24 | GSSA Variable SOURCE | classes.py:90:6:90:21 | ControlFlowNode for Attribute() | -| classes.py:89:9:89:24 | GSSA Variable SOURCE | classes.py:91:8:91:23 | ControlFlowNode for Attribute() | -| classes.py:89:9:89:24 | GSSA Variable SOURCE | classes.py:99:18:99:29 | GSSA Variable SOURCE | -| classes.py:89:9:89:24 | GSSA Variable c | classes.py:90:6:90:21 | ControlFlowNode for Attribute() | -| classes.py:89:9:89:24 | GSSA Variable c | classes.py:91:8:91:23 | ControlFlowNode for Attribute() | -| classes.py:89:9:89:24 | GSSA Variable c | classes.py:99:6:99:30 | ControlFlowNode for Attribute() | -| classes.py:89:9:89:24 | GSSA Variable c | classes.py:100:18:100:31 | GSSA Variable c | -| classes.py:90:6:90:21 | GSSA Variable oiter | classes.py:91:8:91:23 | ControlFlowNode for Attribute() | -| classes.py:90:6:90:21 | GSSA Variable oiter | classes.py:91:8:91:23 | GSSA Variable oiter | -| classes.py:91:8:91:23 | GSSA Variable oiter | classes.py:99:6:99:30 | ControlFlowNode for Attribute() | -| classes.py:91:8:91:23 | GSSA Variable oiter | classes.py:100:6:100:32 | ControlFlowNode for Attribute() | -| classes.py:91:8:91:23 | GSSA Variable oiter | classes.py:112:6:112:30 | ControlFlowNode for Attribute() | -| classes.py:99:18:99:29 | GSSA Variable SOURCE | classes.py:99:6:99:30 | ControlFlowNode for Attribute() | -| classes.py:99:18:99:29 | GSSA Variable SOURCE | classes.py:100:18:100:31 | GSSA Variable SOURCE | -| classes.py:100:18:100:31 | GSSA Variable SOURCE | classes.py:100:6:100:32 | ControlFlowNode for Attribute() | -| classes.py:100:18:100:31 | GSSA Variable SOURCE | classes.py:112:18:112:29 | GSSA Variable SOURCE | -| classes.py:100:18:100:31 | GSSA Variable c | classes.py:100:6:100:32 | ControlFlowNode for Attribute() | -| classes.py:100:18:100:31 | GSSA Variable c | classes.py:112:6:112:30 | ControlFlowNode for Attribute() | -| classes.py:112:18:112:29 | GSSA Variable SOURCE | classes.py:112:6:112:30 | ControlFlowNode for Attribute() | -| test.py:35:9:35:14 | ControlFlowNode for SOURCE | test.py:36:10:36:10 | ControlFlowNode for x | -| test.py:40:9:40:16 | ControlFlowNode for Str | test.py:41:10:41:10 | ControlFlowNode for x | -| test.py:44:9:44:17 | ControlFlowNode for Str | test.py:45:10:45:10 | ControlFlowNode for x | -| test.py:48:9:48:10 | ControlFlowNode for IntegerLiteral | test.py:49:10:49:10 | ControlFlowNode for x | -| test.py:52:9:52:12 | ControlFlowNode for FloatLiteral | test.py:53:10:53:10 | ControlFlowNode for x | -| test.py:61:10:61:15 | ControlFlowNode for SOURCE | test.py:62:10:62:10 | ControlFlowNode for x | -| test.py:238:28:238:33 | ControlFlowNode for SOURCE | test.py:238:10:238:34 | ControlFlowNode for second() | -| test.py:297:12:297:17 | ControlFlowNode for SOURCE | test.py:297:10:297:18 | ControlFlowNode for f() | -| test.py:301:28:301:33 | ControlFlowNode for SOURCE | test.py:301:10:301:34 | ControlFlowNode for second() | +| classes.py:18:1:18:6 | GSSA Variable SOURCE | classes.py:43:6:43:17 | ControlFlowNode for f() | +| classes.py:18:1:18:6 | GSSA Variable SOURCE | classes.py:43:6:43:17 | GSSA Variable SOURCE | +| classes.py:18:1:18:6 | GSSA Variable SOURCE | classes.py:43:8:43:13 | ControlFlowNode for SOURCE | +| classes.py:18:10:18:17 | ControlFlowNode for Str | classes.py:18:1:18:6 | GSSA Variable SOURCE | +| classes.py:43:6:43:17 | GSSA Variable SOURCE | classes.py:70:5:70:7 | ControlFlowNode for C() | +| classes.py:43:6:43:17 | GSSA Variable SOURCE | classes.py:76:6:76:24 | ControlFlowNode for Attribute() | +| classes.py:43:6:43:17 | GSSA Variable SOURCE | classes.py:76:6:76:24 | GSSA Variable SOURCE | +| classes.py:43:6:43:17 | GSSA Variable SOURCE | classes.py:76:15:76:20 | ControlFlowNode for SOURCE | +| classes.py:43:8:43:13 | ControlFlowNode for SOURCE | classes.py:43:6:43:17 | ControlFlowNode for f() | +| classes.py:70:1:70:1 | GSSA Variable c | classes.py:76:6:76:24 | ControlFlowNode for Attribute() | +| classes.py:70:1:70:1 | GSSA Variable c | classes.py:76:6:76:24 | GSSA Variable c | +| classes.py:70:5:70:7 | ControlFlowNode for C() | classes.py:70:1:70:1 | GSSA Variable c | +| classes.py:76:6:76:24 | GSSA Variable SOURCE | classes.py:77:6:77:27 | ControlFlowNode for Attribute() | +| classes.py:76:6:76:24 | GSSA Variable SOURCE | classes.py:77:18:77:23 | ControlFlowNode for SOURCE | +| classes.py:76:6:76:24 | GSSA Variable SOURCE | classes.py:78:6:78:27 | ControlFlowNode for func_obj() | +| classes.py:76:6:76:24 | GSSA Variable SOURCE | classes.py:85:6:85:26 | ControlFlowNode for Attribute() | +| classes.py:76:6:76:24 | GSSA Variable SOURCE | classes.py:85:6:85:26 | GSSA Variable SOURCE | +| classes.py:76:6:76:24 | GSSA Variable SOURCE | classes.py:85:20:85:25 | ControlFlowNode for SOURCE | +| classes.py:76:6:76:24 | GSSA Variable c | classes.py:77:6:77:27 | ControlFlowNode for Attribute() | +| classes.py:76:6:76:24 | GSSA Variable c | classes.py:77:6:77:27 | GSSA Variable c | +| classes.py:76:15:76:20 | ControlFlowNode for SOURCE | classes.py:76:6:76:24 | ControlFlowNode for Attribute() | +| classes.py:77:6:77:27 | GSSA Variable c | classes.py:78:6:78:27 | ControlFlowNode for func_obj() | +| classes.py:77:6:77:27 | GSSA Variable c | classes.py:78:6:78:27 | GSSA Variable c | +| classes.py:77:18:77:23 | ControlFlowNode for SOURCE | classes.py:77:6:77:27 | ControlFlowNode for Attribute() | +| classes.py:78:6:78:27 | GSSA Variable c | classes.py:85:6:85:26 | ControlFlowNode for Attribute() | +| classes.py:78:6:78:27 | GSSA Variable c | classes.py:85:6:85:26 | GSSA Variable c | +| classes.py:85:6:85:26 | GSSA Variable SOURCE | classes.py:86:6:86:26 | ControlFlowNode for Attribute() | +| classes.py:85:6:85:26 | GSSA Variable SOURCE | classes.py:86:6:86:26 | GSSA Variable SOURCE | +| classes.py:85:6:85:26 | GSSA Variable SOURCE | classes.py:86:20:86:25 | ControlFlowNode for SOURCE | +| classes.py:85:6:85:26 | GSSA Variable c | classes.py:86:6:86:26 | ControlFlowNode for Attribute() | +| classes.py:85:6:85:26 | GSSA Variable c | classes.py:87:6:87:26 | ControlFlowNode for c_func_obj() | +| classes.py:85:6:85:26 | GSSA Variable c | classes.py:97:8:97:21 | ControlFlowNode for gen() | +| classes.py:85:6:85:26 | GSSA Variable c | classes.py:98:6:98:20 | ControlFlowNode for Attribute() | +| classes.py:85:6:85:26 | GSSA Variable c | classes.py:101:9:101:24 | ControlFlowNode for Attribute() | +| classes.py:85:6:85:26 | GSSA Variable c | classes.py:101:9:101:24 | GSSA Variable c | +| classes.py:85:20:85:25 | ControlFlowNode for SOURCE | classes.py:85:6:85:26 | ControlFlowNode for Attribute() | +| classes.py:86:6:86:26 | GSSA Variable SOURCE | classes.py:87:6:87:26 | ControlFlowNode for c_func_obj() | +| classes.py:86:6:86:26 | GSSA Variable SOURCE | classes.py:97:8:97:21 | ControlFlowNode for gen() | +| classes.py:86:6:86:26 | GSSA Variable SOURCE | classes.py:97:8:97:21 | GSSA Variable SOURCE | +| classes.py:86:20:86:25 | ControlFlowNode for SOURCE | classes.py:86:6:86:26 | ControlFlowNode for Attribute() | +| classes.py:97:1:97:4 | GSSA Variable iter | classes.py:98:6:98:20 | ControlFlowNode for Attribute() | +| classes.py:97:1:97:4 | GSSA Variable iter | classes.py:98:6:98:20 | GSSA Variable iter | +| classes.py:97:8:97:21 | ControlFlowNode for gen() | classes.py:97:1:97:4 | GSSA Variable iter | +| classes.py:97:8:97:21 | GSSA Variable SOURCE | classes.py:98:6:98:20 | ControlFlowNode for Attribute() | +| classes.py:97:8:97:21 | GSSA Variable SOURCE | classes.py:101:9:101:24 | ControlFlowNode for Attribute() | +| classes.py:97:8:97:21 | GSSA Variable SOURCE | classes.py:101:9:101:24 | GSSA Variable SOURCE | +| classes.py:98:6:98:20 | GSSA Variable iter | classes.py:101:9:101:24 | ControlFlowNode for Attribute() | +| classes.py:98:6:98:20 | GSSA Variable iter | classes.py:102:6:102:21 | ControlFlowNode for Attribute() | +| classes.py:98:6:98:20 | GSSA Variable iter | classes.py:111:6:111:30 | ControlFlowNode for Attribute() | +| classes.py:98:6:98:20 | GSSA Variable iter | classes.py:112:6:112:32 | ControlFlowNode for Attribute() | +| classes.py:98:6:98:20 | GSSA Variable iter | classes.py:124:6:124:30 | ControlFlowNode for Attribute() | +| classes.py:101:1:101:5 | GSSA Variable oiter | classes.py:102:6:102:21 | ControlFlowNode for Attribute() | +| classes.py:101:1:101:5 | GSSA Variable oiter | classes.py:102:6:102:21 | GSSA Variable oiter | +| classes.py:101:9:101:24 | ControlFlowNode for Attribute() | classes.py:101:1:101:5 | GSSA Variable oiter | +| classes.py:101:9:101:24 | GSSA Variable SOURCE | classes.py:102:6:102:21 | ControlFlowNode for Attribute() | +| classes.py:101:9:101:24 | GSSA Variable SOURCE | classes.py:111:18:111:29 | GSSA Variable SOURCE | +| classes.py:101:9:101:24 | GSSA Variable c | classes.py:102:6:102:21 | ControlFlowNode for Attribute() | +| classes.py:101:9:101:24 | GSSA Variable c | classes.py:111:6:111:30 | ControlFlowNode for Attribute() | +| classes.py:101:9:101:24 | GSSA Variable c | classes.py:112:18:112:31 | GSSA Variable c | +| classes.py:102:6:102:21 | GSSA Variable oiter | classes.py:111:6:111:30 | ControlFlowNode for Attribute() | +| classes.py:102:6:102:21 | GSSA Variable oiter | classes.py:112:6:112:32 | ControlFlowNode for Attribute() | +| classes.py:102:6:102:21 | GSSA Variable oiter | classes.py:124:6:124:30 | ControlFlowNode for Attribute() | +| classes.py:111:18:111:29 | GSSA Variable SOURCE | classes.py:111:6:111:30 | ControlFlowNode for Attribute() | +| classes.py:111:18:111:29 | GSSA Variable SOURCE | classes.py:112:18:112:31 | GSSA Variable SOURCE | +| classes.py:112:18:112:31 | GSSA Variable SOURCE | classes.py:112:6:112:32 | ControlFlowNode for Attribute() | +| classes.py:112:18:112:31 | GSSA Variable SOURCE | classes.py:124:18:124:29 | GSSA Variable SOURCE | +| classes.py:112:18:112:31 | GSSA Variable c | classes.py:112:6:112:32 | ControlFlowNode for Attribute() | +| classes.py:112:18:112:31 | GSSA Variable c | classes.py:124:6:124:30 | ControlFlowNode for Attribute() | +| classes.py:124:18:124:29 | GSSA Variable SOURCE | classes.py:124:6:124:30 | ControlFlowNode for Attribute() | +| test.py:43:9:43:14 | ControlFlowNode for SOURCE | test.py:44:10:44:10 | ControlFlowNode for x | +| test.py:48:9:48:16 | ControlFlowNode for Str | test.py:49:10:49:10 | ControlFlowNode for x | +| test.py:52:9:52:17 | ControlFlowNode for Str | test.py:53:10:53:10 | ControlFlowNode for x | +| test.py:56:9:56:10 | ControlFlowNode for IntegerLiteral | test.py:57:10:57:10 | ControlFlowNode for x | +| test.py:60:9:60:12 | ControlFlowNode for FloatLiteral | test.py:61:10:61:10 | ControlFlowNode for x | +| test.py:69:10:69:15 | ControlFlowNode for SOURCE | test.py:70:10:70:10 | ControlFlowNode for x | +| test.py:246:28:246:33 | ControlFlowNode for SOURCE | test.py:246:10:246:34 | ControlFlowNode for second() | +| test.py:305:12:305:17 | ControlFlowNode for SOURCE | test.py:305:10:305:18 | ControlFlowNode for f() | +| test.py:309:28:309:33 | ControlFlowNode for SOURCE | test.py:309:10:309:34 | ControlFlowNode for second() | nodes -| classes.py:16:1:16:6 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | -| classes.py:16:10:16:17 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str | -| classes.py:31:6:31:17 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() | -| classes.py:31:6:31:17 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | -| classes.py:31:8:31:13 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| classes.py:58:1:58:1 | GSSA Variable c | semmle.label | GSSA Variable c | -| classes.py:58:5:58:7 | ControlFlowNode for C() | semmle.label | ControlFlowNode for C() | -| classes.py:64:6:64:24 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| classes.py:64:6:64:24 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | -| classes.py:64:6:64:24 | GSSA Variable c | semmle.label | GSSA Variable c | -| classes.py:64:15:64:20 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| classes.py:65:6:65:27 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| classes.py:65:6:65:27 | GSSA Variable c | semmle.label | GSSA Variable c | -| classes.py:65:18:65:23 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| classes.py:66:6:66:27 | ControlFlowNode for func_obj() | semmle.label | ControlFlowNode for func_obj() | -| classes.py:66:6:66:27 | GSSA Variable c | semmle.label | GSSA Variable c | -| classes.py:73:6:73:26 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| classes.py:73:6:73:26 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | -| classes.py:73:6:73:26 | GSSA Variable c | semmle.label | GSSA Variable c | -| classes.py:73:20:73:25 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| classes.py:74:6:74:26 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| classes.py:74:6:74:26 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | -| classes.py:74:20:74:25 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| classes.py:75:6:75:26 | ControlFlowNode for c_func_obj() | semmle.label | ControlFlowNode for c_func_obj() | -| classes.py:85:1:85:4 | GSSA Variable iter | semmle.label | GSSA Variable iter | -| classes.py:85:8:85:21 | ControlFlowNode for gen() | semmle.label | ControlFlowNode for gen() | -| classes.py:85:8:85:21 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | -| classes.py:86:6:86:20 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| classes.py:86:6:86:20 | GSSA Variable iter | semmle.label | GSSA Variable iter | -| classes.py:87:8:87:22 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| classes.py:87:8:87:22 | GSSA Variable iter | semmle.label | GSSA Variable iter | -| classes.py:89:1:89:5 | GSSA Variable oiter | semmle.label | GSSA Variable oiter | -| classes.py:89:9:89:24 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| classes.py:89:9:89:24 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | -| classes.py:89:9:89:24 | GSSA Variable c | semmle.label | GSSA Variable c | -| classes.py:90:6:90:21 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| classes.py:90:6:90:21 | GSSA Variable oiter | semmle.label | GSSA Variable oiter | -| classes.py:91:8:91:23 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| classes.py:91:8:91:23 | GSSA Variable oiter | semmle.label | GSSA Variable oiter | -| classes.py:99:6:99:30 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| classes.py:99:18:99:29 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | -| classes.py:100:6:100:32 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| classes.py:100:18:100:31 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | -| classes.py:100:18:100:31 | GSSA Variable c | semmle.label | GSSA Variable c | -| classes.py:112:6:112:30 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| classes.py:112:18:112:29 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | -| test.py:35:9:35:14 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:36:10:36:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | -| test.py:40:9:40:16 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str | -| test.py:41:10:41:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | -| test.py:44:9:44:17 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str | -| test.py:45:10:45:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | -| test.py:48:9:48:10 | ControlFlowNode for IntegerLiteral | semmle.label | ControlFlowNode for IntegerLiteral | +| classes.py:18:1:18:6 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| classes.py:18:10:18:17 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str | +| classes.py:43:6:43:17 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() | +| classes.py:43:6:43:17 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| classes.py:43:8:43:13 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| classes.py:70:1:70:1 | GSSA Variable c | semmle.label | GSSA Variable c | +| classes.py:70:5:70:7 | ControlFlowNode for C() | semmle.label | ControlFlowNode for C() | +| classes.py:76:6:76:24 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| classes.py:76:6:76:24 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| classes.py:76:6:76:24 | GSSA Variable c | semmle.label | GSSA Variable c | +| classes.py:76:15:76:20 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| classes.py:77:6:77:27 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| classes.py:77:6:77:27 | GSSA Variable c | semmle.label | GSSA Variable c | +| classes.py:77:18:77:23 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| classes.py:78:6:78:27 | ControlFlowNode for func_obj() | semmle.label | ControlFlowNode for func_obj() | +| classes.py:78:6:78:27 | GSSA Variable c | semmle.label | GSSA Variable c | +| classes.py:85:6:85:26 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| classes.py:85:6:85:26 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| classes.py:85:6:85:26 | GSSA Variable c | semmle.label | GSSA Variable c | +| classes.py:85:20:85:25 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| classes.py:86:6:86:26 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| classes.py:86:6:86:26 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| classes.py:86:20:86:25 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| classes.py:87:6:87:26 | ControlFlowNode for c_func_obj() | semmle.label | ControlFlowNode for c_func_obj() | +| classes.py:97:1:97:4 | GSSA Variable iter | semmle.label | GSSA Variable iter | +| classes.py:97:8:97:21 | ControlFlowNode for gen() | semmle.label | ControlFlowNode for gen() | +| classes.py:97:8:97:21 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| classes.py:98:6:98:20 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| classes.py:98:6:98:20 | GSSA Variable iter | semmle.label | GSSA Variable iter | +| classes.py:101:1:101:5 | GSSA Variable oiter | semmle.label | GSSA Variable oiter | +| classes.py:101:9:101:24 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| classes.py:101:9:101:24 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| classes.py:101:9:101:24 | GSSA Variable c | semmle.label | GSSA Variable c | +| classes.py:102:6:102:21 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| classes.py:102:6:102:21 | GSSA Variable oiter | semmle.label | GSSA Variable oiter | +| classes.py:111:6:111:30 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| classes.py:111:18:111:29 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| classes.py:112:6:112:32 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| classes.py:112:18:112:31 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| classes.py:112:18:112:31 | GSSA Variable c | semmle.label | GSSA Variable c | +| classes.py:124:6:124:30 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| classes.py:124:18:124:29 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| test.py:43:9:43:14 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:44:10:44:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | +| test.py:48:9:48:16 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str | | test.py:49:10:49:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | -| test.py:52:9:52:12 | ControlFlowNode for FloatLiteral | semmle.label | ControlFlowNode for FloatLiteral | +| test.py:52:9:52:17 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str | | test.py:53:10:53:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | -| test.py:61:10:61:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:62:10:62:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | -| test.py:238:10:238:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | -| test.py:238:28:238:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:297:10:297:18 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() | -| test.py:297:12:297:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:301:10:301:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | -| test.py:301:28:301:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:56:9:56:10 | ControlFlowNode for IntegerLiteral | semmle.label | ControlFlowNode for IntegerLiteral | +| test.py:57:10:57:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | +| test.py:60:9:60:12 | ControlFlowNode for FloatLiteral | semmle.label | ControlFlowNode for FloatLiteral | +| test.py:61:10:61:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | +| test.py:69:10:69:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:70:10:70:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | +| test.py:246:10:246:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | +| test.py:246:28:246:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:305:10:305:18 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() | +| test.py:305:12:305:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:309:10:309:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | +| test.py:309:28:309:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | #select -| classes.py:31:6:31:17 | ControlFlowNode for f() | classes.py:16:10:16:17 | ControlFlowNode for Str | classes.py:31:6:31:17 | ControlFlowNode for f() | | -| classes.py:31:6:31:17 | ControlFlowNode for f() | classes.py:31:8:31:13 | ControlFlowNode for SOURCE | classes.py:31:6:31:17 | ControlFlowNode for f() | | -| classes.py:64:6:64:24 | ControlFlowNode for Attribute() | classes.py:16:10:16:17 | ControlFlowNode for Str | classes.py:64:6:64:24 | ControlFlowNode for Attribute() | | -| classes.py:64:6:64:24 | ControlFlowNode for Attribute() | classes.py:64:15:64:20 | ControlFlowNode for SOURCE | classes.py:64:6:64:24 | ControlFlowNode for Attribute() | | -| classes.py:65:6:65:27 | ControlFlowNode for Attribute() | classes.py:16:10:16:17 | ControlFlowNode for Str | classes.py:65:6:65:27 | ControlFlowNode for Attribute() | | -| classes.py:65:6:65:27 | ControlFlowNode for Attribute() | classes.py:65:18:65:23 | ControlFlowNode for SOURCE | classes.py:65:6:65:27 | ControlFlowNode for Attribute() | | -| classes.py:66:6:66:27 | ControlFlowNode for func_obj() | classes.py:16:10:16:17 | ControlFlowNode for Str | classes.py:66:6:66:27 | ControlFlowNode for func_obj() | | -| classes.py:73:6:73:26 | ControlFlowNode for Attribute() | classes.py:16:10:16:17 | ControlFlowNode for Str | classes.py:73:6:73:26 | ControlFlowNode for Attribute() | | -| classes.py:73:6:73:26 | ControlFlowNode for Attribute() | classes.py:73:20:73:25 | ControlFlowNode for SOURCE | classes.py:73:6:73:26 | ControlFlowNode for Attribute() | | -| classes.py:74:6:74:26 | ControlFlowNode for Attribute() | classes.py:16:10:16:17 | ControlFlowNode for Str | classes.py:74:6:74:26 | ControlFlowNode for Attribute() | | -| classes.py:74:6:74:26 | ControlFlowNode for Attribute() | classes.py:74:20:74:25 | ControlFlowNode for SOURCE | classes.py:74:6:74:26 | ControlFlowNode for Attribute() | | -| classes.py:75:6:75:26 | ControlFlowNode for c_func_obj() | classes.py:16:10:16:17 | ControlFlowNode for Str | classes.py:75:6:75:26 | ControlFlowNode for c_func_obj() | | -| classes.py:86:6:86:20 | ControlFlowNode for Attribute() | classes.py:16:10:16:17 | ControlFlowNode for Str | classes.py:86:6:86:20 | ControlFlowNode for Attribute() | | -| classes.py:87:8:87:22 | ControlFlowNode for Attribute() | classes.py:16:10:16:17 | ControlFlowNode for Str | classes.py:87:8:87:22 | ControlFlowNode for Attribute() | | -| classes.py:90:6:90:21 | ControlFlowNode for Attribute() | classes.py:16:10:16:17 | ControlFlowNode for Str | classes.py:90:6:90:21 | ControlFlowNode for Attribute() | | -| classes.py:91:8:91:23 | ControlFlowNode for Attribute() | classes.py:16:10:16:17 | ControlFlowNode for Str | classes.py:91:8:91:23 | ControlFlowNode for Attribute() | | -| classes.py:99:6:99:30 | ControlFlowNode for Attribute() | classes.py:16:10:16:17 | ControlFlowNode for Str | classes.py:99:6:99:30 | ControlFlowNode for Attribute() | | -| classes.py:100:6:100:32 | ControlFlowNode for Attribute() | classes.py:16:10:16:17 | ControlFlowNode for Str | classes.py:100:6:100:32 | ControlFlowNode for Attribute() | | -| classes.py:112:6:112:30 | ControlFlowNode for Attribute() | classes.py:16:10:16:17 | ControlFlowNode for Str | classes.py:112:6:112:30 | ControlFlowNode for Attribute() | | -| test.py:36:10:36:10 | ControlFlowNode for x | test.py:35:9:35:14 | ControlFlowNode for SOURCE | test.py:36:10:36:10 | ControlFlowNode for x | | -| test.py:41:10:41:10 | ControlFlowNode for x | test.py:40:9:40:16 | ControlFlowNode for Str | test.py:41:10:41:10 | ControlFlowNode for x | | -| test.py:45:10:45:10 | ControlFlowNode for x | test.py:44:9:44:17 | ControlFlowNode for Str | test.py:45:10:45:10 | ControlFlowNode for x | | -| test.py:49:10:49:10 | ControlFlowNode for x | test.py:48:9:48:10 | ControlFlowNode for IntegerLiteral | test.py:49:10:49:10 | ControlFlowNode for x | | -| test.py:53:10:53:10 | ControlFlowNode for x | test.py:52:9:52:12 | ControlFlowNode for FloatLiteral | test.py:53:10:53:10 | ControlFlowNode for x | | -| test.py:62:10:62:10 | ControlFlowNode for x | test.py:61:10:61:15 | ControlFlowNode for SOURCE | test.py:62:10:62:10 | ControlFlowNode for x | | -| test.py:238:10:238:34 | ControlFlowNode for second() | test.py:238:28:238:33 | ControlFlowNode for SOURCE | test.py:238:10:238:34 | ControlFlowNode for second() | | -| test.py:297:10:297:18 | ControlFlowNode for f() | test.py:297:12:297:17 | ControlFlowNode for SOURCE | test.py:297:10:297:18 | ControlFlowNode for f() | | -| test.py:301:10:301:34 | ControlFlowNode for second() | test.py:301:28:301:33 | ControlFlowNode for SOURCE | test.py:301:10:301:34 | ControlFlowNode for second() | | +| classes.py:43:6:43:17 | ControlFlowNode for f() | classes.py:18:10:18:17 | ControlFlowNode for Str | classes.py:43:6:43:17 | ControlFlowNode for f() | | +| classes.py:43:6:43:17 | ControlFlowNode for f() | classes.py:43:8:43:13 | ControlFlowNode for SOURCE | classes.py:43:6:43:17 | ControlFlowNode for f() | | +| classes.py:76:6:76:24 | ControlFlowNode for Attribute() | classes.py:18:10:18:17 | ControlFlowNode for Str | classes.py:76:6:76:24 | ControlFlowNode for Attribute() | | +| classes.py:76:6:76:24 | ControlFlowNode for Attribute() | classes.py:76:15:76:20 | ControlFlowNode for SOURCE | classes.py:76:6:76:24 | ControlFlowNode for Attribute() | | +| classes.py:77:6:77:27 | ControlFlowNode for Attribute() | classes.py:18:10:18:17 | ControlFlowNode for Str | classes.py:77:6:77:27 | ControlFlowNode for Attribute() | | +| classes.py:77:6:77:27 | ControlFlowNode for Attribute() | classes.py:77:18:77:23 | ControlFlowNode for SOURCE | classes.py:77:6:77:27 | ControlFlowNode for Attribute() | | +| classes.py:78:6:78:27 | ControlFlowNode for func_obj() | classes.py:18:10:18:17 | ControlFlowNode for Str | classes.py:78:6:78:27 | ControlFlowNode for func_obj() | | +| classes.py:85:6:85:26 | ControlFlowNode for Attribute() | classes.py:18:10:18:17 | ControlFlowNode for Str | classes.py:85:6:85:26 | ControlFlowNode for Attribute() | | +| classes.py:85:6:85:26 | ControlFlowNode for Attribute() | classes.py:85:20:85:25 | ControlFlowNode for SOURCE | classes.py:85:6:85:26 | ControlFlowNode for Attribute() | | +| classes.py:86:6:86:26 | ControlFlowNode for Attribute() | classes.py:18:10:18:17 | ControlFlowNode for Str | classes.py:86:6:86:26 | ControlFlowNode for Attribute() | | +| classes.py:86:6:86:26 | ControlFlowNode for Attribute() | classes.py:86:20:86:25 | ControlFlowNode for SOURCE | classes.py:86:6:86:26 | ControlFlowNode for Attribute() | | +| classes.py:87:6:87:26 | ControlFlowNode for c_func_obj() | classes.py:18:10:18:17 | ControlFlowNode for Str | classes.py:87:6:87:26 | ControlFlowNode for c_func_obj() | | +| classes.py:98:6:98:20 | ControlFlowNode for Attribute() | classes.py:18:10:18:17 | ControlFlowNode for Str | classes.py:98:6:98:20 | ControlFlowNode for Attribute() | | +| classes.py:102:6:102:21 | ControlFlowNode for Attribute() | classes.py:18:10:18:17 | ControlFlowNode for Str | classes.py:102:6:102:21 | ControlFlowNode for Attribute() | | +| classes.py:111:6:111:30 | ControlFlowNode for Attribute() | classes.py:18:10:18:17 | ControlFlowNode for Str | classes.py:111:6:111:30 | ControlFlowNode for Attribute() | | +| classes.py:112:6:112:32 | ControlFlowNode for Attribute() | classes.py:18:10:18:17 | ControlFlowNode for Str | classes.py:112:6:112:32 | ControlFlowNode for Attribute() | | +| classes.py:124:6:124:30 | ControlFlowNode for Attribute() | classes.py:18:10:18:17 | ControlFlowNode for Str | classes.py:124:6:124:30 | ControlFlowNode for Attribute() | | +| test.py:44:10:44:10 | ControlFlowNode for x | test.py:43:9:43:14 | ControlFlowNode for SOURCE | test.py:44:10:44:10 | ControlFlowNode for x | | +| test.py:49:10:49:10 | ControlFlowNode for x | test.py:48:9:48:16 | ControlFlowNode for Str | test.py:49:10:49:10 | ControlFlowNode for x | | +| test.py:53:10:53:10 | ControlFlowNode for x | test.py:52:9:52:17 | ControlFlowNode for Str | test.py:53:10:53:10 | ControlFlowNode for x | | +| test.py:57:10:57:10 | ControlFlowNode for x | test.py:56:9:56:10 | ControlFlowNode for IntegerLiteral | test.py:57:10:57:10 | ControlFlowNode for x | | +| test.py:61:10:61:10 | ControlFlowNode for x | test.py:60:9:60:12 | ControlFlowNode for FloatLiteral | test.py:61:10:61:10 | ControlFlowNode for x | | +| test.py:70:10:70:10 | ControlFlowNode for x | test.py:69:10:69:15 | ControlFlowNode for SOURCE | test.py:70:10:70:10 | ControlFlowNode for x | | +| test.py:246:10:246:34 | ControlFlowNode for second() | test.py:246:28:246:33 | ControlFlowNode for SOURCE | test.py:246:10:246:34 | ControlFlowNode for second() | | +| test.py:305:10:305:18 | ControlFlowNode for f() | test.py:305:12:305:17 | ControlFlowNode for SOURCE | test.py:305:10:305:18 | ControlFlowNode for f() | | +| test.py:309:10:309:34 | ControlFlowNode for second() | test.py:309:28:309:33 | ControlFlowNode for SOURCE | test.py:309:10:309:34 | ControlFlowNode for second() | | From 3929e013505a0a58f3469cfe625990e3a68d1617 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Tue, 11 Aug 2020 08:10:46 +0200 Subject: [PATCH 023/133] Python: tests for async iterators/context managers --- .../experimental/dataflow/coverage/classes.py | 82 +++++++++++-------- 1 file changed, 48 insertions(+), 34 deletions(-) diff --git a/python/ql/test/experimental/dataflow/coverage/classes.py b/python/ql/test/experimental/dataflow/coverage/classes.py index 3f47b69c943..96c04c09072 100644 --- a/python/ql/test/experimental/dataflow/coverage/classes.py +++ b/python/ql/test/experimental/dataflow/coverage/classes.py @@ -1271,49 +1271,63 @@ async def atest_await(): # # coroutine.throw(type[, value[, traceback]]) # # coroutine.close() -# # 3.4.3. Asynchronous Iterators -# # object.__aiter__(self) -# class With_aiter: +# 3.4.3. Asynchronous Iterators +# object.__aiter__(self) +class With_aiter: -# def __aiter__(self): -# OK() -# return "" # edit to match type + def __aiter__(self): + OK() + return self -# def test_aiter(): -# with_aiter = With_aiter() -# aiter(with_aiter) # edit to effect call + async def __anext__(self): + raise StopAsyncIteration -# # object.__anext__(self) -# class With_anext: +async def atest_aiter(): + with_aiter = With_aiter() + async for x in with_aiter: + pass -# def __anext__(self): -# OK() -# return "" # edit to match type +# object.__anext__(self) +class With_anext: -# def test_anext(): -# with_anext = With_anext() -# anext(with_anext) # edit to effect call + def __aiter__(self): + return self + + async def __anext__(self): + OK() + raise StopAsyncIteration + +async def atest_anext(): + with_anext = With_anext() + async for x in with_anext: + pass -# # 3.4.4. Asynchronous Context Managers -# # object.__aenter__(self) -# class With_aenter: +# 3.4.4. Asynchronous Context Managers +# object.__aenter__(self) +class With_aenter: -# def __aenter__(self): -# OK() -# return "" # edit to match type + async def __aenter__(self): + OK() -# def test_aenter(): -# with_aenter = With_aenter() -# aenter(with_aenter) # edit to effect call + async def __aexit__(self, exc_type, exc_value, traceback): + pass -# # object.__aexit__(self, exc_type, exc_value, traceback) -# class With_aexit: +async def atest_aenter(): + with_aenter = With_aenter() + async with with_aenter: + pass -# def __aexit__(self, exc_type, exc_value, traceback): -# OK() -# return "" # edit to match type +# object.__aexit__(self, exc_type, exc_value, traceback) +class With_aexit: -# def test_aexit(): -# with_aexit = With_aexit() -# aexit(with_aexit) # edit to effect call + async def __aenter__(self): + pass + + async def __aexit__(self, exc_type, exc_value, traceback): + OK() + +async def atest_aexit(): + with_aexit = With_aexit() + async with with_aexit: + pass From 12dfc4afd9673e619a7acc44205c5209f1c452bb Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Tue, 11 Aug 2020 08:16:49 +0200 Subject: [PATCH 024/133] Python: clean up validity check code --- .../ql/test/experimental/dataflow/coverage/validTest.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/python/ql/test/experimental/dataflow/coverage/validTest.py b/python/ql/test/experimental/dataflow/coverage/validTest.py index dbede541e82..cec82c47723 100644 --- a/python/ql/test/experimental/dataflow/coverage/validTest.py +++ b/python/ql/test/experimental/dataflow/coverage/validTest.py @@ -27,9 +27,7 @@ def check_async_test_function(f): sys.stdout = old_stdout check_output(capturer.getvalue(), f) -def check_classes_valid(testFile): - # import python.ql.test.experimental.dataflow.coverage.classes as tests - # import classes as tests +def check_tests_valid(testFile): import importlib tests = importlib.import_module(testFile) for i in dir(tests): @@ -47,5 +45,5 @@ def check_classes_valid(testFile): check_async_test_function(item) if __name__ == '__main__': - check_classes_valid("classes") - check_classes_valid("test") + check_tests_valid("classes") + check_tests_valid("test") From 2c5de7f50e3f5ee91d06945ffbfad74859e0e31a Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Tue, 11 Aug 2020 10:48:23 +0200 Subject: [PATCH 025/133] Python: fix r/l confusion --- python/ql/test/experimental/dataflow/coverage/classes.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/python/ql/test/experimental/dataflow/coverage/classes.py b/python/ql/test/experimental/dataflow/coverage/classes.py index 96c04c09072..d86e442bd92 100644 --- a/python/ql/test/experimental/dataflow/coverage/classes.py +++ b/python/ql/test/experimental/dataflow/coverage/classes.py @@ -870,9 +870,9 @@ class With_rlshift: OK() return self -def ftest_rlshift(): # TypeError: unsupported operand type(s) for >>: 'str' and 'With_rlshift' +def test_rlshift(): with_rlshift = With_rlshift() - "" >> with_rlshift + "" << with_rlshift # object.__rrshift__(self, other) class With_rrshift: @@ -881,9 +881,9 @@ class With_rrshift: OK() return self -def ftest_rrshift(): # TypeError: unsupported operand type(s) for <<: 'str' and 'With_rrshift' +def test_rrshift(): with_rrshift = With_rrshift() - "" << with_rrshift + "" >> with_rrshift # object.__rand__(self, other) class With_rand: From f834d71bab3c93d7a6f0cdb929fbffdb468e34a2 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Tue, 11 Aug 2020 11:22:11 +0200 Subject: [PATCH 026/133] Python: split out data model tests --- .../experimental/dataflow/coverage/classes.py | 157 +---------------- .../dataflow/coverage/datamodel.py | 159 ++++++++++++++++++ 2 files changed, 161 insertions(+), 155 deletions(-) create mode 100644 python/ql/test/experimental/dataflow/coverage/datamodel.py diff --git a/python/ql/test/experimental/dataflow/coverage/classes.py b/python/ql/test/experimental/dataflow/coverage/classes.py index d86e442bd92..63147cfd6ae 100644 --- a/python/ql/test/experimental/dataflow/coverage/classes.py +++ b/python/ql/test/experimental/dataflow/coverage/classes.py @@ -5,164 +5,9 @@ # These tests should cover all the class calls that we hope to support. # It is based on https://docs.python.org/3/reference/datamodel.html, and headings refer there. # -# Intended sources should be the variable `SOURCE` and intended sinks should be -# arguments to the function `SINK` (see python/ql/test/experimental/dataflow/testConfig.qll). -# -# Functions whose name ends with "_with_local_flow" will also be tested for local flow. -# # All functions starting with "test_" should run and print `"OK"`. # This can be checked by running validTest.py. -# These are defined so that we can evaluate the test code. -NONSOURCE = "not a source" -SOURCE = "source" - -def is_source(x): - return x == "source" or x == b"source" or x == 42 or x == 42.0 or x == 42j - -def SINK(x): - if is_source(x): - print("OK") - else: - print("Unexpected flow", x) - -def SINK_F(x): - if is_source(x): - print("Unexpected flow", x) - else: - print("OK") - -# Callable types -# These are the types to which the function call operation (see section Calls) can be applied: - -# User-defined functions -# A user-defined function object is created by a function definition (see section Function definitions). It should be called with an argument list containing the same number of items as the function's formal parameter list. -def f(a, b): - return a - -SINK(f(SOURCE, 3)) - -# Instance methods -# An instance method object combines a class, a class instance and any callable object (normally a user-defined function). -class C(object): - - def method(self, x, cls): - assert cls is self.__class__ - return x - - @classmethod - def classmethod(cls, x): - return x - - @staticmethod - def staticmethod(x): - return x - - def gen(self, x, count): - n = count - while n > 0: - yield x - n -= 1 - - async def coro(self, x): - return x - -c = C() - -# When an instance method object is created by retrieving a user-defined function object from a class via one of its instances, its __self__ attribute is the instance, and the method object is said to be bound. The new method’s __func__ attribute is the original function object. -func_obj = c.method.__func__ - -# When an instance method object is called, the underlying function (__func__) is called, inserting the class instance (__self__) in front of the argument list. For instance, when C is a class which contains a definition for a function f(), and x is an instance of C, calling x.f(1) is equivalent to calling C.f(x, 1). -SINK(c.method(SOURCE, C)) -SINK(C.method(c, SOURCE, C)) -SINK(func_obj(c, SOURCE, C)) - - -# When an instance method object is created by retrieving a class method object from a class or instance, its __self__ attribute is the class itself, and its __func__ attribute is the function object underlying the class method. -c_func_obj = C.classmethod.__func__ - -# When an instance method object is derived from a class method object, the “class instance” stored in __self__ will actually be the class itself, so that calling either x.f(1) or C.f(1) is equivalent to calling f(C,1) where f is the underlying function. -SINK(c.classmethod(SOURCE)) -SINK(C.classmethod(SOURCE)) -SINK(c_func_obj(C, SOURCE)) - -# Generator functions -# A function or method which uses the yield statement (see section The yield statement) is called a generator function. Such a function, when called, always returns an iterator object which can be used to execute the body of the function: calling the iterator’s iterator.__next__() method will cause the function to execute until it provides a value using the yield statement. When the function executes a return statement or falls off the end, a StopIteration exception is raised and the iterator will have reached the end of the set of values to be returned. -def gen(x, count): - n = count - while n > 0: - yield x - n -= 1 - -iter = gen(SOURCE, 1) -SINK(iter.__next__()) -# SINK_F(iter.__next__()) # throws StopIteration, FP - -oiter = c.gen(SOURCE, 1) -SINK(oiter.__next__()) -# SINK_F(oiter.__next__()) # throws StopIteration, FP - -# Coroutine functions -# A function or method which is defined using async def is called a coroutine function. Such a function, when called, returns a coroutine object. It may contain await expressions, as well as async with and async for statements. See also the Coroutine Objects section. -async def coro(x): - return x - -import asyncio -SINK(asyncio.run(coro(SOURCE))) -SINK(asyncio.run(c.coro(SOURCE))) - -class A: - - def __await__(self): - # yield SOURCE -- see https://groups.google.com/g/dev-python/c/_lrrc-vp9TI?pli=1 - return (yield from asyncio.coroutine(lambda: SOURCE)()) - -async def agen(x): - a = A() - return await a - -SINK(asyncio.run(agen(SOURCE))) - -# Asynchronous generator functions -# A function or method which is defined using async def and which uses the yield statement is called a asynchronous generator function. Such a function, when called, returns an asynchronous iterator object which can be used in an async for statement to execute the body of the function. - -# Calling the asynchronous iterator’s aiterator.__anext__() method will return an awaitable which when awaited will execute until it provides a value using the yield expression. When the function executes an empty return statement or falls off the end, a StopAsyncIteration exception is raised and the asynchronous iterator will have reached the end of the set of values to be yielded. - -# Built-in functions -# A built-in function object is a wrapper around a C function. Examples of built-in functions are len() and math.sin() (math is a standard built-in module). The number and type of the arguments are determined by the C function. Special read-only attributes: __doc__ is the function’s documentation string, or None if unavailable; __name__ is the function’s name; __self__ is set to None (but see the next item); __module__ is the name of the module the function was defined in or None if unavailable. - -# Built-in methods -# This is really a different disguise of a built-in function, this time containing an object passed to the C function as an implicit extra argument. An example of a built-in method is alist.append(), assuming alist is a list object. In this case, the special read-only attribute __self__ is set to the object denoted by alist. - -# Classes -# Classes are callable. These objects normally act as factories for new instances of themselves, but variations are possible for class types that override __new__(). The arguments of the call are passed to __new__() and, in the typical case, to __init__() to initialize the new instance. - -# Class Instances -# Instances of arbitrary classes can be made callable by defining a __call__() method in their class. - -# If a class sets __iter__() to None, calling iter() on its instances will raise a TypeError (without falling back to __getitem__()). - -# 3.3.1. Basic customization - -class Customized: - - a = NONSOURCE - b = NONSOURCE - - def __new__(cls): - cls.a = SOURCE - return super().__new__(cls) - - def __init__(self): - self.b = SOURCE - -# testing __new__ and __init__ -customized = Customized() -SINK(Customized.a) -SINK_F(Customized.b) -SINK(customized.a) -SINK(customized.b) - def OK(): print("OK") @@ -1254,6 +1099,8 @@ def test_exit(): pass # 3.4.1. Awaitable Objects +import asyncio + # object.__await__(self) class With_await: diff --git a/python/ql/test/experimental/dataflow/coverage/datamodel.py b/python/ql/test/experimental/dataflow/coverage/datamodel.py new file mode 100644 index 00000000000..82f10f4d53f --- /dev/null +++ b/python/ql/test/experimental/dataflow/coverage/datamodel.py @@ -0,0 +1,159 @@ +# User-defined methods, both instance methods and class methods, can be called in many non-standard ways +# i.e. differently from simply `c.f()` or `C.f()`. For example, a user-defined `__await__` function on a +# class `C` will be called by the syntactic construct `await c` when `c` is an instance of `C`. +# +# These tests are based on the first part of https://docs.python.org/3/reference/datamodel.html. +# A thorough covering of methods in that document is found in classes.py. +# +# Intended sources should be the variable `SOURCE` and intended sinks should be +# arguments to the function `SINK` (see python/ql/test/experimental/dataflow/testConfig.qll). + +# These are defined so that we can evaluate the test code. +NONSOURCE = "not a source" +SOURCE = "source" + +def is_source(x): + return x == "source" or x == b"source" or x == 42 or x == 42.0 or x == 42j + +def SINK(x): + if is_source(x): + print("OK") + else: + print("Unexpected flow", x) + +def SINK_F(x): + if is_source(x): + print("Unexpected flow", x) + else: + print("OK") + +# Callable types +# These are the types to which the function call operation (see section Calls) can be applied: + +# User-defined functions +# A user-defined function object is created by a function definition (see section Function definitions). It should be called with an argument list containing the same number of items as the function's formal parameter list. +def f(a, b): + return a + +SINK(f(SOURCE, 3)) + +# Instance methods +# An instance method object combines a class, a class instance and any callable object (normally a user-defined function). +class C(object): + + def method(self, x, cls): + assert cls is self.__class__ + return x + + @classmethod + def classmethod(cls, x): + return x + + @staticmethod + def staticmethod(x): + return x + + def gen(self, x, count): + n = count + while n > 0: + yield x + n -= 1 + + async def coro(self, x): + return x + +c = C() + +# When an instance method object is created by retrieving a user-defined function object from a class via one of its instances, its __self__ attribute is the instance, and the method object is said to be bound. The new method’s __func__ attribute is the original function object. +func_obj = c.method.__func__ + +# When an instance method object is called, the underlying function (__func__) is called, inserting the class instance (__self__) in front of the argument list. For instance, when C is a class which contains a definition for a function f(), and x is an instance of C, calling x.f(1) is equivalent to calling C.f(x, 1). +SINK(c.method(SOURCE, C)) +SINK(C.method(c, SOURCE, C)) +SINK(func_obj(c, SOURCE, C)) + + +# When an instance method object is created by retrieving a class method object from a class or instance, its __self__ attribute is the class itself, and its __func__ attribute is the function object underlying the class method. +c_func_obj = C.classmethod.__func__ + +# When an instance method object is derived from a class method object, the “class instance” stored in __self__ will actually be the class itself, so that calling either x.f(1) or C.f(1) is equivalent to calling f(C,1) where f is the underlying function. +SINK(c.classmethod(SOURCE)) +SINK(C.classmethod(SOURCE)) +SINK(c_func_obj(C, SOURCE)) + +# Generator functions +# A function or method which uses the yield statement (see section The yield statement) is called a generator function. Such a function, when called, always returns an iterator object which can be used to execute the body of the function: calling the iterator’s iterator.__next__() method will cause the function to execute until it provides a value using the yield statement. When the function executes a return statement or falls off the end, a StopIteration exception is raised and the iterator will have reached the end of the set of values to be returned. +def gen(x, count): + n = count + while n > 0: + yield x + n -= 1 + +iter = gen(SOURCE, 1) +SINK(iter.__next__()) +# SINK_F(iter.__next__()) # throws StopIteration, FP + +oiter = c.gen(SOURCE, 1) +SINK(oiter.__next__()) +# SINK_F(oiter.__next__()) # throws StopIteration, FP + +# Coroutine functions +# A function or method which is defined using async def is called a coroutine function. Such a function, when called, returns a coroutine object. It may contain await expressions, as well as async with and async for statements. See also the Coroutine Objects section. +async def coro(x): + return x + +import asyncio +SINK(asyncio.run(coro(SOURCE))) +SINK(asyncio.run(c.coro(SOURCE))) + +class A: + + def __await__(self): + # yield SOURCE -- see https://groups.google.com/g/dev-python/c/_lrrc-vp9TI?pli=1 + return (yield from asyncio.coroutine(lambda: SOURCE)()) + +async def agen(x): + a = A() + return await a + +SINK(asyncio.run(agen(SOURCE))) + +# Asynchronous generator functions +# A function or method which is defined using async def and which uses the yield statement is called a asynchronous generator function. Such a function, when called, returns an asynchronous iterator object which can be used in an async for statement to execute the body of the function. + +# Calling the asynchronous iterator’s aiterator.__anext__() method will return an awaitable which when awaited will execute until it provides a value using the yield expression. When the function executes an empty return statement or falls off the end, a StopAsyncIteration exception is raised and the asynchronous iterator will have reached the end of the set of values to be yielded. + +# Built-in functions +# A built-in function object is a wrapper around a C function. Examples of built-in functions are len() and math.sin() (math is a standard built-in module). The number and type of the arguments are determined by the C function. Special read-only attributes: __doc__ is the function’s documentation string, or None if unavailable; __name__ is the function’s name; __self__ is set to None (but see the next item); __module__ is the name of the module the function was defined in or None if unavailable. + +# Built-in methods +# This is really a different disguise of a built-in function, this time containing an object passed to the C function as an implicit extra argument. An example of a built-in method is alist.append(), assuming alist is a list object. In this case, the special read-only attribute __self__ is set to the object denoted by alist. + +# Classes +# Classes are callable. These objects normally act as factories for new instances of themselves, but variations are possible for class types that override __new__(). The arguments of the call are passed to __new__() and, in the typical case, to __init__() to initialize the new instance. + +# Class Instances +# Instances of arbitrary classes can be made callable by defining a __call__() method in their class. + +# If a class sets __iter__() to None, calling iter() on its instances will raise a TypeError (without falling back to __getitem__()). + +# 3.3.1. Basic customization + +class Customized: + + a = NONSOURCE + b = NONSOURCE + + def __new__(cls): + cls.a = SOURCE + return super().__new__(cls) + + def __init__(self): + self.b = SOURCE + +# testing __new__ and __init__ +customized = Customized() +SINK(Customized.a) +SINK_F(Customized.b) +SINK(customized.a) +SINK(customized.b) From 394991164fecbe11586432d3d92db1b16c4a7d36 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Tue, 11 Aug 2020 13:05:35 +0200 Subject: [PATCH 027/133] Python: Update test expectations --- .../coverage/classesCallGraph.expected | 118 +------- .../dataflow/coverage/dataflow.expected | 256 +++++++++--------- 2 files changed, 134 insertions(+), 240 deletions(-) diff --git a/python/ql/test/experimental/dataflow/coverage/classesCallGraph.expected b/python/ql/test/experimental/dataflow/coverage/classesCallGraph.expected index 23d7c73ac30..fde0cce16d6 100644 --- a/python/ql/test/experimental/dataflow/coverage/classesCallGraph.expected +++ b/python/ql/test/experimental/dataflow/coverage/classesCallGraph.expected @@ -1,112 +1,6 @@ -| classes.py:21:12:21:78 | ControlFlowNode for BoolExpr | classes.py:24:8:24:19 | ControlFlowNode for is_source() | -| classes.py:21:12:21:78 | ControlFlowNode for BoolExpr | classes.py:30:8:30:19 | ControlFlowNode for is_source() | -| classes.py:24:18:24:18 | ControlFlowNode for x | classes.py:20:15:20:15 | SSA variable x | -| classes.py:30:18:30:18 | ControlFlowNode for x | classes.py:20:15:20:15 | SSA variable x | -| classes.py:41:10:41:10 | ControlFlowNode for a | classes.py:20:15:20:15 | SSA variable x | -| classes.py:41:10:41:10 | ControlFlowNode for a | classes.py:23:10:23:10 | SSA variable x | -| classes.py:41:10:41:10 | ControlFlowNode for a | classes.py:43:6:43:17 | ControlFlowNode for f() | -| classes.py:43:6:43:17 | ControlFlowNode for f() | classes.py:20:15:20:15 | SSA variable x | -| classes.py:43:6:43:17 | ControlFlowNode for f() | classes.py:23:10:23:10 | SSA variable x | -| classes.py:43:6:43:17 | ControlFlowNode for f() | classes.py:43:6:43:17 | ControlFlowNode for f() | -| classes.py:43:8:43:13 | ControlFlowNode for SOURCE | classes.py:20:15:20:15 | SSA variable x | -| classes.py:43:8:43:13 | ControlFlowNode for SOURCE | classes.py:23:10:23:10 | SSA variable x | -| classes.py:43:8:43:13 | ControlFlowNode for SOURCE | classes.py:40:7:40:7 | SSA variable a | -| classes.py:43:8:43:13 | ControlFlowNode for SOURCE | classes.py:43:6:43:17 | ControlFlowNode for f() | -| classes.py:43:16:43:16 | ControlFlowNode for IntegerLiteral | classes.py:40:10:40:10 | SSA variable b | -| classes.py:51:16:51:16 | ControlFlowNode for x | classes.py:20:15:20:15 | SSA variable x | -| classes.py:51:16:51:16 | ControlFlowNode for x | classes.py:23:10:23:10 | SSA variable x | -| classes.py:51:16:51:16 | ControlFlowNode for x | classes.py:76:6:76:24 | ControlFlowNode for Attribute() | -| classes.py:51:16:51:16 | ControlFlowNode for x | classes.py:77:6:77:27 | ControlFlowNode for Attribute() | -| classes.py:55:16:55:16 | ControlFlowNode for x | classes.py:20:15:20:15 | SSA variable x | -| classes.py:55:16:55:16 | ControlFlowNode for x | classes.py:23:10:23:10 | SSA variable x | -| classes.py:55:16:55:16 | ControlFlowNode for x | classes.py:85:6:85:26 | ControlFlowNode for Attribute() | -| classes.py:55:16:55:16 | ControlFlowNode for x | classes.py:86:6:86:26 | ControlFlowNode for Attribute() | -| classes.py:68:14:68:14 | ControlFlowNode for x | classes.py:112:18:112:31 | ControlFlowNode for Attribute() | -| classes.py:76:6:76:24 | ControlFlowNode for Attribute() | classes.py:20:15:20:15 | SSA variable x | -| classes.py:76:6:76:24 | ControlFlowNode for Attribute() | classes.py:23:10:23:10 | SSA variable x | -| classes.py:76:6:76:24 | ControlFlowNode for Attribute() | classes.py:76:6:76:24 | ControlFlowNode for Attribute() | -| classes.py:76:15:76:20 | ControlFlowNode for SOURCE | classes.py:20:15:20:15 | SSA variable x | -| classes.py:76:15:76:20 | ControlFlowNode for SOURCE | classes.py:23:10:23:10 | SSA variable x | -| classes.py:76:15:76:20 | ControlFlowNode for SOURCE | classes.py:49:16:49:19 | SSA variable self | -| classes.py:76:15:76:20 | ControlFlowNode for SOURCE | classes.py:49:22:49:22 | SSA variable x | -| classes.py:76:15:76:20 | ControlFlowNode for SOURCE | classes.py:76:6:76:24 | ControlFlowNode for Attribute() | -| classes.py:76:23:76:23 | ControlFlowNode for C | classes.py:20:15:20:15 | SSA variable x | -| classes.py:76:23:76:23 | ControlFlowNode for C | classes.py:23:10:23:10 | SSA variable x | -| classes.py:76:23:76:23 | ControlFlowNode for C | classes.py:49:22:49:22 | SSA variable x | -| classes.py:76:23:76:23 | ControlFlowNode for C | classes.py:49:25:49:27 | SSA variable cls | -| classes.py:76:23:76:23 | ControlFlowNode for C | classes.py:76:6:76:24 | ControlFlowNode for Attribute() | -| classes.py:77:6:77:27 | ControlFlowNode for Attribute() | classes.py:20:15:20:15 | SSA variable x | -| classes.py:77:6:77:27 | ControlFlowNode for Attribute() | classes.py:23:10:23:10 | SSA variable x | -| classes.py:77:6:77:27 | ControlFlowNode for Attribute() | classes.py:77:6:77:27 | ControlFlowNode for Attribute() | -| classes.py:77:15:77:15 | ControlFlowNode for c | classes.py:49:16:49:19 | SSA variable self | -| classes.py:77:18:77:23 | ControlFlowNode for SOURCE | classes.py:20:15:20:15 | SSA variable x | -| classes.py:77:18:77:23 | ControlFlowNode for SOURCE | classes.py:23:10:23:10 | SSA variable x | -| classes.py:77:18:77:23 | ControlFlowNode for SOURCE | classes.py:49:22:49:22 | SSA variable x | -| classes.py:77:18:77:23 | ControlFlowNode for SOURCE | classes.py:77:6:77:27 | ControlFlowNode for Attribute() | -| classes.py:77:26:77:26 | ControlFlowNode for C | classes.py:49:25:49:27 | SSA variable cls | -| classes.py:78:6:78:27 | ControlFlowNode for func_obj() | classes.py:20:15:20:15 | SSA variable x | -| classes.py:78:6:78:27 | ControlFlowNode for func_obj() | classes.py:23:10:23:10 | SSA variable x | -| classes.py:78:6:78:27 | ControlFlowNode for func_obj() | classes.py:78:6:78:27 | ControlFlowNode for func_obj() | -| classes.py:85:6:85:26 | ControlFlowNode for Attribute() | classes.py:20:15:20:15 | SSA variable x | -| classes.py:85:6:85:26 | ControlFlowNode for Attribute() | classes.py:23:10:23:10 | SSA variable x | -| classes.py:85:6:85:26 | ControlFlowNode for Attribute() | classes.py:85:6:85:26 | ControlFlowNode for Attribute() | -| classes.py:85:20:85:25 | ControlFlowNode for SOURCE | classes.py:20:15:20:15 | SSA variable x | -| classes.py:85:20:85:25 | ControlFlowNode for SOURCE | classes.py:23:10:23:10 | SSA variable x | -| classes.py:85:20:85:25 | ControlFlowNode for SOURCE | classes.py:54:21:54:23 | SSA variable cls | -| classes.py:85:20:85:25 | ControlFlowNode for SOURCE | classes.py:54:26:54:26 | SSA variable x | -| classes.py:85:20:85:25 | ControlFlowNode for SOURCE | classes.py:85:6:85:26 | ControlFlowNode for Attribute() | -| classes.py:86:6:86:26 | ControlFlowNode for Attribute() | classes.py:20:15:20:15 | SSA variable x | -| classes.py:86:6:86:26 | ControlFlowNode for Attribute() | classes.py:23:10:23:10 | SSA variable x | -| classes.py:86:6:86:26 | ControlFlowNode for Attribute() | classes.py:86:6:86:26 | ControlFlowNode for Attribute() | -| classes.py:86:20:86:25 | ControlFlowNode for SOURCE | classes.py:20:15:20:15 | SSA variable x | -| classes.py:86:20:86:25 | ControlFlowNode for SOURCE | classes.py:23:10:23:10 | SSA variable x | -| classes.py:86:20:86:25 | ControlFlowNode for SOURCE | classes.py:54:21:54:23 | SSA variable cls | -| classes.py:86:20:86:25 | ControlFlowNode for SOURCE | classes.py:54:26:54:26 | SSA variable x | -| classes.py:86:20:86:25 | ControlFlowNode for SOURCE | classes.py:86:6:86:26 | ControlFlowNode for Attribute() | -| classes.py:87:6:87:26 | ControlFlowNode for c_func_obj() | classes.py:20:15:20:15 | SSA variable x | -| classes.py:87:6:87:26 | ControlFlowNode for c_func_obj() | classes.py:23:10:23:10 | SSA variable x | -| classes.py:87:6:87:26 | ControlFlowNode for c_func_obj() | classes.py:87:6:87:26 | ControlFlowNode for c_func_obj() | -| classes.py:97:12:97:17 | ControlFlowNode for SOURCE | classes.py:91:9:91:9 | SSA variable x | -| classes.py:97:20:97:20 | ControlFlowNode for IntegerLiteral | classes.py:91:12:91:16 | SSA variable count | -| classes.py:98:6:98:20 | ControlFlowNode for Attribute() | classes.py:20:15:20:15 | SSA variable x | -| classes.py:98:6:98:20 | ControlFlowNode for Attribute() | classes.py:23:10:23:10 | SSA variable x | -| classes.py:98:6:98:20 | ControlFlowNode for Attribute() | classes.py:98:6:98:20 | ControlFlowNode for Attribute() | -| classes.py:101:15:101:20 | ControlFlowNode for SOURCE | classes.py:61:13:61:16 | SSA variable self | -| classes.py:101:15:101:20 | ControlFlowNode for SOURCE | classes.py:61:19:61:19 | SSA variable x | -| classes.py:101:23:101:23 | ControlFlowNode for IntegerLiteral | classes.py:61:19:61:19 | SSA variable x | -| classes.py:101:23:101:23 | ControlFlowNode for IntegerLiteral | classes.py:61:22:61:26 | SSA variable count | -| classes.py:102:6:102:21 | ControlFlowNode for Attribute() | classes.py:20:15:20:15 | SSA variable x | -| classes.py:102:6:102:21 | ControlFlowNode for Attribute() | classes.py:23:10:23:10 | SSA variable x | -| classes.py:102:6:102:21 | ControlFlowNode for Attribute() | classes.py:102:6:102:21 | ControlFlowNode for Attribute() | -| classes.py:108:10:108:10 | ControlFlowNode for x | classes.py:111:18:111:29 | ControlFlowNode for coro() | -| classes.py:111:6:111:30 | ControlFlowNode for Attribute() | classes.py:20:15:20:15 | SSA variable x | -| classes.py:111:6:111:30 | ControlFlowNode for Attribute() | classes.py:23:10:23:10 | SSA variable x | -| classes.py:111:6:111:30 | ControlFlowNode for Attribute() | classes.py:111:6:111:30 | ControlFlowNode for Attribute() | -| classes.py:111:23:111:28 | ControlFlowNode for SOURCE | classes.py:107:16:107:16 | SSA variable x | -| classes.py:111:23:111:28 | ControlFlowNode for SOURCE | classes.py:111:18:111:29 | ControlFlowNode for coro() | -| classes.py:112:6:112:32 | ControlFlowNode for Attribute() | classes.py:20:15:20:15 | SSA variable x | -| classes.py:112:6:112:32 | ControlFlowNode for Attribute() | classes.py:23:10:23:10 | SSA variable x | -| classes.py:112:6:112:32 | ControlFlowNode for Attribute() | classes.py:112:6:112:32 | ControlFlowNode for Attribute() | -| classes.py:112:25:112:30 | ControlFlowNode for SOURCE | classes.py:67:20:67:23 | SSA variable self | -| classes.py:112:25:112:30 | ControlFlowNode for SOURCE | classes.py:67:26:67:26 | SSA variable x | -| classes.py:112:25:112:30 | ControlFlowNode for SOURCE | classes.py:112:18:112:31 | ControlFlowNode for Attribute() | -| classes.py:122:10:122:16 | ControlFlowNode for Await | classes.py:124:18:124:29 | ControlFlowNode for agen() | -| classes.py:124:6:124:30 | ControlFlowNode for Attribute() | classes.py:20:15:20:15 | SSA variable x | -| classes.py:124:6:124:30 | ControlFlowNode for Attribute() | classes.py:23:10:23:10 | SSA variable x | -| classes.py:124:6:124:30 | ControlFlowNode for Attribute() | classes.py:124:6:124:30 | ControlFlowNode for Attribute() | -| classes.py:124:23:124:28 | ControlFlowNode for SOURCE | classes.py:120:16:120:16 | SSA variable x | -| classes.py:154:12:154:31 | ControlFlowNode for Attribute() | classes.py:154:12:154:31 | ControlFlowNode for Attribute() | -| classes.py:161:6:161:17 | ControlFlowNode for Attribute | classes.py:20:15:20:15 | SSA variable x | -| classes.py:161:6:161:17 | ControlFlowNode for Attribute | classes.py:23:10:23:10 | SSA variable x | -| classes.py:162:8:162:19 | ControlFlowNode for Attribute | classes.py:20:15:20:15 | SSA variable x | -| classes.py:162:8:162:19 | ControlFlowNode for Attribute | classes.py:29:12:29:12 | SSA variable x | -| classes.py:163:6:163:17 | ControlFlowNode for Attribute | classes.py:20:15:20:15 | SSA variable x | -| classes.py:163:6:163:17 | ControlFlowNode for Attribute | classes.py:23:10:23:10 | SSA variable x | -| classes.py:164:6:164:17 | ControlFlowNode for Attribute | classes.py:20:15:20:15 | SSA variable x | -| classes.py:164:6:164:17 | ControlFlowNode for Attribute | classes.py:23:10:23:10 | SSA variable x | -| classes.py:174:12:174:31 | ControlFlowNode for Attribute() | classes.py:174:12:174:31 | ControlFlowNode for Attribute() | -| classes.py:329:7:329:22 | ControlFlowNode for set() | classes.py:329:7:329:22 | ControlFlowNode for set() | -| classes.py:333:7:333:28 | ControlFlowNode for frozenset() | classes.py:333:7:333:28 | ControlFlowNode for frozenset() | -| classes.py:337:7:337:26 | ControlFlowNode for dict() | classes.py:337:7:337:26 | ControlFlowNode for dict() | -| classes.py:458:28:458:51 | ControlFlowNode for dict() | classes.py:458:28:458:51 | ControlFlowNode for dict() | -| classes.py:575:12:575:24 | ControlFlowNode for Attribute() | classes.py:575:12:575:24 | ControlFlowNode for Attribute() | +| classes.py:19:12:19:31 | ControlFlowNode for Attribute() | classes.py:19:12:19:31 | ControlFlowNode for Attribute() | +| classes.py:174:7:174:22 | ControlFlowNode for set() | classes.py:174:7:174:22 | ControlFlowNode for set() | +| classes.py:178:7:178:28 | ControlFlowNode for frozenset() | classes.py:178:7:178:28 | ControlFlowNode for frozenset() | +| classes.py:182:7:182:26 | ControlFlowNode for dict() | classes.py:182:7:182:26 | ControlFlowNode for dict() | +| classes.py:303:28:303:51 | ControlFlowNode for dict() | classes.py:303:28:303:51 | ControlFlowNode for dict() | +| classes.py:420:12:420:24 | ControlFlowNode for Attribute() | classes.py:420:12:420:24 | ControlFlowNode for Attribute() | diff --git a/python/ql/test/experimental/dataflow/coverage/dataflow.expected b/python/ql/test/experimental/dataflow/coverage/dataflow.expected index 700da23c5ef..2b446581634 100644 --- a/python/ql/test/experimental/dataflow/coverage/dataflow.expected +++ b/python/ql/test/experimental/dataflow/coverage/dataflow.expected @@ -1,73 +1,73 @@ edges -| classes.py:18:1:18:6 | GSSA Variable SOURCE | classes.py:43:6:43:17 | ControlFlowNode for f() | -| classes.py:18:1:18:6 | GSSA Variable SOURCE | classes.py:43:6:43:17 | GSSA Variable SOURCE | -| classes.py:18:1:18:6 | GSSA Variable SOURCE | classes.py:43:8:43:13 | ControlFlowNode for SOURCE | -| classes.py:18:10:18:17 | ControlFlowNode for Str | classes.py:18:1:18:6 | GSSA Variable SOURCE | -| classes.py:43:6:43:17 | GSSA Variable SOURCE | classes.py:70:5:70:7 | ControlFlowNode for C() | -| classes.py:43:6:43:17 | GSSA Variable SOURCE | classes.py:76:6:76:24 | ControlFlowNode for Attribute() | -| classes.py:43:6:43:17 | GSSA Variable SOURCE | classes.py:76:6:76:24 | GSSA Variable SOURCE | -| classes.py:43:6:43:17 | GSSA Variable SOURCE | classes.py:76:15:76:20 | ControlFlowNode for SOURCE | -| classes.py:43:8:43:13 | ControlFlowNode for SOURCE | classes.py:43:6:43:17 | ControlFlowNode for f() | -| classes.py:70:1:70:1 | GSSA Variable c | classes.py:76:6:76:24 | ControlFlowNode for Attribute() | -| classes.py:70:1:70:1 | GSSA Variable c | classes.py:76:6:76:24 | GSSA Variable c | -| classes.py:70:5:70:7 | ControlFlowNode for C() | classes.py:70:1:70:1 | GSSA Variable c | -| classes.py:76:6:76:24 | GSSA Variable SOURCE | classes.py:77:6:77:27 | ControlFlowNode for Attribute() | -| classes.py:76:6:76:24 | GSSA Variable SOURCE | classes.py:77:18:77:23 | ControlFlowNode for SOURCE | -| classes.py:76:6:76:24 | GSSA Variable SOURCE | classes.py:78:6:78:27 | ControlFlowNode for func_obj() | -| classes.py:76:6:76:24 | GSSA Variable SOURCE | classes.py:85:6:85:26 | ControlFlowNode for Attribute() | -| classes.py:76:6:76:24 | GSSA Variable SOURCE | classes.py:85:6:85:26 | GSSA Variable SOURCE | -| classes.py:76:6:76:24 | GSSA Variable SOURCE | classes.py:85:20:85:25 | ControlFlowNode for SOURCE | -| classes.py:76:6:76:24 | GSSA Variable c | classes.py:77:6:77:27 | ControlFlowNode for Attribute() | -| classes.py:76:6:76:24 | GSSA Variable c | classes.py:77:6:77:27 | GSSA Variable c | -| classes.py:76:15:76:20 | ControlFlowNode for SOURCE | classes.py:76:6:76:24 | ControlFlowNode for Attribute() | -| classes.py:77:6:77:27 | GSSA Variable c | classes.py:78:6:78:27 | ControlFlowNode for func_obj() | -| classes.py:77:6:77:27 | GSSA Variable c | classes.py:78:6:78:27 | GSSA Variable c | -| classes.py:77:18:77:23 | ControlFlowNode for SOURCE | classes.py:77:6:77:27 | ControlFlowNode for Attribute() | -| classes.py:78:6:78:27 | GSSA Variable c | classes.py:85:6:85:26 | ControlFlowNode for Attribute() | -| classes.py:78:6:78:27 | GSSA Variable c | classes.py:85:6:85:26 | GSSA Variable c | -| classes.py:85:6:85:26 | GSSA Variable SOURCE | classes.py:86:6:86:26 | ControlFlowNode for Attribute() | -| classes.py:85:6:85:26 | GSSA Variable SOURCE | classes.py:86:6:86:26 | GSSA Variable SOURCE | -| classes.py:85:6:85:26 | GSSA Variable SOURCE | classes.py:86:20:86:25 | ControlFlowNode for SOURCE | -| classes.py:85:6:85:26 | GSSA Variable c | classes.py:86:6:86:26 | ControlFlowNode for Attribute() | -| classes.py:85:6:85:26 | GSSA Variable c | classes.py:87:6:87:26 | ControlFlowNode for c_func_obj() | -| classes.py:85:6:85:26 | GSSA Variable c | classes.py:97:8:97:21 | ControlFlowNode for gen() | -| classes.py:85:6:85:26 | GSSA Variable c | classes.py:98:6:98:20 | ControlFlowNode for Attribute() | -| classes.py:85:6:85:26 | GSSA Variable c | classes.py:101:9:101:24 | ControlFlowNode for Attribute() | -| classes.py:85:6:85:26 | GSSA Variable c | classes.py:101:9:101:24 | GSSA Variable c | -| classes.py:85:20:85:25 | ControlFlowNode for SOURCE | classes.py:85:6:85:26 | ControlFlowNode for Attribute() | -| classes.py:86:6:86:26 | GSSA Variable SOURCE | classes.py:87:6:87:26 | ControlFlowNode for c_func_obj() | -| classes.py:86:6:86:26 | GSSA Variable SOURCE | classes.py:97:8:97:21 | ControlFlowNode for gen() | -| classes.py:86:6:86:26 | GSSA Variable SOURCE | classes.py:97:8:97:21 | GSSA Variable SOURCE | -| classes.py:86:20:86:25 | ControlFlowNode for SOURCE | classes.py:86:6:86:26 | ControlFlowNode for Attribute() | -| classes.py:97:1:97:4 | GSSA Variable iter | classes.py:98:6:98:20 | ControlFlowNode for Attribute() | -| classes.py:97:1:97:4 | GSSA Variable iter | classes.py:98:6:98:20 | GSSA Variable iter | -| classes.py:97:8:97:21 | ControlFlowNode for gen() | classes.py:97:1:97:4 | GSSA Variable iter | -| classes.py:97:8:97:21 | GSSA Variable SOURCE | classes.py:98:6:98:20 | ControlFlowNode for Attribute() | -| classes.py:97:8:97:21 | GSSA Variable SOURCE | classes.py:101:9:101:24 | ControlFlowNode for Attribute() | -| classes.py:97:8:97:21 | GSSA Variable SOURCE | classes.py:101:9:101:24 | GSSA Variable SOURCE | -| classes.py:98:6:98:20 | GSSA Variable iter | classes.py:101:9:101:24 | ControlFlowNode for Attribute() | -| classes.py:98:6:98:20 | GSSA Variable iter | classes.py:102:6:102:21 | ControlFlowNode for Attribute() | -| classes.py:98:6:98:20 | GSSA Variable iter | classes.py:111:6:111:30 | ControlFlowNode for Attribute() | -| classes.py:98:6:98:20 | GSSA Variable iter | classes.py:112:6:112:32 | ControlFlowNode for Attribute() | -| classes.py:98:6:98:20 | GSSA Variable iter | classes.py:124:6:124:30 | ControlFlowNode for Attribute() | -| classes.py:101:1:101:5 | GSSA Variable oiter | classes.py:102:6:102:21 | ControlFlowNode for Attribute() | -| classes.py:101:1:101:5 | GSSA Variable oiter | classes.py:102:6:102:21 | GSSA Variable oiter | -| classes.py:101:9:101:24 | ControlFlowNode for Attribute() | classes.py:101:1:101:5 | GSSA Variable oiter | -| classes.py:101:9:101:24 | GSSA Variable SOURCE | classes.py:102:6:102:21 | ControlFlowNode for Attribute() | -| classes.py:101:9:101:24 | GSSA Variable SOURCE | classes.py:111:18:111:29 | GSSA Variable SOURCE | -| classes.py:101:9:101:24 | GSSA Variable c | classes.py:102:6:102:21 | ControlFlowNode for Attribute() | -| classes.py:101:9:101:24 | GSSA Variable c | classes.py:111:6:111:30 | ControlFlowNode for Attribute() | -| classes.py:101:9:101:24 | GSSA Variable c | classes.py:112:18:112:31 | GSSA Variable c | -| classes.py:102:6:102:21 | GSSA Variable oiter | classes.py:111:6:111:30 | ControlFlowNode for Attribute() | -| classes.py:102:6:102:21 | GSSA Variable oiter | classes.py:112:6:112:32 | ControlFlowNode for Attribute() | -| classes.py:102:6:102:21 | GSSA Variable oiter | classes.py:124:6:124:30 | ControlFlowNode for Attribute() | -| classes.py:111:18:111:29 | GSSA Variable SOURCE | classes.py:111:6:111:30 | ControlFlowNode for Attribute() | -| classes.py:111:18:111:29 | GSSA Variable SOURCE | classes.py:112:18:112:31 | GSSA Variable SOURCE | -| classes.py:112:18:112:31 | GSSA Variable SOURCE | classes.py:112:6:112:32 | ControlFlowNode for Attribute() | -| classes.py:112:18:112:31 | GSSA Variable SOURCE | classes.py:124:18:124:29 | GSSA Variable SOURCE | -| classes.py:112:18:112:31 | GSSA Variable c | classes.py:112:6:112:32 | ControlFlowNode for Attribute() | -| classes.py:112:18:112:31 | GSSA Variable c | classes.py:124:6:124:30 | ControlFlowNode for Attribute() | -| classes.py:124:18:124:29 | GSSA Variable SOURCE | classes.py:124:6:124:30 | ControlFlowNode for Attribute() | +| datamodel.py:13:1:13:6 | GSSA Variable SOURCE | datamodel.py:38:6:38:17 | ControlFlowNode for f() | +| datamodel.py:13:1:13:6 | GSSA Variable SOURCE | datamodel.py:38:6:38:17 | GSSA Variable SOURCE | +| datamodel.py:13:1:13:6 | GSSA Variable SOURCE | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | +| datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:13:1:13:6 | GSSA Variable SOURCE | +| datamodel.py:38:6:38:17 | GSSA Variable SOURCE | datamodel.py:65:5:65:7 | ControlFlowNode for C() | +| datamodel.py:38:6:38:17 | GSSA Variable SOURCE | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | +| datamodel.py:38:6:38:17 | GSSA Variable SOURCE | datamodel.py:71:6:71:24 | GSSA Variable SOURCE | +| datamodel.py:38:6:38:17 | GSSA Variable SOURCE | datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | +| datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:38:6:38:17 | ControlFlowNode for f() | +| datamodel.py:65:1:65:1 | GSSA Variable c | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | +| datamodel.py:65:1:65:1 | GSSA Variable c | datamodel.py:71:6:71:24 | GSSA Variable c | +| datamodel.py:65:5:65:7 | ControlFlowNode for C() | datamodel.py:65:1:65:1 | GSSA Variable c | +| datamodel.py:71:6:71:24 | GSSA Variable SOURCE | datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | +| datamodel.py:71:6:71:24 | GSSA Variable SOURCE | datamodel.py:72:18:72:23 | ControlFlowNode for SOURCE | +| datamodel.py:71:6:71:24 | GSSA Variable SOURCE | datamodel.py:73:6:73:27 | ControlFlowNode for func_obj() | +| datamodel.py:71:6:71:24 | GSSA Variable SOURCE | datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | +| datamodel.py:71:6:71:24 | GSSA Variable SOURCE | datamodel.py:80:6:80:26 | GSSA Variable SOURCE | +| datamodel.py:71:6:71:24 | GSSA Variable SOURCE | datamodel.py:80:20:80:25 | ControlFlowNode for SOURCE | +| datamodel.py:71:6:71:24 | GSSA Variable c | datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | +| datamodel.py:71:6:71:24 | GSSA Variable c | datamodel.py:72:6:72:27 | GSSA Variable c | +| datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | +| datamodel.py:72:6:72:27 | GSSA Variable c | datamodel.py:73:6:73:27 | ControlFlowNode for func_obj() | +| datamodel.py:72:6:72:27 | GSSA Variable c | datamodel.py:73:6:73:27 | GSSA Variable c | +| datamodel.py:72:18:72:23 | ControlFlowNode for SOURCE | datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | +| datamodel.py:73:6:73:27 | GSSA Variable c | datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | +| datamodel.py:73:6:73:27 | GSSA Variable c | datamodel.py:80:6:80:26 | GSSA Variable c | +| datamodel.py:80:6:80:26 | GSSA Variable SOURCE | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | +| datamodel.py:80:6:80:26 | GSSA Variable SOURCE | datamodel.py:81:6:81:26 | GSSA Variable SOURCE | +| datamodel.py:80:6:80:26 | GSSA Variable SOURCE | datamodel.py:81:20:81:25 | ControlFlowNode for SOURCE | +| datamodel.py:80:6:80:26 | GSSA Variable c | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | +| datamodel.py:80:6:80:26 | GSSA Variable c | datamodel.py:82:6:82:26 | ControlFlowNode for c_func_obj() | +| datamodel.py:80:6:80:26 | GSSA Variable c | datamodel.py:92:8:92:21 | ControlFlowNode for gen() | +| datamodel.py:80:6:80:26 | GSSA Variable c | datamodel.py:93:6:93:20 | ControlFlowNode for Attribute() | +| datamodel.py:80:6:80:26 | GSSA Variable c | datamodel.py:96:9:96:24 | ControlFlowNode for Attribute() | +| datamodel.py:80:6:80:26 | GSSA Variable c | datamodel.py:96:9:96:24 | GSSA Variable c | +| datamodel.py:80:20:80:25 | ControlFlowNode for SOURCE | datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | +| datamodel.py:81:6:81:26 | GSSA Variable SOURCE | datamodel.py:82:6:82:26 | ControlFlowNode for c_func_obj() | +| datamodel.py:81:6:81:26 | GSSA Variable SOURCE | datamodel.py:92:8:92:21 | ControlFlowNode for gen() | +| datamodel.py:81:6:81:26 | GSSA Variable SOURCE | datamodel.py:92:8:92:21 | GSSA Variable SOURCE | +| datamodel.py:81:20:81:25 | ControlFlowNode for SOURCE | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | +| datamodel.py:92:1:92:4 | GSSA Variable iter | datamodel.py:93:6:93:20 | ControlFlowNode for Attribute() | +| datamodel.py:92:1:92:4 | GSSA Variable iter | datamodel.py:93:6:93:20 | GSSA Variable iter | +| datamodel.py:92:8:92:21 | ControlFlowNode for gen() | datamodel.py:92:1:92:4 | GSSA Variable iter | +| datamodel.py:92:8:92:21 | GSSA Variable SOURCE | datamodel.py:93:6:93:20 | ControlFlowNode for Attribute() | +| datamodel.py:92:8:92:21 | GSSA Variable SOURCE | datamodel.py:96:9:96:24 | ControlFlowNode for Attribute() | +| datamodel.py:92:8:92:21 | GSSA Variable SOURCE | datamodel.py:96:9:96:24 | GSSA Variable SOURCE | +| datamodel.py:93:6:93:20 | GSSA Variable iter | datamodel.py:96:9:96:24 | ControlFlowNode for Attribute() | +| datamodel.py:93:6:93:20 | GSSA Variable iter | datamodel.py:97:6:97:21 | ControlFlowNode for Attribute() | +| datamodel.py:93:6:93:20 | GSSA Variable iter | datamodel.py:106:6:106:30 | ControlFlowNode for Attribute() | +| datamodel.py:93:6:93:20 | GSSA Variable iter | datamodel.py:107:6:107:32 | ControlFlowNode for Attribute() | +| datamodel.py:93:6:93:20 | GSSA Variable iter | datamodel.py:119:6:119:30 | ControlFlowNode for Attribute() | +| datamodel.py:96:1:96:5 | GSSA Variable oiter | datamodel.py:97:6:97:21 | ControlFlowNode for Attribute() | +| datamodel.py:96:1:96:5 | GSSA Variable oiter | datamodel.py:97:6:97:21 | GSSA Variable oiter | +| datamodel.py:96:9:96:24 | ControlFlowNode for Attribute() | datamodel.py:96:1:96:5 | GSSA Variable oiter | +| datamodel.py:96:9:96:24 | GSSA Variable SOURCE | datamodel.py:97:6:97:21 | ControlFlowNode for Attribute() | +| datamodel.py:96:9:96:24 | GSSA Variable SOURCE | datamodel.py:106:18:106:29 | GSSA Variable SOURCE | +| datamodel.py:96:9:96:24 | GSSA Variable c | datamodel.py:97:6:97:21 | ControlFlowNode for Attribute() | +| datamodel.py:96:9:96:24 | GSSA Variable c | datamodel.py:106:6:106:30 | ControlFlowNode for Attribute() | +| datamodel.py:96:9:96:24 | GSSA Variable c | datamodel.py:107:18:107:31 | GSSA Variable c | +| datamodel.py:97:6:97:21 | GSSA Variable oiter | datamodel.py:106:6:106:30 | ControlFlowNode for Attribute() | +| datamodel.py:97:6:97:21 | GSSA Variable oiter | datamodel.py:107:6:107:32 | ControlFlowNode for Attribute() | +| datamodel.py:97:6:97:21 | GSSA Variable oiter | datamodel.py:119:6:119:30 | ControlFlowNode for Attribute() | +| datamodel.py:106:18:106:29 | GSSA Variable SOURCE | datamodel.py:106:6:106:30 | ControlFlowNode for Attribute() | +| datamodel.py:106:18:106:29 | GSSA Variable SOURCE | datamodel.py:107:18:107:31 | GSSA Variable SOURCE | +| datamodel.py:107:18:107:31 | GSSA Variable SOURCE | datamodel.py:107:6:107:32 | ControlFlowNode for Attribute() | +| datamodel.py:107:18:107:31 | GSSA Variable SOURCE | datamodel.py:119:18:119:29 | GSSA Variable SOURCE | +| datamodel.py:107:18:107:31 | GSSA Variable c | datamodel.py:107:6:107:32 | ControlFlowNode for Attribute() | +| datamodel.py:107:18:107:31 | GSSA Variable c | datamodel.py:119:6:119:30 | ControlFlowNode for Attribute() | +| datamodel.py:119:18:119:29 | GSSA Variable SOURCE | datamodel.py:119:6:119:30 | ControlFlowNode for Attribute() | | test.py:43:9:43:14 | ControlFlowNode for SOURCE | test.py:44:10:44:10 | ControlFlowNode for x | | test.py:48:9:48:16 | ControlFlowNode for Str | test.py:49:10:49:10 | ControlFlowNode for x | | test.py:52:9:52:17 | ControlFlowNode for Str | test.py:53:10:53:10 | ControlFlowNode for x | @@ -78,48 +78,48 @@ edges | test.py:305:12:305:17 | ControlFlowNode for SOURCE | test.py:305:10:305:18 | ControlFlowNode for f() | | test.py:309:28:309:33 | ControlFlowNode for SOURCE | test.py:309:10:309:34 | ControlFlowNode for second() | nodes -| classes.py:18:1:18:6 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | -| classes.py:18:10:18:17 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str | -| classes.py:43:6:43:17 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() | -| classes.py:43:6:43:17 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | -| classes.py:43:8:43:13 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| classes.py:70:1:70:1 | GSSA Variable c | semmle.label | GSSA Variable c | -| classes.py:70:5:70:7 | ControlFlowNode for C() | semmle.label | ControlFlowNode for C() | -| classes.py:76:6:76:24 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| classes.py:76:6:76:24 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | -| classes.py:76:6:76:24 | GSSA Variable c | semmle.label | GSSA Variable c | -| classes.py:76:15:76:20 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| classes.py:77:6:77:27 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| classes.py:77:6:77:27 | GSSA Variable c | semmle.label | GSSA Variable c | -| classes.py:77:18:77:23 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| classes.py:78:6:78:27 | ControlFlowNode for func_obj() | semmle.label | ControlFlowNode for func_obj() | -| classes.py:78:6:78:27 | GSSA Variable c | semmle.label | GSSA Variable c | -| classes.py:85:6:85:26 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| classes.py:85:6:85:26 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | -| classes.py:85:6:85:26 | GSSA Variable c | semmle.label | GSSA Variable c | -| classes.py:85:20:85:25 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| classes.py:86:6:86:26 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| classes.py:86:6:86:26 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | -| classes.py:86:20:86:25 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| classes.py:87:6:87:26 | ControlFlowNode for c_func_obj() | semmle.label | ControlFlowNode for c_func_obj() | -| classes.py:97:1:97:4 | GSSA Variable iter | semmle.label | GSSA Variable iter | -| classes.py:97:8:97:21 | ControlFlowNode for gen() | semmle.label | ControlFlowNode for gen() | -| classes.py:97:8:97:21 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | -| classes.py:98:6:98:20 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| classes.py:98:6:98:20 | GSSA Variable iter | semmle.label | GSSA Variable iter | -| classes.py:101:1:101:5 | GSSA Variable oiter | semmle.label | GSSA Variable oiter | -| classes.py:101:9:101:24 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| classes.py:101:9:101:24 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | -| classes.py:101:9:101:24 | GSSA Variable c | semmle.label | GSSA Variable c | -| classes.py:102:6:102:21 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| classes.py:102:6:102:21 | GSSA Variable oiter | semmle.label | GSSA Variable oiter | -| classes.py:111:6:111:30 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| classes.py:111:18:111:29 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | -| classes.py:112:6:112:32 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| classes.py:112:18:112:31 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | -| classes.py:112:18:112:31 | GSSA Variable c | semmle.label | GSSA Variable c | -| classes.py:124:6:124:30 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| classes.py:124:18:124:29 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| datamodel.py:13:1:13:6 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| datamodel.py:13:10:13:17 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str | +| datamodel.py:38:6:38:17 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() | +| datamodel.py:38:6:38:17 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| datamodel.py:65:1:65:1 | GSSA Variable c | semmle.label | GSSA Variable c | +| datamodel.py:65:5:65:7 | ControlFlowNode for C() | semmle.label | ControlFlowNode for C() | +| datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| datamodel.py:71:6:71:24 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| datamodel.py:71:6:71:24 | GSSA Variable c | semmle.label | GSSA Variable c | +| datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| datamodel.py:72:6:72:27 | GSSA Variable c | semmle.label | GSSA Variable c | +| datamodel.py:72:18:72:23 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| datamodel.py:73:6:73:27 | ControlFlowNode for func_obj() | semmle.label | ControlFlowNode for func_obj() | +| datamodel.py:73:6:73:27 | GSSA Variable c | semmle.label | GSSA Variable c | +| datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| datamodel.py:80:6:80:26 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| datamodel.py:80:6:80:26 | GSSA Variable c | semmle.label | GSSA Variable c | +| datamodel.py:80:20:80:25 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| datamodel.py:81:6:81:26 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| datamodel.py:81:20:81:25 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| datamodel.py:82:6:82:26 | ControlFlowNode for c_func_obj() | semmle.label | ControlFlowNode for c_func_obj() | +| datamodel.py:92:1:92:4 | GSSA Variable iter | semmle.label | GSSA Variable iter | +| datamodel.py:92:8:92:21 | ControlFlowNode for gen() | semmle.label | ControlFlowNode for gen() | +| datamodel.py:92:8:92:21 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| datamodel.py:93:6:93:20 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| datamodel.py:93:6:93:20 | GSSA Variable iter | semmle.label | GSSA Variable iter | +| datamodel.py:96:1:96:5 | GSSA Variable oiter | semmle.label | GSSA Variable oiter | +| datamodel.py:96:9:96:24 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| datamodel.py:96:9:96:24 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| datamodel.py:96:9:96:24 | GSSA Variable c | semmle.label | GSSA Variable c | +| datamodel.py:97:6:97:21 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| datamodel.py:97:6:97:21 | GSSA Variable oiter | semmle.label | GSSA Variable oiter | +| datamodel.py:106:6:106:30 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| datamodel.py:106:18:106:29 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| datamodel.py:107:6:107:32 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| datamodel.py:107:18:107:31 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| datamodel.py:107:18:107:31 | GSSA Variable c | semmle.label | GSSA Variable c | +| datamodel.py:119:6:119:30 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| datamodel.py:119:18:119:29 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | | test.py:43:9:43:14 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:44:10:44:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | | test.py:48:9:48:16 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str | @@ -139,23 +139,23 @@ nodes | test.py:309:10:309:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | | test.py:309:28:309:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | #select -| classes.py:43:6:43:17 | ControlFlowNode for f() | classes.py:18:10:18:17 | ControlFlowNode for Str | classes.py:43:6:43:17 | ControlFlowNode for f() | | -| classes.py:43:6:43:17 | ControlFlowNode for f() | classes.py:43:8:43:13 | ControlFlowNode for SOURCE | classes.py:43:6:43:17 | ControlFlowNode for f() | | -| classes.py:76:6:76:24 | ControlFlowNode for Attribute() | classes.py:18:10:18:17 | ControlFlowNode for Str | classes.py:76:6:76:24 | ControlFlowNode for Attribute() | | -| classes.py:76:6:76:24 | ControlFlowNode for Attribute() | classes.py:76:15:76:20 | ControlFlowNode for SOURCE | classes.py:76:6:76:24 | ControlFlowNode for Attribute() | | -| classes.py:77:6:77:27 | ControlFlowNode for Attribute() | classes.py:18:10:18:17 | ControlFlowNode for Str | classes.py:77:6:77:27 | ControlFlowNode for Attribute() | | -| classes.py:77:6:77:27 | ControlFlowNode for Attribute() | classes.py:77:18:77:23 | ControlFlowNode for SOURCE | classes.py:77:6:77:27 | ControlFlowNode for Attribute() | | -| classes.py:78:6:78:27 | ControlFlowNode for func_obj() | classes.py:18:10:18:17 | ControlFlowNode for Str | classes.py:78:6:78:27 | ControlFlowNode for func_obj() | | -| classes.py:85:6:85:26 | ControlFlowNode for Attribute() | classes.py:18:10:18:17 | ControlFlowNode for Str | classes.py:85:6:85:26 | ControlFlowNode for Attribute() | | -| classes.py:85:6:85:26 | ControlFlowNode for Attribute() | classes.py:85:20:85:25 | ControlFlowNode for SOURCE | classes.py:85:6:85:26 | ControlFlowNode for Attribute() | | -| classes.py:86:6:86:26 | ControlFlowNode for Attribute() | classes.py:18:10:18:17 | ControlFlowNode for Str | classes.py:86:6:86:26 | ControlFlowNode for Attribute() | | -| classes.py:86:6:86:26 | ControlFlowNode for Attribute() | classes.py:86:20:86:25 | ControlFlowNode for SOURCE | classes.py:86:6:86:26 | ControlFlowNode for Attribute() | | -| classes.py:87:6:87:26 | ControlFlowNode for c_func_obj() | classes.py:18:10:18:17 | ControlFlowNode for Str | classes.py:87:6:87:26 | ControlFlowNode for c_func_obj() | | -| classes.py:98:6:98:20 | ControlFlowNode for Attribute() | classes.py:18:10:18:17 | ControlFlowNode for Str | classes.py:98:6:98:20 | ControlFlowNode for Attribute() | | -| classes.py:102:6:102:21 | ControlFlowNode for Attribute() | classes.py:18:10:18:17 | ControlFlowNode for Str | classes.py:102:6:102:21 | ControlFlowNode for Attribute() | | -| classes.py:111:6:111:30 | ControlFlowNode for Attribute() | classes.py:18:10:18:17 | ControlFlowNode for Str | classes.py:111:6:111:30 | ControlFlowNode for Attribute() | | -| classes.py:112:6:112:32 | ControlFlowNode for Attribute() | classes.py:18:10:18:17 | ControlFlowNode for Str | classes.py:112:6:112:32 | ControlFlowNode for Attribute() | | -| classes.py:124:6:124:30 | ControlFlowNode for Attribute() | classes.py:18:10:18:17 | ControlFlowNode for Str | classes.py:124:6:124:30 | ControlFlowNode for Attribute() | | +| datamodel.py:38:6:38:17 | ControlFlowNode for f() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:38:6:38:17 | ControlFlowNode for f() | | +| datamodel.py:38:6:38:17 | ControlFlowNode for f() | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:38:6:38:17 | ControlFlowNode for f() | | +| datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | | +| datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | | +| datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | | +| datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | datamodel.py:72:18:72:23 | ControlFlowNode for SOURCE | datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | | +| datamodel.py:73:6:73:27 | ControlFlowNode for func_obj() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:73:6:73:27 | ControlFlowNode for func_obj() | | +| datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | | +| datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | datamodel.py:80:20:80:25 | ControlFlowNode for SOURCE | datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | | +| datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | | +| datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | datamodel.py:81:20:81:25 | ControlFlowNode for SOURCE | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | | +| datamodel.py:82:6:82:26 | ControlFlowNode for c_func_obj() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:82:6:82:26 | ControlFlowNode for c_func_obj() | | +| datamodel.py:93:6:93:20 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:93:6:93:20 | ControlFlowNode for Attribute() | | +| datamodel.py:97:6:97:21 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:97:6:97:21 | ControlFlowNode for Attribute() | | +| datamodel.py:106:6:106:30 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:106:6:106:30 | ControlFlowNode for Attribute() | | +| datamodel.py:107:6:107:32 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:107:6:107:32 | ControlFlowNode for Attribute() | | +| datamodel.py:119:6:119:30 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:119:6:119:30 | ControlFlowNode for Attribute() | | | test.py:44:10:44:10 | ControlFlowNode for x | test.py:43:9:43:14 | ControlFlowNode for SOURCE | test.py:44:10:44:10 | ControlFlowNode for x | | | test.py:49:10:49:10 | ControlFlowNode for x | test.py:48:9:48:16 | ControlFlowNode for Str | test.py:49:10:49:10 | ControlFlowNode for x | | | test.py:53:10:53:10 | ControlFlowNode for x | test.py:52:9:52:17 | ControlFlowNode for Str | test.py:53:10:53:10 | ControlFlowNode for x | | From dd4d00293d07f140f53ef524930b4edc62e1728c Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Tue, 11 Aug 2020 14:16:02 +0200 Subject: [PATCH 028/133] Python: remaining class tests --- .../experimental/dataflow/coverage/classes.py | 50 ++++++++++++++++++- .../coverage/classesCallGraph.expected | 2 +- 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/python/ql/test/experimental/dataflow/coverage/classes.py b/python/ql/test/experimental/dataflow/coverage/classes.py index 63147cfd6ae..927fbc50abe 100644 --- a/python/ql/test/experimental/dataflow/coverage/classes.py +++ b/python/ql/test/experimental/dataflow/coverage/classes.py @@ -302,13 +302,20 @@ def test_set_name(): with_set_name = With_set_name() type("Owner", (object,), dict(attr=with_set_name)) -# 3.3.2.4. __slots__ +# 3.3.2.4. __slots__ // We are not testing the suppression of -weakref_ and _dict_ here # object.__slots__ # __weakref__ # __dict__ # 3.3.3. Customizing class creation # classmethod object.__init_subclass__(cls) +class With_init_subclass: + + def __init_subclass__(cls): + OK() + +def test_init_subclass(): + type("Subclass", (With_init_subclass,), {}) # 3.3.3.1. Metaclasses # By default, classes are constructed using type(). The class body is executed in a new namespace and the class name is bound locally to the result of type(name, bases, namespace). @@ -318,13 +325,52 @@ def test_set_name(): # 3.3.3.4. Preparing the class namespace # metaclass.__prepare__(name, bases, **kwds) +class With_prepare(type): + + def __prepare__(name, bases, **kwds): + OK() + return kwds + + +def test_prepare(): + class With_meta(metaclass=With_prepare): + pass # 3.3.4. Customizing instance and subclass checks # class.__instancecheck__(self, instance) +class With_instancecheck: + + def __instancecheck__(self, instance): + OK() + return True + +def test_instancecheck(): + with_instancecheck = With_instancecheck() + isinstance("", with_instancecheck) + # class.__subclasscheck__(self, subclass) +class With_subclasscheck: + + def __subclasscheck__(self, subclass): + OK() + return True + +def test_subclasscheck(): + with_subclasscheck = With_subclasscheck() + issubclass(object, with_subclasscheck) + # 3.3.5. Emulating generic types # classmethod object.__class_getitem__(cls, key) +class With_class_getitem: + + def __class_getitem__(cls, key): + OK() + return object + +def test_class_getitem(): + with_class_getitem = With_class_getitem[int]() + # 3.3.6. Emulating callable objects # object.__call__(self[, args...]) @@ -1113,7 +1159,7 @@ async def atest_await(): await(with_await) -# # 3.4.2. Coroutine Objects +# # 3.4.2. Coroutine Objects // These should be handled as normal function calls # # coroutine.send(value) # # coroutine.throw(type[, value[, traceback]]) # # coroutine.close() diff --git a/python/ql/test/experimental/dataflow/coverage/classesCallGraph.expected b/python/ql/test/experimental/dataflow/coverage/classesCallGraph.expected index fde0cce16d6..4baf0b077ab 100644 --- a/python/ql/test/experimental/dataflow/coverage/classesCallGraph.expected +++ b/python/ql/test/experimental/dataflow/coverage/classesCallGraph.expected @@ -3,4 +3,4 @@ | classes.py:178:7:178:28 | ControlFlowNode for frozenset() | classes.py:178:7:178:28 | ControlFlowNode for frozenset() | | classes.py:182:7:182:26 | ControlFlowNode for dict() | classes.py:182:7:182:26 | ControlFlowNode for dict() | | classes.py:303:28:303:51 | ControlFlowNode for dict() | classes.py:303:28:303:51 | ControlFlowNode for dict() | -| classes.py:420:12:420:24 | ControlFlowNode for Attribute() | classes.py:420:12:420:24 | ControlFlowNode for Attribute() | +| classes.py:466:12:466:24 | ControlFlowNode for Attribute() | classes.py:466:12:466:24 | ControlFlowNode for Attribute() | From 21246624b4aa1fee03b6a4088898bc35a8dbfb82 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Tue, 11 Aug 2020 15:15:39 +0200 Subject: [PATCH 029/133] Java: Add PrintWriter.format as XSS sink. --- java/ql/src/semmle/code/java/security/XSS.qll | 1 + 1 file changed, 1 insertion(+) diff --git a/java/ql/src/semmle/code/java/security/XSS.qll b/java/ql/src/semmle/code/java/security/XSS.qll index 9f5ed3fe9d6..fd1fdcde061 100644 --- a/java/ql/src/semmle/code/java/security/XSS.qll +++ b/java/ql/src/semmle/code/java/security/XSS.qll @@ -97,6 +97,7 @@ class WritingMethod extends Method { ( this.getName().matches("print%") or this.getName() = "append" or + this.getName() = "format" or this.getName() = "write" ) } From 2ea25b9d90502cf08efa7246762f4db7f4e04a0e Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Tue, 11 Aug 2020 16:45:42 +0200 Subject: [PATCH 030/133] C++: Precise printing of integer bounds The pretty-printing of a QL `float` didn't include enough digits to tell whether a large number had accurate bounds. The `toString` value of a float appears to be more precise. --- .../SimpleRangeAnalysis/lowerBound.expected | 1048 ++++++++--------- .../SimpleRangeAnalysis/lowerBound.ql | 2 +- .../SimpleRangeAnalysis/upperBound.expected | 1048 ++++++++--------- .../SimpleRangeAnalysis/upperBound.ql | 2 +- 4 files changed, 1050 insertions(+), 1050 deletions(-) diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected index 4ad86a3d2ab..ebef46d3e2d 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected @@ -1,524 +1,524 @@ -| inline_assembly.c:10:3:10:3 | y | 0.0 | -| inline_assembly.c:12:29:12:29 | x | 0.0 | -| inline_assembly.c:12:32:12:32 | y | 1.0 | -| inline_assembly.c:16:25:16:25 | x | 0.0 | -| inline_assembly.c:16:35:16:35 | y | 1.0 | -| inline_assembly.c:21:29:21:29 | x | 0.0 | -| inline_assembly.c:21:32:21:32 | y | 0.0 | -| minmax.c:18:37:18:37 | x | 1.0 | -| minmax.c:18:40:18:40 | y | 2.0 | -| minmax.c:18:43:18:43 | z | 3.0 | -| minmax.c:20:2:20:2 | z | -2.147483648E9 | -| minmax.c:22:8:22:8 | x | 1.0 | -| minmax.c:22:14:22:14 | y | 2.0 | -| minmax.c:22:18:22:18 | t | -2.147483648E9 | -| minmax.c:22:22:22:22 | x | 1.0 | -| minmax.c:23:3:23:3 | t | 0.0 | -| minmax.c:26:37:26:37 | x | 1.0 | -| minmax.c:26:40:26:40 | y | 2.0 | -| minmax.c:26:43:26:43 | z | 0.0 | -| test.c:8:5:8:9 | count | -2.147483648E9 | -| test.c:8:13:8:17 | count | -2.147483648E9 | -| test.c:10:10:10:14 | count | -2.147483648E9 | -| test.c:16:5:16:9 | count | -2.147483648E9 | -| test.c:16:14:16:18 | count | 0.0 | -| test.c:18:10:18:14 | count | 0.0 | -| test.c:24:5:24:9 | count | 0.0 | -| test.c:25:5:25:9 | count | -2.147483648E9 | -| test.c:25:13:25:17 | count | 1.0 | -| test.c:27:10:27:14 | count | 0.0 | -| test.c:33:8:33:8 | i | -2.147483648E9 | -| test.c:33:15:33:15 | i | 0.0 | -| test.c:33:22:33:22 | i | -2.147483648E9 | -| test.c:33:26:33:26 | i | 0.0 | -| test.c:34:5:34:9 | total | -2.147483648E9 | -| test.c:34:14:34:14 | i | 0.0 | -| test.c:36:10:36:14 | total | -2.147483648E9 | -| test.c:36:18:36:18 | i | 2.0 | -| test.c:42:8:42:8 | i | -2.147483648E9 | -| test.c:42:15:42:15 | i | 0.0 | -| test.c:42:22:42:22 | i | 0.0 | -| test.c:43:5:43:9 | total | -2.147483648E9 | -| test.c:43:14:43:14 | i | 0.0 | -| test.c:45:10:45:14 | total | -2.147483648E9 | -| test.c:45:18:45:18 | i | 2.0 | -| test.c:51:8:51:8 | i | -2.147483648E9 | -| test.c:51:15:51:15 | i | 0.0 | -| test.c:51:24:51:24 | i | -2.147483648E9 | -| test.c:51:28:51:28 | i | 0.0 | -| test.c:52:5:52:9 | total | -2.147483648E9 | -| test.c:52:14:52:14 | i | 0.0 | -| test.c:54:10:54:14 | total | -2.147483648E9 | -| test.c:54:18:54:18 | i | 2.0 | -| test.c:58:7:58:7 | i | -2.147483648E9 | -| test.c:59:9:59:9 | i | -2.147483648E9 | -| test.c:60:14:60:14 | i | -2.147483648E9 | -| test.c:67:15:67:15 | y | -2.147483648E9 | -| test.c:67:20:67:20 | y | -999.0 | -| test.c:68:9:68:9 | x | -2.147483648E9 | -| test.c:68:13:68:13 | y | -999.0 | -| test.c:69:14:69:14 | x | -2.147483648E9 | -| test.c:72:10:72:10 | y | -2.147483648E9 | -| test.c:76:7:76:7 | y | -2.147483648E9 | -| test.c:77:9:77:9 | x | -2.147483648E9 | -| test.c:81:9:81:9 | x | -2.147483648E9 | -| test.c:85:10:85:10 | x | 4.0 | -| test.c:89:7:89:7 | y | -2.147483648E9 | -| test.c:90:9:90:9 | x | -2.147483648E9 | -| test.c:90:13:90:13 | y | 8.0 | -| test.c:93:12:93:12 | x | 8.0 | -| test.c:100:3:100:3 | c | -128.0 | -| test.c:101:7:101:7 | c | -128.0 | -| test.c:104:7:104:7 | c | -128.0 | -| test.c:105:5:105:5 | c | -128.0 | -| test.c:106:9:106:9 | c | -128.0 | -| test.c:109:9:109:9 | c | -128.0 | -| test.c:119:10:119:10 | n | 0.0 | -| test.c:124:11:124:15 | Start | 0.0 | -| test.c:127:6:127:10 | Start | 0.0 | -| test.c:127:15:127:20 | Length | 0.0 | -| test.c:135:22:135:22 | c | -128.0 | -| test.c:137:20:137:20 | x | 0.0 | -| test.c:138:11:138:11 | i | -2.147483648E9 | -| test.c:139:19:139:19 | c | -128.0 | -| test.c:139:23:139:23 | i | -2.147483648E9 | -| test.c:139:27:139:28 | uc | 0.0 | -| test.c:139:32:139:32 | x | 0.0 | -| test.c:139:36:139:36 | y | 0.0 | -| test.c:139:40:139:40 | z | -2.147483648E9 | -| test.c:144:23:144:23 | x | -2.147483648E9 | -| test.c:145:32:145:32 | x | -2.147483648E9 | -| test.c:146:33:146:33 | x | -2.147483648E9 | -| test.c:147:31:147:31 | x | -2.147483648E9 | -| test.c:148:13:148:13 | x | -2.147483648E9 | -| test.c:149:23:149:23 | x | -2.147483648E9 | -| test.c:150:10:150:11 | x0 | -128.0 | -| test.c:150:15:150:16 | x1 | 0.0 | -| test.c:150:20:150:21 | x2 | 0.0 | -| test.c:150:25:150:26 | x3 | -2.147483648E9 | -| test.c:150:30:150:31 | c0 | -128.0 | -| test.c:150:35:150:36 | s0 | 0.0 | -| test.c:154:11:154:11 | x | -9.223372036854776E18 | -| test.c:154:20:154:20 | x | 1.0 | -| test.c:154:30:154:30 | x | 1.0 | -| test.c:154:35:154:35 | x | 1.0 | -| test.c:161:12:161:12 | a | -2.147483648E9 | -| test.c:161:17:161:17 | a | 3.0 | -| test.c:162:14:162:14 | a | 3.0 | -| test.c:163:14:163:14 | a | 3.0 | -| test.c:164:5:164:9 | total | 0.0 | -| test.c:164:14:164:14 | b | 3.0 | -| test.c:164:16:164:16 | c | -11.0 | -| test.c:166:12:166:12 | a | -2.147483648E9 | -| test.c:166:17:166:17 | a | 0.0 | -| test.c:167:14:167:14 | a | 0.0 | -| test.c:168:14:168:14 | a | 0.0 | -| test.c:169:5:169:9 | total | -8.0 | -| test.c:169:14:169:14 | b | 0.0 | -| test.c:169:16:169:16 | c | -11.0 | -| test.c:171:13:171:13 | a | -2.147483648E9 | -| test.c:171:18:171:18 | a | -7.0 | -| test.c:172:14:172:14 | a | -7.0 | -| test.c:173:14:173:14 | a | -7.0 | -| test.c:174:5:174:9 | total | -19.0 | -| test.c:174:14:174:14 | b | -7.0 | -| test.c:174:16:174:16 | c | -11.0 | -| test.c:176:13:176:13 | a | -2.147483648E9 | -| test.c:176:18:176:18 | a | -7.0 | -| test.c:177:14:177:14 | a | -7.0 | -| test.c:178:14:178:14 | a | -7.0 | -| test.c:179:5:179:9 | total | -37.0 | -| test.c:179:14:179:14 | b | -7.0 | -| test.c:179:16:179:16 | c | -1.0 | -| test.c:181:13:181:13 | a | -2.147483648E9 | -| test.c:181:18:181:18 | a | -7.0 | -| test.c:182:14:182:14 | a | -7.0 | -| test.c:183:14:183:14 | a | -7.0 | -| test.c:184:5:184:9 | total | -45.0 | -| test.c:184:14:184:14 | b | -7.0 | -| test.c:184:16:184:16 | c | -0.0 | -| test.c:186:13:186:13 | a | -2.147483648E9 | -| test.c:186:18:186:18 | a | -7.0 | -| test.c:187:14:187:14 | a | -7.0 | -| test.c:188:14:188:14 | a | -7.0 | -| test.c:189:5:189:9 | total | -52.0 | -| test.c:189:14:189:14 | b | -7.0 | -| test.c:189:16:189:16 | c | 2.0 | -| test.c:192:10:192:14 | total | -57.0 | -| test.c:200:12:200:12 | a | -2.147483648E9 | -| test.c:200:17:200:17 | a | 3.0 | -| test.c:200:33:200:33 | b | -2.147483648E9 | -| test.c:200:38:200:38 | b | 5.0 | -| test.c:201:13:201:13 | a | 3.0 | -| test.c:201:15:201:15 | b | 5.0 | -| test.c:202:5:202:9 | total | 0.0 | -| test.c:202:14:202:14 | r | -2.147483648E9 | -| test.c:204:12:204:12 | a | -2.147483648E9 | -| test.c:204:17:204:17 | a | 3.0 | -| test.c:204:33:204:33 | b | -2.147483648E9 | -| test.c:204:38:204:38 | b | 0.0 | -| test.c:205:13:205:13 | a | 3.0 | -| test.c:205:15:205:15 | b | 0.0 | -| test.c:206:5:206:9 | total | -2.147483648E9 | -| test.c:206:14:206:14 | r | -2.147483648E9 | -| test.c:208:12:208:12 | a | -2.147483648E9 | -| test.c:208:17:208:17 | a | 3.0 | -| test.c:208:35:208:35 | b | -2.147483648E9 | -| test.c:208:40:208:40 | b | -13.0 | -| test.c:209:13:209:13 | a | 3.0 | -| test.c:209:15:209:15 | b | -13.0 | -| test.c:210:5:210:9 | total | -2.147483648E9 | -| test.c:210:14:210:14 | r | -2.147483648E9 | -| test.c:212:12:212:12 | a | -2.147483648E9 | -| test.c:212:17:212:17 | a | 3.0 | -| test.c:212:35:212:35 | b | -2.147483648E9 | -| test.c:212:40:212:40 | b | -13.0 | -| test.c:213:13:213:13 | a | 3.0 | -| test.c:213:15:213:15 | b | -13.0 | -| test.c:214:5:214:9 | total | -2.147483648E9 | -| test.c:214:14:214:14 | r | -2.147483648E9 | -| test.c:216:12:216:12 | a | -2.147483648E9 | -| test.c:216:17:216:17 | a | 3.0 | -| test.c:216:35:216:35 | b | -2.147483648E9 | -| test.c:216:40:216:40 | b | -13.0 | -| test.c:217:13:217:13 | a | 3.0 | -| test.c:217:15:217:15 | b | -13.0 | -| test.c:218:5:218:9 | total | -2.147483648E9 | -| test.c:218:14:218:14 | r | -2.147483648E9 | -| test.c:221:10:221:14 | total | -2.147483648E9 | -| test.c:228:12:228:12 | a | -2.147483648E9 | -| test.c:228:17:228:17 | a | 0.0 | -| test.c:228:33:228:33 | b | -2.147483648E9 | -| test.c:228:38:228:38 | b | 5.0 | -| test.c:229:13:229:13 | a | 0.0 | -| test.c:229:15:229:15 | b | 5.0 | -| test.c:230:5:230:9 | total | 0.0 | -| test.c:230:14:230:14 | r | -2.147483648E9 | -| test.c:232:12:232:12 | a | -2.147483648E9 | -| test.c:232:17:232:17 | a | 0.0 | -| test.c:232:33:232:33 | b | -2.147483648E9 | -| test.c:232:38:232:38 | b | 0.0 | -| test.c:233:13:233:13 | a | 0.0 | -| test.c:233:15:233:15 | b | 0.0 | -| test.c:234:5:234:9 | total | -2.147483648E9 | -| test.c:234:14:234:14 | r | -2.147483648E9 | -| test.c:236:12:236:12 | a | -2.147483648E9 | -| test.c:236:17:236:17 | a | 0.0 | -| test.c:236:35:236:35 | b | -2.147483648E9 | -| test.c:236:40:236:40 | b | -13.0 | -| test.c:237:13:237:13 | a | 0.0 | -| test.c:237:15:237:15 | b | -13.0 | -| test.c:238:5:238:9 | total | -2.147483648E9 | -| test.c:238:14:238:14 | r | -2.147483648E9 | -| test.c:240:12:240:12 | a | -2.147483648E9 | -| test.c:240:17:240:17 | a | 0.0 | -| test.c:240:35:240:35 | b | -2.147483648E9 | -| test.c:240:40:240:40 | b | -13.0 | -| test.c:241:13:241:13 | a | 0.0 | -| test.c:241:15:241:15 | b | -13.0 | -| test.c:242:5:242:9 | total | -2.147483648E9 | -| test.c:242:14:242:14 | r | -2.147483648E9 | -| test.c:244:12:244:12 | a | -2.147483648E9 | -| test.c:244:17:244:17 | a | 0.0 | -| test.c:244:35:244:35 | b | -2.147483648E9 | -| test.c:244:40:244:40 | b | -13.0 | -| test.c:245:13:245:13 | a | 0.0 | -| test.c:245:15:245:15 | b | -13.0 | -| test.c:246:5:246:9 | total | -2.147483648E9 | -| test.c:246:14:246:14 | r | -2.147483648E9 | -| test.c:249:10:249:14 | total | -2.147483648E9 | -| test.c:256:14:256:14 | a | -2.147483648E9 | -| test.c:256:19:256:19 | a | -17.0 | -| test.c:256:35:256:35 | b | -2.147483648E9 | -| test.c:256:40:256:40 | b | 5.0 | -| test.c:257:13:257:13 | a | -17.0 | -| test.c:257:15:257:15 | b | 5.0 | -| test.c:258:5:258:9 | total | 0.0 | -| test.c:258:14:258:14 | r | -2.147483648E9 | -| test.c:260:14:260:14 | a | -2.147483648E9 | -| test.c:260:19:260:19 | a | -17.0 | -| test.c:260:35:260:35 | b | -2.147483648E9 | -| test.c:260:40:260:40 | b | 0.0 | -| test.c:261:13:261:13 | a | -17.0 | -| test.c:261:15:261:15 | b | 0.0 | -| test.c:262:5:262:9 | total | -2.147483648E9 | -| test.c:262:14:262:14 | r | -2.147483648E9 | -| test.c:264:14:264:14 | a | -2.147483648E9 | -| test.c:264:19:264:19 | a | -17.0 | -| test.c:264:37:264:37 | b | -2.147483648E9 | -| test.c:264:42:264:42 | b | -13.0 | -| test.c:265:13:265:13 | a | -17.0 | -| test.c:265:15:265:15 | b | -13.0 | -| test.c:266:5:266:9 | total | -2.147483648E9 | -| test.c:266:14:266:14 | r | -2.147483648E9 | -| test.c:268:14:268:14 | a | -2.147483648E9 | -| test.c:268:19:268:19 | a | -17.0 | -| test.c:268:37:268:37 | b | -2.147483648E9 | -| test.c:268:42:268:42 | b | -13.0 | -| test.c:269:13:269:13 | a | -17.0 | -| test.c:269:15:269:15 | b | -13.0 | -| test.c:270:5:270:9 | total | -2.147483648E9 | -| test.c:270:14:270:14 | r | -2.147483648E9 | -| test.c:272:14:272:14 | a | -2.147483648E9 | -| test.c:272:19:272:19 | a | -17.0 | -| test.c:272:37:272:37 | b | -2.147483648E9 | -| test.c:272:42:272:42 | b | -13.0 | -| test.c:273:13:273:13 | a | -17.0 | -| test.c:273:15:273:15 | b | -13.0 | -| test.c:274:5:274:9 | total | -2.147483648E9 | -| test.c:274:14:274:14 | r | -2.147483648E9 | -| test.c:277:10:277:14 | total | -2.147483648E9 | -| test.c:284:14:284:14 | a | -2.147483648E9 | -| test.c:284:19:284:19 | a | -17.0 | -| test.c:284:34:284:34 | b | -2.147483648E9 | -| test.c:284:39:284:39 | b | 5.0 | -| test.c:285:13:285:13 | a | -17.0 | -| test.c:285:15:285:15 | b | 5.0 | -| test.c:286:5:286:9 | total | 0.0 | -| test.c:286:14:286:14 | r | -2.147483648E9 | -| test.c:288:14:288:14 | a | -2.147483648E9 | -| test.c:288:19:288:19 | a | -17.0 | -| test.c:288:34:288:34 | b | -2.147483648E9 | -| test.c:288:39:288:39 | b | 0.0 | -| test.c:289:13:289:13 | a | -17.0 | -| test.c:289:15:289:15 | b | 0.0 | -| test.c:290:5:290:9 | total | -2.147483648E9 | -| test.c:290:14:290:14 | r | -2.147483648E9 | -| test.c:292:14:292:14 | a | -2.147483648E9 | -| test.c:292:19:292:19 | a | -17.0 | -| test.c:292:36:292:36 | b | -2.147483648E9 | -| test.c:292:41:292:41 | b | -13.0 | -| test.c:293:13:293:13 | a | -17.0 | -| test.c:293:15:293:15 | b | -13.0 | -| test.c:294:5:294:9 | total | -2.147483648E9 | -| test.c:294:14:294:14 | r | -2.147483648E9 | -| test.c:296:14:296:14 | a | -2.147483648E9 | -| test.c:296:19:296:19 | a | -17.0 | -| test.c:296:36:296:36 | b | -2.147483648E9 | -| test.c:296:41:296:41 | b | -13.0 | -| test.c:297:13:297:13 | a | -17.0 | -| test.c:297:15:297:15 | b | -13.0 | -| test.c:298:5:298:9 | total | -2.147483648E9 | -| test.c:298:14:298:14 | r | -2.147483648E9 | -| test.c:300:14:300:14 | a | -2.147483648E9 | -| test.c:300:19:300:19 | a | -17.0 | -| test.c:300:36:300:36 | b | -2.147483648E9 | -| test.c:300:41:300:41 | b | -13.0 | -| test.c:301:13:301:13 | a | -17.0 | -| test.c:301:15:301:15 | b | -13.0 | -| test.c:302:5:302:9 | total | -2.147483648E9 | -| test.c:302:14:302:14 | r | -2.147483648E9 | -| test.c:305:10:305:14 | total | -2.147483648E9 | -| test.c:312:14:312:14 | a | -2.147483648E9 | -| test.c:312:19:312:19 | a | -17.0 | -| test.c:312:35:312:35 | b | -2.147483648E9 | -| test.c:312:40:312:40 | b | 5.0 | -| test.c:313:13:313:13 | a | -17.0 | -| test.c:313:15:313:15 | b | 5.0 | -| test.c:314:5:314:9 | total | 0.0 | -| test.c:314:14:314:14 | r | -2.147483648E9 | -| test.c:316:14:316:14 | a | -2.147483648E9 | -| test.c:316:19:316:19 | a | -17.0 | -| test.c:316:35:316:35 | b | -2.147483648E9 | -| test.c:316:40:316:40 | b | 0.0 | -| test.c:317:13:317:13 | a | -17.0 | -| test.c:317:15:317:15 | b | 0.0 | -| test.c:318:5:318:9 | total | -2.147483648E9 | -| test.c:318:14:318:14 | r | -2.147483648E9 | -| test.c:320:14:320:14 | a | -2.147483648E9 | -| test.c:320:19:320:19 | a | -17.0 | -| test.c:320:37:320:37 | b | -2.147483648E9 | -| test.c:320:42:320:42 | b | -13.0 | -| test.c:321:13:321:13 | a | -17.0 | -| test.c:321:15:321:15 | b | -13.0 | -| test.c:322:5:322:9 | total | -2.147483648E9 | -| test.c:322:14:322:14 | r | -2.147483648E9 | -| test.c:324:14:324:14 | a | -2.147483648E9 | -| test.c:324:19:324:19 | a | -17.0 | -| test.c:324:37:324:37 | b | -2.147483648E9 | -| test.c:324:42:324:42 | b | -13.0 | -| test.c:325:13:325:13 | a | -17.0 | -| test.c:325:15:325:15 | b | -13.0 | -| test.c:326:5:326:9 | total | -2.147483648E9 | -| test.c:326:14:326:14 | r | -2.147483648E9 | -| test.c:328:14:328:14 | a | -2.147483648E9 | -| test.c:328:19:328:19 | a | -17.0 | -| test.c:328:37:328:37 | b | -2.147483648E9 | -| test.c:328:42:328:42 | b | -13.0 | -| test.c:329:13:329:13 | a | -17.0 | -| test.c:329:15:329:15 | b | -13.0 | -| test.c:330:5:330:9 | total | -2.147483648E9 | -| test.c:330:14:330:14 | r | -2.147483648E9 | -| test.c:333:10:333:14 | total | -2.147483648E9 | -| test.c:338:7:338:7 | x | -2.147483648E9 | -| test.c:342:10:342:10 | i | 0.0 | -| test.c:343:5:343:5 | i | 0.0 | -| test.c:345:3:345:3 | d | -2.147483648E9 | -| test.c:345:7:345:7 | i | 3.0 | -| test.c:346:7:346:7 | x | 0.0 | -| test.c:347:9:347:9 | d | 3.0 | -| test.c:347:14:347:14 | x | 0.0 | -| test.c:357:3:357:4 | y1 | 0.0 | -| test.c:357:8:357:8 | x | 0.0 | -| test.c:357:18:357:18 | x | 0.0 | -| test.c:358:3:358:4 | y2 | 0.0 | -| test.c:358:8:358:8 | x | 0.0 | -| test.c:358:24:358:24 | x | 0.0 | -| test.c:359:3:359:4 | y3 | 0.0 | -| test.c:360:3:360:4 | y4 | 0.0 | -| test.c:361:3:361:4 | y5 | 0.0 | -| test.c:362:3:362:4 | y6 | 0.0 | -| test.c:363:3:363:4 | y7 | 0.0 | -| test.c:364:3:364:4 | y8 | 0.0 | -| test.c:365:7:365:7 | x | 0.0 | -| test.c:366:5:366:6 | y3 | 0.0 | -| test.c:366:10:366:10 | x | 0.0 | -| test.c:367:5:367:6 | y4 | 0.0 | -| test.c:367:10:367:10 | x | 0.0 | -| test.c:368:5:368:6 | y5 | 0.0 | -| test.c:368:11:368:11 | x | 0.0 | -| test.c:369:5:369:6 | y6 | 0.0 | -| test.c:369:27:369:27 | x | 0.0 | -| test.c:370:5:370:6 | y7 | 0.0 | -| test.c:370:27:370:27 | x | 0.0 | -| test.c:371:5:371:6 | y8 | 0.0 | -| test.c:371:28:371:28 | x | 0.0 | -| test.c:373:10:373:11 | y1 | 0.0 | -| test.c:373:15:373:16 | y2 | 0.0 | -| test.c:373:20:373:21 | y3 | 0.0 | -| test.c:373:25:373:26 | y4 | 0.0 | -| test.c:373:30:373:31 | y5 | 0.0 | -| test.c:373:35:373:36 | y6 | 0.0 | -| test.c:373:40:373:41 | y7 | 0.0 | -| test.c:373:45:373:46 | y8 | 0.0 | -| test.c:379:3:379:4 | y1 | 0.0 | -| test.c:379:8:379:8 | x | 0.0 | -| test.c:379:18:379:18 | x | 101.0 | -| test.c:380:3:380:4 | y2 | 0.0 | -| test.c:380:8:380:8 | x | 0.0 | -| test.c:380:25:380:25 | x | 101.0 | -| test.c:381:3:381:4 | y3 | 0.0 | -| test.c:382:3:382:4 | y4 | 0.0 | -| test.c:383:3:383:4 | y5 | 0.0 | -| test.c:384:7:384:7 | x | 0.0 | -| test.c:385:5:385:6 | y3 | 0.0 | -| test.c:385:11:385:11 | x | 300.0 | -| test.c:386:5:386:6 | y4 | 0.0 | -| test.c:386:11:386:11 | x | 300.0 | -| test.c:387:5:387:6 | y5 | 0.0 | -| test.c:387:27:387:27 | x | 300.0 | -| test.c:389:10:389:11 | y1 | 101.0 | -| test.c:389:15:389:16 | y2 | 101.0 | -| test.c:389:20:389:21 | y3 | 0.0 | -| test.c:389:25:389:26 | y4 | 100.0 | -| test.c:389:30:389:31 | y5 | 0.0 | -| test.c:394:20:394:20 | x | 0.0 | -| test.c:394:30:394:30 | x | 0.0 | -| test.c:397:3:397:4 | y1 | 0.0 | -| test.c:397:11:397:11 | y | 0.0 | -| test.c:397:14:397:14 | y | 1.0 | -| test.c:398:3:398:4 | y2 | 0.0 | -| test.c:398:9:398:9 | y | 1.0 | -| test.c:398:14:398:14 | y | 2.0 | -| test.c:398:22:398:22 | y | 5.0 | -| test.c:399:10:399:11 | y1 | 1.0 | -| test.c:399:15:399:16 | y2 | 5.0 | -| test.c:407:3:407:3 | i | -2.147483648E9 | -| test.c:408:7:408:7 | i | 10.0 | -| test.c:410:3:410:3 | i | -2.147483648E9 | -| test.c:411:3:411:3 | i | 10.0 | -| test.c:412:7:412:7 | i | -2.147483648E9 | -| test.c:414:3:414:3 | i | -2.147483648E9 | -| test.c:415:3:415:3 | i | 40.0 | -| test.c:416:7:416:7 | i | -2.147483648E9 | -| test.c:418:3:418:3 | i | -2.147483648E9 | -| test.c:418:7:418:7 | j | -2.147483648E9 | -| test.c:419:7:419:7 | i | 40.0 | -| test.c:421:3:421:3 | i | -2.147483648E9 | -| test.c:421:8:421:8 | j | 40.0 | -| test.c:422:7:422:7 | i | 50.0 | -| test.c:424:3:424:3 | i | -2.147483648E9 | -| test.c:424:13:424:13 | j | -2.147483648E9 | -| test.c:425:7:425:7 | i | -2.147483648E9 | -| test.c:432:12:432:12 | a | 0.0 | -| test.c:432:17:432:17 | a | 3.0 | -| test.c:432:33:432:33 | b | 0.0 | -| test.c:432:38:432:38 | b | 5.0 | -| test.c:433:13:433:13 | a | 3.0 | -| test.c:433:15:433:15 | b | 5.0 | -| test.c:434:5:434:9 | total | 0.0 | -| test.c:434:14:434:14 | r | -2.147483648E9 | -| test.c:436:12:436:12 | a | 0.0 | -| test.c:436:17:436:17 | a | 3.0 | -| test.c:436:33:436:33 | b | 0.0 | -| test.c:436:38:436:38 | b | 0.0 | -| test.c:437:13:437:13 | a | 3.0 | -| test.c:437:15:437:15 | b | 0.0 | -| test.c:438:5:438:9 | total | -2.147483648E9 | -| test.c:438:14:438:14 | r | -2.147483648E9 | -| test.c:440:12:440:12 | a | 0.0 | -| test.c:440:17:440:17 | a | 3.0 | -| test.c:440:34:440:34 | b | 0.0 | -| test.c:440:39:440:39 | b | 13.0 | -| test.c:441:13:441:13 | a | 3.0 | -| test.c:441:15:441:15 | b | 13.0 | -| test.c:442:5:442:9 | total | -2.147483648E9 | -| test.c:442:14:442:14 | r | -2.147483648E9 | -| test.c:445:10:445:14 | total | -2.147483648E9 | -| test.c:451:12:451:12 | b | 0.0 | -| test.c:451:17:451:17 | b | 5.0 | -| test.c:452:16:452:16 | b | 5.0 | -| test.c:453:5:453:9 | total | 0.0 | -| test.c:453:14:453:14 | r | -2.147483648E9 | -| test.c:455:12:455:12 | b | 0.0 | -| test.c:455:17:455:17 | b | 0.0 | -| test.c:456:16:456:16 | b | 0.0 | -| test.c:457:5:457:9 | total | -2.147483648E9 | -| test.c:457:14:457:14 | r | -2.147483648E9 | -| test.c:459:13:459:13 | b | 0.0 | -| test.c:459:18:459:18 | b | 13.0 | -| test.c:460:16:460:16 | b | 13.0 | -| test.c:461:5:461:9 | total | -2.147483648E9 | -| test.c:461:14:461:14 | r | -2.147483648E9 | -| test.c:464:10:464:14 | total | -2.147483648E9 | -| test.cpp:10:7:10:7 | b | -2.147483648E9 | -| test.cpp:11:5:11:5 | x | -2.147483648E9 | -| test.cpp:13:10:13:10 | x | -2.147483648E9 | -| test.cpp:18:30:18:30 | x | -2.147483648E9 | -| test.cpp:19:10:19:11 | x0 | -128.0 | -| test.cpp:27:7:27:7 | y | -2.147483648E9 | -| test.cpp:28:5:28:5 | x | -2.147483648E9 | -| test.cpp:30:7:30:7 | y | -2.147483648E9 | -| test.cpp:31:5:31:5 | x | -2.147483648E9 | -| test.cpp:33:7:33:7 | y | -2.147483648E9 | -| test.cpp:34:5:34:5 | x | -2.147483648E9 | -| test.cpp:36:7:36:7 | y | -2.147483648E9 | -| test.cpp:37:5:37:5 | x | -2.147483648E9 | -| test.cpp:39:7:39:7 | y | -2.147483648E9 | -| test.cpp:40:5:40:5 | x | -2.147483648E9 | -| test.cpp:42:7:42:7 | y | -2.147483648E9 | -| test.cpp:43:5:43:5 | x | -2.147483648E9 | -| test.cpp:45:7:45:7 | y | -2.147483648E9 | -| test.cpp:46:5:46:5 | x | -2.147483648E9 | -| test.cpp:51:7:51:7 | x | -2.147483648E9 | -| test.cpp:52:21:52:21 | x | 0.0 | -| test.cpp:53:5:53:5 | t | 0.0 | -| test.cpp:53:15:53:16 | xb | 0.0 | -| test.cpp:56:7:56:7 | x | -2.147483648E9 | -| test.cpp:57:21:57:21 | x | 1.0 | -| test.cpp:58:5:58:5 | t | 0.0 | -| test.cpp:58:15:58:16 | xb | 1.0 | -| test.cpp:61:7:61:7 | x | -2.147483648E9 | -| test.cpp:62:21:62:21 | x | -2.147483648E9 | -| test.cpp:63:5:63:5 | t | 0.0 | -| test.cpp:63:15:63:16 | xb | 1.0 | -| test.cpp:66:19:66:19 | x | -2.147483648E9 | -| test.cpp:67:3:67:3 | t | 0.0 | -| test.cpp:67:13:67:14 | xb | 0.0 | -| test.cpp:69:10:69:10 | b | 0.0 | -| test.cpp:69:21:69:21 | t | 0.0 | -| test.cpp:74:30:74:30 | c | 0.0 | -| test.cpp:74:34:74:34 | c | 0.0 | -| test.cpp:75:22:75:30 | c_times_2 | 0.0 | -| test.cpp:77:5:77:13 | c_times_2 | 0.0 | -| test.cpp:79:3:79:11 | c_times_2 | 0.0 | +| inline_assembly.c:10:3:10:3 | y | 0 | +| inline_assembly.c:12:29:12:29 | x | 0 | +| inline_assembly.c:12:32:12:32 | y | 1 | +| inline_assembly.c:16:25:16:25 | x | 0 | +| inline_assembly.c:16:35:16:35 | y | 1 | +| inline_assembly.c:21:29:21:29 | x | 0 | +| inline_assembly.c:21:32:21:32 | y | 0 | +| minmax.c:18:37:18:37 | x | 1 | +| minmax.c:18:40:18:40 | y | 2 | +| minmax.c:18:43:18:43 | z | 3 | +| minmax.c:20:2:20:2 | z | -2147483648 | +| minmax.c:22:8:22:8 | x | 1 | +| minmax.c:22:14:22:14 | y | 2 | +| minmax.c:22:18:22:18 | t | -2147483648 | +| minmax.c:22:22:22:22 | x | 1 | +| minmax.c:23:3:23:3 | t | 0 | +| minmax.c:26:37:26:37 | x | 1 | +| minmax.c:26:40:26:40 | y | 2 | +| minmax.c:26:43:26:43 | z | 0 | +| test.c:8:5:8:9 | count | -2147483648 | +| test.c:8:13:8:17 | count | -2147483648 | +| test.c:10:10:10:14 | count | -2147483648 | +| test.c:16:5:16:9 | count | -2147483648 | +| test.c:16:14:16:18 | count | 0 | +| test.c:18:10:18:14 | count | 0 | +| test.c:24:5:24:9 | count | 0 | +| test.c:25:5:25:9 | count | -2147483648 | +| test.c:25:13:25:17 | count | 1 | +| test.c:27:10:27:14 | count | 0 | +| test.c:33:8:33:8 | i | -2147483648 | +| test.c:33:15:33:15 | i | 0 | +| test.c:33:22:33:22 | i | -2147483648 | +| test.c:33:26:33:26 | i | 0 | +| test.c:34:5:34:9 | total | -2147483648 | +| test.c:34:14:34:14 | i | 0 | +| test.c:36:10:36:14 | total | -2147483648 | +| test.c:36:18:36:18 | i | 2 | +| test.c:42:8:42:8 | i | -2147483648 | +| test.c:42:15:42:15 | i | 0 | +| test.c:42:22:42:22 | i | 0 | +| test.c:43:5:43:9 | total | -2147483648 | +| test.c:43:14:43:14 | i | 0 | +| test.c:45:10:45:14 | total | -2147483648 | +| test.c:45:18:45:18 | i | 2 | +| test.c:51:8:51:8 | i | -2147483648 | +| test.c:51:15:51:15 | i | 0 | +| test.c:51:24:51:24 | i | -2147483648 | +| test.c:51:28:51:28 | i | 0 | +| test.c:52:5:52:9 | total | -2147483648 | +| test.c:52:14:52:14 | i | 0 | +| test.c:54:10:54:14 | total | -2147483648 | +| test.c:54:18:54:18 | i | 2 | +| test.c:58:7:58:7 | i | -2147483648 | +| test.c:59:9:59:9 | i | -2147483648 | +| test.c:60:14:60:14 | i | -2147483648 | +| test.c:67:15:67:15 | y | -2147483648 | +| test.c:67:20:67:20 | y | -999 | +| test.c:68:9:68:9 | x | -2147483648 | +| test.c:68:13:68:13 | y | -999 | +| test.c:69:14:69:14 | x | -2147483648 | +| test.c:72:10:72:10 | y | -2147483648 | +| test.c:76:7:76:7 | y | -2147483648 | +| test.c:77:9:77:9 | x | -2147483648 | +| test.c:81:9:81:9 | x | -2147483648 | +| test.c:85:10:85:10 | x | 4 | +| test.c:89:7:89:7 | y | -2147483648 | +| test.c:90:9:90:9 | x | -2147483648 | +| test.c:90:13:90:13 | y | 8 | +| test.c:93:12:93:12 | x | 8 | +| test.c:100:3:100:3 | c | -128 | +| test.c:101:7:101:7 | c | -128 | +| test.c:104:7:104:7 | c | -128 | +| test.c:105:5:105:5 | c | -128 | +| test.c:106:9:106:9 | c | -128 | +| test.c:109:9:109:9 | c | -128 | +| test.c:119:10:119:10 | n | 0 | +| test.c:124:11:124:15 | Start | 0 | +| test.c:127:6:127:10 | Start | 0 | +| test.c:127:15:127:20 | Length | 0 | +| test.c:135:22:135:22 | c | -128 | +| test.c:137:20:137:20 | x | 0 | +| test.c:138:11:138:11 | i | -2147483648 | +| test.c:139:19:139:19 | c | -128 | +| test.c:139:23:139:23 | i | -2147483648 | +| test.c:139:27:139:28 | uc | 0 | +| test.c:139:32:139:32 | x | 0 | +| test.c:139:36:139:36 | y | 0 | +| test.c:139:40:139:40 | z | -2147483648 | +| test.c:144:23:144:23 | x | -2147483648 | +| test.c:145:32:145:32 | x | -2147483648 | +| test.c:146:33:146:33 | x | -2147483648 | +| test.c:147:31:147:31 | x | -2147483648 | +| test.c:148:13:148:13 | x | -2147483648 | +| test.c:149:23:149:23 | x | -2147483648 | +| test.c:150:10:150:11 | x0 | -128 | +| test.c:150:15:150:16 | x1 | 0 | +| test.c:150:20:150:21 | x2 | 0 | +| test.c:150:25:150:26 | x3 | -2147483648 | +| test.c:150:30:150:31 | c0 | -128 | +| test.c:150:35:150:36 | s0 | 0 | +| test.c:154:11:154:11 | x | -9223372036854776000 | +| test.c:154:20:154:20 | x | 1 | +| test.c:154:30:154:30 | x | 1 | +| test.c:154:35:154:35 | x | 1 | +| test.c:161:12:161:12 | a | -2147483648 | +| test.c:161:17:161:17 | a | 3 | +| test.c:162:14:162:14 | a | 3 | +| test.c:163:14:163:14 | a | 3 | +| test.c:164:5:164:9 | total | 0 | +| test.c:164:14:164:14 | b | 3 | +| test.c:164:16:164:16 | c | -11 | +| test.c:166:12:166:12 | a | -2147483648 | +| test.c:166:17:166:17 | a | 0 | +| test.c:167:14:167:14 | a | 0 | +| test.c:168:14:168:14 | a | 0 | +| test.c:169:5:169:9 | total | -8 | +| test.c:169:14:169:14 | b | 0 | +| test.c:169:16:169:16 | c | -11 | +| test.c:171:13:171:13 | a | -2147483648 | +| test.c:171:18:171:18 | a | -7 | +| test.c:172:14:172:14 | a | -7 | +| test.c:173:14:173:14 | a | -7 | +| test.c:174:5:174:9 | total | -19 | +| test.c:174:14:174:14 | b | -7 | +| test.c:174:16:174:16 | c | -11 | +| test.c:176:13:176:13 | a | -2147483648 | +| test.c:176:18:176:18 | a | -7 | +| test.c:177:14:177:14 | a | -7 | +| test.c:178:14:178:14 | a | -7 | +| test.c:179:5:179:9 | total | -37 | +| test.c:179:14:179:14 | b | -7 | +| test.c:179:16:179:16 | c | -1 | +| test.c:181:13:181:13 | a | -2147483648 | +| test.c:181:18:181:18 | a | -7 | +| test.c:182:14:182:14 | a | -7 | +| test.c:183:14:183:14 | a | -7 | +| test.c:184:5:184:9 | total | -45 | +| test.c:184:14:184:14 | b | -7 | +| test.c:184:16:184:16 | c | -0 | +| test.c:186:13:186:13 | a | -2147483648 | +| test.c:186:18:186:18 | a | -7 | +| test.c:187:14:187:14 | a | -7 | +| test.c:188:14:188:14 | a | -7 | +| test.c:189:5:189:9 | total | -52 | +| test.c:189:14:189:14 | b | -7 | +| test.c:189:16:189:16 | c | 2 | +| test.c:192:10:192:14 | total | -57 | +| test.c:200:12:200:12 | a | -2147483648 | +| test.c:200:17:200:17 | a | 3 | +| test.c:200:33:200:33 | b | -2147483648 | +| test.c:200:38:200:38 | b | 5 | +| test.c:201:13:201:13 | a | 3 | +| test.c:201:15:201:15 | b | 5 | +| test.c:202:5:202:9 | total | 0 | +| test.c:202:14:202:14 | r | -2147483648 | +| test.c:204:12:204:12 | a | -2147483648 | +| test.c:204:17:204:17 | a | 3 | +| test.c:204:33:204:33 | b | -2147483648 | +| test.c:204:38:204:38 | b | 0 | +| test.c:205:13:205:13 | a | 3 | +| test.c:205:15:205:15 | b | 0 | +| test.c:206:5:206:9 | total | -2147483648 | +| test.c:206:14:206:14 | r | -2147483648 | +| test.c:208:12:208:12 | a | -2147483648 | +| test.c:208:17:208:17 | a | 3 | +| test.c:208:35:208:35 | b | -2147483648 | +| test.c:208:40:208:40 | b | -13 | +| test.c:209:13:209:13 | a | 3 | +| test.c:209:15:209:15 | b | -13 | +| test.c:210:5:210:9 | total | -2147483648 | +| test.c:210:14:210:14 | r | -2147483648 | +| test.c:212:12:212:12 | a | -2147483648 | +| test.c:212:17:212:17 | a | 3 | +| test.c:212:35:212:35 | b | -2147483648 | +| test.c:212:40:212:40 | b | -13 | +| test.c:213:13:213:13 | a | 3 | +| test.c:213:15:213:15 | b | -13 | +| test.c:214:5:214:9 | total | -2147483648 | +| test.c:214:14:214:14 | r | -2147483648 | +| test.c:216:12:216:12 | a | -2147483648 | +| test.c:216:17:216:17 | a | 3 | +| test.c:216:35:216:35 | b | -2147483648 | +| test.c:216:40:216:40 | b | -13 | +| test.c:217:13:217:13 | a | 3 | +| test.c:217:15:217:15 | b | -13 | +| test.c:218:5:218:9 | total | -2147483648 | +| test.c:218:14:218:14 | r | -2147483648 | +| test.c:221:10:221:14 | total | -2147483648 | +| test.c:228:12:228:12 | a | -2147483648 | +| test.c:228:17:228:17 | a | 0 | +| test.c:228:33:228:33 | b | -2147483648 | +| test.c:228:38:228:38 | b | 5 | +| test.c:229:13:229:13 | a | 0 | +| test.c:229:15:229:15 | b | 5 | +| test.c:230:5:230:9 | total | 0 | +| test.c:230:14:230:14 | r | -2147483648 | +| test.c:232:12:232:12 | a | -2147483648 | +| test.c:232:17:232:17 | a | 0 | +| test.c:232:33:232:33 | b | -2147483648 | +| test.c:232:38:232:38 | b | 0 | +| test.c:233:13:233:13 | a | 0 | +| test.c:233:15:233:15 | b | 0 | +| test.c:234:5:234:9 | total | -2147483648 | +| test.c:234:14:234:14 | r | -2147483648 | +| test.c:236:12:236:12 | a | -2147483648 | +| test.c:236:17:236:17 | a | 0 | +| test.c:236:35:236:35 | b | -2147483648 | +| test.c:236:40:236:40 | b | -13 | +| test.c:237:13:237:13 | a | 0 | +| test.c:237:15:237:15 | b | -13 | +| test.c:238:5:238:9 | total | -2147483648 | +| test.c:238:14:238:14 | r | -2147483648 | +| test.c:240:12:240:12 | a | -2147483648 | +| test.c:240:17:240:17 | a | 0 | +| test.c:240:35:240:35 | b | -2147483648 | +| test.c:240:40:240:40 | b | -13 | +| test.c:241:13:241:13 | a | 0 | +| test.c:241:15:241:15 | b | -13 | +| test.c:242:5:242:9 | total | -2147483648 | +| test.c:242:14:242:14 | r | -2147483648 | +| test.c:244:12:244:12 | a | -2147483648 | +| test.c:244:17:244:17 | a | 0 | +| test.c:244:35:244:35 | b | -2147483648 | +| test.c:244:40:244:40 | b | -13 | +| test.c:245:13:245:13 | a | 0 | +| test.c:245:15:245:15 | b | -13 | +| test.c:246:5:246:9 | total | -2147483648 | +| test.c:246:14:246:14 | r | -2147483648 | +| test.c:249:10:249:14 | total | -2147483648 | +| test.c:256:14:256:14 | a | -2147483648 | +| test.c:256:19:256:19 | a | -17 | +| test.c:256:35:256:35 | b | -2147483648 | +| test.c:256:40:256:40 | b | 5 | +| test.c:257:13:257:13 | a | -17 | +| test.c:257:15:257:15 | b | 5 | +| test.c:258:5:258:9 | total | 0 | +| test.c:258:14:258:14 | r | -2147483648 | +| test.c:260:14:260:14 | a | -2147483648 | +| test.c:260:19:260:19 | a | -17 | +| test.c:260:35:260:35 | b | -2147483648 | +| test.c:260:40:260:40 | b | 0 | +| test.c:261:13:261:13 | a | -17 | +| test.c:261:15:261:15 | b | 0 | +| test.c:262:5:262:9 | total | -2147483648 | +| test.c:262:14:262:14 | r | -2147483648 | +| test.c:264:14:264:14 | a | -2147483648 | +| test.c:264:19:264:19 | a | -17 | +| test.c:264:37:264:37 | b | -2147483648 | +| test.c:264:42:264:42 | b | -13 | +| test.c:265:13:265:13 | a | -17 | +| test.c:265:15:265:15 | b | -13 | +| test.c:266:5:266:9 | total | -2147483648 | +| test.c:266:14:266:14 | r | -2147483648 | +| test.c:268:14:268:14 | a | -2147483648 | +| test.c:268:19:268:19 | a | -17 | +| test.c:268:37:268:37 | b | -2147483648 | +| test.c:268:42:268:42 | b | -13 | +| test.c:269:13:269:13 | a | -17 | +| test.c:269:15:269:15 | b | -13 | +| test.c:270:5:270:9 | total | -2147483648 | +| test.c:270:14:270:14 | r | -2147483648 | +| test.c:272:14:272:14 | a | -2147483648 | +| test.c:272:19:272:19 | a | -17 | +| test.c:272:37:272:37 | b | -2147483648 | +| test.c:272:42:272:42 | b | -13 | +| test.c:273:13:273:13 | a | -17 | +| test.c:273:15:273:15 | b | -13 | +| test.c:274:5:274:9 | total | -2147483648 | +| test.c:274:14:274:14 | r | -2147483648 | +| test.c:277:10:277:14 | total | -2147483648 | +| test.c:284:14:284:14 | a | -2147483648 | +| test.c:284:19:284:19 | a | -17 | +| test.c:284:34:284:34 | b | -2147483648 | +| test.c:284:39:284:39 | b | 5 | +| test.c:285:13:285:13 | a | -17 | +| test.c:285:15:285:15 | b | 5 | +| test.c:286:5:286:9 | total | 0 | +| test.c:286:14:286:14 | r | -2147483648 | +| test.c:288:14:288:14 | a | -2147483648 | +| test.c:288:19:288:19 | a | -17 | +| test.c:288:34:288:34 | b | -2147483648 | +| test.c:288:39:288:39 | b | 0 | +| test.c:289:13:289:13 | a | -17 | +| test.c:289:15:289:15 | b | 0 | +| test.c:290:5:290:9 | total | -2147483648 | +| test.c:290:14:290:14 | r | -2147483648 | +| test.c:292:14:292:14 | a | -2147483648 | +| test.c:292:19:292:19 | a | -17 | +| test.c:292:36:292:36 | b | -2147483648 | +| test.c:292:41:292:41 | b | -13 | +| test.c:293:13:293:13 | a | -17 | +| test.c:293:15:293:15 | b | -13 | +| test.c:294:5:294:9 | total | -2147483648 | +| test.c:294:14:294:14 | r | -2147483648 | +| test.c:296:14:296:14 | a | -2147483648 | +| test.c:296:19:296:19 | a | -17 | +| test.c:296:36:296:36 | b | -2147483648 | +| test.c:296:41:296:41 | b | -13 | +| test.c:297:13:297:13 | a | -17 | +| test.c:297:15:297:15 | b | -13 | +| test.c:298:5:298:9 | total | -2147483648 | +| test.c:298:14:298:14 | r | -2147483648 | +| test.c:300:14:300:14 | a | -2147483648 | +| test.c:300:19:300:19 | a | -17 | +| test.c:300:36:300:36 | b | -2147483648 | +| test.c:300:41:300:41 | b | -13 | +| test.c:301:13:301:13 | a | -17 | +| test.c:301:15:301:15 | b | -13 | +| test.c:302:5:302:9 | total | -2147483648 | +| test.c:302:14:302:14 | r | -2147483648 | +| test.c:305:10:305:14 | total | -2147483648 | +| test.c:312:14:312:14 | a | -2147483648 | +| test.c:312:19:312:19 | a | -17 | +| test.c:312:35:312:35 | b | -2147483648 | +| test.c:312:40:312:40 | b | 5 | +| test.c:313:13:313:13 | a | -17 | +| test.c:313:15:313:15 | b | 5 | +| test.c:314:5:314:9 | total | 0 | +| test.c:314:14:314:14 | r | -2147483648 | +| test.c:316:14:316:14 | a | -2147483648 | +| test.c:316:19:316:19 | a | -17 | +| test.c:316:35:316:35 | b | -2147483648 | +| test.c:316:40:316:40 | b | 0 | +| test.c:317:13:317:13 | a | -17 | +| test.c:317:15:317:15 | b | 0 | +| test.c:318:5:318:9 | total | -2147483648 | +| test.c:318:14:318:14 | r | -2147483648 | +| test.c:320:14:320:14 | a | -2147483648 | +| test.c:320:19:320:19 | a | -17 | +| test.c:320:37:320:37 | b | -2147483648 | +| test.c:320:42:320:42 | b | -13 | +| test.c:321:13:321:13 | a | -17 | +| test.c:321:15:321:15 | b | -13 | +| test.c:322:5:322:9 | total | -2147483648 | +| test.c:322:14:322:14 | r | -2147483648 | +| test.c:324:14:324:14 | a | -2147483648 | +| test.c:324:19:324:19 | a | -17 | +| test.c:324:37:324:37 | b | -2147483648 | +| test.c:324:42:324:42 | b | -13 | +| test.c:325:13:325:13 | a | -17 | +| test.c:325:15:325:15 | b | -13 | +| test.c:326:5:326:9 | total | -2147483648 | +| test.c:326:14:326:14 | r | -2147483648 | +| test.c:328:14:328:14 | a | -2147483648 | +| test.c:328:19:328:19 | a | -17 | +| test.c:328:37:328:37 | b | -2147483648 | +| test.c:328:42:328:42 | b | -13 | +| test.c:329:13:329:13 | a | -17 | +| test.c:329:15:329:15 | b | -13 | +| test.c:330:5:330:9 | total | -2147483648 | +| test.c:330:14:330:14 | r | -2147483648 | +| test.c:333:10:333:14 | total | -2147483648 | +| test.c:338:7:338:7 | x | -2147483648 | +| test.c:342:10:342:10 | i | 0 | +| test.c:343:5:343:5 | i | 0 | +| test.c:345:3:345:3 | d | -2147483648 | +| test.c:345:7:345:7 | i | 3 | +| test.c:346:7:346:7 | x | 0 | +| test.c:347:9:347:9 | d | 3 | +| test.c:347:14:347:14 | x | 0 | +| test.c:357:3:357:4 | y1 | 0 | +| test.c:357:8:357:8 | x | 0 | +| test.c:357:18:357:18 | x | 0 | +| test.c:358:3:358:4 | y2 | 0 | +| test.c:358:8:358:8 | x | 0 | +| test.c:358:24:358:24 | x | 0 | +| test.c:359:3:359:4 | y3 | 0 | +| test.c:360:3:360:4 | y4 | 0 | +| test.c:361:3:361:4 | y5 | 0 | +| test.c:362:3:362:4 | y6 | 0 | +| test.c:363:3:363:4 | y7 | 0 | +| test.c:364:3:364:4 | y8 | 0 | +| test.c:365:7:365:7 | x | 0 | +| test.c:366:5:366:6 | y3 | 0 | +| test.c:366:10:366:10 | x | 0 | +| test.c:367:5:367:6 | y4 | 0 | +| test.c:367:10:367:10 | x | 0 | +| test.c:368:5:368:6 | y5 | 0 | +| test.c:368:11:368:11 | x | 0 | +| test.c:369:5:369:6 | y6 | 0 | +| test.c:369:27:369:27 | x | 0 | +| test.c:370:5:370:6 | y7 | 0 | +| test.c:370:27:370:27 | x | 0 | +| test.c:371:5:371:6 | y8 | 0 | +| test.c:371:28:371:28 | x | 0 | +| test.c:373:10:373:11 | y1 | 0 | +| test.c:373:15:373:16 | y2 | 0 | +| test.c:373:20:373:21 | y3 | 0 | +| test.c:373:25:373:26 | y4 | 0 | +| test.c:373:30:373:31 | y5 | 0 | +| test.c:373:35:373:36 | y6 | 0 | +| test.c:373:40:373:41 | y7 | 0 | +| test.c:373:45:373:46 | y8 | 0 | +| test.c:379:3:379:4 | y1 | 0 | +| test.c:379:8:379:8 | x | 0 | +| test.c:379:18:379:18 | x | 101 | +| test.c:380:3:380:4 | y2 | 0 | +| test.c:380:8:380:8 | x | 0 | +| test.c:380:25:380:25 | x | 101 | +| test.c:381:3:381:4 | y3 | 0 | +| test.c:382:3:382:4 | y4 | 0 | +| test.c:383:3:383:4 | y5 | 0 | +| test.c:384:7:384:7 | x | 0 | +| test.c:385:5:385:6 | y3 | 0 | +| test.c:385:11:385:11 | x | 300 | +| test.c:386:5:386:6 | y4 | 0 | +| test.c:386:11:386:11 | x | 300 | +| test.c:387:5:387:6 | y5 | 0 | +| test.c:387:27:387:27 | x | 300 | +| test.c:389:10:389:11 | y1 | 101 | +| test.c:389:15:389:16 | y2 | 101 | +| test.c:389:20:389:21 | y3 | 0 | +| test.c:389:25:389:26 | y4 | 100 | +| test.c:389:30:389:31 | y5 | 0 | +| test.c:394:20:394:20 | x | 0 | +| test.c:394:30:394:30 | x | 0 | +| test.c:397:3:397:4 | y1 | 0 | +| test.c:397:11:397:11 | y | 0 | +| test.c:397:14:397:14 | y | 1 | +| test.c:398:3:398:4 | y2 | 0 | +| test.c:398:9:398:9 | y | 1 | +| test.c:398:14:398:14 | y | 2 | +| test.c:398:22:398:22 | y | 5 | +| test.c:399:10:399:11 | y1 | 1 | +| test.c:399:15:399:16 | y2 | 5 | +| test.c:407:3:407:3 | i | -2147483648 | +| test.c:408:7:408:7 | i | 10 | +| test.c:410:3:410:3 | i | -2147483648 | +| test.c:411:3:411:3 | i | 10 | +| test.c:412:7:412:7 | i | -2147483648 | +| test.c:414:3:414:3 | i | -2147483648 | +| test.c:415:3:415:3 | i | 40 | +| test.c:416:7:416:7 | i | -2147483648 | +| test.c:418:3:418:3 | i | -2147483648 | +| test.c:418:7:418:7 | j | -2147483648 | +| test.c:419:7:419:7 | i | 40 | +| test.c:421:3:421:3 | i | -2147483648 | +| test.c:421:8:421:8 | j | 40 | +| test.c:422:7:422:7 | i | 50 | +| test.c:424:3:424:3 | i | -2147483648 | +| test.c:424:13:424:13 | j | -2147483648 | +| test.c:425:7:425:7 | i | -2147483648 | +| test.c:432:12:432:12 | a | 0 | +| test.c:432:17:432:17 | a | 3 | +| test.c:432:33:432:33 | b | 0 | +| test.c:432:38:432:38 | b | 5 | +| test.c:433:13:433:13 | a | 3 | +| test.c:433:15:433:15 | b | 5 | +| test.c:434:5:434:9 | total | 0 | +| test.c:434:14:434:14 | r | -2147483648 | +| test.c:436:12:436:12 | a | 0 | +| test.c:436:17:436:17 | a | 3 | +| test.c:436:33:436:33 | b | 0 | +| test.c:436:38:436:38 | b | 0 | +| test.c:437:13:437:13 | a | 3 | +| test.c:437:15:437:15 | b | 0 | +| test.c:438:5:438:9 | total | -2147483648 | +| test.c:438:14:438:14 | r | -2147483648 | +| test.c:440:12:440:12 | a | 0 | +| test.c:440:17:440:17 | a | 3 | +| test.c:440:34:440:34 | b | 0 | +| test.c:440:39:440:39 | b | 13 | +| test.c:441:13:441:13 | a | 3 | +| test.c:441:15:441:15 | b | 13 | +| test.c:442:5:442:9 | total | -2147483648 | +| test.c:442:14:442:14 | r | -2147483648 | +| test.c:445:10:445:14 | total | -2147483648 | +| test.c:451:12:451:12 | b | 0 | +| test.c:451:17:451:17 | b | 5 | +| test.c:452:16:452:16 | b | 5 | +| test.c:453:5:453:9 | total | 0 | +| test.c:453:14:453:14 | r | -2147483648 | +| test.c:455:12:455:12 | b | 0 | +| test.c:455:17:455:17 | b | 0 | +| test.c:456:16:456:16 | b | 0 | +| test.c:457:5:457:9 | total | -2147483648 | +| test.c:457:14:457:14 | r | -2147483648 | +| test.c:459:13:459:13 | b | 0 | +| test.c:459:18:459:18 | b | 13 | +| test.c:460:16:460:16 | b | 13 | +| test.c:461:5:461:9 | total | -2147483648 | +| test.c:461:14:461:14 | r | -2147483648 | +| test.c:464:10:464:14 | total | -2147483648 | +| test.cpp:10:7:10:7 | b | -2147483648 | +| test.cpp:11:5:11:5 | x | -2147483648 | +| test.cpp:13:10:13:10 | x | -2147483648 | +| test.cpp:18:30:18:30 | x | -2147483648 | +| test.cpp:19:10:19:11 | x0 | -128 | +| test.cpp:27:7:27:7 | y | -2147483648 | +| test.cpp:28:5:28:5 | x | -2147483648 | +| test.cpp:30:7:30:7 | y | -2147483648 | +| test.cpp:31:5:31:5 | x | -2147483648 | +| test.cpp:33:7:33:7 | y | -2147483648 | +| test.cpp:34:5:34:5 | x | -2147483648 | +| test.cpp:36:7:36:7 | y | -2147483648 | +| test.cpp:37:5:37:5 | x | -2147483648 | +| test.cpp:39:7:39:7 | y | -2147483648 | +| test.cpp:40:5:40:5 | x | -2147483648 | +| test.cpp:42:7:42:7 | y | -2147483648 | +| test.cpp:43:5:43:5 | x | -2147483648 | +| test.cpp:45:7:45:7 | y | -2147483648 | +| test.cpp:46:5:46:5 | x | -2147483648 | +| test.cpp:51:7:51:7 | x | -2147483648 | +| test.cpp:52:21:52:21 | x | 0 | +| test.cpp:53:5:53:5 | t | 0 | +| test.cpp:53:15:53:16 | xb | 0 | +| test.cpp:56:7:56:7 | x | -2147483648 | +| test.cpp:57:21:57:21 | x | 1 | +| test.cpp:58:5:58:5 | t | 0 | +| test.cpp:58:15:58:16 | xb | 1 | +| test.cpp:61:7:61:7 | x | -2147483648 | +| test.cpp:62:21:62:21 | x | -2147483648 | +| test.cpp:63:5:63:5 | t | 0 | +| test.cpp:63:15:63:16 | xb | 1 | +| test.cpp:66:19:66:19 | x | -2147483648 | +| test.cpp:67:3:67:3 | t | 0 | +| test.cpp:67:13:67:14 | xb | 0 | +| test.cpp:69:10:69:10 | b | 0 | +| test.cpp:69:21:69:21 | t | 0 | +| test.cpp:74:30:74:30 | c | 0 | +| test.cpp:74:34:74:34 | c | 0 | +| test.cpp:75:22:75:30 | c_times_2 | 0 | +| test.cpp:77:5:77:13 | c_times_2 | 0 | +| test.cpp:79:3:79:11 | c_times_2 | 0 | diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.ql b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.ql index 67da6367972..70c2d8590e9 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.ql +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.ql @@ -1,4 +1,4 @@ import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis from VariableAccess expr -select expr, lowerBound(expr) +select expr, lowerBound(expr).toString() diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected index a124f87f6f8..2b04c8933cc 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected @@ -1,524 +1,524 @@ -| inline_assembly.c:10:3:10:3 | y | 4.294967295E9 | -| inline_assembly.c:12:29:12:29 | x | 0.0 | -| inline_assembly.c:12:32:12:32 | y | 1.0 | -| inline_assembly.c:16:25:16:25 | x | 0.0 | -| inline_assembly.c:16:35:16:35 | y | 1.0 | -| inline_assembly.c:21:29:21:29 | x | 4.294967295E9 | -| inline_assembly.c:21:32:21:32 | y | 4.294967295E9 | -| minmax.c:18:37:18:37 | x | 1.0 | -| minmax.c:18:40:18:40 | y | 2.0 | -| minmax.c:18:43:18:43 | z | 3.0 | -| minmax.c:20:2:20:2 | z | 2.147483647E9 | -| minmax.c:22:8:22:8 | x | 1.0 | -| minmax.c:22:14:22:14 | y | 2.0 | -| minmax.c:22:18:22:18 | t | 2.147483647E9 | -| minmax.c:22:22:22:22 | x | 1.0 | -| minmax.c:23:3:23:3 | t | 1.0 | -| minmax.c:26:37:26:37 | x | 1.0 | -| minmax.c:26:40:26:40 | y | 2.0 | -| minmax.c:26:43:26:43 | z | 1.0 | -| test.c:8:5:8:9 | count | 2.147483647E9 | -| test.c:8:13:8:17 | count | 2.147483647E9 | -| test.c:10:10:10:14 | count | 2.147483647E9 | -| test.c:16:5:16:9 | count | 2.147483647E9 | -| test.c:16:14:16:18 | count | 15.0 | -| test.c:18:10:18:14 | count | 15.0 | -| test.c:24:5:24:9 | count | 15.0 | -| test.c:25:5:25:9 | count | 2.147483647E9 | -| test.c:25:13:25:17 | count | 127.0 | -| test.c:27:10:27:14 | count | 15.0 | -| test.c:33:8:33:8 | i | 2.147483647E9 | -| test.c:33:15:33:15 | i | 2.0 | -| test.c:33:22:33:22 | i | 2.147483647E9 | -| test.c:33:26:33:26 | i | 1.0 | -| test.c:34:5:34:9 | total | 2.147483647E9 | -| test.c:34:14:34:14 | i | 1.0 | -| test.c:36:10:36:14 | total | 2.147483647E9 | -| test.c:36:18:36:18 | i | 2.0 | -| test.c:42:8:42:8 | i | 2.147483647E9 | -| test.c:42:15:42:15 | i | 2.0 | -| test.c:42:22:42:22 | i | 1.0 | -| test.c:43:5:43:9 | total | 2.147483647E9 | -| test.c:43:14:43:14 | i | 1.0 | -| test.c:45:10:45:14 | total | 2.147483647E9 | -| test.c:45:18:45:18 | i | 2.0 | -| test.c:51:8:51:8 | i | 2.147483647E9 | -| test.c:51:15:51:15 | i | 2.0 | -| test.c:51:24:51:24 | i | 2.147483647E9 | -| test.c:51:28:51:28 | i | 1.0 | -| test.c:52:5:52:9 | total | 2.147483647E9 | -| test.c:52:14:52:14 | i | 1.0 | -| test.c:54:10:54:14 | total | 2.147483647E9 | -| test.c:54:18:54:18 | i | 2.0 | -| test.c:58:7:58:7 | i | 2.147483647E9 | -| test.c:59:9:59:9 | i | 3.0 | -| test.c:60:14:60:14 | i | 3.0 | -| test.c:67:15:67:15 | y | 2.147483647E9 | -| test.c:67:20:67:20 | y | 2.147483647E9 | -| test.c:68:9:68:9 | x | 2.147483647E9 | -| test.c:68:13:68:13 | y | 9.0 | -| test.c:69:14:69:14 | x | 6.0 | -| test.c:72:10:72:10 | y | 2.147483647E9 | -| test.c:76:7:76:7 | y | 2.147483647E9 | -| test.c:77:9:77:9 | x | 2.147483647E9 | -| test.c:81:9:81:9 | x | 2.147483647E9 | -| test.c:85:10:85:10 | x | 2.147483647E9 | -| test.c:89:7:89:7 | y | 2.147483647E9 | -| test.c:90:9:90:9 | x | 2.147483647E9 | -| test.c:90:13:90:13 | y | 2.147483647E9 | -| test.c:93:12:93:12 | x | 2.147483647E9 | -| test.c:100:3:100:3 | c | 127.0 | -| test.c:101:7:101:7 | c | 127.0 | -| test.c:104:7:104:7 | c | 127.0 | -| test.c:105:5:105:5 | c | 127.0 | -| test.c:106:9:106:9 | c | 127.0 | -| test.c:109:9:109:9 | c | 127.0 | -| test.c:119:10:119:10 | n | 1.8446744073709552E19 | -| test.c:124:11:124:15 | Start | 1.8446744073709552E19 | -| test.c:127:6:127:10 | Start | 1.8446744073709552E19 | -| test.c:127:15:127:20 | Length | 1.8446744073709552E19 | -| test.c:135:22:135:22 | c | 127.0 | -| test.c:137:20:137:20 | x | 0.0 | -| test.c:138:11:138:11 | i | 2.147483647E9 | -| test.c:139:19:139:19 | c | 127.0 | -| test.c:139:23:139:23 | i | 2.147483647E9 | -| test.c:139:27:139:28 | uc | 255.0 | -| test.c:139:32:139:32 | x | 0.0 | -| test.c:139:36:139:36 | y | 4.294967295E9 | -| test.c:139:40:139:40 | z | 2.147483647E9 | -| test.c:144:23:144:23 | x | 2.147483647E9 | -| test.c:145:32:145:32 | x | 2.147483647E9 | -| test.c:146:33:146:33 | x | 2.147483647E9 | -| test.c:147:31:147:31 | x | 2.147483647E9 | -| test.c:148:13:148:13 | x | 2.147483647E9 | -| test.c:149:23:149:23 | x | 2.147483647E9 | -| test.c:150:10:150:11 | x0 | 127.0 | -| test.c:150:15:150:16 | x1 | 255.0 | -| test.c:150:20:150:21 | x2 | 65535.0 | -| test.c:150:25:150:26 | x3 | 2.147483647E9 | -| test.c:150:30:150:31 | c0 | 127.0 | -| test.c:150:35:150:36 | s0 | 65535.0 | -| test.c:154:11:154:11 | x | 9.223372036854776E18 | -| test.c:154:20:154:20 | x | 9.223372036854776E18 | -| test.c:154:30:154:30 | x | 9.223372036854776E18 | -| test.c:154:35:154:35 | x | 2.147483647E9 | -| test.c:161:12:161:12 | a | 2.147483647E9 | -| test.c:161:17:161:17 | a | 2.147483647E9 | -| test.c:162:14:162:14 | a | 11.0 | -| test.c:163:14:163:14 | a | 11.0 | -| test.c:164:5:164:9 | total | 0.0 | -| test.c:164:14:164:14 | b | 11.0 | -| test.c:164:16:164:16 | c | -3.0 | -| test.c:166:12:166:12 | a | 2.147483647E9 | -| test.c:166:17:166:17 | a | 2.147483647E9 | -| test.c:167:14:167:14 | a | 11.0 | -| test.c:168:14:168:14 | a | 11.0 | -| test.c:169:5:169:9 | total | 8.0 | -| test.c:169:14:169:14 | b | 11.0 | -| test.c:169:16:169:16 | c | -0.0 | -| test.c:171:13:171:13 | a | 2.147483647E9 | -| test.c:171:18:171:18 | a | 2.147483647E9 | -| test.c:172:14:172:14 | a | 11.0 | -| test.c:173:14:173:14 | a | 11.0 | -| test.c:174:5:174:9 | total | 19.0 | -| test.c:174:14:174:14 | b | 11.0 | -| test.c:174:16:174:16 | c | 7.0 | -| test.c:176:13:176:13 | a | 2.147483647E9 | -| test.c:176:18:176:18 | a | 2.147483647E9 | -| test.c:177:14:177:14 | a | 1.0 | -| test.c:178:14:178:14 | a | 1.0 | -| test.c:179:5:179:9 | total | 37.0 | -| test.c:179:14:179:14 | b | 1.0 | -| test.c:179:16:179:16 | c | 7.0 | -| test.c:181:13:181:13 | a | 2.147483647E9 | -| test.c:181:18:181:18 | a | 2.147483647E9 | -| test.c:182:14:182:14 | a | 0.0 | -| test.c:183:14:183:14 | a | 0.0 | -| test.c:184:5:184:9 | total | 45.0 | -| test.c:184:14:184:14 | b | 0.0 | -| test.c:184:16:184:16 | c | 7.0 | -| test.c:186:13:186:13 | a | 2.147483647E9 | -| test.c:186:18:186:18 | a | 2.147483647E9 | -| test.c:187:14:187:14 | a | -2.0 | -| test.c:188:14:188:14 | a | -2.0 | -| test.c:189:5:189:9 | total | 52.0 | -| test.c:189:14:189:14 | b | -2.0 | -| test.c:189:16:189:16 | c | 7.0 | -| test.c:192:10:192:14 | total | 57.0 | -| test.c:200:12:200:12 | a | 2.147483647E9 | -| test.c:200:17:200:17 | a | 2.147483647E9 | -| test.c:200:33:200:33 | b | 2.147483647E9 | -| test.c:200:38:200:38 | b | 2.147483647E9 | -| test.c:201:13:201:13 | a | 11.0 | -| test.c:201:15:201:15 | b | 23.0 | -| test.c:202:5:202:9 | total | 0.0 | -| test.c:202:14:202:14 | r | 2.147483647E9 | -| test.c:204:12:204:12 | a | 2.147483647E9 | -| test.c:204:17:204:17 | a | 2.147483647E9 | -| test.c:204:33:204:33 | b | 2.147483647E9 | -| test.c:204:38:204:38 | b | 2.147483647E9 | -| test.c:205:13:205:13 | a | 11.0 | -| test.c:205:15:205:15 | b | 23.0 | -| test.c:206:5:206:9 | total | 2.147483647E9 | -| test.c:206:14:206:14 | r | 2.147483647E9 | -| test.c:208:12:208:12 | a | 2.147483647E9 | -| test.c:208:17:208:17 | a | 2.147483647E9 | -| test.c:208:35:208:35 | b | 2.147483647E9 | -| test.c:208:40:208:40 | b | 2.147483647E9 | -| test.c:209:13:209:13 | a | 11.0 | -| test.c:209:15:209:15 | b | 23.0 | -| test.c:210:5:210:9 | total | 2.147483647E9 | -| test.c:210:14:210:14 | r | 2.147483647E9 | -| test.c:212:12:212:12 | a | 2.147483647E9 | -| test.c:212:17:212:17 | a | 2.147483647E9 | -| test.c:212:35:212:35 | b | 2.147483647E9 | -| test.c:212:40:212:40 | b | 2.147483647E9 | -| test.c:213:13:213:13 | a | 11.0 | -| test.c:213:15:213:15 | b | 0.0 | -| test.c:214:5:214:9 | total | 2.147483647E9 | -| test.c:214:14:214:14 | r | 2.147483647E9 | -| test.c:216:12:216:12 | a | 2.147483647E9 | -| test.c:216:17:216:17 | a | 2.147483647E9 | -| test.c:216:35:216:35 | b | 2.147483647E9 | -| test.c:216:40:216:40 | b | 2.147483647E9 | -| test.c:217:13:217:13 | a | 11.0 | -| test.c:217:15:217:15 | b | -7.0 | -| test.c:218:5:218:9 | total | 2.147483647E9 | -| test.c:218:14:218:14 | r | 2.147483647E9 | -| test.c:221:10:221:14 | total | 2.147483647E9 | -| test.c:228:12:228:12 | a | 2.147483647E9 | -| test.c:228:17:228:17 | a | 2.147483647E9 | -| test.c:228:33:228:33 | b | 2.147483647E9 | -| test.c:228:38:228:38 | b | 2.147483647E9 | -| test.c:229:13:229:13 | a | 11.0 | -| test.c:229:15:229:15 | b | 23.0 | -| test.c:230:5:230:9 | total | 0.0 | -| test.c:230:14:230:14 | r | 2.147483647E9 | -| test.c:232:12:232:12 | a | 2.147483647E9 | -| test.c:232:17:232:17 | a | 2.147483647E9 | -| test.c:232:33:232:33 | b | 2.147483647E9 | -| test.c:232:38:232:38 | b | 2.147483647E9 | -| test.c:233:13:233:13 | a | 11.0 | -| test.c:233:15:233:15 | b | 23.0 | -| test.c:234:5:234:9 | total | 2.147483647E9 | -| test.c:234:14:234:14 | r | 2.147483647E9 | -| test.c:236:12:236:12 | a | 2.147483647E9 | -| test.c:236:17:236:17 | a | 2.147483647E9 | -| test.c:236:35:236:35 | b | 2.147483647E9 | -| test.c:236:40:236:40 | b | 2.147483647E9 | -| test.c:237:13:237:13 | a | 11.0 | -| test.c:237:15:237:15 | b | 23.0 | -| test.c:238:5:238:9 | total | 2.147483647E9 | -| test.c:238:14:238:14 | r | 2.147483647E9 | -| test.c:240:12:240:12 | a | 2.147483647E9 | -| test.c:240:17:240:17 | a | 2.147483647E9 | -| test.c:240:35:240:35 | b | 2.147483647E9 | -| test.c:240:40:240:40 | b | 2.147483647E9 | -| test.c:241:13:241:13 | a | 11.0 | -| test.c:241:15:241:15 | b | 0.0 | -| test.c:242:5:242:9 | total | 2.147483647E9 | -| test.c:242:14:242:14 | r | 2.147483647E9 | -| test.c:244:12:244:12 | a | 2.147483647E9 | -| test.c:244:17:244:17 | a | 2.147483647E9 | -| test.c:244:35:244:35 | b | 2.147483647E9 | -| test.c:244:40:244:40 | b | 2.147483647E9 | -| test.c:245:13:245:13 | a | 11.0 | -| test.c:245:15:245:15 | b | -7.0 | -| test.c:246:5:246:9 | total | 2.147483647E9 | -| test.c:246:14:246:14 | r | 2.147483647E9 | -| test.c:249:10:249:14 | total | 2.147483647E9 | -| test.c:256:14:256:14 | a | 2.147483647E9 | -| test.c:256:19:256:19 | a | 2.147483647E9 | -| test.c:256:35:256:35 | b | 2.147483647E9 | -| test.c:256:40:256:40 | b | 2.147483647E9 | -| test.c:257:13:257:13 | a | 11.0 | -| test.c:257:15:257:15 | b | 23.0 | -| test.c:258:5:258:9 | total | 0.0 | -| test.c:258:14:258:14 | r | 2.147483647E9 | -| test.c:260:14:260:14 | a | 2.147483647E9 | -| test.c:260:19:260:19 | a | 2.147483647E9 | -| test.c:260:35:260:35 | b | 2.147483647E9 | -| test.c:260:40:260:40 | b | 2.147483647E9 | -| test.c:261:13:261:13 | a | 11.0 | -| test.c:261:15:261:15 | b | 23.0 | -| test.c:262:5:262:9 | total | 2.147483647E9 | -| test.c:262:14:262:14 | r | 2.147483647E9 | -| test.c:264:14:264:14 | a | 2.147483647E9 | -| test.c:264:19:264:19 | a | 2.147483647E9 | -| test.c:264:37:264:37 | b | 2.147483647E9 | -| test.c:264:42:264:42 | b | 2.147483647E9 | -| test.c:265:13:265:13 | a | 11.0 | -| test.c:265:15:265:15 | b | 23.0 | -| test.c:266:5:266:9 | total | 2.147483647E9 | -| test.c:266:14:266:14 | r | 2.147483647E9 | -| test.c:268:14:268:14 | a | 2.147483647E9 | -| test.c:268:19:268:19 | a | 2.147483647E9 | -| test.c:268:37:268:37 | b | 2.147483647E9 | -| test.c:268:42:268:42 | b | 2.147483647E9 | -| test.c:269:13:269:13 | a | 11.0 | -| test.c:269:15:269:15 | b | 0.0 | -| test.c:270:5:270:9 | total | 2.147483647E9 | -| test.c:270:14:270:14 | r | 2.147483647E9 | -| test.c:272:14:272:14 | a | 2.147483647E9 | -| test.c:272:19:272:19 | a | 2.147483647E9 | -| test.c:272:37:272:37 | b | 2.147483647E9 | -| test.c:272:42:272:42 | b | 2.147483647E9 | -| test.c:273:13:273:13 | a | 11.0 | -| test.c:273:15:273:15 | b | -7.0 | -| test.c:274:5:274:9 | total | 2.147483647E9 | -| test.c:274:14:274:14 | r | 2.147483647E9 | -| test.c:277:10:277:14 | total | 2.147483647E9 | -| test.c:284:14:284:14 | a | 2.147483647E9 | -| test.c:284:19:284:19 | a | 2.147483647E9 | -| test.c:284:34:284:34 | b | 2.147483647E9 | -| test.c:284:39:284:39 | b | 2.147483647E9 | -| test.c:285:13:285:13 | a | 0.0 | -| test.c:285:15:285:15 | b | 23.0 | -| test.c:286:5:286:9 | total | 0.0 | -| test.c:286:14:286:14 | r | 2.147483647E9 | -| test.c:288:14:288:14 | a | 2.147483647E9 | -| test.c:288:19:288:19 | a | 2.147483647E9 | -| test.c:288:34:288:34 | b | 2.147483647E9 | -| test.c:288:39:288:39 | b | 2.147483647E9 | -| test.c:289:13:289:13 | a | 0.0 | -| test.c:289:15:289:15 | b | 23.0 | -| test.c:290:5:290:9 | total | 2.147483647E9 | -| test.c:290:14:290:14 | r | 2.147483647E9 | -| test.c:292:14:292:14 | a | 2.147483647E9 | -| test.c:292:19:292:19 | a | 2.147483647E9 | -| test.c:292:36:292:36 | b | 2.147483647E9 | -| test.c:292:41:292:41 | b | 2.147483647E9 | -| test.c:293:13:293:13 | a | 0.0 | -| test.c:293:15:293:15 | b | 23.0 | -| test.c:294:5:294:9 | total | 2.147483647E9 | -| test.c:294:14:294:14 | r | 2.147483647E9 | -| test.c:296:14:296:14 | a | 2.147483647E9 | -| test.c:296:19:296:19 | a | 2.147483647E9 | -| test.c:296:36:296:36 | b | 2.147483647E9 | -| test.c:296:41:296:41 | b | 2.147483647E9 | -| test.c:297:13:297:13 | a | 0.0 | -| test.c:297:15:297:15 | b | 0.0 | -| test.c:298:5:298:9 | total | 2.147483647E9 | -| test.c:298:14:298:14 | r | 2.147483647E9 | -| test.c:300:14:300:14 | a | 2.147483647E9 | -| test.c:300:19:300:19 | a | 2.147483647E9 | -| test.c:300:36:300:36 | b | 2.147483647E9 | -| test.c:300:41:300:41 | b | 2.147483647E9 | -| test.c:301:13:301:13 | a | 0.0 | -| test.c:301:15:301:15 | b | -7.0 | -| test.c:302:5:302:9 | total | 2.147483647E9 | -| test.c:302:14:302:14 | r | 2.147483647E9 | -| test.c:305:10:305:14 | total | 2.147483647E9 | -| test.c:312:14:312:14 | a | 2.147483647E9 | -| test.c:312:19:312:19 | a | 2.147483647E9 | -| test.c:312:35:312:35 | b | 2.147483647E9 | -| test.c:312:40:312:40 | b | 2.147483647E9 | -| test.c:313:13:313:13 | a | -2.0 | -| test.c:313:15:313:15 | b | 23.0 | -| test.c:314:5:314:9 | total | 0.0 | -| test.c:314:14:314:14 | r | 2.147483647E9 | -| test.c:316:14:316:14 | a | 2.147483647E9 | -| test.c:316:19:316:19 | a | 2.147483647E9 | -| test.c:316:35:316:35 | b | 2.147483647E9 | -| test.c:316:40:316:40 | b | 2.147483647E9 | -| test.c:317:13:317:13 | a | -2.0 | -| test.c:317:15:317:15 | b | 23.0 | -| test.c:318:5:318:9 | total | 2.147483647E9 | -| test.c:318:14:318:14 | r | 2.147483647E9 | -| test.c:320:14:320:14 | a | 2.147483647E9 | -| test.c:320:19:320:19 | a | 2.147483647E9 | -| test.c:320:37:320:37 | b | 2.147483647E9 | -| test.c:320:42:320:42 | b | 2.147483647E9 | -| test.c:321:13:321:13 | a | -2.0 | -| test.c:321:15:321:15 | b | 23.0 | -| test.c:322:5:322:9 | total | 2.147483647E9 | -| test.c:322:14:322:14 | r | 2.147483647E9 | -| test.c:324:14:324:14 | a | 2.147483647E9 | -| test.c:324:19:324:19 | a | 2.147483647E9 | -| test.c:324:37:324:37 | b | 2.147483647E9 | -| test.c:324:42:324:42 | b | 2.147483647E9 | -| test.c:325:13:325:13 | a | -2.0 | -| test.c:325:15:325:15 | b | 0.0 | -| test.c:326:5:326:9 | total | 2.147483647E9 | -| test.c:326:14:326:14 | r | 2.147483647E9 | -| test.c:328:14:328:14 | a | 2.147483647E9 | -| test.c:328:19:328:19 | a | 2.147483647E9 | -| test.c:328:37:328:37 | b | 2.147483647E9 | -| test.c:328:42:328:42 | b | 2.147483647E9 | -| test.c:329:13:329:13 | a | -2.0 | -| test.c:329:15:329:15 | b | -7.0 | -| test.c:330:5:330:9 | total | 2.147483647E9 | -| test.c:330:14:330:14 | r | 2.147483647E9 | -| test.c:333:10:333:14 | total | 2.147483647E9 | -| test.c:338:7:338:7 | x | 2.147483647E9 | -| test.c:342:10:342:10 | i | 7.0 | -| test.c:343:5:343:5 | i | 2.0 | -| test.c:345:3:345:3 | d | 2.147483647E9 | -| test.c:345:7:345:7 | i | 7.0 | -| test.c:346:7:346:7 | x | 2.147483647E9 | -| test.c:347:9:347:9 | d | 7.0 | -| test.c:347:14:347:14 | x | -1.0 | -| test.c:357:3:357:4 | y1 | 4.294967295E9 | -| test.c:357:8:357:8 | x | 4.294967295E9 | -| test.c:357:18:357:18 | x | 99.0 | -| test.c:358:3:358:4 | y2 | 4.294967295E9 | -| test.c:358:8:358:8 | x | 4.294967295E9 | -| test.c:358:24:358:24 | x | 99.0 | -| test.c:359:3:359:4 | y3 | 4.294967295E9 | -| test.c:360:3:360:4 | y4 | 4.294967295E9 | -| test.c:361:3:361:4 | y5 | 4.294967295E9 | -| test.c:362:3:362:4 | y6 | 4.294967295E9 | -| test.c:363:3:363:4 | y7 | 4.294967295E9 | -| test.c:364:3:364:4 | y8 | 4.294967295E9 | -| test.c:365:7:365:7 | x | 4.294967295E9 | -| test.c:366:5:366:6 | y3 | 4.294967295E9 | -| test.c:366:10:366:10 | x | 299.0 | -| test.c:367:5:367:6 | y4 | 4.294967295E9 | -| test.c:367:10:367:10 | x | 299.0 | -| test.c:368:5:368:6 | y5 | 4.294967295E9 | -| test.c:368:11:368:11 | x | 299.0 | -| test.c:369:5:369:6 | y6 | 4.294967295E9 | -| test.c:369:27:369:27 | x | 299.0 | -| test.c:370:5:370:6 | y7 | 4.294967295E9 | -| test.c:370:27:370:27 | x | 299.0 | -| test.c:371:5:371:6 | y8 | 4.294967295E9 | -| test.c:371:28:371:28 | x | 299.0 | -| test.c:373:10:373:11 | y1 | 99.0 | -| test.c:373:15:373:16 | y2 | 99.0 | -| test.c:373:20:373:21 | y3 | 299.0 | -| test.c:373:25:373:26 | y4 | 500.0 | -| test.c:373:30:373:31 | y5 | 300.0 | -| test.c:373:35:373:36 | y6 | 255.0 | -| test.c:373:40:373:41 | y7 | 500.0 | -| test.c:373:45:373:46 | y8 | 300.0 | -| test.c:379:3:379:4 | y1 | 4.294967295E9 | -| test.c:379:8:379:8 | x | 4.294967295E9 | -| test.c:379:18:379:18 | x | 4.294967295E9 | -| test.c:380:3:380:4 | y2 | 4.294967295E9 | -| test.c:380:8:380:8 | x | 4.294967295E9 | -| test.c:380:25:380:25 | x | 4.294967295E9 | -| test.c:381:3:381:4 | y3 | 4.294967295E9 | -| test.c:382:3:382:4 | y4 | 4.294967295E9 | -| test.c:383:3:383:4 | y5 | 4.294967295E9 | -| test.c:384:7:384:7 | x | 4.294967295E9 | -| test.c:385:5:385:6 | y3 | 4.294967295E9 | -| test.c:385:11:385:11 | x | 4.294967295E9 | -| test.c:386:5:386:6 | y4 | 4.294967295E9 | -| test.c:386:11:386:11 | x | 4.294967295E9 | -| test.c:387:5:387:6 | y5 | 4.294967295E9 | -| test.c:387:27:387:27 | x | 4.294967295E9 | -| test.c:389:10:389:11 | y1 | 4.294967295E9 | -| test.c:389:15:389:16 | y2 | 4.294967295E9 | -| test.c:389:20:389:21 | y3 | 4.294967295E9 | -| test.c:389:25:389:26 | y4 | 4.294967295E9 | -| test.c:389:30:389:31 | y5 | 1000.0 | -| test.c:394:20:394:20 | x | 4.294967295E9 | -| test.c:394:30:394:30 | x | 99.0 | -| test.c:397:3:397:4 | y1 | 4.294967295E9 | -| test.c:397:11:397:11 | y | 100.0 | -| test.c:397:14:397:14 | y | 101.0 | -| test.c:398:3:398:4 | y2 | 4.294967295E9 | -| test.c:398:9:398:9 | y | 101.0 | -| test.c:398:14:398:14 | y | 102.0 | -| test.c:398:22:398:22 | y | 105.0 | -| test.c:399:10:399:11 | y1 | 101.0 | -| test.c:399:15:399:16 | y2 | 105.0 | -| test.c:407:3:407:3 | i | 2.147483647E9 | -| test.c:408:7:408:7 | i | 10.0 | -| test.c:410:3:410:3 | i | 2.147483647E9 | -| test.c:411:3:411:3 | i | 10.0 | -| test.c:412:7:412:7 | i | 2.147483647E9 | -| test.c:414:3:414:3 | i | 2.147483647E9 | -| test.c:415:3:415:3 | i | 40.0 | -| test.c:416:7:416:7 | i | 2.147483647E9 | -| test.c:418:3:418:3 | i | 2.147483647E9 | -| test.c:418:7:418:7 | j | 2.147483647E9 | -| test.c:419:7:419:7 | i | 40.0 | -| test.c:421:3:421:3 | i | 2.147483647E9 | -| test.c:421:8:421:8 | j | 40.0 | -| test.c:422:7:422:7 | i | 50.0 | -| test.c:424:3:424:3 | i | 2.147483647E9 | -| test.c:424:13:424:13 | j | 2.147483647E9 | -| test.c:425:7:425:7 | i | 2.147483647E9 | -| test.c:432:12:432:12 | a | 4.294967295E9 | -| test.c:432:17:432:17 | a | 4.294967295E9 | -| test.c:432:33:432:33 | b | 4.294967295E9 | -| test.c:432:38:432:38 | b | 4.294967295E9 | -| test.c:433:13:433:13 | a | 11.0 | -| test.c:433:15:433:15 | b | 23.0 | -| test.c:434:5:434:9 | total | 0.0 | -| test.c:434:14:434:14 | r | 2.147483647E9 | -| test.c:436:12:436:12 | a | 4.294967295E9 | -| test.c:436:17:436:17 | a | 4.294967295E9 | -| test.c:436:33:436:33 | b | 4.294967295E9 | -| test.c:436:38:436:38 | b | 4.294967295E9 | -| test.c:437:13:437:13 | a | 11.0 | -| test.c:437:15:437:15 | b | 23.0 | -| test.c:438:5:438:9 | total | 2.147483647E9 | -| test.c:438:14:438:14 | r | 2.147483647E9 | -| test.c:440:12:440:12 | a | 4.294967295E9 | -| test.c:440:17:440:17 | a | 4.294967295E9 | -| test.c:440:34:440:34 | b | 4.294967295E9 | -| test.c:440:39:440:39 | b | 4.294967295E9 | -| test.c:441:13:441:13 | a | 11.0 | -| test.c:441:15:441:15 | b | 23.0 | -| test.c:442:5:442:9 | total | 2.147483647E9 | -| test.c:442:14:442:14 | r | 2.147483647E9 | -| test.c:445:10:445:14 | total | 2.147483647E9 | -| test.c:451:12:451:12 | b | 4.294967295E9 | -| test.c:451:17:451:17 | b | 4.294967295E9 | -| test.c:452:16:452:16 | b | 23.0 | -| test.c:453:5:453:9 | total | 0.0 | -| test.c:453:14:453:14 | r | 2.147483647E9 | -| test.c:455:12:455:12 | b | 4.294967295E9 | -| test.c:455:17:455:17 | b | 4.294967295E9 | -| test.c:456:16:456:16 | b | 23.0 | -| test.c:457:5:457:9 | total | 2.147483647E9 | -| test.c:457:14:457:14 | r | 2.147483647E9 | -| test.c:459:13:459:13 | b | 4.294967295E9 | -| test.c:459:18:459:18 | b | 4.294967295E9 | -| test.c:460:16:460:16 | b | 23.0 | -| test.c:461:5:461:9 | total | 2.147483647E9 | -| test.c:461:14:461:14 | r | 2.147483647E9 | -| test.c:464:10:464:14 | total | 2.147483647E9 | -| test.cpp:10:7:10:7 | b | 2.147483647E9 | -| test.cpp:11:5:11:5 | x | 2.147483647E9 | -| test.cpp:13:10:13:10 | x | 2.147483647E9 | -| test.cpp:18:30:18:30 | x | 2.147483647E9 | -| test.cpp:19:10:19:11 | x0 | 127.0 | -| test.cpp:27:7:27:7 | y | 2.147483647E9 | -| test.cpp:28:5:28:5 | x | 2.147483647E9 | -| test.cpp:30:7:30:7 | y | 2.147483647E9 | -| test.cpp:31:5:31:5 | x | 2.147483647E9 | -| test.cpp:33:7:33:7 | y | 2.147483647E9 | -| test.cpp:34:5:34:5 | x | 2.147483647E9 | -| test.cpp:36:7:36:7 | y | 2.147483647E9 | -| test.cpp:37:5:37:5 | x | 2.147483647E9 | -| test.cpp:39:7:39:7 | y | 2.147483647E9 | -| test.cpp:40:5:40:5 | x | 2.147483647E9 | -| test.cpp:42:7:42:7 | y | 2.147483647E9 | -| test.cpp:43:5:43:5 | x | 2.147483647E9 | -| test.cpp:45:7:45:7 | y | 2.147483647E9 | -| test.cpp:46:5:46:5 | x | 2.147483647E9 | -| test.cpp:51:7:51:7 | x | 2.147483647E9 | -| test.cpp:52:21:52:21 | x | 0.0 | -| test.cpp:53:5:53:5 | t | 0.0 | -| test.cpp:53:15:53:16 | xb | 0.0 | -| test.cpp:56:7:56:7 | x | 2.147483647E9 | -| test.cpp:57:21:57:21 | x | 2.147483647E9 | -| test.cpp:58:5:58:5 | t | 0.0 | -| test.cpp:58:15:58:16 | xb | 1.0 | -| test.cpp:61:7:61:7 | x | 2.147483647E9 | -| test.cpp:62:21:62:21 | x | -1.0 | -| test.cpp:63:5:63:5 | t | 1.0 | -| test.cpp:63:15:63:16 | xb | 1.0 | -| test.cpp:66:19:66:19 | x | 2.147483647E9 | -| test.cpp:67:3:67:3 | t | 2.0 | -| test.cpp:67:13:67:14 | xb | 1.0 | -| test.cpp:69:10:69:10 | b | 1.0 | -| test.cpp:69:21:69:21 | t | 3.0 | -| test.cpp:74:30:74:30 | c | 255.0 | -| test.cpp:74:34:74:34 | c | 255.0 | -| test.cpp:75:22:75:30 | c_times_2 | 510.0 | -| test.cpp:77:5:77:13 | c_times_2 | 510.0 | -| test.cpp:79:3:79:11 | c_times_2 | 510.0 | +| inline_assembly.c:10:3:10:3 | y | 4294967295 | +| inline_assembly.c:12:29:12:29 | x | 0 | +| inline_assembly.c:12:32:12:32 | y | 1 | +| inline_assembly.c:16:25:16:25 | x | 0 | +| inline_assembly.c:16:35:16:35 | y | 1 | +| inline_assembly.c:21:29:21:29 | x | 4294967295 | +| inline_assembly.c:21:32:21:32 | y | 4294967295 | +| minmax.c:18:37:18:37 | x | 1 | +| minmax.c:18:40:18:40 | y | 2 | +| minmax.c:18:43:18:43 | z | 3 | +| minmax.c:20:2:20:2 | z | 2147483647 | +| minmax.c:22:8:22:8 | x | 1 | +| minmax.c:22:14:22:14 | y | 2 | +| minmax.c:22:18:22:18 | t | 2147483647 | +| minmax.c:22:22:22:22 | x | 1 | +| minmax.c:23:3:23:3 | t | 1 | +| minmax.c:26:37:26:37 | x | 1 | +| minmax.c:26:40:26:40 | y | 2 | +| minmax.c:26:43:26:43 | z | 1 | +| test.c:8:5:8:9 | count | 2147483647 | +| test.c:8:13:8:17 | count | 2147483647 | +| test.c:10:10:10:14 | count | 2147483647 | +| test.c:16:5:16:9 | count | 2147483647 | +| test.c:16:14:16:18 | count | 15 | +| test.c:18:10:18:14 | count | 15 | +| test.c:24:5:24:9 | count | 15 | +| test.c:25:5:25:9 | count | 2147483647 | +| test.c:25:13:25:17 | count | 127 | +| test.c:27:10:27:14 | count | 15 | +| test.c:33:8:33:8 | i | 2147483647 | +| test.c:33:15:33:15 | i | 2 | +| test.c:33:22:33:22 | i | 2147483647 | +| test.c:33:26:33:26 | i | 1 | +| test.c:34:5:34:9 | total | 2147483647 | +| test.c:34:14:34:14 | i | 1 | +| test.c:36:10:36:14 | total | 2147483647 | +| test.c:36:18:36:18 | i | 2 | +| test.c:42:8:42:8 | i | 2147483647 | +| test.c:42:15:42:15 | i | 2 | +| test.c:42:22:42:22 | i | 1 | +| test.c:43:5:43:9 | total | 2147483647 | +| test.c:43:14:43:14 | i | 1 | +| test.c:45:10:45:14 | total | 2147483647 | +| test.c:45:18:45:18 | i | 2 | +| test.c:51:8:51:8 | i | 2147483647 | +| test.c:51:15:51:15 | i | 2 | +| test.c:51:24:51:24 | i | 2147483647 | +| test.c:51:28:51:28 | i | 1 | +| test.c:52:5:52:9 | total | 2147483647 | +| test.c:52:14:52:14 | i | 1 | +| test.c:54:10:54:14 | total | 2147483647 | +| test.c:54:18:54:18 | i | 2 | +| test.c:58:7:58:7 | i | 2147483647 | +| test.c:59:9:59:9 | i | 3 | +| test.c:60:14:60:14 | i | 3 | +| test.c:67:15:67:15 | y | 2147483647 | +| test.c:67:20:67:20 | y | 2147483647 | +| test.c:68:9:68:9 | x | 2147483647 | +| test.c:68:13:68:13 | y | 9 | +| test.c:69:14:69:14 | x | 6 | +| test.c:72:10:72:10 | y | 2147483647 | +| test.c:76:7:76:7 | y | 2147483647 | +| test.c:77:9:77:9 | x | 2147483647 | +| test.c:81:9:81:9 | x | 2147483647 | +| test.c:85:10:85:10 | x | 2147483647 | +| test.c:89:7:89:7 | y | 2147483647 | +| test.c:90:9:90:9 | x | 2147483647 | +| test.c:90:13:90:13 | y | 2147483647 | +| test.c:93:12:93:12 | x | 2147483647 | +| test.c:100:3:100:3 | c | 127 | +| test.c:101:7:101:7 | c | 127 | +| test.c:104:7:104:7 | c | 127 | +| test.c:105:5:105:5 | c | 127 | +| test.c:106:9:106:9 | c | 127 | +| test.c:109:9:109:9 | c | 127 | +| test.c:119:10:119:10 | n | 18446744073709552000 | +| test.c:124:11:124:15 | Start | 18446744073709552000 | +| test.c:127:6:127:10 | Start | 18446744073709552000 | +| test.c:127:15:127:20 | Length | 18446744073709552000 | +| test.c:135:22:135:22 | c | 127 | +| test.c:137:20:137:20 | x | 0 | +| test.c:138:11:138:11 | i | 2147483647 | +| test.c:139:19:139:19 | c | 127 | +| test.c:139:23:139:23 | i | 2147483647 | +| test.c:139:27:139:28 | uc | 255 | +| test.c:139:32:139:32 | x | 0 | +| test.c:139:36:139:36 | y | 4294967295 | +| test.c:139:40:139:40 | z | 2147483647 | +| test.c:144:23:144:23 | x | 2147483647 | +| test.c:145:32:145:32 | x | 2147483647 | +| test.c:146:33:146:33 | x | 2147483647 | +| test.c:147:31:147:31 | x | 2147483647 | +| test.c:148:13:148:13 | x | 2147483647 | +| test.c:149:23:149:23 | x | 2147483647 | +| test.c:150:10:150:11 | x0 | 127 | +| test.c:150:15:150:16 | x1 | 255 | +| test.c:150:20:150:21 | x2 | 65535 | +| test.c:150:25:150:26 | x3 | 2147483647 | +| test.c:150:30:150:31 | c0 | 127 | +| test.c:150:35:150:36 | s0 | 65535 | +| test.c:154:11:154:11 | x | 9223372036854776000 | +| test.c:154:20:154:20 | x | 9223372036854776000 | +| test.c:154:30:154:30 | x | 9223372036854776000 | +| test.c:154:35:154:35 | x | 2147483647 | +| test.c:161:12:161:12 | a | 2147483647 | +| test.c:161:17:161:17 | a | 2147483647 | +| test.c:162:14:162:14 | a | 11 | +| test.c:163:14:163:14 | a | 11 | +| test.c:164:5:164:9 | total | 0 | +| test.c:164:14:164:14 | b | 11 | +| test.c:164:16:164:16 | c | -3 | +| test.c:166:12:166:12 | a | 2147483647 | +| test.c:166:17:166:17 | a | 2147483647 | +| test.c:167:14:167:14 | a | 11 | +| test.c:168:14:168:14 | a | 11 | +| test.c:169:5:169:9 | total | 8 | +| test.c:169:14:169:14 | b | 11 | +| test.c:169:16:169:16 | c | -0 | +| test.c:171:13:171:13 | a | 2147483647 | +| test.c:171:18:171:18 | a | 2147483647 | +| test.c:172:14:172:14 | a | 11 | +| test.c:173:14:173:14 | a | 11 | +| test.c:174:5:174:9 | total | 19 | +| test.c:174:14:174:14 | b | 11 | +| test.c:174:16:174:16 | c | 7 | +| test.c:176:13:176:13 | a | 2147483647 | +| test.c:176:18:176:18 | a | 2147483647 | +| test.c:177:14:177:14 | a | 1 | +| test.c:178:14:178:14 | a | 1 | +| test.c:179:5:179:9 | total | 37 | +| test.c:179:14:179:14 | b | 1 | +| test.c:179:16:179:16 | c | 7 | +| test.c:181:13:181:13 | a | 2147483647 | +| test.c:181:18:181:18 | a | 2147483647 | +| test.c:182:14:182:14 | a | 0 | +| test.c:183:14:183:14 | a | 0 | +| test.c:184:5:184:9 | total | 45 | +| test.c:184:14:184:14 | b | 0 | +| test.c:184:16:184:16 | c | 7 | +| test.c:186:13:186:13 | a | 2147483647 | +| test.c:186:18:186:18 | a | 2147483647 | +| test.c:187:14:187:14 | a | -2 | +| test.c:188:14:188:14 | a | -2 | +| test.c:189:5:189:9 | total | 52 | +| test.c:189:14:189:14 | b | -2 | +| test.c:189:16:189:16 | c | 7 | +| test.c:192:10:192:14 | total | 57 | +| test.c:200:12:200:12 | a | 2147483647 | +| test.c:200:17:200:17 | a | 2147483647 | +| test.c:200:33:200:33 | b | 2147483647 | +| test.c:200:38:200:38 | b | 2147483647 | +| test.c:201:13:201:13 | a | 11 | +| test.c:201:15:201:15 | b | 23 | +| test.c:202:5:202:9 | total | 0 | +| test.c:202:14:202:14 | r | 2147483647 | +| test.c:204:12:204:12 | a | 2147483647 | +| test.c:204:17:204:17 | a | 2147483647 | +| test.c:204:33:204:33 | b | 2147483647 | +| test.c:204:38:204:38 | b | 2147483647 | +| test.c:205:13:205:13 | a | 11 | +| test.c:205:15:205:15 | b | 23 | +| test.c:206:5:206:9 | total | 2147483647 | +| test.c:206:14:206:14 | r | 2147483647 | +| test.c:208:12:208:12 | a | 2147483647 | +| test.c:208:17:208:17 | a | 2147483647 | +| test.c:208:35:208:35 | b | 2147483647 | +| test.c:208:40:208:40 | b | 2147483647 | +| test.c:209:13:209:13 | a | 11 | +| test.c:209:15:209:15 | b | 23 | +| test.c:210:5:210:9 | total | 2147483647 | +| test.c:210:14:210:14 | r | 2147483647 | +| test.c:212:12:212:12 | a | 2147483647 | +| test.c:212:17:212:17 | a | 2147483647 | +| test.c:212:35:212:35 | b | 2147483647 | +| test.c:212:40:212:40 | b | 2147483647 | +| test.c:213:13:213:13 | a | 11 | +| test.c:213:15:213:15 | b | 0 | +| test.c:214:5:214:9 | total | 2147483647 | +| test.c:214:14:214:14 | r | 2147483647 | +| test.c:216:12:216:12 | a | 2147483647 | +| test.c:216:17:216:17 | a | 2147483647 | +| test.c:216:35:216:35 | b | 2147483647 | +| test.c:216:40:216:40 | b | 2147483647 | +| test.c:217:13:217:13 | a | 11 | +| test.c:217:15:217:15 | b | -7 | +| test.c:218:5:218:9 | total | 2147483647 | +| test.c:218:14:218:14 | r | 2147483647 | +| test.c:221:10:221:14 | total | 2147483647 | +| test.c:228:12:228:12 | a | 2147483647 | +| test.c:228:17:228:17 | a | 2147483647 | +| test.c:228:33:228:33 | b | 2147483647 | +| test.c:228:38:228:38 | b | 2147483647 | +| test.c:229:13:229:13 | a | 11 | +| test.c:229:15:229:15 | b | 23 | +| test.c:230:5:230:9 | total | 0 | +| test.c:230:14:230:14 | r | 2147483647 | +| test.c:232:12:232:12 | a | 2147483647 | +| test.c:232:17:232:17 | a | 2147483647 | +| test.c:232:33:232:33 | b | 2147483647 | +| test.c:232:38:232:38 | b | 2147483647 | +| test.c:233:13:233:13 | a | 11 | +| test.c:233:15:233:15 | b | 23 | +| test.c:234:5:234:9 | total | 2147483647 | +| test.c:234:14:234:14 | r | 2147483647 | +| test.c:236:12:236:12 | a | 2147483647 | +| test.c:236:17:236:17 | a | 2147483647 | +| test.c:236:35:236:35 | b | 2147483647 | +| test.c:236:40:236:40 | b | 2147483647 | +| test.c:237:13:237:13 | a | 11 | +| test.c:237:15:237:15 | b | 23 | +| test.c:238:5:238:9 | total | 2147483647 | +| test.c:238:14:238:14 | r | 2147483647 | +| test.c:240:12:240:12 | a | 2147483647 | +| test.c:240:17:240:17 | a | 2147483647 | +| test.c:240:35:240:35 | b | 2147483647 | +| test.c:240:40:240:40 | b | 2147483647 | +| test.c:241:13:241:13 | a | 11 | +| test.c:241:15:241:15 | b | 0 | +| test.c:242:5:242:9 | total | 2147483647 | +| test.c:242:14:242:14 | r | 2147483647 | +| test.c:244:12:244:12 | a | 2147483647 | +| test.c:244:17:244:17 | a | 2147483647 | +| test.c:244:35:244:35 | b | 2147483647 | +| test.c:244:40:244:40 | b | 2147483647 | +| test.c:245:13:245:13 | a | 11 | +| test.c:245:15:245:15 | b | -7 | +| test.c:246:5:246:9 | total | 2147483647 | +| test.c:246:14:246:14 | r | 2147483647 | +| test.c:249:10:249:14 | total | 2147483647 | +| test.c:256:14:256:14 | a | 2147483647 | +| test.c:256:19:256:19 | a | 2147483647 | +| test.c:256:35:256:35 | b | 2147483647 | +| test.c:256:40:256:40 | b | 2147483647 | +| test.c:257:13:257:13 | a | 11 | +| test.c:257:15:257:15 | b | 23 | +| test.c:258:5:258:9 | total | 0 | +| test.c:258:14:258:14 | r | 2147483647 | +| test.c:260:14:260:14 | a | 2147483647 | +| test.c:260:19:260:19 | a | 2147483647 | +| test.c:260:35:260:35 | b | 2147483647 | +| test.c:260:40:260:40 | b | 2147483647 | +| test.c:261:13:261:13 | a | 11 | +| test.c:261:15:261:15 | b | 23 | +| test.c:262:5:262:9 | total | 2147483647 | +| test.c:262:14:262:14 | r | 2147483647 | +| test.c:264:14:264:14 | a | 2147483647 | +| test.c:264:19:264:19 | a | 2147483647 | +| test.c:264:37:264:37 | b | 2147483647 | +| test.c:264:42:264:42 | b | 2147483647 | +| test.c:265:13:265:13 | a | 11 | +| test.c:265:15:265:15 | b | 23 | +| test.c:266:5:266:9 | total | 2147483647 | +| test.c:266:14:266:14 | r | 2147483647 | +| test.c:268:14:268:14 | a | 2147483647 | +| test.c:268:19:268:19 | a | 2147483647 | +| test.c:268:37:268:37 | b | 2147483647 | +| test.c:268:42:268:42 | b | 2147483647 | +| test.c:269:13:269:13 | a | 11 | +| test.c:269:15:269:15 | b | 0 | +| test.c:270:5:270:9 | total | 2147483647 | +| test.c:270:14:270:14 | r | 2147483647 | +| test.c:272:14:272:14 | a | 2147483647 | +| test.c:272:19:272:19 | a | 2147483647 | +| test.c:272:37:272:37 | b | 2147483647 | +| test.c:272:42:272:42 | b | 2147483647 | +| test.c:273:13:273:13 | a | 11 | +| test.c:273:15:273:15 | b | -7 | +| test.c:274:5:274:9 | total | 2147483647 | +| test.c:274:14:274:14 | r | 2147483647 | +| test.c:277:10:277:14 | total | 2147483647 | +| test.c:284:14:284:14 | a | 2147483647 | +| test.c:284:19:284:19 | a | 2147483647 | +| test.c:284:34:284:34 | b | 2147483647 | +| test.c:284:39:284:39 | b | 2147483647 | +| test.c:285:13:285:13 | a | 0 | +| test.c:285:15:285:15 | b | 23 | +| test.c:286:5:286:9 | total | 0 | +| test.c:286:14:286:14 | r | 2147483647 | +| test.c:288:14:288:14 | a | 2147483647 | +| test.c:288:19:288:19 | a | 2147483647 | +| test.c:288:34:288:34 | b | 2147483647 | +| test.c:288:39:288:39 | b | 2147483647 | +| test.c:289:13:289:13 | a | 0 | +| test.c:289:15:289:15 | b | 23 | +| test.c:290:5:290:9 | total | 2147483647 | +| test.c:290:14:290:14 | r | 2147483647 | +| test.c:292:14:292:14 | a | 2147483647 | +| test.c:292:19:292:19 | a | 2147483647 | +| test.c:292:36:292:36 | b | 2147483647 | +| test.c:292:41:292:41 | b | 2147483647 | +| test.c:293:13:293:13 | a | 0 | +| test.c:293:15:293:15 | b | 23 | +| test.c:294:5:294:9 | total | 2147483647 | +| test.c:294:14:294:14 | r | 2147483647 | +| test.c:296:14:296:14 | a | 2147483647 | +| test.c:296:19:296:19 | a | 2147483647 | +| test.c:296:36:296:36 | b | 2147483647 | +| test.c:296:41:296:41 | b | 2147483647 | +| test.c:297:13:297:13 | a | 0 | +| test.c:297:15:297:15 | b | 0 | +| test.c:298:5:298:9 | total | 2147483647 | +| test.c:298:14:298:14 | r | 2147483647 | +| test.c:300:14:300:14 | a | 2147483647 | +| test.c:300:19:300:19 | a | 2147483647 | +| test.c:300:36:300:36 | b | 2147483647 | +| test.c:300:41:300:41 | b | 2147483647 | +| test.c:301:13:301:13 | a | 0 | +| test.c:301:15:301:15 | b | -7 | +| test.c:302:5:302:9 | total | 2147483647 | +| test.c:302:14:302:14 | r | 2147483647 | +| test.c:305:10:305:14 | total | 2147483647 | +| test.c:312:14:312:14 | a | 2147483647 | +| test.c:312:19:312:19 | a | 2147483647 | +| test.c:312:35:312:35 | b | 2147483647 | +| test.c:312:40:312:40 | b | 2147483647 | +| test.c:313:13:313:13 | a | -2 | +| test.c:313:15:313:15 | b | 23 | +| test.c:314:5:314:9 | total | 0 | +| test.c:314:14:314:14 | r | 2147483647 | +| test.c:316:14:316:14 | a | 2147483647 | +| test.c:316:19:316:19 | a | 2147483647 | +| test.c:316:35:316:35 | b | 2147483647 | +| test.c:316:40:316:40 | b | 2147483647 | +| test.c:317:13:317:13 | a | -2 | +| test.c:317:15:317:15 | b | 23 | +| test.c:318:5:318:9 | total | 2147483647 | +| test.c:318:14:318:14 | r | 2147483647 | +| test.c:320:14:320:14 | a | 2147483647 | +| test.c:320:19:320:19 | a | 2147483647 | +| test.c:320:37:320:37 | b | 2147483647 | +| test.c:320:42:320:42 | b | 2147483647 | +| test.c:321:13:321:13 | a | -2 | +| test.c:321:15:321:15 | b | 23 | +| test.c:322:5:322:9 | total | 2147483647 | +| test.c:322:14:322:14 | r | 2147483647 | +| test.c:324:14:324:14 | a | 2147483647 | +| test.c:324:19:324:19 | a | 2147483647 | +| test.c:324:37:324:37 | b | 2147483647 | +| test.c:324:42:324:42 | b | 2147483647 | +| test.c:325:13:325:13 | a | -2 | +| test.c:325:15:325:15 | b | 0 | +| test.c:326:5:326:9 | total | 2147483647 | +| test.c:326:14:326:14 | r | 2147483647 | +| test.c:328:14:328:14 | a | 2147483647 | +| test.c:328:19:328:19 | a | 2147483647 | +| test.c:328:37:328:37 | b | 2147483647 | +| test.c:328:42:328:42 | b | 2147483647 | +| test.c:329:13:329:13 | a | -2 | +| test.c:329:15:329:15 | b | -7 | +| test.c:330:5:330:9 | total | 2147483647 | +| test.c:330:14:330:14 | r | 2147483647 | +| test.c:333:10:333:14 | total | 2147483647 | +| test.c:338:7:338:7 | x | 2147483647 | +| test.c:342:10:342:10 | i | 7 | +| test.c:343:5:343:5 | i | 2 | +| test.c:345:3:345:3 | d | 2147483647 | +| test.c:345:7:345:7 | i | 7 | +| test.c:346:7:346:7 | x | 2147483647 | +| test.c:347:9:347:9 | d | 7 | +| test.c:347:14:347:14 | x | -1 | +| test.c:357:3:357:4 | y1 | 4294967295 | +| test.c:357:8:357:8 | x | 4294967295 | +| test.c:357:18:357:18 | x | 99 | +| test.c:358:3:358:4 | y2 | 4294967295 | +| test.c:358:8:358:8 | x | 4294967295 | +| test.c:358:24:358:24 | x | 99 | +| test.c:359:3:359:4 | y3 | 4294967295 | +| test.c:360:3:360:4 | y4 | 4294967295 | +| test.c:361:3:361:4 | y5 | 4294967295 | +| test.c:362:3:362:4 | y6 | 4294967295 | +| test.c:363:3:363:4 | y7 | 4294967295 | +| test.c:364:3:364:4 | y8 | 4294967295 | +| test.c:365:7:365:7 | x | 4294967295 | +| test.c:366:5:366:6 | y3 | 4294967295 | +| test.c:366:10:366:10 | x | 299 | +| test.c:367:5:367:6 | y4 | 4294967295 | +| test.c:367:10:367:10 | x | 299 | +| test.c:368:5:368:6 | y5 | 4294967295 | +| test.c:368:11:368:11 | x | 299 | +| test.c:369:5:369:6 | y6 | 4294967295 | +| test.c:369:27:369:27 | x | 299 | +| test.c:370:5:370:6 | y7 | 4294967295 | +| test.c:370:27:370:27 | x | 299 | +| test.c:371:5:371:6 | y8 | 4294967295 | +| test.c:371:28:371:28 | x | 299 | +| test.c:373:10:373:11 | y1 | 99 | +| test.c:373:15:373:16 | y2 | 99 | +| test.c:373:20:373:21 | y3 | 299 | +| test.c:373:25:373:26 | y4 | 500 | +| test.c:373:30:373:31 | y5 | 300 | +| test.c:373:35:373:36 | y6 | 255 | +| test.c:373:40:373:41 | y7 | 500 | +| test.c:373:45:373:46 | y8 | 300 | +| test.c:379:3:379:4 | y1 | 4294967295 | +| test.c:379:8:379:8 | x | 4294967295 | +| test.c:379:18:379:18 | x | 4294967295 | +| test.c:380:3:380:4 | y2 | 4294967295 | +| test.c:380:8:380:8 | x | 4294967295 | +| test.c:380:25:380:25 | x | 4294967295 | +| test.c:381:3:381:4 | y3 | 4294967295 | +| test.c:382:3:382:4 | y4 | 4294967295 | +| test.c:383:3:383:4 | y5 | 4294967295 | +| test.c:384:7:384:7 | x | 4294967295 | +| test.c:385:5:385:6 | y3 | 4294967295 | +| test.c:385:11:385:11 | x | 4294967295 | +| test.c:386:5:386:6 | y4 | 4294967295 | +| test.c:386:11:386:11 | x | 4294967295 | +| test.c:387:5:387:6 | y5 | 4294967295 | +| test.c:387:27:387:27 | x | 4294967295 | +| test.c:389:10:389:11 | y1 | 4294967295 | +| test.c:389:15:389:16 | y2 | 4294967295 | +| test.c:389:20:389:21 | y3 | 4294967295 | +| test.c:389:25:389:26 | y4 | 4294967295 | +| test.c:389:30:389:31 | y5 | 1000 | +| test.c:394:20:394:20 | x | 4294967295 | +| test.c:394:30:394:30 | x | 99 | +| test.c:397:3:397:4 | y1 | 4294967295 | +| test.c:397:11:397:11 | y | 100 | +| test.c:397:14:397:14 | y | 101 | +| test.c:398:3:398:4 | y2 | 4294967295 | +| test.c:398:9:398:9 | y | 101 | +| test.c:398:14:398:14 | y | 102 | +| test.c:398:22:398:22 | y | 105 | +| test.c:399:10:399:11 | y1 | 101 | +| test.c:399:15:399:16 | y2 | 105 | +| test.c:407:3:407:3 | i | 2147483647 | +| test.c:408:7:408:7 | i | 10 | +| test.c:410:3:410:3 | i | 2147483647 | +| test.c:411:3:411:3 | i | 10 | +| test.c:412:7:412:7 | i | 2147483647 | +| test.c:414:3:414:3 | i | 2147483647 | +| test.c:415:3:415:3 | i | 40 | +| test.c:416:7:416:7 | i | 2147483647 | +| test.c:418:3:418:3 | i | 2147483647 | +| test.c:418:7:418:7 | j | 2147483647 | +| test.c:419:7:419:7 | i | 40 | +| test.c:421:3:421:3 | i | 2147483647 | +| test.c:421:8:421:8 | j | 40 | +| test.c:422:7:422:7 | i | 50 | +| test.c:424:3:424:3 | i | 2147483647 | +| test.c:424:13:424:13 | j | 2147483647 | +| test.c:425:7:425:7 | i | 2147483647 | +| test.c:432:12:432:12 | a | 4294967295 | +| test.c:432:17:432:17 | a | 4294967295 | +| test.c:432:33:432:33 | b | 4294967295 | +| test.c:432:38:432:38 | b | 4294967295 | +| test.c:433:13:433:13 | a | 11 | +| test.c:433:15:433:15 | b | 23 | +| test.c:434:5:434:9 | total | 0 | +| test.c:434:14:434:14 | r | 2147483647 | +| test.c:436:12:436:12 | a | 4294967295 | +| test.c:436:17:436:17 | a | 4294967295 | +| test.c:436:33:436:33 | b | 4294967295 | +| test.c:436:38:436:38 | b | 4294967295 | +| test.c:437:13:437:13 | a | 11 | +| test.c:437:15:437:15 | b | 23 | +| test.c:438:5:438:9 | total | 2147483647 | +| test.c:438:14:438:14 | r | 2147483647 | +| test.c:440:12:440:12 | a | 4294967295 | +| test.c:440:17:440:17 | a | 4294967295 | +| test.c:440:34:440:34 | b | 4294967295 | +| test.c:440:39:440:39 | b | 4294967295 | +| test.c:441:13:441:13 | a | 11 | +| test.c:441:15:441:15 | b | 23 | +| test.c:442:5:442:9 | total | 2147483647 | +| test.c:442:14:442:14 | r | 2147483647 | +| test.c:445:10:445:14 | total | 2147483647 | +| test.c:451:12:451:12 | b | 4294967295 | +| test.c:451:17:451:17 | b | 4294967295 | +| test.c:452:16:452:16 | b | 23 | +| test.c:453:5:453:9 | total | 0 | +| test.c:453:14:453:14 | r | 2147483647 | +| test.c:455:12:455:12 | b | 4294967295 | +| test.c:455:17:455:17 | b | 4294967295 | +| test.c:456:16:456:16 | b | 23 | +| test.c:457:5:457:9 | total | 2147483647 | +| test.c:457:14:457:14 | r | 2147483647 | +| test.c:459:13:459:13 | b | 4294967295 | +| test.c:459:18:459:18 | b | 4294967295 | +| test.c:460:16:460:16 | b | 23 | +| test.c:461:5:461:9 | total | 2147483647 | +| test.c:461:14:461:14 | r | 2147483647 | +| test.c:464:10:464:14 | total | 2147483647 | +| test.cpp:10:7:10:7 | b | 2147483647 | +| test.cpp:11:5:11:5 | x | 2147483647 | +| test.cpp:13:10:13:10 | x | 2147483647 | +| test.cpp:18:30:18:30 | x | 2147483647 | +| test.cpp:19:10:19:11 | x0 | 127 | +| test.cpp:27:7:27:7 | y | 2147483647 | +| test.cpp:28:5:28:5 | x | 2147483647 | +| test.cpp:30:7:30:7 | y | 2147483647 | +| test.cpp:31:5:31:5 | x | 2147483647 | +| test.cpp:33:7:33:7 | y | 2147483647 | +| test.cpp:34:5:34:5 | x | 2147483647 | +| test.cpp:36:7:36:7 | y | 2147483647 | +| test.cpp:37:5:37:5 | x | 2147483647 | +| test.cpp:39:7:39:7 | y | 2147483647 | +| test.cpp:40:5:40:5 | x | 2147483647 | +| test.cpp:42:7:42:7 | y | 2147483647 | +| test.cpp:43:5:43:5 | x | 2147483647 | +| test.cpp:45:7:45:7 | y | 2147483647 | +| test.cpp:46:5:46:5 | x | 2147483647 | +| test.cpp:51:7:51:7 | x | 2147483647 | +| test.cpp:52:21:52:21 | x | 0 | +| test.cpp:53:5:53:5 | t | 0 | +| test.cpp:53:15:53:16 | xb | 0 | +| test.cpp:56:7:56:7 | x | 2147483647 | +| test.cpp:57:21:57:21 | x | 2147483647 | +| test.cpp:58:5:58:5 | t | 0 | +| test.cpp:58:15:58:16 | xb | 1 | +| test.cpp:61:7:61:7 | x | 2147483647 | +| test.cpp:62:21:62:21 | x | -1 | +| test.cpp:63:5:63:5 | t | 1 | +| test.cpp:63:15:63:16 | xb | 1 | +| test.cpp:66:19:66:19 | x | 2147483647 | +| test.cpp:67:3:67:3 | t | 2 | +| test.cpp:67:13:67:14 | xb | 1 | +| test.cpp:69:10:69:10 | b | 1 | +| test.cpp:69:21:69:21 | t | 3 | +| test.cpp:74:30:74:30 | c | 255 | +| test.cpp:74:34:74:34 | c | 255 | +| test.cpp:75:22:75:30 | c_times_2 | 510 | +| test.cpp:77:5:77:13 | c_times_2 | 510 | +| test.cpp:79:3:79:11 | c_times_2 | 510 | diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.ql b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.ql index 341e5784aa3..26d188ce89c 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.ql +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.ql @@ -1,4 +1,4 @@ import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis from VariableAccess expr -select expr, upperBound(expr) +select expr, upperBound(expr).toString() From 030ab4f626064b5f81395674fb5499f6eaa088ef Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 10 Aug 2020 10:56:58 +0100 Subject: [PATCH 031/133] C++: Add string append operators to the test (changes layout). --- .../dataflow/taint-tests/localTaint.expected | 398 +++++++++--------- .../dataflow/taint-tests/stl.cpp | 8 + .../dataflow/taint-tests/taint.expected | 42 +- .../dataflow/taint-tests/test_diff.expected | 40 +- .../dataflow/taint-tests/test_ir.expected | 8 +- 5 files changed, 252 insertions(+), 244 deletions(-) diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected index ed26a2de21d..7e496929ee0 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -308,205 +308,205 @@ | movableclass.cpp:65:13:65:18 | call to source | movableclass.cpp:65:13:65:20 | call to MyMovableClass | TAINT | | movableclass.cpp:65:13:65:20 | call to MyMovableClass | movableclass.cpp:65:8:65:9 | ref arg s3 | TAINT | | movableclass.cpp:65:13:65:20 | call to MyMovableClass | movableclass.cpp:65:11:65:11 | call to operator= | TAINT | -| stl.cpp:97:12:97:17 | call to source | stl.cpp:101:7:101:7 | a | | -| stl.cpp:98:16:98:20 | 123 | stl.cpp:98:16:98:21 | call to basic_string | TAINT | -| stl.cpp:98:16:98:21 | call to basic_string | stl.cpp:102:7:102:7 | b | | -| stl.cpp:98:16:98:21 | call to basic_string | stl.cpp:104:7:104:7 | b | | -| stl.cpp:99:16:99:21 | call to source | stl.cpp:99:16:99:24 | call to basic_string | TAINT | -| stl.cpp:99:16:99:24 | call to basic_string | stl.cpp:103:7:103:7 | c | | -| stl.cpp:99:16:99:24 | call to basic_string | stl.cpp:105:7:105:7 | c | | -| stl.cpp:104:7:104:7 | b | stl.cpp:104:9:104:13 | call to c_str | TAINT | -| stl.cpp:105:7:105:7 | c | stl.cpp:105:9:105:13 | call to c_str | TAINT | -| stl.cpp:110:20:110:22 | call to basic_stringstream | stl.cpp:113:2:113:4 | ss1 | | -| stl.cpp:110:20:110:22 | call to basic_stringstream | stl.cpp:119:7:119:9 | ss1 | | -| stl.cpp:110:20:110:22 | call to basic_stringstream | stl.cpp:124:7:124:9 | ss1 | | -| stl.cpp:110:25:110:27 | call to basic_stringstream | stl.cpp:114:2:114:4 | ss2 | | -| stl.cpp:110:25:110:27 | call to basic_stringstream | stl.cpp:120:7:120:9 | ss2 | | -| stl.cpp:110:25:110:27 | call to basic_stringstream | stl.cpp:125:7:125:9 | ss2 | | -| stl.cpp:110:30:110:32 | call to basic_stringstream | stl.cpp:115:2:115:4 | ss3 | | -| stl.cpp:110:30:110:32 | call to basic_stringstream | stl.cpp:121:7:121:9 | ss3 | | -| stl.cpp:110:30:110:32 | call to basic_stringstream | stl.cpp:126:7:126:9 | ss3 | | -| stl.cpp:110:35:110:37 | call to basic_stringstream | stl.cpp:116:2:116:4 | ss4 | | -| stl.cpp:110:35:110:37 | call to basic_stringstream | stl.cpp:122:7:122:9 | ss4 | | -| stl.cpp:110:35:110:37 | call to basic_stringstream | stl.cpp:127:7:127:9 | ss4 | | -| stl.cpp:110:40:110:42 | call to basic_stringstream | stl.cpp:117:2:117:4 | ss5 | | -| stl.cpp:110:40:110:42 | call to basic_stringstream | stl.cpp:123:7:123:9 | ss5 | | -| stl.cpp:110:40:110:42 | call to basic_stringstream | stl.cpp:128:7:128:9 | ss5 | | -| stl.cpp:111:16:111:21 | call to source | stl.cpp:111:16:111:24 | call to basic_string | TAINT | -| stl.cpp:111:16:111:24 | call to basic_string | stl.cpp:117:9:117:9 | t | | -| stl.cpp:113:2:113:4 | ref arg ss1 | stl.cpp:119:7:119:9 | ss1 | | -| stl.cpp:113:2:113:4 | ref arg ss1 | stl.cpp:124:7:124:9 | ss1 | | -| stl.cpp:114:2:114:4 | ref arg ss2 | stl.cpp:120:7:120:9 | ss2 | | -| stl.cpp:114:2:114:4 | ref arg ss2 | stl.cpp:125:7:125:9 | ss2 | | -| stl.cpp:115:2:115:4 | ref arg ss3 | stl.cpp:121:7:121:9 | ss3 | | -| stl.cpp:115:2:115:4 | ref arg ss3 | stl.cpp:126:7:126:9 | ss3 | | -| stl.cpp:116:2:116:4 | ref arg ss4 | stl.cpp:122:7:122:9 | ss4 | | -| stl.cpp:116:2:116:4 | ref arg ss4 | stl.cpp:127:7:127:9 | ss4 | | -| stl.cpp:117:2:117:4 | ref arg ss5 | stl.cpp:123:7:123:9 | ss5 | | -| stl.cpp:117:2:117:4 | ref arg ss5 | stl.cpp:128:7:128:9 | ss5 | | -| stl.cpp:131:32:131:37 | source | stl.cpp:136:9:136:14 | source | | -| stl.cpp:133:20:133:22 | call to basic_stringstream | stl.cpp:135:2:135:4 | ss1 | | -| stl.cpp:133:20:133:22 | call to basic_stringstream | stl.cpp:138:7:138:9 | ss1 | | -| stl.cpp:133:20:133:22 | call to basic_stringstream | stl.cpp:140:7:140:9 | ss1 | | -| stl.cpp:133:25:133:27 | call to basic_stringstream | stl.cpp:136:2:136:4 | ss2 | | -| stl.cpp:133:25:133:27 | call to basic_stringstream | stl.cpp:139:7:139:9 | ss2 | | -| stl.cpp:133:25:133:27 | call to basic_stringstream | stl.cpp:141:7:141:9 | ss2 | | -| stl.cpp:135:2:135:4 | ref arg ss1 | stl.cpp:138:7:138:9 | ss1 | | -| stl.cpp:135:2:135:4 | ref arg ss1 | stl.cpp:140:7:140:9 | ss1 | | -| stl.cpp:136:2:136:4 | ref arg ss2 | stl.cpp:139:7:139:9 | ss2 | | -| stl.cpp:136:2:136:4 | ref arg ss2 | stl.cpp:141:7:141:9 | ss2 | | -| stl.cpp:154:16:154:28 | call to basic_string | stl.cpp:155:7:155:11 | path1 | | -| stl.cpp:154:17:154:26 | call to user_input | stl.cpp:154:16:154:28 | call to basic_string | TAINT | -| stl.cpp:155:7:155:11 | path1 | stl.cpp:155:13:155:17 | call to c_str | TAINT | -| stl.cpp:158:10:158:19 | call to user_input | stl.cpp:158:10:158:21 | call to basic_string | TAINT | -| stl.cpp:158:10:158:21 | call to basic_string | stl.cpp:158:2:158:21 | ... = ... | | -| stl.cpp:158:10:158:21 | call to basic_string | stl.cpp:159:7:159:11 | path2 | | -| stl.cpp:159:7:159:11 | path2 | stl.cpp:159:13:159:17 | call to c_str | TAINT | -| stl.cpp:161:15:161:24 | call to user_input | stl.cpp:161:15:161:27 | call to basic_string | TAINT | -| stl.cpp:161:15:161:27 | call to basic_string | stl.cpp:162:7:162:11 | path3 | | -| stl.cpp:162:7:162:11 | path3 | stl.cpp:162:13:162:17 | call to c_str | TAINT | -| stl.cpp:167:19:167:24 | call to source | stl.cpp:170:17:170:18 | cs | | -| stl.cpp:167:19:167:24 | call to source | stl.cpp:172:7:172:8 | cs | | -| stl.cpp:170:17:170:18 | cs | stl.cpp:170:17:170:19 | call to basic_string | TAINT | -| stl.cpp:170:17:170:19 | call to basic_string | stl.cpp:173:7:173:8 | ss | | -| stl.cpp:178:19:178:24 | call to source | stl.cpp:181:17:181:18 | cs | | -| stl.cpp:181:17:181:18 | cs | stl.cpp:181:17:181:19 | call to basic_string | TAINT | -| stl.cpp:181:17:181:19 | call to basic_string | stl.cpp:184:7:184:8 | ss | | -| stl.cpp:181:17:181:19 | call to basic_string | stl.cpp:187:7:187:8 | ss | | -| stl.cpp:184:7:184:8 | ss | stl.cpp:184:10:184:14 | call to c_str | TAINT | -| stl.cpp:184:10:184:14 | call to c_str | stl.cpp:184:2:184:16 | ... = ... | | -| stl.cpp:184:10:184:14 | call to c_str | stl.cpp:186:7:186:8 | cs | | -| stl.cpp:193:18:193:24 | hello | stl.cpp:193:18:193:25 | call to basic_string | TAINT | -| stl.cpp:193:18:193:25 | call to basic_string | stl.cpp:198:8:198:9 | s1 | | -| stl.cpp:194:19:194:26 | call to basic_string | stl.cpp:199:8:199:9 | s2 | | -| stl.cpp:194:20:194:26 | hello | stl.cpp:194:19:194:26 | call to basic_string | TAINT | -| stl.cpp:196:8:196:14 | call to basic_string | stl.cpp:196:3:196:14 | ... = ... | | -| stl.cpp:196:8:196:14 | call to basic_string | stl.cpp:200:8:200:9 | s3 | | -| stl.cpp:196:8:196:14 | hello | stl.cpp:196:8:196:14 | call to basic_string | TAINT | -| stl.cpp:204:18:204:23 | call to source | stl.cpp:204:18:204:26 | call to basic_string | TAINT | -| stl.cpp:204:18:204:26 | call to basic_string | stl.cpp:209:8:209:9 | s1 | | -| stl.cpp:205:19:205:27 | call to basic_string | stl.cpp:210:8:210:9 | s2 | | -| stl.cpp:205:20:205:25 | call to source | stl.cpp:205:19:205:27 | call to basic_string | TAINT | -| stl.cpp:207:8:207:13 | call to source | stl.cpp:207:8:207:15 | call to basic_string | TAINT | -| stl.cpp:207:8:207:15 | call to basic_string | stl.cpp:207:3:207:15 | ... = ... | | -| stl.cpp:207:8:207:15 | call to basic_string | stl.cpp:211:8:211:9 | s3 | | -| stl.cpp:215:15:215:16 | call to basic_string | stl.cpp:216:20:216:21 | s1 | | -| stl.cpp:215:15:215:16 | call to basic_string | stl.cpp:218:8:218:9 | s1 | | -| stl.cpp:215:15:215:16 | call to basic_string | stl.cpp:220:8:220:9 | s1 | | -| stl.cpp:216:20:216:21 | s1 | stl.cpp:221:8:221:9 | s2 | | -| stl.cpp:218:8:218:9 | s1 | stl.cpp:218:3:218:9 | ... = ... | | -| stl.cpp:218:8:218:9 | s1 | stl.cpp:222:8:222:9 | s3 | | -| stl.cpp:226:19:226:40 | call to basic_string | stl.cpp:230:8:230:9 | s1 | | -| stl.cpp:226:32:226:37 | call to source | stl.cpp:226:19:226:40 | call to basic_string | TAINT | -| stl.cpp:228:8:228:28 | call to basic_string | stl.cpp:228:3:228:28 | ... = ... | | -| stl.cpp:228:8:228:28 | call to basic_string | stl.cpp:231:8:231:9 | s2 | | -| stl.cpp:228:20:228:25 | call to source | stl.cpp:228:8:228:28 | call to basic_string | TAINT | -| stl.cpp:238:16:238:21 | call to source | stl.cpp:238:16:238:24 | call to basic_string | TAINT | -| stl.cpp:238:16:238:24 | call to basic_string | stl.cpp:239:15:239:15 | s | | -| stl.cpp:238:16:238:24 | call to basic_string | stl.cpp:243:33:243:33 | s | | -| stl.cpp:238:16:238:24 | call to basic_string | stl.cpp:243:50:243:50 | s | | -| stl.cpp:238:16:238:24 | call to basic_string | stl.cpp:247:16:247:16 | s | | -| stl.cpp:239:15:239:15 | call to begin | stl.cpp:239:15:239:15 | (__begin) | | -| stl.cpp:239:15:239:15 | call to begin | stl.cpp:239:15:239:15 | (__begin) | | -| stl.cpp:239:15:239:15 | call to begin | stl.cpp:239:15:239:15 | (__begin) | | -| stl.cpp:239:15:239:15 | call to end | stl.cpp:239:15:239:15 | (__end) | | -| stl.cpp:239:15:239:15 | call to operator* | stl.cpp:240:8:240:8 | c | | -| stl.cpp:239:15:239:15 | ref arg (__begin) | stl.cpp:239:15:239:15 | (__begin) | | -| stl.cpp:239:15:239:15 | ref arg (__begin) | stl.cpp:239:15:239:15 | (__begin) | | -| stl.cpp:239:15:239:15 | ref arg (__begin) | stl.cpp:239:15:239:15 | (__begin) | | -| stl.cpp:239:15:239:15 | ref arg (__range) | stl.cpp:239:15:239:15 | (__range) | | -| stl.cpp:239:15:239:15 | s | stl.cpp:239:15:239:15 | (__range) | | -| stl.cpp:239:15:239:15 | s | stl.cpp:239:15:239:15 | (__range) | | -| stl.cpp:239:15:239:15 | s | stl.cpp:239:15:239:15 | call to operator* | TAINT | -| stl.cpp:243:33:243:33 | ref arg s | stl.cpp:243:50:243:50 | s | | -| stl.cpp:243:33:243:33 | ref arg s | stl.cpp:247:16:247:16 | s | | -| stl.cpp:243:35:243:39 | call to begin | stl.cpp:243:44:243:45 | it | | -| stl.cpp:243:35:243:39 | call to begin | stl.cpp:243:61:243:62 | it | | -| stl.cpp:243:35:243:39 | call to begin | stl.cpp:244:9:244:10 | it | | -| stl.cpp:243:50:243:50 | ref arg s | stl.cpp:243:50:243:50 | s | | -| stl.cpp:243:50:243:50 | ref arg s | stl.cpp:247:16:247:16 | s | | -| stl.cpp:243:61:243:62 | ref arg it | stl.cpp:243:44:243:45 | it | | -| stl.cpp:243:61:243:62 | ref arg it | stl.cpp:243:61:243:62 | it | | -| stl.cpp:243:61:243:62 | ref arg it | stl.cpp:244:9:244:10 | it | | -| stl.cpp:247:16:247:16 | call to begin | stl.cpp:247:16:247:16 | (__begin) | | -| stl.cpp:247:16:247:16 | call to begin | stl.cpp:247:16:247:16 | (__begin) | | -| stl.cpp:247:16:247:16 | call to begin | stl.cpp:247:16:247:16 | (__begin) | | -| stl.cpp:247:16:247:16 | call to end | stl.cpp:247:16:247:16 | (__end) | | -| stl.cpp:247:16:247:16 | call to operator* | stl.cpp:248:8:248:8 | c | | -| stl.cpp:247:16:247:16 | ref arg (__begin) | stl.cpp:247:16:247:16 | (__begin) | | -| stl.cpp:247:16:247:16 | ref arg (__begin) | stl.cpp:247:16:247:16 | (__begin) | | -| stl.cpp:247:16:247:16 | ref arg (__begin) | stl.cpp:247:16:247:16 | (__begin) | | -| stl.cpp:247:16:247:16 | ref arg (__range) | stl.cpp:247:16:247:16 | (__range) | | -| stl.cpp:247:16:247:16 | s | stl.cpp:247:16:247:16 | (__range) | | -| stl.cpp:247:16:247:16 | s | stl.cpp:247:16:247:16 | (__range) | | -| stl.cpp:247:16:247:16 | s | stl.cpp:247:16:247:16 | call to operator* | TAINT | -| stl.cpp:251:28:251:33 | call to source | stl.cpp:251:28:251:36 | call to basic_string | TAINT | -| stl.cpp:251:28:251:36 | call to basic_string | stl.cpp:252:22:252:28 | const_s | | -| stl.cpp:252:22:252:22 | call to begin | stl.cpp:252:22:252:22 | (__begin) | | -| stl.cpp:252:22:252:22 | call to begin | stl.cpp:252:22:252:22 | (__begin) | | -| stl.cpp:252:22:252:22 | call to begin | stl.cpp:252:22:252:22 | (__begin) | | -| stl.cpp:252:22:252:22 | call to end | stl.cpp:252:22:252:22 | (__end) | | -| stl.cpp:252:22:252:22 | call to operator* | stl.cpp:253:8:253:8 | c | | -| stl.cpp:252:22:252:22 | ref arg (__begin) | stl.cpp:252:22:252:22 | (__begin) | | -| stl.cpp:252:22:252:22 | ref arg (__begin) | stl.cpp:252:22:252:22 | (__begin) | | -| stl.cpp:252:22:252:22 | ref arg (__begin) | stl.cpp:252:22:252:22 | (__begin) | | -| stl.cpp:252:22:252:28 | const_s | stl.cpp:252:22:252:22 | (__range) | | -| stl.cpp:252:22:252:28 | const_s | stl.cpp:252:22:252:22 | (__range) | | -| stl.cpp:252:22:252:28 | const_s | stl.cpp:252:22:252:22 | call to operator* | TAINT | -| stl.cpp:288:43:288:49 | source1 | stl.cpp:292:21:292:27 | source1 | | -| stl.cpp:288:43:288:49 | source1 | stl.cpp:306:33:306:39 | source1 | | -| stl.cpp:292:21:292:27 | source1 | stl.cpp:292:21:292:28 | call to vector | TAINT | -| stl.cpp:292:21:292:28 | call to vector | stl.cpp:294:14:294:14 | v | | -| stl.cpp:292:21:292:28 | call to vector | stl.cpp:298:38:298:38 | v | | -| stl.cpp:292:21:292:28 | call to vector | stl.cpp:298:55:298:55 | v | | -| stl.cpp:292:21:292:28 | call to vector | stl.cpp:302:15:302:15 | v | | -| stl.cpp:294:14:294:14 | call to begin | stl.cpp:294:14:294:14 | (__begin) | | -| stl.cpp:294:14:294:14 | call to begin | stl.cpp:294:14:294:14 | (__begin) | | -| stl.cpp:294:14:294:14 | call to begin | stl.cpp:294:14:294:14 | (__begin) | | -| stl.cpp:294:14:294:14 | call to end | stl.cpp:294:14:294:14 | (__end) | | -| stl.cpp:294:14:294:14 | call to operator* | stl.cpp:295:8:295:8 | x | | -| stl.cpp:294:14:294:14 | ref arg (__begin) | stl.cpp:294:14:294:14 | (__begin) | | -| stl.cpp:294:14:294:14 | ref arg (__begin) | stl.cpp:294:14:294:14 | (__begin) | | -| stl.cpp:294:14:294:14 | ref arg (__begin) | stl.cpp:294:14:294:14 | (__begin) | | -| stl.cpp:294:14:294:14 | ref arg (__range) | stl.cpp:294:14:294:14 | (__range) | | -| stl.cpp:294:14:294:14 | v | stl.cpp:294:14:294:14 | (__range) | | -| stl.cpp:294:14:294:14 | v | stl.cpp:294:14:294:14 | (__range) | | -| stl.cpp:294:14:294:14 | v | stl.cpp:294:14:294:14 | call to operator* | TAINT | -| stl.cpp:298:38:298:38 | ref arg v | stl.cpp:298:55:298:55 | v | | -| stl.cpp:298:38:298:38 | ref arg v | stl.cpp:302:15:302:15 | v | | -| stl.cpp:298:40:298:44 | call to begin | stl.cpp:298:49:298:50 | it | | -| stl.cpp:298:40:298:44 | call to begin | stl.cpp:298:66:298:67 | it | | -| stl.cpp:298:40:298:44 | call to begin | stl.cpp:299:9:299:10 | it | | -| stl.cpp:298:55:298:55 | ref arg v | stl.cpp:298:55:298:55 | v | | -| stl.cpp:298:55:298:55 | ref arg v | stl.cpp:302:15:302:15 | v | | -| stl.cpp:298:66:298:67 | ref arg it | stl.cpp:298:49:298:50 | it | | -| stl.cpp:298:66:298:67 | ref arg it | stl.cpp:298:66:298:67 | it | | -| stl.cpp:298:66:298:67 | ref arg it | stl.cpp:299:9:299:10 | it | | -| stl.cpp:302:15:302:15 | call to begin | stl.cpp:302:15:302:15 | (__begin) | | -| stl.cpp:302:15:302:15 | call to begin | stl.cpp:302:15:302:15 | (__begin) | | -| stl.cpp:302:15:302:15 | call to begin | stl.cpp:302:15:302:15 | (__begin) | | -| stl.cpp:302:15:302:15 | call to end | stl.cpp:302:15:302:15 | (__end) | | -| stl.cpp:302:15:302:15 | call to operator* | stl.cpp:303:8:303:8 | x | | -| stl.cpp:302:15:302:15 | ref arg (__begin) | stl.cpp:302:15:302:15 | (__begin) | | -| stl.cpp:302:15:302:15 | ref arg (__begin) | stl.cpp:302:15:302:15 | (__begin) | | -| stl.cpp:302:15:302:15 | ref arg (__begin) | stl.cpp:302:15:302:15 | (__begin) | | -| stl.cpp:302:15:302:15 | ref arg (__range) | stl.cpp:302:15:302:15 | (__range) | | -| stl.cpp:302:15:302:15 | v | stl.cpp:302:15:302:15 | (__range) | | -| stl.cpp:302:15:302:15 | v | stl.cpp:302:15:302:15 | (__range) | | -| stl.cpp:302:15:302:15 | v | stl.cpp:302:15:302:15 | call to operator* | TAINT | -| stl.cpp:306:33:306:39 | source1 | stl.cpp:306:33:306:40 | call to vector | TAINT | -| stl.cpp:306:33:306:40 | call to vector | stl.cpp:307:21:307:27 | const_v | | -| stl.cpp:307:21:307:21 | call to begin | stl.cpp:307:21:307:21 | (__begin) | | -| stl.cpp:307:21:307:21 | call to begin | stl.cpp:307:21:307:21 | (__begin) | | -| stl.cpp:307:21:307:21 | call to begin | stl.cpp:307:21:307:21 | (__begin) | | -| stl.cpp:307:21:307:21 | call to end | stl.cpp:307:21:307:21 | (__end) | | -| stl.cpp:307:21:307:21 | call to operator* | stl.cpp:308:8:308:8 | x | | -| stl.cpp:307:21:307:21 | ref arg (__begin) | stl.cpp:307:21:307:21 | (__begin) | | -| stl.cpp:307:21:307:21 | ref arg (__begin) | stl.cpp:307:21:307:21 | (__begin) | | -| stl.cpp:307:21:307:21 | ref arg (__begin) | stl.cpp:307:21:307:21 | (__begin) | | -| stl.cpp:307:21:307:27 | const_v | stl.cpp:307:21:307:21 | (__range) | | -| stl.cpp:307:21:307:27 | const_v | stl.cpp:307:21:307:21 | (__range) | | -| stl.cpp:307:21:307:27 | const_v | stl.cpp:307:21:307:21 | call to operator* | TAINT | +| stl.cpp:105:12:105:17 | call to source | stl.cpp:109:7:109:7 | a | | +| stl.cpp:106:16:106:20 | 123 | stl.cpp:106:16:106:21 | call to basic_string | TAINT | +| stl.cpp:106:16:106:21 | call to basic_string | stl.cpp:110:7:110:7 | b | | +| stl.cpp:106:16:106:21 | call to basic_string | stl.cpp:112:7:112:7 | b | | +| stl.cpp:107:16:107:21 | call to source | stl.cpp:107:16:107:24 | call to basic_string | TAINT | +| stl.cpp:107:16:107:24 | call to basic_string | stl.cpp:111:7:111:7 | c | | +| stl.cpp:107:16:107:24 | call to basic_string | stl.cpp:113:7:113:7 | c | | +| stl.cpp:112:7:112:7 | b | stl.cpp:112:9:112:13 | call to c_str | TAINT | +| stl.cpp:113:7:113:7 | c | stl.cpp:113:9:113:13 | call to c_str | TAINT | +| stl.cpp:118:20:118:22 | call to basic_stringstream | stl.cpp:121:2:121:4 | ss1 | | +| stl.cpp:118:20:118:22 | call to basic_stringstream | stl.cpp:127:7:127:9 | ss1 | | +| stl.cpp:118:20:118:22 | call to basic_stringstream | stl.cpp:132:7:132:9 | ss1 | | +| stl.cpp:118:25:118:27 | call to basic_stringstream | stl.cpp:122:2:122:4 | ss2 | | +| stl.cpp:118:25:118:27 | call to basic_stringstream | stl.cpp:128:7:128:9 | ss2 | | +| stl.cpp:118:25:118:27 | call to basic_stringstream | stl.cpp:133:7:133:9 | ss2 | | +| stl.cpp:118:30:118:32 | call to basic_stringstream | stl.cpp:123:2:123:4 | ss3 | | +| stl.cpp:118:30:118:32 | call to basic_stringstream | stl.cpp:129:7:129:9 | ss3 | | +| stl.cpp:118:30:118:32 | call to basic_stringstream | stl.cpp:134:7:134:9 | ss3 | | +| stl.cpp:118:35:118:37 | call to basic_stringstream | stl.cpp:124:2:124:4 | ss4 | | +| stl.cpp:118:35:118:37 | call to basic_stringstream | stl.cpp:130:7:130:9 | ss4 | | +| stl.cpp:118:35:118:37 | call to basic_stringstream | stl.cpp:135:7:135:9 | ss4 | | +| stl.cpp:118:40:118:42 | call to basic_stringstream | stl.cpp:125:2:125:4 | ss5 | | +| stl.cpp:118:40:118:42 | call to basic_stringstream | stl.cpp:131:7:131:9 | ss5 | | +| stl.cpp:118:40:118:42 | call to basic_stringstream | stl.cpp:136:7:136:9 | ss5 | | +| stl.cpp:119:16:119:21 | call to source | stl.cpp:119:16:119:24 | call to basic_string | TAINT | +| stl.cpp:119:16:119:24 | call to basic_string | stl.cpp:125:9:125:9 | t | | +| stl.cpp:121:2:121:4 | ref arg ss1 | stl.cpp:127:7:127:9 | ss1 | | +| stl.cpp:121:2:121:4 | ref arg ss1 | stl.cpp:132:7:132:9 | ss1 | | +| stl.cpp:122:2:122:4 | ref arg ss2 | stl.cpp:128:7:128:9 | ss2 | | +| stl.cpp:122:2:122:4 | ref arg ss2 | stl.cpp:133:7:133:9 | ss2 | | +| stl.cpp:123:2:123:4 | ref arg ss3 | stl.cpp:129:7:129:9 | ss3 | | +| stl.cpp:123:2:123:4 | ref arg ss3 | stl.cpp:134:7:134:9 | ss3 | | +| stl.cpp:124:2:124:4 | ref arg ss4 | stl.cpp:130:7:130:9 | ss4 | | +| stl.cpp:124:2:124:4 | ref arg ss4 | stl.cpp:135:7:135:9 | ss4 | | +| stl.cpp:125:2:125:4 | ref arg ss5 | stl.cpp:131:7:131:9 | ss5 | | +| stl.cpp:125:2:125:4 | ref arg ss5 | stl.cpp:136:7:136:9 | ss5 | | +| stl.cpp:139:32:139:37 | source | stl.cpp:144:9:144:14 | source | | +| stl.cpp:141:20:141:22 | call to basic_stringstream | stl.cpp:143:2:143:4 | ss1 | | +| stl.cpp:141:20:141:22 | call to basic_stringstream | stl.cpp:146:7:146:9 | ss1 | | +| stl.cpp:141:20:141:22 | call to basic_stringstream | stl.cpp:148:7:148:9 | ss1 | | +| stl.cpp:141:25:141:27 | call to basic_stringstream | stl.cpp:144:2:144:4 | ss2 | | +| stl.cpp:141:25:141:27 | call to basic_stringstream | stl.cpp:147:7:147:9 | ss2 | | +| stl.cpp:141:25:141:27 | call to basic_stringstream | stl.cpp:149:7:149:9 | ss2 | | +| stl.cpp:143:2:143:4 | ref arg ss1 | stl.cpp:146:7:146:9 | ss1 | | +| stl.cpp:143:2:143:4 | ref arg ss1 | stl.cpp:148:7:148:9 | ss1 | | +| stl.cpp:144:2:144:4 | ref arg ss2 | stl.cpp:147:7:147:9 | ss2 | | +| stl.cpp:144:2:144:4 | ref arg ss2 | stl.cpp:149:7:149:9 | ss2 | | +| stl.cpp:162:16:162:28 | call to basic_string | stl.cpp:163:7:163:11 | path1 | | +| stl.cpp:162:17:162:26 | call to user_input | stl.cpp:162:16:162:28 | call to basic_string | TAINT | +| stl.cpp:163:7:163:11 | path1 | stl.cpp:163:13:163:17 | call to c_str | TAINT | +| stl.cpp:166:10:166:19 | call to user_input | stl.cpp:166:10:166:21 | call to basic_string | TAINT | +| stl.cpp:166:10:166:21 | call to basic_string | stl.cpp:166:2:166:21 | ... = ... | | +| stl.cpp:166:10:166:21 | call to basic_string | stl.cpp:167:7:167:11 | path2 | | +| stl.cpp:167:7:167:11 | path2 | stl.cpp:167:13:167:17 | call to c_str | TAINT | +| stl.cpp:169:15:169:24 | call to user_input | stl.cpp:169:15:169:27 | call to basic_string | TAINT | +| stl.cpp:169:15:169:27 | call to basic_string | stl.cpp:170:7:170:11 | path3 | | +| stl.cpp:170:7:170:11 | path3 | stl.cpp:170:13:170:17 | call to c_str | TAINT | +| stl.cpp:175:19:175:24 | call to source | stl.cpp:178:17:178:18 | cs | | +| stl.cpp:175:19:175:24 | call to source | stl.cpp:180:7:180:8 | cs | | +| stl.cpp:178:17:178:18 | cs | stl.cpp:178:17:178:19 | call to basic_string | TAINT | +| stl.cpp:178:17:178:19 | call to basic_string | stl.cpp:181:7:181:8 | ss | | +| stl.cpp:186:19:186:24 | call to source | stl.cpp:189:17:189:18 | cs | | +| stl.cpp:189:17:189:18 | cs | stl.cpp:189:17:189:19 | call to basic_string | TAINT | +| stl.cpp:189:17:189:19 | call to basic_string | stl.cpp:192:7:192:8 | ss | | +| stl.cpp:189:17:189:19 | call to basic_string | stl.cpp:195:7:195:8 | ss | | +| stl.cpp:192:7:192:8 | ss | stl.cpp:192:10:192:14 | call to c_str | TAINT | +| stl.cpp:192:10:192:14 | call to c_str | stl.cpp:192:2:192:16 | ... = ... | | +| stl.cpp:192:10:192:14 | call to c_str | stl.cpp:194:7:194:8 | cs | | +| stl.cpp:201:18:201:24 | hello | stl.cpp:201:18:201:25 | call to basic_string | TAINT | +| stl.cpp:201:18:201:25 | call to basic_string | stl.cpp:206:8:206:9 | s1 | | +| stl.cpp:202:19:202:26 | call to basic_string | stl.cpp:207:8:207:9 | s2 | | +| stl.cpp:202:20:202:26 | hello | stl.cpp:202:19:202:26 | call to basic_string | TAINT | +| stl.cpp:204:8:204:14 | call to basic_string | stl.cpp:204:3:204:14 | ... = ... | | +| stl.cpp:204:8:204:14 | call to basic_string | stl.cpp:208:8:208:9 | s3 | | +| stl.cpp:204:8:204:14 | hello | stl.cpp:204:8:204:14 | call to basic_string | TAINT | +| stl.cpp:212:18:212:23 | call to source | stl.cpp:212:18:212:26 | call to basic_string | TAINT | +| stl.cpp:212:18:212:26 | call to basic_string | stl.cpp:217:8:217:9 | s1 | | +| stl.cpp:213:19:213:27 | call to basic_string | stl.cpp:218:8:218:9 | s2 | | +| stl.cpp:213:20:213:25 | call to source | stl.cpp:213:19:213:27 | call to basic_string | TAINT | +| stl.cpp:215:8:215:13 | call to source | stl.cpp:215:8:215:15 | call to basic_string | TAINT | +| stl.cpp:215:8:215:15 | call to basic_string | stl.cpp:215:3:215:15 | ... = ... | | +| stl.cpp:215:8:215:15 | call to basic_string | stl.cpp:219:8:219:9 | s3 | | +| stl.cpp:223:15:223:16 | call to basic_string | stl.cpp:224:20:224:21 | s1 | | +| stl.cpp:223:15:223:16 | call to basic_string | stl.cpp:226:8:226:9 | s1 | | +| stl.cpp:223:15:223:16 | call to basic_string | stl.cpp:228:8:228:9 | s1 | | +| stl.cpp:224:20:224:21 | s1 | stl.cpp:229:8:229:9 | s2 | | +| stl.cpp:226:8:226:9 | s1 | stl.cpp:226:3:226:9 | ... = ... | | +| stl.cpp:226:8:226:9 | s1 | stl.cpp:230:8:230:9 | s3 | | +| stl.cpp:234:19:234:40 | call to basic_string | stl.cpp:238:8:238:9 | s1 | | +| stl.cpp:234:32:234:37 | call to source | stl.cpp:234:19:234:40 | call to basic_string | TAINT | +| stl.cpp:236:8:236:28 | call to basic_string | stl.cpp:236:3:236:28 | ... = ... | | +| stl.cpp:236:8:236:28 | call to basic_string | stl.cpp:239:8:239:9 | s2 | | +| stl.cpp:236:20:236:25 | call to source | stl.cpp:236:8:236:28 | call to basic_string | TAINT | +| stl.cpp:246:16:246:21 | call to source | stl.cpp:246:16:246:24 | call to basic_string | TAINT | +| stl.cpp:246:16:246:24 | call to basic_string | stl.cpp:247:15:247:15 | s | | +| stl.cpp:246:16:246:24 | call to basic_string | stl.cpp:251:33:251:33 | s | | +| stl.cpp:246:16:246:24 | call to basic_string | stl.cpp:251:50:251:50 | s | | +| stl.cpp:246:16:246:24 | call to basic_string | stl.cpp:255:16:255:16 | s | | +| stl.cpp:247:15:247:15 | call to begin | stl.cpp:247:15:247:15 | (__begin) | | +| stl.cpp:247:15:247:15 | call to begin | stl.cpp:247:15:247:15 | (__begin) | | +| stl.cpp:247:15:247:15 | call to begin | stl.cpp:247:15:247:15 | (__begin) | | +| stl.cpp:247:15:247:15 | call to end | stl.cpp:247:15:247:15 | (__end) | | +| stl.cpp:247:15:247:15 | call to operator* | stl.cpp:248:8:248:8 | c | | +| stl.cpp:247:15:247:15 | ref arg (__begin) | stl.cpp:247:15:247:15 | (__begin) | | +| stl.cpp:247:15:247:15 | ref arg (__begin) | stl.cpp:247:15:247:15 | (__begin) | | +| stl.cpp:247:15:247:15 | ref arg (__begin) | stl.cpp:247:15:247:15 | (__begin) | | +| stl.cpp:247:15:247:15 | ref arg (__range) | stl.cpp:247:15:247:15 | (__range) | | +| stl.cpp:247:15:247:15 | s | stl.cpp:247:15:247:15 | (__range) | | +| stl.cpp:247:15:247:15 | s | stl.cpp:247:15:247:15 | (__range) | | +| stl.cpp:247:15:247:15 | s | stl.cpp:247:15:247:15 | call to operator* | TAINT | +| stl.cpp:251:33:251:33 | ref arg s | stl.cpp:251:50:251:50 | s | | +| stl.cpp:251:33:251:33 | ref arg s | stl.cpp:255:16:255:16 | s | | +| stl.cpp:251:35:251:39 | call to begin | stl.cpp:251:44:251:45 | it | | +| stl.cpp:251:35:251:39 | call to begin | stl.cpp:251:61:251:62 | it | | +| stl.cpp:251:35:251:39 | call to begin | stl.cpp:252:9:252:10 | it | | +| stl.cpp:251:50:251:50 | ref arg s | stl.cpp:251:50:251:50 | s | | +| stl.cpp:251:50:251:50 | ref arg s | stl.cpp:255:16:255:16 | s | | +| stl.cpp:251:61:251:62 | ref arg it | stl.cpp:251:44:251:45 | it | | +| stl.cpp:251:61:251:62 | ref arg it | stl.cpp:251:61:251:62 | it | | +| stl.cpp:251:61:251:62 | ref arg it | stl.cpp:252:9:252:10 | it | | +| stl.cpp:255:16:255:16 | call to begin | stl.cpp:255:16:255:16 | (__begin) | | +| stl.cpp:255:16:255:16 | call to begin | stl.cpp:255:16:255:16 | (__begin) | | +| stl.cpp:255:16:255:16 | call to begin | stl.cpp:255:16:255:16 | (__begin) | | +| stl.cpp:255:16:255:16 | call to end | stl.cpp:255:16:255:16 | (__end) | | +| stl.cpp:255:16:255:16 | call to operator* | stl.cpp:256:8:256:8 | c | | +| stl.cpp:255:16:255:16 | ref arg (__begin) | stl.cpp:255:16:255:16 | (__begin) | | +| stl.cpp:255:16:255:16 | ref arg (__begin) | stl.cpp:255:16:255:16 | (__begin) | | +| stl.cpp:255:16:255:16 | ref arg (__begin) | stl.cpp:255:16:255:16 | (__begin) | | +| stl.cpp:255:16:255:16 | ref arg (__range) | stl.cpp:255:16:255:16 | (__range) | | +| stl.cpp:255:16:255:16 | s | stl.cpp:255:16:255:16 | (__range) | | +| stl.cpp:255:16:255:16 | s | stl.cpp:255:16:255:16 | (__range) | | +| stl.cpp:255:16:255:16 | s | stl.cpp:255:16:255:16 | call to operator* | TAINT | +| stl.cpp:259:28:259:33 | call to source | stl.cpp:259:28:259:36 | call to basic_string | TAINT | +| stl.cpp:259:28:259:36 | call to basic_string | stl.cpp:260:22:260:28 | const_s | | +| stl.cpp:260:22:260:22 | call to begin | stl.cpp:260:22:260:22 | (__begin) | | +| stl.cpp:260:22:260:22 | call to begin | stl.cpp:260:22:260:22 | (__begin) | | +| stl.cpp:260:22:260:22 | call to begin | stl.cpp:260:22:260:22 | (__begin) | | +| stl.cpp:260:22:260:22 | call to end | stl.cpp:260:22:260:22 | (__end) | | +| stl.cpp:260:22:260:22 | call to operator* | stl.cpp:261:8:261:8 | c | | +| stl.cpp:260:22:260:22 | ref arg (__begin) | stl.cpp:260:22:260:22 | (__begin) | | +| stl.cpp:260:22:260:22 | ref arg (__begin) | stl.cpp:260:22:260:22 | (__begin) | | +| stl.cpp:260:22:260:22 | ref arg (__begin) | stl.cpp:260:22:260:22 | (__begin) | | +| stl.cpp:260:22:260:28 | const_s | stl.cpp:260:22:260:22 | (__range) | | +| stl.cpp:260:22:260:28 | const_s | stl.cpp:260:22:260:22 | (__range) | | +| stl.cpp:260:22:260:28 | const_s | stl.cpp:260:22:260:22 | call to operator* | TAINT | +| stl.cpp:296:43:296:49 | source1 | stl.cpp:300:21:300:27 | source1 | | +| stl.cpp:296:43:296:49 | source1 | stl.cpp:314:33:314:39 | source1 | | +| stl.cpp:300:21:300:27 | source1 | stl.cpp:300:21:300:28 | call to vector | TAINT | +| stl.cpp:300:21:300:28 | call to vector | stl.cpp:302:14:302:14 | v | | +| stl.cpp:300:21:300:28 | call to vector | stl.cpp:306:38:306:38 | v | | +| stl.cpp:300:21:300:28 | call to vector | stl.cpp:306:55:306:55 | v | | +| stl.cpp:300:21:300:28 | call to vector | stl.cpp:310:15:310:15 | v | | +| stl.cpp:302:14:302:14 | call to begin | stl.cpp:302:14:302:14 | (__begin) | | +| stl.cpp:302:14:302:14 | call to begin | stl.cpp:302:14:302:14 | (__begin) | | +| stl.cpp:302:14:302:14 | call to begin | stl.cpp:302:14:302:14 | (__begin) | | +| stl.cpp:302:14:302:14 | call to end | stl.cpp:302:14:302:14 | (__end) | | +| stl.cpp:302:14:302:14 | call to operator* | stl.cpp:303:8:303:8 | x | | +| stl.cpp:302:14:302:14 | ref arg (__begin) | stl.cpp:302:14:302:14 | (__begin) | | +| stl.cpp:302:14:302:14 | ref arg (__begin) | stl.cpp:302:14:302:14 | (__begin) | | +| stl.cpp:302:14:302:14 | ref arg (__begin) | stl.cpp:302:14:302:14 | (__begin) | | +| stl.cpp:302:14:302:14 | ref arg (__range) | stl.cpp:302:14:302:14 | (__range) | | +| stl.cpp:302:14:302:14 | v | stl.cpp:302:14:302:14 | (__range) | | +| stl.cpp:302:14:302:14 | v | stl.cpp:302:14:302:14 | (__range) | | +| stl.cpp:302:14:302:14 | v | stl.cpp:302:14:302:14 | call to operator* | TAINT | +| stl.cpp:306:38:306:38 | ref arg v | stl.cpp:306:55:306:55 | v | | +| stl.cpp:306:38:306:38 | ref arg v | stl.cpp:310:15:310:15 | v | | +| stl.cpp:306:40:306:44 | call to begin | stl.cpp:306:49:306:50 | it | | +| stl.cpp:306:40:306:44 | call to begin | stl.cpp:306:66:306:67 | it | | +| stl.cpp:306:40:306:44 | call to begin | stl.cpp:307:9:307:10 | it | | +| stl.cpp:306:55:306:55 | ref arg v | stl.cpp:306:55:306:55 | v | | +| stl.cpp:306:55:306:55 | ref arg v | stl.cpp:310:15:310:15 | v | | +| stl.cpp:306:66:306:67 | ref arg it | stl.cpp:306:49:306:50 | it | | +| stl.cpp:306:66:306:67 | ref arg it | stl.cpp:306:66:306:67 | it | | +| stl.cpp:306:66:306:67 | ref arg it | stl.cpp:307:9:307:10 | it | | +| stl.cpp:310:15:310:15 | call to begin | stl.cpp:310:15:310:15 | (__begin) | | +| stl.cpp:310:15:310:15 | call to begin | stl.cpp:310:15:310:15 | (__begin) | | +| stl.cpp:310:15:310:15 | call to begin | stl.cpp:310:15:310:15 | (__begin) | | +| stl.cpp:310:15:310:15 | call to end | stl.cpp:310:15:310:15 | (__end) | | +| stl.cpp:310:15:310:15 | call to operator* | stl.cpp:311:8:311:8 | x | | +| stl.cpp:310:15:310:15 | ref arg (__begin) | stl.cpp:310:15:310:15 | (__begin) | | +| stl.cpp:310:15:310:15 | ref arg (__begin) | stl.cpp:310:15:310:15 | (__begin) | | +| stl.cpp:310:15:310:15 | ref arg (__begin) | stl.cpp:310:15:310:15 | (__begin) | | +| stl.cpp:310:15:310:15 | ref arg (__range) | stl.cpp:310:15:310:15 | (__range) | | +| stl.cpp:310:15:310:15 | v | stl.cpp:310:15:310:15 | (__range) | | +| stl.cpp:310:15:310:15 | v | stl.cpp:310:15:310:15 | (__range) | | +| stl.cpp:310:15:310:15 | v | stl.cpp:310:15:310:15 | call to operator* | TAINT | +| stl.cpp:314:33:314:39 | source1 | stl.cpp:314:33:314:40 | call to vector | TAINT | +| stl.cpp:314:33:314:40 | call to vector | stl.cpp:315:21:315:27 | const_v | | +| stl.cpp:315:21:315:21 | call to begin | stl.cpp:315:21:315:21 | (__begin) | | +| stl.cpp:315:21:315:21 | call to begin | stl.cpp:315:21:315:21 | (__begin) | | +| stl.cpp:315:21:315:21 | call to begin | stl.cpp:315:21:315:21 | (__begin) | | +| stl.cpp:315:21:315:21 | call to end | stl.cpp:315:21:315:21 | (__end) | | +| stl.cpp:315:21:315:21 | call to operator* | stl.cpp:316:8:316:8 | x | | +| stl.cpp:315:21:315:21 | ref arg (__begin) | stl.cpp:315:21:315:21 | (__begin) | | +| stl.cpp:315:21:315:21 | ref arg (__begin) | stl.cpp:315:21:315:21 | (__begin) | | +| stl.cpp:315:21:315:21 | ref arg (__begin) | stl.cpp:315:21:315:21 | (__begin) | | +| stl.cpp:315:21:315:27 | const_v | stl.cpp:315:21:315:21 | (__range) | | +| stl.cpp:315:21:315:27 | const_v | stl.cpp:315:21:315:21 | (__range) | | +| stl.cpp:315:21:315:27 | const_v | stl.cpp:315:21:315:21 | call to operator* | TAINT | | structlikeclass.cpp:5:7:5:7 | Unknown literal | structlikeclass.cpp:5:7:5:7 | constructor init of field v | TAINT | | structlikeclass.cpp:5:7:5:7 | Unknown literal | structlikeclass.cpp:5:7:5:7 | constructor init of field v | TAINT | | structlikeclass.cpp:5:7:5:7 | this | structlikeclass.cpp:5:7:5:7 | constructor init of field v [pre-this] | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp index 654628a4dd4..c3788cac899 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp @@ -49,8 +49,16 @@ namespace std const_iterator end() const; const_iterator cbegin() const; const_iterator cend() const; + + template basic_string& operator+=(const T& t); + basic_string& operator+=(const charT* s); + basic_string& append(const basic_string& str); + basic_string& append(const charT* s); }; + template basic_string operator+(const basic_string& lhs, const basic_string& rhs); + template basic_string operator+(const basic_string& lhs, const charT* rhs); + typedef basic_string string; template > diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected index cd213ac2055..2f470e7b574 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -32,27 +32,27 @@ | movableclass.cpp:55:8:55:9 | s2 | movableclass.cpp:52:23:52:28 | call to source | | movableclass.cpp:64:8:64:9 | s2 | movableclass.cpp:23:55:23:60 | call to source | | movableclass.cpp:65:11:65:11 | call to operator= | movableclass.cpp:65:13:65:18 | call to source | -| stl.cpp:101:7:101:7 | a | stl.cpp:97:12:97:17 | call to source | -| stl.cpp:103:7:103:7 | c | stl.cpp:99:16:99:21 | call to source | -| stl.cpp:105:9:105:13 | call to c_str | stl.cpp:99:16:99:21 | call to source | -| stl.cpp:155:13:155:17 | call to c_str | stl.cpp:147:10:147:15 | call to source | -| stl.cpp:159:13:159:17 | call to c_str | stl.cpp:147:10:147:15 | call to source | -| stl.cpp:162:13:162:17 | call to c_str | stl.cpp:147:10:147:15 | call to source | -| stl.cpp:172:7:172:8 | cs | stl.cpp:167:19:167:24 | call to source | -| stl.cpp:173:7:173:8 | ss | stl.cpp:167:19:167:24 | call to source | -| stl.cpp:186:7:186:8 | cs | stl.cpp:178:19:178:24 | call to source | -| stl.cpp:187:7:187:8 | ss | stl.cpp:178:19:178:24 | call to source | -| stl.cpp:209:8:209:9 | s1 | stl.cpp:204:18:204:23 | call to source | -| stl.cpp:210:8:210:9 | s2 | stl.cpp:205:20:205:25 | call to source | -| stl.cpp:211:8:211:9 | s3 | stl.cpp:207:8:207:13 | call to source | -| stl.cpp:230:8:230:9 | s1 | stl.cpp:226:32:226:37 | call to source | -| stl.cpp:231:8:231:9 | s2 | stl.cpp:228:20:228:25 | call to source | -| stl.cpp:240:8:240:8 | c | stl.cpp:238:16:238:21 | call to source | -| stl.cpp:248:8:248:8 | c | stl.cpp:238:16:238:21 | call to source | -| stl.cpp:253:8:253:8 | c | stl.cpp:251:28:251:33 | call to source | -| stl.cpp:295:8:295:8 | x | stl.cpp:288:43:288:49 | source1 | -| stl.cpp:303:8:303:8 | x | stl.cpp:288:43:288:49 | source1 | -| stl.cpp:308:8:308:8 | x | stl.cpp:288:43:288:49 | source1 | +| stl.cpp:109:7:109:7 | a | stl.cpp:105:12:105:17 | call to source | +| stl.cpp:111:7:111:7 | c | stl.cpp:107:16:107:21 | call to source | +| stl.cpp:113:9:113:13 | call to c_str | stl.cpp:107:16:107:21 | call to source | +| stl.cpp:163:13:163:17 | call to c_str | stl.cpp:155:10:155:15 | call to source | +| stl.cpp:167:13:167:17 | call to c_str | stl.cpp:155:10:155:15 | call to source | +| stl.cpp:170:13:170:17 | call to c_str | stl.cpp:155:10:155:15 | call to source | +| stl.cpp:180:7:180:8 | cs | stl.cpp:175:19:175:24 | call to source | +| stl.cpp:181:7:181:8 | ss | stl.cpp:175:19:175:24 | call to source | +| stl.cpp:194:7:194:8 | cs | stl.cpp:186:19:186:24 | call to source | +| stl.cpp:195:7:195:8 | ss | stl.cpp:186:19:186:24 | call to source | +| stl.cpp:217:8:217:9 | s1 | stl.cpp:212:18:212:23 | call to source | +| stl.cpp:218:8:218:9 | s2 | stl.cpp:213:20:213:25 | call to source | +| stl.cpp:219:8:219:9 | s3 | stl.cpp:215:8:215:13 | call to source | +| stl.cpp:238:8:238:9 | s1 | stl.cpp:234:32:234:37 | call to source | +| stl.cpp:239:8:239:9 | s2 | stl.cpp:236:20:236:25 | call to source | +| stl.cpp:248:8:248:8 | c | stl.cpp:246:16:246:21 | call to source | +| stl.cpp:256:8:256:8 | c | stl.cpp:246:16:246:21 | call to source | +| stl.cpp:261:8:261:8 | c | stl.cpp:259:28:259:33 | call to source | +| stl.cpp:303:8:303:8 | x | stl.cpp:296:43:296:49 | source1 | +| stl.cpp:311:8:311:8 | x | stl.cpp:296:43:296:49 | source1 | +| stl.cpp:316:8:316:8 | x | stl.cpp:296:43:296:49 | source1 | | structlikeclass.cpp:35:8:35:9 | s1 | structlikeclass.cpp:29:22:29:27 | call to source | | structlikeclass.cpp:36:8:36:9 | s2 | structlikeclass.cpp:30:24:30:29 | call to source | | structlikeclass.cpp:37:8:37:9 | s3 | structlikeclass.cpp:29:22:29:27 | call to source | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected index be3b27ea69d..359286e62b6 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected @@ -30,26 +30,26 @@ | movableclass.cpp:55:8:55:9 | movableclass.cpp:52:23:52:28 | AST only | | movableclass.cpp:64:8:64:9 | movableclass.cpp:23:55:23:60 | AST only | | movableclass.cpp:65:11:65:11 | movableclass.cpp:65:13:65:18 | AST only | -| stl.cpp:103:7:103:7 | stl.cpp:99:16:99:21 | AST only | -| stl.cpp:105:9:105:13 | stl.cpp:99:16:99:21 | AST only | -| stl.cpp:155:13:155:17 | stl.cpp:147:10:147:15 | AST only | -| stl.cpp:159:13:159:17 | stl.cpp:147:10:147:15 | AST only | -| stl.cpp:162:13:162:17 | stl.cpp:147:10:147:15 | AST only | -| stl.cpp:172:7:172:8 | stl.cpp:167:19:167:26 | IR only | -| stl.cpp:173:7:173:8 | stl.cpp:167:19:167:24 | AST only | -| stl.cpp:186:7:186:8 | stl.cpp:178:19:178:24 | AST only | -| stl.cpp:187:7:187:8 | stl.cpp:178:19:178:24 | AST only | -| stl.cpp:209:8:209:9 | stl.cpp:204:18:204:23 | AST only | -| stl.cpp:210:8:210:9 | stl.cpp:205:20:205:25 | AST only | -| stl.cpp:211:8:211:9 | stl.cpp:207:8:207:13 | AST only | -| stl.cpp:230:8:230:9 | stl.cpp:226:32:226:37 | AST only | -| stl.cpp:231:8:231:9 | stl.cpp:228:20:228:25 | AST only | -| stl.cpp:240:8:240:8 | stl.cpp:238:16:238:21 | AST only | -| stl.cpp:248:8:248:8 | stl.cpp:238:16:238:21 | AST only | -| stl.cpp:253:8:253:8 | stl.cpp:251:28:251:33 | AST only | -| stl.cpp:295:8:295:8 | stl.cpp:288:43:288:49 | AST only | -| stl.cpp:303:8:303:8 | stl.cpp:288:43:288:49 | AST only | -| stl.cpp:308:8:308:8 | stl.cpp:288:43:288:49 | AST only | +| stl.cpp:111:7:111:7 | stl.cpp:107:16:107:21 | AST only | +| stl.cpp:113:9:113:13 | stl.cpp:107:16:107:21 | AST only | +| stl.cpp:163:13:163:17 | stl.cpp:155:10:155:15 | AST only | +| stl.cpp:167:13:167:17 | stl.cpp:155:10:155:15 | AST only | +| stl.cpp:170:13:170:17 | stl.cpp:155:10:155:15 | AST only | +| stl.cpp:180:7:180:8 | stl.cpp:175:19:175:26 | IR only | +| stl.cpp:181:7:181:8 | stl.cpp:175:19:175:24 | AST only | +| stl.cpp:194:7:194:8 | stl.cpp:186:19:186:24 | AST only | +| stl.cpp:195:7:195:8 | stl.cpp:186:19:186:24 | AST only | +| stl.cpp:217:8:217:9 | stl.cpp:212:18:212:23 | AST only | +| stl.cpp:218:8:218:9 | stl.cpp:213:20:213:25 | AST only | +| stl.cpp:219:8:219:9 | stl.cpp:215:8:215:13 | AST only | +| stl.cpp:238:8:238:9 | stl.cpp:234:32:234:37 | AST only | +| stl.cpp:239:8:239:9 | stl.cpp:236:20:236:25 | AST only | +| stl.cpp:248:8:248:8 | stl.cpp:246:16:246:21 | AST only | +| stl.cpp:256:8:256:8 | stl.cpp:246:16:246:21 | AST only | +| stl.cpp:261:8:261:8 | stl.cpp:259:28:259:33 | AST only | +| stl.cpp:303:8:303:8 | stl.cpp:296:43:296:49 | AST only | +| stl.cpp:311:8:311:8 | stl.cpp:296:43:296:49 | AST only | +| stl.cpp:316:8:316:8 | stl.cpp:296:43:296:49 | AST only | | structlikeclass.cpp:35:8:35:9 | structlikeclass.cpp:29:22:29:27 | AST only | | structlikeclass.cpp:36:8:36:9 | structlikeclass.cpp:30:24:30:29 | AST only | | structlikeclass.cpp:37:8:37:9 | structlikeclass.cpp:29:22:29:27 | AST only | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected index 62debb5d11f..fae0af72b67 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected @@ -1,10 +1,10 @@ | format.cpp:157:7:157:22 | (int)... | format.cpp:147:12:147:25 | call to source | | format.cpp:157:7:157:22 | access to array | format.cpp:147:12:147:25 | call to source | | format.cpp:158:7:158:27 | ... + ... | format.cpp:148:16:148:30 | call to source | -| stl.cpp:101:7:101:7 | (const char *)... | stl.cpp:97:12:97:17 | call to source | -| stl.cpp:101:7:101:7 | a | stl.cpp:97:12:97:17 | call to source | -| stl.cpp:172:7:172:8 | cs | stl.cpp:167:19:167:24 | call to source | -| stl.cpp:172:7:172:8 | cs | stl.cpp:167:19:167:26 | (const char *)... | +| stl.cpp:109:7:109:7 | (const char *)... | stl.cpp:105:12:105:17 | call to source | +| stl.cpp:109:7:109:7 | a | stl.cpp:105:12:105:17 | call to source | +| stl.cpp:180:7:180:8 | cs | stl.cpp:175:19:175:24 | call to source | +| stl.cpp:180:7:180:8 | cs | stl.cpp:175:19:175:26 | (const char *)... | | structlikeclass.cpp:38:8:38:9 | s4 | structlikeclass.cpp:33:8:33:13 | call to source | | structlikeclass.cpp:61:8:61:9 | s2 | structlikeclass.cpp:58:24:58:29 | call to source | | structlikeclass.cpp:62:8:62:20 | ... = ... | structlikeclass.cpp:62:13:62:18 | call to source | From f824a893ca6dd7902e8f958a46704b10c8531c48 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 10 Aug 2020 16:46:47 +0100 Subject: [PATCH 032/133] C++: Add test cases for appending strings. --- .../dataflow/taint-tests/localTaint.expected | 46 +++++++++++++++++++ .../dataflow/taint-tests/stl.cpp | 42 +++++++++++++++++ 2 files changed, 88 insertions(+) diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected index 7e496929ee0..84460e258d3 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -507,6 +507,52 @@ | stl.cpp:315:21:315:27 | const_v | stl.cpp:315:21:315:21 | (__range) | | | stl.cpp:315:21:315:27 | const_v | stl.cpp:315:21:315:21 | (__range) | | | stl.cpp:315:21:315:27 | const_v | stl.cpp:315:21:315:21 | call to operator* | TAINT | +| stl.cpp:322:18:322:24 | hello | stl.cpp:322:18:322:25 | call to basic_string | TAINT | +| stl.cpp:322:18:322:25 | call to basic_string | stl.cpp:325:8:325:9 | s1 | | +| stl.cpp:322:18:322:25 | call to basic_string | stl.cpp:325:13:325:14 | s1 | | +| stl.cpp:322:18:322:25 | call to basic_string | stl.cpp:326:8:326:9 | s1 | | +| stl.cpp:322:18:322:25 | call to basic_string | stl.cpp:327:13:327:14 | s1 | | +| stl.cpp:322:18:322:25 | call to basic_string | stl.cpp:330:8:330:9 | s1 | | +| stl.cpp:322:18:322:25 | call to basic_string | stl.cpp:331:8:331:9 | s1 | | +| stl.cpp:323:18:323:23 | call to source | stl.cpp:323:18:323:26 | call to basic_string | TAINT | +| stl.cpp:323:18:323:26 | call to basic_string | stl.cpp:326:13:326:14 | s2 | | +| stl.cpp:323:18:323:26 | call to basic_string | stl.cpp:327:8:327:9 | s2 | | +| stl.cpp:323:18:323:26 | call to basic_string | stl.cpp:328:8:328:9 | s2 | | +| stl.cpp:323:18:323:26 | call to basic_string | stl.cpp:328:13:328:14 | s2 | | +| stl.cpp:335:18:335:22 | abc | stl.cpp:335:18:335:23 | call to basic_string | TAINT | +| stl.cpp:335:18:335:23 | call to basic_string | stl.cpp:339:8:339:9 | s3 | | +| stl.cpp:335:18:335:23 | call to basic_string | stl.cpp:342:8:342:9 | s3 | | +| stl.cpp:335:18:335:23 | call to basic_string | stl.cpp:346:8:346:9 | s3 | | +| stl.cpp:335:18:335:23 | call to basic_string | stl.cpp:351:8:351:9 | s3 | | +| stl.cpp:335:18:335:23 | call to basic_string | stl.cpp:355:8:355:9 | s3 | | +| stl.cpp:336:18:336:23 | call to source | stl.cpp:336:18:336:26 | call to basic_string | TAINT | +| stl.cpp:336:18:336:26 | call to basic_string | stl.cpp:339:13:339:14 | s4 | | +| stl.cpp:336:18:336:26 | call to basic_string | stl.cpp:343:9:343:10 | s4 | | +| stl.cpp:336:18:336:26 | call to basic_string | stl.cpp:352:13:352:14 | s4 | | +| stl.cpp:339:11:339:11 | call to operator+ | stl.cpp:339:3:339:14 | ... = ... | | +| stl.cpp:339:11:339:11 | call to operator+ | stl.cpp:340:8:340:9 | s5 | | +| stl.cpp:342:8:342:9 | s3 | stl.cpp:342:3:342:9 | ... = ... | | +| stl.cpp:342:8:342:9 | s3 | stl.cpp:343:3:343:4 | s6 | | +| stl.cpp:342:8:342:9 | s3 | stl.cpp:344:8:344:9 | s6 | | +| stl.cpp:343:3:343:4 | ref arg s6 | stl.cpp:344:8:344:9 | s6 | | +| stl.cpp:346:8:346:9 | s3 | stl.cpp:346:3:346:9 | ... = ... | | +| stl.cpp:346:8:346:9 | s3 | stl.cpp:347:3:347:4 | s7 | | +| stl.cpp:346:8:346:9 | s3 | stl.cpp:348:3:348:4 | s7 | | +| stl.cpp:346:8:346:9 | s3 | stl.cpp:349:8:349:9 | s7 | | +| stl.cpp:347:3:347:4 | ref arg s7 | stl.cpp:348:3:348:4 | s7 | | +| stl.cpp:347:3:347:4 | ref arg s7 | stl.cpp:349:8:349:9 | s7 | | +| stl.cpp:348:3:348:4 | ref arg s7 | stl.cpp:349:8:349:9 | s7 | | +| stl.cpp:351:8:351:9 | s3 | stl.cpp:351:3:351:9 | ... = ... | | +| stl.cpp:351:8:351:9 | s3 | stl.cpp:352:3:352:4 | s8 | | +| stl.cpp:351:8:351:9 | s3 | stl.cpp:353:8:353:9 | s8 | | +| stl.cpp:352:3:352:4 | ref arg s8 | stl.cpp:353:8:353:9 | s8 | | +| stl.cpp:355:8:355:9 | s3 | stl.cpp:355:3:355:9 | ... = ... | | +| stl.cpp:355:8:355:9 | s3 | stl.cpp:356:3:356:4 | s9 | | +| stl.cpp:355:8:355:9 | s3 | stl.cpp:357:3:357:4 | s9 | | +| stl.cpp:355:8:355:9 | s3 | stl.cpp:358:8:358:9 | s9 | | +| stl.cpp:356:3:356:4 | ref arg s9 | stl.cpp:357:3:357:4 | s9 | | +| stl.cpp:356:3:356:4 | ref arg s9 | stl.cpp:358:8:358:9 | s9 | | +| stl.cpp:357:3:357:4 | ref arg s9 | stl.cpp:358:8:358:9 | s9 | | | structlikeclass.cpp:5:7:5:7 | Unknown literal | structlikeclass.cpp:5:7:5:7 | constructor init of field v | TAINT | | structlikeclass.cpp:5:7:5:7 | Unknown literal | structlikeclass.cpp:5:7:5:7 | constructor init of field v | TAINT | | structlikeclass.cpp:5:7:5:7 | this | structlikeclass.cpp:5:7:5:7 | constructor init of field v [pre-this] | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp index c3788cac899..32429150bca 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp @@ -316,3 +316,45 @@ void test_range_based_for_loop_vector(int source1) { sink(x); // tainted [NOT DETECTED by IR] } } + +void test_string_append() { + { + std::string s1("hello"); + std::string s2(source()); + + sink(s1 + s1); + sink(s1 + s2); // tainted [NOT DETECTED] + sink(s2 + s1); // tainted [NOT DETECTED] + sink(s2 + s2); // tainted [NOT DETECTED] + + sink(s1 + " world"); + sink(s1 + source()); // tainted [NOT DETECTED] + } + + { + std::string s3("abc"); + std::string s4(source()); + std::string s5, s6, s7, s8, s9; + + s5 = s3 + s4; + sink(s5); // tainted [NOT DETECTED] + + s6 = s3; + s6 += s4; + sink(s6); // tainted [NOT DETECTED] + + s7 = s3; + s7 += source(); + s7 += " "; + sink(s7); // tainted [NOT DETECTED] + + s8 = s3; + s8.append(s4); + sink(s8); // tainted [NOT DETECTED] + + s9 = s3; + s9.append(source()); + s9.append(" "); + sink(s9); // tainted [NOT DETECTED] + } +} From a57dfd6b678605d0066ad84bed1569063bebd12f Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 11 Aug 2020 11:31:28 +0100 Subject: [PATCH 033/133] C++: Taint through std::string append. --- .../cpp/models/implementations/StdString.qll | 16 ++++++++++++++++ .../dataflow/taint-tests/localTaint.expected | 6 ++++++ .../library-tests/dataflow/taint-tests/stl.cpp | 4 ++-- .../dataflow/taint-tests/taint.expected | 2 ++ .../dataflow/taint-tests/test_diff.expected | 2 ++ 5 files changed, 28 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll index 9ffef420a19..8820b8813fa 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -12,3 +12,19 @@ class StdStringCStr extends TaintFunction { output.isReturnValue() } } + +/** + * The `std::string` function `append`. + */ +class StdStringAppend extends TaintFunction { + StdStringAppend() { this.hasQualifiedName("std", "basic_string", "append") } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // flow from parameter to string itself (qualifier) and return value + input.isParameterDeref(0) and + ( + output.isQualifierObject() or + output.isReturnValueDeref() + ) + } +} diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected index 84460e258d3..d9ae1254933 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -546,13 +546,19 @@ | stl.cpp:351:8:351:9 | s3 | stl.cpp:352:3:352:4 | s8 | | | stl.cpp:351:8:351:9 | s3 | stl.cpp:353:8:353:9 | s8 | | | stl.cpp:352:3:352:4 | ref arg s8 | stl.cpp:353:8:353:9 | s8 | | +| stl.cpp:352:13:352:14 | s4 | stl.cpp:352:3:352:4 | ref arg s8 | TAINT | +| stl.cpp:352:13:352:14 | s4 | stl.cpp:352:6:352:11 | call to append | TAINT | | stl.cpp:355:8:355:9 | s3 | stl.cpp:355:3:355:9 | ... = ... | | | stl.cpp:355:8:355:9 | s3 | stl.cpp:356:3:356:4 | s9 | | | stl.cpp:355:8:355:9 | s3 | stl.cpp:357:3:357:4 | s9 | | | stl.cpp:355:8:355:9 | s3 | stl.cpp:358:8:358:9 | s9 | | | stl.cpp:356:3:356:4 | ref arg s9 | stl.cpp:357:3:357:4 | s9 | | | stl.cpp:356:3:356:4 | ref arg s9 | stl.cpp:358:8:358:9 | s9 | | +| stl.cpp:356:13:356:18 | call to source | stl.cpp:356:3:356:4 | ref arg s9 | TAINT | +| stl.cpp:356:13:356:18 | call to source | stl.cpp:356:6:356:11 | call to append | TAINT | | stl.cpp:357:3:357:4 | ref arg s9 | stl.cpp:358:8:358:9 | s9 | | +| stl.cpp:357:13:357:15 | | stl.cpp:357:3:357:4 | ref arg s9 | TAINT | +| stl.cpp:357:13:357:15 | | stl.cpp:357:6:357:11 | call to append | TAINT | | structlikeclass.cpp:5:7:5:7 | Unknown literal | structlikeclass.cpp:5:7:5:7 | constructor init of field v | TAINT | | structlikeclass.cpp:5:7:5:7 | Unknown literal | structlikeclass.cpp:5:7:5:7 | constructor init of field v | TAINT | | structlikeclass.cpp:5:7:5:7 | this | structlikeclass.cpp:5:7:5:7 | constructor init of field v [pre-this] | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp index 32429150bca..2ae246cac08 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp @@ -350,11 +350,11 @@ void test_string_append() { s8 = s3; s8.append(s4); - sink(s8); // tainted [NOT DETECTED] + sink(s8); // tainted s9 = s3; s9.append(source()); s9.append(" "); - sink(s9); // tainted [NOT DETECTED] + sink(s9); // tainted } } diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected index 2f470e7b574..855f886c626 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -53,6 +53,8 @@ | stl.cpp:303:8:303:8 | x | stl.cpp:296:43:296:49 | source1 | | stl.cpp:311:8:311:8 | x | stl.cpp:296:43:296:49 | source1 | | stl.cpp:316:8:316:8 | x | stl.cpp:296:43:296:49 | source1 | +| stl.cpp:353:8:353:9 | s8 | stl.cpp:336:18:336:23 | call to source | +| stl.cpp:358:8:358:9 | s9 | stl.cpp:356:13:356:18 | call to source | | structlikeclass.cpp:35:8:35:9 | s1 | structlikeclass.cpp:29:22:29:27 | call to source | | structlikeclass.cpp:36:8:36:9 | s2 | structlikeclass.cpp:30:24:30:29 | call to source | | structlikeclass.cpp:37:8:37:9 | s3 | structlikeclass.cpp:29:22:29:27 | call to source | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected index 359286e62b6..c7a0ebe6d84 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected @@ -50,6 +50,8 @@ | stl.cpp:303:8:303:8 | stl.cpp:296:43:296:49 | AST only | | stl.cpp:311:8:311:8 | stl.cpp:296:43:296:49 | AST only | | stl.cpp:316:8:316:8 | stl.cpp:296:43:296:49 | AST only | +| stl.cpp:353:8:353:9 | stl.cpp:336:18:336:23 | AST only | +| stl.cpp:358:8:358:9 | stl.cpp:356:13:356:18 | AST only | | structlikeclass.cpp:35:8:35:9 | structlikeclass.cpp:29:22:29:27 | AST only | | structlikeclass.cpp:36:8:36:9 | structlikeclass.cpp:30:24:30:29 | AST only | | structlikeclass.cpp:37:8:37:9 | structlikeclass.cpp:29:22:29:27 | AST only | From cf6f53082323e133e701c08091508e39476ea165 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 11 Aug 2020 15:02:36 +0100 Subject: [PATCH 034/133] C++: Taint through std::string operator+. --- .../cpp/models/implementations/StdString.qll | 26 +++++++++++++++++++ .../dataflow/taint-tests/localTaint.expected | 14 ++++++++++ .../dataflow/taint-tests/stl.cpp | 10 +++---- .../dataflow/taint-tests/taint.expected | 5 ++++ .../dataflow/taint-tests/test_diff.expected | 5 ++++ 5 files changed, 55 insertions(+), 5 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll index 8820b8813fa..aae2012d758 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -1,5 +1,12 @@ import semmle.code.cpp.models.interfaces.Taint +/** + * The `std::basic_string` template class. + */ +class StdBasicString extends TemplateClass { + StdBasicString() { this.hasQualifiedName("std", "basic_string") } +} + /** * The standard function `std::string.c_str`. */ @@ -13,6 +20,25 @@ class StdStringCStr extends TaintFunction { } } +/** + * The `std::string` function `operator+`. + */ +class StdStringPlus extends TaintFunction { + StdStringPlus() { + this.hasQualifiedName("std", "operator+") and + this.getParameter(0).getType().getUnspecifiedType().(ReferenceType).getBaseType() = any(StdBasicString s).getAnInstantiation() + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // flow from parameters to return value + ( + input.isParameterDeref(0) or + input.isParameterDeref(1) + ) and + output.isReturnValueDeref() + } +} + /** * The `std::string` function `append`. */ diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected index d9ae1254933..c91dfe970e3 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -519,6 +519,18 @@ | stl.cpp:323:18:323:26 | call to basic_string | stl.cpp:327:8:327:9 | s2 | | | stl.cpp:323:18:323:26 | call to basic_string | stl.cpp:328:8:328:9 | s2 | | | stl.cpp:323:18:323:26 | call to basic_string | stl.cpp:328:13:328:14 | s2 | | +| stl.cpp:325:8:325:9 | s1 | stl.cpp:325:11:325:11 | call to operator+ | TAINT | +| stl.cpp:325:13:325:14 | s1 | stl.cpp:325:11:325:11 | call to operator+ | TAINT | +| stl.cpp:326:8:326:9 | s1 | stl.cpp:326:11:326:11 | call to operator+ | TAINT | +| stl.cpp:326:13:326:14 | s2 | stl.cpp:326:11:326:11 | call to operator+ | TAINT | +| stl.cpp:327:8:327:9 | s2 | stl.cpp:327:11:327:11 | call to operator+ | TAINT | +| stl.cpp:327:13:327:14 | s1 | stl.cpp:327:11:327:11 | call to operator+ | TAINT | +| stl.cpp:328:8:328:9 | s2 | stl.cpp:328:11:328:11 | call to operator+ | TAINT | +| stl.cpp:328:13:328:14 | s2 | stl.cpp:328:11:328:11 | call to operator+ | TAINT | +| stl.cpp:330:8:330:9 | s1 | stl.cpp:330:11:330:11 | call to operator+ | TAINT | +| stl.cpp:330:13:330:20 | world | stl.cpp:330:11:330:11 | call to operator+ | TAINT | +| stl.cpp:331:8:331:9 | s1 | stl.cpp:331:11:331:11 | call to operator+ | TAINT | +| stl.cpp:331:13:331:18 | call to source | stl.cpp:331:11:331:11 | call to operator+ | TAINT | | stl.cpp:335:18:335:22 | abc | stl.cpp:335:18:335:23 | call to basic_string | TAINT | | stl.cpp:335:18:335:23 | call to basic_string | stl.cpp:339:8:339:9 | s3 | | | stl.cpp:335:18:335:23 | call to basic_string | stl.cpp:342:8:342:9 | s3 | | @@ -529,8 +541,10 @@ | stl.cpp:336:18:336:26 | call to basic_string | stl.cpp:339:13:339:14 | s4 | | | stl.cpp:336:18:336:26 | call to basic_string | stl.cpp:343:9:343:10 | s4 | | | stl.cpp:336:18:336:26 | call to basic_string | stl.cpp:352:13:352:14 | s4 | | +| stl.cpp:339:8:339:9 | s3 | stl.cpp:339:11:339:11 | call to operator+ | TAINT | | stl.cpp:339:11:339:11 | call to operator+ | stl.cpp:339:3:339:14 | ... = ... | | | stl.cpp:339:11:339:11 | call to operator+ | stl.cpp:340:8:340:9 | s5 | | +| stl.cpp:339:13:339:14 | s4 | stl.cpp:339:11:339:11 | call to operator+ | TAINT | | stl.cpp:342:8:342:9 | s3 | stl.cpp:342:3:342:9 | ... = ... | | | stl.cpp:342:8:342:9 | s3 | stl.cpp:343:3:343:4 | s6 | | | stl.cpp:342:8:342:9 | s3 | stl.cpp:344:8:344:9 | s6 | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp index 2ae246cac08..8c3e9423605 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp @@ -323,12 +323,12 @@ void test_string_append() { std::string s2(source()); sink(s1 + s1); - sink(s1 + s2); // tainted [NOT DETECTED] - sink(s2 + s1); // tainted [NOT DETECTED] - sink(s2 + s2); // tainted [NOT DETECTED] + sink(s1 + s2); // tainted + sink(s2 + s1); // tainted + sink(s2 + s2); // tainted sink(s1 + " world"); - sink(s1 + source()); // tainted [NOT DETECTED] + sink(s1 + source()); // tainted } { @@ -337,7 +337,7 @@ void test_string_append() { std::string s5, s6, s7, s8, s9; s5 = s3 + s4; - sink(s5); // tainted [NOT DETECTED] + sink(s5); // tainted s6 = s3; s6 += s4; diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected index 855f886c626..f04733bab7d 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -53,6 +53,11 @@ | stl.cpp:303:8:303:8 | x | stl.cpp:296:43:296:49 | source1 | | stl.cpp:311:8:311:8 | x | stl.cpp:296:43:296:49 | source1 | | stl.cpp:316:8:316:8 | x | stl.cpp:296:43:296:49 | source1 | +| stl.cpp:326:11:326:11 | call to operator+ | stl.cpp:323:18:323:23 | call to source | +| stl.cpp:327:11:327:11 | call to operator+ | stl.cpp:323:18:323:23 | call to source | +| stl.cpp:328:11:328:11 | call to operator+ | stl.cpp:323:18:323:23 | call to source | +| stl.cpp:331:11:331:11 | call to operator+ | stl.cpp:331:13:331:18 | call to source | +| stl.cpp:340:8:340:9 | s5 | stl.cpp:336:18:336:23 | call to source | | stl.cpp:353:8:353:9 | s8 | stl.cpp:336:18:336:23 | call to source | | stl.cpp:358:8:358:9 | s9 | stl.cpp:356:13:356:18 | call to source | | structlikeclass.cpp:35:8:35:9 | s1 | structlikeclass.cpp:29:22:29:27 | call to source | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected index c7a0ebe6d84..5c80cbfd071 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected @@ -50,6 +50,11 @@ | stl.cpp:303:8:303:8 | stl.cpp:296:43:296:49 | AST only | | stl.cpp:311:8:311:8 | stl.cpp:296:43:296:49 | AST only | | stl.cpp:316:8:316:8 | stl.cpp:296:43:296:49 | AST only | +| stl.cpp:326:11:326:11 | stl.cpp:323:18:323:23 | AST only | +| stl.cpp:327:11:327:11 | stl.cpp:323:18:323:23 | AST only | +| stl.cpp:328:11:328:11 | stl.cpp:323:18:323:23 | AST only | +| stl.cpp:331:11:331:11 | stl.cpp:331:13:331:18 | AST only | +| stl.cpp:340:8:340:9 | stl.cpp:336:18:336:23 | AST only | | stl.cpp:353:8:353:9 | stl.cpp:336:18:336:23 | AST only | | stl.cpp:358:8:358:9 | stl.cpp:356:13:356:18 | AST only | | structlikeclass.cpp:35:8:35:9 | structlikeclass.cpp:29:22:29:27 | AST only | From f62ad750481b9d0d72147e3d221a859bf3c1aa5b Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 11 Aug 2020 15:25:48 +0100 Subject: [PATCH 035/133] C++: Taint through std::string operator+=. --- .../semmle/code/cpp/models/implementations/StdString.qll | 7 +++++-- .../library-tests/dataflow/taint-tests/localTaint.expected | 6 ++++++ cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp | 4 ++-- .../test/library-tests/dataflow/taint-tests/taint.expected | 2 ++ .../library-tests/dataflow/taint-tests/test_diff.expected | 2 ++ 5 files changed, 17 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll index aae2012d758..35965fe207d 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -40,10 +40,13 @@ class StdStringPlus extends TaintFunction { } /** - * The `std::string` function `append`. + * The `std::string` functions `operator+=` and `append`. */ class StdStringAppend extends TaintFunction { - StdStringAppend() { this.hasQualifiedName("std", "basic_string", "append") } + StdStringAppend() { + this.hasQualifiedName("std", "basic_string", "operator+=") or + this.hasQualifiedName("std", "basic_string", "append") + } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from parameter to string itself (qualifier) and return value diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected index c91dfe970e3..08fdcd85eeb 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -549,13 +549,19 @@ | stl.cpp:342:8:342:9 | s3 | stl.cpp:343:3:343:4 | s6 | | | stl.cpp:342:8:342:9 | s3 | stl.cpp:344:8:344:9 | s6 | | | stl.cpp:343:3:343:4 | ref arg s6 | stl.cpp:344:8:344:9 | s6 | | +| stl.cpp:343:9:343:10 | s4 | stl.cpp:343:3:343:4 | ref arg s6 | TAINT | +| stl.cpp:343:9:343:10 | s4 | stl.cpp:343:6:343:6 | call to operator+= | TAINT | | stl.cpp:346:8:346:9 | s3 | stl.cpp:346:3:346:9 | ... = ... | | | stl.cpp:346:8:346:9 | s3 | stl.cpp:347:3:347:4 | s7 | | | stl.cpp:346:8:346:9 | s3 | stl.cpp:348:3:348:4 | s7 | | | stl.cpp:346:8:346:9 | s3 | stl.cpp:349:8:349:9 | s7 | | | stl.cpp:347:3:347:4 | ref arg s7 | stl.cpp:348:3:348:4 | s7 | | | stl.cpp:347:3:347:4 | ref arg s7 | stl.cpp:349:8:349:9 | s7 | | +| stl.cpp:347:9:347:14 | call to source | stl.cpp:347:3:347:4 | ref arg s7 | TAINT | +| stl.cpp:347:9:347:14 | call to source | stl.cpp:347:6:347:6 | call to operator+= | TAINT | | stl.cpp:348:3:348:4 | ref arg s7 | stl.cpp:349:8:349:9 | s7 | | +| stl.cpp:348:9:348:11 | | stl.cpp:348:3:348:4 | ref arg s7 | TAINT | +| stl.cpp:348:9:348:11 | | stl.cpp:348:6:348:6 | call to operator+= | TAINT | | stl.cpp:351:8:351:9 | s3 | stl.cpp:351:3:351:9 | ... = ... | | | stl.cpp:351:8:351:9 | s3 | stl.cpp:352:3:352:4 | s8 | | | stl.cpp:351:8:351:9 | s3 | stl.cpp:353:8:353:9 | s8 | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp index 8c3e9423605..698bed82c02 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp @@ -341,12 +341,12 @@ void test_string_append() { s6 = s3; s6 += s4; - sink(s6); // tainted [NOT DETECTED] + sink(s6); // tainted s7 = s3; s7 += source(); s7 += " "; - sink(s7); // tainted [NOT DETECTED] + sink(s7); // tainted s8 = s3; s8.append(s4); diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected index f04733bab7d..345f8674aad 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -58,6 +58,8 @@ | stl.cpp:328:11:328:11 | call to operator+ | stl.cpp:323:18:323:23 | call to source | | stl.cpp:331:11:331:11 | call to operator+ | stl.cpp:331:13:331:18 | call to source | | stl.cpp:340:8:340:9 | s5 | stl.cpp:336:18:336:23 | call to source | +| stl.cpp:344:8:344:9 | s6 | stl.cpp:336:18:336:23 | call to source | +| stl.cpp:349:8:349:9 | s7 | stl.cpp:347:9:347:14 | call to source | | stl.cpp:353:8:353:9 | s8 | stl.cpp:336:18:336:23 | call to source | | stl.cpp:358:8:358:9 | s9 | stl.cpp:356:13:356:18 | call to source | | structlikeclass.cpp:35:8:35:9 | s1 | structlikeclass.cpp:29:22:29:27 | call to source | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected index 5c80cbfd071..4c83b90df08 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected @@ -55,6 +55,8 @@ | stl.cpp:328:11:328:11 | stl.cpp:323:18:323:23 | AST only | | stl.cpp:331:11:331:11 | stl.cpp:331:13:331:18 | AST only | | stl.cpp:340:8:340:9 | stl.cpp:336:18:336:23 | AST only | +| stl.cpp:344:8:344:9 | stl.cpp:336:18:336:23 | AST only | +| stl.cpp:349:8:349:9 | stl.cpp:347:9:347:14 | AST only | | stl.cpp:353:8:353:9 | stl.cpp:336:18:336:23 | AST only | | stl.cpp:358:8:358:9 | stl.cpp:356:13:356:18 | AST only | | structlikeclass.cpp:35:8:35:9 | structlikeclass.cpp:29:22:29:27 | AST only | From 128b8328b980a49e553b654772bf4ed06ce58578 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 11 Aug 2020 16:16:02 +0100 Subject: [PATCH 036/133] C++: Autoformat. --- .../src/semmle/code/cpp/models/implementations/StdString.qll | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll index 35965fe207d..9d83ef2bd35 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -26,7 +26,8 @@ class StdStringCStr extends TaintFunction { class StdStringPlus extends TaintFunction { StdStringPlus() { this.hasQualifiedName("std", "operator+") and - this.getParameter(0).getType().getUnspecifiedType().(ReferenceType).getBaseType() = any(StdBasicString s).getAnInstantiation() + this.getParameter(0).getType().getUnspecifiedType().(ReferenceType).getBaseType() = + any(StdBasicString s).getAnInstantiation() } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { From 50558257fc98a567e2e31288fa8cbf5b06428382 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 11 Aug 2020 17:05:49 +0100 Subject: [PATCH 037/133] C++: Change note. --- change-notes/1.26/analysis-cpp.md | 1 + 1 file changed, 1 insertion(+) diff --git a/change-notes/1.26/analysis-cpp.md b/change-notes/1.26/analysis-cpp.md index 083229e18c4..01809bf33b5 100644 --- a/change-notes/1.26/analysis-cpp.md +++ b/change-notes/1.26/analysis-cpp.md @@ -17,3 +17,4 @@ The following changes in version 1.26 affect C/C++ analysis in all applications. ## Changes to libraries +* The models library now models more taint flows through `std::string`. From a655124213f9111b055a07ee012526a2d24f6883 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 11 Aug 2020 17:28:31 +0100 Subject: [PATCH 038/133] C++: I think this is more correct. --- cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll index 9d83ef2bd35..4a77e241874 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -36,7 +36,7 @@ class StdStringPlus extends TaintFunction { input.isParameterDeref(0) or input.isParameterDeref(1) ) and - output.isReturnValueDeref() + output.isReturnValue() } } From 1ee96a4b4f43b249a051c05b1f6c0c40a259cc94 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Tue, 11 Aug 2020 11:55:39 +0200 Subject: [PATCH 039/133] C++: SimpleRangeAnalysis: unsigned multiplication --- .../cpp/rangeanalysis/SimpleRangeAnalysis.qll | 22 +++++++++++++++++ .../SimpleRangeAnalysis/lowerBound.expected | 24 +++++++++---------- .../SimpleRangeAnalysis/upperBound.expected | 24 +++++++++---------- .../PointlessComparison/PointlessComparison.c | 4 ++-- 4 files changed, 48 insertions(+), 26 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll index 9ebd2b2219a..e726cafb250 100644 --- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll @@ -156,6 +156,10 @@ float safeFloor(float v) { result = v } +private class UnsignedMulExpr extends MulExpr { + UnsignedMulExpr() { this.getType().(IntegralType).isUnsigned() } +} + /** Set of expressions which we know how to analyze. */ private predicate analyzableExpr(Expr e) { // The type of the expression must be arithmetic. We reuse the logic in @@ -178,6 +182,8 @@ private predicate analyzableExpr(Expr e) { or e instanceof SubExpr or + e instanceof UnsignedMulExpr + or e instanceof AssignExpr or e instanceof AssignAddExpr @@ -278,6 +284,8 @@ private predicate exprDependsOnDef(Expr e, RangeSsaDefinition srcDef, StackVaria or exists(SubExpr subExpr | e = subExpr | exprDependsOnDef(subExpr.getAnOperand(), srcDef, srcVar)) or + exists(UnsignedMulExpr mulExpr | e = mulExpr | exprDependsOnDef(mulExpr.getAnOperand(), srcDef, srcVar)) + or exists(AssignExpr addExpr | e = addExpr | exprDependsOnDef(addExpr.getRValue(), srcDef, srcVar)) or exists(AssignAddExpr addExpr | e = addExpr | @@ -625,6 +633,13 @@ private float getLowerBoundsImpl(Expr expr) { result = addRoundingDown(xLow, -yHigh) ) or + exists(UnsignedMulExpr mulExpr, float xLow, float yLow | + expr = mulExpr and + xLow = getFullyConvertedLowerBounds(mulExpr.getLeftOperand()) and + yLow = getFullyConvertedLowerBounds(mulExpr.getRightOperand()) and + result = xLow * yLow + ) + or exists(AssignExpr assign | expr = assign and result = getFullyConvertedLowerBounds(assign.getRValue()) @@ -794,6 +809,13 @@ private float getUpperBoundsImpl(Expr expr) { result = addRoundingUp(xHigh, -yLow) ) or + exists(UnsignedMulExpr mulExpr, float xHigh, float yHigh | + expr = mulExpr and + xHigh = getFullyConvertedUpperBounds(mulExpr.getLeftOperand()) and + yHigh = getFullyConvertedUpperBounds(mulExpr.getRightOperand()) and + result = xHigh * yHigh + ) + or exists(AssignExpr assign | expr = assign and result = getFullyConvertedUpperBounds(assign.getRValue()) diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected index ebef46d3e2d..b254eb8cf2e 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected @@ -447,40 +447,40 @@ | test.c:433:13:433:13 | a | 3 | | test.c:433:15:433:15 | b | 5 | | test.c:434:5:434:9 | total | 0 | -| test.c:434:14:434:14 | r | -2147483648 | +| test.c:434:14:434:14 | r | 15 | | test.c:436:12:436:12 | a | 0 | | test.c:436:17:436:17 | a | 3 | | test.c:436:33:436:33 | b | 0 | | test.c:436:38:436:38 | b | 0 | | test.c:437:13:437:13 | a | 3 | | test.c:437:15:437:15 | b | 0 | -| test.c:438:5:438:9 | total | -2147483648 | -| test.c:438:14:438:14 | r | -2147483648 | +| test.c:438:5:438:9 | total | 0 | +| test.c:438:14:438:14 | r | 0 | | test.c:440:12:440:12 | a | 0 | | test.c:440:17:440:17 | a | 3 | | test.c:440:34:440:34 | b | 0 | | test.c:440:39:440:39 | b | 13 | | test.c:441:13:441:13 | a | 3 | | test.c:441:15:441:15 | b | 13 | -| test.c:442:5:442:9 | total | -2147483648 | -| test.c:442:14:442:14 | r | -2147483648 | -| test.c:445:10:445:14 | total | -2147483648 | +| test.c:442:5:442:9 | total | 0 | +| test.c:442:14:442:14 | r | 39 | +| test.c:445:10:445:14 | total | 0 | | test.c:451:12:451:12 | b | 0 | | test.c:451:17:451:17 | b | 5 | | test.c:452:16:452:16 | b | 5 | | test.c:453:5:453:9 | total | 0 | -| test.c:453:14:453:14 | r | -2147483648 | +| test.c:453:14:453:14 | r | 55 | | test.c:455:12:455:12 | b | 0 | | test.c:455:17:455:17 | b | 0 | | test.c:456:16:456:16 | b | 0 | -| test.c:457:5:457:9 | total | -2147483648 | -| test.c:457:14:457:14 | r | -2147483648 | +| test.c:457:5:457:9 | total | 0 | +| test.c:457:14:457:14 | r | 0 | | test.c:459:13:459:13 | b | 0 | | test.c:459:18:459:18 | b | 13 | | test.c:460:16:460:16 | b | 13 | -| test.c:461:5:461:9 | total | -2147483648 | -| test.c:461:14:461:14 | r | -2147483648 | -| test.c:464:10:464:14 | total | -2147483648 | +| test.c:461:5:461:9 | total | 0 | +| test.c:461:14:461:14 | r | 143 | +| test.c:464:10:464:14 | total | 0 | | test.cpp:10:7:10:7 | b | -2147483648 | | test.cpp:11:5:11:5 | x | -2147483648 | | test.cpp:13:10:13:10 | x | -2147483648 | diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected index 2b04c8933cc..1552413d112 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected @@ -447,40 +447,40 @@ | test.c:433:13:433:13 | a | 11 | | test.c:433:15:433:15 | b | 23 | | test.c:434:5:434:9 | total | 0 | -| test.c:434:14:434:14 | r | 2147483647 | +| test.c:434:14:434:14 | r | 253 | | test.c:436:12:436:12 | a | 4294967295 | | test.c:436:17:436:17 | a | 4294967295 | | test.c:436:33:436:33 | b | 4294967295 | | test.c:436:38:436:38 | b | 4294967295 | | test.c:437:13:437:13 | a | 11 | | test.c:437:15:437:15 | b | 23 | -| test.c:438:5:438:9 | total | 2147483647 | -| test.c:438:14:438:14 | r | 2147483647 | +| test.c:438:5:438:9 | total | 253 | +| test.c:438:14:438:14 | r | 253 | | test.c:440:12:440:12 | a | 4294967295 | | test.c:440:17:440:17 | a | 4294967295 | | test.c:440:34:440:34 | b | 4294967295 | | test.c:440:39:440:39 | b | 4294967295 | | test.c:441:13:441:13 | a | 11 | | test.c:441:15:441:15 | b | 23 | -| test.c:442:5:442:9 | total | 2147483647 | -| test.c:442:14:442:14 | r | 2147483647 | -| test.c:445:10:445:14 | total | 2147483647 | +| test.c:442:5:442:9 | total | 506 | +| test.c:442:14:442:14 | r | 253 | +| test.c:445:10:445:14 | total | 759 | | test.c:451:12:451:12 | b | 4294967295 | | test.c:451:17:451:17 | b | 4294967295 | | test.c:452:16:452:16 | b | 23 | | test.c:453:5:453:9 | total | 0 | -| test.c:453:14:453:14 | r | 2147483647 | +| test.c:453:14:453:14 | r | 253 | | test.c:455:12:455:12 | b | 4294967295 | | test.c:455:17:455:17 | b | 4294967295 | | test.c:456:16:456:16 | b | 23 | -| test.c:457:5:457:9 | total | 2147483647 | -| test.c:457:14:457:14 | r | 2147483647 | +| test.c:457:5:457:9 | total | 253 | +| test.c:457:14:457:14 | r | 253 | | test.c:459:13:459:13 | b | 4294967295 | | test.c:459:18:459:18 | b | 4294967295 | | test.c:460:16:460:16 | b | 23 | -| test.c:461:5:461:9 | total | 2147483647 | -| test.c:461:14:461:14 | r | 2147483647 | -| test.c:464:10:464:14 | total | 2147483647 | +| test.c:461:5:461:9 | total | 506 | +| test.c:461:14:461:14 | r | 253 | +| test.c:464:10:464:14 | total | 759 | | test.cpp:10:7:10:7 | b | 2147483647 | | test.cpp:11:5:11:5 | x | 2147483647 | | test.cpp:13:10:13:10 | x | 2147483647 | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/PointlessComparison/PointlessComparison.c b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/PointlessComparison/PointlessComparison.c index a2a67402a8e..d9337ca96eb 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/PointlessComparison/PointlessComparison.c +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/PointlessComparison/PointlessComparison.c @@ -385,10 +385,10 @@ void bitwise_ands() void unsigned_mult(unsigned int x, unsigned int y) { if(x < 13 && y < 35) { - if(x * y > 1024) {} // always false [NOT DETECTED] + if(x * y > 1024) {} // always false if(x * y < 204) {} if(x >= 3 && y >= 2) { - if(x * y < 5) {} // always false [NOT DETECTED] + if(x * y < 5) {} // always false } } } \ No newline at end of file From 93d8d8eb1dbf13aaf8a92ff7ffa3559e472b0251 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Tue, 11 Aug 2020 16:28:53 +0200 Subject: [PATCH 040/133] C++: Demonstrate range analysis MulExpr bugs Unless these issues can be reproduced in far less contrived code, I don't think they will cause problems in practice. --- .../SimpleRangeAnalysis/lowerBound.expected | 20 ++++++++++++ .../rangeanalysis/SimpleRangeAnalysis/test.c | 27 ++++++++++++++++ .../SimpleRangeAnalysis/upperBound.expected | 20 ++++++++++++ .../PointlessComparison/PointlessComparison.c | 31 ++++++++++++++++++- .../PointlessComparison.expected | 3 ++ 5 files changed, 100 insertions(+), 1 deletion(-) diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected index b254eb8cf2e..3c0d1f943e8 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected @@ -481,6 +481,26 @@ | test.c:461:5:461:9 | total | 0 | | test.c:461:14:461:14 | r | 143 | | test.c:464:10:464:14 | total | 0 | +| test.c:469:3:469:3 | x | 0 | +| test.c:469:7:469:7 | y | 0 | +| test.c:470:3:470:4 | xy | 0 | +| test.c:470:8:470:8 | x | 1000000003 | +| test.c:470:12:470:12 | y | 1000000003 | +| test.c:471:10:471:11 | xy | 1000000006000000000 | +| test.c:476:3:476:3 | x | 0 | +| test.c:477:3:477:3 | y | 0 | +| test.c:478:3:478:4 | xy | 0 | +| test.c:478:8:478:8 | x | 274177 | +| test.c:478:12:478:12 | y | 67280421310721 | +| test.c:479:10:479:11 | xy | 18446744073709552000 | +| test.c:483:7:483:8 | ui | 0 | +| test.c:484:43:484:44 | ui | 10 | +| test.c:484:48:484:49 | ui | 10 | +| test.c:485:12:485:17 | result | 100 | +| test.c:487:7:487:8 | ul | 0 | +| test.c:488:28:488:29 | ul | 10 | +| test.c:488:33:488:34 | ul | 10 | +| test.c:489:12:489:17 | result | 0 | | test.cpp:10:7:10:7 | b | -2147483648 | | test.cpp:11:5:11:5 | x | -2147483648 | | test.cpp:13:10:13:10 | x | -2147483648 | diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c index 537aee7961d..e85f44b73c2 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c @@ -463,3 +463,30 @@ int test_unsigned_mult02(unsigned b) { return total; } + +unsigned long mult_rounding() { + unsigned long x, y, xy; + x = y = 1000000003UL; // 1e9 + 3 + xy = x * y; + return xy; // BUG: upper bound should be >= 1000000006000000009UL +} + +unsigned long mult_overflow() { + unsigned long x, y, xy; + x = 274177UL; + y = 67280421310721UL; + xy = x * y; + return xy; // BUG: lower bound should be <= 18446744073709551617UL +} + +unsigned long mult_lower_bound(unsigned int ui, unsigned long ul) { + if (ui >= 10) { + unsigned long result = (unsigned long)ui * ui; + return result; // BUG: upper bound should be >= 18446744065119617025 (possibly a pretty-printing bug) + } + if (ul >= 10) { + unsigned long result = ul * ul; + return result; // lower bound is correctly 0 (overflow is possible) + } + return 0; +} diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected index 1552413d112..ca253c03f56 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected @@ -481,6 +481,26 @@ | test.c:461:5:461:9 | total | 506 | | test.c:461:14:461:14 | r | 253 | | test.c:464:10:464:14 | total | 759 | +| test.c:469:3:469:3 | x | 18446744073709552000 | +| test.c:469:7:469:7 | y | 18446744073709552000 | +| test.c:470:3:470:4 | xy | 18446744073709552000 | +| test.c:470:8:470:8 | x | 1000000003 | +| test.c:470:12:470:12 | y | 1000000003 | +| test.c:471:10:471:11 | xy | 1000000006000000000 | +| test.c:476:3:476:3 | x | 18446744073709552000 | +| test.c:477:3:477:3 | y | 18446744073709552000 | +| test.c:478:3:478:4 | xy | 18446744073709552000 | +| test.c:478:8:478:8 | x | 274177 | +| test.c:478:12:478:12 | y | 67280421310721 | +| test.c:479:10:479:11 | xy | 18446744073709552000 | +| test.c:483:7:483:8 | ui | 4294967295 | +| test.c:484:43:484:44 | ui | 4294967295 | +| test.c:484:48:484:49 | ui | 4294967295 | +| test.c:485:12:485:17 | result | 18446744065119617000 | +| test.c:487:7:487:8 | ul | 18446744073709552000 | +| test.c:488:28:488:29 | ul | 18446744073709552000 | +| test.c:488:33:488:34 | ul | 18446744073709552000 | +| test.c:489:12:489:17 | result | 18446744073709552000 | | test.cpp:10:7:10:7 | b | 2147483647 | | test.cpp:11:5:11:5 | x | 2147483647 | | test.cpp:13:10:13:10 | x | 2147483647 | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/PointlessComparison/PointlessComparison.c b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/PointlessComparison/PointlessComparison.c index d9337ca96eb..9fc257e3eeb 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/PointlessComparison/PointlessComparison.c +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/PointlessComparison/PointlessComparison.c @@ -391,4 +391,33 @@ void unsigned_mult(unsigned int x, unsigned int y) { if(x * y < 5) {} // always false } } -} \ No newline at end of file +} + +void mult_rounding() { + unsigned long x, y, xy; + x = y = 1000000003UL; // 1e9 + 3 + xy = 1000000006000000009UL; // x * y, precisely + // Even though the range analysis wrongly considers x*y to be xy - 9, there + // are no PointlessComparison false positives in these tests because alerts + // are suppressed when ulp() < 1, which roughly means that the number is + // larger than 2^53. + if (x * y < xy) {} // always false [NOT DETECTED] + if (x * y > xy) {} // always false [NOT DETECTED] +} + +void mult_overflow() { + unsigned long x, y; + // The following two numbers multiply to 2^64 + 1, which is 1 when truncated + // to 64-bit unsigned. + x = 274177UL; + y = 67280421310721UL; + if (x * y == 1) {} // always true [BUG: reported as always false] + + // This bug appears to be caused by + // `RangeAnalysisUtils::typeUpperBound(unsigned long)` having a result of + // 2**64 + 384, making the range analysis think that the multiplication can't + // overflow. The correct `typeUpperBound` would be 2**64 - 1, but we can't + // represent that with a QL float or int. We could make `typeUpperBound` + // exclusive instead of inclusive, but there is no exclusive upper bound for + // floats. +} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/PointlessComparison/PointlessComparison.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/PointlessComparison/PointlessComparison.expected index c2c6cf6f14d..35ca55120df 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/PointlessComparison/PointlessComparison.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/PointlessComparison/PointlessComparison.expected @@ -41,6 +41,9 @@ | PointlessComparison.c:372:6:372:16 | ... >= ... | Comparison is always true because ... >> ... >= 1. | | PointlessComparison.c:373:6:373:16 | ... >= ... | Comparison is always false because ... >> ... <= 1. | | PointlessComparison.c:383:6:383:17 | ... >= ... | Comparison is always false because ... & ... <= 2. | +| PointlessComparison.c:388:10:388:21 | ... > ... | Comparison is always false because ... * ... <= 408. | +| PointlessComparison.c:391:12:391:20 | ... < ... | Comparison is always false because ... * ... >= 6. | +| PointlessComparison.c:414:7:414:16 | ... == ... | Comparison is always false because ... * ... >= 18446744073709552000. | | PointlessComparison.cpp:36:6:36:33 | ... >= ... | Comparison is always false because ... >> ... <= 9223372036854776000. | | PointlessComparison.cpp:41:6:41:29 | ... >= ... | Comparison is always false because ... >> ... <= 140737488355327.5. | | PointlessComparison.cpp:42:6:42:29 | ... >= ... | Comparison is always false because ... >> ... <= 140737488355327.5. | From b4679cb8cf510a2f56175225690a085a6c98a458 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Wed, 12 Aug 2020 13:09:23 +0200 Subject: [PATCH 041/133] C++: Autoformat fixup --- .../src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll index e726cafb250..56bcb5820f8 100644 --- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll @@ -284,7 +284,9 @@ private predicate exprDependsOnDef(Expr e, RangeSsaDefinition srcDef, StackVaria or exists(SubExpr subExpr | e = subExpr | exprDependsOnDef(subExpr.getAnOperand(), srcDef, srcVar)) or - exists(UnsignedMulExpr mulExpr | e = mulExpr | exprDependsOnDef(mulExpr.getAnOperand(), srcDef, srcVar)) + exists(UnsignedMulExpr mulExpr | e = mulExpr | + exprDependsOnDef(mulExpr.getAnOperand(), srcDef, srcVar) + ) or exists(AssignExpr addExpr | e = addExpr | exprDependsOnDef(addExpr.getRValue(), srcDef, srcVar)) or From b99ca601543cb4db2fa48ae32dee0b23f99e2fd6 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 12 Aug 2020 12:43:28 +0100 Subject: [PATCH 042/133] C++: Address review comments. --- .../code/cpp/models/implementations/StdString.qll | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll index 4a77e241874..17ccfc954b2 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -26,8 +26,7 @@ class StdStringCStr extends TaintFunction { class StdStringPlus extends TaintFunction { StdStringPlus() { this.hasQualifiedName("std", "operator+") and - this.getParameter(0).getType().getUnspecifiedType().(ReferenceType).getBaseType() = - any(StdBasicString s).getAnInstantiation() + this.getUnspecifiedType() = any(StdBasicString s).getAnInstantiation() } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { @@ -49,9 +48,17 @@ class StdStringAppend extends TaintFunction { this.hasQualifiedName("std", "basic_string", "append") } + /** + * Gets the index of a parameter to this function that is a string. + */ + int getAStringParameter() { + getParameter(result).getType() instanceof PointerType or + getParameter(result).getType() instanceof ReferenceType + } + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from parameter to string itself (qualifier) and return value - input.isParameterDeref(0) and + input.isParameterDeref(getAStringParameter()) and ( output.isQualifierObject() or output.isReturnValueDeref() From 1d111c3e1f56e0bbb802e9352ef0c24c3c81b41e Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 12 Aug 2020 14:25:35 +0200 Subject: [PATCH 043/133] expand what urls are detected by `js/incomplete-url-substring-sanitization` --- .../Security/CWE-020/IncompleteUrlSubstringSanitization.ql | 4 ++++ .../CWE-020/IncompleteUrlSubstringSanitization.expected | 2 ++ .../CWE-020/tst-IncompleteUrlSubstringSanitization.js | 6 +++++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql b/javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql index 14115853640..5df0a8c58f5 100644 --- a/javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql +++ b/javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql @@ -43,6 +43,10 @@ where or // target is a HTTP URL to a domain on any TLD target.regexpMatch("(?i)https?://([a-z0-9-]+\\.)+([a-z]+)(:[0-9]+)?/?") + or + // target is a HTTP URL to a domain on any TLD with path elements, and the check is an includes check + check instanceof StringOps::Includes and + target.regexpMatch("(?i)https?://([a-z0-9-]+\\.)+([a-z]+)(:[0-9]+)?/([a-z0-9-]+/?)*") ) and ( if check instanceof StringOps::StartsWith diff --git a/javascript/ql/test/query-tests/Security/CWE-020/IncompleteUrlSubstringSanitization.expected b/javascript/ql/test/query-tests/Security/CWE-020/IncompleteUrlSubstringSanitization.expected index efbaad5a672..ef99aaaefc6 100644 --- a/javascript/ql/test/query-tests/Security/CWE-020/IncompleteUrlSubstringSanitization.expected +++ b/javascript/ql/test/query-tests/Security/CWE-020/IncompleteUrlSubstringSanitization.expected @@ -20,3 +20,5 @@ | tst-IncompleteUrlSubstringSanitization.js:63:4:63:33 | x.index ... !== -1 | '$@' can be anywhere in the URL, and arbitrary hosts may come before or after it. | tst-IncompleteUrlSubstringSanitization.js:63:14:63:25 | "secure.com" | secure.com | | tst-IncompleteUrlSubstringSanitization.js:64:3:64:26 | x.inclu ... e.com") | '$@' can be anywhere in the URL, and arbitrary hosts may come before or after it. | tst-IncompleteUrlSubstringSanitization.js:64:14:64:25 | "secure.com" | secure.com | | tst-IncompleteUrlSubstringSanitization.js:66:6:66:29 | x.inclu ... e.com") | '$@' can be anywhere in the URL, and arbitrary hosts may come before or after it. | tst-IncompleteUrlSubstringSanitization.js:66:17:66:28 | "secure.com" | secure.com | +| tst-IncompleteUrlSubstringSanitization.js:73:5:73:48 | x.index ... ") >= 0 | '$@' can be anywhere in the URL, and arbitrary hosts may come before or after it. | tst-IncompleteUrlSubstringSanitization.js:73:15:73:42 | "https: ... oo/bar" | https://secure.com/foo/bar | +| tst-IncompleteUrlSubstringSanitization.js:74:5:74:40 | x.index ... ") >= 0 | '$@' can be anywhere in the URL, and arbitrary hosts may come before or after it. | tst-IncompleteUrlSubstringSanitization.js:74:15:74:34 | "https://secure.com" | https://secure.com | diff --git a/javascript/ql/test/query-tests/Security/CWE-020/tst-IncompleteUrlSubstringSanitization.js b/javascript/ql/test/query-tests/Security/CWE-020/tst-IncompleteUrlSubstringSanitization.js index f7246c2a401..905a2cadffa 100644 --- a/javascript/ql/test/query-tests/Security/CWE-020/tst-IncompleteUrlSubstringSanitization.js +++ b/javascript/ql/test/query-tests/Security/CWE-020/tst-IncompleteUrlSubstringSanitization.js @@ -67,5 +67,9 @@ } else { doSomeThingWithTrustedURL(x); - } + } + + x.startsWith("https://secure.com/foo/bar"); // OK - the trailing slash makes prefix checks safe. + x.indexOf("https://secure.com/foo/bar") >= 0 // NOT OK - the url can be anywhere in the string. + x.indexOf("https://secure.com") >= 0 // NOT OK }); From dc55ce2bf04ee27d7dcf410e1b0ab2309ccfe244 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 12 Aug 2020 14:27:33 +0200 Subject: [PATCH 044/133] add change note --- change-notes/1.26/analysis-javascript.md | 1 + 1 file changed, 1 insertion(+) diff --git a/change-notes/1.26/analysis-javascript.md b/change-notes/1.26/analysis-javascript.md index 2615bb804d8..f6e95eedcb4 100644 --- a/change-notes/1.26/analysis-javascript.md +++ b/change-notes/1.26/analysis-javascript.md @@ -24,6 +24,7 @@ | **Query** | **Expected impact** | **Change** | |--------------------------------|------------------------------|---------------------------------------------------------------------------| +| Incomplete URL substring sanitization (`js/incomplete-url-substring-sanitization`) | More results | This query now recognizes additional URLs when the substring check is an includes check. | ## Changes to libraries From def1d888c624d5f0e27a14b009f5a41773cf4d35 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 12 Aug 2020 15:22:14 +0200 Subject: [PATCH 045/133] C#: Add body of partial methods --- .../Semmle.Extraction.CSharp/Entities/Method.cs | 4 ++-- .../Semmle.Extraction.CSharp/Entities/OrdinaryMethod.cs | 2 ++ .../Semmle.Extraction.CSharp/Entities/Symbol.cs | 9 +++++---- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs index 982d21b2569..aeb57609b8a 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs @@ -80,7 +80,7 @@ namespace Semmle.Extraction.CSharp.Entities else Expression.Create(Context, expr, this, 0); - Context.NumberOfLines(trapFile, symbol, this); + Context.NumberOfLines(trapFile, BodyDeclaringSymbol, this); }); } @@ -126,7 +126,7 @@ namespace Semmle.Extraction.CSharp.Entities { trapFile.Write('<'); // Encode the nullability of the type arguments in the label. - // Type arguments with different nullability can result in + // Type arguments with different nullability can result in // a constructed method with different nullability of its parameters and return type, // so we need to create a distinct database entity for it. trapFile.BuildList(",", m.symbol.GetAnnotatedTypeArguments(), (ta, tb0) => { AddSignatureTypeToId(m.Context, tb0, m.symbol, ta.Symbol); trapFile.Write((int)ta.Nullability); }); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/OrdinaryMethod.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/OrdinaryMethod.cs index cb12918e72e..23aa8af9721 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/OrdinaryMethod.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/OrdinaryMethod.cs @@ -13,6 +13,8 @@ namespace Semmle.Extraction.CSharp.Entities public override string Name => symbol.GetName(); + protected override IMethodSymbol BodyDeclaringSymbol => symbol.PartialImplementationPart ?? symbol; + public IMethodSymbol SourceDeclaration { get diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Symbol.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Symbol.cs index 4f239083d24..099080705c5 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Symbol.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Symbol.cs @@ -95,14 +95,15 @@ namespace Semmle.Extraction.CSharp.Entities Context.BindComments(this, FullLocation); } + protected virtual T BodyDeclaringSymbol => symbol; + public BlockSyntax Block { get { - return symbol. + return BodyDeclaringSymbol. DeclaringSyntaxReferences. - Select(r => r.GetSyntax()). - SelectMany(n => n.ChildNodes()). + SelectMany(r => r.GetSyntax().ChildNodes()). OfType(). FirstOrDefault(); } @@ -112,7 +113,7 @@ namespace Semmle.Extraction.CSharp.Entities { get { - return symbol. + return BodyDeclaringSymbol. DeclaringSyntaxReferences. SelectMany(r => r.GetSyntax().ChildNodes()). OfType(). From aa6cb51bbac9f2fca2b7d6e558d9f4e1340c0d2f Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 12 Aug 2020 16:55:26 +0100 Subject: [PATCH 046/133] C++: QLDoc SAL.qll. --- cpp/ql/src/Microsoft/SAL.qll | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/Microsoft/SAL.qll b/cpp/ql/src/Microsoft/SAL.qll index 04ea9a9c5fa..f3acc809e0c 100644 --- a/cpp/ql/src/Microsoft/SAL.qll +++ b/cpp/ql/src/Microsoft/SAL.qll @@ -1,5 +1,13 @@ +/** + * Provides classes for identifying and reasoning about Microsoft source code + * annoatation language (SAL) macros. + */ + import cpp +/** + * A SAL macro defined in `sal.h` or a similar header file. + */ class SALMacro extends Macro { SALMacro() { exists(string filename | filename = this.getFile().getBaseName() | @@ -22,25 +30,32 @@ class SALMacro extends Macro { pragma[noinline] predicate isTopLevelMacroAccess(MacroAccess ma) { not exists(ma.getParentInvocation()) } +/** + * An invocation of a SAL macro (excluding invocations inside other macros). + */ class SALAnnotation extends MacroInvocation { SALAnnotation() { this.getMacro() instanceof SALMacro and isTopLevelMacroAccess(this) } - /** Returns the `Declaration` annotated by `this`. */ + /** Gets the `Declaration` annotated by `this`. */ Declaration getDeclaration() { annotatesAt(this, result.getADeclarationEntry(), _, _) and not result instanceof Type // exclude typedefs } - /** Returns the `DeclarationEntry` annotated by `this`. */ + /** Gets the `DeclarationEntry` annotated by `this`. */ DeclarationEntry getDeclarationEntry() { annotatesAt(this, result, _, _) and not result instanceof TypeDeclarationEntry // exclude typedefs } } +/** + * A SAL macro indicating that the return value of a function should always be + * checked. + */ class SALCheckReturn extends SALAnnotation { SALCheckReturn() { exists(SALMacro m | m = this.getMacro() | @@ -50,6 +65,10 @@ class SALCheckReturn extends SALAnnotation { } } +/** + * A SAL macro indicating that a pointer variable or return value should not be + * `NULL`. + */ class SALNotNull extends SALAnnotation { SALNotNull() { exists(SALMacro m | m = this.getMacro() | @@ -69,6 +88,9 @@ class SALNotNull extends SALAnnotation { } } +/** + * A SAL macro indicating that a value may be `NULL`. + */ class SALMaybeNull extends SALAnnotation { SALMaybeNull() { exists(SALMacro m | m = this.getMacro() | From d444778535984753d04486154f7be016a7bba762 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 12 Aug 2020 16:57:43 +0100 Subject: [PATCH 047/133] C++: Make a few things in SAL.qll private where it looks like that was intended (and they're not used outside the file). --- cpp/ql/src/Microsoft/SAL.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/Microsoft/SAL.qll b/cpp/ql/src/Microsoft/SAL.qll index f3acc809e0c..18a14997370 100644 --- a/cpp/ql/src/Microsoft/SAL.qll +++ b/cpp/ql/src/Microsoft/SAL.qll @@ -27,7 +27,7 @@ class SALMacro extends Macro { } } -pragma[noinline] +private pragma[noinline] predicate isTopLevelMacroAccess(MacroAccess ma) { not exists(ma.getParentInvocation()) } /** @@ -107,7 +107,7 @@ class SALMaybeNull extends SALAnnotation { * Holds if `a` annotates the declaration entry `d` and * its start position is the `idx`th position in `file` that holds a SAL element. */ -predicate annotatesAt(SALAnnotation a, DeclarationEntry d, File file, int idx) { +private predicate annotatesAt(SALAnnotation a, DeclarationEntry d, File file, int idx) { annotatesAtPosition(a.(SALElement).getStartPosition(), d, file, idx) } From 9719da864300d3746073acbf2b6168a1b272ca54 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 12 Aug 2020 16:58:50 +0100 Subject: [PATCH 048/133] C++: Move a class that looks like it's intended to be public (and is used outside of the library) above the 'Implementation details' threshold. --- cpp/ql/src/Microsoft/SAL.qll | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/cpp/ql/src/Microsoft/SAL.qll b/cpp/ql/src/Microsoft/SAL.qll index 18a14997370..8276a14a298 100644 --- a/cpp/ql/src/Microsoft/SAL.qll +++ b/cpp/ql/src/Microsoft/SAL.qll @@ -101,6 +101,22 @@ class SALMaybeNull extends SALAnnotation { } } +/** + * A parameter annotated by one or more SAL annotations. + */ +class SALParameter extends Parameter { + /** One of this parameter's annotations. */ + SALAnnotation a; + + SALParameter() { annotatesAt(a, this.getADeclarationEntry(), _, _) } + + predicate isIn() { a.getMacroName().toLowerCase().matches("%\\_in%") } + + predicate isOut() { a.getMacroName().toLowerCase().matches("%\\_out%") } + + predicate isInOut() { a.getMacroName().toLowerCase().matches("%\\_inout%") } +} + /////////////////////////////////////////////////////////////////////////////// // Implementation details /** @@ -131,22 +147,6 @@ private predicate annotatesAtPosition(SALPosition pos, DeclarationEntry d, File ) } -/** - * A parameter annotated by one or more SAL annotations. - */ -class SALParameter extends Parameter { - /** One of this parameter's annotations. */ - SALAnnotation a; - - SALParameter() { annotatesAt(a, this.getADeclarationEntry(), _, _) } - - predicate isIn() { a.getMacroName().toLowerCase().matches("%\\_in%") } - - predicate isOut() { a.getMacroName().toLowerCase().matches("%\\_out%") } - - predicate isInOut() { a.getMacroName().toLowerCase().matches("%\\_inout%") } -} - /** * A SAL element, that is, a SAL annotation or a declaration entry * that may have SAL annotations. From 2655616a0a31123dfac52d9fb4db94cd0d18ccec Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 12 Aug 2020 16:59:15 +0100 Subject: [PATCH 049/133] C++: Autoformat. --- cpp/ql/src/Microsoft/SAL.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/Microsoft/SAL.qll b/cpp/ql/src/Microsoft/SAL.qll index 8276a14a298..c565aa69f2c 100644 --- a/cpp/ql/src/Microsoft/SAL.qll +++ b/cpp/ql/src/Microsoft/SAL.qll @@ -27,8 +27,8 @@ class SALMacro extends Macro { } } -private pragma[noinline] -predicate isTopLevelMacroAccess(MacroAccess ma) { not exists(ma.getParentInvocation()) } +pragma[noinline] +private predicate isTopLevelMacroAccess(MacroAccess ma) { not exists(ma.getParentInvocation()) } /** * An invocation of a SAL macro (excluding invocations inside other macros). From 5e5a112c364261ff1a01029abe4eabfcab0e01dc Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Thu, 13 Aug 2020 08:37:13 +0200 Subject: [PATCH 050/133] C++: Change note --- change-notes/1.26/analysis-cpp.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/change-notes/1.26/analysis-cpp.md b/change-notes/1.26/analysis-cpp.md index 083229e18c4..414637850b4 100644 --- a/change-notes/1.26/analysis-cpp.md +++ b/change-notes/1.26/analysis-cpp.md @@ -14,6 +14,9 @@ The following changes in version 1.26 affect C/C++ analysis in all applications. | **Query** | **Expected impact** | **Change** | |----------------------------|------------------------|------------------------------------------------------------------| | Inconsistent direction of for loop (`cpp/inconsistent-loop-direction`) | Fewer false positive results | The query now accounts for intentional wrapping of an unsigned loop counter. | +| Comparison result is always the same (`cpp/constant-comparison`) | More correct results | Bounds on expressions involving multiplication can now be determined in more cases. | ## Changes to libraries +* The `SimpleRangeAnalysis` library now supports multiplications of the form + `e1 * e2` when `e1` and `e2` are unsigned. From f5abf74e0f3ff43763d2b17dbad5ffaa91d96873 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 13 Aug 2020 09:05:22 +0100 Subject: [PATCH 051/133] Update cpp/ql/src/Microsoft/SAL.qll Co-authored-by: Robert Marsh --- cpp/ql/src/Microsoft/SAL.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/Microsoft/SAL.qll b/cpp/ql/src/Microsoft/SAL.qll index c565aa69f2c..b5185b3c908 100644 --- a/cpp/ql/src/Microsoft/SAL.qll +++ b/cpp/ql/src/Microsoft/SAL.qll @@ -1,6 +1,6 @@ /** * Provides classes for identifying and reasoning about Microsoft source code - * annoatation language (SAL) macros. + * annotation language (SAL) macros. */ import cpp From dc5c0f8e7a72970698a53525ab27b468a18144e4 Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Thu, 13 Aug 2020 10:49:11 +0200 Subject: [PATCH 052/133] Python: Add test case for missing modules --- .../ql/test/query-tests/Imports/general/ImportStarUsed.expected | 1 + .../query-tests/Imports/general/UnintentionalImport.expected | 1 + python/ql/test/query-tests/Imports/general/imports_test.py | 2 ++ 3 files changed, 4 insertions(+) diff --git a/python/ql/test/query-tests/Imports/general/ImportStarUsed.expected b/python/ql/test/query-tests/Imports/general/ImportStarUsed.expected index 9aa101edbca..d29bc2b9b5f 100644 --- a/python/ql/test/query-tests/Imports/general/ImportStarUsed.expected +++ b/python/ql/test/query-tests/Imports/general/ImportStarUsed.expected @@ -1,2 +1,3 @@ | imports_test.py:21:1:21:20 | from module import * | Using 'from ... import *' pollutes the namespace | | imports_test.py:22:1:22:32 | from module_without_all import * | Using 'from ... import *' pollutes the namespace | +| imports_test.py:65:1:65:40 | from module_that_does_not_exist import * | Using 'from ... import *' pollutes the namespace | diff --git a/python/ql/test/query-tests/Imports/general/UnintentionalImport.expected b/python/ql/test/query-tests/Imports/general/UnintentionalImport.expected index 89e48e2f071..235c143873a 100644 --- a/python/ql/test/query-tests/Imports/general/UnintentionalImport.expected +++ b/python/ql/test/query-tests/Imports/general/UnintentionalImport.expected @@ -1 +1,2 @@ | imports_test.py:22:1:22:32 | from module_without_all import * | Import pollutes the enclosing namespace, as the imported module $@ does not define '__all__'. | module_without_all.py:0:0:0:0 | Module module_without_all | module_without_all | +| imports_test.py:65:1:65:40 | from module_that_does_not_exist import * | Import pollutes the enclosing namespace, as the imported module $@ does not define '__all__'. | file://:0:0:0:0 | Missing module module_that_does_not_exist | module_that_does_not_exist | diff --git a/python/ql/test/query-tests/Imports/general/imports_test.py b/python/ql/test/query-tests/Imports/general/imports_test.py index 5e5184b78c7..4b51f8254fc 100644 --- a/python/ql/test/query-tests/Imports/general/imports_test.py +++ b/python/ql/test/query-tests/Imports/general/imports_test.py @@ -61,3 +61,5 @@ import module1 as different #Use it different +# FP reported in https://github.com/github/codeql/issues/4003 +from module_that_does_not_exist import * From a1a1218f95f1161aa9f48bf593ff97d8324ea99b Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Thu, 13 Aug 2020 10:50:28 +0200 Subject: [PATCH 053/133] Python: Ignore `from foo import *` when `foo` is absent. --- python/ql/src/Imports/UnintentionalImport.ql | 2 +- .../query-tests/Imports/general/UnintentionalImport.expected | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/python/ql/src/Imports/UnintentionalImport.ql b/python/ql/src/Imports/UnintentionalImport.ql index dfd751fd527..2a3c2b6460b 100644 --- a/python/ql/src/Imports/UnintentionalImport.ql +++ b/python/ql/src/Imports/UnintentionalImport.ql @@ -26,7 +26,7 @@ predicate all_defined(ModuleValue exporter) { } from ImportStar imp, ModuleValue exporter -where import_star(imp, exporter) and not all_defined(exporter) +where import_star(imp, exporter) and not all_defined(exporter) and not exporter.isAbsent() select imp, "Import pollutes the enclosing namespace, as the imported module $@ does not define '__all__'.", exporter, exporter.getName() diff --git a/python/ql/test/query-tests/Imports/general/UnintentionalImport.expected b/python/ql/test/query-tests/Imports/general/UnintentionalImport.expected index 235c143873a..89e48e2f071 100644 --- a/python/ql/test/query-tests/Imports/general/UnintentionalImport.expected +++ b/python/ql/test/query-tests/Imports/general/UnintentionalImport.expected @@ -1,2 +1 @@ | imports_test.py:22:1:22:32 | from module_without_all import * | Import pollutes the enclosing namespace, as the imported module $@ does not define '__all__'. | module_without_all.py:0:0:0:0 | Module module_without_all | module_without_all | -| imports_test.py:65:1:65:40 | from module_that_does_not_exist import * | Import pollutes the enclosing namespace, as the imported module $@ does not define '__all__'. | file://:0:0:0:0 | Missing module module_that_does_not_exist | module_that_does_not_exist | From 2c7bb8c51f55795d1820650d1f5940ba79516e51 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 13 Aug 2020 11:18:27 +0200 Subject: [PATCH 054/133] adjust error message when files have been found while extracting --- .../extractor/src/com/semmle/js/extractor/AutoBuild.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java index 66cb57ba30f..9992e912043 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java +++ b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java @@ -210,6 +210,7 @@ public class AutoBuild { private final String defaultEncoding; private ExecutorService threadPool; private volatile boolean seenCode = false; + private volatile boolean seenFiles = false; private boolean installDependencies = false; private int installDependenciesTimeout; private final VirtualSourceRoot virtualSourceRoot; @@ -472,7 +473,11 @@ public class AutoBuild { shutdownThreadPool(); } if (!seenCode) { - warn("No JavaScript or TypeScript code found."); + if (seenFiles) { + warn("Only found JavaScript or TypeScript files that were empty or contained syntax errors."); + } else { + warn("No JavaScript or TypeScript code found."); + } return -1; } return 0; @@ -1201,6 +1206,7 @@ protected DependencyInstallationResult preparePackagesAndDependencies(Set long start = logBeginProcess("Extracting " + file); Integer loc = extractor.extract(f, state); if (!extractor.getConfig().isExterns() && (loc == null || loc != 0)) seenCode = true; + if (!extractor.getConfig().isExterns()) seenFiles = true; logEndProcess(start, "Done extracting " + file); } catch (Throwable t) { System.err.println("Exception while extracting " + file + "."); From dc6943b739f0a5603917ebaf5818c4186045cd22 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 13 Aug 2020 11:34:53 +0200 Subject: [PATCH 055/133] Update change-notes/1.26/analysis-javascript.md Co-authored-by: Esben Sparre Andreasen --- change-notes/1.26/analysis-javascript.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/change-notes/1.26/analysis-javascript.md b/change-notes/1.26/analysis-javascript.md index f6e95eedcb4..653d33be915 100644 --- a/change-notes/1.26/analysis-javascript.md +++ b/change-notes/1.26/analysis-javascript.md @@ -24,8 +24,7 @@ | **Query** | **Expected impact** | **Change** | |--------------------------------|------------------------------|---------------------------------------------------------------------------| -| Incomplete URL substring sanitization (`js/incomplete-url-substring-sanitization`) | More results | This query now recognizes additional URLs when the substring check is an includes check. | +| Incomplete URL substring sanitization (`js/incomplete-url-substring-sanitization`) | More results | This query now recognizes additional URLs when the substring check is an inclusion check. | ## Changes to libraries - From 3fb9c2880693d07ed18bd5c762b20ff6a2023f47 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 13 Aug 2020 11:33:31 +0200 Subject: [PATCH 056/133] adjust comment about slash position --- .../Security/CWE-020/tst-IncompleteUrlSubstringSanitization.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/test/query-tests/Security/CWE-020/tst-IncompleteUrlSubstringSanitization.js b/javascript/ql/test/query-tests/Security/CWE-020/tst-IncompleteUrlSubstringSanitization.js index 905a2cadffa..3a812eac0b6 100644 --- a/javascript/ql/test/query-tests/Security/CWE-020/tst-IncompleteUrlSubstringSanitization.js +++ b/javascript/ql/test/query-tests/Security/CWE-020/tst-IncompleteUrlSubstringSanitization.js @@ -69,7 +69,7 @@ doSomeThingWithTrustedURL(x); } - x.startsWith("https://secure.com/foo/bar"); // OK - the trailing slash makes prefix checks safe. + x.startsWith("https://secure.com/foo/bar"); // OK - a forward slash after the domain makes prefix checks safe. x.indexOf("https://secure.com/foo/bar") >= 0 // NOT OK - the url can be anywhere in the string. x.indexOf("https://secure.com") >= 0 // NOT OK }); From 15a74493e0b10209066cad34c56cc1878ad2678c Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 13 Aug 2020 11:45:58 +0200 Subject: [PATCH 057/133] more permissive path elements in `js/incomplete-url-substring-sanitization` --- .../src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql | 2 +- .../CWE-020/IncompleteUrlSubstringSanitization.expected | 1 + .../Security/CWE-020/tst-IncompleteUrlSubstringSanitization.js | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql b/javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql index 5df0a8c58f5..09aad31c96d 100644 --- a/javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql +++ b/javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql @@ -46,7 +46,7 @@ where or // target is a HTTP URL to a domain on any TLD with path elements, and the check is an includes check check instanceof StringOps::Includes and - target.regexpMatch("(?i)https?://([a-z0-9-]+\\.)+([a-z]+)(:[0-9]+)?/([a-z0-9-]+/?)*") + target.regexpMatch("(?i)https?://([a-z0-9-]+\\.)+([a-z]+)(:[0-9]+)?/[a-z0-9/_-]+") ) and ( if check instanceof StringOps::StartsWith diff --git a/javascript/ql/test/query-tests/Security/CWE-020/IncompleteUrlSubstringSanitization.expected b/javascript/ql/test/query-tests/Security/CWE-020/IncompleteUrlSubstringSanitization.expected index ef99aaaefc6..fa1d5872ecb 100644 --- a/javascript/ql/test/query-tests/Security/CWE-020/IncompleteUrlSubstringSanitization.expected +++ b/javascript/ql/test/query-tests/Security/CWE-020/IncompleteUrlSubstringSanitization.expected @@ -22,3 +22,4 @@ | tst-IncompleteUrlSubstringSanitization.js:66:6:66:29 | x.inclu ... e.com") | '$@' can be anywhere in the URL, and arbitrary hosts may come before or after it. | tst-IncompleteUrlSubstringSanitization.js:66:17:66:28 | "secure.com" | secure.com | | tst-IncompleteUrlSubstringSanitization.js:73:5:73:48 | x.index ... ") >= 0 | '$@' can be anywhere in the URL, and arbitrary hosts may come before or after it. | tst-IncompleteUrlSubstringSanitization.js:73:15:73:42 | "https: ... oo/bar" | https://secure.com/foo/bar | | tst-IncompleteUrlSubstringSanitization.js:74:5:74:40 | x.index ... ") >= 0 | '$@' can be anywhere in the URL, and arbitrary hosts may come before or after it. | tst-IncompleteUrlSubstringSanitization.js:74:15:74:34 | "https://secure.com" | https://secure.com | +| tst-IncompleteUrlSubstringSanitization.js:75:5:75:52 | x.index ... ") >= 0 | '$@' can be anywhere in the URL, and arbitrary hosts may come before or after it. | tst-IncompleteUrlSubstringSanitization.js:75:15:75:46 | "https: ... ar-baz" | https://secure.com/foo/bar-baz | diff --git a/javascript/ql/test/query-tests/Security/CWE-020/tst-IncompleteUrlSubstringSanitization.js b/javascript/ql/test/query-tests/Security/CWE-020/tst-IncompleteUrlSubstringSanitization.js index 3a812eac0b6..efbaaff1986 100644 --- a/javascript/ql/test/query-tests/Security/CWE-020/tst-IncompleteUrlSubstringSanitization.js +++ b/javascript/ql/test/query-tests/Security/CWE-020/tst-IncompleteUrlSubstringSanitization.js @@ -72,4 +72,5 @@ x.startsWith("https://secure.com/foo/bar"); // OK - a forward slash after the domain makes prefix checks safe. x.indexOf("https://secure.com/foo/bar") >= 0 // NOT OK - the url can be anywhere in the string. x.indexOf("https://secure.com") >= 0 // NOT OK + x.indexOf("https://secure.com/foo/bar-baz") >= 0 // NOT OK - the url can be anywhere in the string. }); From dcccdee22739f95f389fbfe81efb81766bdfd311 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 12 Aug 2020 21:10:05 +0200 Subject: [PATCH 058/133] C#: Speed up `Implements.qll` and `Unification.qll` Restrict constructed GVN types to those that are complete, and reduce intermediate string construction in `toString()` computations. --- .../ql/src/semmle/code/csharp/Implements.qll | 86 +++++++++++------- .../ql/src/semmle/code/csharp/Unification.qll | 87 ++++++++++++------- 2 files changed, 113 insertions(+), 60 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/Implements.qll b/csharp/ql/src/semmle/code/csharp/Implements.qll index 5ea4b51bfa2..8f577e98872 100644 --- a/csharp/ql/src/semmle/code/csharp/Implements.qll +++ b/csharp/ql/src/semmle/code/csharp/Implements.qll @@ -259,7 +259,7 @@ private module Gvn { private newtype TGvnType = TLeafGvnType(LeafType t) or TMethodTypeParameterGvnType(int i) { i = any(MethodTypeParameter p).getIndex() } or - TConstructedGvnType(ConstructedGvnTypeList l) + TConstructedGvnType(ConstructedGvnTypeList l) { l.isComplete() } private newtype TConstructedGvnTypeList = TConstructedGvnTypeNil(Unification::CompoundTypeKind k) or @@ -334,6 +334,8 @@ private module Gvn { ) } + predicate isComplete() { this.getKind().getNumberOfTypeParameters() - 1 = this.length() } + private GvnType getArg(int i) { exists(GvnType head, ConstructedGvnTypeList tail | this = TConstructedGvnTypeCons(head, tail) @@ -345,47 +347,71 @@ private module Gvn { ) } + private Unification::GenericType getConstructedGenericDeclaringTypeAt(int i) { + i = 0 and + result = this.getKind().getConstructedSourceDeclaration() + or + result = this.getConstructedGenericDeclaringTypeAt(i - 1).getGenericDeclaringType() + } + + private predicate isDeclaringTypeAt(int i) { + exists(this.getConstructedGenericDeclaringTypeAt(i - 1)) + } + /** - * Gets a textual representation of this constructed type, restricted - * to the prefix `t` of the underlying source declaration type. - * - * The `toString()` calculation needs to be split up into prefixes, in - * order to apply the type arguments correctly. For example, a source - * declaration type `A<>.B.C<,>` applied to types `int, string, bool` - * needs to be printed as `A.B.C`. + * Gets the `j`th `toString()` part of the `i`th nested component of this + * constructed type, if any. The nested components are sorted in reverse + * order, while the individual parts are sorted in normal order. */ language[monotonicAggregates] - private string toStringConstructed(Unification::GenericType t) { - t = this.getKind().getConstructedSourceDeclaration().getGenericDeclaringType*() and - exists(int offset, int children, string name, string nameArgs | - offset = t.getNumberOfDeclaringArguments() and - children = t.getNumberOfArgumentsSelf() and - name = Unification::getNameNested(t) and - if children = 0 - then nameArgs = name - else - exists(string offsetArgs | - offsetArgs = - concat(int i | - i in [offset .. offset + children - 1] - | - this.getArg(i).toString(), "," order by i - ) and - nameArgs = name.prefix(name.length() - children - 1) + "<" + offsetArgs + ">" + private string toStringConstructedPart(int i, int j) { + this.isComplete() and + exists(Unification::GenericType t | + t = this.getConstructedGenericDeclaringTypeAt(i) and + exists(int offset, int children, string name | + offset = t.getNumberOfDeclaringArguments() and + children = t.getNumberOfArgumentsSelf() and + name = Unification::getNameNested(t) and + if children = 0 + then + j = 0 and result = name + or + this.isDeclaringTypeAt(i) and j = 1 and result = "." + else ( + j = 0 and result = name.prefix(name.length() - children - 1) + "<" + or + j in [1 .. 2 * children - 1] and + if j % 2 = 0 + then result = "," + else result = this.getArg((j + 1) / 2 + offset - 1).toString() + or + j = 2 * children and + result = ">" + or + this.isDeclaringTypeAt(i) and + j = 2 * children + 1 and + result = "." ) - | - offset = 0 and result = nameArgs - or - result = this.toStringConstructed(t.getGenericDeclaringType()) + "." + nameArgs + ) ) } language[monotonicAggregates] string toString() { + this.isComplete() and exists(Unification::CompoundTypeKind k | k = this.getKind() | result = k.toStringBuiltin(this.getArg(0).toString()) or - result = this.toStringConstructed(k.getConstructedSourceDeclaration()) + result = + strictconcat(int i, int j | + exists(Unification::GenericType t, int children | + t = this.getConstructedGenericDeclaringTypeAt(i) and + children = t.getNumberOfArgumentsSelf() and + if children = 0 then j = 0 else j in [0 .. 2 * children] + ) + | + this.toStringConstructedPart(i, j) order by i desc, j + ) ) } diff --git a/csharp/ql/src/semmle/code/csharp/Unification.qll b/csharp/ql/src/semmle/code/csharp/Unification.qll index 2c7545c7609..795e97164f0 100644 --- a/csharp/ql/src/semmle/code/csharp/Unification.qll +++ b/csharp/ql/src/semmle/code/csharp/Unification.qll @@ -213,6 +213,8 @@ module Gvn { ) } + predicate isComplete() { this.getKind().getNumberOfTypeParameters() - 1 = this.length() } + GvnType getArg(int i) { exists(GvnType head, ConstructedGvnTypeList tail | this = TConstructedGvnTypeCons(head, tail) @@ -224,47 +226,72 @@ module Gvn { ) } + private GenericType getConstructedGenericDeclaringTypeAt(int i) { + i = 0 and + result = this.getKind().getConstructedSourceDeclaration() + or + result = this.getConstructedGenericDeclaringTypeAt(i - 1).getGenericDeclaringType() + } + + private predicate isDeclaringTypeAt(int i) { + exists(this.getConstructedGenericDeclaringTypeAt(i - 1)) + } + /** - * Gets a textual representation of this constructed type, restricted - * to the prefix `t` of the underlying source declaration type. - * - * The `toString()` calculation needs to be split up into prefixes, in - * order to apply the type arguments correctly. For example, a source - * declaration type `A<>.B.C<,>` applied to types `int, string, bool` - * needs to be printed as `A.B.C`. + * Gets the `j`th `toString()` part of the `i`th nested component of this + * constructed type, if any. The nested components are sorted in reverse + * order, while the individual parts are sorted in normal order. */ language[monotonicAggregates] - private string toStringConstructed(GenericType t) { - t = this.getKind().getConstructedSourceDeclaration().getGenericDeclaringType*() and - exists(int offset, int children, string name, string nameArgs | - offset = t.getNumberOfDeclaringArguments() and - children = t.getNumberOfArgumentsSelf() and - name = getNameNested(t) and - if children = 0 - then nameArgs = name - else - exists(string offsetArgs | - offsetArgs = - concat(int i | - i in [offset .. offset + children - 1] - | - this.getArg(i).toString(), "," order by i - ) and - nameArgs = name.prefix(name.length() - children - 1) + "<" + offsetArgs + ">" + private string toStringConstructedPart(int i, int j) { + this.isComplete() and + exists(GenericType t | + t = this.getConstructedGenericDeclaringTypeAt(i) and + exists(int offset, int children, string name | + offset = t.getNumberOfDeclaringArguments() and + children = t.getNumberOfArgumentsSelf() and + name = getNameNested(t) and + if children = 0 + then + j = 0 and result = name + or + this.isDeclaringTypeAt(i) and j = 1 and result = "." + else ( + j = 0 and result = name.prefix(name.length() - children - 1) + "<" + or + j in [1 .. 2 * children - 1] and + if j % 2 = 0 + then result = "," + else result = this.getArg((j + 1) / 2 + offset - 1).toString() + or + j = 2 * children and + result = ">" + or + this.isDeclaringTypeAt(i) and + j = 2 * children + 1 and + result = "." ) - | - offset = 0 and result = nameArgs - or - result = this.toStringConstructed(t.getGenericDeclaringType()) + "." + nameArgs + ) ) } language[monotonicAggregates] string toString() { + this.isComplete() and exists(CompoundTypeKind k | k = this.getKind() | result = k.toStringBuiltin(this.getArg(0).toString()) or - result = this.toStringConstructed(k.getConstructedSourceDeclaration()) + result = + strictconcat(int i, int j, int offset | + exists(GenericType t, int children | + t = this.getConstructedGenericDeclaringTypeAt(i) and + children = t.getNumberOfArgumentsSelf() and + (if this.isDeclaringTypeAt(i) then offset = 1 else offset = 0) and + if children = 0 then j in [0 .. offset] else j in [0 .. 2 * children + offset] + ) + | + this.toStringConstructedPart(i, j) order by i desc, j + ) ) } @@ -482,7 +509,7 @@ module Gvn { newtype TGvnType = TLeafGvnType(LeafType t) or TTypeParameterGvnType() or - TConstructedGvnType(ConstructedGvnTypeList l) + TConstructedGvnType(ConstructedGvnTypeList l) { l.isComplete() } cached newtype TConstructedGvnTypeList = From cca2d9d8253253a8a76f04e548b0169395de489e Mon Sep 17 00:00:00 2001 From: Marcono1234 Date: Thu, 13 Aug 2020 13:12:57 +0200 Subject: [PATCH 059/133] Simplify VarAccess.isLValue() --- java/ql/src/semmle/code/java/Expr.qll | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/java/ql/src/semmle/code/java/Expr.qll b/java/ql/src/semmle/code/java/Expr.qll index 63fc61bf1aa..cb3fcae1873 100755 --- a/java/ql/src/semmle/code/java/Expr.qll +++ b/java/ql/src/semmle/code/java/Expr.qll @@ -1344,10 +1344,7 @@ class VarAccess extends Expr, @varaccess { */ predicate isLValue() { exists(Assignment a | a.getDest() = this) or - exists(PreIncExpr e | e.getExpr() = this) or - exists(PreDecExpr e | e.getExpr() = this) or - exists(PostIncExpr e | e.getExpr() = this) or - exists(PostDecExpr e | e.getExpr() = this) + exists(UnaryAssignExpr e | e.getExpr() = this) } /** From 732a8fa4c9c17fa7a463d397d87d1fca353f59b9 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 13 Aug 2020 12:44:54 +0100 Subject: [PATCH 060/133] C++: Add another member function. --- .../dataflow/taint-tests/localTaint.expected | 538 +++++++++--------- .../dataflow/taint-tests/stl.cpp | 9 + .../dataflow/taint-tests/taint.expected | 60 +- .../dataflow/taint-tests/test_diff.expected | 58 +- .../dataflow/taint-tests/test_ir.expected | 8 +- 5 files changed, 341 insertions(+), 332 deletions(-) diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected index 08fdcd85eeb..a387ca676d6 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -308,277 +308,277 @@ | movableclass.cpp:65:13:65:18 | call to source | movableclass.cpp:65:13:65:20 | call to MyMovableClass | TAINT | | movableclass.cpp:65:13:65:20 | call to MyMovableClass | movableclass.cpp:65:8:65:9 | ref arg s3 | TAINT | | movableclass.cpp:65:13:65:20 | call to MyMovableClass | movableclass.cpp:65:11:65:11 | call to operator= | TAINT | -| stl.cpp:105:12:105:17 | call to source | stl.cpp:109:7:109:7 | a | | -| stl.cpp:106:16:106:20 | 123 | stl.cpp:106:16:106:21 | call to basic_string | TAINT | -| stl.cpp:106:16:106:21 | call to basic_string | stl.cpp:110:7:110:7 | b | | -| stl.cpp:106:16:106:21 | call to basic_string | stl.cpp:112:7:112:7 | b | | -| stl.cpp:107:16:107:21 | call to source | stl.cpp:107:16:107:24 | call to basic_string | TAINT | -| stl.cpp:107:16:107:24 | call to basic_string | stl.cpp:111:7:111:7 | c | | -| stl.cpp:107:16:107:24 | call to basic_string | stl.cpp:113:7:113:7 | c | | -| stl.cpp:112:7:112:7 | b | stl.cpp:112:9:112:13 | call to c_str | TAINT | -| stl.cpp:113:7:113:7 | c | stl.cpp:113:9:113:13 | call to c_str | TAINT | -| stl.cpp:118:20:118:22 | call to basic_stringstream | stl.cpp:121:2:121:4 | ss1 | | -| stl.cpp:118:20:118:22 | call to basic_stringstream | stl.cpp:127:7:127:9 | ss1 | | -| stl.cpp:118:20:118:22 | call to basic_stringstream | stl.cpp:132:7:132:9 | ss1 | | -| stl.cpp:118:25:118:27 | call to basic_stringstream | stl.cpp:122:2:122:4 | ss2 | | -| stl.cpp:118:25:118:27 | call to basic_stringstream | stl.cpp:128:7:128:9 | ss2 | | -| stl.cpp:118:25:118:27 | call to basic_stringstream | stl.cpp:133:7:133:9 | ss2 | | -| stl.cpp:118:30:118:32 | call to basic_stringstream | stl.cpp:123:2:123:4 | ss3 | | -| stl.cpp:118:30:118:32 | call to basic_stringstream | stl.cpp:129:7:129:9 | ss3 | | -| stl.cpp:118:30:118:32 | call to basic_stringstream | stl.cpp:134:7:134:9 | ss3 | | -| stl.cpp:118:35:118:37 | call to basic_stringstream | stl.cpp:124:2:124:4 | ss4 | | -| stl.cpp:118:35:118:37 | call to basic_stringstream | stl.cpp:130:7:130:9 | ss4 | | -| stl.cpp:118:35:118:37 | call to basic_stringstream | stl.cpp:135:7:135:9 | ss4 | | -| stl.cpp:118:40:118:42 | call to basic_stringstream | stl.cpp:125:2:125:4 | ss5 | | -| stl.cpp:118:40:118:42 | call to basic_stringstream | stl.cpp:131:7:131:9 | ss5 | | -| stl.cpp:118:40:118:42 | call to basic_stringstream | stl.cpp:136:7:136:9 | ss5 | | -| stl.cpp:119:16:119:21 | call to source | stl.cpp:119:16:119:24 | call to basic_string | TAINT | -| stl.cpp:119:16:119:24 | call to basic_string | stl.cpp:125:9:125:9 | t | | -| stl.cpp:121:2:121:4 | ref arg ss1 | stl.cpp:127:7:127:9 | ss1 | | -| stl.cpp:121:2:121:4 | ref arg ss1 | stl.cpp:132:7:132:9 | ss1 | | -| stl.cpp:122:2:122:4 | ref arg ss2 | stl.cpp:128:7:128:9 | ss2 | | -| stl.cpp:122:2:122:4 | ref arg ss2 | stl.cpp:133:7:133:9 | ss2 | | -| stl.cpp:123:2:123:4 | ref arg ss3 | stl.cpp:129:7:129:9 | ss3 | | -| stl.cpp:123:2:123:4 | ref arg ss3 | stl.cpp:134:7:134:9 | ss3 | | -| stl.cpp:124:2:124:4 | ref arg ss4 | stl.cpp:130:7:130:9 | ss4 | | -| stl.cpp:124:2:124:4 | ref arg ss4 | stl.cpp:135:7:135:9 | ss4 | | -| stl.cpp:125:2:125:4 | ref arg ss5 | stl.cpp:131:7:131:9 | ss5 | | -| stl.cpp:125:2:125:4 | ref arg ss5 | stl.cpp:136:7:136:9 | ss5 | | -| stl.cpp:139:32:139:37 | source | stl.cpp:144:9:144:14 | source | | -| stl.cpp:141:20:141:22 | call to basic_stringstream | stl.cpp:143:2:143:4 | ss1 | | -| stl.cpp:141:20:141:22 | call to basic_stringstream | stl.cpp:146:7:146:9 | ss1 | | -| stl.cpp:141:20:141:22 | call to basic_stringstream | stl.cpp:148:7:148:9 | ss1 | | -| stl.cpp:141:25:141:27 | call to basic_stringstream | stl.cpp:144:2:144:4 | ss2 | | -| stl.cpp:141:25:141:27 | call to basic_stringstream | stl.cpp:147:7:147:9 | ss2 | | -| stl.cpp:141:25:141:27 | call to basic_stringstream | stl.cpp:149:7:149:9 | ss2 | | -| stl.cpp:143:2:143:4 | ref arg ss1 | stl.cpp:146:7:146:9 | ss1 | | -| stl.cpp:143:2:143:4 | ref arg ss1 | stl.cpp:148:7:148:9 | ss1 | | -| stl.cpp:144:2:144:4 | ref arg ss2 | stl.cpp:147:7:147:9 | ss2 | | -| stl.cpp:144:2:144:4 | ref arg ss2 | stl.cpp:149:7:149:9 | ss2 | | -| stl.cpp:162:16:162:28 | call to basic_string | stl.cpp:163:7:163:11 | path1 | | -| stl.cpp:162:17:162:26 | call to user_input | stl.cpp:162:16:162:28 | call to basic_string | TAINT | -| stl.cpp:163:7:163:11 | path1 | stl.cpp:163:13:163:17 | call to c_str | TAINT | -| stl.cpp:166:10:166:19 | call to user_input | stl.cpp:166:10:166:21 | call to basic_string | TAINT | -| stl.cpp:166:10:166:21 | call to basic_string | stl.cpp:166:2:166:21 | ... = ... | | -| stl.cpp:166:10:166:21 | call to basic_string | stl.cpp:167:7:167:11 | path2 | | -| stl.cpp:167:7:167:11 | path2 | stl.cpp:167:13:167:17 | call to c_str | TAINT | -| stl.cpp:169:15:169:24 | call to user_input | stl.cpp:169:15:169:27 | call to basic_string | TAINT | -| stl.cpp:169:15:169:27 | call to basic_string | stl.cpp:170:7:170:11 | path3 | | -| stl.cpp:170:7:170:11 | path3 | stl.cpp:170:13:170:17 | call to c_str | TAINT | -| stl.cpp:175:19:175:24 | call to source | stl.cpp:178:17:178:18 | cs | | -| stl.cpp:175:19:175:24 | call to source | stl.cpp:180:7:180:8 | cs | | -| stl.cpp:178:17:178:18 | cs | stl.cpp:178:17:178:19 | call to basic_string | TAINT | -| stl.cpp:178:17:178:19 | call to basic_string | stl.cpp:181:7:181:8 | ss | | -| stl.cpp:186:19:186:24 | call to source | stl.cpp:189:17:189:18 | cs | | -| stl.cpp:189:17:189:18 | cs | stl.cpp:189:17:189:19 | call to basic_string | TAINT | -| stl.cpp:189:17:189:19 | call to basic_string | stl.cpp:192:7:192:8 | ss | | -| stl.cpp:189:17:189:19 | call to basic_string | stl.cpp:195:7:195:8 | ss | | -| stl.cpp:192:7:192:8 | ss | stl.cpp:192:10:192:14 | call to c_str | TAINT | -| stl.cpp:192:10:192:14 | call to c_str | stl.cpp:192:2:192:16 | ... = ... | | -| stl.cpp:192:10:192:14 | call to c_str | stl.cpp:194:7:194:8 | cs | | -| stl.cpp:201:18:201:24 | hello | stl.cpp:201:18:201:25 | call to basic_string | TAINT | -| stl.cpp:201:18:201:25 | call to basic_string | stl.cpp:206:8:206:9 | s1 | | -| stl.cpp:202:19:202:26 | call to basic_string | stl.cpp:207:8:207:9 | s2 | | -| stl.cpp:202:20:202:26 | hello | stl.cpp:202:19:202:26 | call to basic_string | TAINT | -| stl.cpp:204:8:204:14 | call to basic_string | stl.cpp:204:3:204:14 | ... = ... | | -| stl.cpp:204:8:204:14 | call to basic_string | stl.cpp:208:8:208:9 | s3 | | -| stl.cpp:204:8:204:14 | hello | stl.cpp:204:8:204:14 | call to basic_string | TAINT | -| stl.cpp:212:18:212:23 | call to source | stl.cpp:212:18:212:26 | call to basic_string | TAINT | -| stl.cpp:212:18:212:26 | call to basic_string | stl.cpp:217:8:217:9 | s1 | | -| stl.cpp:213:19:213:27 | call to basic_string | stl.cpp:218:8:218:9 | s2 | | -| stl.cpp:213:20:213:25 | call to source | stl.cpp:213:19:213:27 | call to basic_string | TAINT | -| stl.cpp:215:8:215:13 | call to source | stl.cpp:215:8:215:15 | call to basic_string | TAINT | -| stl.cpp:215:8:215:15 | call to basic_string | stl.cpp:215:3:215:15 | ... = ... | | -| stl.cpp:215:8:215:15 | call to basic_string | stl.cpp:219:8:219:9 | s3 | | -| stl.cpp:223:15:223:16 | call to basic_string | stl.cpp:224:20:224:21 | s1 | | -| stl.cpp:223:15:223:16 | call to basic_string | stl.cpp:226:8:226:9 | s1 | | -| stl.cpp:223:15:223:16 | call to basic_string | stl.cpp:228:8:228:9 | s1 | | -| stl.cpp:224:20:224:21 | s1 | stl.cpp:229:8:229:9 | s2 | | -| stl.cpp:226:8:226:9 | s1 | stl.cpp:226:3:226:9 | ... = ... | | -| stl.cpp:226:8:226:9 | s1 | stl.cpp:230:8:230:9 | s3 | | -| stl.cpp:234:19:234:40 | call to basic_string | stl.cpp:238:8:238:9 | s1 | | -| stl.cpp:234:32:234:37 | call to source | stl.cpp:234:19:234:40 | call to basic_string | TAINT | -| stl.cpp:236:8:236:28 | call to basic_string | stl.cpp:236:3:236:28 | ... = ... | | -| stl.cpp:236:8:236:28 | call to basic_string | stl.cpp:239:8:239:9 | s2 | | -| stl.cpp:236:20:236:25 | call to source | stl.cpp:236:8:236:28 | call to basic_string | TAINT | -| stl.cpp:246:16:246:21 | call to source | stl.cpp:246:16:246:24 | call to basic_string | TAINT | -| stl.cpp:246:16:246:24 | call to basic_string | stl.cpp:247:15:247:15 | s | | -| stl.cpp:246:16:246:24 | call to basic_string | stl.cpp:251:33:251:33 | s | | -| stl.cpp:246:16:246:24 | call to basic_string | stl.cpp:251:50:251:50 | s | | -| stl.cpp:246:16:246:24 | call to basic_string | stl.cpp:255:16:255:16 | s | | -| stl.cpp:247:15:247:15 | call to begin | stl.cpp:247:15:247:15 | (__begin) | | -| stl.cpp:247:15:247:15 | call to begin | stl.cpp:247:15:247:15 | (__begin) | | -| stl.cpp:247:15:247:15 | call to begin | stl.cpp:247:15:247:15 | (__begin) | | -| stl.cpp:247:15:247:15 | call to end | stl.cpp:247:15:247:15 | (__end) | | -| stl.cpp:247:15:247:15 | call to operator* | stl.cpp:248:8:248:8 | c | | -| stl.cpp:247:15:247:15 | ref arg (__begin) | stl.cpp:247:15:247:15 | (__begin) | | -| stl.cpp:247:15:247:15 | ref arg (__begin) | stl.cpp:247:15:247:15 | (__begin) | | -| stl.cpp:247:15:247:15 | ref arg (__begin) | stl.cpp:247:15:247:15 | (__begin) | | -| stl.cpp:247:15:247:15 | ref arg (__range) | stl.cpp:247:15:247:15 | (__range) | | -| stl.cpp:247:15:247:15 | s | stl.cpp:247:15:247:15 | (__range) | | -| stl.cpp:247:15:247:15 | s | stl.cpp:247:15:247:15 | (__range) | | -| stl.cpp:247:15:247:15 | s | stl.cpp:247:15:247:15 | call to operator* | TAINT | -| stl.cpp:251:33:251:33 | ref arg s | stl.cpp:251:50:251:50 | s | | -| stl.cpp:251:33:251:33 | ref arg s | stl.cpp:255:16:255:16 | s | | -| stl.cpp:251:35:251:39 | call to begin | stl.cpp:251:44:251:45 | it | | -| stl.cpp:251:35:251:39 | call to begin | stl.cpp:251:61:251:62 | it | | -| stl.cpp:251:35:251:39 | call to begin | stl.cpp:252:9:252:10 | it | | -| stl.cpp:251:50:251:50 | ref arg s | stl.cpp:251:50:251:50 | s | | -| stl.cpp:251:50:251:50 | ref arg s | stl.cpp:255:16:255:16 | s | | -| stl.cpp:251:61:251:62 | ref arg it | stl.cpp:251:44:251:45 | it | | -| stl.cpp:251:61:251:62 | ref arg it | stl.cpp:251:61:251:62 | it | | -| stl.cpp:251:61:251:62 | ref arg it | stl.cpp:252:9:252:10 | it | | -| stl.cpp:255:16:255:16 | call to begin | stl.cpp:255:16:255:16 | (__begin) | | -| stl.cpp:255:16:255:16 | call to begin | stl.cpp:255:16:255:16 | (__begin) | | -| stl.cpp:255:16:255:16 | call to begin | stl.cpp:255:16:255:16 | (__begin) | | -| stl.cpp:255:16:255:16 | call to end | stl.cpp:255:16:255:16 | (__end) | | -| stl.cpp:255:16:255:16 | call to operator* | stl.cpp:256:8:256:8 | c | | -| stl.cpp:255:16:255:16 | ref arg (__begin) | stl.cpp:255:16:255:16 | (__begin) | | -| stl.cpp:255:16:255:16 | ref arg (__begin) | stl.cpp:255:16:255:16 | (__begin) | | -| stl.cpp:255:16:255:16 | ref arg (__begin) | stl.cpp:255:16:255:16 | (__begin) | | -| stl.cpp:255:16:255:16 | ref arg (__range) | stl.cpp:255:16:255:16 | (__range) | | -| stl.cpp:255:16:255:16 | s | stl.cpp:255:16:255:16 | (__range) | | -| stl.cpp:255:16:255:16 | s | stl.cpp:255:16:255:16 | (__range) | | -| stl.cpp:255:16:255:16 | s | stl.cpp:255:16:255:16 | call to operator* | TAINT | -| stl.cpp:259:28:259:33 | call to source | stl.cpp:259:28:259:36 | call to basic_string | TAINT | -| stl.cpp:259:28:259:36 | call to basic_string | stl.cpp:260:22:260:28 | const_s | | -| stl.cpp:260:22:260:22 | call to begin | stl.cpp:260:22:260:22 | (__begin) | | -| stl.cpp:260:22:260:22 | call to begin | stl.cpp:260:22:260:22 | (__begin) | | -| stl.cpp:260:22:260:22 | call to begin | stl.cpp:260:22:260:22 | (__begin) | | -| stl.cpp:260:22:260:22 | call to end | stl.cpp:260:22:260:22 | (__end) | | -| stl.cpp:260:22:260:22 | call to operator* | stl.cpp:261:8:261:8 | c | | -| stl.cpp:260:22:260:22 | ref arg (__begin) | stl.cpp:260:22:260:22 | (__begin) | | -| stl.cpp:260:22:260:22 | ref arg (__begin) | stl.cpp:260:22:260:22 | (__begin) | | -| stl.cpp:260:22:260:22 | ref arg (__begin) | stl.cpp:260:22:260:22 | (__begin) | | -| stl.cpp:260:22:260:28 | const_s | stl.cpp:260:22:260:22 | (__range) | | -| stl.cpp:260:22:260:28 | const_s | stl.cpp:260:22:260:22 | (__range) | | -| stl.cpp:260:22:260:28 | const_s | stl.cpp:260:22:260:22 | call to operator* | TAINT | -| stl.cpp:296:43:296:49 | source1 | stl.cpp:300:21:300:27 | source1 | | -| stl.cpp:296:43:296:49 | source1 | stl.cpp:314:33:314:39 | source1 | | -| stl.cpp:300:21:300:27 | source1 | stl.cpp:300:21:300:28 | call to vector | TAINT | -| stl.cpp:300:21:300:28 | call to vector | stl.cpp:302:14:302:14 | v | | -| stl.cpp:300:21:300:28 | call to vector | stl.cpp:306:38:306:38 | v | | -| stl.cpp:300:21:300:28 | call to vector | stl.cpp:306:55:306:55 | v | | -| stl.cpp:300:21:300:28 | call to vector | stl.cpp:310:15:310:15 | v | | -| stl.cpp:302:14:302:14 | call to begin | stl.cpp:302:14:302:14 | (__begin) | | -| stl.cpp:302:14:302:14 | call to begin | stl.cpp:302:14:302:14 | (__begin) | | -| stl.cpp:302:14:302:14 | call to begin | stl.cpp:302:14:302:14 | (__begin) | | -| stl.cpp:302:14:302:14 | call to end | stl.cpp:302:14:302:14 | (__end) | | -| stl.cpp:302:14:302:14 | call to operator* | stl.cpp:303:8:303:8 | x | | -| stl.cpp:302:14:302:14 | ref arg (__begin) | stl.cpp:302:14:302:14 | (__begin) | | -| stl.cpp:302:14:302:14 | ref arg (__begin) | stl.cpp:302:14:302:14 | (__begin) | | -| stl.cpp:302:14:302:14 | ref arg (__begin) | stl.cpp:302:14:302:14 | (__begin) | | -| stl.cpp:302:14:302:14 | ref arg (__range) | stl.cpp:302:14:302:14 | (__range) | | -| stl.cpp:302:14:302:14 | v | stl.cpp:302:14:302:14 | (__range) | | -| stl.cpp:302:14:302:14 | v | stl.cpp:302:14:302:14 | (__range) | | -| stl.cpp:302:14:302:14 | v | stl.cpp:302:14:302:14 | call to operator* | TAINT | -| stl.cpp:306:38:306:38 | ref arg v | stl.cpp:306:55:306:55 | v | | -| stl.cpp:306:38:306:38 | ref arg v | stl.cpp:310:15:310:15 | v | | -| stl.cpp:306:40:306:44 | call to begin | stl.cpp:306:49:306:50 | it | | -| stl.cpp:306:40:306:44 | call to begin | stl.cpp:306:66:306:67 | it | | -| stl.cpp:306:40:306:44 | call to begin | stl.cpp:307:9:307:10 | it | | -| stl.cpp:306:55:306:55 | ref arg v | stl.cpp:306:55:306:55 | v | | -| stl.cpp:306:55:306:55 | ref arg v | stl.cpp:310:15:310:15 | v | | -| stl.cpp:306:66:306:67 | ref arg it | stl.cpp:306:49:306:50 | it | | -| stl.cpp:306:66:306:67 | ref arg it | stl.cpp:306:66:306:67 | it | | -| stl.cpp:306:66:306:67 | ref arg it | stl.cpp:307:9:307:10 | it | | -| stl.cpp:310:15:310:15 | call to begin | stl.cpp:310:15:310:15 | (__begin) | | -| stl.cpp:310:15:310:15 | call to begin | stl.cpp:310:15:310:15 | (__begin) | | -| stl.cpp:310:15:310:15 | call to begin | stl.cpp:310:15:310:15 | (__begin) | | -| stl.cpp:310:15:310:15 | call to end | stl.cpp:310:15:310:15 | (__end) | | -| stl.cpp:310:15:310:15 | call to operator* | stl.cpp:311:8:311:8 | x | | -| stl.cpp:310:15:310:15 | ref arg (__begin) | stl.cpp:310:15:310:15 | (__begin) | | -| stl.cpp:310:15:310:15 | ref arg (__begin) | stl.cpp:310:15:310:15 | (__begin) | | -| stl.cpp:310:15:310:15 | ref arg (__begin) | stl.cpp:310:15:310:15 | (__begin) | | -| stl.cpp:310:15:310:15 | ref arg (__range) | stl.cpp:310:15:310:15 | (__range) | | -| stl.cpp:310:15:310:15 | v | stl.cpp:310:15:310:15 | (__range) | | -| stl.cpp:310:15:310:15 | v | stl.cpp:310:15:310:15 | (__range) | | -| stl.cpp:310:15:310:15 | v | stl.cpp:310:15:310:15 | call to operator* | TAINT | -| stl.cpp:314:33:314:39 | source1 | stl.cpp:314:33:314:40 | call to vector | TAINT | -| stl.cpp:314:33:314:40 | call to vector | stl.cpp:315:21:315:27 | const_v | | -| stl.cpp:315:21:315:21 | call to begin | stl.cpp:315:21:315:21 | (__begin) | | -| stl.cpp:315:21:315:21 | call to begin | stl.cpp:315:21:315:21 | (__begin) | | -| stl.cpp:315:21:315:21 | call to begin | stl.cpp:315:21:315:21 | (__begin) | | -| stl.cpp:315:21:315:21 | call to end | stl.cpp:315:21:315:21 | (__end) | | -| stl.cpp:315:21:315:21 | call to operator* | stl.cpp:316:8:316:8 | x | | -| stl.cpp:315:21:315:21 | ref arg (__begin) | stl.cpp:315:21:315:21 | (__begin) | | -| stl.cpp:315:21:315:21 | ref arg (__begin) | stl.cpp:315:21:315:21 | (__begin) | | -| stl.cpp:315:21:315:21 | ref arg (__begin) | stl.cpp:315:21:315:21 | (__begin) | | -| stl.cpp:315:21:315:27 | const_v | stl.cpp:315:21:315:21 | (__range) | | -| stl.cpp:315:21:315:27 | const_v | stl.cpp:315:21:315:21 | (__range) | | -| stl.cpp:315:21:315:27 | const_v | stl.cpp:315:21:315:21 | call to operator* | TAINT | -| stl.cpp:322:18:322:24 | hello | stl.cpp:322:18:322:25 | call to basic_string | TAINT | -| stl.cpp:322:18:322:25 | call to basic_string | stl.cpp:325:8:325:9 | s1 | | -| stl.cpp:322:18:322:25 | call to basic_string | stl.cpp:325:13:325:14 | s1 | | -| stl.cpp:322:18:322:25 | call to basic_string | stl.cpp:326:8:326:9 | s1 | | -| stl.cpp:322:18:322:25 | call to basic_string | stl.cpp:327:13:327:14 | s1 | | -| stl.cpp:322:18:322:25 | call to basic_string | stl.cpp:330:8:330:9 | s1 | | -| stl.cpp:322:18:322:25 | call to basic_string | stl.cpp:331:8:331:9 | s1 | | -| stl.cpp:323:18:323:23 | call to source | stl.cpp:323:18:323:26 | call to basic_string | TAINT | -| stl.cpp:323:18:323:26 | call to basic_string | stl.cpp:326:13:326:14 | s2 | | -| stl.cpp:323:18:323:26 | call to basic_string | stl.cpp:327:8:327:9 | s2 | | -| stl.cpp:323:18:323:26 | call to basic_string | stl.cpp:328:8:328:9 | s2 | | -| stl.cpp:323:18:323:26 | call to basic_string | stl.cpp:328:13:328:14 | s2 | | -| stl.cpp:325:8:325:9 | s1 | stl.cpp:325:11:325:11 | call to operator+ | TAINT | -| stl.cpp:325:13:325:14 | s1 | stl.cpp:325:11:325:11 | call to operator+ | TAINT | -| stl.cpp:326:8:326:9 | s1 | stl.cpp:326:11:326:11 | call to operator+ | TAINT | -| stl.cpp:326:13:326:14 | s2 | stl.cpp:326:11:326:11 | call to operator+ | TAINT | -| stl.cpp:327:8:327:9 | s2 | stl.cpp:327:11:327:11 | call to operator+ | TAINT | -| stl.cpp:327:13:327:14 | s1 | stl.cpp:327:11:327:11 | call to operator+ | TAINT | -| stl.cpp:328:8:328:9 | s2 | stl.cpp:328:11:328:11 | call to operator+ | TAINT | -| stl.cpp:328:13:328:14 | s2 | stl.cpp:328:11:328:11 | call to operator+ | TAINT | -| stl.cpp:330:8:330:9 | s1 | stl.cpp:330:11:330:11 | call to operator+ | TAINT | -| stl.cpp:330:13:330:20 | world | stl.cpp:330:11:330:11 | call to operator+ | TAINT | -| stl.cpp:331:8:331:9 | s1 | stl.cpp:331:11:331:11 | call to operator+ | TAINT | -| stl.cpp:331:13:331:18 | call to source | stl.cpp:331:11:331:11 | call to operator+ | TAINT | -| stl.cpp:335:18:335:22 | abc | stl.cpp:335:18:335:23 | call to basic_string | TAINT | -| stl.cpp:335:18:335:23 | call to basic_string | stl.cpp:339:8:339:9 | s3 | | -| stl.cpp:335:18:335:23 | call to basic_string | stl.cpp:342:8:342:9 | s3 | | -| stl.cpp:335:18:335:23 | call to basic_string | stl.cpp:346:8:346:9 | s3 | | -| stl.cpp:335:18:335:23 | call to basic_string | stl.cpp:351:8:351:9 | s3 | | -| stl.cpp:335:18:335:23 | call to basic_string | stl.cpp:355:8:355:9 | s3 | | -| stl.cpp:336:18:336:23 | call to source | stl.cpp:336:18:336:26 | call to basic_string | TAINT | -| stl.cpp:336:18:336:26 | call to basic_string | stl.cpp:339:13:339:14 | s4 | | -| stl.cpp:336:18:336:26 | call to basic_string | stl.cpp:343:9:343:10 | s4 | | -| stl.cpp:336:18:336:26 | call to basic_string | stl.cpp:352:13:352:14 | s4 | | -| stl.cpp:339:8:339:9 | s3 | stl.cpp:339:11:339:11 | call to operator+ | TAINT | -| stl.cpp:339:11:339:11 | call to operator+ | stl.cpp:339:3:339:14 | ... = ... | | -| stl.cpp:339:11:339:11 | call to operator+ | stl.cpp:340:8:340:9 | s5 | | -| stl.cpp:339:13:339:14 | s4 | stl.cpp:339:11:339:11 | call to operator+ | TAINT | -| stl.cpp:342:8:342:9 | s3 | stl.cpp:342:3:342:9 | ... = ... | | -| stl.cpp:342:8:342:9 | s3 | stl.cpp:343:3:343:4 | s6 | | -| stl.cpp:342:8:342:9 | s3 | stl.cpp:344:8:344:9 | s6 | | -| stl.cpp:343:3:343:4 | ref arg s6 | stl.cpp:344:8:344:9 | s6 | | -| stl.cpp:343:9:343:10 | s4 | stl.cpp:343:3:343:4 | ref arg s6 | TAINT | -| stl.cpp:343:9:343:10 | s4 | stl.cpp:343:6:343:6 | call to operator+= | TAINT | -| stl.cpp:346:8:346:9 | s3 | stl.cpp:346:3:346:9 | ... = ... | | -| stl.cpp:346:8:346:9 | s3 | stl.cpp:347:3:347:4 | s7 | | -| stl.cpp:346:8:346:9 | s3 | stl.cpp:348:3:348:4 | s7 | | -| stl.cpp:346:8:346:9 | s3 | stl.cpp:349:8:349:9 | s7 | | -| stl.cpp:347:3:347:4 | ref arg s7 | stl.cpp:348:3:348:4 | s7 | | -| stl.cpp:347:3:347:4 | ref arg s7 | stl.cpp:349:8:349:9 | s7 | | -| stl.cpp:347:9:347:14 | call to source | stl.cpp:347:3:347:4 | ref arg s7 | TAINT | -| stl.cpp:347:9:347:14 | call to source | stl.cpp:347:6:347:6 | call to operator+= | TAINT | -| stl.cpp:348:3:348:4 | ref arg s7 | stl.cpp:349:8:349:9 | s7 | | -| stl.cpp:348:9:348:11 | | stl.cpp:348:3:348:4 | ref arg s7 | TAINT | -| stl.cpp:348:9:348:11 | | stl.cpp:348:6:348:6 | call to operator+= | TAINT | +| stl.cpp:109:12:109:17 | call to source | stl.cpp:113:7:113:7 | a | | +| stl.cpp:110:16:110:20 | 123 | stl.cpp:110:16:110:21 | call to basic_string | TAINT | +| stl.cpp:110:16:110:21 | call to basic_string | stl.cpp:114:7:114:7 | b | | +| stl.cpp:110:16:110:21 | call to basic_string | stl.cpp:116:7:116:7 | b | | +| stl.cpp:111:16:111:21 | call to source | stl.cpp:111:16:111:24 | call to basic_string | TAINT | +| stl.cpp:111:16:111:24 | call to basic_string | stl.cpp:115:7:115:7 | c | | +| stl.cpp:111:16:111:24 | call to basic_string | stl.cpp:117:7:117:7 | c | | +| stl.cpp:116:7:116:7 | b | stl.cpp:116:9:116:13 | call to c_str | TAINT | +| stl.cpp:117:7:117:7 | c | stl.cpp:117:9:117:13 | call to c_str | TAINT | +| stl.cpp:122:20:122:22 | call to basic_stringstream | stl.cpp:125:2:125:4 | ss1 | | +| stl.cpp:122:20:122:22 | call to basic_stringstream | stl.cpp:131:7:131:9 | ss1 | | +| stl.cpp:122:20:122:22 | call to basic_stringstream | stl.cpp:136:7:136:9 | ss1 | | +| stl.cpp:122:25:122:27 | call to basic_stringstream | stl.cpp:126:2:126:4 | ss2 | | +| stl.cpp:122:25:122:27 | call to basic_stringstream | stl.cpp:132:7:132:9 | ss2 | | +| stl.cpp:122:25:122:27 | call to basic_stringstream | stl.cpp:137:7:137:9 | ss2 | | +| stl.cpp:122:30:122:32 | call to basic_stringstream | stl.cpp:127:2:127:4 | ss3 | | +| stl.cpp:122:30:122:32 | call to basic_stringstream | stl.cpp:133:7:133:9 | ss3 | | +| stl.cpp:122:30:122:32 | call to basic_stringstream | stl.cpp:138:7:138:9 | ss3 | | +| stl.cpp:122:35:122:37 | call to basic_stringstream | stl.cpp:128:2:128:4 | ss4 | | +| stl.cpp:122:35:122:37 | call to basic_stringstream | stl.cpp:134:7:134:9 | ss4 | | +| stl.cpp:122:35:122:37 | call to basic_stringstream | stl.cpp:139:7:139:9 | ss4 | | +| stl.cpp:122:40:122:42 | call to basic_stringstream | stl.cpp:129:2:129:4 | ss5 | | +| stl.cpp:122:40:122:42 | call to basic_stringstream | stl.cpp:135:7:135:9 | ss5 | | +| stl.cpp:122:40:122:42 | call to basic_stringstream | stl.cpp:140:7:140:9 | ss5 | | +| stl.cpp:123:16:123:21 | call to source | stl.cpp:123:16:123:24 | call to basic_string | TAINT | +| stl.cpp:123:16:123:24 | call to basic_string | stl.cpp:129:9:129:9 | t | | +| stl.cpp:125:2:125:4 | ref arg ss1 | stl.cpp:131:7:131:9 | ss1 | | +| stl.cpp:125:2:125:4 | ref arg ss1 | stl.cpp:136:7:136:9 | ss1 | | +| stl.cpp:126:2:126:4 | ref arg ss2 | stl.cpp:132:7:132:9 | ss2 | | +| stl.cpp:126:2:126:4 | ref arg ss2 | stl.cpp:137:7:137:9 | ss2 | | +| stl.cpp:127:2:127:4 | ref arg ss3 | stl.cpp:133:7:133:9 | ss3 | | +| stl.cpp:127:2:127:4 | ref arg ss3 | stl.cpp:138:7:138:9 | ss3 | | +| stl.cpp:128:2:128:4 | ref arg ss4 | stl.cpp:134:7:134:9 | ss4 | | +| stl.cpp:128:2:128:4 | ref arg ss4 | stl.cpp:139:7:139:9 | ss4 | | +| stl.cpp:129:2:129:4 | ref arg ss5 | stl.cpp:135:7:135:9 | ss5 | | +| stl.cpp:129:2:129:4 | ref arg ss5 | stl.cpp:140:7:140:9 | ss5 | | +| stl.cpp:143:32:143:37 | source | stl.cpp:148:9:148:14 | source | | +| stl.cpp:145:20:145:22 | call to basic_stringstream | stl.cpp:147:2:147:4 | ss1 | | +| stl.cpp:145:20:145:22 | call to basic_stringstream | stl.cpp:150:7:150:9 | ss1 | | +| stl.cpp:145:20:145:22 | call to basic_stringstream | stl.cpp:152:7:152:9 | ss1 | | +| stl.cpp:145:25:145:27 | call to basic_stringstream | stl.cpp:148:2:148:4 | ss2 | | +| stl.cpp:145:25:145:27 | call to basic_stringstream | stl.cpp:151:7:151:9 | ss2 | | +| stl.cpp:145:25:145:27 | call to basic_stringstream | stl.cpp:153:7:153:9 | ss2 | | +| stl.cpp:147:2:147:4 | ref arg ss1 | stl.cpp:150:7:150:9 | ss1 | | +| stl.cpp:147:2:147:4 | ref arg ss1 | stl.cpp:152:7:152:9 | ss1 | | +| stl.cpp:148:2:148:4 | ref arg ss2 | stl.cpp:151:7:151:9 | ss2 | | +| stl.cpp:148:2:148:4 | ref arg ss2 | stl.cpp:153:7:153:9 | ss2 | | +| stl.cpp:166:16:166:28 | call to basic_string | stl.cpp:167:7:167:11 | path1 | | +| stl.cpp:166:17:166:26 | call to user_input | stl.cpp:166:16:166:28 | call to basic_string | TAINT | +| stl.cpp:167:7:167:11 | path1 | stl.cpp:167:13:167:17 | call to c_str | TAINT | +| stl.cpp:170:10:170:19 | call to user_input | stl.cpp:170:10:170:21 | call to basic_string | TAINT | +| stl.cpp:170:10:170:21 | call to basic_string | stl.cpp:170:2:170:21 | ... = ... | | +| stl.cpp:170:10:170:21 | call to basic_string | stl.cpp:171:7:171:11 | path2 | | +| stl.cpp:171:7:171:11 | path2 | stl.cpp:171:13:171:17 | call to c_str | TAINT | +| stl.cpp:173:15:173:24 | call to user_input | stl.cpp:173:15:173:27 | call to basic_string | TAINT | +| stl.cpp:173:15:173:27 | call to basic_string | stl.cpp:174:7:174:11 | path3 | | +| stl.cpp:174:7:174:11 | path3 | stl.cpp:174:13:174:17 | call to c_str | TAINT | +| stl.cpp:179:19:179:24 | call to source | stl.cpp:182:17:182:18 | cs | | +| stl.cpp:179:19:179:24 | call to source | stl.cpp:184:7:184:8 | cs | | +| stl.cpp:182:17:182:18 | cs | stl.cpp:182:17:182:19 | call to basic_string | TAINT | +| stl.cpp:182:17:182:19 | call to basic_string | stl.cpp:185:7:185:8 | ss | | +| stl.cpp:190:19:190:24 | call to source | stl.cpp:193:17:193:18 | cs | | +| stl.cpp:193:17:193:18 | cs | stl.cpp:193:17:193:19 | call to basic_string | TAINT | +| stl.cpp:193:17:193:19 | call to basic_string | stl.cpp:196:7:196:8 | ss | | +| stl.cpp:193:17:193:19 | call to basic_string | stl.cpp:199:7:199:8 | ss | | +| stl.cpp:196:7:196:8 | ss | stl.cpp:196:10:196:14 | call to c_str | TAINT | +| stl.cpp:196:10:196:14 | call to c_str | stl.cpp:196:2:196:16 | ... = ... | | +| stl.cpp:196:10:196:14 | call to c_str | stl.cpp:198:7:198:8 | cs | | +| stl.cpp:205:18:205:24 | hello | stl.cpp:205:18:205:25 | call to basic_string | TAINT | +| stl.cpp:205:18:205:25 | call to basic_string | stl.cpp:210:8:210:9 | s1 | | +| stl.cpp:206:19:206:26 | call to basic_string | stl.cpp:211:8:211:9 | s2 | | +| stl.cpp:206:20:206:26 | hello | stl.cpp:206:19:206:26 | call to basic_string | TAINT | +| stl.cpp:208:8:208:14 | call to basic_string | stl.cpp:208:3:208:14 | ... = ... | | +| stl.cpp:208:8:208:14 | call to basic_string | stl.cpp:212:8:212:9 | s3 | | +| stl.cpp:208:8:208:14 | hello | stl.cpp:208:8:208:14 | call to basic_string | TAINT | +| stl.cpp:216:18:216:23 | call to source | stl.cpp:216:18:216:26 | call to basic_string | TAINT | +| stl.cpp:216:18:216:26 | call to basic_string | stl.cpp:221:8:221:9 | s1 | | +| stl.cpp:217:19:217:27 | call to basic_string | stl.cpp:222:8:222:9 | s2 | | +| stl.cpp:217:20:217:25 | call to source | stl.cpp:217:19:217:27 | call to basic_string | TAINT | +| stl.cpp:219:8:219:13 | call to source | stl.cpp:219:8:219:15 | call to basic_string | TAINT | +| stl.cpp:219:8:219:15 | call to basic_string | stl.cpp:219:3:219:15 | ... = ... | | +| stl.cpp:219:8:219:15 | call to basic_string | stl.cpp:223:8:223:9 | s3 | | +| stl.cpp:227:15:227:16 | call to basic_string | stl.cpp:228:20:228:21 | s1 | | +| stl.cpp:227:15:227:16 | call to basic_string | stl.cpp:230:8:230:9 | s1 | | +| stl.cpp:227:15:227:16 | call to basic_string | stl.cpp:232:8:232:9 | s1 | | +| stl.cpp:228:20:228:21 | s1 | stl.cpp:233:8:233:9 | s2 | | +| stl.cpp:230:8:230:9 | s1 | stl.cpp:230:3:230:9 | ... = ... | | +| stl.cpp:230:8:230:9 | s1 | stl.cpp:234:8:234:9 | s3 | | +| stl.cpp:238:19:238:40 | call to basic_string | stl.cpp:242:8:242:9 | s1 | | +| stl.cpp:238:32:238:37 | call to source | stl.cpp:238:19:238:40 | call to basic_string | TAINT | +| stl.cpp:240:8:240:28 | call to basic_string | stl.cpp:240:3:240:28 | ... = ... | | +| stl.cpp:240:8:240:28 | call to basic_string | stl.cpp:243:8:243:9 | s2 | | +| stl.cpp:240:20:240:25 | call to source | stl.cpp:240:8:240:28 | call to basic_string | TAINT | +| stl.cpp:250:16:250:21 | call to source | stl.cpp:250:16:250:24 | call to basic_string | TAINT | +| stl.cpp:250:16:250:24 | call to basic_string | stl.cpp:251:15:251:15 | s | | +| stl.cpp:250:16:250:24 | call to basic_string | stl.cpp:255:33:255:33 | s | | +| stl.cpp:250:16:250:24 | call to basic_string | stl.cpp:255:50:255:50 | s | | +| stl.cpp:250:16:250:24 | call to basic_string | stl.cpp:259:16:259:16 | s | | +| stl.cpp:251:15:251:15 | call to begin | stl.cpp:251:15:251:15 | (__begin) | | +| stl.cpp:251:15:251:15 | call to begin | stl.cpp:251:15:251:15 | (__begin) | | +| stl.cpp:251:15:251:15 | call to begin | stl.cpp:251:15:251:15 | (__begin) | | +| stl.cpp:251:15:251:15 | call to end | stl.cpp:251:15:251:15 | (__end) | | +| stl.cpp:251:15:251:15 | call to operator* | stl.cpp:252:8:252:8 | c | | +| stl.cpp:251:15:251:15 | ref arg (__begin) | stl.cpp:251:15:251:15 | (__begin) | | +| stl.cpp:251:15:251:15 | ref arg (__begin) | stl.cpp:251:15:251:15 | (__begin) | | +| stl.cpp:251:15:251:15 | ref arg (__begin) | stl.cpp:251:15:251:15 | (__begin) | | +| stl.cpp:251:15:251:15 | ref arg (__range) | stl.cpp:251:15:251:15 | (__range) | | +| stl.cpp:251:15:251:15 | s | stl.cpp:251:15:251:15 | (__range) | | +| stl.cpp:251:15:251:15 | s | stl.cpp:251:15:251:15 | (__range) | | +| stl.cpp:251:15:251:15 | s | stl.cpp:251:15:251:15 | call to operator* | TAINT | +| stl.cpp:255:33:255:33 | ref arg s | stl.cpp:255:50:255:50 | s | | +| stl.cpp:255:33:255:33 | ref arg s | stl.cpp:259:16:259:16 | s | | +| stl.cpp:255:35:255:39 | call to begin | stl.cpp:255:44:255:45 | it | | +| stl.cpp:255:35:255:39 | call to begin | stl.cpp:255:61:255:62 | it | | +| stl.cpp:255:35:255:39 | call to begin | stl.cpp:256:9:256:10 | it | | +| stl.cpp:255:50:255:50 | ref arg s | stl.cpp:255:50:255:50 | s | | +| stl.cpp:255:50:255:50 | ref arg s | stl.cpp:259:16:259:16 | s | | +| stl.cpp:255:61:255:62 | ref arg it | stl.cpp:255:44:255:45 | it | | +| stl.cpp:255:61:255:62 | ref arg it | stl.cpp:255:61:255:62 | it | | +| stl.cpp:255:61:255:62 | ref arg it | stl.cpp:256:9:256:10 | it | | +| stl.cpp:259:16:259:16 | call to begin | stl.cpp:259:16:259:16 | (__begin) | | +| stl.cpp:259:16:259:16 | call to begin | stl.cpp:259:16:259:16 | (__begin) | | +| stl.cpp:259:16:259:16 | call to begin | stl.cpp:259:16:259:16 | (__begin) | | +| stl.cpp:259:16:259:16 | call to end | stl.cpp:259:16:259:16 | (__end) | | +| stl.cpp:259:16:259:16 | call to operator* | stl.cpp:260:8:260:8 | c | | +| stl.cpp:259:16:259:16 | ref arg (__begin) | stl.cpp:259:16:259:16 | (__begin) | | +| stl.cpp:259:16:259:16 | ref arg (__begin) | stl.cpp:259:16:259:16 | (__begin) | | +| stl.cpp:259:16:259:16 | ref arg (__begin) | stl.cpp:259:16:259:16 | (__begin) | | +| stl.cpp:259:16:259:16 | ref arg (__range) | stl.cpp:259:16:259:16 | (__range) | | +| stl.cpp:259:16:259:16 | s | stl.cpp:259:16:259:16 | (__range) | | +| stl.cpp:259:16:259:16 | s | stl.cpp:259:16:259:16 | (__range) | | +| stl.cpp:259:16:259:16 | s | stl.cpp:259:16:259:16 | call to operator* | TAINT | +| stl.cpp:263:28:263:33 | call to source | stl.cpp:263:28:263:36 | call to basic_string | TAINT | +| stl.cpp:263:28:263:36 | call to basic_string | stl.cpp:264:22:264:28 | const_s | | +| stl.cpp:264:22:264:22 | call to begin | stl.cpp:264:22:264:22 | (__begin) | | +| stl.cpp:264:22:264:22 | call to begin | stl.cpp:264:22:264:22 | (__begin) | | +| stl.cpp:264:22:264:22 | call to begin | stl.cpp:264:22:264:22 | (__begin) | | +| stl.cpp:264:22:264:22 | call to end | stl.cpp:264:22:264:22 | (__end) | | +| stl.cpp:264:22:264:22 | call to operator* | stl.cpp:265:8:265:8 | c | | +| stl.cpp:264:22:264:22 | ref arg (__begin) | stl.cpp:264:22:264:22 | (__begin) | | +| stl.cpp:264:22:264:22 | ref arg (__begin) | stl.cpp:264:22:264:22 | (__begin) | | +| stl.cpp:264:22:264:22 | ref arg (__begin) | stl.cpp:264:22:264:22 | (__begin) | | +| stl.cpp:264:22:264:28 | const_s | stl.cpp:264:22:264:22 | (__range) | | +| stl.cpp:264:22:264:28 | const_s | stl.cpp:264:22:264:22 | (__range) | | +| stl.cpp:264:22:264:28 | const_s | stl.cpp:264:22:264:22 | call to operator* | TAINT | +| stl.cpp:300:43:300:49 | source1 | stl.cpp:304:21:304:27 | source1 | | +| stl.cpp:300:43:300:49 | source1 | stl.cpp:318:33:318:39 | source1 | | +| stl.cpp:304:21:304:27 | source1 | stl.cpp:304:21:304:28 | call to vector | TAINT | +| stl.cpp:304:21:304:28 | call to vector | stl.cpp:306:14:306:14 | v | | +| stl.cpp:304:21:304:28 | call to vector | stl.cpp:310:38:310:38 | v | | +| stl.cpp:304:21:304:28 | call to vector | stl.cpp:310:55:310:55 | v | | +| stl.cpp:304:21:304:28 | call to vector | stl.cpp:314:15:314:15 | v | | +| stl.cpp:306:14:306:14 | call to begin | stl.cpp:306:14:306:14 | (__begin) | | +| stl.cpp:306:14:306:14 | call to begin | stl.cpp:306:14:306:14 | (__begin) | | +| stl.cpp:306:14:306:14 | call to begin | stl.cpp:306:14:306:14 | (__begin) | | +| stl.cpp:306:14:306:14 | call to end | stl.cpp:306:14:306:14 | (__end) | | +| stl.cpp:306:14:306:14 | call to operator* | stl.cpp:307:8:307:8 | x | | +| stl.cpp:306:14:306:14 | ref arg (__begin) | stl.cpp:306:14:306:14 | (__begin) | | +| stl.cpp:306:14:306:14 | ref arg (__begin) | stl.cpp:306:14:306:14 | (__begin) | | +| stl.cpp:306:14:306:14 | ref arg (__begin) | stl.cpp:306:14:306:14 | (__begin) | | +| stl.cpp:306:14:306:14 | ref arg (__range) | stl.cpp:306:14:306:14 | (__range) | | +| stl.cpp:306:14:306:14 | v | stl.cpp:306:14:306:14 | (__range) | | +| stl.cpp:306:14:306:14 | v | stl.cpp:306:14:306:14 | (__range) | | +| stl.cpp:306:14:306:14 | v | stl.cpp:306:14:306:14 | call to operator* | TAINT | +| stl.cpp:310:38:310:38 | ref arg v | stl.cpp:310:55:310:55 | v | | +| stl.cpp:310:38:310:38 | ref arg v | stl.cpp:314:15:314:15 | v | | +| stl.cpp:310:40:310:44 | call to begin | stl.cpp:310:49:310:50 | it | | +| stl.cpp:310:40:310:44 | call to begin | stl.cpp:310:66:310:67 | it | | +| stl.cpp:310:40:310:44 | call to begin | stl.cpp:311:9:311:10 | it | | +| stl.cpp:310:55:310:55 | ref arg v | stl.cpp:310:55:310:55 | v | | +| stl.cpp:310:55:310:55 | ref arg v | stl.cpp:314:15:314:15 | v | | +| stl.cpp:310:66:310:67 | ref arg it | stl.cpp:310:49:310:50 | it | | +| stl.cpp:310:66:310:67 | ref arg it | stl.cpp:310:66:310:67 | it | | +| stl.cpp:310:66:310:67 | ref arg it | stl.cpp:311:9:311:10 | it | | +| stl.cpp:314:15:314:15 | call to begin | stl.cpp:314:15:314:15 | (__begin) | | +| stl.cpp:314:15:314:15 | call to begin | stl.cpp:314:15:314:15 | (__begin) | | +| stl.cpp:314:15:314:15 | call to begin | stl.cpp:314:15:314:15 | (__begin) | | +| stl.cpp:314:15:314:15 | call to end | stl.cpp:314:15:314:15 | (__end) | | +| stl.cpp:314:15:314:15 | call to operator* | stl.cpp:315:8:315:8 | x | | +| stl.cpp:314:15:314:15 | ref arg (__begin) | stl.cpp:314:15:314:15 | (__begin) | | +| stl.cpp:314:15:314:15 | ref arg (__begin) | stl.cpp:314:15:314:15 | (__begin) | | +| stl.cpp:314:15:314:15 | ref arg (__begin) | stl.cpp:314:15:314:15 | (__begin) | | +| stl.cpp:314:15:314:15 | ref arg (__range) | stl.cpp:314:15:314:15 | (__range) | | +| stl.cpp:314:15:314:15 | v | stl.cpp:314:15:314:15 | (__range) | | +| stl.cpp:314:15:314:15 | v | stl.cpp:314:15:314:15 | (__range) | | +| stl.cpp:314:15:314:15 | v | stl.cpp:314:15:314:15 | call to operator* | TAINT | +| stl.cpp:318:33:318:39 | source1 | stl.cpp:318:33:318:40 | call to vector | TAINT | +| stl.cpp:318:33:318:40 | call to vector | stl.cpp:319:21:319:27 | const_v | | +| stl.cpp:319:21:319:21 | call to begin | stl.cpp:319:21:319:21 | (__begin) | | +| stl.cpp:319:21:319:21 | call to begin | stl.cpp:319:21:319:21 | (__begin) | | +| stl.cpp:319:21:319:21 | call to begin | stl.cpp:319:21:319:21 | (__begin) | | +| stl.cpp:319:21:319:21 | call to end | stl.cpp:319:21:319:21 | (__end) | | +| stl.cpp:319:21:319:21 | call to operator* | stl.cpp:320:8:320:8 | x | | +| stl.cpp:319:21:319:21 | ref arg (__begin) | stl.cpp:319:21:319:21 | (__begin) | | +| stl.cpp:319:21:319:21 | ref arg (__begin) | stl.cpp:319:21:319:21 | (__begin) | | +| stl.cpp:319:21:319:21 | ref arg (__begin) | stl.cpp:319:21:319:21 | (__begin) | | +| stl.cpp:319:21:319:27 | const_v | stl.cpp:319:21:319:21 | (__range) | | +| stl.cpp:319:21:319:27 | const_v | stl.cpp:319:21:319:21 | (__range) | | +| stl.cpp:319:21:319:27 | const_v | stl.cpp:319:21:319:21 | call to operator* | TAINT | +| stl.cpp:331:18:331:24 | hello | stl.cpp:331:18:331:25 | call to basic_string | TAINT | +| stl.cpp:331:18:331:25 | call to basic_string | stl.cpp:334:8:334:9 | s1 | | +| stl.cpp:331:18:331:25 | call to basic_string | stl.cpp:334:13:334:14 | s1 | | +| stl.cpp:331:18:331:25 | call to basic_string | stl.cpp:335:8:335:9 | s1 | | +| stl.cpp:331:18:331:25 | call to basic_string | stl.cpp:336:13:336:14 | s1 | | +| stl.cpp:331:18:331:25 | call to basic_string | stl.cpp:339:8:339:9 | s1 | | +| stl.cpp:331:18:331:25 | call to basic_string | stl.cpp:340:8:340:9 | s1 | | +| stl.cpp:332:18:332:23 | call to source | stl.cpp:332:18:332:26 | call to basic_string | TAINT | +| stl.cpp:332:18:332:26 | call to basic_string | stl.cpp:335:13:335:14 | s2 | | +| stl.cpp:332:18:332:26 | call to basic_string | stl.cpp:336:8:336:9 | s2 | | +| stl.cpp:332:18:332:26 | call to basic_string | stl.cpp:337:8:337:9 | s2 | | +| stl.cpp:332:18:332:26 | call to basic_string | stl.cpp:337:13:337:14 | s2 | | +| stl.cpp:334:8:334:9 | s1 | stl.cpp:334:11:334:11 | call to operator+ | TAINT | +| stl.cpp:334:13:334:14 | s1 | stl.cpp:334:11:334:11 | call to operator+ | TAINT | +| stl.cpp:335:8:335:9 | s1 | stl.cpp:335:11:335:11 | call to operator+ | TAINT | +| stl.cpp:335:13:335:14 | s2 | stl.cpp:335:11:335:11 | call to operator+ | TAINT | +| stl.cpp:336:8:336:9 | s2 | stl.cpp:336:11:336:11 | call to operator+ | TAINT | +| stl.cpp:336:13:336:14 | s1 | stl.cpp:336:11:336:11 | call to operator+ | TAINT | +| stl.cpp:337:8:337:9 | s2 | stl.cpp:337:11:337:11 | call to operator+ | TAINT | +| stl.cpp:337:13:337:14 | s2 | stl.cpp:337:11:337:11 | call to operator+ | TAINT | +| stl.cpp:339:8:339:9 | s1 | stl.cpp:339:11:339:11 | call to operator+ | TAINT | +| stl.cpp:339:13:339:20 | world | stl.cpp:339:11:339:11 | call to operator+ | TAINT | +| stl.cpp:340:8:340:9 | s1 | stl.cpp:340:11:340:11 | call to operator+ | TAINT | +| stl.cpp:340:13:340:18 | call to source | stl.cpp:340:11:340:11 | call to operator+ | TAINT | +| stl.cpp:344:18:344:22 | abc | stl.cpp:344:18:344:23 | call to basic_string | TAINT | +| stl.cpp:344:18:344:23 | call to basic_string | stl.cpp:348:8:348:9 | s3 | | +| stl.cpp:344:18:344:23 | call to basic_string | stl.cpp:351:8:351:9 | s3 | | +| stl.cpp:344:18:344:23 | call to basic_string | stl.cpp:355:8:355:9 | s3 | | +| stl.cpp:344:18:344:23 | call to basic_string | stl.cpp:360:8:360:9 | s3 | | +| stl.cpp:344:18:344:23 | call to basic_string | stl.cpp:364:8:364:9 | s3 | | +| stl.cpp:345:18:345:23 | call to source | stl.cpp:345:18:345:26 | call to basic_string | TAINT | +| stl.cpp:345:18:345:26 | call to basic_string | stl.cpp:348:13:348:14 | s4 | | +| stl.cpp:345:18:345:26 | call to basic_string | stl.cpp:352:9:352:10 | s4 | | +| stl.cpp:345:18:345:26 | call to basic_string | stl.cpp:361:13:361:14 | s4 | | +| stl.cpp:348:8:348:9 | s3 | stl.cpp:348:11:348:11 | call to operator+ | TAINT | +| stl.cpp:348:11:348:11 | call to operator+ | stl.cpp:348:3:348:14 | ... = ... | | +| stl.cpp:348:11:348:11 | call to operator+ | stl.cpp:349:8:349:9 | s5 | | +| stl.cpp:348:13:348:14 | s4 | stl.cpp:348:11:348:11 | call to operator+ | TAINT | | stl.cpp:351:8:351:9 | s3 | stl.cpp:351:3:351:9 | ... = ... | | -| stl.cpp:351:8:351:9 | s3 | stl.cpp:352:3:352:4 | s8 | | -| stl.cpp:351:8:351:9 | s3 | stl.cpp:353:8:353:9 | s8 | | -| stl.cpp:352:3:352:4 | ref arg s8 | stl.cpp:353:8:353:9 | s8 | | -| stl.cpp:352:13:352:14 | s4 | stl.cpp:352:3:352:4 | ref arg s8 | TAINT | -| stl.cpp:352:13:352:14 | s4 | stl.cpp:352:6:352:11 | call to append | TAINT | +| stl.cpp:351:8:351:9 | s3 | stl.cpp:352:3:352:4 | s6 | | +| stl.cpp:351:8:351:9 | s3 | stl.cpp:353:8:353:9 | s6 | | +| stl.cpp:352:3:352:4 | ref arg s6 | stl.cpp:353:8:353:9 | s6 | | +| stl.cpp:352:9:352:10 | s4 | stl.cpp:352:3:352:4 | ref arg s6 | TAINT | +| stl.cpp:352:9:352:10 | s4 | stl.cpp:352:6:352:6 | call to operator+= | TAINT | | stl.cpp:355:8:355:9 | s3 | stl.cpp:355:3:355:9 | ... = ... | | -| stl.cpp:355:8:355:9 | s3 | stl.cpp:356:3:356:4 | s9 | | -| stl.cpp:355:8:355:9 | s3 | stl.cpp:357:3:357:4 | s9 | | -| stl.cpp:355:8:355:9 | s3 | stl.cpp:358:8:358:9 | s9 | | -| stl.cpp:356:3:356:4 | ref arg s9 | stl.cpp:357:3:357:4 | s9 | | -| stl.cpp:356:3:356:4 | ref arg s9 | stl.cpp:358:8:358:9 | s9 | | -| stl.cpp:356:13:356:18 | call to source | stl.cpp:356:3:356:4 | ref arg s9 | TAINT | -| stl.cpp:356:13:356:18 | call to source | stl.cpp:356:6:356:11 | call to append | TAINT | -| stl.cpp:357:3:357:4 | ref arg s9 | stl.cpp:358:8:358:9 | s9 | | -| stl.cpp:357:13:357:15 | | stl.cpp:357:3:357:4 | ref arg s9 | TAINT | -| stl.cpp:357:13:357:15 | | stl.cpp:357:6:357:11 | call to append | TAINT | +| stl.cpp:355:8:355:9 | s3 | stl.cpp:356:3:356:4 | s7 | | +| stl.cpp:355:8:355:9 | s3 | stl.cpp:357:3:357:4 | s7 | | +| stl.cpp:355:8:355:9 | s3 | stl.cpp:358:8:358:9 | s7 | | +| stl.cpp:356:3:356:4 | ref arg s7 | stl.cpp:357:3:357:4 | s7 | | +| stl.cpp:356:3:356:4 | ref arg s7 | stl.cpp:358:8:358:9 | s7 | | +| stl.cpp:356:9:356:14 | call to source | stl.cpp:356:3:356:4 | ref arg s7 | TAINT | +| stl.cpp:356:9:356:14 | call to source | stl.cpp:356:6:356:6 | call to operator+= | TAINT | +| stl.cpp:357:3:357:4 | ref arg s7 | stl.cpp:358:8:358:9 | s7 | | +| stl.cpp:357:9:357:11 | | stl.cpp:357:3:357:4 | ref arg s7 | TAINT | +| stl.cpp:357:9:357:11 | | stl.cpp:357:6:357:6 | call to operator+= | TAINT | +| stl.cpp:360:8:360:9 | s3 | stl.cpp:360:3:360:9 | ... = ... | | +| stl.cpp:360:8:360:9 | s3 | stl.cpp:361:3:361:4 | s8 | | +| stl.cpp:360:8:360:9 | s3 | stl.cpp:362:8:362:9 | s8 | | +| stl.cpp:361:3:361:4 | ref arg s8 | stl.cpp:362:8:362:9 | s8 | | +| stl.cpp:361:13:361:14 | s4 | stl.cpp:361:3:361:4 | ref arg s8 | TAINT | +| stl.cpp:361:13:361:14 | s4 | stl.cpp:361:6:361:11 | call to append | TAINT | +| stl.cpp:364:8:364:9 | s3 | stl.cpp:364:3:364:9 | ... = ... | | +| stl.cpp:364:8:364:9 | s3 | stl.cpp:365:3:365:4 | s9 | | +| stl.cpp:364:8:364:9 | s3 | stl.cpp:366:3:366:4 | s9 | | +| stl.cpp:364:8:364:9 | s3 | stl.cpp:367:8:367:9 | s9 | | +| stl.cpp:365:3:365:4 | ref arg s9 | stl.cpp:366:3:366:4 | s9 | | +| stl.cpp:365:3:365:4 | ref arg s9 | stl.cpp:367:8:367:9 | s9 | | +| stl.cpp:365:13:365:18 | call to source | stl.cpp:365:3:365:4 | ref arg s9 | TAINT | +| stl.cpp:365:13:365:18 | call to source | stl.cpp:365:6:365:11 | call to append | TAINT | +| stl.cpp:366:3:366:4 | ref arg s9 | stl.cpp:367:8:367:9 | s9 | | +| stl.cpp:366:13:366:15 | | stl.cpp:366:3:366:4 | ref arg s9 | TAINT | +| stl.cpp:366:13:366:15 | | stl.cpp:366:6:366:11 | call to append | TAINT | | structlikeclass.cpp:5:7:5:7 | Unknown literal | structlikeclass.cpp:5:7:5:7 | constructor init of field v | TAINT | | structlikeclass.cpp:5:7:5:7 | Unknown literal | structlikeclass.cpp:5:7:5:7 | constructor init of field v | TAINT | | structlikeclass.cpp:5:7:5:7 | this | structlikeclass.cpp:5:7:5:7 | constructor init of field v [pre-this] | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp index 698bed82c02..991b9fc5cc6 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp @@ -30,11 +30,14 @@ namespace std template class allocator { public: allocator() throw(); + typedef size_t size_type; }; template, class Allocator = allocator > class basic_string { public: + typedef typename Allocator::size_type size_type; + explicit basic_string(const Allocator& a = Allocator()); basic_string(const charT* s, const Allocator& a = Allocator()); @@ -54,6 +57,7 @@ namespace std basic_string& operator+=(const charT* s); basic_string& append(const basic_string& str); basic_string& append(const charT* s); + basic_string& append(size_type n, charT c); }; template basic_string operator+(const basic_string& lhs, const basic_string& rhs); @@ -317,6 +321,11 @@ void test_range_based_for_loop_vector(int source1) { } } +namespace ns_char +{ + char source(); +} + void test_string_append() { { std::string s1("hello"); diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected index 345f8674aad..050ba49f97b 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -32,36 +32,36 @@ | movableclass.cpp:55:8:55:9 | s2 | movableclass.cpp:52:23:52:28 | call to source | | movableclass.cpp:64:8:64:9 | s2 | movableclass.cpp:23:55:23:60 | call to source | | movableclass.cpp:65:11:65:11 | call to operator= | movableclass.cpp:65:13:65:18 | call to source | -| stl.cpp:109:7:109:7 | a | stl.cpp:105:12:105:17 | call to source | -| stl.cpp:111:7:111:7 | c | stl.cpp:107:16:107:21 | call to source | -| stl.cpp:113:9:113:13 | call to c_str | stl.cpp:107:16:107:21 | call to source | -| stl.cpp:163:13:163:17 | call to c_str | stl.cpp:155:10:155:15 | call to source | -| stl.cpp:167:13:167:17 | call to c_str | stl.cpp:155:10:155:15 | call to source | -| stl.cpp:170:13:170:17 | call to c_str | stl.cpp:155:10:155:15 | call to source | -| stl.cpp:180:7:180:8 | cs | stl.cpp:175:19:175:24 | call to source | -| stl.cpp:181:7:181:8 | ss | stl.cpp:175:19:175:24 | call to source | -| stl.cpp:194:7:194:8 | cs | stl.cpp:186:19:186:24 | call to source | -| stl.cpp:195:7:195:8 | ss | stl.cpp:186:19:186:24 | call to source | -| stl.cpp:217:8:217:9 | s1 | stl.cpp:212:18:212:23 | call to source | -| stl.cpp:218:8:218:9 | s2 | stl.cpp:213:20:213:25 | call to source | -| stl.cpp:219:8:219:9 | s3 | stl.cpp:215:8:215:13 | call to source | -| stl.cpp:238:8:238:9 | s1 | stl.cpp:234:32:234:37 | call to source | -| stl.cpp:239:8:239:9 | s2 | stl.cpp:236:20:236:25 | call to source | -| stl.cpp:248:8:248:8 | c | stl.cpp:246:16:246:21 | call to source | -| stl.cpp:256:8:256:8 | c | stl.cpp:246:16:246:21 | call to source | -| stl.cpp:261:8:261:8 | c | stl.cpp:259:28:259:33 | call to source | -| stl.cpp:303:8:303:8 | x | stl.cpp:296:43:296:49 | source1 | -| stl.cpp:311:8:311:8 | x | stl.cpp:296:43:296:49 | source1 | -| stl.cpp:316:8:316:8 | x | stl.cpp:296:43:296:49 | source1 | -| stl.cpp:326:11:326:11 | call to operator+ | stl.cpp:323:18:323:23 | call to source | -| stl.cpp:327:11:327:11 | call to operator+ | stl.cpp:323:18:323:23 | call to source | -| stl.cpp:328:11:328:11 | call to operator+ | stl.cpp:323:18:323:23 | call to source | -| stl.cpp:331:11:331:11 | call to operator+ | stl.cpp:331:13:331:18 | call to source | -| stl.cpp:340:8:340:9 | s5 | stl.cpp:336:18:336:23 | call to source | -| stl.cpp:344:8:344:9 | s6 | stl.cpp:336:18:336:23 | call to source | -| stl.cpp:349:8:349:9 | s7 | stl.cpp:347:9:347:14 | call to source | -| stl.cpp:353:8:353:9 | s8 | stl.cpp:336:18:336:23 | call to source | -| stl.cpp:358:8:358:9 | s9 | stl.cpp:356:13:356:18 | call to source | +| stl.cpp:113:7:113:7 | a | stl.cpp:109:12:109:17 | call to source | +| stl.cpp:115:7:115:7 | c | stl.cpp:111:16:111:21 | call to source | +| stl.cpp:117:9:117:13 | call to c_str | stl.cpp:111:16:111:21 | call to source | +| stl.cpp:167:13:167:17 | call to c_str | stl.cpp:159:10:159:15 | call to source | +| stl.cpp:171:13:171:17 | call to c_str | stl.cpp:159:10:159:15 | call to source | +| stl.cpp:174:13:174:17 | call to c_str | stl.cpp:159:10:159:15 | call to source | +| stl.cpp:184:7:184:8 | cs | stl.cpp:179:19:179:24 | call to source | +| stl.cpp:185:7:185:8 | ss | stl.cpp:179:19:179:24 | call to source | +| stl.cpp:198:7:198:8 | cs | stl.cpp:190:19:190:24 | call to source | +| stl.cpp:199:7:199:8 | ss | stl.cpp:190:19:190:24 | call to source | +| stl.cpp:221:8:221:9 | s1 | stl.cpp:216:18:216:23 | call to source | +| stl.cpp:222:8:222:9 | s2 | stl.cpp:217:20:217:25 | call to source | +| stl.cpp:223:8:223:9 | s3 | stl.cpp:219:8:219:13 | call to source | +| stl.cpp:242:8:242:9 | s1 | stl.cpp:238:32:238:37 | call to source | +| stl.cpp:243:8:243:9 | s2 | stl.cpp:240:20:240:25 | call to source | +| stl.cpp:252:8:252:8 | c | stl.cpp:250:16:250:21 | call to source | +| stl.cpp:260:8:260:8 | c | stl.cpp:250:16:250:21 | call to source | +| stl.cpp:265:8:265:8 | c | stl.cpp:263:28:263:33 | call to source | +| stl.cpp:307:8:307:8 | x | stl.cpp:300:43:300:49 | source1 | +| stl.cpp:315:8:315:8 | x | stl.cpp:300:43:300:49 | source1 | +| stl.cpp:320:8:320:8 | x | stl.cpp:300:43:300:49 | source1 | +| stl.cpp:335:11:335:11 | call to operator+ | stl.cpp:332:18:332:23 | call to source | +| stl.cpp:336:11:336:11 | call to operator+ | stl.cpp:332:18:332:23 | call to source | +| stl.cpp:337:11:337:11 | call to operator+ | stl.cpp:332:18:332:23 | call to source | +| stl.cpp:340:11:340:11 | call to operator+ | stl.cpp:340:13:340:18 | call to source | +| stl.cpp:349:8:349:9 | s5 | stl.cpp:345:18:345:23 | call to source | +| stl.cpp:353:8:353:9 | s6 | stl.cpp:345:18:345:23 | call to source | +| stl.cpp:358:8:358:9 | s7 | stl.cpp:356:9:356:14 | call to source | +| stl.cpp:362:8:362:9 | s8 | stl.cpp:345:18:345:23 | call to source | +| stl.cpp:367:8:367:9 | s9 | stl.cpp:365:13:365:18 | call to source | | structlikeclass.cpp:35:8:35:9 | s1 | structlikeclass.cpp:29:22:29:27 | call to source | | structlikeclass.cpp:36:8:36:9 | s2 | structlikeclass.cpp:30:24:30:29 | call to source | | structlikeclass.cpp:37:8:37:9 | s3 | structlikeclass.cpp:29:22:29:27 | call to source | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected index 4c83b90df08..839a077e3e6 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected @@ -30,35 +30,35 @@ | movableclass.cpp:55:8:55:9 | movableclass.cpp:52:23:52:28 | AST only | | movableclass.cpp:64:8:64:9 | movableclass.cpp:23:55:23:60 | AST only | | movableclass.cpp:65:11:65:11 | movableclass.cpp:65:13:65:18 | AST only | -| stl.cpp:111:7:111:7 | stl.cpp:107:16:107:21 | AST only | -| stl.cpp:113:9:113:13 | stl.cpp:107:16:107:21 | AST only | -| stl.cpp:163:13:163:17 | stl.cpp:155:10:155:15 | AST only | -| stl.cpp:167:13:167:17 | stl.cpp:155:10:155:15 | AST only | -| stl.cpp:170:13:170:17 | stl.cpp:155:10:155:15 | AST only | -| stl.cpp:180:7:180:8 | stl.cpp:175:19:175:26 | IR only | -| stl.cpp:181:7:181:8 | stl.cpp:175:19:175:24 | AST only | -| stl.cpp:194:7:194:8 | stl.cpp:186:19:186:24 | AST only | -| stl.cpp:195:7:195:8 | stl.cpp:186:19:186:24 | AST only | -| stl.cpp:217:8:217:9 | stl.cpp:212:18:212:23 | AST only | -| stl.cpp:218:8:218:9 | stl.cpp:213:20:213:25 | AST only | -| stl.cpp:219:8:219:9 | stl.cpp:215:8:215:13 | AST only | -| stl.cpp:238:8:238:9 | stl.cpp:234:32:234:37 | AST only | -| stl.cpp:239:8:239:9 | stl.cpp:236:20:236:25 | AST only | -| stl.cpp:248:8:248:8 | stl.cpp:246:16:246:21 | AST only | -| stl.cpp:256:8:256:8 | stl.cpp:246:16:246:21 | AST only | -| stl.cpp:261:8:261:8 | stl.cpp:259:28:259:33 | AST only | -| stl.cpp:303:8:303:8 | stl.cpp:296:43:296:49 | AST only | -| stl.cpp:311:8:311:8 | stl.cpp:296:43:296:49 | AST only | -| stl.cpp:316:8:316:8 | stl.cpp:296:43:296:49 | AST only | -| stl.cpp:326:11:326:11 | stl.cpp:323:18:323:23 | AST only | -| stl.cpp:327:11:327:11 | stl.cpp:323:18:323:23 | AST only | -| stl.cpp:328:11:328:11 | stl.cpp:323:18:323:23 | AST only | -| stl.cpp:331:11:331:11 | stl.cpp:331:13:331:18 | AST only | -| stl.cpp:340:8:340:9 | stl.cpp:336:18:336:23 | AST only | -| stl.cpp:344:8:344:9 | stl.cpp:336:18:336:23 | AST only | -| stl.cpp:349:8:349:9 | stl.cpp:347:9:347:14 | AST only | -| stl.cpp:353:8:353:9 | stl.cpp:336:18:336:23 | AST only | -| stl.cpp:358:8:358:9 | stl.cpp:356:13:356:18 | AST only | +| stl.cpp:115:7:115:7 | stl.cpp:111:16:111:21 | AST only | +| stl.cpp:117:9:117:13 | stl.cpp:111:16:111:21 | AST only | +| stl.cpp:167:13:167:17 | stl.cpp:159:10:159:15 | AST only | +| stl.cpp:171:13:171:17 | stl.cpp:159:10:159:15 | AST only | +| stl.cpp:174:13:174:17 | stl.cpp:159:10:159:15 | AST only | +| stl.cpp:184:7:184:8 | stl.cpp:179:19:179:26 | IR only | +| stl.cpp:185:7:185:8 | stl.cpp:179:19:179:24 | AST only | +| stl.cpp:198:7:198:8 | stl.cpp:190:19:190:24 | AST only | +| stl.cpp:199:7:199:8 | stl.cpp:190:19:190:24 | AST only | +| stl.cpp:221:8:221:9 | stl.cpp:216:18:216:23 | AST only | +| stl.cpp:222:8:222:9 | stl.cpp:217:20:217:25 | AST only | +| stl.cpp:223:8:223:9 | stl.cpp:219:8:219:13 | AST only | +| stl.cpp:242:8:242:9 | stl.cpp:238:32:238:37 | AST only | +| stl.cpp:243:8:243:9 | stl.cpp:240:20:240:25 | AST only | +| stl.cpp:252:8:252:8 | stl.cpp:250:16:250:21 | AST only | +| stl.cpp:260:8:260:8 | stl.cpp:250:16:250:21 | AST only | +| stl.cpp:265:8:265:8 | stl.cpp:263:28:263:33 | AST only | +| stl.cpp:307:8:307:8 | stl.cpp:300:43:300:49 | AST only | +| stl.cpp:315:8:315:8 | stl.cpp:300:43:300:49 | AST only | +| stl.cpp:320:8:320:8 | stl.cpp:300:43:300:49 | AST only | +| stl.cpp:335:11:335:11 | stl.cpp:332:18:332:23 | AST only | +| stl.cpp:336:11:336:11 | stl.cpp:332:18:332:23 | AST only | +| stl.cpp:337:11:337:11 | stl.cpp:332:18:332:23 | AST only | +| stl.cpp:340:11:340:11 | stl.cpp:340:13:340:18 | AST only | +| stl.cpp:349:8:349:9 | stl.cpp:345:18:345:23 | AST only | +| stl.cpp:353:8:353:9 | stl.cpp:345:18:345:23 | AST only | +| stl.cpp:358:8:358:9 | stl.cpp:356:9:356:14 | AST only | +| stl.cpp:362:8:362:9 | stl.cpp:345:18:345:23 | AST only | +| stl.cpp:367:8:367:9 | stl.cpp:365:13:365:18 | AST only | | structlikeclass.cpp:35:8:35:9 | structlikeclass.cpp:29:22:29:27 | AST only | | structlikeclass.cpp:36:8:36:9 | structlikeclass.cpp:30:24:30:29 | AST only | | structlikeclass.cpp:37:8:37:9 | structlikeclass.cpp:29:22:29:27 | AST only | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected index fae0af72b67..463637d73e0 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected @@ -1,10 +1,10 @@ | format.cpp:157:7:157:22 | (int)... | format.cpp:147:12:147:25 | call to source | | format.cpp:157:7:157:22 | access to array | format.cpp:147:12:147:25 | call to source | | format.cpp:158:7:158:27 | ... + ... | format.cpp:148:16:148:30 | call to source | -| stl.cpp:109:7:109:7 | (const char *)... | stl.cpp:105:12:105:17 | call to source | -| stl.cpp:109:7:109:7 | a | stl.cpp:105:12:105:17 | call to source | -| stl.cpp:180:7:180:8 | cs | stl.cpp:175:19:175:24 | call to source | -| stl.cpp:180:7:180:8 | cs | stl.cpp:175:19:175:26 | (const char *)... | +| stl.cpp:113:7:113:7 | (const char *)... | stl.cpp:109:12:109:17 | call to source | +| stl.cpp:113:7:113:7 | a | stl.cpp:109:12:109:17 | call to source | +| stl.cpp:184:7:184:8 | cs | stl.cpp:179:19:179:24 | call to source | +| stl.cpp:184:7:184:8 | cs | stl.cpp:179:19:179:26 | (const char *)... | | structlikeclass.cpp:38:8:38:9 | s4 | structlikeclass.cpp:33:8:33:13 | call to source | | structlikeclass.cpp:61:8:61:9 | s2 | structlikeclass.cpp:58:24:58:29 | call to source | | structlikeclass.cpp:62:8:62:20 | ... = ... | structlikeclass.cpp:62:13:62:18 | call to source | From 3c0e7a709f4289cde3222b3705d124279996a407 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 13 Aug 2020 14:22:11 +0100 Subject: [PATCH 061/133] C++: Add a test of append with CharT. --- cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp index 991b9fc5cc6..46b3448d37e 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp @@ -366,4 +366,12 @@ void test_string_append() { s9.append(" "); sink(s9); // tainted } + + { + std::string s10("abc"); + char c = ns_char::source(); + + s10.append(1, c); + sink(s10); // tainted [NOT DETECTED] + } } From 7349333006343c4e9a1768b4a8e25d87b2d6a53e Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 13 Aug 2020 14:44:51 +0100 Subject: [PATCH 062/133] C++: Taint through char append. --- .../semmle/code/cpp/models/implementations/StdString.qll | 6 ++++-- .../library-tests/dataflow/taint-tests/localTaint.expected | 7 +++++++ cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp | 2 +- .../test/library-tests/dataflow/taint-tests/taint.expected | 1 + .../library-tests/dataflow/taint-tests/test_diff.expected | 1 + 5 files changed, 14 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll index 17ccfc954b2..06ca6ad8fd7 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -49,11 +49,13 @@ class StdStringAppend extends TaintFunction { } /** - * Gets the index of a parameter to this function that is a string. + * Gets the index of a parameter to this function that is a string (or + * character). */ int getAStringParameter() { getParameter(result).getType() instanceof PointerType or - getParameter(result).getType() instanceof ReferenceType + getParameter(result).getType() instanceof ReferenceType or + getParameter(result).getType() = getDeclaringType().getTemplateArgument(0) // i.e. `std::basic_string::CharT` } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected index a387ca676d6..cbaa02ae640 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -579,6 +579,13 @@ | stl.cpp:366:3:366:4 | ref arg s9 | stl.cpp:367:8:367:9 | s9 | | | stl.cpp:366:13:366:15 | | stl.cpp:366:3:366:4 | ref arg s9 | TAINT | | stl.cpp:366:13:366:15 | | stl.cpp:366:6:366:11 | call to append | TAINT | +| stl.cpp:371:19:371:23 | abc | stl.cpp:371:19:371:24 | call to basic_string | TAINT | +| stl.cpp:371:19:371:24 | call to basic_string | stl.cpp:374:3:374:5 | s10 | | +| stl.cpp:371:19:371:24 | call to basic_string | stl.cpp:375:8:375:10 | s10 | | +| stl.cpp:372:12:372:26 | call to source | stl.cpp:374:17:374:17 | c | | +| stl.cpp:374:3:374:5 | ref arg s10 | stl.cpp:375:8:375:10 | s10 | | +| stl.cpp:374:17:374:17 | c | stl.cpp:374:3:374:5 | ref arg s10 | TAINT | +| stl.cpp:374:17:374:17 | c | stl.cpp:374:7:374:12 | call to append | TAINT | | structlikeclass.cpp:5:7:5:7 | Unknown literal | structlikeclass.cpp:5:7:5:7 | constructor init of field v | TAINT | | structlikeclass.cpp:5:7:5:7 | Unknown literal | structlikeclass.cpp:5:7:5:7 | constructor init of field v | TAINT | | structlikeclass.cpp:5:7:5:7 | this | structlikeclass.cpp:5:7:5:7 | constructor init of field v [pre-this] | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp index 46b3448d37e..d0253b9b025 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp @@ -372,6 +372,6 @@ void test_string_append() { char c = ns_char::source(); s10.append(1, c); - sink(s10); // tainted [NOT DETECTED] + sink(s10); // tainted } } diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected index 050ba49f97b..3c3ed47e351 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -62,6 +62,7 @@ | stl.cpp:358:8:358:9 | s7 | stl.cpp:356:9:356:14 | call to source | | stl.cpp:362:8:362:9 | s8 | stl.cpp:345:18:345:23 | call to source | | stl.cpp:367:8:367:9 | s9 | stl.cpp:365:13:365:18 | call to source | +| stl.cpp:375:8:375:10 | s10 | stl.cpp:372:12:372:26 | call to source | | structlikeclass.cpp:35:8:35:9 | s1 | structlikeclass.cpp:29:22:29:27 | call to source | | structlikeclass.cpp:36:8:36:9 | s2 | structlikeclass.cpp:30:24:30:29 | call to source | | structlikeclass.cpp:37:8:37:9 | s3 | structlikeclass.cpp:29:22:29:27 | call to source | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected index 839a077e3e6..7704bbf9bf0 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected @@ -59,6 +59,7 @@ | stl.cpp:358:8:358:9 | stl.cpp:356:9:356:14 | AST only | | stl.cpp:362:8:362:9 | stl.cpp:345:18:345:23 | AST only | | stl.cpp:367:8:367:9 | stl.cpp:365:13:365:18 | AST only | +| stl.cpp:375:8:375:10 | stl.cpp:372:12:372:26 | AST only | | structlikeclass.cpp:35:8:35:9 | structlikeclass.cpp:29:22:29:27 | AST only | | structlikeclass.cpp:36:8:36:9 | structlikeclass.cpp:30:24:30:29 | AST only | | structlikeclass.cpp:37:8:37:9 | structlikeclass.cpp:29:22:29:27 | AST only | From 3d60756d40a005dc8007047695e56636f01f539c Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 13 Aug 2020 15:45:57 +0100 Subject: [PATCH 063/133] C++: Downgrade the query precision. --- cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql b/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql index 54c6d1e7a96..cc2d52385c7 100644 --- a/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql +++ b/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql @@ -4,7 +4,7 @@ * user can result in integer overflow. * @kind path-problem * @problem.severity error - * @precision high + * @precision medium * @id cpp/uncontrolled-allocation-size * @tags reliability * security From 5d7f771933465e4417ec73561aff2280d0d4507c Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 13 Aug 2020 17:43:21 +0100 Subject: [PATCH 064/133] C++: Split off stl.h from stl.cpp. --- .../dataflow/taint-tests/stl.cpp | 190 +++++++++--------- .../library-tests/dataflow/taint-tests/stl.h | 126 ++++++++++++ 2 files changed, 221 insertions(+), 95 deletions(-) create mode 100644 cpp/ql/test/library-tests/dataflow/taint-tests/stl.h diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp index d0253b9b025..02fa029850d 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp @@ -1,103 +1,103 @@ -typedef unsigned long size_t; +#include "stl.h" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -namespace std -{ - template struct char_traits; - typedef size_t streamsize; - struct ptrdiff_t; - template - struct iterator { - iterator &operator++(); - iterator operator++(int); - bool operator==(iterator other) const; - bool operator!=(iterator other) const; - reference_type operator*() const; - }; - struct input_iterator_tag {}; - struct forward_iterator_tag : public input_iterator_tag {}; - struct bidirectional_iterator_tag : public forward_iterator_tag {}; - struct random_access_iterator_tag : public bidirectional_iterator_tag {}; - template class allocator { - public: - allocator() throw(); - typedef size_t size_type; - }; - - template, class Allocator = allocator > - class basic_string { - public: - typedef typename Allocator::size_type size_type; - explicit basic_string(const Allocator& a = Allocator()); - basic_string(const charT* s, const Allocator& a = Allocator()); - const charT* c_str() const; - typedef std::iterator iterator; - typedef std::iterator const_iterator; - iterator begin(); - iterator end(); - const_iterator begin() const; - const_iterator end() const; - const_iterator cbegin() const; - const_iterator cend() const; - template basic_string& operator+=(const T& t); - basic_string& operator+=(const charT* s); - basic_string& append(const basic_string& str); - basic_string& append(const charT* s); - basic_string& append(size_type n, charT c); - }; - template basic_string operator+(const basic_string& lhs, const basic_string& rhs); - template basic_string operator+(const basic_string& lhs, const charT* rhs); - typedef basic_string string; - template > - class basic_istream /*: virtual public basic_ios - not needed for this test */ { - public: - basic_istream& operator>>(int& n); - }; - template > - class basic_ostream /*: virtual public basic_ios - not needed for this test */ { - public: - typedef charT char_type; - basic_ostream& write(const char_type* s, streamsize n); - basic_ostream& operator<<(int n); - }; - template basic_ostream& operator<<(basic_ostream&, const charT*); - template basic_ostream& operator<<(basic_ostream& os, const basic_string& str); - template> - class basic_iostream : public basic_istream, public basic_ostream { - public: - }; - template, class Allocator = allocator> - class basic_stringstream : public basic_iostream { - public: - explicit basic_stringstream(/*ios_base::openmode which = ios_base::out|ios_base::in - not needed for this test*/); - basic_string str() const; - }; - using stringstream = basic_stringstream; -} char *source(); void sink(const char *s) {}; @@ -273,27 +273,27 @@ void test_range_based_for_loop_string() { -namespace std { - template - class vector { - private: - void *data_; - public: - vector(int size); - T& operator[](int idx); - const T& operator[](int idx) const; - typedef std::iterator iterator; - typedef std::iterator const_iterator; - iterator begin() noexcept; - iterator end() noexcept; - const_iterator begin() const noexcept; - const_iterator end() const noexcept; - }; -} + + + + + + + + + + + + + + + + + void sink(int); diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h new file mode 100644 index 00000000000..4ebd5e9283a --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h @@ -0,0 +1,126 @@ + +typedef unsigned long size_t; + +// --- string --- + +namespace std +{ + template struct char_traits; + + typedef size_t streamsize; + + struct ptrdiff_t; + + template + struct iterator { + iterator &operator++(); + iterator operator++(int); + bool operator==(iterator other) const; + bool operator!=(iterator other) const; + reference_type operator*() const; + }; + + struct input_iterator_tag {}; + struct forward_iterator_tag : public input_iterator_tag {}; + struct bidirectional_iterator_tag : public forward_iterator_tag {}; + struct random_access_iterator_tag : public bidirectional_iterator_tag {}; + + template class allocator { + public: + allocator() throw(); + typedef size_t size_type; + }; + + template, class Allocator = allocator > + class basic_string { + public: + typedef typename Allocator::size_type size_type; + + explicit basic_string(const Allocator& a = Allocator()); + basic_string(const charT* s, const Allocator& a = Allocator()); + + const charT* c_str() const; + + typedef std::iterator iterator; + typedef std::iterator const_iterator; + + iterator begin(); + iterator end(); + const_iterator begin() const; + const_iterator end() const; + const_iterator cbegin() const; + const_iterator cend() const; + + template basic_string& operator+=(const T& t); + basic_string& operator+=(const charT* s); + basic_string& append(const basic_string& str); + basic_string& append(const charT* s); + basic_string& append(size_type n, charT c); + }; + + template basic_string operator+(const basic_string& lhs, const basic_string& rhs); + template basic_string operator+(const basic_string& lhs, const charT* rhs); + + typedef basic_string string; + + template > + class basic_istream /*: virtual public basic_ios - not needed for this test */ { + public: + basic_istream& operator>>(int& n); + }; + + template > + class basic_ostream /*: virtual public basic_ios - not needed for this test */ { + public: + typedef charT char_type; + basic_ostream& write(const char_type* s, streamsize n); + + basic_ostream& operator<<(int n); + }; + + template basic_ostream& operator<<(basic_ostream&, const charT*); + template basic_ostream& operator<<(basic_ostream& os, const basic_string& str); + + template> + class basic_iostream : public basic_istream, public basic_ostream { + public: + }; + + template, class Allocator = allocator> + class basic_stringstream : public basic_iostream { + public: + explicit basic_stringstream(/*ios_base::openmode which = ios_base::out|ios_base::in - not needed for this test*/); + + basic_string str() const; + }; + + using stringstream = basic_stringstream; +} + +// --- vector --- + +namespace std { + template + class vector { + private: + void *data_; + public: + vector(int size); + + T& operator[](int idx); + const T& operator[](int idx) const; + + typedef std::iterator iterator; + typedef std::iterator const_iterator; + + iterator begin() noexcept; + iterator end() noexcept; + + const_iterator begin() const noexcept; + const_iterator end() const noexcept; + }; +} From f343eb91431b4369aed484fbf2831cbbdd37e5fc Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 13 Aug 2020 17:47:25 +0100 Subject: [PATCH 065/133] C++: Split stl.cpp into string.cpp and vector.cpp. --- .../dataflow/taint-tests/localTaint.expected | 556 +++++++++--------- .../taint-tests/{stl.cpp => string.cpp} | 153 ----- .../dataflow/taint-tests/taint.expected | 62 +- .../dataflow/taint-tests/test_diff.expected | 60 +- .../dataflow/taint-tests/test_ir.expected | 8 +- .../dataflow/taint-tests/vector.cpp | 30 + 6 files changed, 373 insertions(+), 496 deletions(-) rename cpp/ql/test/library-tests/dataflow/taint-tests/{stl.cpp => string.cpp} (82%) create mode 100644 cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected index cbaa02ae640..6fb86dc1fd4 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -308,284 +308,230 @@ | movableclass.cpp:65:13:65:18 | call to source | movableclass.cpp:65:13:65:20 | call to MyMovableClass | TAINT | | movableclass.cpp:65:13:65:20 | call to MyMovableClass | movableclass.cpp:65:8:65:9 | ref arg s3 | TAINT | | movableclass.cpp:65:13:65:20 | call to MyMovableClass | movableclass.cpp:65:11:65:11 | call to operator= | TAINT | -| stl.cpp:109:12:109:17 | call to source | stl.cpp:113:7:113:7 | a | | -| stl.cpp:110:16:110:20 | 123 | stl.cpp:110:16:110:21 | call to basic_string | TAINT | -| stl.cpp:110:16:110:21 | call to basic_string | stl.cpp:114:7:114:7 | b | | -| stl.cpp:110:16:110:21 | call to basic_string | stl.cpp:116:7:116:7 | b | | -| stl.cpp:111:16:111:21 | call to source | stl.cpp:111:16:111:24 | call to basic_string | TAINT | -| stl.cpp:111:16:111:24 | call to basic_string | stl.cpp:115:7:115:7 | c | | -| stl.cpp:111:16:111:24 | call to basic_string | stl.cpp:117:7:117:7 | c | | -| stl.cpp:116:7:116:7 | b | stl.cpp:116:9:116:13 | call to c_str | TAINT | -| stl.cpp:117:7:117:7 | c | stl.cpp:117:9:117:13 | call to c_str | TAINT | -| stl.cpp:122:20:122:22 | call to basic_stringstream | stl.cpp:125:2:125:4 | ss1 | | -| stl.cpp:122:20:122:22 | call to basic_stringstream | stl.cpp:131:7:131:9 | ss1 | | -| stl.cpp:122:20:122:22 | call to basic_stringstream | stl.cpp:136:7:136:9 | ss1 | | -| stl.cpp:122:25:122:27 | call to basic_stringstream | stl.cpp:126:2:126:4 | ss2 | | -| stl.cpp:122:25:122:27 | call to basic_stringstream | stl.cpp:132:7:132:9 | ss2 | | -| stl.cpp:122:25:122:27 | call to basic_stringstream | stl.cpp:137:7:137:9 | ss2 | | -| stl.cpp:122:30:122:32 | call to basic_stringstream | stl.cpp:127:2:127:4 | ss3 | | -| stl.cpp:122:30:122:32 | call to basic_stringstream | stl.cpp:133:7:133:9 | ss3 | | -| stl.cpp:122:30:122:32 | call to basic_stringstream | stl.cpp:138:7:138:9 | ss3 | | -| stl.cpp:122:35:122:37 | call to basic_stringstream | stl.cpp:128:2:128:4 | ss4 | | -| stl.cpp:122:35:122:37 | call to basic_stringstream | stl.cpp:134:7:134:9 | ss4 | | -| stl.cpp:122:35:122:37 | call to basic_stringstream | stl.cpp:139:7:139:9 | ss4 | | -| stl.cpp:122:40:122:42 | call to basic_stringstream | stl.cpp:129:2:129:4 | ss5 | | -| stl.cpp:122:40:122:42 | call to basic_stringstream | stl.cpp:135:7:135:9 | ss5 | | -| stl.cpp:122:40:122:42 | call to basic_stringstream | stl.cpp:140:7:140:9 | ss5 | | -| stl.cpp:123:16:123:21 | call to source | stl.cpp:123:16:123:24 | call to basic_string | TAINT | -| stl.cpp:123:16:123:24 | call to basic_string | stl.cpp:129:9:129:9 | t | | -| stl.cpp:125:2:125:4 | ref arg ss1 | stl.cpp:131:7:131:9 | ss1 | | -| stl.cpp:125:2:125:4 | ref arg ss1 | stl.cpp:136:7:136:9 | ss1 | | -| stl.cpp:126:2:126:4 | ref arg ss2 | stl.cpp:132:7:132:9 | ss2 | | -| stl.cpp:126:2:126:4 | ref arg ss2 | stl.cpp:137:7:137:9 | ss2 | | -| stl.cpp:127:2:127:4 | ref arg ss3 | stl.cpp:133:7:133:9 | ss3 | | -| stl.cpp:127:2:127:4 | ref arg ss3 | stl.cpp:138:7:138:9 | ss3 | | -| stl.cpp:128:2:128:4 | ref arg ss4 | stl.cpp:134:7:134:9 | ss4 | | -| stl.cpp:128:2:128:4 | ref arg ss4 | stl.cpp:139:7:139:9 | ss4 | | -| stl.cpp:129:2:129:4 | ref arg ss5 | stl.cpp:135:7:135:9 | ss5 | | -| stl.cpp:129:2:129:4 | ref arg ss5 | stl.cpp:140:7:140:9 | ss5 | | -| stl.cpp:143:32:143:37 | source | stl.cpp:148:9:148:14 | source | | -| stl.cpp:145:20:145:22 | call to basic_stringstream | stl.cpp:147:2:147:4 | ss1 | | -| stl.cpp:145:20:145:22 | call to basic_stringstream | stl.cpp:150:7:150:9 | ss1 | | -| stl.cpp:145:20:145:22 | call to basic_stringstream | stl.cpp:152:7:152:9 | ss1 | | -| stl.cpp:145:25:145:27 | call to basic_stringstream | stl.cpp:148:2:148:4 | ss2 | | -| stl.cpp:145:25:145:27 | call to basic_stringstream | stl.cpp:151:7:151:9 | ss2 | | -| stl.cpp:145:25:145:27 | call to basic_stringstream | stl.cpp:153:7:153:9 | ss2 | | -| stl.cpp:147:2:147:4 | ref arg ss1 | stl.cpp:150:7:150:9 | ss1 | | -| stl.cpp:147:2:147:4 | ref arg ss1 | stl.cpp:152:7:152:9 | ss1 | | -| stl.cpp:148:2:148:4 | ref arg ss2 | stl.cpp:151:7:151:9 | ss2 | | -| stl.cpp:148:2:148:4 | ref arg ss2 | stl.cpp:153:7:153:9 | ss2 | | -| stl.cpp:166:16:166:28 | call to basic_string | stl.cpp:167:7:167:11 | path1 | | -| stl.cpp:166:17:166:26 | call to user_input | stl.cpp:166:16:166:28 | call to basic_string | TAINT | -| stl.cpp:167:7:167:11 | path1 | stl.cpp:167:13:167:17 | call to c_str | TAINT | -| stl.cpp:170:10:170:19 | call to user_input | stl.cpp:170:10:170:21 | call to basic_string | TAINT | -| stl.cpp:170:10:170:21 | call to basic_string | stl.cpp:170:2:170:21 | ... = ... | | -| stl.cpp:170:10:170:21 | call to basic_string | stl.cpp:171:7:171:11 | path2 | | -| stl.cpp:171:7:171:11 | path2 | stl.cpp:171:13:171:17 | call to c_str | TAINT | -| stl.cpp:173:15:173:24 | call to user_input | stl.cpp:173:15:173:27 | call to basic_string | TAINT | -| stl.cpp:173:15:173:27 | call to basic_string | stl.cpp:174:7:174:11 | path3 | | -| stl.cpp:174:7:174:11 | path3 | stl.cpp:174:13:174:17 | call to c_str | TAINT | -| stl.cpp:179:19:179:24 | call to source | stl.cpp:182:17:182:18 | cs | | -| stl.cpp:179:19:179:24 | call to source | stl.cpp:184:7:184:8 | cs | | -| stl.cpp:182:17:182:18 | cs | stl.cpp:182:17:182:19 | call to basic_string | TAINT | -| stl.cpp:182:17:182:19 | call to basic_string | stl.cpp:185:7:185:8 | ss | | -| stl.cpp:190:19:190:24 | call to source | stl.cpp:193:17:193:18 | cs | | -| stl.cpp:193:17:193:18 | cs | stl.cpp:193:17:193:19 | call to basic_string | TAINT | -| stl.cpp:193:17:193:19 | call to basic_string | stl.cpp:196:7:196:8 | ss | | -| stl.cpp:193:17:193:19 | call to basic_string | stl.cpp:199:7:199:8 | ss | | -| stl.cpp:196:7:196:8 | ss | stl.cpp:196:10:196:14 | call to c_str | TAINT | -| stl.cpp:196:10:196:14 | call to c_str | stl.cpp:196:2:196:16 | ... = ... | | -| stl.cpp:196:10:196:14 | call to c_str | stl.cpp:198:7:198:8 | cs | | -| stl.cpp:205:18:205:24 | hello | stl.cpp:205:18:205:25 | call to basic_string | TAINT | -| stl.cpp:205:18:205:25 | call to basic_string | stl.cpp:210:8:210:9 | s1 | | -| stl.cpp:206:19:206:26 | call to basic_string | stl.cpp:211:8:211:9 | s2 | | -| stl.cpp:206:20:206:26 | hello | stl.cpp:206:19:206:26 | call to basic_string | TAINT | -| stl.cpp:208:8:208:14 | call to basic_string | stl.cpp:208:3:208:14 | ... = ... | | -| stl.cpp:208:8:208:14 | call to basic_string | stl.cpp:212:8:212:9 | s3 | | -| stl.cpp:208:8:208:14 | hello | stl.cpp:208:8:208:14 | call to basic_string | TAINT | -| stl.cpp:216:18:216:23 | call to source | stl.cpp:216:18:216:26 | call to basic_string | TAINT | -| stl.cpp:216:18:216:26 | call to basic_string | stl.cpp:221:8:221:9 | s1 | | -| stl.cpp:217:19:217:27 | call to basic_string | stl.cpp:222:8:222:9 | s2 | | -| stl.cpp:217:20:217:25 | call to source | stl.cpp:217:19:217:27 | call to basic_string | TAINT | -| stl.cpp:219:8:219:13 | call to source | stl.cpp:219:8:219:15 | call to basic_string | TAINT | -| stl.cpp:219:8:219:15 | call to basic_string | stl.cpp:219:3:219:15 | ... = ... | | -| stl.cpp:219:8:219:15 | call to basic_string | stl.cpp:223:8:223:9 | s3 | | -| stl.cpp:227:15:227:16 | call to basic_string | stl.cpp:228:20:228:21 | s1 | | -| stl.cpp:227:15:227:16 | call to basic_string | stl.cpp:230:8:230:9 | s1 | | -| stl.cpp:227:15:227:16 | call to basic_string | stl.cpp:232:8:232:9 | s1 | | -| stl.cpp:228:20:228:21 | s1 | stl.cpp:233:8:233:9 | s2 | | -| stl.cpp:230:8:230:9 | s1 | stl.cpp:230:3:230:9 | ... = ... | | -| stl.cpp:230:8:230:9 | s1 | stl.cpp:234:8:234:9 | s3 | | -| stl.cpp:238:19:238:40 | call to basic_string | stl.cpp:242:8:242:9 | s1 | | -| stl.cpp:238:32:238:37 | call to source | stl.cpp:238:19:238:40 | call to basic_string | TAINT | -| stl.cpp:240:8:240:28 | call to basic_string | stl.cpp:240:3:240:28 | ... = ... | | -| stl.cpp:240:8:240:28 | call to basic_string | stl.cpp:243:8:243:9 | s2 | | -| stl.cpp:240:20:240:25 | call to source | stl.cpp:240:8:240:28 | call to basic_string | TAINT | -| stl.cpp:250:16:250:21 | call to source | stl.cpp:250:16:250:24 | call to basic_string | TAINT | -| stl.cpp:250:16:250:24 | call to basic_string | stl.cpp:251:15:251:15 | s | | -| stl.cpp:250:16:250:24 | call to basic_string | stl.cpp:255:33:255:33 | s | | -| stl.cpp:250:16:250:24 | call to basic_string | stl.cpp:255:50:255:50 | s | | -| stl.cpp:250:16:250:24 | call to basic_string | stl.cpp:259:16:259:16 | s | | -| stl.cpp:251:15:251:15 | call to begin | stl.cpp:251:15:251:15 | (__begin) | | -| stl.cpp:251:15:251:15 | call to begin | stl.cpp:251:15:251:15 | (__begin) | | -| stl.cpp:251:15:251:15 | call to begin | stl.cpp:251:15:251:15 | (__begin) | | -| stl.cpp:251:15:251:15 | call to end | stl.cpp:251:15:251:15 | (__end) | | -| stl.cpp:251:15:251:15 | call to operator* | stl.cpp:252:8:252:8 | c | | -| stl.cpp:251:15:251:15 | ref arg (__begin) | stl.cpp:251:15:251:15 | (__begin) | | -| stl.cpp:251:15:251:15 | ref arg (__begin) | stl.cpp:251:15:251:15 | (__begin) | | -| stl.cpp:251:15:251:15 | ref arg (__begin) | stl.cpp:251:15:251:15 | (__begin) | | -| stl.cpp:251:15:251:15 | ref arg (__range) | stl.cpp:251:15:251:15 | (__range) | | -| stl.cpp:251:15:251:15 | s | stl.cpp:251:15:251:15 | (__range) | | -| stl.cpp:251:15:251:15 | s | stl.cpp:251:15:251:15 | (__range) | | -| stl.cpp:251:15:251:15 | s | stl.cpp:251:15:251:15 | call to operator* | TAINT | -| stl.cpp:255:33:255:33 | ref arg s | stl.cpp:255:50:255:50 | s | | -| stl.cpp:255:33:255:33 | ref arg s | stl.cpp:259:16:259:16 | s | | -| stl.cpp:255:35:255:39 | call to begin | stl.cpp:255:44:255:45 | it | | -| stl.cpp:255:35:255:39 | call to begin | stl.cpp:255:61:255:62 | it | | -| stl.cpp:255:35:255:39 | call to begin | stl.cpp:256:9:256:10 | it | | -| stl.cpp:255:50:255:50 | ref arg s | stl.cpp:255:50:255:50 | s | | -| stl.cpp:255:50:255:50 | ref arg s | stl.cpp:259:16:259:16 | s | | -| stl.cpp:255:61:255:62 | ref arg it | stl.cpp:255:44:255:45 | it | | -| stl.cpp:255:61:255:62 | ref arg it | stl.cpp:255:61:255:62 | it | | -| stl.cpp:255:61:255:62 | ref arg it | stl.cpp:256:9:256:10 | it | | -| stl.cpp:259:16:259:16 | call to begin | stl.cpp:259:16:259:16 | (__begin) | | -| stl.cpp:259:16:259:16 | call to begin | stl.cpp:259:16:259:16 | (__begin) | | -| stl.cpp:259:16:259:16 | call to begin | stl.cpp:259:16:259:16 | (__begin) | | -| stl.cpp:259:16:259:16 | call to end | stl.cpp:259:16:259:16 | (__end) | | -| stl.cpp:259:16:259:16 | call to operator* | stl.cpp:260:8:260:8 | c | | -| stl.cpp:259:16:259:16 | ref arg (__begin) | stl.cpp:259:16:259:16 | (__begin) | | -| stl.cpp:259:16:259:16 | ref arg (__begin) | stl.cpp:259:16:259:16 | (__begin) | | -| stl.cpp:259:16:259:16 | ref arg (__begin) | stl.cpp:259:16:259:16 | (__begin) | | -| stl.cpp:259:16:259:16 | ref arg (__range) | stl.cpp:259:16:259:16 | (__range) | | -| stl.cpp:259:16:259:16 | s | stl.cpp:259:16:259:16 | (__range) | | -| stl.cpp:259:16:259:16 | s | stl.cpp:259:16:259:16 | (__range) | | -| stl.cpp:259:16:259:16 | s | stl.cpp:259:16:259:16 | call to operator* | TAINT | -| stl.cpp:263:28:263:33 | call to source | stl.cpp:263:28:263:36 | call to basic_string | TAINT | -| stl.cpp:263:28:263:36 | call to basic_string | stl.cpp:264:22:264:28 | const_s | | -| stl.cpp:264:22:264:22 | call to begin | stl.cpp:264:22:264:22 | (__begin) | | -| stl.cpp:264:22:264:22 | call to begin | stl.cpp:264:22:264:22 | (__begin) | | -| stl.cpp:264:22:264:22 | call to begin | stl.cpp:264:22:264:22 | (__begin) | | -| stl.cpp:264:22:264:22 | call to end | stl.cpp:264:22:264:22 | (__end) | | -| stl.cpp:264:22:264:22 | call to operator* | stl.cpp:265:8:265:8 | c | | -| stl.cpp:264:22:264:22 | ref arg (__begin) | stl.cpp:264:22:264:22 | (__begin) | | -| stl.cpp:264:22:264:22 | ref arg (__begin) | stl.cpp:264:22:264:22 | (__begin) | | -| stl.cpp:264:22:264:22 | ref arg (__begin) | stl.cpp:264:22:264:22 | (__begin) | | -| stl.cpp:264:22:264:28 | const_s | stl.cpp:264:22:264:22 | (__range) | | -| stl.cpp:264:22:264:28 | const_s | stl.cpp:264:22:264:22 | (__range) | | -| stl.cpp:264:22:264:28 | const_s | stl.cpp:264:22:264:22 | call to operator* | TAINT | -| stl.cpp:300:43:300:49 | source1 | stl.cpp:304:21:304:27 | source1 | | -| stl.cpp:300:43:300:49 | source1 | stl.cpp:318:33:318:39 | source1 | | -| stl.cpp:304:21:304:27 | source1 | stl.cpp:304:21:304:28 | call to vector | TAINT | -| stl.cpp:304:21:304:28 | call to vector | stl.cpp:306:14:306:14 | v | | -| stl.cpp:304:21:304:28 | call to vector | stl.cpp:310:38:310:38 | v | | -| stl.cpp:304:21:304:28 | call to vector | stl.cpp:310:55:310:55 | v | | -| stl.cpp:304:21:304:28 | call to vector | stl.cpp:314:15:314:15 | v | | -| stl.cpp:306:14:306:14 | call to begin | stl.cpp:306:14:306:14 | (__begin) | | -| stl.cpp:306:14:306:14 | call to begin | stl.cpp:306:14:306:14 | (__begin) | | -| stl.cpp:306:14:306:14 | call to begin | stl.cpp:306:14:306:14 | (__begin) | | -| stl.cpp:306:14:306:14 | call to end | stl.cpp:306:14:306:14 | (__end) | | -| stl.cpp:306:14:306:14 | call to operator* | stl.cpp:307:8:307:8 | x | | -| stl.cpp:306:14:306:14 | ref arg (__begin) | stl.cpp:306:14:306:14 | (__begin) | | -| stl.cpp:306:14:306:14 | ref arg (__begin) | stl.cpp:306:14:306:14 | (__begin) | | -| stl.cpp:306:14:306:14 | ref arg (__begin) | stl.cpp:306:14:306:14 | (__begin) | | -| stl.cpp:306:14:306:14 | ref arg (__range) | stl.cpp:306:14:306:14 | (__range) | | -| stl.cpp:306:14:306:14 | v | stl.cpp:306:14:306:14 | (__range) | | -| stl.cpp:306:14:306:14 | v | stl.cpp:306:14:306:14 | (__range) | | -| stl.cpp:306:14:306:14 | v | stl.cpp:306:14:306:14 | call to operator* | TAINT | -| stl.cpp:310:38:310:38 | ref arg v | stl.cpp:310:55:310:55 | v | | -| stl.cpp:310:38:310:38 | ref arg v | stl.cpp:314:15:314:15 | v | | -| stl.cpp:310:40:310:44 | call to begin | stl.cpp:310:49:310:50 | it | | -| stl.cpp:310:40:310:44 | call to begin | stl.cpp:310:66:310:67 | it | | -| stl.cpp:310:40:310:44 | call to begin | stl.cpp:311:9:311:10 | it | | -| stl.cpp:310:55:310:55 | ref arg v | stl.cpp:310:55:310:55 | v | | -| stl.cpp:310:55:310:55 | ref arg v | stl.cpp:314:15:314:15 | v | | -| stl.cpp:310:66:310:67 | ref arg it | stl.cpp:310:49:310:50 | it | | -| stl.cpp:310:66:310:67 | ref arg it | stl.cpp:310:66:310:67 | it | | -| stl.cpp:310:66:310:67 | ref arg it | stl.cpp:311:9:311:10 | it | | -| stl.cpp:314:15:314:15 | call to begin | stl.cpp:314:15:314:15 | (__begin) | | -| stl.cpp:314:15:314:15 | call to begin | stl.cpp:314:15:314:15 | (__begin) | | -| stl.cpp:314:15:314:15 | call to begin | stl.cpp:314:15:314:15 | (__begin) | | -| stl.cpp:314:15:314:15 | call to end | stl.cpp:314:15:314:15 | (__end) | | -| stl.cpp:314:15:314:15 | call to operator* | stl.cpp:315:8:315:8 | x | | -| stl.cpp:314:15:314:15 | ref arg (__begin) | stl.cpp:314:15:314:15 | (__begin) | | -| stl.cpp:314:15:314:15 | ref arg (__begin) | stl.cpp:314:15:314:15 | (__begin) | | -| stl.cpp:314:15:314:15 | ref arg (__begin) | stl.cpp:314:15:314:15 | (__begin) | | -| stl.cpp:314:15:314:15 | ref arg (__range) | stl.cpp:314:15:314:15 | (__range) | | -| stl.cpp:314:15:314:15 | v | stl.cpp:314:15:314:15 | (__range) | | -| stl.cpp:314:15:314:15 | v | stl.cpp:314:15:314:15 | (__range) | | -| stl.cpp:314:15:314:15 | v | stl.cpp:314:15:314:15 | call to operator* | TAINT | -| stl.cpp:318:33:318:39 | source1 | stl.cpp:318:33:318:40 | call to vector | TAINT | -| stl.cpp:318:33:318:40 | call to vector | stl.cpp:319:21:319:27 | const_v | | -| stl.cpp:319:21:319:21 | call to begin | stl.cpp:319:21:319:21 | (__begin) | | -| stl.cpp:319:21:319:21 | call to begin | stl.cpp:319:21:319:21 | (__begin) | | -| stl.cpp:319:21:319:21 | call to begin | stl.cpp:319:21:319:21 | (__begin) | | -| stl.cpp:319:21:319:21 | call to end | stl.cpp:319:21:319:21 | (__end) | | -| stl.cpp:319:21:319:21 | call to operator* | stl.cpp:320:8:320:8 | x | | -| stl.cpp:319:21:319:21 | ref arg (__begin) | stl.cpp:319:21:319:21 | (__begin) | | -| stl.cpp:319:21:319:21 | ref arg (__begin) | stl.cpp:319:21:319:21 | (__begin) | | -| stl.cpp:319:21:319:21 | ref arg (__begin) | stl.cpp:319:21:319:21 | (__begin) | | -| stl.cpp:319:21:319:27 | const_v | stl.cpp:319:21:319:21 | (__range) | | -| stl.cpp:319:21:319:27 | const_v | stl.cpp:319:21:319:21 | (__range) | | -| stl.cpp:319:21:319:27 | const_v | stl.cpp:319:21:319:21 | call to operator* | TAINT | -| stl.cpp:331:18:331:24 | hello | stl.cpp:331:18:331:25 | call to basic_string | TAINT | -| stl.cpp:331:18:331:25 | call to basic_string | stl.cpp:334:8:334:9 | s1 | | -| stl.cpp:331:18:331:25 | call to basic_string | stl.cpp:334:13:334:14 | s1 | | -| stl.cpp:331:18:331:25 | call to basic_string | stl.cpp:335:8:335:9 | s1 | | -| stl.cpp:331:18:331:25 | call to basic_string | stl.cpp:336:13:336:14 | s1 | | -| stl.cpp:331:18:331:25 | call to basic_string | stl.cpp:339:8:339:9 | s1 | | -| stl.cpp:331:18:331:25 | call to basic_string | stl.cpp:340:8:340:9 | s1 | | -| stl.cpp:332:18:332:23 | call to source | stl.cpp:332:18:332:26 | call to basic_string | TAINT | -| stl.cpp:332:18:332:26 | call to basic_string | stl.cpp:335:13:335:14 | s2 | | -| stl.cpp:332:18:332:26 | call to basic_string | stl.cpp:336:8:336:9 | s2 | | -| stl.cpp:332:18:332:26 | call to basic_string | stl.cpp:337:8:337:9 | s2 | | -| stl.cpp:332:18:332:26 | call to basic_string | stl.cpp:337:13:337:14 | s2 | | -| stl.cpp:334:8:334:9 | s1 | stl.cpp:334:11:334:11 | call to operator+ | TAINT | -| stl.cpp:334:13:334:14 | s1 | stl.cpp:334:11:334:11 | call to operator+ | TAINT | -| stl.cpp:335:8:335:9 | s1 | stl.cpp:335:11:335:11 | call to operator+ | TAINT | -| stl.cpp:335:13:335:14 | s2 | stl.cpp:335:11:335:11 | call to operator+ | TAINT | -| stl.cpp:336:8:336:9 | s2 | stl.cpp:336:11:336:11 | call to operator+ | TAINT | -| stl.cpp:336:13:336:14 | s1 | stl.cpp:336:11:336:11 | call to operator+ | TAINT | -| stl.cpp:337:8:337:9 | s2 | stl.cpp:337:11:337:11 | call to operator+ | TAINT | -| stl.cpp:337:13:337:14 | s2 | stl.cpp:337:11:337:11 | call to operator+ | TAINT | -| stl.cpp:339:8:339:9 | s1 | stl.cpp:339:11:339:11 | call to operator+ | TAINT | -| stl.cpp:339:13:339:20 | world | stl.cpp:339:11:339:11 | call to operator+ | TAINT | -| stl.cpp:340:8:340:9 | s1 | stl.cpp:340:11:340:11 | call to operator+ | TAINT | -| stl.cpp:340:13:340:18 | call to source | stl.cpp:340:11:340:11 | call to operator+ | TAINT | -| stl.cpp:344:18:344:22 | abc | stl.cpp:344:18:344:23 | call to basic_string | TAINT | -| stl.cpp:344:18:344:23 | call to basic_string | stl.cpp:348:8:348:9 | s3 | | -| stl.cpp:344:18:344:23 | call to basic_string | stl.cpp:351:8:351:9 | s3 | | -| stl.cpp:344:18:344:23 | call to basic_string | stl.cpp:355:8:355:9 | s3 | | -| stl.cpp:344:18:344:23 | call to basic_string | stl.cpp:360:8:360:9 | s3 | | -| stl.cpp:344:18:344:23 | call to basic_string | stl.cpp:364:8:364:9 | s3 | | -| stl.cpp:345:18:345:23 | call to source | stl.cpp:345:18:345:26 | call to basic_string | TAINT | -| stl.cpp:345:18:345:26 | call to basic_string | stl.cpp:348:13:348:14 | s4 | | -| stl.cpp:345:18:345:26 | call to basic_string | stl.cpp:352:9:352:10 | s4 | | -| stl.cpp:345:18:345:26 | call to basic_string | stl.cpp:361:13:361:14 | s4 | | -| stl.cpp:348:8:348:9 | s3 | stl.cpp:348:11:348:11 | call to operator+ | TAINT | -| stl.cpp:348:11:348:11 | call to operator+ | stl.cpp:348:3:348:14 | ... = ... | | -| stl.cpp:348:11:348:11 | call to operator+ | stl.cpp:349:8:349:9 | s5 | | -| stl.cpp:348:13:348:14 | s4 | stl.cpp:348:11:348:11 | call to operator+ | TAINT | -| stl.cpp:351:8:351:9 | s3 | stl.cpp:351:3:351:9 | ... = ... | | -| stl.cpp:351:8:351:9 | s3 | stl.cpp:352:3:352:4 | s6 | | -| stl.cpp:351:8:351:9 | s3 | stl.cpp:353:8:353:9 | s6 | | -| stl.cpp:352:3:352:4 | ref arg s6 | stl.cpp:353:8:353:9 | s6 | | -| stl.cpp:352:9:352:10 | s4 | stl.cpp:352:3:352:4 | ref arg s6 | TAINT | -| stl.cpp:352:9:352:10 | s4 | stl.cpp:352:6:352:6 | call to operator+= | TAINT | -| stl.cpp:355:8:355:9 | s3 | stl.cpp:355:3:355:9 | ... = ... | | -| stl.cpp:355:8:355:9 | s3 | stl.cpp:356:3:356:4 | s7 | | -| stl.cpp:355:8:355:9 | s3 | stl.cpp:357:3:357:4 | s7 | | -| stl.cpp:355:8:355:9 | s3 | stl.cpp:358:8:358:9 | s7 | | -| stl.cpp:356:3:356:4 | ref arg s7 | stl.cpp:357:3:357:4 | s7 | | -| stl.cpp:356:3:356:4 | ref arg s7 | stl.cpp:358:8:358:9 | s7 | | -| stl.cpp:356:9:356:14 | call to source | stl.cpp:356:3:356:4 | ref arg s7 | TAINT | -| stl.cpp:356:9:356:14 | call to source | stl.cpp:356:6:356:6 | call to operator+= | TAINT | -| stl.cpp:357:3:357:4 | ref arg s7 | stl.cpp:358:8:358:9 | s7 | | -| stl.cpp:357:9:357:11 | | stl.cpp:357:3:357:4 | ref arg s7 | TAINT | -| stl.cpp:357:9:357:11 | | stl.cpp:357:6:357:6 | call to operator+= | TAINT | -| stl.cpp:360:8:360:9 | s3 | stl.cpp:360:3:360:9 | ... = ... | | -| stl.cpp:360:8:360:9 | s3 | stl.cpp:361:3:361:4 | s8 | | -| stl.cpp:360:8:360:9 | s3 | stl.cpp:362:8:362:9 | s8 | | -| stl.cpp:361:3:361:4 | ref arg s8 | stl.cpp:362:8:362:9 | s8 | | -| stl.cpp:361:13:361:14 | s4 | stl.cpp:361:3:361:4 | ref arg s8 | TAINT | -| stl.cpp:361:13:361:14 | s4 | stl.cpp:361:6:361:11 | call to append | TAINT | -| stl.cpp:364:8:364:9 | s3 | stl.cpp:364:3:364:9 | ... = ... | | -| stl.cpp:364:8:364:9 | s3 | stl.cpp:365:3:365:4 | s9 | | -| stl.cpp:364:8:364:9 | s3 | stl.cpp:366:3:366:4 | s9 | | -| stl.cpp:364:8:364:9 | s3 | stl.cpp:367:8:367:9 | s9 | | -| stl.cpp:365:3:365:4 | ref arg s9 | stl.cpp:366:3:366:4 | s9 | | -| stl.cpp:365:3:365:4 | ref arg s9 | stl.cpp:367:8:367:9 | s9 | | -| stl.cpp:365:13:365:18 | call to source | stl.cpp:365:3:365:4 | ref arg s9 | TAINT | -| stl.cpp:365:13:365:18 | call to source | stl.cpp:365:6:365:11 | call to append | TAINT | -| stl.cpp:366:3:366:4 | ref arg s9 | stl.cpp:367:8:367:9 | s9 | | -| stl.cpp:366:13:366:15 | | stl.cpp:366:3:366:4 | ref arg s9 | TAINT | -| stl.cpp:366:13:366:15 | | stl.cpp:366:6:366:11 | call to append | TAINT | -| stl.cpp:371:19:371:23 | abc | stl.cpp:371:19:371:24 | call to basic_string | TAINT | -| stl.cpp:371:19:371:24 | call to basic_string | stl.cpp:374:3:374:5 | s10 | | -| stl.cpp:371:19:371:24 | call to basic_string | stl.cpp:375:8:375:10 | s10 | | -| stl.cpp:372:12:372:26 | call to source | stl.cpp:374:17:374:17 | c | | -| stl.cpp:374:3:374:5 | ref arg s10 | stl.cpp:375:8:375:10 | s10 | | -| stl.cpp:374:17:374:17 | c | stl.cpp:374:3:374:5 | ref arg s10 | TAINT | -| stl.cpp:374:17:374:17 | c | stl.cpp:374:7:374:12 | call to append | TAINT | +| string.cpp:11:12:11:17 | call to source | string.cpp:15:7:15:7 | a | | +| string.cpp:12:16:12:20 | 123 | string.cpp:12:16:12:21 | call to basic_string | TAINT | +| string.cpp:12:16:12:21 | call to basic_string | string.cpp:16:7:16:7 | b | | +| string.cpp:12:16:12:21 | call to basic_string | string.cpp:18:7:18:7 | b | | +| string.cpp:13:16:13:21 | call to source | string.cpp:13:16:13:24 | call to basic_string | TAINT | +| string.cpp:13:16:13:24 | call to basic_string | string.cpp:17:7:17:7 | c | | +| string.cpp:13:16:13:24 | call to basic_string | string.cpp:19:7:19:7 | c | | +| string.cpp:18:7:18:7 | b | string.cpp:18:9:18:13 | call to c_str | TAINT | +| string.cpp:19:7:19:7 | c | string.cpp:19:9:19:13 | call to c_str | TAINT | +| string.cpp:24:20:24:22 | call to basic_stringstream | string.cpp:27:2:27:4 | ss1 | | +| string.cpp:24:20:24:22 | call to basic_stringstream | string.cpp:33:7:33:9 | ss1 | | +| string.cpp:24:20:24:22 | call to basic_stringstream | string.cpp:38:7:38:9 | ss1 | | +| string.cpp:24:25:24:27 | call to basic_stringstream | string.cpp:28:2:28:4 | ss2 | | +| string.cpp:24:25:24:27 | call to basic_stringstream | string.cpp:34:7:34:9 | ss2 | | +| string.cpp:24:25:24:27 | call to basic_stringstream | string.cpp:39:7:39:9 | ss2 | | +| string.cpp:24:30:24:32 | call to basic_stringstream | string.cpp:29:2:29:4 | ss3 | | +| string.cpp:24:30:24:32 | call to basic_stringstream | string.cpp:35:7:35:9 | ss3 | | +| string.cpp:24:30:24:32 | call to basic_stringstream | string.cpp:40:7:40:9 | ss3 | | +| string.cpp:24:35:24:37 | call to basic_stringstream | string.cpp:30:2:30:4 | ss4 | | +| string.cpp:24:35:24:37 | call to basic_stringstream | string.cpp:36:7:36:9 | ss4 | | +| string.cpp:24:35:24:37 | call to basic_stringstream | string.cpp:41:7:41:9 | ss4 | | +| string.cpp:24:40:24:42 | call to basic_stringstream | string.cpp:31:2:31:4 | ss5 | | +| string.cpp:24:40:24:42 | call to basic_stringstream | string.cpp:37:7:37:9 | ss5 | | +| string.cpp:24:40:24:42 | call to basic_stringstream | string.cpp:42:7:42:9 | ss5 | | +| string.cpp:25:16:25:21 | call to source | string.cpp:25:16:25:24 | call to basic_string | TAINT | +| string.cpp:25:16:25:24 | call to basic_string | string.cpp:31:9:31:9 | t | | +| string.cpp:27:2:27:4 | ref arg ss1 | string.cpp:33:7:33:9 | ss1 | | +| string.cpp:27:2:27:4 | ref arg ss1 | string.cpp:38:7:38:9 | ss1 | | +| string.cpp:28:2:28:4 | ref arg ss2 | string.cpp:34:7:34:9 | ss2 | | +| string.cpp:28:2:28:4 | ref arg ss2 | string.cpp:39:7:39:9 | ss2 | | +| string.cpp:29:2:29:4 | ref arg ss3 | string.cpp:35:7:35:9 | ss3 | | +| string.cpp:29:2:29:4 | ref arg ss3 | string.cpp:40:7:40:9 | ss3 | | +| string.cpp:30:2:30:4 | ref arg ss4 | string.cpp:36:7:36:9 | ss4 | | +| string.cpp:30:2:30:4 | ref arg ss4 | string.cpp:41:7:41:9 | ss4 | | +| string.cpp:31:2:31:4 | ref arg ss5 | string.cpp:37:7:37:9 | ss5 | | +| string.cpp:31:2:31:4 | ref arg ss5 | string.cpp:42:7:42:9 | ss5 | | +| string.cpp:45:32:45:37 | source | string.cpp:50:9:50:14 | source | | +| string.cpp:47:20:47:22 | call to basic_stringstream | string.cpp:49:2:49:4 | ss1 | | +| string.cpp:47:20:47:22 | call to basic_stringstream | string.cpp:52:7:52:9 | ss1 | | +| string.cpp:47:20:47:22 | call to basic_stringstream | string.cpp:54:7:54:9 | ss1 | | +| string.cpp:47:25:47:27 | call to basic_stringstream | string.cpp:50:2:50:4 | ss2 | | +| string.cpp:47:25:47:27 | call to basic_stringstream | string.cpp:53:7:53:9 | ss2 | | +| string.cpp:47:25:47:27 | call to basic_stringstream | string.cpp:55:7:55:9 | ss2 | | +| string.cpp:49:2:49:4 | ref arg ss1 | string.cpp:52:7:52:9 | ss1 | | +| string.cpp:49:2:49:4 | ref arg ss1 | string.cpp:54:7:54:9 | ss1 | | +| string.cpp:50:2:50:4 | ref arg ss2 | string.cpp:53:7:53:9 | ss2 | | +| string.cpp:50:2:50:4 | ref arg ss2 | string.cpp:55:7:55:9 | ss2 | | +| string.cpp:68:16:68:28 | call to basic_string | string.cpp:69:7:69:11 | path1 | | +| string.cpp:68:17:68:26 | call to user_input | string.cpp:68:16:68:28 | call to basic_string | TAINT | +| string.cpp:69:7:69:11 | path1 | string.cpp:69:13:69:17 | call to c_str | TAINT | +| string.cpp:72:10:72:19 | call to user_input | string.cpp:72:10:72:21 | call to basic_string | TAINT | +| string.cpp:72:10:72:21 | call to basic_string | string.cpp:72:2:72:21 | ... = ... | | +| string.cpp:72:10:72:21 | call to basic_string | string.cpp:73:7:73:11 | path2 | | +| string.cpp:73:7:73:11 | path2 | string.cpp:73:13:73:17 | call to c_str | TAINT | +| string.cpp:75:15:75:24 | call to user_input | string.cpp:75:15:75:27 | call to basic_string | TAINT | +| string.cpp:75:15:75:27 | call to basic_string | string.cpp:76:7:76:11 | path3 | | +| string.cpp:76:7:76:11 | path3 | string.cpp:76:13:76:17 | call to c_str | TAINT | +| string.cpp:81:19:81:24 | call to source | string.cpp:84:17:84:18 | cs | | +| string.cpp:81:19:81:24 | call to source | string.cpp:86:7:86:8 | cs | | +| string.cpp:84:17:84:18 | cs | string.cpp:84:17:84:19 | call to basic_string | TAINT | +| string.cpp:84:17:84:19 | call to basic_string | string.cpp:87:7:87:8 | ss | | +| string.cpp:92:19:92:24 | call to source | string.cpp:95:17:95:18 | cs | | +| string.cpp:95:17:95:18 | cs | string.cpp:95:17:95:19 | call to basic_string | TAINT | +| string.cpp:95:17:95:19 | call to basic_string | string.cpp:98:7:98:8 | ss | | +| string.cpp:95:17:95:19 | call to basic_string | string.cpp:101:7:101:8 | ss | | +| string.cpp:98:7:98:8 | ss | string.cpp:98:10:98:14 | call to c_str | TAINT | +| string.cpp:98:10:98:14 | call to c_str | string.cpp:98:2:98:16 | ... = ... | | +| string.cpp:98:10:98:14 | call to c_str | string.cpp:100:7:100:8 | cs | | +| string.cpp:107:18:107:24 | hello | string.cpp:107:18:107:25 | call to basic_string | TAINT | +| string.cpp:107:18:107:25 | call to basic_string | string.cpp:112:8:112:9 | s1 | | +| string.cpp:108:19:108:26 | call to basic_string | string.cpp:113:8:113:9 | s2 | | +| string.cpp:108:20:108:26 | hello | string.cpp:108:19:108:26 | call to basic_string | TAINT | +| string.cpp:110:8:110:14 | call to basic_string | string.cpp:110:3:110:14 | ... = ... | | +| string.cpp:110:8:110:14 | call to basic_string | string.cpp:114:8:114:9 | s3 | | +| string.cpp:110:8:110:14 | hello | string.cpp:110:8:110:14 | call to basic_string | TAINT | +| string.cpp:118:18:118:23 | call to source | string.cpp:118:18:118:26 | call to basic_string | TAINT | +| string.cpp:118:18:118:26 | call to basic_string | string.cpp:123:8:123:9 | s1 | | +| string.cpp:119:19:119:27 | call to basic_string | string.cpp:124:8:124:9 | s2 | | +| string.cpp:119:20:119:25 | call to source | string.cpp:119:19:119:27 | call to basic_string | TAINT | +| string.cpp:121:8:121:13 | call to source | string.cpp:121:8:121:15 | call to basic_string | TAINT | +| string.cpp:121:8:121:15 | call to basic_string | string.cpp:121:3:121:15 | ... = ... | | +| string.cpp:121:8:121:15 | call to basic_string | string.cpp:125:8:125:9 | s3 | | +| string.cpp:129:15:129:16 | call to basic_string | string.cpp:130:20:130:21 | s1 | | +| string.cpp:129:15:129:16 | call to basic_string | string.cpp:132:8:132:9 | s1 | | +| string.cpp:129:15:129:16 | call to basic_string | string.cpp:134:8:134:9 | s1 | | +| string.cpp:130:20:130:21 | s1 | string.cpp:135:8:135:9 | s2 | | +| string.cpp:132:8:132:9 | s1 | string.cpp:132:3:132:9 | ... = ... | | +| string.cpp:132:8:132:9 | s1 | string.cpp:136:8:136:9 | s3 | | +| string.cpp:140:19:140:40 | call to basic_string | string.cpp:144:8:144:9 | s1 | | +| string.cpp:140:32:140:37 | call to source | string.cpp:140:19:140:40 | call to basic_string | TAINT | +| string.cpp:142:8:142:28 | call to basic_string | string.cpp:142:3:142:28 | ... = ... | | +| string.cpp:142:8:142:28 | call to basic_string | string.cpp:145:8:145:9 | s2 | | +| string.cpp:142:20:142:25 | call to source | string.cpp:142:8:142:28 | call to basic_string | TAINT | +| string.cpp:152:16:152:21 | call to source | string.cpp:152:16:152:24 | call to basic_string | TAINT | +| string.cpp:152:16:152:24 | call to basic_string | string.cpp:153:15:153:15 | s | | +| string.cpp:152:16:152:24 | call to basic_string | string.cpp:157:33:157:33 | s | | +| string.cpp:152:16:152:24 | call to basic_string | string.cpp:157:50:157:50 | s | | +| string.cpp:152:16:152:24 | call to basic_string | string.cpp:161:16:161:16 | s | | +| string.cpp:153:15:153:15 | call to begin | string.cpp:153:15:153:15 | (__begin) | | +| string.cpp:153:15:153:15 | call to begin | string.cpp:153:15:153:15 | (__begin) | | +| string.cpp:153:15:153:15 | call to begin | string.cpp:153:15:153:15 | (__begin) | | +| string.cpp:153:15:153:15 | call to end | string.cpp:153:15:153:15 | (__end) | | +| string.cpp:153:15:153:15 | call to operator* | string.cpp:154:8:154:8 | c | | +| string.cpp:153:15:153:15 | ref arg (__begin) | string.cpp:153:15:153:15 | (__begin) | | +| string.cpp:153:15:153:15 | ref arg (__begin) | string.cpp:153:15:153:15 | (__begin) | | +| string.cpp:153:15:153:15 | ref arg (__begin) | string.cpp:153:15:153:15 | (__begin) | | +| string.cpp:153:15:153:15 | ref arg (__range) | string.cpp:153:15:153:15 | (__range) | | +| string.cpp:153:15:153:15 | s | string.cpp:153:15:153:15 | (__range) | | +| string.cpp:153:15:153:15 | s | string.cpp:153:15:153:15 | (__range) | | +| string.cpp:153:15:153:15 | s | string.cpp:153:15:153:15 | call to operator* | TAINT | +| string.cpp:157:33:157:33 | ref arg s | string.cpp:157:50:157:50 | s | | +| string.cpp:157:33:157:33 | ref arg s | string.cpp:161:16:161:16 | s | | +| string.cpp:157:35:157:39 | call to begin | string.cpp:157:44:157:45 | it | | +| string.cpp:157:35:157:39 | call to begin | string.cpp:157:61:157:62 | it | | +| string.cpp:157:35:157:39 | call to begin | string.cpp:158:9:158:10 | it | | +| string.cpp:157:50:157:50 | ref arg s | string.cpp:157:50:157:50 | s | | +| string.cpp:157:50:157:50 | ref arg s | string.cpp:161:16:161:16 | s | | +| string.cpp:157:61:157:62 | ref arg it | string.cpp:157:44:157:45 | it | | +| string.cpp:157:61:157:62 | ref arg it | string.cpp:157:61:157:62 | it | | +| string.cpp:157:61:157:62 | ref arg it | string.cpp:158:9:158:10 | it | | +| string.cpp:161:16:161:16 | call to begin | string.cpp:161:16:161:16 | (__begin) | | +| string.cpp:161:16:161:16 | call to begin | string.cpp:161:16:161:16 | (__begin) | | +| string.cpp:161:16:161:16 | call to begin | string.cpp:161:16:161:16 | (__begin) | | +| string.cpp:161:16:161:16 | call to end | string.cpp:161:16:161:16 | (__end) | | +| string.cpp:161:16:161:16 | call to operator* | string.cpp:162:8:162:8 | c | | +| string.cpp:161:16:161:16 | ref arg (__begin) | string.cpp:161:16:161:16 | (__begin) | | +| string.cpp:161:16:161:16 | ref arg (__begin) | string.cpp:161:16:161:16 | (__begin) | | +| string.cpp:161:16:161:16 | ref arg (__begin) | string.cpp:161:16:161:16 | (__begin) | | +| string.cpp:161:16:161:16 | ref arg (__range) | string.cpp:161:16:161:16 | (__range) | | +| string.cpp:161:16:161:16 | s | string.cpp:161:16:161:16 | (__range) | | +| string.cpp:161:16:161:16 | s | string.cpp:161:16:161:16 | (__range) | | +| string.cpp:161:16:161:16 | s | string.cpp:161:16:161:16 | call to operator* | TAINT | +| string.cpp:165:28:165:33 | call to source | string.cpp:165:28:165:36 | call to basic_string | TAINT | +| string.cpp:165:28:165:36 | call to basic_string | string.cpp:166:22:166:28 | const_s | | +| string.cpp:166:22:166:22 | call to begin | string.cpp:166:22:166:22 | (__begin) | | +| string.cpp:166:22:166:22 | call to begin | string.cpp:166:22:166:22 | (__begin) | | +| string.cpp:166:22:166:22 | call to begin | string.cpp:166:22:166:22 | (__begin) | | +| string.cpp:166:22:166:22 | call to end | string.cpp:166:22:166:22 | (__end) | | +| string.cpp:166:22:166:22 | call to operator* | string.cpp:167:8:167:8 | c | | +| string.cpp:166:22:166:22 | ref arg (__begin) | string.cpp:166:22:166:22 | (__begin) | | +| string.cpp:166:22:166:22 | ref arg (__begin) | string.cpp:166:22:166:22 | (__begin) | | +| string.cpp:166:22:166:22 | ref arg (__begin) | string.cpp:166:22:166:22 | (__begin) | | +| string.cpp:166:22:166:28 | const_s | string.cpp:166:22:166:22 | (__range) | | +| string.cpp:166:22:166:28 | const_s | string.cpp:166:22:166:22 | (__range) | | +| string.cpp:166:22:166:28 | const_s | string.cpp:166:22:166:22 | call to operator* | TAINT | +| string.cpp:178:18:178:24 | hello | string.cpp:178:18:178:25 | call to basic_string | TAINT | +| string.cpp:178:18:178:25 | call to basic_string | string.cpp:181:8:181:9 | s1 | | +| string.cpp:178:18:178:25 | call to basic_string | string.cpp:181:13:181:14 | s1 | | +| string.cpp:178:18:178:25 | call to basic_string | string.cpp:182:8:182:9 | s1 | | +| string.cpp:178:18:178:25 | call to basic_string | string.cpp:183:13:183:14 | s1 | | +| string.cpp:178:18:178:25 | call to basic_string | string.cpp:186:8:186:9 | s1 | | +| string.cpp:178:18:178:25 | call to basic_string | string.cpp:187:8:187:9 | s1 | | +| string.cpp:179:18:179:23 | call to source | string.cpp:179:18:179:26 | call to basic_string | TAINT | +| string.cpp:179:18:179:26 | call to basic_string | string.cpp:182:13:182:14 | s2 | | +| string.cpp:179:18:179:26 | call to basic_string | string.cpp:183:8:183:9 | s2 | | +| string.cpp:179:18:179:26 | call to basic_string | string.cpp:184:8:184:9 | s2 | | +| string.cpp:179:18:179:26 | call to basic_string | string.cpp:184:13:184:14 | s2 | | +| string.cpp:181:8:181:9 | s1 | string.cpp:181:11:181:11 | call to operator+ | TAINT | +| string.cpp:181:13:181:14 | s1 | string.cpp:181:11:181:11 | call to operator+ | TAINT | +| string.cpp:182:8:182:9 | s1 | string.cpp:182:11:182:11 | call to operator+ | TAINT | +| string.cpp:182:13:182:14 | s2 | string.cpp:182:11:182:11 | call to operator+ | TAINT | +| string.cpp:183:8:183:9 | s2 | string.cpp:183:11:183:11 | call to operator+ | TAINT | +| string.cpp:183:13:183:14 | s1 | string.cpp:183:11:183:11 | call to operator+ | TAINT | +| string.cpp:184:8:184:9 | s2 | string.cpp:184:11:184:11 | call to operator+ | TAINT | +| string.cpp:184:13:184:14 | s2 | string.cpp:184:11:184:11 | call to operator+ | TAINT | +| string.cpp:186:8:186:9 | s1 | string.cpp:186:11:186:11 | call to operator+ | TAINT | +| string.cpp:186:13:186:20 | world | string.cpp:186:11:186:11 | call to operator+ | TAINT | +| string.cpp:187:8:187:9 | s1 | string.cpp:187:11:187:11 | call to operator+ | TAINT | +| string.cpp:187:13:187:18 | call to source | string.cpp:187:11:187:11 | call to operator+ | TAINT | +| string.cpp:191:18:191:22 | abc | string.cpp:191:18:191:23 | call to basic_string | TAINT | +| string.cpp:191:18:191:23 | call to basic_string | string.cpp:195:8:195:9 | s3 | | +| string.cpp:191:18:191:23 | call to basic_string | string.cpp:198:8:198:9 | s3 | | +| string.cpp:191:18:191:23 | call to basic_string | string.cpp:202:8:202:9 | s3 | | +| string.cpp:191:18:191:23 | call to basic_string | string.cpp:207:8:207:9 | s3 | | +| string.cpp:191:18:191:23 | call to basic_string | string.cpp:211:8:211:9 | s3 | | +| string.cpp:192:18:192:23 | call to source | string.cpp:192:18:192:26 | call to basic_string | TAINT | +| string.cpp:192:18:192:26 | call to basic_string | string.cpp:195:13:195:14 | s4 | | +| string.cpp:192:18:192:26 | call to basic_string | string.cpp:199:9:199:10 | s4 | | +| string.cpp:192:18:192:26 | call to basic_string | string.cpp:208:13:208:14 | s4 | | +| string.cpp:195:8:195:9 | s3 | string.cpp:195:11:195:11 | call to operator+ | TAINT | +| string.cpp:195:11:195:11 | call to operator+ | string.cpp:195:3:195:14 | ... = ... | | +| string.cpp:195:11:195:11 | call to operator+ | string.cpp:196:8:196:9 | s5 | | +| string.cpp:195:13:195:14 | s4 | string.cpp:195:11:195:11 | call to operator+ | TAINT | +| string.cpp:198:8:198:9 | s3 | string.cpp:198:3:198:9 | ... = ... | | +| string.cpp:198:8:198:9 | s3 | string.cpp:199:3:199:4 | s6 | | +| string.cpp:198:8:198:9 | s3 | string.cpp:200:8:200:9 | s6 | | +| string.cpp:199:3:199:4 | ref arg s6 | string.cpp:200:8:200:9 | s6 | | +| string.cpp:199:9:199:10 | s4 | string.cpp:199:3:199:4 | ref arg s6 | TAINT | +| string.cpp:199:9:199:10 | s4 | string.cpp:199:6:199:6 | call to operator+= | TAINT | +| string.cpp:202:8:202:9 | s3 | string.cpp:202:3:202:9 | ... = ... | | +| string.cpp:202:8:202:9 | s3 | string.cpp:203:3:203:4 | s7 | | +| string.cpp:202:8:202:9 | s3 | string.cpp:204:3:204:4 | s7 | | +| string.cpp:202:8:202:9 | s3 | string.cpp:205:8:205:9 | s7 | | +| string.cpp:203:3:203:4 | ref arg s7 | string.cpp:204:3:204:4 | s7 | | +| string.cpp:203:3:203:4 | ref arg s7 | string.cpp:205:8:205:9 | s7 | | +| string.cpp:203:9:203:14 | call to source | string.cpp:203:3:203:4 | ref arg s7 | TAINT | +| string.cpp:203:9:203:14 | call to source | string.cpp:203:6:203:6 | call to operator+= | TAINT | +| string.cpp:204:3:204:4 | ref arg s7 | string.cpp:205:8:205:9 | s7 | | +| string.cpp:204:9:204:11 | | string.cpp:204:3:204:4 | ref arg s7 | TAINT | +| string.cpp:204:9:204:11 | | string.cpp:204:6:204:6 | call to operator+= | TAINT | +| string.cpp:207:8:207:9 | s3 | string.cpp:207:3:207:9 | ... = ... | | +| string.cpp:207:8:207:9 | s3 | string.cpp:208:3:208:4 | s8 | | +| string.cpp:207:8:207:9 | s3 | string.cpp:209:8:209:9 | s8 | | +| string.cpp:208:3:208:4 | ref arg s8 | string.cpp:209:8:209:9 | s8 | | +| string.cpp:208:13:208:14 | s4 | string.cpp:208:3:208:4 | ref arg s8 | TAINT | +| string.cpp:208:13:208:14 | s4 | string.cpp:208:6:208:11 | call to append | TAINT | +| string.cpp:211:8:211:9 | s3 | string.cpp:211:3:211:9 | ... = ... | | +| string.cpp:211:8:211:9 | s3 | string.cpp:212:3:212:4 | s9 | | +| string.cpp:211:8:211:9 | s3 | string.cpp:213:3:213:4 | s9 | | +| string.cpp:211:8:211:9 | s3 | string.cpp:214:8:214:9 | s9 | | +| string.cpp:212:3:212:4 | ref arg s9 | string.cpp:213:3:213:4 | s9 | | +| string.cpp:212:3:212:4 | ref arg s9 | string.cpp:214:8:214:9 | s9 | | +| string.cpp:212:13:212:18 | call to source | string.cpp:212:3:212:4 | ref arg s9 | TAINT | +| string.cpp:212:13:212:18 | call to source | string.cpp:212:6:212:11 | call to append | TAINT | +| string.cpp:213:3:213:4 | ref arg s9 | string.cpp:214:8:214:9 | s9 | | +| string.cpp:213:13:213:15 | | string.cpp:213:3:213:4 | ref arg s9 | TAINT | +| string.cpp:213:13:213:15 | | string.cpp:213:6:213:11 | call to append | TAINT | +| string.cpp:218:19:218:23 | abc | string.cpp:218:19:218:24 | call to basic_string | TAINT | +| string.cpp:218:19:218:24 | call to basic_string | string.cpp:221:3:221:5 | s10 | | +| string.cpp:218:19:218:24 | call to basic_string | string.cpp:222:8:222:10 | s10 | | +| string.cpp:219:12:219:26 | call to source | string.cpp:221:17:221:17 | c | | +| string.cpp:221:3:221:5 | ref arg s10 | string.cpp:222:8:222:10 | s10 | | +| string.cpp:221:17:221:17 | c | string.cpp:221:3:221:5 | ref arg s10 | TAINT | +| string.cpp:221:17:221:17 | c | string.cpp:221:7:221:12 | call to append | TAINT | | structlikeclass.cpp:5:7:5:7 | Unknown literal | structlikeclass.cpp:5:7:5:7 | constructor init of field v | TAINT | | structlikeclass.cpp:5:7:5:7 | Unknown literal | structlikeclass.cpp:5:7:5:7 | constructor init of field v | TAINT | | structlikeclass.cpp:5:7:5:7 | this | structlikeclass.cpp:5:7:5:7 | constructor init of field v [pre-this] | | @@ -1384,3 +1330,57 @@ | taint.cpp:483:18:483:19 | ref arg & ... | taint.cpp:483:19:483:19 | n [inner post update] | | | taint.cpp:483:19:483:19 | n | taint.cpp:483:18:483:19 | & ... | | | taint.cpp:483:28:483:34 | source1 | taint.cpp:483:11:483:15 | ref arg & ... | TAINT | +| vector.cpp:8:43:8:49 | source1 | vector.cpp:12:21:12:27 | source1 | | +| vector.cpp:8:43:8:49 | source1 | vector.cpp:26:33:26:39 | source1 | | +| vector.cpp:12:21:12:27 | source1 | vector.cpp:12:21:12:28 | call to vector | TAINT | +| vector.cpp:12:21:12:28 | call to vector | vector.cpp:14:14:14:14 | v | | +| vector.cpp:12:21:12:28 | call to vector | vector.cpp:18:38:18:38 | v | | +| vector.cpp:12:21:12:28 | call to vector | vector.cpp:18:55:18:55 | v | | +| vector.cpp:12:21:12:28 | call to vector | vector.cpp:22:15:22:15 | v | | +| vector.cpp:14:14:14:14 | call to begin | vector.cpp:14:14:14:14 | (__begin) | | +| vector.cpp:14:14:14:14 | call to begin | vector.cpp:14:14:14:14 | (__begin) | | +| vector.cpp:14:14:14:14 | call to begin | vector.cpp:14:14:14:14 | (__begin) | | +| vector.cpp:14:14:14:14 | call to end | vector.cpp:14:14:14:14 | (__end) | | +| vector.cpp:14:14:14:14 | call to operator* | vector.cpp:15:8:15:8 | x | | +| vector.cpp:14:14:14:14 | ref arg (__begin) | vector.cpp:14:14:14:14 | (__begin) | | +| vector.cpp:14:14:14:14 | ref arg (__begin) | vector.cpp:14:14:14:14 | (__begin) | | +| vector.cpp:14:14:14:14 | ref arg (__begin) | vector.cpp:14:14:14:14 | (__begin) | | +| vector.cpp:14:14:14:14 | ref arg (__range) | vector.cpp:14:14:14:14 | (__range) | | +| vector.cpp:14:14:14:14 | v | vector.cpp:14:14:14:14 | (__range) | | +| vector.cpp:14:14:14:14 | v | vector.cpp:14:14:14:14 | (__range) | | +| vector.cpp:14:14:14:14 | v | vector.cpp:14:14:14:14 | call to operator* | TAINT | +| vector.cpp:18:38:18:38 | ref arg v | vector.cpp:18:55:18:55 | v | | +| vector.cpp:18:38:18:38 | ref arg v | vector.cpp:22:15:22:15 | v | | +| vector.cpp:18:40:18:44 | call to begin | vector.cpp:18:49:18:50 | it | | +| vector.cpp:18:40:18:44 | call to begin | vector.cpp:18:66:18:67 | it | | +| vector.cpp:18:40:18:44 | call to begin | vector.cpp:19:9:19:10 | it | | +| vector.cpp:18:55:18:55 | ref arg v | vector.cpp:18:55:18:55 | v | | +| vector.cpp:18:55:18:55 | ref arg v | vector.cpp:22:15:22:15 | v | | +| vector.cpp:18:66:18:67 | ref arg it | vector.cpp:18:49:18:50 | it | | +| vector.cpp:18:66:18:67 | ref arg it | vector.cpp:18:66:18:67 | it | | +| vector.cpp:18:66:18:67 | ref arg it | vector.cpp:19:9:19:10 | it | | +| vector.cpp:22:15:22:15 | call to begin | vector.cpp:22:15:22:15 | (__begin) | | +| vector.cpp:22:15:22:15 | call to begin | vector.cpp:22:15:22:15 | (__begin) | | +| vector.cpp:22:15:22:15 | call to begin | vector.cpp:22:15:22:15 | (__begin) | | +| vector.cpp:22:15:22:15 | call to end | vector.cpp:22:15:22:15 | (__end) | | +| vector.cpp:22:15:22:15 | call to operator* | vector.cpp:23:8:23:8 | x | | +| vector.cpp:22:15:22:15 | ref arg (__begin) | vector.cpp:22:15:22:15 | (__begin) | | +| vector.cpp:22:15:22:15 | ref arg (__begin) | vector.cpp:22:15:22:15 | (__begin) | | +| vector.cpp:22:15:22:15 | ref arg (__begin) | vector.cpp:22:15:22:15 | (__begin) | | +| vector.cpp:22:15:22:15 | ref arg (__range) | vector.cpp:22:15:22:15 | (__range) | | +| vector.cpp:22:15:22:15 | v | vector.cpp:22:15:22:15 | (__range) | | +| vector.cpp:22:15:22:15 | v | vector.cpp:22:15:22:15 | (__range) | | +| vector.cpp:22:15:22:15 | v | vector.cpp:22:15:22:15 | call to operator* | TAINT | +| vector.cpp:26:33:26:39 | source1 | vector.cpp:26:33:26:40 | call to vector | TAINT | +| vector.cpp:26:33:26:40 | call to vector | vector.cpp:27:21:27:27 | const_v | | +| vector.cpp:27:21:27:21 | call to begin | vector.cpp:27:21:27:21 | (__begin) | | +| vector.cpp:27:21:27:21 | call to begin | vector.cpp:27:21:27:21 | (__begin) | | +| vector.cpp:27:21:27:21 | call to begin | vector.cpp:27:21:27:21 | (__begin) | | +| vector.cpp:27:21:27:21 | call to end | vector.cpp:27:21:27:21 | (__end) | | +| vector.cpp:27:21:27:21 | call to operator* | vector.cpp:28:8:28:8 | x | | +| vector.cpp:27:21:27:21 | ref arg (__begin) | vector.cpp:27:21:27:21 | (__begin) | | +| vector.cpp:27:21:27:21 | ref arg (__begin) | vector.cpp:27:21:27:21 | (__begin) | | +| vector.cpp:27:21:27:21 | ref arg (__begin) | vector.cpp:27:21:27:21 | (__begin) | | +| vector.cpp:27:21:27:27 | const_v | vector.cpp:27:21:27:21 | (__range) | | +| vector.cpp:27:21:27:27 | const_v | vector.cpp:27:21:27:21 | (__range) | | +| vector.cpp:27:21:27:27 | const_v | vector.cpp:27:21:27:21 | call to operator* | TAINT | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp similarity index 82% rename from cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp rename to cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp index 02fa029850d..07314e4b2ab 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp @@ -1,104 +1,6 @@ #include "stl.h" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - char *source(); void sink(const char *s) {}; void sink(const std::string &s) {}; @@ -266,61 +168,6 @@ void test_range_based_for_loop_string() { } } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void sink(int); - -void test_range_based_for_loop_vector(int source1) { - // Tainting the vector by allocating a tainted length. This doesn't represent - // how a vector would typically get tainted, but it allows this test to avoid - // being concerned with std::vector modeling. - std::vector v(source1); - - for(int x : v) { - sink(x); // tainted [NOT DETECTED by IR] - } - - for(std::vector::iterator it = v.begin(); it != v.end(); ++it) { - sink(*it); // tainted [NOT DETECTED] - } - - for(int& x : v) { - sink(x); // tainted [NOT DETECTED by IR] - } - - const std::vector const_v(source1); - for(const int& x : const_v) { - sink(x); // tainted [NOT DETECTED by IR] - } -} - namespace ns_char { char source(); diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected index 3c3ed47e351..8647fddaaf5 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -32,37 +32,34 @@ | movableclass.cpp:55:8:55:9 | s2 | movableclass.cpp:52:23:52:28 | call to source | | movableclass.cpp:64:8:64:9 | s2 | movableclass.cpp:23:55:23:60 | call to source | | movableclass.cpp:65:11:65:11 | call to operator= | movableclass.cpp:65:13:65:18 | call to source | -| stl.cpp:113:7:113:7 | a | stl.cpp:109:12:109:17 | call to source | -| stl.cpp:115:7:115:7 | c | stl.cpp:111:16:111:21 | call to source | -| stl.cpp:117:9:117:13 | call to c_str | stl.cpp:111:16:111:21 | call to source | -| stl.cpp:167:13:167:17 | call to c_str | stl.cpp:159:10:159:15 | call to source | -| stl.cpp:171:13:171:17 | call to c_str | stl.cpp:159:10:159:15 | call to source | -| stl.cpp:174:13:174:17 | call to c_str | stl.cpp:159:10:159:15 | call to source | -| stl.cpp:184:7:184:8 | cs | stl.cpp:179:19:179:24 | call to source | -| stl.cpp:185:7:185:8 | ss | stl.cpp:179:19:179:24 | call to source | -| stl.cpp:198:7:198:8 | cs | stl.cpp:190:19:190:24 | call to source | -| stl.cpp:199:7:199:8 | ss | stl.cpp:190:19:190:24 | call to source | -| stl.cpp:221:8:221:9 | s1 | stl.cpp:216:18:216:23 | call to source | -| stl.cpp:222:8:222:9 | s2 | stl.cpp:217:20:217:25 | call to source | -| stl.cpp:223:8:223:9 | s3 | stl.cpp:219:8:219:13 | call to source | -| stl.cpp:242:8:242:9 | s1 | stl.cpp:238:32:238:37 | call to source | -| stl.cpp:243:8:243:9 | s2 | stl.cpp:240:20:240:25 | call to source | -| stl.cpp:252:8:252:8 | c | stl.cpp:250:16:250:21 | call to source | -| stl.cpp:260:8:260:8 | c | stl.cpp:250:16:250:21 | call to source | -| stl.cpp:265:8:265:8 | c | stl.cpp:263:28:263:33 | call to source | -| stl.cpp:307:8:307:8 | x | stl.cpp:300:43:300:49 | source1 | -| stl.cpp:315:8:315:8 | x | stl.cpp:300:43:300:49 | source1 | -| stl.cpp:320:8:320:8 | x | stl.cpp:300:43:300:49 | source1 | -| stl.cpp:335:11:335:11 | call to operator+ | stl.cpp:332:18:332:23 | call to source | -| stl.cpp:336:11:336:11 | call to operator+ | stl.cpp:332:18:332:23 | call to source | -| stl.cpp:337:11:337:11 | call to operator+ | stl.cpp:332:18:332:23 | call to source | -| stl.cpp:340:11:340:11 | call to operator+ | stl.cpp:340:13:340:18 | call to source | -| stl.cpp:349:8:349:9 | s5 | stl.cpp:345:18:345:23 | call to source | -| stl.cpp:353:8:353:9 | s6 | stl.cpp:345:18:345:23 | call to source | -| stl.cpp:358:8:358:9 | s7 | stl.cpp:356:9:356:14 | call to source | -| stl.cpp:362:8:362:9 | s8 | stl.cpp:345:18:345:23 | call to source | -| stl.cpp:367:8:367:9 | s9 | stl.cpp:365:13:365:18 | call to source | -| stl.cpp:375:8:375:10 | s10 | stl.cpp:372:12:372:26 | call to source | +| string.cpp:15:7:15:7 | a | string.cpp:11:12:11:17 | call to source | +| string.cpp:17:7:17:7 | c | string.cpp:13:16:13:21 | call to source | +| string.cpp:19:9:19:13 | call to c_str | string.cpp:13:16:13:21 | call to source | +| string.cpp:69:13:69:17 | call to c_str | string.cpp:61:10:61:15 | call to source | +| string.cpp:73:13:73:17 | call to c_str | string.cpp:61:10:61:15 | call to source | +| string.cpp:76:13:76:17 | call to c_str | string.cpp:61:10:61:15 | call to source | +| string.cpp:86:7:86:8 | cs | string.cpp:81:19:81:24 | call to source | +| string.cpp:87:7:87:8 | ss | string.cpp:81:19:81:24 | call to source | +| string.cpp:100:7:100:8 | cs | string.cpp:92:19:92:24 | call to source | +| string.cpp:101:7:101:8 | ss | string.cpp:92:19:92:24 | call to source | +| string.cpp:123:8:123:9 | s1 | string.cpp:118:18:118:23 | call to source | +| string.cpp:124:8:124:9 | s2 | string.cpp:119:20:119:25 | call to source | +| string.cpp:125:8:125:9 | s3 | string.cpp:121:8:121:13 | call to source | +| string.cpp:144:8:144:9 | s1 | string.cpp:140:32:140:37 | call to source | +| string.cpp:145:8:145:9 | s2 | string.cpp:142:20:142:25 | call to source | +| string.cpp:154:8:154:8 | c | string.cpp:152:16:152:21 | call to source | +| string.cpp:162:8:162:8 | c | string.cpp:152:16:152:21 | call to source | +| string.cpp:167:8:167:8 | c | string.cpp:165:28:165:33 | call to source | +| string.cpp:182:11:182:11 | call to operator+ | string.cpp:179:18:179:23 | call to source | +| string.cpp:183:11:183:11 | call to operator+ | string.cpp:179:18:179:23 | call to source | +| string.cpp:184:11:184:11 | call to operator+ | string.cpp:179:18:179:23 | call to source | +| string.cpp:187:11:187:11 | call to operator+ | string.cpp:187:13:187:18 | call to source | +| string.cpp:196:8:196:9 | s5 | string.cpp:192:18:192:23 | call to source | +| string.cpp:200:8:200:9 | s6 | string.cpp:192:18:192:23 | call to source | +| string.cpp:205:8:205:9 | s7 | string.cpp:203:9:203:14 | call to source | +| string.cpp:209:8:209:9 | s8 | string.cpp:192:18:192:23 | call to source | +| string.cpp:214:8:214:9 | s9 | string.cpp:212:13:212:18 | call to source | +| string.cpp:222:8:222:10 | s10 | string.cpp:219:12:219:26 | call to source | | structlikeclass.cpp:35:8:35:9 | s1 | structlikeclass.cpp:29:22:29:27 | call to source | | structlikeclass.cpp:36:8:36:9 | s2 | structlikeclass.cpp:30:24:30:29 | call to source | | structlikeclass.cpp:37:8:37:9 | s3 | structlikeclass.cpp:29:22:29:27 | call to source | @@ -169,3 +166,6 @@ | taint.cpp:470:7:470:7 | x | taint.cpp:462:6:462:11 | call to source | | taint.cpp:471:7:471:7 | y | taint.cpp:462:6:462:11 | call to source | | taint.cpp:485:7:485:10 | line | taint.cpp:480:26:480:32 | source1 | +| vector.cpp:15:8:15:8 | x | vector.cpp:8:43:8:49 | source1 | +| vector.cpp:23:8:23:8 | x | vector.cpp:8:43:8:49 | source1 | +| vector.cpp:28:8:28:8 | x | vector.cpp:8:43:8:49 | source1 | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected index 7704bbf9bf0..d18a2c14437 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected @@ -30,36 +30,33 @@ | movableclass.cpp:55:8:55:9 | movableclass.cpp:52:23:52:28 | AST only | | movableclass.cpp:64:8:64:9 | movableclass.cpp:23:55:23:60 | AST only | | movableclass.cpp:65:11:65:11 | movableclass.cpp:65:13:65:18 | AST only | -| stl.cpp:115:7:115:7 | stl.cpp:111:16:111:21 | AST only | -| stl.cpp:117:9:117:13 | stl.cpp:111:16:111:21 | AST only | -| stl.cpp:167:13:167:17 | stl.cpp:159:10:159:15 | AST only | -| stl.cpp:171:13:171:17 | stl.cpp:159:10:159:15 | AST only | -| stl.cpp:174:13:174:17 | stl.cpp:159:10:159:15 | AST only | -| stl.cpp:184:7:184:8 | stl.cpp:179:19:179:26 | IR only | -| stl.cpp:185:7:185:8 | stl.cpp:179:19:179:24 | AST only | -| stl.cpp:198:7:198:8 | stl.cpp:190:19:190:24 | AST only | -| stl.cpp:199:7:199:8 | stl.cpp:190:19:190:24 | AST only | -| stl.cpp:221:8:221:9 | stl.cpp:216:18:216:23 | AST only | -| stl.cpp:222:8:222:9 | stl.cpp:217:20:217:25 | AST only | -| stl.cpp:223:8:223:9 | stl.cpp:219:8:219:13 | AST only | -| stl.cpp:242:8:242:9 | stl.cpp:238:32:238:37 | AST only | -| stl.cpp:243:8:243:9 | stl.cpp:240:20:240:25 | AST only | -| stl.cpp:252:8:252:8 | stl.cpp:250:16:250:21 | AST only | -| stl.cpp:260:8:260:8 | stl.cpp:250:16:250:21 | AST only | -| stl.cpp:265:8:265:8 | stl.cpp:263:28:263:33 | AST only | -| stl.cpp:307:8:307:8 | stl.cpp:300:43:300:49 | AST only | -| stl.cpp:315:8:315:8 | stl.cpp:300:43:300:49 | AST only | -| stl.cpp:320:8:320:8 | stl.cpp:300:43:300:49 | AST only | -| stl.cpp:335:11:335:11 | stl.cpp:332:18:332:23 | AST only | -| stl.cpp:336:11:336:11 | stl.cpp:332:18:332:23 | AST only | -| stl.cpp:337:11:337:11 | stl.cpp:332:18:332:23 | AST only | -| stl.cpp:340:11:340:11 | stl.cpp:340:13:340:18 | AST only | -| stl.cpp:349:8:349:9 | stl.cpp:345:18:345:23 | AST only | -| stl.cpp:353:8:353:9 | stl.cpp:345:18:345:23 | AST only | -| stl.cpp:358:8:358:9 | stl.cpp:356:9:356:14 | AST only | -| stl.cpp:362:8:362:9 | stl.cpp:345:18:345:23 | AST only | -| stl.cpp:367:8:367:9 | stl.cpp:365:13:365:18 | AST only | -| stl.cpp:375:8:375:10 | stl.cpp:372:12:372:26 | AST only | +| string.cpp:17:7:17:7 | string.cpp:13:16:13:21 | AST only | +| string.cpp:19:9:19:13 | string.cpp:13:16:13:21 | AST only | +| string.cpp:69:13:69:17 | string.cpp:61:10:61:15 | AST only | +| string.cpp:73:13:73:17 | string.cpp:61:10:61:15 | AST only | +| string.cpp:76:13:76:17 | string.cpp:61:10:61:15 | AST only | +| string.cpp:86:7:86:8 | string.cpp:81:19:81:26 | IR only | +| string.cpp:87:7:87:8 | string.cpp:81:19:81:24 | AST only | +| string.cpp:100:7:100:8 | string.cpp:92:19:92:24 | AST only | +| string.cpp:101:7:101:8 | string.cpp:92:19:92:24 | AST only | +| string.cpp:123:8:123:9 | string.cpp:118:18:118:23 | AST only | +| string.cpp:124:8:124:9 | string.cpp:119:20:119:25 | AST only | +| string.cpp:125:8:125:9 | string.cpp:121:8:121:13 | AST only | +| string.cpp:144:8:144:9 | string.cpp:140:32:140:37 | AST only | +| string.cpp:145:8:145:9 | string.cpp:142:20:142:25 | AST only | +| string.cpp:154:8:154:8 | string.cpp:152:16:152:21 | AST only | +| string.cpp:162:8:162:8 | string.cpp:152:16:152:21 | AST only | +| string.cpp:167:8:167:8 | string.cpp:165:28:165:33 | AST only | +| string.cpp:182:11:182:11 | string.cpp:179:18:179:23 | AST only | +| string.cpp:183:11:183:11 | string.cpp:179:18:179:23 | AST only | +| string.cpp:184:11:184:11 | string.cpp:179:18:179:23 | AST only | +| string.cpp:187:11:187:11 | string.cpp:187:13:187:18 | AST only | +| string.cpp:196:8:196:9 | string.cpp:192:18:192:23 | AST only | +| string.cpp:200:8:200:9 | string.cpp:192:18:192:23 | AST only | +| string.cpp:205:8:205:9 | string.cpp:203:9:203:14 | AST only | +| string.cpp:209:8:209:9 | string.cpp:192:18:192:23 | AST only | +| string.cpp:214:8:214:9 | string.cpp:212:13:212:18 | AST only | +| string.cpp:222:8:222:10 | string.cpp:219:12:219:26 | AST only | | structlikeclass.cpp:35:8:35:9 | structlikeclass.cpp:29:22:29:27 | AST only | | structlikeclass.cpp:36:8:36:9 | structlikeclass.cpp:30:24:30:29 | AST only | | structlikeclass.cpp:37:8:37:9 | structlikeclass.cpp:29:22:29:27 | AST only | @@ -104,3 +101,6 @@ | taint.cpp:446:7:446:7 | taint.cpp:445:14:445:28 | AST only | | taint.cpp:447:9:447:17 | taint.cpp:445:14:445:28 | AST only | | taint.cpp:471:7:471:7 | taint.cpp:462:6:462:11 | AST only | +| vector.cpp:15:8:15:8 | vector.cpp:8:43:8:49 | AST only | +| vector.cpp:23:8:23:8 | vector.cpp:8:43:8:49 | AST only | +| vector.cpp:28:8:28:8 | vector.cpp:8:43:8:49 | AST only | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected index 463637d73e0..69e1fe2901f 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected @@ -1,10 +1,10 @@ | format.cpp:157:7:157:22 | (int)... | format.cpp:147:12:147:25 | call to source | | format.cpp:157:7:157:22 | access to array | format.cpp:147:12:147:25 | call to source | | format.cpp:158:7:158:27 | ... + ... | format.cpp:148:16:148:30 | call to source | -| stl.cpp:113:7:113:7 | (const char *)... | stl.cpp:109:12:109:17 | call to source | -| stl.cpp:113:7:113:7 | a | stl.cpp:109:12:109:17 | call to source | -| stl.cpp:184:7:184:8 | cs | stl.cpp:179:19:179:24 | call to source | -| stl.cpp:184:7:184:8 | cs | stl.cpp:179:19:179:26 | (const char *)... | +| string.cpp:15:7:15:7 | (const char *)... | string.cpp:11:12:11:17 | call to source | +| string.cpp:15:7:15:7 | a | string.cpp:11:12:11:17 | call to source | +| string.cpp:86:7:86:8 | cs | string.cpp:81:19:81:24 | call to source | +| string.cpp:86:7:86:8 | cs | string.cpp:81:19:81:26 | (const char *)... | | structlikeclass.cpp:38:8:38:9 | s4 | structlikeclass.cpp:33:8:33:13 | call to source | | structlikeclass.cpp:61:8:61:9 | s2 | structlikeclass.cpp:58:24:58:29 | call to source | | structlikeclass.cpp:62:8:62:20 | ... = ... | structlikeclass.cpp:62:13:62:18 | call to source | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp new file mode 100644 index 00000000000..337e4b40a1f --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp @@ -0,0 +1,30 @@ + +#include "stl.h" + +using namespace std; + +void sink(int); + +void test_range_based_for_loop_vector(int source1) { + // Tainting the vector by allocating a tainted length. This doesn't represent + // how a vector would typically get tainted, but it allows this test to avoid + // being concerned with std::vector modeling. + std::vector v(source1); + + for(int x : v) { + sink(x); // tainted [NOT DETECTED by IR] + } + + for(std::vector::iterator it = v.begin(); it != v.end(); ++it) { + sink(*it); // tainted [NOT DETECTED] + } + + for(int& x : v) { + sink(x); // tainted [NOT DETECTED by IR] + } + + const std::vector const_v(source1); + for(const int& x : const_v) { + sink(x); // tainted [NOT DETECTED by IR] + } +} From 49d2f66ddbd52981570d5742bbe8c24dd828a2df Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 13 Aug 2020 18:08:58 +0100 Subject: [PATCH 066/133] C++: Tidy up sources and sinks. --- .../dataflow/taint-tests/localTaint.expected | 442 +++++++++--------- .../dataflow/taint-tests/string.cpp | 29 +- .../dataflow/taint-tests/taint.expected | 56 +-- .../dataflow/taint-tests/test_diff.expected | 54 +-- .../dataflow/taint-tests/test_ir.expected | 8 +- 5 files changed, 294 insertions(+), 295 deletions(-) diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected index 6fb86dc1fd4..f4449f8ed16 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -308,230 +308,230 @@ | movableclass.cpp:65:13:65:18 | call to source | movableclass.cpp:65:13:65:20 | call to MyMovableClass | TAINT | | movableclass.cpp:65:13:65:20 | call to MyMovableClass | movableclass.cpp:65:8:65:9 | ref arg s3 | TAINT | | movableclass.cpp:65:13:65:20 | call to MyMovableClass | movableclass.cpp:65:11:65:11 | call to operator= | TAINT | -| string.cpp:11:12:11:17 | call to source | string.cpp:15:7:15:7 | a | | -| string.cpp:12:16:12:20 | 123 | string.cpp:12:16:12:21 | call to basic_string | TAINT | -| string.cpp:12:16:12:21 | call to basic_string | string.cpp:16:7:16:7 | b | | -| string.cpp:12:16:12:21 | call to basic_string | string.cpp:18:7:18:7 | b | | -| string.cpp:13:16:13:21 | call to source | string.cpp:13:16:13:24 | call to basic_string | TAINT | -| string.cpp:13:16:13:24 | call to basic_string | string.cpp:17:7:17:7 | c | | -| string.cpp:13:16:13:24 | call to basic_string | string.cpp:19:7:19:7 | c | | -| string.cpp:18:7:18:7 | b | string.cpp:18:9:18:13 | call to c_str | TAINT | -| string.cpp:19:7:19:7 | c | string.cpp:19:9:19:13 | call to c_str | TAINT | -| string.cpp:24:20:24:22 | call to basic_stringstream | string.cpp:27:2:27:4 | ss1 | | -| string.cpp:24:20:24:22 | call to basic_stringstream | string.cpp:33:7:33:9 | ss1 | | -| string.cpp:24:20:24:22 | call to basic_stringstream | string.cpp:38:7:38:9 | ss1 | | -| string.cpp:24:25:24:27 | call to basic_stringstream | string.cpp:28:2:28:4 | ss2 | | -| string.cpp:24:25:24:27 | call to basic_stringstream | string.cpp:34:7:34:9 | ss2 | | -| string.cpp:24:25:24:27 | call to basic_stringstream | string.cpp:39:7:39:9 | ss2 | | -| string.cpp:24:30:24:32 | call to basic_stringstream | string.cpp:29:2:29:4 | ss3 | | -| string.cpp:24:30:24:32 | call to basic_stringstream | string.cpp:35:7:35:9 | ss3 | | -| string.cpp:24:30:24:32 | call to basic_stringstream | string.cpp:40:7:40:9 | ss3 | | -| string.cpp:24:35:24:37 | call to basic_stringstream | string.cpp:30:2:30:4 | ss4 | | -| string.cpp:24:35:24:37 | call to basic_stringstream | string.cpp:36:7:36:9 | ss4 | | -| string.cpp:24:35:24:37 | call to basic_stringstream | string.cpp:41:7:41:9 | ss4 | | -| string.cpp:24:40:24:42 | call to basic_stringstream | string.cpp:31:2:31:4 | ss5 | | -| string.cpp:24:40:24:42 | call to basic_stringstream | string.cpp:37:7:37:9 | ss5 | | -| string.cpp:24:40:24:42 | call to basic_stringstream | string.cpp:42:7:42:9 | ss5 | | -| string.cpp:25:16:25:21 | call to source | string.cpp:25:16:25:24 | call to basic_string | TAINT | -| string.cpp:25:16:25:24 | call to basic_string | string.cpp:31:9:31:9 | t | | -| string.cpp:27:2:27:4 | ref arg ss1 | string.cpp:33:7:33:9 | ss1 | | -| string.cpp:27:2:27:4 | ref arg ss1 | string.cpp:38:7:38:9 | ss1 | | -| string.cpp:28:2:28:4 | ref arg ss2 | string.cpp:34:7:34:9 | ss2 | | -| string.cpp:28:2:28:4 | ref arg ss2 | string.cpp:39:7:39:9 | ss2 | | -| string.cpp:29:2:29:4 | ref arg ss3 | string.cpp:35:7:35:9 | ss3 | | -| string.cpp:29:2:29:4 | ref arg ss3 | string.cpp:40:7:40:9 | ss3 | | -| string.cpp:30:2:30:4 | ref arg ss4 | string.cpp:36:7:36:9 | ss4 | | -| string.cpp:30:2:30:4 | ref arg ss4 | string.cpp:41:7:41:9 | ss4 | | -| string.cpp:31:2:31:4 | ref arg ss5 | string.cpp:37:7:37:9 | ss5 | | -| string.cpp:31:2:31:4 | ref arg ss5 | string.cpp:42:7:42:9 | ss5 | | -| string.cpp:45:32:45:37 | source | string.cpp:50:9:50:14 | source | | -| string.cpp:47:20:47:22 | call to basic_stringstream | string.cpp:49:2:49:4 | ss1 | | -| string.cpp:47:20:47:22 | call to basic_stringstream | string.cpp:52:7:52:9 | ss1 | | -| string.cpp:47:20:47:22 | call to basic_stringstream | string.cpp:54:7:54:9 | ss1 | | -| string.cpp:47:25:47:27 | call to basic_stringstream | string.cpp:50:2:50:4 | ss2 | | -| string.cpp:47:25:47:27 | call to basic_stringstream | string.cpp:53:7:53:9 | ss2 | | -| string.cpp:47:25:47:27 | call to basic_stringstream | string.cpp:55:7:55:9 | ss2 | | -| string.cpp:49:2:49:4 | ref arg ss1 | string.cpp:52:7:52:9 | ss1 | | -| string.cpp:49:2:49:4 | ref arg ss1 | string.cpp:54:7:54:9 | ss1 | | -| string.cpp:50:2:50:4 | ref arg ss2 | string.cpp:53:7:53:9 | ss2 | | -| string.cpp:50:2:50:4 | ref arg ss2 | string.cpp:55:7:55:9 | ss2 | | -| string.cpp:68:16:68:28 | call to basic_string | string.cpp:69:7:69:11 | path1 | | -| string.cpp:68:17:68:26 | call to user_input | string.cpp:68:16:68:28 | call to basic_string | TAINT | -| string.cpp:69:7:69:11 | path1 | string.cpp:69:13:69:17 | call to c_str | TAINT | -| string.cpp:72:10:72:19 | call to user_input | string.cpp:72:10:72:21 | call to basic_string | TAINT | -| string.cpp:72:10:72:21 | call to basic_string | string.cpp:72:2:72:21 | ... = ... | | -| string.cpp:72:10:72:21 | call to basic_string | string.cpp:73:7:73:11 | path2 | | -| string.cpp:73:7:73:11 | path2 | string.cpp:73:13:73:17 | call to c_str | TAINT | -| string.cpp:75:15:75:24 | call to user_input | string.cpp:75:15:75:27 | call to basic_string | TAINT | -| string.cpp:75:15:75:27 | call to basic_string | string.cpp:76:7:76:11 | path3 | | -| string.cpp:76:7:76:11 | path3 | string.cpp:76:13:76:17 | call to c_str | TAINT | -| string.cpp:81:19:81:24 | call to source | string.cpp:84:17:84:18 | cs | | -| string.cpp:81:19:81:24 | call to source | string.cpp:86:7:86:8 | cs | | -| string.cpp:84:17:84:18 | cs | string.cpp:84:17:84:19 | call to basic_string | TAINT | -| string.cpp:84:17:84:19 | call to basic_string | string.cpp:87:7:87:8 | ss | | -| string.cpp:92:19:92:24 | call to source | string.cpp:95:17:95:18 | cs | | -| string.cpp:95:17:95:18 | cs | string.cpp:95:17:95:19 | call to basic_string | TAINT | -| string.cpp:95:17:95:19 | call to basic_string | string.cpp:98:7:98:8 | ss | | -| string.cpp:95:17:95:19 | call to basic_string | string.cpp:101:7:101:8 | ss | | -| string.cpp:98:7:98:8 | ss | string.cpp:98:10:98:14 | call to c_str | TAINT | -| string.cpp:98:10:98:14 | call to c_str | string.cpp:98:2:98:16 | ... = ... | | -| string.cpp:98:10:98:14 | call to c_str | string.cpp:100:7:100:8 | cs | | -| string.cpp:107:18:107:24 | hello | string.cpp:107:18:107:25 | call to basic_string | TAINT | -| string.cpp:107:18:107:25 | call to basic_string | string.cpp:112:8:112:9 | s1 | | -| string.cpp:108:19:108:26 | call to basic_string | string.cpp:113:8:113:9 | s2 | | -| string.cpp:108:20:108:26 | hello | string.cpp:108:19:108:26 | call to basic_string | TAINT | -| string.cpp:110:8:110:14 | call to basic_string | string.cpp:110:3:110:14 | ... = ... | | -| string.cpp:110:8:110:14 | call to basic_string | string.cpp:114:8:114:9 | s3 | | -| string.cpp:110:8:110:14 | hello | string.cpp:110:8:110:14 | call to basic_string | TAINT | -| string.cpp:118:18:118:23 | call to source | string.cpp:118:18:118:26 | call to basic_string | TAINT | -| string.cpp:118:18:118:26 | call to basic_string | string.cpp:123:8:123:9 | s1 | | -| string.cpp:119:19:119:27 | call to basic_string | string.cpp:124:8:124:9 | s2 | | -| string.cpp:119:20:119:25 | call to source | string.cpp:119:19:119:27 | call to basic_string | TAINT | -| string.cpp:121:8:121:13 | call to source | string.cpp:121:8:121:15 | call to basic_string | TAINT | -| string.cpp:121:8:121:15 | call to basic_string | string.cpp:121:3:121:15 | ... = ... | | -| string.cpp:121:8:121:15 | call to basic_string | string.cpp:125:8:125:9 | s3 | | -| string.cpp:129:15:129:16 | call to basic_string | string.cpp:130:20:130:21 | s1 | | -| string.cpp:129:15:129:16 | call to basic_string | string.cpp:132:8:132:9 | s1 | | -| string.cpp:129:15:129:16 | call to basic_string | string.cpp:134:8:134:9 | s1 | | -| string.cpp:130:20:130:21 | s1 | string.cpp:135:8:135:9 | s2 | | -| string.cpp:132:8:132:9 | s1 | string.cpp:132:3:132:9 | ... = ... | | -| string.cpp:132:8:132:9 | s1 | string.cpp:136:8:136:9 | s3 | | -| string.cpp:140:19:140:40 | call to basic_string | string.cpp:144:8:144:9 | s1 | | -| string.cpp:140:32:140:37 | call to source | string.cpp:140:19:140:40 | call to basic_string | TAINT | -| string.cpp:142:8:142:28 | call to basic_string | string.cpp:142:3:142:28 | ... = ... | | -| string.cpp:142:8:142:28 | call to basic_string | string.cpp:145:8:145:9 | s2 | | -| string.cpp:142:20:142:25 | call to source | string.cpp:142:8:142:28 | call to basic_string | TAINT | -| string.cpp:152:16:152:21 | call to source | string.cpp:152:16:152:24 | call to basic_string | TAINT | -| string.cpp:152:16:152:24 | call to basic_string | string.cpp:153:15:153:15 | s | | -| string.cpp:152:16:152:24 | call to basic_string | string.cpp:157:33:157:33 | s | | -| string.cpp:152:16:152:24 | call to basic_string | string.cpp:157:50:157:50 | s | | -| string.cpp:152:16:152:24 | call to basic_string | string.cpp:161:16:161:16 | s | | -| string.cpp:153:15:153:15 | call to begin | string.cpp:153:15:153:15 | (__begin) | | -| string.cpp:153:15:153:15 | call to begin | string.cpp:153:15:153:15 | (__begin) | | -| string.cpp:153:15:153:15 | call to begin | string.cpp:153:15:153:15 | (__begin) | | -| string.cpp:153:15:153:15 | call to end | string.cpp:153:15:153:15 | (__end) | | -| string.cpp:153:15:153:15 | call to operator* | string.cpp:154:8:154:8 | c | | -| string.cpp:153:15:153:15 | ref arg (__begin) | string.cpp:153:15:153:15 | (__begin) | | -| string.cpp:153:15:153:15 | ref arg (__begin) | string.cpp:153:15:153:15 | (__begin) | | -| string.cpp:153:15:153:15 | ref arg (__begin) | string.cpp:153:15:153:15 | (__begin) | | -| string.cpp:153:15:153:15 | ref arg (__range) | string.cpp:153:15:153:15 | (__range) | | -| string.cpp:153:15:153:15 | s | string.cpp:153:15:153:15 | (__range) | | -| string.cpp:153:15:153:15 | s | string.cpp:153:15:153:15 | (__range) | | -| string.cpp:153:15:153:15 | s | string.cpp:153:15:153:15 | call to operator* | TAINT | -| string.cpp:157:33:157:33 | ref arg s | string.cpp:157:50:157:50 | s | | -| string.cpp:157:33:157:33 | ref arg s | string.cpp:161:16:161:16 | s | | -| string.cpp:157:35:157:39 | call to begin | string.cpp:157:44:157:45 | it | | -| string.cpp:157:35:157:39 | call to begin | string.cpp:157:61:157:62 | it | | -| string.cpp:157:35:157:39 | call to begin | string.cpp:158:9:158:10 | it | | -| string.cpp:157:50:157:50 | ref arg s | string.cpp:157:50:157:50 | s | | -| string.cpp:157:50:157:50 | ref arg s | string.cpp:161:16:161:16 | s | | -| string.cpp:157:61:157:62 | ref arg it | string.cpp:157:44:157:45 | it | | -| string.cpp:157:61:157:62 | ref arg it | string.cpp:157:61:157:62 | it | | -| string.cpp:157:61:157:62 | ref arg it | string.cpp:158:9:158:10 | it | | -| string.cpp:161:16:161:16 | call to begin | string.cpp:161:16:161:16 | (__begin) | | -| string.cpp:161:16:161:16 | call to begin | string.cpp:161:16:161:16 | (__begin) | | -| string.cpp:161:16:161:16 | call to begin | string.cpp:161:16:161:16 | (__begin) | | -| string.cpp:161:16:161:16 | call to end | string.cpp:161:16:161:16 | (__end) | | -| string.cpp:161:16:161:16 | call to operator* | string.cpp:162:8:162:8 | c | | -| string.cpp:161:16:161:16 | ref arg (__begin) | string.cpp:161:16:161:16 | (__begin) | | -| string.cpp:161:16:161:16 | ref arg (__begin) | string.cpp:161:16:161:16 | (__begin) | | -| string.cpp:161:16:161:16 | ref arg (__begin) | string.cpp:161:16:161:16 | (__begin) | | -| string.cpp:161:16:161:16 | ref arg (__range) | string.cpp:161:16:161:16 | (__range) | | -| string.cpp:161:16:161:16 | s | string.cpp:161:16:161:16 | (__range) | | -| string.cpp:161:16:161:16 | s | string.cpp:161:16:161:16 | (__range) | | -| string.cpp:161:16:161:16 | s | string.cpp:161:16:161:16 | call to operator* | TAINT | -| string.cpp:165:28:165:33 | call to source | string.cpp:165:28:165:36 | call to basic_string | TAINT | -| string.cpp:165:28:165:36 | call to basic_string | string.cpp:166:22:166:28 | const_s | | -| string.cpp:166:22:166:22 | call to begin | string.cpp:166:22:166:22 | (__begin) | | -| string.cpp:166:22:166:22 | call to begin | string.cpp:166:22:166:22 | (__begin) | | -| string.cpp:166:22:166:22 | call to begin | string.cpp:166:22:166:22 | (__begin) | | -| string.cpp:166:22:166:22 | call to end | string.cpp:166:22:166:22 | (__end) | | -| string.cpp:166:22:166:22 | call to operator* | string.cpp:167:8:167:8 | c | | -| string.cpp:166:22:166:22 | ref arg (__begin) | string.cpp:166:22:166:22 | (__begin) | | -| string.cpp:166:22:166:22 | ref arg (__begin) | string.cpp:166:22:166:22 | (__begin) | | -| string.cpp:166:22:166:22 | ref arg (__begin) | string.cpp:166:22:166:22 | (__begin) | | -| string.cpp:166:22:166:28 | const_s | string.cpp:166:22:166:22 | (__range) | | -| string.cpp:166:22:166:28 | const_s | string.cpp:166:22:166:22 | (__range) | | -| string.cpp:166:22:166:28 | const_s | string.cpp:166:22:166:22 | call to operator* | TAINT | -| string.cpp:178:18:178:24 | hello | string.cpp:178:18:178:25 | call to basic_string | TAINT | -| string.cpp:178:18:178:25 | call to basic_string | string.cpp:181:8:181:9 | s1 | | -| string.cpp:178:18:178:25 | call to basic_string | string.cpp:181:13:181:14 | s1 | | -| string.cpp:178:18:178:25 | call to basic_string | string.cpp:182:8:182:9 | s1 | | -| string.cpp:178:18:178:25 | call to basic_string | string.cpp:183:13:183:14 | s1 | | -| string.cpp:178:18:178:25 | call to basic_string | string.cpp:186:8:186:9 | s1 | | -| string.cpp:178:18:178:25 | call to basic_string | string.cpp:187:8:187:9 | s1 | | -| string.cpp:179:18:179:23 | call to source | string.cpp:179:18:179:26 | call to basic_string | TAINT | -| string.cpp:179:18:179:26 | call to basic_string | string.cpp:182:13:182:14 | s2 | | -| string.cpp:179:18:179:26 | call to basic_string | string.cpp:183:8:183:9 | s2 | | -| string.cpp:179:18:179:26 | call to basic_string | string.cpp:184:8:184:9 | s2 | | -| string.cpp:179:18:179:26 | call to basic_string | string.cpp:184:13:184:14 | s2 | | +| string.cpp:25:12:25:17 | call to source | string.cpp:29:7:29:7 | a | | +| string.cpp:26:16:26:20 | 123 | string.cpp:26:16:26:21 | call to basic_string | TAINT | +| string.cpp:26:16:26:21 | call to basic_string | string.cpp:30:7:30:7 | b | | +| string.cpp:26:16:26:21 | call to basic_string | string.cpp:32:7:32:7 | b | | +| string.cpp:27:16:27:21 | call to source | string.cpp:27:16:27:24 | call to basic_string | TAINT | +| string.cpp:27:16:27:24 | call to basic_string | string.cpp:31:7:31:7 | c | | +| string.cpp:27:16:27:24 | call to basic_string | string.cpp:33:7:33:7 | c | | +| string.cpp:32:7:32:7 | b | string.cpp:32:9:32:13 | call to c_str | TAINT | +| string.cpp:33:7:33:7 | c | string.cpp:33:9:33:13 | call to c_str | TAINT | +| string.cpp:38:20:38:22 | call to basic_stringstream | string.cpp:41:2:41:4 | ss1 | | +| string.cpp:38:20:38:22 | call to basic_stringstream | string.cpp:47:7:47:9 | ss1 | | +| string.cpp:38:20:38:22 | call to basic_stringstream | string.cpp:52:7:52:9 | ss1 | | +| string.cpp:38:25:38:27 | call to basic_stringstream | string.cpp:42:2:42:4 | ss2 | | +| string.cpp:38:25:38:27 | call to basic_stringstream | string.cpp:48:7:48:9 | ss2 | | +| string.cpp:38:25:38:27 | call to basic_stringstream | string.cpp:53:7:53:9 | ss2 | | +| string.cpp:38:30:38:32 | call to basic_stringstream | string.cpp:43:2:43:4 | ss3 | | +| string.cpp:38:30:38:32 | call to basic_stringstream | string.cpp:49:7:49:9 | ss3 | | +| string.cpp:38:30:38:32 | call to basic_stringstream | string.cpp:54:7:54:9 | ss3 | | +| string.cpp:38:35:38:37 | call to basic_stringstream | string.cpp:44:2:44:4 | ss4 | | +| string.cpp:38:35:38:37 | call to basic_stringstream | string.cpp:50:7:50:9 | ss4 | | +| string.cpp:38:35:38:37 | call to basic_stringstream | string.cpp:55:7:55:9 | ss4 | | +| string.cpp:38:40:38:42 | call to basic_stringstream | string.cpp:45:2:45:4 | ss5 | | +| string.cpp:38:40:38:42 | call to basic_stringstream | string.cpp:51:7:51:9 | ss5 | | +| string.cpp:38:40:38:42 | call to basic_stringstream | string.cpp:56:7:56:9 | ss5 | | +| string.cpp:39:16:39:21 | call to source | string.cpp:39:16:39:24 | call to basic_string | TAINT | +| string.cpp:39:16:39:24 | call to basic_string | string.cpp:45:9:45:9 | t | | +| string.cpp:41:2:41:4 | ref arg ss1 | string.cpp:47:7:47:9 | ss1 | | +| string.cpp:41:2:41:4 | ref arg ss1 | string.cpp:52:7:52:9 | ss1 | | +| string.cpp:42:2:42:4 | ref arg ss2 | string.cpp:48:7:48:9 | ss2 | | +| string.cpp:42:2:42:4 | ref arg ss2 | string.cpp:53:7:53:9 | ss2 | | +| string.cpp:43:2:43:4 | ref arg ss3 | string.cpp:49:7:49:9 | ss3 | | +| string.cpp:43:2:43:4 | ref arg ss3 | string.cpp:54:7:54:9 | ss3 | | +| string.cpp:44:2:44:4 | ref arg ss4 | string.cpp:50:7:50:9 | ss4 | | +| string.cpp:44:2:44:4 | ref arg ss4 | string.cpp:55:7:55:9 | ss4 | | +| string.cpp:45:2:45:4 | ref arg ss5 | string.cpp:51:7:51:9 | ss5 | | +| string.cpp:45:2:45:4 | ref arg ss5 | string.cpp:56:7:56:9 | ss5 | | +| string.cpp:59:32:59:37 | source | string.cpp:64:9:64:14 | source | | +| string.cpp:61:20:61:22 | call to basic_stringstream | string.cpp:63:2:63:4 | ss1 | | +| string.cpp:61:20:61:22 | call to basic_stringstream | string.cpp:66:7:66:9 | ss1 | | +| string.cpp:61:20:61:22 | call to basic_stringstream | string.cpp:68:7:68:9 | ss1 | | +| string.cpp:61:25:61:27 | call to basic_stringstream | string.cpp:64:2:64:4 | ss2 | | +| string.cpp:61:25:61:27 | call to basic_stringstream | string.cpp:67:7:67:9 | ss2 | | +| string.cpp:61:25:61:27 | call to basic_stringstream | string.cpp:69:7:69:9 | ss2 | | +| string.cpp:63:2:63:4 | ref arg ss1 | string.cpp:66:7:66:9 | ss1 | | +| string.cpp:63:2:63:4 | ref arg ss1 | string.cpp:68:7:68:9 | ss1 | | +| string.cpp:64:2:64:4 | ref arg ss2 | string.cpp:67:7:67:9 | ss2 | | +| string.cpp:64:2:64:4 | ref arg ss2 | string.cpp:69:7:69:9 | ss2 | | +| string.cpp:74:16:74:28 | call to basic_string | string.cpp:75:7:75:11 | path1 | | +| string.cpp:74:17:74:26 | call to user_input | string.cpp:74:16:74:28 | call to basic_string | TAINT | +| string.cpp:75:7:75:11 | path1 | string.cpp:75:13:75:17 | call to c_str | TAINT | +| string.cpp:78:10:78:19 | call to user_input | string.cpp:78:10:78:21 | call to basic_string | TAINT | +| string.cpp:78:10:78:21 | call to basic_string | string.cpp:78:2:78:21 | ... = ... | | +| string.cpp:78:10:78:21 | call to basic_string | string.cpp:79:7:79:11 | path2 | | +| string.cpp:79:7:79:11 | path2 | string.cpp:79:13:79:17 | call to c_str | TAINT | +| string.cpp:81:15:81:24 | call to user_input | string.cpp:81:15:81:27 | call to basic_string | TAINT | +| string.cpp:81:15:81:27 | call to basic_string | string.cpp:82:7:82:11 | path3 | | +| string.cpp:82:7:82:11 | path3 | string.cpp:82:13:82:17 | call to c_str | TAINT | +| string.cpp:87:19:87:24 | call to source | string.cpp:90:17:90:18 | cs | | +| string.cpp:87:19:87:24 | call to source | string.cpp:92:7:92:8 | cs | | +| string.cpp:90:17:90:18 | cs | string.cpp:90:17:90:19 | call to basic_string | TAINT | +| string.cpp:90:17:90:19 | call to basic_string | string.cpp:93:7:93:8 | ss | | +| string.cpp:98:19:98:24 | call to source | string.cpp:101:17:101:18 | cs | | +| string.cpp:101:17:101:18 | cs | string.cpp:101:17:101:19 | call to basic_string | TAINT | +| string.cpp:101:17:101:19 | call to basic_string | string.cpp:104:7:104:8 | ss | | +| string.cpp:101:17:101:19 | call to basic_string | string.cpp:107:7:107:8 | ss | | +| string.cpp:104:7:104:8 | ss | string.cpp:104:10:104:14 | call to c_str | TAINT | +| string.cpp:104:10:104:14 | call to c_str | string.cpp:104:2:104:16 | ... = ... | | +| string.cpp:104:10:104:14 | call to c_str | string.cpp:106:7:106:8 | cs | | +| string.cpp:113:18:113:24 | hello | string.cpp:113:18:113:25 | call to basic_string | TAINT | +| string.cpp:113:18:113:25 | call to basic_string | string.cpp:118:8:118:9 | s1 | | +| string.cpp:114:19:114:26 | call to basic_string | string.cpp:119:8:119:9 | s2 | | +| string.cpp:114:20:114:26 | hello | string.cpp:114:19:114:26 | call to basic_string | TAINT | +| string.cpp:116:8:116:14 | call to basic_string | string.cpp:116:3:116:14 | ... = ... | | +| string.cpp:116:8:116:14 | call to basic_string | string.cpp:120:8:120:9 | s3 | | +| string.cpp:116:8:116:14 | hello | string.cpp:116:8:116:14 | call to basic_string | TAINT | +| string.cpp:124:18:124:23 | call to source | string.cpp:124:18:124:26 | call to basic_string | TAINT | +| string.cpp:124:18:124:26 | call to basic_string | string.cpp:129:8:129:9 | s1 | | +| string.cpp:125:19:125:27 | call to basic_string | string.cpp:130:8:130:9 | s2 | | +| string.cpp:125:20:125:25 | call to source | string.cpp:125:19:125:27 | call to basic_string | TAINT | +| string.cpp:127:8:127:13 | call to source | string.cpp:127:8:127:15 | call to basic_string | TAINT | +| string.cpp:127:8:127:15 | call to basic_string | string.cpp:127:3:127:15 | ... = ... | | +| string.cpp:127:8:127:15 | call to basic_string | string.cpp:131:8:131:9 | s3 | | +| string.cpp:135:15:135:16 | call to basic_string | string.cpp:136:20:136:21 | s1 | | +| string.cpp:135:15:135:16 | call to basic_string | string.cpp:138:8:138:9 | s1 | | +| string.cpp:135:15:135:16 | call to basic_string | string.cpp:140:8:140:9 | s1 | | +| string.cpp:136:20:136:21 | s1 | string.cpp:141:8:141:9 | s2 | | +| string.cpp:138:8:138:9 | s1 | string.cpp:138:3:138:9 | ... = ... | | +| string.cpp:138:8:138:9 | s1 | string.cpp:142:8:142:9 | s3 | | +| string.cpp:146:19:146:40 | call to basic_string | string.cpp:150:8:150:9 | s1 | | +| string.cpp:146:32:146:37 | call to source | string.cpp:146:19:146:40 | call to basic_string | TAINT | +| string.cpp:148:8:148:28 | call to basic_string | string.cpp:148:3:148:28 | ... = ... | | +| string.cpp:148:8:148:28 | call to basic_string | string.cpp:151:8:151:9 | s2 | | +| string.cpp:148:20:148:25 | call to source | string.cpp:148:8:148:28 | call to basic_string | TAINT | +| string.cpp:156:16:156:21 | call to source | string.cpp:156:16:156:24 | call to basic_string | TAINT | +| string.cpp:156:16:156:24 | call to basic_string | string.cpp:157:15:157:15 | s | | +| string.cpp:156:16:156:24 | call to basic_string | string.cpp:161:33:161:33 | s | | +| string.cpp:156:16:156:24 | call to basic_string | string.cpp:161:50:161:50 | s | | +| string.cpp:156:16:156:24 | call to basic_string | string.cpp:165:16:165:16 | s | | +| string.cpp:157:15:157:15 | call to begin | string.cpp:157:15:157:15 | (__begin) | | +| string.cpp:157:15:157:15 | call to begin | string.cpp:157:15:157:15 | (__begin) | | +| string.cpp:157:15:157:15 | call to begin | string.cpp:157:15:157:15 | (__begin) | | +| string.cpp:157:15:157:15 | call to end | string.cpp:157:15:157:15 | (__end) | | +| string.cpp:157:15:157:15 | call to operator* | string.cpp:158:8:158:8 | c | | +| string.cpp:157:15:157:15 | ref arg (__begin) | string.cpp:157:15:157:15 | (__begin) | | +| string.cpp:157:15:157:15 | ref arg (__begin) | string.cpp:157:15:157:15 | (__begin) | | +| string.cpp:157:15:157:15 | ref arg (__begin) | string.cpp:157:15:157:15 | (__begin) | | +| string.cpp:157:15:157:15 | ref arg (__range) | string.cpp:157:15:157:15 | (__range) | | +| string.cpp:157:15:157:15 | s | string.cpp:157:15:157:15 | (__range) | | +| string.cpp:157:15:157:15 | s | string.cpp:157:15:157:15 | (__range) | | +| string.cpp:157:15:157:15 | s | string.cpp:157:15:157:15 | call to operator* | TAINT | +| string.cpp:161:33:161:33 | ref arg s | string.cpp:161:50:161:50 | s | | +| string.cpp:161:33:161:33 | ref arg s | string.cpp:165:16:165:16 | s | | +| string.cpp:161:35:161:39 | call to begin | string.cpp:161:44:161:45 | it | | +| string.cpp:161:35:161:39 | call to begin | string.cpp:161:61:161:62 | it | | +| string.cpp:161:35:161:39 | call to begin | string.cpp:162:9:162:10 | it | | +| string.cpp:161:50:161:50 | ref arg s | string.cpp:161:50:161:50 | s | | +| string.cpp:161:50:161:50 | ref arg s | string.cpp:165:16:165:16 | s | | +| string.cpp:161:61:161:62 | ref arg it | string.cpp:161:44:161:45 | it | | +| string.cpp:161:61:161:62 | ref arg it | string.cpp:161:61:161:62 | it | | +| string.cpp:161:61:161:62 | ref arg it | string.cpp:162:9:162:10 | it | | +| string.cpp:165:16:165:16 | call to begin | string.cpp:165:16:165:16 | (__begin) | | +| string.cpp:165:16:165:16 | call to begin | string.cpp:165:16:165:16 | (__begin) | | +| string.cpp:165:16:165:16 | call to begin | string.cpp:165:16:165:16 | (__begin) | | +| string.cpp:165:16:165:16 | call to end | string.cpp:165:16:165:16 | (__end) | | +| string.cpp:165:16:165:16 | call to operator* | string.cpp:166:8:166:8 | c | | +| string.cpp:165:16:165:16 | ref arg (__begin) | string.cpp:165:16:165:16 | (__begin) | | +| string.cpp:165:16:165:16 | ref arg (__begin) | string.cpp:165:16:165:16 | (__begin) | | +| string.cpp:165:16:165:16 | ref arg (__begin) | string.cpp:165:16:165:16 | (__begin) | | +| string.cpp:165:16:165:16 | ref arg (__range) | string.cpp:165:16:165:16 | (__range) | | +| string.cpp:165:16:165:16 | s | string.cpp:165:16:165:16 | (__range) | | +| string.cpp:165:16:165:16 | s | string.cpp:165:16:165:16 | (__range) | | +| string.cpp:165:16:165:16 | s | string.cpp:165:16:165:16 | call to operator* | TAINT | +| string.cpp:169:28:169:33 | call to source | string.cpp:169:28:169:36 | call to basic_string | TAINT | +| string.cpp:169:28:169:36 | call to basic_string | string.cpp:170:22:170:28 | const_s | | +| string.cpp:170:22:170:22 | call to begin | string.cpp:170:22:170:22 | (__begin) | | +| string.cpp:170:22:170:22 | call to begin | string.cpp:170:22:170:22 | (__begin) | | +| string.cpp:170:22:170:22 | call to begin | string.cpp:170:22:170:22 | (__begin) | | +| string.cpp:170:22:170:22 | call to end | string.cpp:170:22:170:22 | (__end) | | +| string.cpp:170:22:170:22 | call to operator* | string.cpp:171:8:171:8 | c | | +| string.cpp:170:22:170:22 | ref arg (__begin) | string.cpp:170:22:170:22 | (__begin) | | +| string.cpp:170:22:170:22 | ref arg (__begin) | string.cpp:170:22:170:22 | (__begin) | | +| string.cpp:170:22:170:22 | ref arg (__begin) | string.cpp:170:22:170:22 | (__begin) | | +| string.cpp:170:22:170:28 | const_s | string.cpp:170:22:170:22 | (__range) | | +| string.cpp:170:22:170:28 | const_s | string.cpp:170:22:170:22 | (__range) | | +| string.cpp:170:22:170:28 | const_s | string.cpp:170:22:170:22 | call to operator* | TAINT | +| string.cpp:177:18:177:24 | hello | string.cpp:177:18:177:25 | call to basic_string | TAINT | +| string.cpp:177:18:177:25 | call to basic_string | string.cpp:180:8:180:9 | s1 | | +| string.cpp:177:18:177:25 | call to basic_string | string.cpp:180:13:180:14 | s1 | | +| string.cpp:177:18:177:25 | call to basic_string | string.cpp:181:8:181:9 | s1 | | +| string.cpp:177:18:177:25 | call to basic_string | string.cpp:182:13:182:14 | s1 | | +| string.cpp:177:18:177:25 | call to basic_string | string.cpp:185:8:185:9 | s1 | | +| string.cpp:177:18:177:25 | call to basic_string | string.cpp:186:8:186:9 | s1 | | +| string.cpp:178:18:178:23 | call to source | string.cpp:178:18:178:26 | call to basic_string | TAINT | +| string.cpp:178:18:178:26 | call to basic_string | string.cpp:181:13:181:14 | s2 | | +| string.cpp:178:18:178:26 | call to basic_string | string.cpp:182:8:182:9 | s2 | | +| string.cpp:178:18:178:26 | call to basic_string | string.cpp:183:8:183:9 | s2 | | +| string.cpp:178:18:178:26 | call to basic_string | string.cpp:183:13:183:14 | s2 | | +| string.cpp:180:8:180:9 | s1 | string.cpp:180:11:180:11 | call to operator+ | TAINT | +| string.cpp:180:13:180:14 | s1 | string.cpp:180:11:180:11 | call to operator+ | TAINT | | string.cpp:181:8:181:9 | s1 | string.cpp:181:11:181:11 | call to operator+ | TAINT | -| string.cpp:181:13:181:14 | s1 | string.cpp:181:11:181:11 | call to operator+ | TAINT | -| string.cpp:182:8:182:9 | s1 | string.cpp:182:11:182:11 | call to operator+ | TAINT | -| string.cpp:182:13:182:14 | s2 | string.cpp:182:11:182:11 | call to operator+ | TAINT | +| string.cpp:181:13:181:14 | s2 | string.cpp:181:11:181:11 | call to operator+ | TAINT | +| string.cpp:182:8:182:9 | s2 | string.cpp:182:11:182:11 | call to operator+ | TAINT | +| string.cpp:182:13:182:14 | s1 | string.cpp:182:11:182:11 | call to operator+ | TAINT | | string.cpp:183:8:183:9 | s2 | string.cpp:183:11:183:11 | call to operator+ | TAINT | -| string.cpp:183:13:183:14 | s1 | string.cpp:183:11:183:11 | call to operator+ | TAINT | -| string.cpp:184:8:184:9 | s2 | string.cpp:184:11:184:11 | call to operator+ | TAINT | -| string.cpp:184:13:184:14 | s2 | string.cpp:184:11:184:11 | call to operator+ | TAINT | +| string.cpp:183:13:183:14 | s2 | string.cpp:183:11:183:11 | call to operator+ | TAINT | +| string.cpp:185:8:185:9 | s1 | string.cpp:185:11:185:11 | call to operator+ | TAINT | +| string.cpp:185:13:185:20 | world | string.cpp:185:11:185:11 | call to operator+ | TAINT | | string.cpp:186:8:186:9 | s1 | string.cpp:186:11:186:11 | call to operator+ | TAINT | -| string.cpp:186:13:186:20 | world | string.cpp:186:11:186:11 | call to operator+ | TAINT | -| string.cpp:187:8:187:9 | s1 | string.cpp:187:11:187:11 | call to operator+ | TAINT | -| string.cpp:187:13:187:18 | call to source | string.cpp:187:11:187:11 | call to operator+ | TAINT | -| string.cpp:191:18:191:22 | abc | string.cpp:191:18:191:23 | call to basic_string | TAINT | -| string.cpp:191:18:191:23 | call to basic_string | string.cpp:195:8:195:9 | s3 | | -| string.cpp:191:18:191:23 | call to basic_string | string.cpp:198:8:198:9 | s3 | | -| string.cpp:191:18:191:23 | call to basic_string | string.cpp:202:8:202:9 | s3 | | -| string.cpp:191:18:191:23 | call to basic_string | string.cpp:207:8:207:9 | s3 | | -| string.cpp:191:18:191:23 | call to basic_string | string.cpp:211:8:211:9 | s3 | | -| string.cpp:192:18:192:23 | call to source | string.cpp:192:18:192:26 | call to basic_string | TAINT | -| string.cpp:192:18:192:26 | call to basic_string | string.cpp:195:13:195:14 | s4 | | -| string.cpp:192:18:192:26 | call to basic_string | string.cpp:199:9:199:10 | s4 | | -| string.cpp:192:18:192:26 | call to basic_string | string.cpp:208:13:208:14 | s4 | | -| string.cpp:195:8:195:9 | s3 | string.cpp:195:11:195:11 | call to operator+ | TAINT | -| string.cpp:195:11:195:11 | call to operator+ | string.cpp:195:3:195:14 | ... = ... | | -| string.cpp:195:11:195:11 | call to operator+ | string.cpp:196:8:196:9 | s5 | | -| string.cpp:195:13:195:14 | s4 | string.cpp:195:11:195:11 | call to operator+ | TAINT | -| string.cpp:198:8:198:9 | s3 | string.cpp:198:3:198:9 | ... = ... | | -| string.cpp:198:8:198:9 | s3 | string.cpp:199:3:199:4 | s6 | | -| string.cpp:198:8:198:9 | s3 | string.cpp:200:8:200:9 | s6 | | -| string.cpp:199:3:199:4 | ref arg s6 | string.cpp:200:8:200:9 | s6 | | -| string.cpp:199:9:199:10 | s4 | string.cpp:199:3:199:4 | ref arg s6 | TAINT | -| string.cpp:199:9:199:10 | s4 | string.cpp:199:6:199:6 | call to operator+= | TAINT | -| string.cpp:202:8:202:9 | s3 | string.cpp:202:3:202:9 | ... = ... | | -| string.cpp:202:8:202:9 | s3 | string.cpp:203:3:203:4 | s7 | | -| string.cpp:202:8:202:9 | s3 | string.cpp:204:3:204:4 | s7 | | -| string.cpp:202:8:202:9 | s3 | string.cpp:205:8:205:9 | s7 | | -| string.cpp:203:3:203:4 | ref arg s7 | string.cpp:204:3:204:4 | s7 | | -| string.cpp:203:3:203:4 | ref arg s7 | string.cpp:205:8:205:9 | s7 | | -| string.cpp:203:9:203:14 | call to source | string.cpp:203:3:203:4 | ref arg s7 | TAINT | -| string.cpp:203:9:203:14 | call to source | string.cpp:203:6:203:6 | call to operator+= | TAINT | -| string.cpp:204:3:204:4 | ref arg s7 | string.cpp:205:8:205:9 | s7 | | -| string.cpp:204:9:204:11 | | string.cpp:204:3:204:4 | ref arg s7 | TAINT | -| string.cpp:204:9:204:11 | | string.cpp:204:6:204:6 | call to operator+= | TAINT | -| string.cpp:207:8:207:9 | s3 | string.cpp:207:3:207:9 | ... = ... | | -| string.cpp:207:8:207:9 | s3 | string.cpp:208:3:208:4 | s8 | | -| string.cpp:207:8:207:9 | s3 | string.cpp:209:8:209:9 | s8 | | -| string.cpp:208:3:208:4 | ref arg s8 | string.cpp:209:8:209:9 | s8 | | -| string.cpp:208:13:208:14 | s4 | string.cpp:208:3:208:4 | ref arg s8 | TAINT | -| string.cpp:208:13:208:14 | s4 | string.cpp:208:6:208:11 | call to append | TAINT | -| string.cpp:211:8:211:9 | s3 | string.cpp:211:3:211:9 | ... = ... | | -| string.cpp:211:8:211:9 | s3 | string.cpp:212:3:212:4 | s9 | | -| string.cpp:211:8:211:9 | s3 | string.cpp:213:3:213:4 | s9 | | -| string.cpp:211:8:211:9 | s3 | string.cpp:214:8:214:9 | s9 | | -| string.cpp:212:3:212:4 | ref arg s9 | string.cpp:213:3:213:4 | s9 | | -| string.cpp:212:3:212:4 | ref arg s9 | string.cpp:214:8:214:9 | s9 | | -| string.cpp:212:13:212:18 | call to source | string.cpp:212:3:212:4 | ref arg s9 | TAINT | -| string.cpp:212:13:212:18 | call to source | string.cpp:212:6:212:11 | call to append | TAINT | -| string.cpp:213:3:213:4 | ref arg s9 | string.cpp:214:8:214:9 | s9 | | -| string.cpp:213:13:213:15 | | string.cpp:213:3:213:4 | ref arg s9 | TAINT | -| string.cpp:213:13:213:15 | | string.cpp:213:6:213:11 | call to append | TAINT | -| string.cpp:218:19:218:23 | abc | string.cpp:218:19:218:24 | call to basic_string | TAINT | -| string.cpp:218:19:218:24 | call to basic_string | string.cpp:221:3:221:5 | s10 | | -| string.cpp:218:19:218:24 | call to basic_string | string.cpp:222:8:222:10 | s10 | | -| string.cpp:219:12:219:26 | call to source | string.cpp:221:17:221:17 | c | | -| string.cpp:221:3:221:5 | ref arg s10 | string.cpp:222:8:222:10 | s10 | | -| string.cpp:221:17:221:17 | c | string.cpp:221:3:221:5 | ref arg s10 | TAINT | -| string.cpp:221:17:221:17 | c | string.cpp:221:7:221:12 | call to append | TAINT | +| string.cpp:186:13:186:18 | call to source | string.cpp:186:11:186:11 | call to operator+ | TAINT | +| string.cpp:190:18:190:22 | abc | string.cpp:190:18:190:23 | call to basic_string | TAINT | +| string.cpp:190:18:190:23 | call to basic_string | string.cpp:194:8:194:9 | s3 | | +| string.cpp:190:18:190:23 | call to basic_string | string.cpp:197:8:197:9 | s3 | | +| string.cpp:190:18:190:23 | call to basic_string | string.cpp:201:8:201:9 | s3 | | +| string.cpp:190:18:190:23 | call to basic_string | string.cpp:206:8:206:9 | s3 | | +| string.cpp:190:18:190:23 | call to basic_string | string.cpp:210:8:210:9 | s3 | | +| string.cpp:191:18:191:23 | call to source | string.cpp:191:18:191:26 | call to basic_string | TAINT | +| string.cpp:191:18:191:26 | call to basic_string | string.cpp:194:13:194:14 | s4 | | +| string.cpp:191:18:191:26 | call to basic_string | string.cpp:198:9:198:10 | s4 | | +| string.cpp:191:18:191:26 | call to basic_string | string.cpp:207:13:207:14 | s4 | | +| string.cpp:194:8:194:9 | s3 | string.cpp:194:11:194:11 | call to operator+ | TAINT | +| string.cpp:194:11:194:11 | call to operator+ | string.cpp:194:3:194:14 | ... = ... | | +| string.cpp:194:11:194:11 | call to operator+ | string.cpp:195:8:195:9 | s5 | | +| string.cpp:194:13:194:14 | s4 | string.cpp:194:11:194:11 | call to operator+ | TAINT | +| string.cpp:197:8:197:9 | s3 | string.cpp:197:3:197:9 | ... = ... | | +| string.cpp:197:8:197:9 | s3 | string.cpp:198:3:198:4 | s6 | | +| string.cpp:197:8:197:9 | s3 | string.cpp:199:8:199:9 | s6 | | +| string.cpp:198:3:198:4 | ref arg s6 | string.cpp:199:8:199:9 | s6 | | +| string.cpp:198:9:198:10 | s4 | string.cpp:198:3:198:4 | ref arg s6 | TAINT | +| string.cpp:198:9:198:10 | s4 | string.cpp:198:6:198:6 | call to operator+= | TAINT | +| string.cpp:201:8:201:9 | s3 | string.cpp:201:3:201:9 | ... = ... | | +| string.cpp:201:8:201:9 | s3 | string.cpp:202:3:202:4 | s7 | | +| string.cpp:201:8:201:9 | s3 | string.cpp:203:3:203:4 | s7 | | +| string.cpp:201:8:201:9 | s3 | string.cpp:204:8:204:9 | s7 | | +| string.cpp:202:3:202:4 | ref arg s7 | string.cpp:203:3:203:4 | s7 | | +| string.cpp:202:3:202:4 | ref arg s7 | string.cpp:204:8:204:9 | s7 | | +| string.cpp:202:9:202:14 | call to source | string.cpp:202:3:202:4 | ref arg s7 | TAINT | +| string.cpp:202:9:202:14 | call to source | string.cpp:202:6:202:6 | call to operator+= | TAINT | +| string.cpp:203:3:203:4 | ref arg s7 | string.cpp:204:8:204:9 | s7 | | +| string.cpp:203:9:203:11 | | string.cpp:203:3:203:4 | ref arg s7 | TAINT | +| string.cpp:203:9:203:11 | | string.cpp:203:6:203:6 | call to operator+= | TAINT | +| string.cpp:206:8:206:9 | s3 | string.cpp:206:3:206:9 | ... = ... | | +| string.cpp:206:8:206:9 | s3 | string.cpp:207:3:207:4 | s8 | | +| string.cpp:206:8:206:9 | s3 | string.cpp:208:8:208:9 | s8 | | +| string.cpp:207:3:207:4 | ref arg s8 | string.cpp:208:8:208:9 | s8 | | +| string.cpp:207:13:207:14 | s4 | string.cpp:207:3:207:4 | ref arg s8 | TAINT | +| string.cpp:207:13:207:14 | s4 | string.cpp:207:6:207:11 | call to append | TAINT | +| string.cpp:210:8:210:9 | s3 | string.cpp:210:3:210:9 | ... = ... | | +| string.cpp:210:8:210:9 | s3 | string.cpp:211:3:211:4 | s9 | | +| string.cpp:210:8:210:9 | s3 | string.cpp:212:3:212:4 | s9 | | +| string.cpp:210:8:210:9 | s3 | string.cpp:213:8:213:9 | s9 | | +| string.cpp:211:3:211:4 | ref arg s9 | string.cpp:212:3:212:4 | s9 | | +| string.cpp:211:3:211:4 | ref arg s9 | string.cpp:213:8:213:9 | s9 | | +| string.cpp:211:13:211:18 | call to source | string.cpp:211:3:211:4 | ref arg s9 | TAINT | +| string.cpp:211:13:211:18 | call to source | string.cpp:211:6:211:11 | call to append | TAINT | +| string.cpp:212:3:212:4 | ref arg s9 | string.cpp:213:8:213:9 | s9 | | +| string.cpp:212:13:212:15 | | string.cpp:212:3:212:4 | ref arg s9 | TAINT | +| string.cpp:212:13:212:15 | | string.cpp:212:6:212:11 | call to append | TAINT | +| string.cpp:217:19:217:23 | abc | string.cpp:217:19:217:24 | call to basic_string | TAINT | +| string.cpp:217:19:217:24 | call to basic_string | string.cpp:220:3:220:5 | s10 | | +| string.cpp:217:19:217:24 | call to basic_string | string.cpp:221:8:221:10 | s10 | | +| string.cpp:218:12:218:26 | call to source | string.cpp:220:17:220:17 | c | | +| string.cpp:220:3:220:5 | ref arg s10 | string.cpp:221:8:221:10 | s10 | | +| string.cpp:220:17:220:17 | c | string.cpp:220:3:220:5 | ref arg s10 | TAINT | +| string.cpp:220:17:220:17 | c | string.cpp:220:7:220:12 | call to append | TAINT | | structlikeclass.cpp:5:7:5:7 | Unknown literal | structlikeclass.cpp:5:7:5:7 | constructor init of field v | TAINT | | structlikeclass.cpp:5:7:5:7 | Unknown literal | structlikeclass.cpp:5:7:5:7 | constructor init of field v | TAINT | | structlikeclass.cpp:5:7:5:7 | this | structlikeclass.cpp:5:7:5:7 | constructor init of field v [pre-this] | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp index 07314e4b2ab..8770dc54be2 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp @@ -1,10 +1,24 @@ #include "stl.h" +using namespace std; + char *source(); + +namespace ns_char +{ + char source(); +} + +char *user_input() { + return source(); +} + void sink(const char *s) {}; void sink(const std::string &s) {}; void sink(const std::stringstream &s) {}; +void sink(const char *filename, const char *mode); +void sink(char) {} void test_string() { @@ -55,14 +69,6 @@ void test_stringstream_int(int source) sink(ss2.str()); // tainted [NOT DETECTED] } -using namespace std; - -char *user_input() { - return source(); -} - -void sink(const char *filename, const char *mode); - void test_strings2() { string path1 = user_input(); @@ -146,8 +152,6 @@ void test_string_constructors_assignments() } } -void sink(char) {} - void test_range_based_for_loop_string() { std::string s(source()); for(char c : s) { @@ -168,11 +172,6 @@ void test_range_based_for_loop_string() { } } -namespace ns_char -{ - char source(); -} - void test_string_append() { { std::string s1("hello"); diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected index 8647fddaaf5..7f475398c1d 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -32,34 +32,34 @@ | movableclass.cpp:55:8:55:9 | s2 | movableclass.cpp:52:23:52:28 | call to source | | movableclass.cpp:64:8:64:9 | s2 | movableclass.cpp:23:55:23:60 | call to source | | movableclass.cpp:65:11:65:11 | call to operator= | movableclass.cpp:65:13:65:18 | call to source | -| string.cpp:15:7:15:7 | a | string.cpp:11:12:11:17 | call to source | -| string.cpp:17:7:17:7 | c | string.cpp:13:16:13:21 | call to source | -| string.cpp:19:9:19:13 | call to c_str | string.cpp:13:16:13:21 | call to source | -| string.cpp:69:13:69:17 | call to c_str | string.cpp:61:10:61:15 | call to source | -| string.cpp:73:13:73:17 | call to c_str | string.cpp:61:10:61:15 | call to source | -| string.cpp:76:13:76:17 | call to c_str | string.cpp:61:10:61:15 | call to source | -| string.cpp:86:7:86:8 | cs | string.cpp:81:19:81:24 | call to source | -| string.cpp:87:7:87:8 | ss | string.cpp:81:19:81:24 | call to source | -| string.cpp:100:7:100:8 | cs | string.cpp:92:19:92:24 | call to source | -| string.cpp:101:7:101:8 | ss | string.cpp:92:19:92:24 | call to source | -| string.cpp:123:8:123:9 | s1 | string.cpp:118:18:118:23 | call to source | -| string.cpp:124:8:124:9 | s2 | string.cpp:119:20:119:25 | call to source | -| string.cpp:125:8:125:9 | s3 | string.cpp:121:8:121:13 | call to source | -| string.cpp:144:8:144:9 | s1 | string.cpp:140:32:140:37 | call to source | -| string.cpp:145:8:145:9 | s2 | string.cpp:142:20:142:25 | call to source | -| string.cpp:154:8:154:8 | c | string.cpp:152:16:152:21 | call to source | -| string.cpp:162:8:162:8 | c | string.cpp:152:16:152:21 | call to source | -| string.cpp:167:8:167:8 | c | string.cpp:165:28:165:33 | call to source | -| string.cpp:182:11:182:11 | call to operator+ | string.cpp:179:18:179:23 | call to source | -| string.cpp:183:11:183:11 | call to operator+ | string.cpp:179:18:179:23 | call to source | -| string.cpp:184:11:184:11 | call to operator+ | string.cpp:179:18:179:23 | call to source | -| string.cpp:187:11:187:11 | call to operator+ | string.cpp:187:13:187:18 | call to source | -| string.cpp:196:8:196:9 | s5 | string.cpp:192:18:192:23 | call to source | -| string.cpp:200:8:200:9 | s6 | string.cpp:192:18:192:23 | call to source | -| string.cpp:205:8:205:9 | s7 | string.cpp:203:9:203:14 | call to source | -| string.cpp:209:8:209:9 | s8 | string.cpp:192:18:192:23 | call to source | -| string.cpp:214:8:214:9 | s9 | string.cpp:212:13:212:18 | call to source | -| string.cpp:222:8:222:10 | s10 | string.cpp:219:12:219:26 | call to source | +| string.cpp:29:7:29:7 | a | string.cpp:25:12:25:17 | call to source | +| string.cpp:31:7:31:7 | c | string.cpp:27:16:27:21 | call to source | +| string.cpp:33:9:33:13 | call to c_str | string.cpp:27:16:27:21 | call to source | +| string.cpp:75:13:75:17 | call to c_str | string.cpp:14:10:14:15 | call to source | +| string.cpp:79:13:79:17 | call to c_str | string.cpp:14:10:14:15 | call to source | +| string.cpp:82:13:82:17 | call to c_str | string.cpp:14:10:14:15 | call to source | +| string.cpp:92:7:92:8 | cs | string.cpp:87:19:87:24 | call to source | +| string.cpp:93:7:93:8 | ss | string.cpp:87:19:87:24 | call to source | +| string.cpp:106:7:106:8 | cs | string.cpp:98:19:98:24 | call to source | +| string.cpp:107:7:107:8 | ss | string.cpp:98:19:98:24 | call to source | +| string.cpp:129:8:129:9 | s1 | string.cpp:124:18:124:23 | call to source | +| string.cpp:130:8:130:9 | s2 | string.cpp:125:20:125:25 | call to source | +| string.cpp:131:8:131:9 | s3 | string.cpp:127:8:127:13 | call to source | +| string.cpp:150:8:150:9 | s1 | string.cpp:146:32:146:37 | call to source | +| string.cpp:151:8:151:9 | s2 | string.cpp:148:20:148:25 | call to source | +| string.cpp:158:8:158:8 | c | string.cpp:156:16:156:21 | call to source | +| string.cpp:166:8:166:8 | c | string.cpp:156:16:156:21 | call to source | +| string.cpp:171:8:171:8 | c | string.cpp:169:28:169:33 | call to source | +| string.cpp:181:11:181:11 | call to operator+ | string.cpp:178:18:178:23 | call to source | +| string.cpp:182:11:182:11 | call to operator+ | string.cpp:178:18:178:23 | call to source | +| string.cpp:183:11:183:11 | call to operator+ | string.cpp:178:18:178:23 | call to source | +| string.cpp:186:11:186:11 | call to operator+ | string.cpp:186:13:186:18 | call to source | +| string.cpp:195:8:195:9 | s5 | string.cpp:191:18:191:23 | call to source | +| string.cpp:199:8:199:9 | s6 | string.cpp:191:18:191:23 | call to source | +| string.cpp:204:8:204:9 | s7 | string.cpp:202:9:202:14 | call to source | +| string.cpp:208:8:208:9 | s8 | string.cpp:191:18:191:23 | call to source | +| string.cpp:213:8:213:9 | s9 | string.cpp:211:13:211:18 | call to source | +| string.cpp:221:8:221:10 | s10 | string.cpp:218:12:218:26 | call to source | | structlikeclass.cpp:35:8:35:9 | s1 | structlikeclass.cpp:29:22:29:27 | call to source | | structlikeclass.cpp:36:8:36:9 | s2 | structlikeclass.cpp:30:24:30:29 | call to source | | structlikeclass.cpp:37:8:37:9 | s3 | structlikeclass.cpp:29:22:29:27 | call to source | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected index d18a2c14437..894b19ea38a 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected @@ -30,33 +30,33 @@ | movableclass.cpp:55:8:55:9 | movableclass.cpp:52:23:52:28 | AST only | | movableclass.cpp:64:8:64:9 | movableclass.cpp:23:55:23:60 | AST only | | movableclass.cpp:65:11:65:11 | movableclass.cpp:65:13:65:18 | AST only | -| string.cpp:17:7:17:7 | string.cpp:13:16:13:21 | AST only | -| string.cpp:19:9:19:13 | string.cpp:13:16:13:21 | AST only | -| string.cpp:69:13:69:17 | string.cpp:61:10:61:15 | AST only | -| string.cpp:73:13:73:17 | string.cpp:61:10:61:15 | AST only | -| string.cpp:76:13:76:17 | string.cpp:61:10:61:15 | AST only | -| string.cpp:86:7:86:8 | string.cpp:81:19:81:26 | IR only | -| string.cpp:87:7:87:8 | string.cpp:81:19:81:24 | AST only | -| string.cpp:100:7:100:8 | string.cpp:92:19:92:24 | AST only | -| string.cpp:101:7:101:8 | string.cpp:92:19:92:24 | AST only | -| string.cpp:123:8:123:9 | string.cpp:118:18:118:23 | AST only | -| string.cpp:124:8:124:9 | string.cpp:119:20:119:25 | AST only | -| string.cpp:125:8:125:9 | string.cpp:121:8:121:13 | AST only | -| string.cpp:144:8:144:9 | string.cpp:140:32:140:37 | AST only | -| string.cpp:145:8:145:9 | string.cpp:142:20:142:25 | AST only | -| string.cpp:154:8:154:8 | string.cpp:152:16:152:21 | AST only | -| string.cpp:162:8:162:8 | string.cpp:152:16:152:21 | AST only | -| string.cpp:167:8:167:8 | string.cpp:165:28:165:33 | AST only | -| string.cpp:182:11:182:11 | string.cpp:179:18:179:23 | AST only | -| string.cpp:183:11:183:11 | string.cpp:179:18:179:23 | AST only | -| string.cpp:184:11:184:11 | string.cpp:179:18:179:23 | AST only | -| string.cpp:187:11:187:11 | string.cpp:187:13:187:18 | AST only | -| string.cpp:196:8:196:9 | string.cpp:192:18:192:23 | AST only | -| string.cpp:200:8:200:9 | string.cpp:192:18:192:23 | AST only | -| string.cpp:205:8:205:9 | string.cpp:203:9:203:14 | AST only | -| string.cpp:209:8:209:9 | string.cpp:192:18:192:23 | AST only | -| string.cpp:214:8:214:9 | string.cpp:212:13:212:18 | AST only | -| string.cpp:222:8:222:10 | string.cpp:219:12:219:26 | AST only | +| string.cpp:31:7:31:7 | string.cpp:27:16:27:21 | AST only | +| string.cpp:33:9:33:13 | string.cpp:27:16:27:21 | AST only | +| string.cpp:75:13:75:17 | string.cpp:14:10:14:15 | AST only | +| string.cpp:79:13:79:17 | string.cpp:14:10:14:15 | AST only | +| string.cpp:82:13:82:17 | string.cpp:14:10:14:15 | AST only | +| string.cpp:92:7:92:8 | string.cpp:87:19:87:26 | IR only | +| string.cpp:93:7:93:8 | string.cpp:87:19:87:24 | AST only | +| string.cpp:106:7:106:8 | string.cpp:98:19:98:24 | AST only | +| string.cpp:107:7:107:8 | string.cpp:98:19:98:24 | AST only | +| string.cpp:129:8:129:9 | string.cpp:124:18:124:23 | AST only | +| string.cpp:130:8:130:9 | string.cpp:125:20:125:25 | AST only | +| string.cpp:131:8:131:9 | string.cpp:127:8:127:13 | AST only | +| string.cpp:150:8:150:9 | string.cpp:146:32:146:37 | AST only | +| string.cpp:151:8:151:9 | string.cpp:148:20:148:25 | AST only | +| string.cpp:158:8:158:8 | string.cpp:156:16:156:21 | AST only | +| string.cpp:166:8:166:8 | string.cpp:156:16:156:21 | AST only | +| string.cpp:171:8:171:8 | string.cpp:169:28:169:33 | AST only | +| string.cpp:181:11:181:11 | string.cpp:178:18:178:23 | AST only | +| string.cpp:182:11:182:11 | string.cpp:178:18:178:23 | AST only | +| string.cpp:183:11:183:11 | string.cpp:178:18:178:23 | AST only | +| string.cpp:186:11:186:11 | string.cpp:186:13:186:18 | AST only | +| string.cpp:195:8:195:9 | string.cpp:191:18:191:23 | AST only | +| string.cpp:199:8:199:9 | string.cpp:191:18:191:23 | AST only | +| string.cpp:204:8:204:9 | string.cpp:202:9:202:14 | AST only | +| string.cpp:208:8:208:9 | string.cpp:191:18:191:23 | AST only | +| string.cpp:213:8:213:9 | string.cpp:211:13:211:18 | AST only | +| string.cpp:221:8:221:10 | string.cpp:218:12:218:26 | AST only | | structlikeclass.cpp:35:8:35:9 | structlikeclass.cpp:29:22:29:27 | AST only | | structlikeclass.cpp:36:8:36:9 | structlikeclass.cpp:30:24:30:29 | AST only | | structlikeclass.cpp:37:8:37:9 | structlikeclass.cpp:29:22:29:27 | AST only | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected index 69e1fe2901f..8fbab29d8da 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected @@ -1,10 +1,10 @@ | format.cpp:157:7:157:22 | (int)... | format.cpp:147:12:147:25 | call to source | | format.cpp:157:7:157:22 | access to array | format.cpp:147:12:147:25 | call to source | | format.cpp:158:7:158:27 | ... + ... | format.cpp:148:16:148:30 | call to source | -| string.cpp:15:7:15:7 | (const char *)... | string.cpp:11:12:11:17 | call to source | -| string.cpp:15:7:15:7 | a | string.cpp:11:12:11:17 | call to source | -| string.cpp:86:7:86:8 | cs | string.cpp:81:19:81:24 | call to source | -| string.cpp:86:7:86:8 | cs | string.cpp:81:19:81:26 | (const char *)... | +| string.cpp:29:7:29:7 | (const char *)... | string.cpp:25:12:25:17 | call to source | +| string.cpp:29:7:29:7 | a | string.cpp:25:12:25:17 | call to source | +| string.cpp:92:7:92:8 | cs | string.cpp:87:19:87:24 | call to source | +| string.cpp:92:7:92:8 | cs | string.cpp:87:19:87:26 | (const char *)... | | structlikeclass.cpp:38:8:38:9 | s4 | structlikeclass.cpp:33:8:33:13 | call to source | | structlikeclass.cpp:61:8:61:9 | s2 | structlikeclass.cpp:58:24:58:29 | call to source | | structlikeclass.cpp:62:8:62:20 | ... = ... | structlikeclass.cpp:62:13:62:18 | call to source | From a839f1fae5c5e962bc38c950871b9de90a7dcc8c Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 13 Aug 2020 18:17:02 +0100 Subject: [PATCH 067/133] C++: Split off stringstream.cpp. --- .../dataflow/taint-tests/localTaint.expected | 448 +++++++++--------- .../dataflow/taint-tests/string.cpp | 37 -- .../dataflow/taint-tests/stringstream.cpp | 45 ++ .../dataflow/taint-tests/taint.expected | 56 +-- .../dataflow/taint-tests/test_diff.expected | 54 +-- .../dataflow/taint-tests/test_ir.expected | 8 +- 6 files changed, 328 insertions(+), 320 deletions(-) create mode 100644 cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected index f4449f8ed16..2fc40532357 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -308,230 +308,230 @@ | movableclass.cpp:65:13:65:18 | call to source | movableclass.cpp:65:13:65:20 | call to MyMovableClass | TAINT | | movableclass.cpp:65:13:65:20 | call to MyMovableClass | movableclass.cpp:65:8:65:9 | ref arg s3 | TAINT | | movableclass.cpp:65:13:65:20 | call to MyMovableClass | movableclass.cpp:65:11:65:11 | call to operator= | TAINT | -| string.cpp:25:12:25:17 | call to source | string.cpp:29:7:29:7 | a | | -| string.cpp:26:16:26:20 | 123 | string.cpp:26:16:26:21 | call to basic_string | TAINT | -| string.cpp:26:16:26:21 | call to basic_string | string.cpp:30:7:30:7 | b | | -| string.cpp:26:16:26:21 | call to basic_string | string.cpp:32:7:32:7 | b | | -| string.cpp:27:16:27:21 | call to source | string.cpp:27:16:27:24 | call to basic_string | TAINT | -| string.cpp:27:16:27:24 | call to basic_string | string.cpp:31:7:31:7 | c | | -| string.cpp:27:16:27:24 | call to basic_string | string.cpp:33:7:33:7 | c | | -| string.cpp:32:7:32:7 | b | string.cpp:32:9:32:13 | call to c_str | TAINT | -| string.cpp:33:7:33:7 | c | string.cpp:33:9:33:13 | call to c_str | TAINT | -| string.cpp:38:20:38:22 | call to basic_stringstream | string.cpp:41:2:41:4 | ss1 | | -| string.cpp:38:20:38:22 | call to basic_stringstream | string.cpp:47:7:47:9 | ss1 | | -| string.cpp:38:20:38:22 | call to basic_stringstream | string.cpp:52:7:52:9 | ss1 | | -| string.cpp:38:25:38:27 | call to basic_stringstream | string.cpp:42:2:42:4 | ss2 | | -| string.cpp:38:25:38:27 | call to basic_stringstream | string.cpp:48:7:48:9 | ss2 | | -| string.cpp:38:25:38:27 | call to basic_stringstream | string.cpp:53:7:53:9 | ss2 | | -| string.cpp:38:30:38:32 | call to basic_stringstream | string.cpp:43:2:43:4 | ss3 | | -| string.cpp:38:30:38:32 | call to basic_stringstream | string.cpp:49:7:49:9 | ss3 | | -| string.cpp:38:30:38:32 | call to basic_stringstream | string.cpp:54:7:54:9 | ss3 | | -| string.cpp:38:35:38:37 | call to basic_stringstream | string.cpp:44:2:44:4 | ss4 | | -| string.cpp:38:35:38:37 | call to basic_stringstream | string.cpp:50:7:50:9 | ss4 | | -| string.cpp:38:35:38:37 | call to basic_stringstream | string.cpp:55:7:55:9 | ss4 | | -| string.cpp:38:40:38:42 | call to basic_stringstream | string.cpp:45:2:45:4 | ss5 | | -| string.cpp:38:40:38:42 | call to basic_stringstream | string.cpp:51:7:51:9 | ss5 | | -| string.cpp:38:40:38:42 | call to basic_stringstream | string.cpp:56:7:56:9 | ss5 | | -| string.cpp:39:16:39:21 | call to source | string.cpp:39:16:39:24 | call to basic_string | TAINT | -| string.cpp:39:16:39:24 | call to basic_string | string.cpp:45:9:45:9 | t | | -| string.cpp:41:2:41:4 | ref arg ss1 | string.cpp:47:7:47:9 | ss1 | | -| string.cpp:41:2:41:4 | ref arg ss1 | string.cpp:52:7:52:9 | ss1 | | -| string.cpp:42:2:42:4 | ref arg ss2 | string.cpp:48:7:48:9 | ss2 | | -| string.cpp:42:2:42:4 | ref arg ss2 | string.cpp:53:7:53:9 | ss2 | | -| string.cpp:43:2:43:4 | ref arg ss3 | string.cpp:49:7:49:9 | ss3 | | -| string.cpp:43:2:43:4 | ref arg ss3 | string.cpp:54:7:54:9 | ss3 | | -| string.cpp:44:2:44:4 | ref arg ss4 | string.cpp:50:7:50:9 | ss4 | | -| string.cpp:44:2:44:4 | ref arg ss4 | string.cpp:55:7:55:9 | ss4 | | -| string.cpp:45:2:45:4 | ref arg ss5 | string.cpp:51:7:51:9 | ss5 | | -| string.cpp:45:2:45:4 | ref arg ss5 | string.cpp:56:7:56:9 | ss5 | | -| string.cpp:59:32:59:37 | source | string.cpp:64:9:64:14 | source | | -| string.cpp:61:20:61:22 | call to basic_stringstream | string.cpp:63:2:63:4 | ss1 | | -| string.cpp:61:20:61:22 | call to basic_stringstream | string.cpp:66:7:66:9 | ss1 | | -| string.cpp:61:20:61:22 | call to basic_stringstream | string.cpp:68:7:68:9 | ss1 | | -| string.cpp:61:25:61:27 | call to basic_stringstream | string.cpp:64:2:64:4 | ss2 | | -| string.cpp:61:25:61:27 | call to basic_stringstream | string.cpp:67:7:67:9 | ss2 | | -| string.cpp:61:25:61:27 | call to basic_stringstream | string.cpp:69:7:69:9 | ss2 | | -| string.cpp:63:2:63:4 | ref arg ss1 | string.cpp:66:7:66:9 | ss1 | | -| string.cpp:63:2:63:4 | ref arg ss1 | string.cpp:68:7:68:9 | ss1 | | -| string.cpp:64:2:64:4 | ref arg ss2 | string.cpp:67:7:67:9 | ss2 | | -| string.cpp:64:2:64:4 | ref arg ss2 | string.cpp:69:7:69:9 | ss2 | | -| string.cpp:74:16:74:28 | call to basic_string | string.cpp:75:7:75:11 | path1 | | -| string.cpp:74:17:74:26 | call to user_input | string.cpp:74:16:74:28 | call to basic_string | TAINT | -| string.cpp:75:7:75:11 | path1 | string.cpp:75:13:75:17 | call to c_str | TAINT | -| string.cpp:78:10:78:19 | call to user_input | string.cpp:78:10:78:21 | call to basic_string | TAINT | -| string.cpp:78:10:78:21 | call to basic_string | string.cpp:78:2:78:21 | ... = ... | | -| string.cpp:78:10:78:21 | call to basic_string | string.cpp:79:7:79:11 | path2 | | -| string.cpp:79:7:79:11 | path2 | string.cpp:79:13:79:17 | call to c_str | TAINT | -| string.cpp:81:15:81:24 | call to user_input | string.cpp:81:15:81:27 | call to basic_string | TAINT | -| string.cpp:81:15:81:27 | call to basic_string | string.cpp:82:7:82:11 | path3 | | -| string.cpp:82:7:82:11 | path3 | string.cpp:82:13:82:17 | call to c_str | TAINT | -| string.cpp:87:19:87:24 | call to source | string.cpp:90:17:90:18 | cs | | -| string.cpp:87:19:87:24 | call to source | string.cpp:92:7:92:8 | cs | | -| string.cpp:90:17:90:18 | cs | string.cpp:90:17:90:19 | call to basic_string | TAINT | -| string.cpp:90:17:90:19 | call to basic_string | string.cpp:93:7:93:8 | ss | | -| string.cpp:98:19:98:24 | call to source | string.cpp:101:17:101:18 | cs | | -| string.cpp:101:17:101:18 | cs | string.cpp:101:17:101:19 | call to basic_string | TAINT | -| string.cpp:101:17:101:19 | call to basic_string | string.cpp:104:7:104:8 | ss | | -| string.cpp:101:17:101:19 | call to basic_string | string.cpp:107:7:107:8 | ss | | -| string.cpp:104:7:104:8 | ss | string.cpp:104:10:104:14 | call to c_str | TAINT | -| string.cpp:104:10:104:14 | call to c_str | string.cpp:104:2:104:16 | ... = ... | | -| string.cpp:104:10:104:14 | call to c_str | string.cpp:106:7:106:8 | cs | | -| string.cpp:113:18:113:24 | hello | string.cpp:113:18:113:25 | call to basic_string | TAINT | -| string.cpp:113:18:113:25 | call to basic_string | string.cpp:118:8:118:9 | s1 | | -| string.cpp:114:19:114:26 | call to basic_string | string.cpp:119:8:119:9 | s2 | | -| string.cpp:114:20:114:26 | hello | string.cpp:114:19:114:26 | call to basic_string | TAINT | -| string.cpp:116:8:116:14 | call to basic_string | string.cpp:116:3:116:14 | ... = ... | | -| string.cpp:116:8:116:14 | call to basic_string | string.cpp:120:8:120:9 | s3 | | -| string.cpp:116:8:116:14 | hello | string.cpp:116:8:116:14 | call to basic_string | TAINT | -| string.cpp:124:18:124:23 | call to source | string.cpp:124:18:124:26 | call to basic_string | TAINT | -| string.cpp:124:18:124:26 | call to basic_string | string.cpp:129:8:129:9 | s1 | | -| string.cpp:125:19:125:27 | call to basic_string | string.cpp:130:8:130:9 | s2 | | -| string.cpp:125:20:125:25 | call to source | string.cpp:125:19:125:27 | call to basic_string | TAINT | -| string.cpp:127:8:127:13 | call to source | string.cpp:127:8:127:15 | call to basic_string | TAINT | -| string.cpp:127:8:127:15 | call to basic_string | string.cpp:127:3:127:15 | ... = ... | | -| string.cpp:127:8:127:15 | call to basic_string | string.cpp:131:8:131:9 | s3 | | -| string.cpp:135:15:135:16 | call to basic_string | string.cpp:136:20:136:21 | s1 | | -| string.cpp:135:15:135:16 | call to basic_string | string.cpp:138:8:138:9 | s1 | | -| string.cpp:135:15:135:16 | call to basic_string | string.cpp:140:8:140:9 | s1 | | -| string.cpp:136:20:136:21 | s1 | string.cpp:141:8:141:9 | s2 | | -| string.cpp:138:8:138:9 | s1 | string.cpp:138:3:138:9 | ... = ... | | -| string.cpp:138:8:138:9 | s1 | string.cpp:142:8:142:9 | s3 | | -| string.cpp:146:19:146:40 | call to basic_string | string.cpp:150:8:150:9 | s1 | | -| string.cpp:146:32:146:37 | call to source | string.cpp:146:19:146:40 | call to basic_string | TAINT | -| string.cpp:148:8:148:28 | call to basic_string | string.cpp:148:3:148:28 | ... = ... | | -| string.cpp:148:8:148:28 | call to basic_string | string.cpp:151:8:151:9 | s2 | | -| string.cpp:148:20:148:25 | call to source | string.cpp:148:8:148:28 | call to basic_string | TAINT | -| string.cpp:156:16:156:21 | call to source | string.cpp:156:16:156:24 | call to basic_string | TAINT | -| string.cpp:156:16:156:24 | call to basic_string | string.cpp:157:15:157:15 | s | | -| string.cpp:156:16:156:24 | call to basic_string | string.cpp:161:33:161:33 | s | | -| string.cpp:156:16:156:24 | call to basic_string | string.cpp:161:50:161:50 | s | | -| string.cpp:156:16:156:24 | call to basic_string | string.cpp:165:16:165:16 | s | | -| string.cpp:157:15:157:15 | call to begin | string.cpp:157:15:157:15 | (__begin) | | -| string.cpp:157:15:157:15 | call to begin | string.cpp:157:15:157:15 | (__begin) | | -| string.cpp:157:15:157:15 | call to begin | string.cpp:157:15:157:15 | (__begin) | | -| string.cpp:157:15:157:15 | call to end | string.cpp:157:15:157:15 | (__end) | | -| string.cpp:157:15:157:15 | call to operator* | string.cpp:158:8:158:8 | c | | -| string.cpp:157:15:157:15 | ref arg (__begin) | string.cpp:157:15:157:15 | (__begin) | | -| string.cpp:157:15:157:15 | ref arg (__begin) | string.cpp:157:15:157:15 | (__begin) | | -| string.cpp:157:15:157:15 | ref arg (__begin) | string.cpp:157:15:157:15 | (__begin) | | -| string.cpp:157:15:157:15 | ref arg (__range) | string.cpp:157:15:157:15 | (__range) | | -| string.cpp:157:15:157:15 | s | string.cpp:157:15:157:15 | (__range) | | -| string.cpp:157:15:157:15 | s | string.cpp:157:15:157:15 | (__range) | | -| string.cpp:157:15:157:15 | s | string.cpp:157:15:157:15 | call to operator* | TAINT | -| string.cpp:161:33:161:33 | ref arg s | string.cpp:161:50:161:50 | s | | -| string.cpp:161:33:161:33 | ref arg s | string.cpp:165:16:165:16 | s | | -| string.cpp:161:35:161:39 | call to begin | string.cpp:161:44:161:45 | it | | -| string.cpp:161:35:161:39 | call to begin | string.cpp:161:61:161:62 | it | | -| string.cpp:161:35:161:39 | call to begin | string.cpp:162:9:162:10 | it | | -| string.cpp:161:50:161:50 | ref arg s | string.cpp:161:50:161:50 | s | | -| string.cpp:161:50:161:50 | ref arg s | string.cpp:165:16:165:16 | s | | -| string.cpp:161:61:161:62 | ref arg it | string.cpp:161:44:161:45 | it | | -| string.cpp:161:61:161:62 | ref arg it | string.cpp:161:61:161:62 | it | | -| string.cpp:161:61:161:62 | ref arg it | string.cpp:162:9:162:10 | it | | -| string.cpp:165:16:165:16 | call to begin | string.cpp:165:16:165:16 | (__begin) | | -| string.cpp:165:16:165:16 | call to begin | string.cpp:165:16:165:16 | (__begin) | | -| string.cpp:165:16:165:16 | call to begin | string.cpp:165:16:165:16 | (__begin) | | -| string.cpp:165:16:165:16 | call to end | string.cpp:165:16:165:16 | (__end) | | -| string.cpp:165:16:165:16 | call to operator* | string.cpp:166:8:166:8 | c | | -| string.cpp:165:16:165:16 | ref arg (__begin) | string.cpp:165:16:165:16 | (__begin) | | -| string.cpp:165:16:165:16 | ref arg (__begin) | string.cpp:165:16:165:16 | (__begin) | | -| string.cpp:165:16:165:16 | ref arg (__begin) | string.cpp:165:16:165:16 | (__begin) | | -| string.cpp:165:16:165:16 | ref arg (__range) | string.cpp:165:16:165:16 | (__range) | | -| string.cpp:165:16:165:16 | s | string.cpp:165:16:165:16 | (__range) | | -| string.cpp:165:16:165:16 | s | string.cpp:165:16:165:16 | (__range) | | -| string.cpp:165:16:165:16 | s | string.cpp:165:16:165:16 | call to operator* | TAINT | -| string.cpp:169:28:169:33 | call to source | string.cpp:169:28:169:36 | call to basic_string | TAINT | -| string.cpp:169:28:169:36 | call to basic_string | string.cpp:170:22:170:28 | const_s | | -| string.cpp:170:22:170:22 | call to begin | string.cpp:170:22:170:22 | (__begin) | | -| string.cpp:170:22:170:22 | call to begin | string.cpp:170:22:170:22 | (__begin) | | -| string.cpp:170:22:170:22 | call to begin | string.cpp:170:22:170:22 | (__begin) | | -| string.cpp:170:22:170:22 | call to end | string.cpp:170:22:170:22 | (__end) | | -| string.cpp:170:22:170:22 | call to operator* | string.cpp:171:8:171:8 | c | | -| string.cpp:170:22:170:22 | ref arg (__begin) | string.cpp:170:22:170:22 | (__begin) | | -| string.cpp:170:22:170:22 | ref arg (__begin) | string.cpp:170:22:170:22 | (__begin) | | -| string.cpp:170:22:170:22 | ref arg (__begin) | string.cpp:170:22:170:22 | (__begin) | | -| string.cpp:170:22:170:28 | const_s | string.cpp:170:22:170:22 | (__range) | | -| string.cpp:170:22:170:28 | const_s | string.cpp:170:22:170:22 | (__range) | | -| string.cpp:170:22:170:28 | const_s | string.cpp:170:22:170:22 | call to operator* | TAINT | -| string.cpp:177:18:177:24 | hello | string.cpp:177:18:177:25 | call to basic_string | TAINT | -| string.cpp:177:18:177:25 | call to basic_string | string.cpp:180:8:180:9 | s1 | | -| string.cpp:177:18:177:25 | call to basic_string | string.cpp:180:13:180:14 | s1 | | -| string.cpp:177:18:177:25 | call to basic_string | string.cpp:181:8:181:9 | s1 | | -| string.cpp:177:18:177:25 | call to basic_string | string.cpp:182:13:182:14 | s1 | | -| string.cpp:177:18:177:25 | call to basic_string | string.cpp:185:8:185:9 | s1 | | -| string.cpp:177:18:177:25 | call to basic_string | string.cpp:186:8:186:9 | s1 | | -| string.cpp:178:18:178:23 | call to source | string.cpp:178:18:178:26 | call to basic_string | TAINT | -| string.cpp:178:18:178:26 | call to basic_string | string.cpp:181:13:181:14 | s2 | | -| string.cpp:178:18:178:26 | call to basic_string | string.cpp:182:8:182:9 | s2 | | -| string.cpp:178:18:178:26 | call to basic_string | string.cpp:183:8:183:9 | s2 | | -| string.cpp:178:18:178:26 | call to basic_string | string.cpp:183:13:183:14 | s2 | | -| string.cpp:180:8:180:9 | s1 | string.cpp:180:11:180:11 | call to operator+ | TAINT | -| string.cpp:180:13:180:14 | s1 | string.cpp:180:11:180:11 | call to operator+ | TAINT | -| string.cpp:181:8:181:9 | s1 | string.cpp:181:11:181:11 | call to operator+ | TAINT | -| string.cpp:181:13:181:14 | s2 | string.cpp:181:11:181:11 | call to operator+ | TAINT | -| string.cpp:182:8:182:9 | s2 | string.cpp:182:11:182:11 | call to operator+ | TAINT | -| string.cpp:182:13:182:14 | s1 | string.cpp:182:11:182:11 | call to operator+ | TAINT | -| string.cpp:183:8:183:9 | s2 | string.cpp:183:11:183:11 | call to operator+ | TAINT | -| string.cpp:183:13:183:14 | s2 | string.cpp:183:11:183:11 | call to operator+ | TAINT | -| string.cpp:185:8:185:9 | s1 | string.cpp:185:11:185:11 | call to operator+ | TAINT | -| string.cpp:185:13:185:20 | world | string.cpp:185:11:185:11 | call to operator+ | TAINT | -| string.cpp:186:8:186:9 | s1 | string.cpp:186:11:186:11 | call to operator+ | TAINT | -| string.cpp:186:13:186:18 | call to source | string.cpp:186:11:186:11 | call to operator+ | TAINT | -| string.cpp:190:18:190:22 | abc | string.cpp:190:18:190:23 | call to basic_string | TAINT | -| string.cpp:190:18:190:23 | call to basic_string | string.cpp:194:8:194:9 | s3 | | -| string.cpp:190:18:190:23 | call to basic_string | string.cpp:197:8:197:9 | s3 | | -| string.cpp:190:18:190:23 | call to basic_string | string.cpp:201:8:201:9 | s3 | | -| string.cpp:190:18:190:23 | call to basic_string | string.cpp:206:8:206:9 | s3 | | -| string.cpp:190:18:190:23 | call to basic_string | string.cpp:210:8:210:9 | s3 | | -| string.cpp:191:18:191:23 | call to source | string.cpp:191:18:191:26 | call to basic_string | TAINT | -| string.cpp:191:18:191:26 | call to basic_string | string.cpp:194:13:194:14 | s4 | | -| string.cpp:191:18:191:26 | call to basic_string | string.cpp:198:9:198:10 | s4 | | -| string.cpp:191:18:191:26 | call to basic_string | string.cpp:207:13:207:14 | s4 | | -| string.cpp:194:8:194:9 | s3 | string.cpp:194:11:194:11 | call to operator+ | TAINT | -| string.cpp:194:11:194:11 | call to operator+ | string.cpp:194:3:194:14 | ... = ... | | -| string.cpp:194:11:194:11 | call to operator+ | string.cpp:195:8:195:9 | s5 | | -| string.cpp:194:13:194:14 | s4 | string.cpp:194:11:194:11 | call to operator+ | TAINT | -| string.cpp:197:8:197:9 | s3 | string.cpp:197:3:197:9 | ... = ... | | -| string.cpp:197:8:197:9 | s3 | string.cpp:198:3:198:4 | s6 | | -| string.cpp:197:8:197:9 | s3 | string.cpp:199:8:199:9 | s6 | | -| string.cpp:198:3:198:4 | ref arg s6 | string.cpp:199:8:199:9 | s6 | | -| string.cpp:198:9:198:10 | s4 | string.cpp:198:3:198:4 | ref arg s6 | TAINT | -| string.cpp:198:9:198:10 | s4 | string.cpp:198:6:198:6 | call to operator+= | TAINT | -| string.cpp:201:8:201:9 | s3 | string.cpp:201:3:201:9 | ... = ... | | -| string.cpp:201:8:201:9 | s3 | string.cpp:202:3:202:4 | s7 | | -| string.cpp:201:8:201:9 | s3 | string.cpp:203:3:203:4 | s7 | | -| string.cpp:201:8:201:9 | s3 | string.cpp:204:8:204:9 | s7 | | -| string.cpp:202:3:202:4 | ref arg s7 | string.cpp:203:3:203:4 | s7 | | -| string.cpp:202:3:202:4 | ref arg s7 | string.cpp:204:8:204:9 | s7 | | -| string.cpp:202:9:202:14 | call to source | string.cpp:202:3:202:4 | ref arg s7 | TAINT | -| string.cpp:202:9:202:14 | call to source | string.cpp:202:6:202:6 | call to operator+= | TAINT | -| string.cpp:203:3:203:4 | ref arg s7 | string.cpp:204:8:204:9 | s7 | | -| string.cpp:203:9:203:11 | | string.cpp:203:3:203:4 | ref arg s7 | TAINT | -| string.cpp:203:9:203:11 | | string.cpp:203:6:203:6 | call to operator+= | TAINT | -| string.cpp:206:8:206:9 | s3 | string.cpp:206:3:206:9 | ... = ... | | -| string.cpp:206:8:206:9 | s3 | string.cpp:207:3:207:4 | s8 | | -| string.cpp:206:8:206:9 | s3 | string.cpp:208:8:208:9 | s8 | | -| string.cpp:207:3:207:4 | ref arg s8 | string.cpp:208:8:208:9 | s8 | | -| string.cpp:207:13:207:14 | s4 | string.cpp:207:3:207:4 | ref arg s8 | TAINT | -| string.cpp:207:13:207:14 | s4 | string.cpp:207:6:207:11 | call to append | TAINT | -| string.cpp:210:8:210:9 | s3 | string.cpp:210:3:210:9 | ... = ... | | -| string.cpp:210:8:210:9 | s3 | string.cpp:211:3:211:4 | s9 | | -| string.cpp:210:8:210:9 | s3 | string.cpp:212:3:212:4 | s9 | | -| string.cpp:210:8:210:9 | s3 | string.cpp:213:8:213:9 | s9 | | -| string.cpp:211:3:211:4 | ref arg s9 | string.cpp:212:3:212:4 | s9 | | -| string.cpp:211:3:211:4 | ref arg s9 | string.cpp:213:8:213:9 | s9 | | -| string.cpp:211:13:211:18 | call to source | string.cpp:211:3:211:4 | ref arg s9 | TAINT | -| string.cpp:211:13:211:18 | call to source | string.cpp:211:6:211:11 | call to append | TAINT | -| string.cpp:212:3:212:4 | ref arg s9 | string.cpp:213:8:213:9 | s9 | | -| string.cpp:212:13:212:15 | | string.cpp:212:3:212:4 | ref arg s9 | TAINT | -| string.cpp:212:13:212:15 | | string.cpp:212:6:212:11 | call to append | TAINT | -| string.cpp:217:19:217:23 | abc | string.cpp:217:19:217:24 | call to basic_string | TAINT | -| string.cpp:217:19:217:24 | call to basic_string | string.cpp:220:3:220:5 | s10 | | -| string.cpp:217:19:217:24 | call to basic_string | string.cpp:221:8:221:10 | s10 | | -| string.cpp:218:12:218:26 | call to source | string.cpp:220:17:220:17 | c | | -| string.cpp:220:3:220:5 | ref arg s10 | string.cpp:221:8:221:10 | s10 | | -| string.cpp:220:17:220:17 | c | string.cpp:220:3:220:5 | ref arg s10 | TAINT | -| string.cpp:220:17:220:17 | c | string.cpp:220:7:220:12 | call to append | TAINT | +| string.cpp:24:12:24:17 | call to source | string.cpp:28:7:28:7 | a | | +| string.cpp:25:16:25:20 | 123 | string.cpp:25:16:25:21 | call to basic_string | TAINT | +| string.cpp:25:16:25:21 | call to basic_string | string.cpp:29:7:29:7 | b | | +| string.cpp:25:16:25:21 | call to basic_string | string.cpp:31:7:31:7 | b | | +| string.cpp:26:16:26:21 | call to source | string.cpp:26:16:26:24 | call to basic_string | TAINT | +| string.cpp:26:16:26:24 | call to basic_string | string.cpp:30:7:30:7 | c | | +| string.cpp:26:16:26:24 | call to basic_string | string.cpp:32:7:32:7 | c | | +| string.cpp:31:7:31:7 | b | string.cpp:31:9:31:13 | call to c_str | TAINT | +| string.cpp:32:7:32:7 | c | string.cpp:32:9:32:13 | call to c_str | TAINT | +| string.cpp:37:16:37:28 | call to basic_string | string.cpp:38:7:38:11 | path1 | | +| string.cpp:37:17:37:26 | call to user_input | string.cpp:37:16:37:28 | call to basic_string | TAINT | +| string.cpp:38:7:38:11 | path1 | string.cpp:38:13:38:17 | call to c_str | TAINT | +| string.cpp:41:10:41:19 | call to user_input | string.cpp:41:10:41:21 | call to basic_string | TAINT | +| string.cpp:41:10:41:21 | call to basic_string | string.cpp:41:2:41:21 | ... = ... | | +| string.cpp:41:10:41:21 | call to basic_string | string.cpp:42:7:42:11 | path2 | | +| string.cpp:42:7:42:11 | path2 | string.cpp:42:13:42:17 | call to c_str | TAINT | +| string.cpp:44:15:44:24 | call to user_input | string.cpp:44:15:44:27 | call to basic_string | TAINT | +| string.cpp:44:15:44:27 | call to basic_string | string.cpp:45:7:45:11 | path3 | | +| string.cpp:45:7:45:11 | path3 | string.cpp:45:13:45:17 | call to c_str | TAINT | +| string.cpp:50:19:50:24 | call to source | string.cpp:53:17:53:18 | cs | | +| string.cpp:50:19:50:24 | call to source | string.cpp:55:7:55:8 | cs | | +| string.cpp:53:17:53:18 | cs | string.cpp:53:17:53:19 | call to basic_string | TAINT | +| string.cpp:53:17:53:19 | call to basic_string | string.cpp:56:7:56:8 | ss | | +| string.cpp:61:19:61:24 | call to source | string.cpp:64:17:64:18 | cs | | +| string.cpp:64:17:64:18 | cs | string.cpp:64:17:64:19 | call to basic_string | TAINT | +| string.cpp:64:17:64:19 | call to basic_string | string.cpp:67:7:67:8 | ss | | +| string.cpp:64:17:64:19 | call to basic_string | string.cpp:70:7:70:8 | ss | | +| string.cpp:67:7:67:8 | ss | string.cpp:67:10:67:14 | call to c_str | TAINT | +| string.cpp:67:10:67:14 | call to c_str | string.cpp:67:2:67:16 | ... = ... | | +| string.cpp:67:10:67:14 | call to c_str | string.cpp:69:7:69:8 | cs | | +| string.cpp:76:18:76:24 | hello | string.cpp:76:18:76:25 | call to basic_string | TAINT | +| string.cpp:76:18:76:25 | call to basic_string | string.cpp:81:8:81:9 | s1 | | +| string.cpp:77:19:77:26 | call to basic_string | string.cpp:82:8:82:9 | s2 | | +| string.cpp:77:20:77:26 | hello | string.cpp:77:19:77:26 | call to basic_string | TAINT | +| string.cpp:79:8:79:14 | call to basic_string | string.cpp:79:3:79:14 | ... = ... | | +| string.cpp:79:8:79:14 | call to basic_string | string.cpp:83:8:83:9 | s3 | | +| string.cpp:79:8:79:14 | hello | string.cpp:79:8:79:14 | call to basic_string | TAINT | +| string.cpp:87:18:87:23 | call to source | string.cpp:87:18:87:26 | call to basic_string | TAINT | +| string.cpp:87:18:87:26 | call to basic_string | string.cpp:92:8:92:9 | s1 | | +| string.cpp:88:19:88:27 | call to basic_string | string.cpp:93:8:93:9 | s2 | | +| string.cpp:88:20:88:25 | call to source | string.cpp:88:19:88:27 | call to basic_string | TAINT | +| string.cpp:90:8:90:13 | call to source | string.cpp:90:8:90:15 | call to basic_string | TAINT | +| string.cpp:90:8:90:15 | call to basic_string | string.cpp:90:3:90:15 | ... = ... | | +| string.cpp:90:8:90:15 | call to basic_string | string.cpp:94:8:94:9 | s3 | | +| string.cpp:98:15:98:16 | call to basic_string | string.cpp:99:20:99:21 | s1 | | +| string.cpp:98:15:98:16 | call to basic_string | string.cpp:101:8:101:9 | s1 | | +| string.cpp:98:15:98:16 | call to basic_string | string.cpp:103:8:103:9 | s1 | | +| string.cpp:99:20:99:21 | s1 | string.cpp:104:8:104:9 | s2 | | +| string.cpp:101:8:101:9 | s1 | string.cpp:101:3:101:9 | ... = ... | | +| string.cpp:101:8:101:9 | s1 | string.cpp:105:8:105:9 | s3 | | +| string.cpp:109:19:109:40 | call to basic_string | string.cpp:113:8:113:9 | s1 | | +| string.cpp:109:32:109:37 | call to source | string.cpp:109:19:109:40 | call to basic_string | TAINT | +| string.cpp:111:8:111:28 | call to basic_string | string.cpp:111:3:111:28 | ... = ... | | +| string.cpp:111:8:111:28 | call to basic_string | string.cpp:114:8:114:9 | s2 | | +| string.cpp:111:20:111:25 | call to source | string.cpp:111:8:111:28 | call to basic_string | TAINT | +| string.cpp:119:16:119:21 | call to source | string.cpp:119:16:119:24 | call to basic_string | TAINT | +| string.cpp:119:16:119:24 | call to basic_string | string.cpp:120:15:120:15 | s | | +| string.cpp:119:16:119:24 | call to basic_string | string.cpp:124:33:124:33 | s | | +| string.cpp:119:16:119:24 | call to basic_string | string.cpp:124:50:124:50 | s | | +| string.cpp:119:16:119:24 | call to basic_string | string.cpp:128:16:128:16 | s | | +| string.cpp:120:15:120:15 | call to begin | string.cpp:120:15:120:15 | (__begin) | | +| string.cpp:120:15:120:15 | call to begin | string.cpp:120:15:120:15 | (__begin) | | +| string.cpp:120:15:120:15 | call to begin | string.cpp:120:15:120:15 | (__begin) | | +| string.cpp:120:15:120:15 | call to end | string.cpp:120:15:120:15 | (__end) | | +| string.cpp:120:15:120:15 | call to operator* | string.cpp:121:8:121:8 | c | | +| string.cpp:120:15:120:15 | ref arg (__begin) | string.cpp:120:15:120:15 | (__begin) | | +| string.cpp:120:15:120:15 | ref arg (__begin) | string.cpp:120:15:120:15 | (__begin) | | +| string.cpp:120:15:120:15 | ref arg (__begin) | string.cpp:120:15:120:15 | (__begin) | | +| string.cpp:120:15:120:15 | ref arg (__range) | string.cpp:120:15:120:15 | (__range) | | +| string.cpp:120:15:120:15 | s | string.cpp:120:15:120:15 | (__range) | | +| string.cpp:120:15:120:15 | s | string.cpp:120:15:120:15 | (__range) | | +| string.cpp:120:15:120:15 | s | string.cpp:120:15:120:15 | call to operator* | TAINT | +| string.cpp:124:33:124:33 | ref arg s | string.cpp:124:50:124:50 | s | | +| string.cpp:124:33:124:33 | ref arg s | string.cpp:128:16:128:16 | s | | +| string.cpp:124:35:124:39 | call to begin | string.cpp:124:44:124:45 | it | | +| string.cpp:124:35:124:39 | call to begin | string.cpp:124:61:124:62 | it | | +| string.cpp:124:35:124:39 | call to begin | string.cpp:125:9:125:10 | it | | +| string.cpp:124:50:124:50 | ref arg s | string.cpp:124:50:124:50 | s | | +| string.cpp:124:50:124:50 | ref arg s | string.cpp:128:16:128:16 | s | | +| string.cpp:124:61:124:62 | ref arg it | string.cpp:124:44:124:45 | it | | +| string.cpp:124:61:124:62 | ref arg it | string.cpp:124:61:124:62 | it | | +| string.cpp:124:61:124:62 | ref arg it | string.cpp:125:9:125:10 | it | | +| string.cpp:128:16:128:16 | call to begin | string.cpp:128:16:128:16 | (__begin) | | +| string.cpp:128:16:128:16 | call to begin | string.cpp:128:16:128:16 | (__begin) | | +| string.cpp:128:16:128:16 | call to begin | string.cpp:128:16:128:16 | (__begin) | | +| string.cpp:128:16:128:16 | call to end | string.cpp:128:16:128:16 | (__end) | | +| string.cpp:128:16:128:16 | call to operator* | string.cpp:129:8:129:8 | c | | +| string.cpp:128:16:128:16 | ref arg (__begin) | string.cpp:128:16:128:16 | (__begin) | | +| string.cpp:128:16:128:16 | ref arg (__begin) | string.cpp:128:16:128:16 | (__begin) | | +| string.cpp:128:16:128:16 | ref arg (__begin) | string.cpp:128:16:128:16 | (__begin) | | +| string.cpp:128:16:128:16 | ref arg (__range) | string.cpp:128:16:128:16 | (__range) | | +| string.cpp:128:16:128:16 | s | string.cpp:128:16:128:16 | (__range) | | +| string.cpp:128:16:128:16 | s | string.cpp:128:16:128:16 | (__range) | | +| string.cpp:128:16:128:16 | s | string.cpp:128:16:128:16 | call to operator* | TAINT | +| string.cpp:132:28:132:33 | call to source | string.cpp:132:28:132:36 | call to basic_string | TAINT | +| string.cpp:132:28:132:36 | call to basic_string | string.cpp:133:22:133:28 | const_s | | +| string.cpp:133:22:133:22 | call to begin | string.cpp:133:22:133:22 | (__begin) | | +| string.cpp:133:22:133:22 | call to begin | string.cpp:133:22:133:22 | (__begin) | | +| string.cpp:133:22:133:22 | call to begin | string.cpp:133:22:133:22 | (__begin) | | +| string.cpp:133:22:133:22 | call to end | string.cpp:133:22:133:22 | (__end) | | +| string.cpp:133:22:133:22 | call to operator* | string.cpp:134:8:134:8 | c | | +| string.cpp:133:22:133:22 | ref arg (__begin) | string.cpp:133:22:133:22 | (__begin) | | +| string.cpp:133:22:133:22 | ref arg (__begin) | string.cpp:133:22:133:22 | (__begin) | | +| string.cpp:133:22:133:22 | ref arg (__begin) | string.cpp:133:22:133:22 | (__begin) | | +| string.cpp:133:22:133:28 | const_s | string.cpp:133:22:133:22 | (__range) | | +| string.cpp:133:22:133:28 | const_s | string.cpp:133:22:133:22 | (__range) | | +| string.cpp:133:22:133:28 | const_s | string.cpp:133:22:133:22 | call to operator* | TAINT | +| string.cpp:140:18:140:24 | hello | string.cpp:140:18:140:25 | call to basic_string | TAINT | +| string.cpp:140:18:140:25 | call to basic_string | string.cpp:143:8:143:9 | s1 | | +| string.cpp:140:18:140:25 | call to basic_string | string.cpp:143:13:143:14 | s1 | | +| string.cpp:140:18:140:25 | call to basic_string | string.cpp:144:8:144:9 | s1 | | +| string.cpp:140:18:140:25 | call to basic_string | string.cpp:145:13:145:14 | s1 | | +| string.cpp:140:18:140:25 | call to basic_string | string.cpp:148:8:148:9 | s1 | | +| string.cpp:140:18:140:25 | call to basic_string | string.cpp:149:8:149:9 | s1 | | +| string.cpp:141:18:141:23 | call to source | string.cpp:141:18:141:26 | call to basic_string | TAINT | +| string.cpp:141:18:141:26 | call to basic_string | string.cpp:144:13:144:14 | s2 | | +| string.cpp:141:18:141:26 | call to basic_string | string.cpp:145:8:145:9 | s2 | | +| string.cpp:141:18:141:26 | call to basic_string | string.cpp:146:8:146:9 | s2 | | +| string.cpp:141:18:141:26 | call to basic_string | string.cpp:146:13:146:14 | s2 | | +| string.cpp:143:8:143:9 | s1 | string.cpp:143:11:143:11 | call to operator+ | TAINT | +| string.cpp:143:13:143:14 | s1 | string.cpp:143:11:143:11 | call to operator+ | TAINT | +| string.cpp:144:8:144:9 | s1 | string.cpp:144:11:144:11 | call to operator+ | TAINT | +| string.cpp:144:13:144:14 | s2 | string.cpp:144:11:144:11 | call to operator+ | TAINT | +| string.cpp:145:8:145:9 | s2 | string.cpp:145:11:145:11 | call to operator+ | TAINT | +| string.cpp:145:13:145:14 | s1 | string.cpp:145:11:145:11 | call to operator+ | TAINT | +| string.cpp:146:8:146:9 | s2 | string.cpp:146:11:146:11 | call to operator+ | TAINT | +| string.cpp:146:13:146:14 | s2 | string.cpp:146:11:146:11 | call to operator+ | TAINT | +| string.cpp:148:8:148:9 | s1 | string.cpp:148:11:148:11 | call to operator+ | TAINT | +| string.cpp:148:13:148:20 | world | string.cpp:148:11:148:11 | call to operator+ | TAINT | +| string.cpp:149:8:149:9 | s1 | string.cpp:149:11:149:11 | call to operator+ | TAINT | +| string.cpp:149:13:149:18 | call to source | string.cpp:149:11:149:11 | call to operator+ | TAINT | +| string.cpp:153:18:153:22 | abc | string.cpp:153:18:153:23 | call to basic_string | TAINT | +| string.cpp:153:18:153:23 | call to basic_string | string.cpp:157:8:157:9 | s3 | | +| string.cpp:153:18:153:23 | call to basic_string | string.cpp:160:8:160:9 | s3 | | +| string.cpp:153:18:153:23 | call to basic_string | string.cpp:164:8:164:9 | s3 | | +| string.cpp:153:18:153:23 | call to basic_string | string.cpp:169:8:169:9 | s3 | | +| string.cpp:153:18:153:23 | call to basic_string | string.cpp:173:8:173:9 | s3 | | +| string.cpp:154:18:154:23 | call to source | string.cpp:154:18:154:26 | call to basic_string | TAINT | +| string.cpp:154:18:154:26 | call to basic_string | string.cpp:157:13:157:14 | s4 | | +| string.cpp:154:18:154:26 | call to basic_string | string.cpp:161:9:161:10 | s4 | | +| string.cpp:154:18:154:26 | call to basic_string | string.cpp:170:13:170:14 | s4 | | +| string.cpp:157:8:157:9 | s3 | string.cpp:157:11:157:11 | call to operator+ | TAINT | +| string.cpp:157:11:157:11 | call to operator+ | string.cpp:157:3:157:14 | ... = ... | | +| string.cpp:157:11:157:11 | call to operator+ | string.cpp:158:8:158:9 | s5 | | +| string.cpp:157:13:157:14 | s4 | string.cpp:157:11:157:11 | call to operator+ | TAINT | +| string.cpp:160:8:160:9 | s3 | string.cpp:160:3:160:9 | ... = ... | | +| string.cpp:160:8:160:9 | s3 | string.cpp:161:3:161:4 | s6 | | +| string.cpp:160:8:160:9 | s3 | string.cpp:162:8:162:9 | s6 | | +| string.cpp:161:3:161:4 | ref arg s6 | string.cpp:162:8:162:9 | s6 | | +| string.cpp:161:9:161:10 | s4 | string.cpp:161:3:161:4 | ref arg s6 | TAINT | +| string.cpp:161:9:161:10 | s4 | string.cpp:161:6:161:6 | call to operator+= | TAINT | +| string.cpp:164:8:164:9 | s3 | string.cpp:164:3:164:9 | ... = ... | | +| string.cpp:164:8:164:9 | s3 | string.cpp:165:3:165:4 | s7 | | +| string.cpp:164:8:164:9 | s3 | string.cpp:166:3:166:4 | s7 | | +| string.cpp:164:8:164:9 | s3 | string.cpp:167:8:167:9 | s7 | | +| string.cpp:165:3:165:4 | ref arg s7 | string.cpp:166:3:166:4 | s7 | | +| string.cpp:165:3:165:4 | ref arg s7 | string.cpp:167:8:167:9 | s7 | | +| string.cpp:165:9:165:14 | call to source | string.cpp:165:3:165:4 | ref arg s7 | TAINT | +| string.cpp:165:9:165:14 | call to source | string.cpp:165:6:165:6 | call to operator+= | TAINT | +| string.cpp:166:3:166:4 | ref arg s7 | string.cpp:167:8:167:9 | s7 | | +| string.cpp:166:9:166:11 | | string.cpp:166:3:166:4 | ref arg s7 | TAINT | +| string.cpp:166:9:166:11 | | string.cpp:166:6:166:6 | call to operator+= | TAINT | +| string.cpp:169:8:169:9 | s3 | string.cpp:169:3:169:9 | ... = ... | | +| string.cpp:169:8:169:9 | s3 | string.cpp:170:3:170:4 | s8 | | +| string.cpp:169:8:169:9 | s3 | string.cpp:171:8:171:9 | s8 | | +| string.cpp:170:3:170:4 | ref arg s8 | string.cpp:171:8:171:9 | s8 | | +| string.cpp:170:13:170:14 | s4 | string.cpp:170:3:170:4 | ref arg s8 | TAINT | +| string.cpp:170:13:170:14 | s4 | string.cpp:170:6:170:11 | call to append | TAINT | +| string.cpp:173:8:173:9 | s3 | string.cpp:173:3:173:9 | ... = ... | | +| string.cpp:173:8:173:9 | s3 | string.cpp:174:3:174:4 | s9 | | +| string.cpp:173:8:173:9 | s3 | string.cpp:175:3:175:4 | s9 | | +| string.cpp:173:8:173:9 | s3 | string.cpp:176:8:176:9 | s9 | | +| string.cpp:174:3:174:4 | ref arg s9 | string.cpp:175:3:175:4 | s9 | | +| string.cpp:174:3:174:4 | ref arg s9 | string.cpp:176:8:176:9 | s9 | | +| string.cpp:174:13:174:18 | call to source | string.cpp:174:3:174:4 | ref arg s9 | TAINT | +| string.cpp:174:13:174:18 | call to source | string.cpp:174:6:174:11 | call to append | TAINT | +| string.cpp:175:3:175:4 | ref arg s9 | string.cpp:176:8:176:9 | s9 | | +| string.cpp:175:13:175:15 | | string.cpp:175:3:175:4 | ref arg s9 | TAINT | +| string.cpp:175:13:175:15 | | string.cpp:175:6:175:11 | call to append | TAINT | +| string.cpp:180:19:180:23 | abc | string.cpp:180:19:180:24 | call to basic_string | TAINT | +| string.cpp:180:19:180:24 | call to basic_string | string.cpp:183:3:183:5 | s10 | | +| string.cpp:180:19:180:24 | call to basic_string | string.cpp:184:8:184:10 | s10 | | +| string.cpp:181:12:181:26 | call to source | string.cpp:183:17:183:17 | c | | +| string.cpp:183:3:183:5 | ref arg s10 | string.cpp:184:8:184:10 | s10 | | +| string.cpp:183:17:183:17 | c | string.cpp:183:3:183:5 | ref arg s10 | TAINT | +| string.cpp:183:17:183:17 | c | string.cpp:183:7:183:12 | call to append | TAINT | +| stringstream.cpp:13:20:13:22 | call to basic_stringstream | stringstream.cpp:16:2:16:4 | ss1 | | +| stringstream.cpp:13:20:13:22 | call to basic_stringstream | stringstream.cpp:22:7:22:9 | ss1 | | +| stringstream.cpp:13:20:13:22 | call to basic_stringstream | stringstream.cpp:27:7:27:9 | ss1 | | +| stringstream.cpp:13:25:13:27 | call to basic_stringstream | stringstream.cpp:17:2:17:4 | ss2 | | +| stringstream.cpp:13:25:13:27 | call to basic_stringstream | stringstream.cpp:23:7:23:9 | ss2 | | +| stringstream.cpp:13:25:13:27 | call to basic_stringstream | stringstream.cpp:28:7:28:9 | ss2 | | +| stringstream.cpp:13:30:13:32 | call to basic_stringstream | stringstream.cpp:18:2:18:4 | ss3 | | +| stringstream.cpp:13:30:13:32 | call to basic_stringstream | stringstream.cpp:24:7:24:9 | ss3 | | +| stringstream.cpp:13:30:13:32 | call to basic_stringstream | stringstream.cpp:29:7:29:9 | ss3 | | +| stringstream.cpp:13:35:13:37 | call to basic_stringstream | stringstream.cpp:19:2:19:4 | ss4 | | +| stringstream.cpp:13:35:13:37 | call to basic_stringstream | stringstream.cpp:25:7:25:9 | ss4 | | +| stringstream.cpp:13:35:13:37 | call to basic_stringstream | stringstream.cpp:30:7:30:9 | ss4 | | +| stringstream.cpp:13:40:13:42 | call to basic_stringstream | stringstream.cpp:20:2:20:4 | ss5 | | +| stringstream.cpp:13:40:13:42 | call to basic_stringstream | stringstream.cpp:26:7:26:9 | ss5 | | +| stringstream.cpp:13:40:13:42 | call to basic_stringstream | stringstream.cpp:31:7:31:9 | ss5 | | +| stringstream.cpp:14:16:14:21 | call to source | stringstream.cpp:14:16:14:24 | call to basic_string | TAINT | +| stringstream.cpp:14:16:14:24 | call to basic_string | stringstream.cpp:20:9:20:9 | t | | +| stringstream.cpp:16:2:16:4 | ref arg ss1 | stringstream.cpp:22:7:22:9 | ss1 | | +| stringstream.cpp:16:2:16:4 | ref arg ss1 | stringstream.cpp:27:7:27:9 | ss1 | | +| stringstream.cpp:17:2:17:4 | ref arg ss2 | stringstream.cpp:23:7:23:9 | ss2 | | +| stringstream.cpp:17:2:17:4 | ref arg ss2 | stringstream.cpp:28:7:28:9 | ss2 | | +| stringstream.cpp:18:2:18:4 | ref arg ss3 | stringstream.cpp:24:7:24:9 | ss3 | | +| stringstream.cpp:18:2:18:4 | ref arg ss3 | stringstream.cpp:29:7:29:9 | ss3 | | +| stringstream.cpp:19:2:19:4 | ref arg ss4 | stringstream.cpp:25:7:25:9 | ss4 | | +| stringstream.cpp:19:2:19:4 | ref arg ss4 | stringstream.cpp:30:7:30:9 | ss4 | | +| stringstream.cpp:20:2:20:4 | ref arg ss5 | stringstream.cpp:26:7:26:9 | ss5 | | +| stringstream.cpp:20:2:20:4 | ref arg ss5 | stringstream.cpp:31:7:31:9 | ss5 | | +| stringstream.cpp:34:32:34:37 | source | stringstream.cpp:39:9:39:14 | source | | +| stringstream.cpp:36:20:36:22 | call to basic_stringstream | stringstream.cpp:38:2:38:4 | ss1 | | +| stringstream.cpp:36:20:36:22 | call to basic_stringstream | stringstream.cpp:41:7:41:9 | ss1 | | +| stringstream.cpp:36:20:36:22 | call to basic_stringstream | stringstream.cpp:43:7:43:9 | ss1 | | +| stringstream.cpp:36:25:36:27 | call to basic_stringstream | stringstream.cpp:39:2:39:4 | ss2 | | +| stringstream.cpp:36:25:36:27 | call to basic_stringstream | stringstream.cpp:42:7:42:9 | ss2 | | +| stringstream.cpp:36:25:36:27 | call to basic_stringstream | stringstream.cpp:44:7:44:9 | ss2 | | +| stringstream.cpp:38:2:38:4 | ref arg ss1 | stringstream.cpp:41:7:41:9 | ss1 | | +| stringstream.cpp:38:2:38:4 | ref arg ss1 | stringstream.cpp:43:7:43:9 | ss1 | | +| stringstream.cpp:39:2:39:4 | ref arg ss2 | stringstream.cpp:42:7:42:9 | ss2 | | +| stringstream.cpp:39:2:39:4 | ref arg ss2 | stringstream.cpp:44:7:44:9 | ss2 | | | structlikeclass.cpp:5:7:5:7 | Unknown literal | structlikeclass.cpp:5:7:5:7 | constructor init of field v | TAINT | | structlikeclass.cpp:5:7:5:7 | Unknown literal | structlikeclass.cpp:5:7:5:7 | constructor init of field v | TAINT | | structlikeclass.cpp:5:7:5:7 | this | structlikeclass.cpp:5:7:5:7 | constructor init of field v [pre-this] | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp index 8770dc54be2..1b8f9c095ab 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp @@ -16,7 +16,6 @@ char *user_input() { void sink(const char *s) {}; void sink(const std::string &s) {}; -void sink(const std::stringstream &s) {}; void sink(const char *filename, const char *mode); void sink(char) {} @@ -33,42 +32,6 @@ void test_string() sink(c.c_str()); // tainted } -void test_stringstream() -{ - std::stringstream ss1, ss2, ss3, ss4, ss5; - std::string t(source()); - - ss1 << "1234"; - ss2 << source(); - ss3 << "123" << source(); - ss4 << source() << "456"; - ss5 << t; - - sink(ss1); - sink(ss2); // tainted [NOT DETECTED] - sink(ss3); // tainted [NOT DETECTED] - sink(ss4); // tainted [NOT DETECTED] - sink(ss5); // tainted [NOT DETECTED] - sink(ss1.str()); - sink(ss2.str()); // tainted [NOT DETECTED] - sink(ss3.str()); // tainted [NOT DETECTED] - sink(ss4.str()); // tainted [NOT DETECTED] - sink(ss5.str()); // tainted [NOT DETECTED] -} - -void test_stringstream_int(int source) -{ - std::stringstream ss1, ss2; - - ss1 << 1234; - ss2 << source; - - sink(ss1); - sink(ss2); // tainted [NOT DETECTED] - sink(ss1.str()); - sink(ss2.str()); // tainted [NOT DETECTED] -} - void test_strings2() { string path1 = user_input(); diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp new file mode 100644 index 00000000000..0656da01277 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp @@ -0,0 +1,45 @@ + +#include "stl.h" + +using namespace std; + +char *source(); + +void sink(const std::string &s) {}; +void sink(const std::stringstream &s) {}; + +void test_stringstream() +{ + std::stringstream ss1, ss2, ss3, ss4, ss5; + std::string t(source()); + + ss1 << "1234"; + ss2 << source(); + ss3 << "123" << source(); + ss4 << source() << "456"; + ss5 << t; + + sink(ss1); + sink(ss2); // tainted [NOT DETECTED] + sink(ss3); // tainted [NOT DETECTED] + sink(ss4); // tainted [NOT DETECTED] + sink(ss5); // tainted [NOT DETECTED] + sink(ss1.str()); + sink(ss2.str()); // tainted [NOT DETECTED] + sink(ss3.str()); // tainted [NOT DETECTED] + sink(ss4.str()); // tainted [NOT DETECTED] + sink(ss5.str()); // tainted [NOT DETECTED] +} + +void test_stringstream_int(int source) +{ + std::stringstream ss1, ss2; + + ss1 << 1234; + ss2 << source; + + sink(ss1); + sink(ss2); // tainted [NOT DETECTED] + sink(ss1.str()); + sink(ss2.str()); // tainted [NOT DETECTED] +} diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected index 7f475398c1d..62fd58a3790 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -32,34 +32,34 @@ | movableclass.cpp:55:8:55:9 | s2 | movableclass.cpp:52:23:52:28 | call to source | | movableclass.cpp:64:8:64:9 | s2 | movableclass.cpp:23:55:23:60 | call to source | | movableclass.cpp:65:11:65:11 | call to operator= | movableclass.cpp:65:13:65:18 | call to source | -| string.cpp:29:7:29:7 | a | string.cpp:25:12:25:17 | call to source | -| string.cpp:31:7:31:7 | c | string.cpp:27:16:27:21 | call to source | -| string.cpp:33:9:33:13 | call to c_str | string.cpp:27:16:27:21 | call to source | -| string.cpp:75:13:75:17 | call to c_str | string.cpp:14:10:14:15 | call to source | -| string.cpp:79:13:79:17 | call to c_str | string.cpp:14:10:14:15 | call to source | -| string.cpp:82:13:82:17 | call to c_str | string.cpp:14:10:14:15 | call to source | -| string.cpp:92:7:92:8 | cs | string.cpp:87:19:87:24 | call to source | -| string.cpp:93:7:93:8 | ss | string.cpp:87:19:87:24 | call to source | -| string.cpp:106:7:106:8 | cs | string.cpp:98:19:98:24 | call to source | -| string.cpp:107:7:107:8 | ss | string.cpp:98:19:98:24 | call to source | -| string.cpp:129:8:129:9 | s1 | string.cpp:124:18:124:23 | call to source | -| string.cpp:130:8:130:9 | s2 | string.cpp:125:20:125:25 | call to source | -| string.cpp:131:8:131:9 | s3 | string.cpp:127:8:127:13 | call to source | -| string.cpp:150:8:150:9 | s1 | string.cpp:146:32:146:37 | call to source | -| string.cpp:151:8:151:9 | s2 | string.cpp:148:20:148:25 | call to source | -| string.cpp:158:8:158:8 | c | string.cpp:156:16:156:21 | call to source | -| string.cpp:166:8:166:8 | c | string.cpp:156:16:156:21 | call to source | -| string.cpp:171:8:171:8 | c | string.cpp:169:28:169:33 | call to source | -| string.cpp:181:11:181:11 | call to operator+ | string.cpp:178:18:178:23 | call to source | -| string.cpp:182:11:182:11 | call to operator+ | string.cpp:178:18:178:23 | call to source | -| string.cpp:183:11:183:11 | call to operator+ | string.cpp:178:18:178:23 | call to source | -| string.cpp:186:11:186:11 | call to operator+ | string.cpp:186:13:186:18 | call to source | -| string.cpp:195:8:195:9 | s5 | string.cpp:191:18:191:23 | call to source | -| string.cpp:199:8:199:9 | s6 | string.cpp:191:18:191:23 | call to source | -| string.cpp:204:8:204:9 | s7 | string.cpp:202:9:202:14 | call to source | -| string.cpp:208:8:208:9 | s8 | string.cpp:191:18:191:23 | call to source | -| string.cpp:213:8:213:9 | s9 | string.cpp:211:13:211:18 | call to source | -| string.cpp:221:8:221:10 | s10 | string.cpp:218:12:218:26 | call to source | +| string.cpp:28:7:28:7 | a | string.cpp:24:12:24:17 | call to source | +| string.cpp:30:7:30:7 | c | string.cpp:26:16:26:21 | call to source | +| string.cpp:32:9:32:13 | call to c_str | string.cpp:26:16:26:21 | call to source | +| string.cpp:38:13:38:17 | call to c_str | string.cpp:14:10:14:15 | call to source | +| string.cpp:42:13:42:17 | call to c_str | string.cpp:14:10:14:15 | call to source | +| string.cpp:45:13:45:17 | call to c_str | string.cpp:14:10:14:15 | call to source | +| string.cpp:55:7:55:8 | cs | string.cpp:50:19:50:24 | call to source | +| string.cpp:56:7:56:8 | ss | string.cpp:50:19:50:24 | call to source | +| string.cpp:69:7:69:8 | cs | string.cpp:61:19:61:24 | call to source | +| string.cpp:70:7:70:8 | ss | string.cpp:61:19:61:24 | call to source | +| string.cpp:92:8:92:9 | s1 | string.cpp:87:18:87:23 | call to source | +| string.cpp:93:8:93:9 | s2 | string.cpp:88:20:88:25 | call to source | +| string.cpp:94:8:94:9 | s3 | string.cpp:90:8:90:13 | call to source | +| string.cpp:113:8:113:9 | s1 | string.cpp:109:32:109:37 | call to source | +| string.cpp:114:8:114:9 | s2 | string.cpp:111:20:111:25 | call to source | +| string.cpp:121:8:121:8 | c | string.cpp:119:16:119:21 | call to source | +| string.cpp:129:8:129:8 | c | string.cpp:119:16:119:21 | call to source | +| string.cpp:134:8:134:8 | c | string.cpp:132:28:132:33 | call to source | +| string.cpp:144:11:144:11 | call to operator+ | string.cpp:141:18:141:23 | call to source | +| string.cpp:145:11:145:11 | call to operator+ | string.cpp:141:18:141:23 | call to source | +| string.cpp:146:11:146:11 | call to operator+ | string.cpp:141:18:141:23 | call to source | +| string.cpp:149:11:149:11 | call to operator+ | string.cpp:149:13:149:18 | call to source | +| string.cpp:158:8:158:9 | s5 | string.cpp:154:18:154:23 | call to source | +| string.cpp:162:8:162:9 | s6 | string.cpp:154:18:154:23 | call to source | +| string.cpp:167:8:167:9 | s7 | string.cpp:165:9:165:14 | call to source | +| string.cpp:171:8:171:9 | s8 | string.cpp:154:18:154:23 | call to source | +| string.cpp:176:8:176:9 | s9 | string.cpp:174:13:174:18 | call to source | +| string.cpp:184:8:184:10 | s10 | string.cpp:181:12:181:26 | call to source | | structlikeclass.cpp:35:8:35:9 | s1 | structlikeclass.cpp:29:22:29:27 | call to source | | structlikeclass.cpp:36:8:36:9 | s2 | structlikeclass.cpp:30:24:30:29 | call to source | | structlikeclass.cpp:37:8:37:9 | s3 | structlikeclass.cpp:29:22:29:27 | call to source | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected index 894b19ea38a..ef4b311d954 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected @@ -30,33 +30,33 @@ | movableclass.cpp:55:8:55:9 | movableclass.cpp:52:23:52:28 | AST only | | movableclass.cpp:64:8:64:9 | movableclass.cpp:23:55:23:60 | AST only | | movableclass.cpp:65:11:65:11 | movableclass.cpp:65:13:65:18 | AST only | -| string.cpp:31:7:31:7 | string.cpp:27:16:27:21 | AST only | -| string.cpp:33:9:33:13 | string.cpp:27:16:27:21 | AST only | -| string.cpp:75:13:75:17 | string.cpp:14:10:14:15 | AST only | -| string.cpp:79:13:79:17 | string.cpp:14:10:14:15 | AST only | -| string.cpp:82:13:82:17 | string.cpp:14:10:14:15 | AST only | -| string.cpp:92:7:92:8 | string.cpp:87:19:87:26 | IR only | -| string.cpp:93:7:93:8 | string.cpp:87:19:87:24 | AST only | -| string.cpp:106:7:106:8 | string.cpp:98:19:98:24 | AST only | -| string.cpp:107:7:107:8 | string.cpp:98:19:98:24 | AST only | -| string.cpp:129:8:129:9 | string.cpp:124:18:124:23 | AST only | -| string.cpp:130:8:130:9 | string.cpp:125:20:125:25 | AST only | -| string.cpp:131:8:131:9 | string.cpp:127:8:127:13 | AST only | -| string.cpp:150:8:150:9 | string.cpp:146:32:146:37 | AST only | -| string.cpp:151:8:151:9 | string.cpp:148:20:148:25 | AST only | -| string.cpp:158:8:158:8 | string.cpp:156:16:156:21 | AST only | -| string.cpp:166:8:166:8 | string.cpp:156:16:156:21 | AST only | -| string.cpp:171:8:171:8 | string.cpp:169:28:169:33 | AST only | -| string.cpp:181:11:181:11 | string.cpp:178:18:178:23 | AST only | -| string.cpp:182:11:182:11 | string.cpp:178:18:178:23 | AST only | -| string.cpp:183:11:183:11 | string.cpp:178:18:178:23 | AST only | -| string.cpp:186:11:186:11 | string.cpp:186:13:186:18 | AST only | -| string.cpp:195:8:195:9 | string.cpp:191:18:191:23 | AST only | -| string.cpp:199:8:199:9 | string.cpp:191:18:191:23 | AST only | -| string.cpp:204:8:204:9 | string.cpp:202:9:202:14 | AST only | -| string.cpp:208:8:208:9 | string.cpp:191:18:191:23 | AST only | -| string.cpp:213:8:213:9 | string.cpp:211:13:211:18 | AST only | -| string.cpp:221:8:221:10 | string.cpp:218:12:218:26 | AST only | +| string.cpp:30:7:30:7 | string.cpp:26:16:26:21 | AST only | +| string.cpp:32:9:32:13 | string.cpp:26:16:26:21 | AST only | +| string.cpp:38:13:38:17 | string.cpp:14:10:14:15 | AST only | +| string.cpp:42:13:42:17 | string.cpp:14:10:14:15 | AST only | +| string.cpp:45:13:45:17 | string.cpp:14:10:14:15 | AST only | +| string.cpp:55:7:55:8 | string.cpp:50:19:50:26 | IR only | +| string.cpp:56:7:56:8 | string.cpp:50:19:50:24 | AST only | +| string.cpp:69:7:69:8 | string.cpp:61:19:61:24 | AST only | +| string.cpp:70:7:70:8 | string.cpp:61:19:61:24 | AST only | +| string.cpp:92:8:92:9 | string.cpp:87:18:87:23 | AST only | +| string.cpp:93:8:93:9 | string.cpp:88:20:88:25 | AST only | +| string.cpp:94:8:94:9 | string.cpp:90:8:90:13 | AST only | +| string.cpp:113:8:113:9 | string.cpp:109:32:109:37 | AST only | +| string.cpp:114:8:114:9 | string.cpp:111:20:111:25 | AST only | +| string.cpp:121:8:121:8 | string.cpp:119:16:119:21 | AST only | +| string.cpp:129:8:129:8 | string.cpp:119:16:119:21 | AST only | +| string.cpp:134:8:134:8 | string.cpp:132:28:132:33 | AST only | +| string.cpp:144:11:144:11 | string.cpp:141:18:141:23 | AST only | +| string.cpp:145:11:145:11 | string.cpp:141:18:141:23 | AST only | +| string.cpp:146:11:146:11 | string.cpp:141:18:141:23 | AST only | +| string.cpp:149:11:149:11 | string.cpp:149:13:149:18 | AST only | +| string.cpp:158:8:158:9 | string.cpp:154:18:154:23 | AST only | +| string.cpp:162:8:162:9 | string.cpp:154:18:154:23 | AST only | +| string.cpp:167:8:167:9 | string.cpp:165:9:165:14 | AST only | +| string.cpp:171:8:171:9 | string.cpp:154:18:154:23 | AST only | +| string.cpp:176:8:176:9 | string.cpp:174:13:174:18 | AST only | +| string.cpp:184:8:184:10 | string.cpp:181:12:181:26 | AST only | | structlikeclass.cpp:35:8:35:9 | structlikeclass.cpp:29:22:29:27 | AST only | | structlikeclass.cpp:36:8:36:9 | structlikeclass.cpp:30:24:30:29 | AST only | | structlikeclass.cpp:37:8:37:9 | structlikeclass.cpp:29:22:29:27 | AST only | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected index 8fbab29d8da..ac79007f6a7 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected @@ -1,10 +1,10 @@ | format.cpp:157:7:157:22 | (int)... | format.cpp:147:12:147:25 | call to source | | format.cpp:157:7:157:22 | access to array | format.cpp:147:12:147:25 | call to source | | format.cpp:158:7:158:27 | ... + ... | format.cpp:148:16:148:30 | call to source | -| string.cpp:29:7:29:7 | (const char *)... | string.cpp:25:12:25:17 | call to source | -| string.cpp:29:7:29:7 | a | string.cpp:25:12:25:17 | call to source | -| string.cpp:92:7:92:8 | cs | string.cpp:87:19:87:24 | call to source | -| string.cpp:92:7:92:8 | cs | string.cpp:87:19:87:26 | (const char *)... | +| string.cpp:28:7:28:7 | (const char *)... | string.cpp:24:12:24:17 | call to source | +| string.cpp:28:7:28:7 | a | string.cpp:24:12:24:17 | call to source | +| string.cpp:55:7:55:8 | cs | string.cpp:50:19:50:24 | call to source | +| string.cpp:55:7:55:8 | cs | string.cpp:50:19:50:26 | (const char *)... | | structlikeclass.cpp:38:8:38:9 | s4 | structlikeclass.cpp:33:8:33:13 | call to source | | structlikeclass.cpp:61:8:61:9 | s2 | structlikeclass.cpp:58:24:58:29 | call to source | | structlikeclass.cpp:62:8:62:20 | ... = ... | structlikeclass.cpp:62:13:62:18 | call to source | From a6bcbe79743426a2bb4cbbfa57b3b4f04a8f7ee1 Mon Sep 17 00:00:00 2001 From: Brian Gianforcaro Date: Thu, 13 Aug 2020 00:13:18 +0000 Subject: [PATCH 068/133] C++: Detect GoogleTest tests cases in FNumberOfTests.ql Co-authored-by: Jonas Jensen --- cpp/ql/src/Metrics/Files/FNumberOfTests.ql | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cpp/ql/src/Metrics/Files/FNumberOfTests.ql b/cpp/ql/src/Metrics/Files/FNumberOfTests.ql index a474b986203..421fc2baba1 100644 --- a/cpp/ql/src/Metrics/Files/FNumberOfTests.ql +++ b/cpp/ql/src/Metrics/Files/FNumberOfTests.ql @@ -18,6 +18,9 @@ Expr getTest() { or // boost tests; http://www.boost.org/ result.(FunctionCall).getTarget().hasQualifiedName("boost::unit_test", "make_test_case") + or + // googletest tests; https://github.com/google/googletest/ + result.(FunctionCall).getTarget().hasQualifiedName("testing::internal", "MakeAndRegisterTestInfo") } from File f, int n From 4947e1d817fbb80ce803b4795b3ef54ef1a7db3a Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Fri, 14 Aug 2020 09:25:32 +0200 Subject: [PATCH 069/133] Java: Temporarily move a qltest. --- .../{CWE-074 => CWE-074-JndiInjection}/JndiInjection.expected | 0 .../{CWE-074 => CWE-074-JndiInjection}/JndiInjection.java | 0 .../{CWE-074 => CWE-074-JndiInjection}/JndiInjection.qlref | 0 .../security/{CWE-074 => CWE-074-JndiInjection}/options | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename java/ql/test/experimental/query-tests/security/{CWE-074 => CWE-074-JndiInjection}/JndiInjection.expected (100%) rename java/ql/test/experimental/query-tests/security/{CWE-074 => CWE-074-JndiInjection}/JndiInjection.java (100%) rename java/ql/test/experimental/query-tests/security/{CWE-074 => CWE-074-JndiInjection}/JndiInjection.qlref (100%) rename java/ql/test/experimental/query-tests/security/{CWE-074 => CWE-074-JndiInjection}/options (100%) diff --git a/java/ql/test/experimental/query-tests/security/CWE-074/JndiInjection.expected b/java/ql/test/experimental/query-tests/security/CWE-074-JndiInjection/JndiInjection.expected similarity index 100% rename from java/ql/test/experimental/query-tests/security/CWE-074/JndiInjection.expected rename to java/ql/test/experimental/query-tests/security/CWE-074-JndiInjection/JndiInjection.expected diff --git a/java/ql/test/experimental/query-tests/security/CWE-074/JndiInjection.java b/java/ql/test/experimental/query-tests/security/CWE-074-JndiInjection/JndiInjection.java similarity index 100% rename from java/ql/test/experimental/query-tests/security/CWE-074/JndiInjection.java rename to java/ql/test/experimental/query-tests/security/CWE-074-JndiInjection/JndiInjection.java diff --git a/java/ql/test/experimental/query-tests/security/CWE-074/JndiInjection.qlref b/java/ql/test/experimental/query-tests/security/CWE-074-JndiInjection/JndiInjection.qlref similarity index 100% rename from java/ql/test/experimental/query-tests/security/CWE-074/JndiInjection.qlref rename to java/ql/test/experimental/query-tests/security/CWE-074-JndiInjection/JndiInjection.qlref diff --git a/java/ql/test/experimental/query-tests/security/CWE-074/options b/java/ql/test/experimental/query-tests/security/CWE-074-JndiInjection/options similarity index 100% rename from java/ql/test/experimental/query-tests/security/CWE-074/options rename to java/ql/test/experimental/query-tests/security/CWE-074-JndiInjection/options From 4b336e9b01f589b3d18db8d15cc40ec764795fd0 Mon Sep 17 00:00:00 2001 From: yoff Date: Fri, 14 Aug 2020 10:53:10 +0200 Subject: [PATCH 070/133] Update python/ql/test/experimental/dataflow/coverage/classes.py Co-authored-by: Taus --- python/ql/test/experimental/dataflow/coverage/classes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/test/experimental/dataflow/coverage/classes.py b/python/ql/test/experimental/dataflow/coverage/classes.py index 927fbc50abe..f6b39527443 100644 --- a/python/ql/test/experimental/dataflow/coverage/classes.py +++ b/python/ql/test/experimental/dataflow/coverage/classes.py @@ -1,5 +1,5 @@ # User-defined methods, both instance methods and class methods, can be called in many non-standard ways -# i.e. differently from simply `c.f()` or `C.f()`. For example, a user-defined `__await__` function on a +# i.e. differently from simply `c.f()` or `C.f()`. For example, a user-defined `__await__` method on a # class `C` will be called by the syntactic construct `await c` when `c` is an instance of `C`. # # These tests should cover all the class calls that we hope to support. From 8d49ad73252a133262499544a66581b16d2f548e Mon Sep 17 00:00:00 2001 From: yoff Date: Fri, 14 Aug 2020 10:53:37 +0200 Subject: [PATCH 071/133] Update python/ql/test/experimental/dataflow/coverage/datamodel.py Co-authored-by: Taus --- python/ql/test/experimental/dataflow/coverage/datamodel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/test/experimental/dataflow/coverage/datamodel.py b/python/ql/test/experimental/dataflow/coverage/datamodel.py index 82f10f4d53f..a3fc54d11a0 100644 --- a/python/ql/test/experimental/dataflow/coverage/datamodel.py +++ b/python/ql/test/experimental/dataflow/coverage/datamodel.py @@ -1,5 +1,5 @@ # User-defined methods, both instance methods and class methods, can be called in many non-standard ways -# i.e. differently from simply `c.f()` or `C.f()`. For example, a user-defined `__await__` function on a +# i.e. differently from simply `c.f()` or `C.f()`. For example, a user-defined `__await__` method on a # class `C` will be called by the syntactic construct `await c` when `c` is an instance of `C`. # # These tests are based on the first part of https://docs.python.org/3/reference/datamodel.html. From 2d29fa1d157456b9f41c1025d43c06c4c0e3d0ad Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Thu, 4 Jun 2020 11:13:23 +0200 Subject: [PATCH 072/133] Data flow: Use precise call contexts in `flowFwd()` --- .../csharp/dataflow/internal/DataFlowImpl.qll | 113 +++++++++++------- .../dataflow/internal/DataFlowImplCommon.qll | 16 ++- 2 files changed, 80 insertions(+), 49 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll index 5042dce683f..4e6eb9d86c0 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { * Holds if `node` can be the first node in a maximal subsequence of local * flow steps in a dataflow path. */ - private predicate localFlowEntry(Node node, Configuration config) { + predicate localFlowEntry(Node node, Configuration config) { nodeCand2(node, config) and ( config.isSource(node) or @@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption { * Holds if `node` is reachable with access path `ap` from a source in * the configuration `config`. * - * The Boolean `fromArg` records whether the node is reached through an + * The call context `cc` records whether the node is reached through an * argument in a call, and if so, `argAp` records the access path of that * argument. */ private predicate flowFwd( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwd0(node, fromArg, argAp, apf, ap, config) and + flowFwd0(node, cc, argAp, apf, ap, config) and flowCand(node, _, _, apf, config) } private predicate flowFwd0( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { flowCand(node, _, _, _, config) and config.isSource(node) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() or flowCand(node, _, _, _, unbind(config)) and ( - exists(Node mid | - flowFwd(mid, fromArg, argAp, apf, ap, config) and - localFlowBigStep(mid, node, true, _, config, _) + exists(Node mid, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and + localFlowBigStep(mid, node, true, _, config, localCC) ) or - exists(Node mid, AccessPathNil nil | - flowFwd(mid, fromArg, argAp, _, nil, config) and - localFlowBigStep(mid, node, false, apf, config, _) and + exists(Node mid, AccessPathNil nil, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and + localFlowBigStep(mid, node, false, apf, config, localCC) and apf = ap.(AccessPathNil).getFront() ) or exists(Node mid | flowFwd(mid, _, _, apf, ap, config) and jumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() ) or exists(Node mid, AccessPathNil nil | flowFwd(mid, _, _, _, nil, config) and additionalJumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() @@ -1704,40 +1704,51 @@ private predicate flowFwd0( ) or // store - exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) + exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config)) or // read exists(TypedContent tc | - flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and + flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and flowFwdConsCand(tc, apf, ap, config) ) or // flow into a callable - flowFwdIn(_, node, _, _, apf, ap, config) and - fromArg = true and + flowFwdIn(_, node, cc, _, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and - fromArg = false + exists(CallContextNoCall innercc, DataFlowCallable c | + flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() + ) or exists(AccessPath argAp0 | flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and - flowFwdIsEntered(call, fromArg, argAp, argAp0, config) + flowFwdIsEntered(call, cc, argAp, argAp0, config) ) ) } +pragma[nomagic] +private predicate flowFwdLocalEntry( + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + LocalCallContext localCC, Configuration config +) { + flowFwd(node, cc, argAp, apf, ap, config) and + localFlowEntry(node, config) and + localCC = getLocalCallContext(cc, node.getEnclosingCallable()) +} + pragma[nomagic] private predicate flowFwdStore( - Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, AccessPathFront apf0 | - flowFwd(mid, fromArg, argAp, apf0, ap0, config) and + flowFwd(mid, cc, argAp, apf0, ap0, config) and flowFwdStore0(mid, tc, node, apf0, apf, config) ) } @@ -1764,20 +1775,20 @@ private predicate flowFwdStore0( pragma[nomagic] private predicate flowFwdRead0( - Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, - boolean fromArg, AccessPathOption argAp, Configuration config + Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc, + AccessPathOption argAp, Configuration config ) { - flowFwd(node1, fromArg, argAp, apf0, ap0, config) and + flowFwd(node1, cc, argAp, apf0, ap0, config) and readCandFwd(node1, tc, apf0, node2, config) } pragma[nomagic] private predicate flowFwdRead( - Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, TypedContent tc | - flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and + flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and flowCand(node, _, _, apf, unbind(config)) and flowCandConsCand(tc, apf, unbind(config)) ) @@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - exists(ArgumentNode arg, boolean allowsFieldFlow | - flowFwd(arg, fromArg, argAp, apf, ap, config) and + exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | + flowFwd(arg, outercc, argAp, apf, ap, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and - flowCand(p, _, _, _, unbind(config)) + c = p.getEnclosingCallable() and + c = resolveCall(call, outercc) and + flowCand(p, _, _, _, unbind(config)) and + if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall() | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1809,13 +1823,19 @@ private predicate flowFwdIn( pragma[nomagic] private predicate flowFwdOut( - DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ReturnNodeExt ret, boolean allowsFieldFlow | - flowFwd(ret, fromArg, argAp, apf, ap, config) and + flowFwd(ret, innercc, argAp, apf, ap, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and - flowCand(node, _, _, _, unbind(config)) + innerc = ret.getEnclosingCallable() and + flowCand(node, _, _, _, unbind(config)) and + ( + resolveReturn(innercc, innerc, call) + or + innercc.(CallContextCall).matchesCall(call) + ) | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg( DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) + flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config) } /** @@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg( */ pragma[nomagic] private predicate flowFwdIsEntered( - DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config + DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and + flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } @@ -1920,7 +1940,7 @@ private predicate flow0( // flow out of a callable flowOut(_, node, _, _, ap, config) and toReturn = true and - if flowFwd(node, true, TAccessPathSome(_), _, ap, config) + if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config) then returnAp = TAccessPathSome(ap) else returnAp = TAccessPathNone() } @@ -2006,9 +2026,10 @@ private predicate flowIsReturned( DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, Configuration config ) { - exists(ReturnNodeExt ret | + exists(ReturnNodeExt ret, CallContextCall ccc | flowOut(call, ret, toReturn, returnAp, ap, config) and - flowFwd(ret, true, TAccessPathSome(_), _, ap, config) + flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and + ccc.matchesCall(call) ) } @@ -2031,7 +2052,7 @@ private newtype TSummaryCtx = exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | parameterFlow(p, ap, ret.getEnclosingCallable(), config) and flow(ret, true, TAccessPathSome(_), ap0, config) and - flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) + flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config) ) } @@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0( ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } @@ -2867,7 +2888,7 @@ private module FlowExploration { ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll index 27ab1d01feb..892250f44bb 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll @@ -512,13 +512,19 @@ abstract class CallContext extends TCallContext { abstract predicate relevantFor(DataFlowCallable callable); } -class CallContextAny extends CallContext, TAnyCallContext { +abstract class CallContextNoCall extends CallContext { } + +class CallContextAny extends CallContextNoCall, TAnyCallContext { override string toString() { result = "CcAny" } override predicate relevantFor(DataFlowCallable callable) { any() } } -abstract class CallContextCall extends CallContext { } +abstract class CallContextCall extends CallContext { + /** Holds if this call context may be `call`. */ + bindingset[call] + abstract predicate matchesCall(DataFlowCall call); +} class CallContextSpecificCall extends CallContextCall, TSpecificCall { override string toString() { @@ -529,6 +535,8 @@ class CallContextSpecificCall extends CallContextCall, TSpecificCall { recordDataFlowCallSite(getCall(), callable) } + override predicate matchesCall(DataFlowCall call) { call = this.getCall() } + DataFlowCall getCall() { this = TSpecificCall(result) } } @@ -538,9 +546,11 @@ class CallContextSomeCall extends CallContextCall, TSomeCall { override predicate relevantFor(DataFlowCallable callable) { exists(ParameterNode p | p.getEnclosingCallable() = callable) } + + override predicate matchesCall(DataFlowCall call) { any() } } -class CallContextReturn extends CallContext, TReturn { +class CallContextReturn extends CallContextNoCall, TReturn { override string toString() { exists(DataFlowCall call | this = TReturn(_, call) | result = "CcReturn(" + call + ")") } From 9ebf8d1d580f8f5b68a62a256ae1d8b74aa9b79c Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 29 Jun 2020 20:02:37 +0200 Subject: [PATCH 073/133] Data flow: Sync files --- .../cpp/dataflow/internal/DataFlowImpl.qll | 113 +++++++++++------- .../cpp/dataflow/internal/DataFlowImpl2.qll | 113 +++++++++++------- .../cpp/dataflow/internal/DataFlowImpl3.qll | 113 +++++++++++------- .../cpp/dataflow/internal/DataFlowImpl4.qll | 113 +++++++++++------- .../dataflow/internal/DataFlowImplCommon.qll | 16 ++- .../dataflow/internal/DataFlowImplLocal.qll | 113 +++++++++++------- .../cpp/ir/dataflow/internal/DataFlowImpl.qll | 113 +++++++++++------- .../ir/dataflow/internal/DataFlowImpl2.qll | 113 +++++++++++------- .../ir/dataflow/internal/DataFlowImpl3.qll | 113 +++++++++++------- .../ir/dataflow/internal/DataFlowImpl4.qll | 113 +++++++++++------- .../dataflow/internal/DataFlowImplCommon.qll | 16 ++- .../dataflow/internal/DataFlowImpl2.qll | 113 +++++++++++------- .../dataflow/internal/DataFlowImpl3.qll | 113 +++++++++++------- .../dataflow/internal/DataFlowImpl4.qll | 113 +++++++++++------- .../dataflow/internal/DataFlowImpl5.qll | 113 +++++++++++------- .../java/dataflow/internal/DataFlowImpl.qll | 113 +++++++++++------- .../java/dataflow/internal/DataFlowImpl2.qll | 113 +++++++++++------- .../java/dataflow/internal/DataFlowImpl3.qll | 113 +++++++++++------- .../java/dataflow/internal/DataFlowImpl4.qll | 113 +++++++++++------- .../java/dataflow/internal/DataFlowImpl5.qll | 113 +++++++++++------- .../dataflow/internal/DataFlowImplCommon.qll | 16 ++- 21 files changed, 1245 insertions(+), 837 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll index 5042dce683f..4e6eb9d86c0 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { * Holds if `node` can be the first node in a maximal subsequence of local * flow steps in a dataflow path. */ - private predicate localFlowEntry(Node node, Configuration config) { + predicate localFlowEntry(Node node, Configuration config) { nodeCand2(node, config) and ( config.isSource(node) or @@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption { * Holds if `node` is reachable with access path `ap` from a source in * the configuration `config`. * - * The Boolean `fromArg` records whether the node is reached through an + * The call context `cc` records whether the node is reached through an * argument in a call, and if so, `argAp` records the access path of that * argument. */ private predicate flowFwd( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwd0(node, fromArg, argAp, apf, ap, config) and + flowFwd0(node, cc, argAp, apf, ap, config) and flowCand(node, _, _, apf, config) } private predicate flowFwd0( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { flowCand(node, _, _, _, config) and config.isSource(node) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() or flowCand(node, _, _, _, unbind(config)) and ( - exists(Node mid | - flowFwd(mid, fromArg, argAp, apf, ap, config) and - localFlowBigStep(mid, node, true, _, config, _) + exists(Node mid, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and + localFlowBigStep(mid, node, true, _, config, localCC) ) or - exists(Node mid, AccessPathNil nil | - flowFwd(mid, fromArg, argAp, _, nil, config) and - localFlowBigStep(mid, node, false, apf, config, _) and + exists(Node mid, AccessPathNil nil, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and + localFlowBigStep(mid, node, false, apf, config, localCC) and apf = ap.(AccessPathNil).getFront() ) or exists(Node mid | flowFwd(mid, _, _, apf, ap, config) and jumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() ) or exists(Node mid, AccessPathNil nil | flowFwd(mid, _, _, _, nil, config) and additionalJumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() @@ -1704,40 +1704,51 @@ private predicate flowFwd0( ) or // store - exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) + exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config)) or // read exists(TypedContent tc | - flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and + flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and flowFwdConsCand(tc, apf, ap, config) ) or // flow into a callable - flowFwdIn(_, node, _, _, apf, ap, config) and - fromArg = true and + flowFwdIn(_, node, cc, _, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and - fromArg = false + exists(CallContextNoCall innercc, DataFlowCallable c | + flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() + ) or exists(AccessPath argAp0 | flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and - flowFwdIsEntered(call, fromArg, argAp, argAp0, config) + flowFwdIsEntered(call, cc, argAp, argAp0, config) ) ) } +pragma[nomagic] +private predicate flowFwdLocalEntry( + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + LocalCallContext localCC, Configuration config +) { + flowFwd(node, cc, argAp, apf, ap, config) and + localFlowEntry(node, config) and + localCC = getLocalCallContext(cc, node.getEnclosingCallable()) +} + pragma[nomagic] private predicate flowFwdStore( - Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, AccessPathFront apf0 | - flowFwd(mid, fromArg, argAp, apf0, ap0, config) and + flowFwd(mid, cc, argAp, apf0, ap0, config) and flowFwdStore0(mid, tc, node, apf0, apf, config) ) } @@ -1764,20 +1775,20 @@ private predicate flowFwdStore0( pragma[nomagic] private predicate flowFwdRead0( - Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, - boolean fromArg, AccessPathOption argAp, Configuration config + Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc, + AccessPathOption argAp, Configuration config ) { - flowFwd(node1, fromArg, argAp, apf0, ap0, config) and + flowFwd(node1, cc, argAp, apf0, ap0, config) and readCandFwd(node1, tc, apf0, node2, config) } pragma[nomagic] private predicate flowFwdRead( - Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, TypedContent tc | - flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and + flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and flowCand(node, _, _, apf, unbind(config)) and flowCandConsCand(tc, apf, unbind(config)) ) @@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - exists(ArgumentNode arg, boolean allowsFieldFlow | - flowFwd(arg, fromArg, argAp, apf, ap, config) and + exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | + flowFwd(arg, outercc, argAp, apf, ap, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and - flowCand(p, _, _, _, unbind(config)) + c = p.getEnclosingCallable() and + c = resolveCall(call, outercc) and + flowCand(p, _, _, _, unbind(config)) and + if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall() | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1809,13 +1823,19 @@ private predicate flowFwdIn( pragma[nomagic] private predicate flowFwdOut( - DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ReturnNodeExt ret, boolean allowsFieldFlow | - flowFwd(ret, fromArg, argAp, apf, ap, config) and + flowFwd(ret, innercc, argAp, apf, ap, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and - flowCand(node, _, _, _, unbind(config)) + innerc = ret.getEnclosingCallable() and + flowCand(node, _, _, _, unbind(config)) and + ( + resolveReturn(innercc, innerc, call) + or + innercc.(CallContextCall).matchesCall(call) + ) | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg( DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) + flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config) } /** @@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg( */ pragma[nomagic] private predicate flowFwdIsEntered( - DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config + DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and + flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } @@ -1920,7 +1940,7 @@ private predicate flow0( // flow out of a callable flowOut(_, node, _, _, ap, config) and toReturn = true and - if flowFwd(node, true, TAccessPathSome(_), _, ap, config) + if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config) then returnAp = TAccessPathSome(ap) else returnAp = TAccessPathNone() } @@ -2006,9 +2026,10 @@ private predicate flowIsReturned( DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, Configuration config ) { - exists(ReturnNodeExt ret | + exists(ReturnNodeExt ret, CallContextCall ccc | flowOut(call, ret, toReturn, returnAp, ap, config) and - flowFwd(ret, true, TAccessPathSome(_), _, ap, config) + flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and + ccc.matchesCall(call) ) } @@ -2031,7 +2052,7 @@ private newtype TSummaryCtx = exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | parameterFlow(p, ap, ret.getEnclosingCallable(), config) and flow(ret, true, TAccessPathSome(_), ap0, config) and - flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) + flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config) ) } @@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0( ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } @@ -2867,7 +2888,7 @@ private module FlowExploration { ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll index 5042dce683f..4e6eb9d86c0 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { * Holds if `node` can be the first node in a maximal subsequence of local * flow steps in a dataflow path. */ - private predicate localFlowEntry(Node node, Configuration config) { + predicate localFlowEntry(Node node, Configuration config) { nodeCand2(node, config) and ( config.isSource(node) or @@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption { * Holds if `node` is reachable with access path `ap` from a source in * the configuration `config`. * - * The Boolean `fromArg` records whether the node is reached through an + * The call context `cc` records whether the node is reached through an * argument in a call, and if so, `argAp` records the access path of that * argument. */ private predicate flowFwd( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwd0(node, fromArg, argAp, apf, ap, config) and + flowFwd0(node, cc, argAp, apf, ap, config) and flowCand(node, _, _, apf, config) } private predicate flowFwd0( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { flowCand(node, _, _, _, config) and config.isSource(node) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() or flowCand(node, _, _, _, unbind(config)) and ( - exists(Node mid | - flowFwd(mid, fromArg, argAp, apf, ap, config) and - localFlowBigStep(mid, node, true, _, config, _) + exists(Node mid, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and + localFlowBigStep(mid, node, true, _, config, localCC) ) or - exists(Node mid, AccessPathNil nil | - flowFwd(mid, fromArg, argAp, _, nil, config) and - localFlowBigStep(mid, node, false, apf, config, _) and + exists(Node mid, AccessPathNil nil, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and + localFlowBigStep(mid, node, false, apf, config, localCC) and apf = ap.(AccessPathNil).getFront() ) or exists(Node mid | flowFwd(mid, _, _, apf, ap, config) and jumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() ) or exists(Node mid, AccessPathNil nil | flowFwd(mid, _, _, _, nil, config) and additionalJumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() @@ -1704,40 +1704,51 @@ private predicate flowFwd0( ) or // store - exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) + exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config)) or // read exists(TypedContent tc | - flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and + flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and flowFwdConsCand(tc, apf, ap, config) ) or // flow into a callable - flowFwdIn(_, node, _, _, apf, ap, config) and - fromArg = true and + flowFwdIn(_, node, cc, _, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and - fromArg = false + exists(CallContextNoCall innercc, DataFlowCallable c | + flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() + ) or exists(AccessPath argAp0 | flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and - flowFwdIsEntered(call, fromArg, argAp, argAp0, config) + flowFwdIsEntered(call, cc, argAp, argAp0, config) ) ) } +pragma[nomagic] +private predicate flowFwdLocalEntry( + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + LocalCallContext localCC, Configuration config +) { + flowFwd(node, cc, argAp, apf, ap, config) and + localFlowEntry(node, config) and + localCC = getLocalCallContext(cc, node.getEnclosingCallable()) +} + pragma[nomagic] private predicate flowFwdStore( - Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, AccessPathFront apf0 | - flowFwd(mid, fromArg, argAp, apf0, ap0, config) and + flowFwd(mid, cc, argAp, apf0, ap0, config) and flowFwdStore0(mid, tc, node, apf0, apf, config) ) } @@ -1764,20 +1775,20 @@ private predicate flowFwdStore0( pragma[nomagic] private predicate flowFwdRead0( - Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, - boolean fromArg, AccessPathOption argAp, Configuration config + Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc, + AccessPathOption argAp, Configuration config ) { - flowFwd(node1, fromArg, argAp, apf0, ap0, config) and + flowFwd(node1, cc, argAp, apf0, ap0, config) and readCandFwd(node1, tc, apf0, node2, config) } pragma[nomagic] private predicate flowFwdRead( - Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, TypedContent tc | - flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and + flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and flowCand(node, _, _, apf, unbind(config)) and flowCandConsCand(tc, apf, unbind(config)) ) @@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - exists(ArgumentNode arg, boolean allowsFieldFlow | - flowFwd(arg, fromArg, argAp, apf, ap, config) and + exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | + flowFwd(arg, outercc, argAp, apf, ap, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and - flowCand(p, _, _, _, unbind(config)) + c = p.getEnclosingCallable() and + c = resolveCall(call, outercc) and + flowCand(p, _, _, _, unbind(config)) and + if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall() | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1809,13 +1823,19 @@ private predicate flowFwdIn( pragma[nomagic] private predicate flowFwdOut( - DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ReturnNodeExt ret, boolean allowsFieldFlow | - flowFwd(ret, fromArg, argAp, apf, ap, config) and + flowFwd(ret, innercc, argAp, apf, ap, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and - flowCand(node, _, _, _, unbind(config)) + innerc = ret.getEnclosingCallable() and + flowCand(node, _, _, _, unbind(config)) and + ( + resolveReturn(innercc, innerc, call) + or + innercc.(CallContextCall).matchesCall(call) + ) | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg( DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) + flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config) } /** @@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg( */ pragma[nomagic] private predicate flowFwdIsEntered( - DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config + DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and + flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } @@ -1920,7 +1940,7 @@ private predicate flow0( // flow out of a callable flowOut(_, node, _, _, ap, config) and toReturn = true and - if flowFwd(node, true, TAccessPathSome(_), _, ap, config) + if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config) then returnAp = TAccessPathSome(ap) else returnAp = TAccessPathNone() } @@ -2006,9 +2026,10 @@ private predicate flowIsReturned( DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, Configuration config ) { - exists(ReturnNodeExt ret | + exists(ReturnNodeExt ret, CallContextCall ccc | flowOut(call, ret, toReturn, returnAp, ap, config) and - flowFwd(ret, true, TAccessPathSome(_), _, ap, config) + flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and + ccc.matchesCall(call) ) } @@ -2031,7 +2052,7 @@ private newtype TSummaryCtx = exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | parameterFlow(p, ap, ret.getEnclosingCallable(), config) and flow(ret, true, TAccessPathSome(_), ap0, config) and - flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) + flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config) ) } @@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0( ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } @@ -2867,7 +2888,7 @@ private module FlowExploration { ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll index 5042dce683f..4e6eb9d86c0 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { * Holds if `node` can be the first node in a maximal subsequence of local * flow steps in a dataflow path. */ - private predicate localFlowEntry(Node node, Configuration config) { + predicate localFlowEntry(Node node, Configuration config) { nodeCand2(node, config) and ( config.isSource(node) or @@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption { * Holds if `node` is reachable with access path `ap` from a source in * the configuration `config`. * - * The Boolean `fromArg` records whether the node is reached through an + * The call context `cc` records whether the node is reached through an * argument in a call, and if so, `argAp` records the access path of that * argument. */ private predicate flowFwd( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwd0(node, fromArg, argAp, apf, ap, config) and + flowFwd0(node, cc, argAp, apf, ap, config) and flowCand(node, _, _, apf, config) } private predicate flowFwd0( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { flowCand(node, _, _, _, config) and config.isSource(node) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() or flowCand(node, _, _, _, unbind(config)) and ( - exists(Node mid | - flowFwd(mid, fromArg, argAp, apf, ap, config) and - localFlowBigStep(mid, node, true, _, config, _) + exists(Node mid, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and + localFlowBigStep(mid, node, true, _, config, localCC) ) or - exists(Node mid, AccessPathNil nil | - flowFwd(mid, fromArg, argAp, _, nil, config) and - localFlowBigStep(mid, node, false, apf, config, _) and + exists(Node mid, AccessPathNil nil, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and + localFlowBigStep(mid, node, false, apf, config, localCC) and apf = ap.(AccessPathNil).getFront() ) or exists(Node mid | flowFwd(mid, _, _, apf, ap, config) and jumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() ) or exists(Node mid, AccessPathNil nil | flowFwd(mid, _, _, _, nil, config) and additionalJumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() @@ -1704,40 +1704,51 @@ private predicate flowFwd0( ) or // store - exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) + exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config)) or // read exists(TypedContent tc | - flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and + flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and flowFwdConsCand(tc, apf, ap, config) ) or // flow into a callable - flowFwdIn(_, node, _, _, apf, ap, config) and - fromArg = true and + flowFwdIn(_, node, cc, _, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and - fromArg = false + exists(CallContextNoCall innercc, DataFlowCallable c | + flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() + ) or exists(AccessPath argAp0 | flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and - flowFwdIsEntered(call, fromArg, argAp, argAp0, config) + flowFwdIsEntered(call, cc, argAp, argAp0, config) ) ) } +pragma[nomagic] +private predicate flowFwdLocalEntry( + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + LocalCallContext localCC, Configuration config +) { + flowFwd(node, cc, argAp, apf, ap, config) and + localFlowEntry(node, config) and + localCC = getLocalCallContext(cc, node.getEnclosingCallable()) +} + pragma[nomagic] private predicate flowFwdStore( - Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, AccessPathFront apf0 | - flowFwd(mid, fromArg, argAp, apf0, ap0, config) and + flowFwd(mid, cc, argAp, apf0, ap0, config) and flowFwdStore0(mid, tc, node, apf0, apf, config) ) } @@ -1764,20 +1775,20 @@ private predicate flowFwdStore0( pragma[nomagic] private predicate flowFwdRead0( - Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, - boolean fromArg, AccessPathOption argAp, Configuration config + Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc, + AccessPathOption argAp, Configuration config ) { - flowFwd(node1, fromArg, argAp, apf0, ap0, config) and + flowFwd(node1, cc, argAp, apf0, ap0, config) and readCandFwd(node1, tc, apf0, node2, config) } pragma[nomagic] private predicate flowFwdRead( - Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, TypedContent tc | - flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and + flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and flowCand(node, _, _, apf, unbind(config)) and flowCandConsCand(tc, apf, unbind(config)) ) @@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - exists(ArgumentNode arg, boolean allowsFieldFlow | - flowFwd(arg, fromArg, argAp, apf, ap, config) and + exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | + flowFwd(arg, outercc, argAp, apf, ap, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and - flowCand(p, _, _, _, unbind(config)) + c = p.getEnclosingCallable() and + c = resolveCall(call, outercc) and + flowCand(p, _, _, _, unbind(config)) and + if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall() | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1809,13 +1823,19 @@ private predicate flowFwdIn( pragma[nomagic] private predicate flowFwdOut( - DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ReturnNodeExt ret, boolean allowsFieldFlow | - flowFwd(ret, fromArg, argAp, apf, ap, config) and + flowFwd(ret, innercc, argAp, apf, ap, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and - flowCand(node, _, _, _, unbind(config)) + innerc = ret.getEnclosingCallable() and + flowCand(node, _, _, _, unbind(config)) and + ( + resolveReturn(innercc, innerc, call) + or + innercc.(CallContextCall).matchesCall(call) + ) | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg( DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) + flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config) } /** @@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg( */ pragma[nomagic] private predicate flowFwdIsEntered( - DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config + DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and + flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } @@ -1920,7 +1940,7 @@ private predicate flow0( // flow out of a callable flowOut(_, node, _, _, ap, config) and toReturn = true and - if flowFwd(node, true, TAccessPathSome(_), _, ap, config) + if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config) then returnAp = TAccessPathSome(ap) else returnAp = TAccessPathNone() } @@ -2006,9 +2026,10 @@ private predicate flowIsReturned( DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, Configuration config ) { - exists(ReturnNodeExt ret | + exists(ReturnNodeExt ret, CallContextCall ccc | flowOut(call, ret, toReturn, returnAp, ap, config) and - flowFwd(ret, true, TAccessPathSome(_), _, ap, config) + flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and + ccc.matchesCall(call) ) } @@ -2031,7 +2052,7 @@ private newtype TSummaryCtx = exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | parameterFlow(p, ap, ret.getEnclosingCallable(), config) and flow(ret, true, TAccessPathSome(_), ap0, config) and - flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) + flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config) ) } @@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0( ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } @@ -2867,7 +2888,7 @@ private module FlowExploration { ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll index 5042dce683f..4e6eb9d86c0 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { * Holds if `node` can be the first node in a maximal subsequence of local * flow steps in a dataflow path. */ - private predicate localFlowEntry(Node node, Configuration config) { + predicate localFlowEntry(Node node, Configuration config) { nodeCand2(node, config) and ( config.isSource(node) or @@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption { * Holds if `node` is reachable with access path `ap` from a source in * the configuration `config`. * - * The Boolean `fromArg` records whether the node is reached through an + * The call context `cc` records whether the node is reached through an * argument in a call, and if so, `argAp` records the access path of that * argument. */ private predicate flowFwd( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwd0(node, fromArg, argAp, apf, ap, config) and + flowFwd0(node, cc, argAp, apf, ap, config) and flowCand(node, _, _, apf, config) } private predicate flowFwd0( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { flowCand(node, _, _, _, config) and config.isSource(node) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() or flowCand(node, _, _, _, unbind(config)) and ( - exists(Node mid | - flowFwd(mid, fromArg, argAp, apf, ap, config) and - localFlowBigStep(mid, node, true, _, config, _) + exists(Node mid, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and + localFlowBigStep(mid, node, true, _, config, localCC) ) or - exists(Node mid, AccessPathNil nil | - flowFwd(mid, fromArg, argAp, _, nil, config) and - localFlowBigStep(mid, node, false, apf, config, _) and + exists(Node mid, AccessPathNil nil, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and + localFlowBigStep(mid, node, false, apf, config, localCC) and apf = ap.(AccessPathNil).getFront() ) or exists(Node mid | flowFwd(mid, _, _, apf, ap, config) and jumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() ) or exists(Node mid, AccessPathNil nil | flowFwd(mid, _, _, _, nil, config) and additionalJumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() @@ -1704,40 +1704,51 @@ private predicate flowFwd0( ) or // store - exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) + exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config)) or // read exists(TypedContent tc | - flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and + flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and flowFwdConsCand(tc, apf, ap, config) ) or // flow into a callable - flowFwdIn(_, node, _, _, apf, ap, config) and - fromArg = true and + flowFwdIn(_, node, cc, _, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and - fromArg = false + exists(CallContextNoCall innercc, DataFlowCallable c | + flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() + ) or exists(AccessPath argAp0 | flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and - flowFwdIsEntered(call, fromArg, argAp, argAp0, config) + flowFwdIsEntered(call, cc, argAp, argAp0, config) ) ) } +pragma[nomagic] +private predicate flowFwdLocalEntry( + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + LocalCallContext localCC, Configuration config +) { + flowFwd(node, cc, argAp, apf, ap, config) and + localFlowEntry(node, config) and + localCC = getLocalCallContext(cc, node.getEnclosingCallable()) +} + pragma[nomagic] private predicate flowFwdStore( - Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, AccessPathFront apf0 | - flowFwd(mid, fromArg, argAp, apf0, ap0, config) and + flowFwd(mid, cc, argAp, apf0, ap0, config) and flowFwdStore0(mid, tc, node, apf0, apf, config) ) } @@ -1764,20 +1775,20 @@ private predicate flowFwdStore0( pragma[nomagic] private predicate flowFwdRead0( - Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, - boolean fromArg, AccessPathOption argAp, Configuration config + Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc, + AccessPathOption argAp, Configuration config ) { - flowFwd(node1, fromArg, argAp, apf0, ap0, config) and + flowFwd(node1, cc, argAp, apf0, ap0, config) and readCandFwd(node1, tc, apf0, node2, config) } pragma[nomagic] private predicate flowFwdRead( - Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, TypedContent tc | - flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and + flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and flowCand(node, _, _, apf, unbind(config)) and flowCandConsCand(tc, apf, unbind(config)) ) @@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - exists(ArgumentNode arg, boolean allowsFieldFlow | - flowFwd(arg, fromArg, argAp, apf, ap, config) and + exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | + flowFwd(arg, outercc, argAp, apf, ap, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and - flowCand(p, _, _, _, unbind(config)) + c = p.getEnclosingCallable() and + c = resolveCall(call, outercc) and + flowCand(p, _, _, _, unbind(config)) and + if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall() | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1809,13 +1823,19 @@ private predicate flowFwdIn( pragma[nomagic] private predicate flowFwdOut( - DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ReturnNodeExt ret, boolean allowsFieldFlow | - flowFwd(ret, fromArg, argAp, apf, ap, config) and + flowFwd(ret, innercc, argAp, apf, ap, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and - flowCand(node, _, _, _, unbind(config)) + innerc = ret.getEnclosingCallable() and + flowCand(node, _, _, _, unbind(config)) and + ( + resolveReturn(innercc, innerc, call) + or + innercc.(CallContextCall).matchesCall(call) + ) | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg( DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) + flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config) } /** @@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg( */ pragma[nomagic] private predicate flowFwdIsEntered( - DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config + DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and + flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } @@ -1920,7 +1940,7 @@ private predicate flow0( // flow out of a callable flowOut(_, node, _, _, ap, config) and toReturn = true and - if flowFwd(node, true, TAccessPathSome(_), _, ap, config) + if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config) then returnAp = TAccessPathSome(ap) else returnAp = TAccessPathNone() } @@ -2006,9 +2026,10 @@ private predicate flowIsReturned( DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, Configuration config ) { - exists(ReturnNodeExt ret | + exists(ReturnNodeExt ret, CallContextCall ccc | flowOut(call, ret, toReturn, returnAp, ap, config) and - flowFwd(ret, true, TAccessPathSome(_), _, ap, config) + flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and + ccc.matchesCall(call) ) } @@ -2031,7 +2052,7 @@ private newtype TSummaryCtx = exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | parameterFlow(p, ap, ret.getEnclosingCallable(), config) and flow(ret, true, TAccessPathSome(_), ap0, config) and - flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) + flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config) ) } @@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0( ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } @@ -2867,7 +2888,7 @@ private module FlowExploration { ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll index 27ab1d01feb..892250f44bb 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll @@ -512,13 +512,19 @@ abstract class CallContext extends TCallContext { abstract predicate relevantFor(DataFlowCallable callable); } -class CallContextAny extends CallContext, TAnyCallContext { +abstract class CallContextNoCall extends CallContext { } + +class CallContextAny extends CallContextNoCall, TAnyCallContext { override string toString() { result = "CcAny" } override predicate relevantFor(DataFlowCallable callable) { any() } } -abstract class CallContextCall extends CallContext { } +abstract class CallContextCall extends CallContext { + /** Holds if this call context may be `call`. */ + bindingset[call] + abstract predicate matchesCall(DataFlowCall call); +} class CallContextSpecificCall extends CallContextCall, TSpecificCall { override string toString() { @@ -529,6 +535,8 @@ class CallContextSpecificCall extends CallContextCall, TSpecificCall { recordDataFlowCallSite(getCall(), callable) } + override predicate matchesCall(DataFlowCall call) { call = this.getCall() } + DataFlowCall getCall() { this = TSpecificCall(result) } } @@ -538,9 +546,11 @@ class CallContextSomeCall extends CallContextCall, TSomeCall { override predicate relevantFor(DataFlowCallable callable) { exists(ParameterNode p | p.getEnclosingCallable() = callable) } + + override predicate matchesCall(DataFlowCall call) { any() } } -class CallContextReturn extends CallContext, TReturn { +class CallContextReturn extends CallContextNoCall, TReturn { override string toString() { exists(DataFlowCall call | this = TReturn(_, call) | result = "CcReturn(" + call + ")") } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll index 5042dce683f..4e6eb9d86c0 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { * Holds if `node` can be the first node in a maximal subsequence of local * flow steps in a dataflow path. */ - private predicate localFlowEntry(Node node, Configuration config) { + predicate localFlowEntry(Node node, Configuration config) { nodeCand2(node, config) and ( config.isSource(node) or @@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption { * Holds if `node` is reachable with access path `ap` from a source in * the configuration `config`. * - * The Boolean `fromArg` records whether the node is reached through an + * The call context `cc` records whether the node is reached through an * argument in a call, and if so, `argAp` records the access path of that * argument. */ private predicate flowFwd( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwd0(node, fromArg, argAp, apf, ap, config) and + flowFwd0(node, cc, argAp, apf, ap, config) and flowCand(node, _, _, apf, config) } private predicate flowFwd0( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { flowCand(node, _, _, _, config) and config.isSource(node) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() or flowCand(node, _, _, _, unbind(config)) and ( - exists(Node mid | - flowFwd(mid, fromArg, argAp, apf, ap, config) and - localFlowBigStep(mid, node, true, _, config, _) + exists(Node mid, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and + localFlowBigStep(mid, node, true, _, config, localCC) ) or - exists(Node mid, AccessPathNil nil | - flowFwd(mid, fromArg, argAp, _, nil, config) and - localFlowBigStep(mid, node, false, apf, config, _) and + exists(Node mid, AccessPathNil nil, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and + localFlowBigStep(mid, node, false, apf, config, localCC) and apf = ap.(AccessPathNil).getFront() ) or exists(Node mid | flowFwd(mid, _, _, apf, ap, config) and jumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() ) or exists(Node mid, AccessPathNil nil | flowFwd(mid, _, _, _, nil, config) and additionalJumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() @@ -1704,40 +1704,51 @@ private predicate flowFwd0( ) or // store - exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) + exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config)) or // read exists(TypedContent tc | - flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and + flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and flowFwdConsCand(tc, apf, ap, config) ) or // flow into a callable - flowFwdIn(_, node, _, _, apf, ap, config) and - fromArg = true and + flowFwdIn(_, node, cc, _, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and - fromArg = false + exists(CallContextNoCall innercc, DataFlowCallable c | + flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() + ) or exists(AccessPath argAp0 | flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and - flowFwdIsEntered(call, fromArg, argAp, argAp0, config) + flowFwdIsEntered(call, cc, argAp, argAp0, config) ) ) } +pragma[nomagic] +private predicate flowFwdLocalEntry( + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + LocalCallContext localCC, Configuration config +) { + flowFwd(node, cc, argAp, apf, ap, config) and + localFlowEntry(node, config) and + localCC = getLocalCallContext(cc, node.getEnclosingCallable()) +} + pragma[nomagic] private predicate flowFwdStore( - Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, AccessPathFront apf0 | - flowFwd(mid, fromArg, argAp, apf0, ap0, config) and + flowFwd(mid, cc, argAp, apf0, ap0, config) and flowFwdStore0(mid, tc, node, apf0, apf, config) ) } @@ -1764,20 +1775,20 @@ private predicate flowFwdStore0( pragma[nomagic] private predicate flowFwdRead0( - Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, - boolean fromArg, AccessPathOption argAp, Configuration config + Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc, + AccessPathOption argAp, Configuration config ) { - flowFwd(node1, fromArg, argAp, apf0, ap0, config) and + flowFwd(node1, cc, argAp, apf0, ap0, config) and readCandFwd(node1, tc, apf0, node2, config) } pragma[nomagic] private predicate flowFwdRead( - Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, TypedContent tc | - flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and + flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and flowCand(node, _, _, apf, unbind(config)) and flowCandConsCand(tc, apf, unbind(config)) ) @@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - exists(ArgumentNode arg, boolean allowsFieldFlow | - flowFwd(arg, fromArg, argAp, apf, ap, config) and + exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | + flowFwd(arg, outercc, argAp, apf, ap, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and - flowCand(p, _, _, _, unbind(config)) + c = p.getEnclosingCallable() and + c = resolveCall(call, outercc) and + flowCand(p, _, _, _, unbind(config)) and + if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall() | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1809,13 +1823,19 @@ private predicate flowFwdIn( pragma[nomagic] private predicate flowFwdOut( - DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ReturnNodeExt ret, boolean allowsFieldFlow | - flowFwd(ret, fromArg, argAp, apf, ap, config) and + flowFwd(ret, innercc, argAp, apf, ap, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and - flowCand(node, _, _, _, unbind(config)) + innerc = ret.getEnclosingCallable() and + flowCand(node, _, _, _, unbind(config)) and + ( + resolveReturn(innercc, innerc, call) + or + innercc.(CallContextCall).matchesCall(call) + ) | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg( DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) + flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config) } /** @@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg( */ pragma[nomagic] private predicate flowFwdIsEntered( - DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config + DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and + flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } @@ -1920,7 +1940,7 @@ private predicate flow0( // flow out of a callable flowOut(_, node, _, _, ap, config) and toReturn = true and - if flowFwd(node, true, TAccessPathSome(_), _, ap, config) + if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config) then returnAp = TAccessPathSome(ap) else returnAp = TAccessPathNone() } @@ -2006,9 +2026,10 @@ private predicate flowIsReturned( DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, Configuration config ) { - exists(ReturnNodeExt ret | + exists(ReturnNodeExt ret, CallContextCall ccc | flowOut(call, ret, toReturn, returnAp, ap, config) and - flowFwd(ret, true, TAccessPathSome(_), _, ap, config) + flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and + ccc.matchesCall(call) ) } @@ -2031,7 +2052,7 @@ private newtype TSummaryCtx = exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | parameterFlow(p, ap, ret.getEnclosingCallable(), config) and flow(ret, true, TAccessPathSome(_), ap0, config) and - flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) + flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config) ) } @@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0( ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } @@ -2867,7 +2888,7 @@ private module FlowExploration { ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll index 5042dce683f..4e6eb9d86c0 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { * Holds if `node` can be the first node in a maximal subsequence of local * flow steps in a dataflow path. */ - private predicate localFlowEntry(Node node, Configuration config) { + predicate localFlowEntry(Node node, Configuration config) { nodeCand2(node, config) and ( config.isSource(node) or @@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption { * Holds if `node` is reachable with access path `ap` from a source in * the configuration `config`. * - * The Boolean `fromArg` records whether the node is reached through an + * The call context `cc` records whether the node is reached through an * argument in a call, and if so, `argAp` records the access path of that * argument. */ private predicate flowFwd( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwd0(node, fromArg, argAp, apf, ap, config) and + flowFwd0(node, cc, argAp, apf, ap, config) and flowCand(node, _, _, apf, config) } private predicate flowFwd0( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { flowCand(node, _, _, _, config) and config.isSource(node) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() or flowCand(node, _, _, _, unbind(config)) and ( - exists(Node mid | - flowFwd(mid, fromArg, argAp, apf, ap, config) and - localFlowBigStep(mid, node, true, _, config, _) + exists(Node mid, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and + localFlowBigStep(mid, node, true, _, config, localCC) ) or - exists(Node mid, AccessPathNil nil | - flowFwd(mid, fromArg, argAp, _, nil, config) and - localFlowBigStep(mid, node, false, apf, config, _) and + exists(Node mid, AccessPathNil nil, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and + localFlowBigStep(mid, node, false, apf, config, localCC) and apf = ap.(AccessPathNil).getFront() ) or exists(Node mid | flowFwd(mid, _, _, apf, ap, config) and jumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() ) or exists(Node mid, AccessPathNil nil | flowFwd(mid, _, _, _, nil, config) and additionalJumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() @@ -1704,40 +1704,51 @@ private predicate flowFwd0( ) or // store - exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) + exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config)) or // read exists(TypedContent tc | - flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and + flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and flowFwdConsCand(tc, apf, ap, config) ) or // flow into a callable - flowFwdIn(_, node, _, _, apf, ap, config) and - fromArg = true and + flowFwdIn(_, node, cc, _, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and - fromArg = false + exists(CallContextNoCall innercc, DataFlowCallable c | + flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() + ) or exists(AccessPath argAp0 | flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and - flowFwdIsEntered(call, fromArg, argAp, argAp0, config) + flowFwdIsEntered(call, cc, argAp, argAp0, config) ) ) } +pragma[nomagic] +private predicate flowFwdLocalEntry( + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + LocalCallContext localCC, Configuration config +) { + flowFwd(node, cc, argAp, apf, ap, config) and + localFlowEntry(node, config) and + localCC = getLocalCallContext(cc, node.getEnclosingCallable()) +} + pragma[nomagic] private predicate flowFwdStore( - Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, AccessPathFront apf0 | - flowFwd(mid, fromArg, argAp, apf0, ap0, config) and + flowFwd(mid, cc, argAp, apf0, ap0, config) and flowFwdStore0(mid, tc, node, apf0, apf, config) ) } @@ -1764,20 +1775,20 @@ private predicate flowFwdStore0( pragma[nomagic] private predicate flowFwdRead0( - Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, - boolean fromArg, AccessPathOption argAp, Configuration config + Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc, + AccessPathOption argAp, Configuration config ) { - flowFwd(node1, fromArg, argAp, apf0, ap0, config) and + flowFwd(node1, cc, argAp, apf0, ap0, config) and readCandFwd(node1, tc, apf0, node2, config) } pragma[nomagic] private predicate flowFwdRead( - Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, TypedContent tc | - flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and + flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and flowCand(node, _, _, apf, unbind(config)) and flowCandConsCand(tc, apf, unbind(config)) ) @@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - exists(ArgumentNode arg, boolean allowsFieldFlow | - flowFwd(arg, fromArg, argAp, apf, ap, config) and + exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | + flowFwd(arg, outercc, argAp, apf, ap, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and - flowCand(p, _, _, _, unbind(config)) + c = p.getEnclosingCallable() and + c = resolveCall(call, outercc) and + flowCand(p, _, _, _, unbind(config)) and + if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall() | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1809,13 +1823,19 @@ private predicate flowFwdIn( pragma[nomagic] private predicate flowFwdOut( - DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ReturnNodeExt ret, boolean allowsFieldFlow | - flowFwd(ret, fromArg, argAp, apf, ap, config) and + flowFwd(ret, innercc, argAp, apf, ap, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and - flowCand(node, _, _, _, unbind(config)) + innerc = ret.getEnclosingCallable() and + flowCand(node, _, _, _, unbind(config)) and + ( + resolveReturn(innercc, innerc, call) + or + innercc.(CallContextCall).matchesCall(call) + ) | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg( DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) + flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config) } /** @@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg( */ pragma[nomagic] private predicate flowFwdIsEntered( - DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config + DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and + flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } @@ -1920,7 +1940,7 @@ private predicate flow0( // flow out of a callable flowOut(_, node, _, _, ap, config) and toReturn = true and - if flowFwd(node, true, TAccessPathSome(_), _, ap, config) + if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config) then returnAp = TAccessPathSome(ap) else returnAp = TAccessPathNone() } @@ -2006,9 +2026,10 @@ private predicate flowIsReturned( DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, Configuration config ) { - exists(ReturnNodeExt ret | + exists(ReturnNodeExt ret, CallContextCall ccc | flowOut(call, ret, toReturn, returnAp, ap, config) and - flowFwd(ret, true, TAccessPathSome(_), _, ap, config) + flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and + ccc.matchesCall(call) ) } @@ -2031,7 +2052,7 @@ private newtype TSummaryCtx = exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | parameterFlow(p, ap, ret.getEnclosingCallable(), config) and flow(ret, true, TAccessPathSome(_), ap0, config) and - flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) + flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config) ) } @@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0( ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } @@ -2867,7 +2888,7 @@ private module FlowExploration { ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll index 5042dce683f..4e6eb9d86c0 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { * Holds if `node` can be the first node in a maximal subsequence of local * flow steps in a dataflow path. */ - private predicate localFlowEntry(Node node, Configuration config) { + predicate localFlowEntry(Node node, Configuration config) { nodeCand2(node, config) and ( config.isSource(node) or @@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption { * Holds if `node` is reachable with access path `ap` from a source in * the configuration `config`. * - * The Boolean `fromArg` records whether the node is reached through an + * The call context `cc` records whether the node is reached through an * argument in a call, and if so, `argAp` records the access path of that * argument. */ private predicate flowFwd( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwd0(node, fromArg, argAp, apf, ap, config) and + flowFwd0(node, cc, argAp, apf, ap, config) and flowCand(node, _, _, apf, config) } private predicate flowFwd0( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { flowCand(node, _, _, _, config) and config.isSource(node) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() or flowCand(node, _, _, _, unbind(config)) and ( - exists(Node mid | - flowFwd(mid, fromArg, argAp, apf, ap, config) and - localFlowBigStep(mid, node, true, _, config, _) + exists(Node mid, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and + localFlowBigStep(mid, node, true, _, config, localCC) ) or - exists(Node mid, AccessPathNil nil | - flowFwd(mid, fromArg, argAp, _, nil, config) and - localFlowBigStep(mid, node, false, apf, config, _) and + exists(Node mid, AccessPathNil nil, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and + localFlowBigStep(mid, node, false, apf, config, localCC) and apf = ap.(AccessPathNil).getFront() ) or exists(Node mid | flowFwd(mid, _, _, apf, ap, config) and jumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() ) or exists(Node mid, AccessPathNil nil | flowFwd(mid, _, _, _, nil, config) and additionalJumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() @@ -1704,40 +1704,51 @@ private predicate flowFwd0( ) or // store - exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) + exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config)) or // read exists(TypedContent tc | - flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and + flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and flowFwdConsCand(tc, apf, ap, config) ) or // flow into a callable - flowFwdIn(_, node, _, _, apf, ap, config) and - fromArg = true and + flowFwdIn(_, node, cc, _, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and - fromArg = false + exists(CallContextNoCall innercc, DataFlowCallable c | + flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() + ) or exists(AccessPath argAp0 | flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and - flowFwdIsEntered(call, fromArg, argAp, argAp0, config) + flowFwdIsEntered(call, cc, argAp, argAp0, config) ) ) } +pragma[nomagic] +private predicate flowFwdLocalEntry( + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + LocalCallContext localCC, Configuration config +) { + flowFwd(node, cc, argAp, apf, ap, config) and + localFlowEntry(node, config) and + localCC = getLocalCallContext(cc, node.getEnclosingCallable()) +} + pragma[nomagic] private predicate flowFwdStore( - Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, AccessPathFront apf0 | - flowFwd(mid, fromArg, argAp, apf0, ap0, config) and + flowFwd(mid, cc, argAp, apf0, ap0, config) and flowFwdStore0(mid, tc, node, apf0, apf, config) ) } @@ -1764,20 +1775,20 @@ private predicate flowFwdStore0( pragma[nomagic] private predicate flowFwdRead0( - Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, - boolean fromArg, AccessPathOption argAp, Configuration config + Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc, + AccessPathOption argAp, Configuration config ) { - flowFwd(node1, fromArg, argAp, apf0, ap0, config) and + flowFwd(node1, cc, argAp, apf0, ap0, config) and readCandFwd(node1, tc, apf0, node2, config) } pragma[nomagic] private predicate flowFwdRead( - Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, TypedContent tc | - flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and + flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and flowCand(node, _, _, apf, unbind(config)) and flowCandConsCand(tc, apf, unbind(config)) ) @@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - exists(ArgumentNode arg, boolean allowsFieldFlow | - flowFwd(arg, fromArg, argAp, apf, ap, config) and + exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | + flowFwd(arg, outercc, argAp, apf, ap, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and - flowCand(p, _, _, _, unbind(config)) + c = p.getEnclosingCallable() and + c = resolveCall(call, outercc) and + flowCand(p, _, _, _, unbind(config)) and + if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall() | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1809,13 +1823,19 @@ private predicate flowFwdIn( pragma[nomagic] private predicate flowFwdOut( - DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ReturnNodeExt ret, boolean allowsFieldFlow | - flowFwd(ret, fromArg, argAp, apf, ap, config) and + flowFwd(ret, innercc, argAp, apf, ap, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and - flowCand(node, _, _, _, unbind(config)) + innerc = ret.getEnclosingCallable() and + flowCand(node, _, _, _, unbind(config)) and + ( + resolveReturn(innercc, innerc, call) + or + innercc.(CallContextCall).matchesCall(call) + ) | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg( DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) + flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config) } /** @@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg( */ pragma[nomagic] private predicate flowFwdIsEntered( - DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config + DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and + flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } @@ -1920,7 +1940,7 @@ private predicate flow0( // flow out of a callable flowOut(_, node, _, _, ap, config) and toReturn = true and - if flowFwd(node, true, TAccessPathSome(_), _, ap, config) + if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config) then returnAp = TAccessPathSome(ap) else returnAp = TAccessPathNone() } @@ -2006,9 +2026,10 @@ private predicate flowIsReturned( DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, Configuration config ) { - exists(ReturnNodeExt ret | + exists(ReturnNodeExt ret, CallContextCall ccc | flowOut(call, ret, toReturn, returnAp, ap, config) and - flowFwd(ret, true, TAccessPathSome(_), _, ap, config) + flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and + ccc.matchesCall(call) ) } @@ -2031,7 +2052,7 @@ private newtype TSummaryCtx = exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | parameterFlow(p, ap, ret.getEnclosingCallable(), config) and flow(ret, true, TAccessPathSome(_), ap0, config) and - flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) + flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config) ) } @@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0( ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } @@ -2867,7 +2888,7 @@ private module FlowExploration { ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll index 5042dce683f..4e6eb9d86c0 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { * Holds if `node` can be the first node in a maximal subsequence of local * flow steps in a dataflow path. */ - private predicate localFlowEntry(Node node, Configuration config) { + predicate localFlowEntry(Node node, Configuration config) { nodeCand2(node, config) and ( config.isSource(node) or @@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption { * Holds if `node` is reachable with access path `ap` from a source in * the configuration `config`. * - * The Boolean `fromArg` records whether the node is reached through an + * The call context `cc` records whether the node is reached through an * argument in a call, and if so, `argAp` records the access path of that * argument. */ private predicate flowFwd( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwd0(node, fromArg, argAp, apf, ap, config) and + flowFwd0(node, cc, argAp, apf, ap, config) and flowCand(node, _, _, apf, config) } private predicate flowFwd0( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { flowCand(node, _, _, _, config) and config.isSource(node) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() or flowCand(node, _, _, _, unbind(config)) and ( - exists(Node mid | - flowFwd(mid, fromArg, argAp, apf, ap, config) and - localFlowBigStep(mid, node, true, _, config, _) + exists(Node mid, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and + localFlowBigStep(mid, node, true, _, config, localCC) ) or - exists(Node mid, AccessPathNil nil | - flowFwd(mid, fromArg, argAp, _, nil, config) and - localFlowBigStep(mid, node, false, apf, config, _) and + exists(Node mid, AccessPathNil nil, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and + localFlowBigStep(mid, node, false, apf, config, localCC) and apf = ap.(AccessPathNil).getFront() ) or exists(Node mid | flowFwd(mid, _, _, apf, ap, config) and jumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() ) or exists(Node mid, AccessPathNil nil | flowFwd(mid, _, _, _, nil, config) and additionalJumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() @@ -1704,40 +1704,51 @@ private predicate flowFwd0( ) or // store - exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) + exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config)) or // read exists(TypedContent tc | - flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and + flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and flowFwdConsCand(tc, apf, ap, config) ) or // flow into a callable - flowFwdIn(_, node, _, _, apf, ap, config) and - fromArg = true and + flowFwdIn(_, node, cc, _, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and - fromArg = false + exists(CallContextNoCall innercc, DataFlowCallable c | + flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() + ) or exists(AccessPath argAp0 | flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and - flowFwdIsEntered(call, fromArg, argAp, argAp0, config) + flowFwdIsEntered(call, cc, argAp, argAp0, config) ) ) } +pragma[nomagic] +private predicate flowFwdLocalEntry( + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + LocalCallContext localCC, Configuration config +) { + flowFwd(node, cc, argAp, apf, ap, config) and + localFlowEntry(node, config) and + localCC = getLocalCallContext(cc, node.getEnclosingCallable()) +} + pragma[nomagic] private predicate flowFwdStore( - Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, AccessPathFront apf0 | - flowFwd(mid, fromArg, argAp, apf0, ap0, config) and + flowFwd(mid, cc, argAp, apf0, ap0, config) and flowFwdStore0(mid, tc, node, apf0, apf, config) ) } @@ -1764,20 +1775,20 @@ private predicate flowFwdStore0( pragma[nomagic] private predicate flowFwdRead0( - Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, - boolean fromArg, AccessPathOption argAp, Configuration config + Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc, + AccessPathOption argAp, Configuration config ) { - flowFwd(node1, fromArg, argAp, apf0, ap0, config) and + flowFwd(node1, cc, argAp, apf0, ap0, config) and readCandFwd(node1, tc, apf0, node2, config) } pragma[nomagic] private predicate flowFwdRead( - Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, TypedContent tc | - flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and + flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and flowCand(node, _, _, apf, unbind(config)) and flowCandConsCand(tc, apf, unbind(config)) ) @@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - exists(ArgumentNode arg, boolean allowsFieldFlow | - flowFwd(arg, fromArg, argAp, apf, ap, config) and + exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | + flowFwd(arg, outercc, argAp, apf, ap, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and - flowCand(p, _, _, _, unbind(config)) + c = p.getEnclosingCallable() and + c = resolveCall(call, outercc) and + flowCand(p, _, _, _, unbind(config)) and + if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall() | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1809,13 +1823,19 @@ private predicate flowFwdIn( pragma[nomagic] private predicate flowFwdOut( - DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ReturnNodeExt ret, boolean allowsFieldFlow | - flowFwd(ret, fromArg, argAp, apf, ap, config) and + flowFwd(ret, innercc, argAp, apf, ap, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and - flowCand(node, _, _, _, unbind(config)) + innerc = ret.getEnclosingCallable() and + flowCand(node, _, _, _, unbind(config)) and + ( + resolveReturn(innercc, innerc, call) + or + innercc.(CallContextCall).matchesCall(call) + ) | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg( DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) + flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config) } /** @@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg( */ pragma[nomagic] private predicate flowFwdIsEntered( - DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config + DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and + flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } @@ -1920,7 +1940,7 @@ private predicate flow0( // flow out of a callable flowOut(_, node, _, _, ap, config) and toReturn = true and - if flowFwd(node, true, TAccessPathSome(_), _, ap, config) + if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config) then returnAp = TAccessPathSome(ap) else returnAp = TAccessPathNone() } @@ -2006,9 +2026,10 @@ private predicate flowIsReturned( DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, Configuration config ) { - exists(ReturnNodeExt ret | + exists(ReturnNodeExt ret, CallContextCall ccc | flowOut(call, ret, toReturn, returnAp, ap, config) and - flowFwd(ret, true, TAccessPathSome(_), _, ap, config) + flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and + ccc.matchesCall(call) ) } @@ -2031,7 +2052,7 @@ private newtype TSummaryCtx = exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | parameterFlow(p, ap, ret.getEnclosingCallable(), config) and flow(ret, true, TAccessPathSome(_), ap0, config) and - flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) + flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config) ) } @@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0( ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } @@ -2867,7 +2888,7 @@ private module FlowExploration { ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll index 5042dce683f..4e6eb9d86c0 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { * Holds if `node` can be the first node in a maximal subsequence of local * flow steps in a dataflow path. */ - private predicate localFlowEntry(Node node, Configuration config) { + predicate localFlowEntry(Node node, Configuration config) { nodeCand2(node, config) and ( config.isSource(node) or @@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption { * Holds if `node` is reachable with access path `ap` from a source in * the configuration `config`. * - * The Boolean `fromArg` records whether the node is reached through an + * The call context `cc` records whether the node is reached through an * argument in a call, and if so, `argAp` records the access path of that * argument. */ private predicate flowFwd( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwd0(node, fromArg, argAp, apf, ap, config) and + flowFwd0(node, cc, argAp, apf, ap, config) and flowCand(node, _, _, apf, config) } private predicate flowFwd0( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { flowCand(node, _, _, _, config) and config.isSource(node) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() or flowCand(node, _, _, _, unbind(config)) and ( - exists(Node mid | - flowFwd(mid, fromArg, argAp, apf, ap, config) and - localFlowBigStep(mid, node, true, _, config, _) + exists(Node mid, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and + localFlowBigStep(mid, node, true, _, config, localCC) ) or - exists(Node mid, AccessPathNil nil | - flowFwd(mid, fromArg, argAp, _, nil, config) and - localFlowBigStep(mid, node, false, apf, config, _) and + exists(Node mid, AccessPathNil nil, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and + localFlowBigStep(mid, node, false, apf, config, localCC) and apf = ap.(AccessPathNil).getFront() ) or exists(Node mid | flowFwd(mid, _, _, apf, ap, config) and jumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() ) or exists(Node mid, AccessPathNil nil | flowFwd(mid, _, _, _, nil, config) and additionalJumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() @@ -1704,40 +1704,51 @@ private predicate flowFwd0( ) or // store - exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) + exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config)) or // read exists(TypedContent tc | - flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and + flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and flowFwdConsCand(tc, apf, ap, config) ) or // flow into a callable - flowFwdIn(_, node, _, _, apf, ap, config) and - fromArg = true and + flowFwdIn(_, node, cc, _, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and - fromArg = false + exists(CallContextNoCall innercc, DataFlowCallable c | + flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() + ) or exists(AccessPath argAp0 | flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and - flowFwdIsEntered(call, fromArg, argAp, argAp0, config) + flowFwdIsEntered(call, cc, argAp, argAp0, config) ) ) } +pragma[nomagic] +private predicate flowFwdLocalEntry( + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + LocalCallContext localCC, Configuration config +) { + flowFwd(node, cc, argAp, apf, ap, config) and + localFlowEntry(node, config) and + localCC = getLocalCallContext(cc, node.getEnclosingCallable()) +} + pragma[nomagic] private predicate flowFwdStore( - Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, AccessPathFront apf0 | - flowFwd(mid, fromArg, argAp, apf0, ap0, config) and + flowFwd(mid, cc, argAp, apf0, ap0, config) and flowFwdStore0(mid, tc, node, apf0, apf, config) ) } @@ -1764,20 +1775,20 @@ private predicate flowFwdStore0( pragma[nomagic] private predicate flowFwdRead0( - Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, - boolean fromArg, AccessPathOption argAp, Configuration config + Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc, + AccessPathOption argAp, Configuration config ) { - flowFwd(node1, fromArg, argAp, apf0, ap0, config) and + flowFwd(node1, cc, argAp, apf0, ap0, config) and readCandFwd(node1, tc, apf0, node2, config) } pragma[nomagic] private predicate flowFwdRead( - Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, TypedContent tc | - flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and + flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and flowCand(node, _, _, apf, unbind(config)) and flowCandConsCand(tc, apf, unbind(config)) ) @@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - exists(ArgumentNode arg, boolean allowsFieldFlow | - flowFwd(arg, fromArg, argAp, apf, ap, config) and + exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | + flowFwd(arg, outercc, argAp, apf, ap, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and - flowCand(p, _, _, _, unbind(config)) + c = p.getEnclosingCallable() and + c = resolveCall(call, outercc) and + flowCand(p, _, _, _, unbind(config)) and + if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall() | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1809,13 +1823,19 @@ private predicate flowFwdIn( pragma[nomagic] private predicate flowFwdOut( - DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ReturnNodeExt ret, boolean allowsFieldFlow | - flowFwd(ret, fromArg, argAp, apf, ap, config) and + flowFwd(ret, innercc, argAp, apf, ap, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and - flowCand(node, _, _, _, unbind(config)) + innerc = ret.getEnclosingCallable() and + flowCand(node, _, _, _, unbind(config)) and + ( + resolveReturn(innercc, innerc, call) + or + innercc.(CallContextCall).matchesCall(call) + ) | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg( DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) + flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config) } /** @@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg( */ pragma[nomagic] private predicate flowFwdIsEntered( - DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config + DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and + flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } @@ -1920,7 +1940,7 @@ private predicate flow0( // flow out of a callable flowOut(_, node, _, _, ap, config) and toReturn = true and - if flowFwd(node, true, TAccessPathSome(_), _, ap, config) + if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config) then returnAp = TAccessPathSome(ap) else returnAp = TAccessPathNone() } @@ -2006,9 +2026,10 @@ private predicate flowIsReturned( DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, Configuration config ) { - exists(ReturnNodeExt ret | + exists(ReturnNodeExt ret, CallContextCall ccc | flowOut(call, ret, toReturn, returnAp, ap, config) and - flowFwd(ret, true, TAccessPathSome(_), _, ap, config) + flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and + ccc.matchesCall(call) ) } @@ -2031,7 +2052,7 @@ private newtype TSummaryCtx = exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | parameterFlow(p, ap, ret.getEnclosingCallable(), config) and flow(ret, true, TAccessPathSome(_), ap0, config) and - flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) + flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config) ) } @@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0( ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } @@ -2867,7 +2888,7 @@ private module FlowExploration { ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll index 27ab1d01feb..892250f44bb 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll @@ -512,13 +512,19 @@ abstract class CallContext extends TCallContext { abstract predicate relevantFor(DataFlowCallable callable); } -class CallContextAny extends CallContext, TAnyCallContext { +abstract class CallContextNoCall extends CallContext { } + +class CallContextAny extends CallContextNoCall, TAnyCallContext { override string toString() { result = "CcAny" } override predicate relevantFor(DataFlowCallable callable) { any() } } -abstract class CallContextCall extends CallContext { } +abstract class CallContextCall extends CallContext { + /** Holds if this call context may be `call`. */ + bindingset[call] + abstract predicate matchesCall(DataFlowCall call); +} class CallContextSpecificCall extends CallContextCall, TSpecificCall { override string toString() { @@ -529,6 +535,8 @@ class CallContextSpecificCall extends CallContextCall, TSpecificCall { recordDataFlowCallSite(getCall(), callable) } + override predicate matchesCall(DataFlowCall call) { call = this.getCall() } + DataFlowCall getCall() { this = TSpecificCall(result) } } @@ -538,9 +546,11 @@ class CallContextSomeCall extends CallContextCall, TSomeCall { override predicate relevantFor(DataFlowCallable callable) { exists(ParameterNode p | p.getEnclosingCallable() = callable) } + + override predicate matchesCall(DataFlowCall call) { any() } } -class CallContextReturn extends CallContext, TReturn { +class CallContextReturn extends CallContextNoCall, TReturn { override string toString() { exists(DataFlowCall call | this = TReturn(_, call) | result = "CcReturn(" + call + ")") } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll index 5042dce683f..4e6eb9d86c0 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { * Holds if `node` can be the first node in a maximal subsequence of local * flow steps in a dataflow path. */ - private predicate localFlowEntry(Node node, Configuration config) { + predicate localFlowEntry(Node node, Configuration config) { nodeCand2(node, config) and ( config.isSource(node) or @@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption { * Holds if `node` is reachable with access path `ap` from a source in * the configuration `config`. * - * The Boolean `fromArg` records whether the node is reached through an + * The call context `cc` records whether the node is reached through an * argument in a call, and if so, `argAp` records the access path of that * argument. */ private predicate flowFwd( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwd0(node, fromArg, argAp, apf, ap, config) and + flowFwd0(node, cc, argAp, apf, ap, config) and flowCand(node, _, _, apf, config) } private predicate flowFwd0( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { flowCand(node, _, _, _, config) and config.isSource(node) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() or flowCand(node, _, _, _, unbind(config)) and ( - exists(Node mid | - flowFwd(mid, fromArg, argAp, apf, ap, config) and - localFlowBigStep(mid, node, true, _, config, _) + exists(Node mid, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and + localFlowBigStep(mid, node, true, _, config, localCC) ) or - exists(Node mid, AccessPathNil nil | - flowFwd(mid, fromArg, argAp, _, nil, config) and - localFlowBigStep(mid, node, false, apf, config, _) and + exists(Node mid, AccessPathNil nil, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and + localFlowBigStep(mid, node, false, apf, config, localCC) and apf = ap.(AccessPathNil).getFront() ) or exists(Node mid | flowFwd(mid, _, _, apf, ap, config) and jumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() ) or exists(Node mid, AccessPathNil nil | flowFwd(mid, _, _, _, nil, config) and additionalJumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() @@ -1704,40 +1704,51 @@ private predicate flowFwd0( ) or // store - exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) + exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config)) or // read exists(TypedContent tc | - flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and + flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and flowFwdConsCand(tc, apf, ap, config) ) or // flow into a callable - flowFwdIn(_, node, _, _, apf, ap, config) and - fromArg = true and + flowFwdIn(_, node, cc, _, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and - fromArg = false + exists(CallContextNoCall innercc, DataFlowCallable c | + flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() + ) or exists(AccessPath argAp0 | flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and - flowFwdIsEntered(call, fromArg, argAp, argAp0, config) + flowFwdIsEntered(call, cc, argAp, argAp0, config) ) ) } +pragma[nomagic] +private predicate flowFwdLocalEntry( + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + LocalCallContext localCC, Configuration config +) { + flowFwd(node, cc, argAp, apf, ap, config) and + localFlowEntry(node, config) and + localCC = getLocalCallContext(cc, node.getEnclosingCallable()) +} + pragma[nomagic] private predicate flowFwdStore( - Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, AccessPathFront apf0 | - flowFwd(mid, fromArg, argAp, apf0, ap0, config) and + flowFwd(mid, cc, argAp, apf0, ap0, config) and flowFwdStore0(mid, tc, node, apf0, apf, config) ) } @@ -1764,20 +1775,20 @@ private predicate flowFwdStore0( pragma[nomagic] private predicate flowFwdRead0( - Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, - boolean fromArg, AccessPathOption argAp, Configuration config + Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc, + AccessPathOption argAp, Configuration config ) { - flowFwd(node1, fromArg, argAp, apf0, ap0, config) and + flowFwd(node1, cc, argAp, apf0, ap0, config) and readCandFwd(node1, tc, apf0, node2, config) } pragma[nomagic] private predicate flowFwdRead( - Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, TypedContent tc | - flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and + flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and flowCand(node, _, _, apf, unbind(config)) and flowCandConsCand(tc, apf, unbind(config)) ) @@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - exists(ArgumentNode arg, boolean allowsFieldFlow | - flowFwd(arg, fromArg, argAp, apf, ap, config) and + exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | + flowFwd(arg, outercc, argAp, apf, ap, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and - flowCand(p, _, _, _, unbind(config)) + c = p.getEnclosingCallable() and + c = resolveCall(call, outercc) and + flowCand(p, _, _, _, unbind(config)) and + if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall() | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1809,13 +1823,19 @@ private predicate flowFwdIn( pragma[nomagic] private predicate flowFwdOut( - DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ReturnNodeExt ret, boolean allowsFieldFlow | - flowFwd(ret, fromArg, argAp, apf, ap, config) and + flowFwd(ret, innercc, argAp, apf, ap, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and - flowCand(node, _, _, _, unbind(config)) + innerc = ret.getEnclosingCallable() and + flowCand(node, _, _, _, unbind(config)) and + ( + resolveReturn(innercc, innerc, call) + or + innercc.(CallContextCall).matchesCall(call) + ) | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg( DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) + flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config) } /** @@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg( */ pragma[nomagic] private predicate flowFwdIsEntered( - DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config + DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and + flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } @@ -1920,7 +1940,7 @@ private predicate flow0( // flow out of a callable flowOut(_, node, _, _, ap, config) and toReturn = true and - if flowFwd(node, true, TAccessPathSome(_), _, ap, config) + if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config) then returnAp = TAccessPathSome(ap) else returnAp = TAccessPathNone() } @@ -2006,9 +2026,10 @@ private predicate flowIsReturned( DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, Configuration config ) { - exists(ReturnNodeExt ret | + exists(ReturnNodeExt ret, CallContextCall ccc | flowOut(call, ret, toReturn, returnAp, ap, config) and - flowFwd(ret, true, TAccessPathSome(_), _, ap, config) + flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and + ccc.matchesCall(call) ) } @@ -2031,7 +2052,7 @@ private newtype TSummaryCtx = exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | parameterFlow(p, ap, ret.getEnclosingCallable(), config) and flow(ret, true, TAccessPathSome(_), ap0, config) and - flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) + flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config) ) } @@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0( ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } @@ -2867,7 +2888,7 @@ private module FlowExploration { ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll index 5042dce683f..4e6eb9d86c0 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { * Holds if `node` can be the first node in a maximal subsequence of local * flow steps in a dataflow path. */ - private predicate localFlowEntry(Node node, Configuration config) { + predicate localFlowEntry(Node node, Configuration config) { nodeCand2(node, config) and ( config.isSource(node) or @@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption { * Holds if `node` is reachable with access path `ap` from a source in * the configuration `config`. * - * The Boolean `fromArg` records whether the node is reached through an + * The call context `cc` records whether the node is reached through an * argument in a call, and if so, `argAp` records the access path of that * argument. */ private predicate flowFwd( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwd0(node, fromArg, argAp, apf, ap, config) and + flowFwd0(node, cc, argAp, apf, ap, config) and flowCand(node, _, _, apf, config) } private predicate flowFwd0( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { flowCand(node, _, _, _, config) and config.isSource(node) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() or flowCand(node, _, _, _, unbind(config)) and ( - exists(Node mid | - flowFwd(mid, fromArg, argAp, apf, ap, config) and - localFlowBigStep(mid, node, true, _, config, _) + exists(Node mid, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and + localFlowBigStep(mid, node, true, _, config, localCC) ) or - exists(Node mid, AccessPathNil nil | - flowFwd(mid, fromArg, argAp, _, nil, config) and - localFlowBigStep(mid, node, false, apf, config, _) and + exists(Node mid, AccessPathNil nil, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and + localFlowBigStep(mid, node, false, apf, config, localCC) and apf = ap.(AccessPathNil).getFront() ) or exists(Node mid | flowFwd(mid, _, _, apf, ap, config) and jumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() ) or exists(Node mid, AccessPathNil nil | flowFwd(mid, _, _, _, nil, config) and additionalJumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() @@ -1704,40 +1704,51 @@ private predicate flowFwd0( ) or // store - exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) + exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config)) or // read exists(TypedContent tc | - flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and + flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and flowFwdConsCand(tc, apf, ap, config) ) or // flow into a callable - flowFwdIn(_, node, _, _, apf, ap, config) and - fromArg = true and + flowFwdIn(_, node, cc, _, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and - fromArg = false + exists(CallContextNoCall innercc, DataFlowCallable c | + flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() + ) or exists(AccessPath argAp0 | flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and - flowFwdIsEntered(call, fromArg, argAp, argAp0, config) + flowFwdIsEntered(call, cc, argAp, argAp0, config) ) ) } +pragma[nomagic] +private predicate flowFwdLocalEntry( + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + LocalCallContext localCC, Configuration config +) { + flowFwd(node, cc, argAp, apf, ap, config) and + localFlowEntry(node, config) and + localCC = getLocalCallContext(cc, node.getEnclosingCallable()) +} + pragma[nomagic] private predicate flowFwdStore( - Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, AccessPathFront apf0 | - flowFwd(mid, fromArg, argAp, apf0, ap0, config) and + flowFwd(mid, cc, argAp, apf0, ap0, config) and flowFwdStore0(mid, tc, node, apf0, apf, config) ) } @@ -1764,20 +1775,20 @@ private predicate flowFwdStore0( pragma[nomagic] private predicate flowFwdRead0( - Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, - boolean fromArg, AccessPathOption argAp, Configuration config + Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc, + AccessPathOption argAp, Configuration config ) { - flowFwd(node1, fromArg, argAp, apf0, ap0, config) and + flowFwd(node1, cc, argAp, apf0, ap0, config) and readCandFwd(node1, tc, apf0, node2, config) } pragma[nomagic] private predicate flowFwdRead( - Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, TypedContent tc | - flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and + flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and flowCand(node, _, _, apf, unbind(config)) and flowCandConsCand(tc, apf, unbind(config)) ) @@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - exists(ArgumentNode arg, boolean allowsFieldFlow | - flowFwd(arg, fromArg, argAp, apf, ap, config) and + exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | + flowFwd(arg, outercc, argAp, apf, ap, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and - flowCand(p, _, _, _, unbind(config)) + c = p.getEnclosingCallable() and + c = resolveCall(call, outercc) and + flowCand(p, _, _, _, unbind(config)) and + if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall() | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1809,13 +1823,19 @@ private predicate flowFwdIn( pragma[nomagic] private predicate flowFwdOut( - DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ReturnNodeExt ret, boolean allowsFieldFlow | - flowFwd(ret, fromArg, argAp, apf, ap, config) and + flowFwd(ret, innercc, argAp, apf, ap, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and - flowCand(node, _, _, _, unbind(config)) + innerc = ret.getEnclosingCallable() and + flowCand(node, _, _, _, unbind(config)) and + ( + resolveReturn(innercc, innerc, call) + or + innercc.(CallContextCall).matchesCall(call) + ) | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg( DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) + flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config) } /** @@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg( */ pragma[nomagic] private predicate flowFwdIsEntered( - DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config + DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and + flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } @@ -1920,7 +1940,7 @@ private predicate flow0( // flow out of a callable flowOut(_, node, _, _, ap, config) and toReturn = true and - if flowFwd(node, true, TAccessPathSome(_), _, ap, config) + if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config) then returnAp = TAccessPathSome(ap) else returnAp = TAccessPathNone() } @@ -2006,9 +2026,10 @@ private predicate flowIsReturned( DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, Configuration config ) { - exists(ReturnNodeExt ret | + exists(ReturnNodeExt ret, CallContextCall ccc | flowOut(call, ret, toReturn, returnAp, ap, config) and - flowFwd(ret, true, TAccessPathSome(_), _, ap, config) + flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and + ccc.matchesCall(call) ) } @@ -2031,7 +2052,7 @@ private newtype TSummaryCtx = exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | parameterFlow(p, ap, ret.getEnclosingCallable(), config) and flow(ret, true, TAccessPathSome(_), ap0, config) and - flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) + flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config) ) } @@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0( ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } @@ -2867,7 +2888,7 @@ private module FlowExploration { ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll index 5042dce683f..4e6eb9d86c0 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { * Holds if `node` can be the first node in a maximal subsequence of local * flow steps in a dataflow path. */ - private predicate localFlowEntry(Node node, Configuration config) { + predicate localFlowEntry(Node node, Configuration config) { nodeCand2(node, config) and ( config.isSource(node) or @@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption { * Holds if `node` is reachable with access path `ap` from a source in * the configuration `config`. * - * The Boolean `fromArg` records whether the node is reached through an + * The call context `cc` records whether the node is reached through an * argument in a call, and if so, `argAp` records the access path of that * argument. */ private predicate flowFwd( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwd0(node, fromArg, argAp, apf, ap, config) and + flowFwd0(node, cc, argAp, apf, ap, config) and flowCand(node, _, _, apf, config) } private predicate flowFwd0( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { flowCand(node, _, _, _, config) and config.isSource(node) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() or flowCand(node, _, _, _, unbind(config)) and ( - exists(Node mid | - flowFwd(mid, fromArg, argAp, apf, ap, config) and - localFlowBigStep(mid, node, true, _, config, _) + exists(Node mid, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and + localFlowBigStep(mid, node, true, _, config, localCC) ) or - exists(Node mid, AccessPathNil nil | - flowFwd(mid, fromArg, argAp, _, nil, config) and - localFlowBigStep(mid, node, false, apf, config, _) and + exists(Node mid, AccessPathNil nil, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and + localFlowBigStep(mid, node, false, apf, config, localCC) and apf = ap.(AccessPathNil).getFront() ) or exists(Node mid | flowFwd(mid, _, _, apf, ap, config) and jumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() ) or exists(Node mid, AccessPathNil nil | flowFwd(mid, _, _, _, nil, config) and additionalJumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() @@ -1704,40 +1704,51 @@ private predicate flowFwd0( ) or // store - exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) + exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config)) or // read exists(TypedContent tc | - flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and + flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and flowFwdConsCand(tc, apf, ap, config) ) or // flow into a callable - flowFwdIn(_, node, _, _, apf, ap, config) and - fromArg = true and + flowFwdIn(_, node, cc, _, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and - fromArg = false + exists(CallContextNoCall innercc, DataFlowCallable c | + flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() + ) or exists(AccessPath argAp0 | flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and - flowFwdIsEntered(call, fromArg, argAp, argAp0, config) + flowFwdIsEntered(call, cc, argAp, argAp0, config) ) ) } +pragma[nomagic] +private predicate flowFwdLocalEntry( + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + LocalCallContext localCC, Configuration config +) { + flowFwd(node, cc, argAp, apf, ap, config) and + localFlowEntry(node, config) and + localCC = getLocalCallContext(cc, node.getEnclosingCallable()) +} + pragma[nomagic] private predicate flowFwdStore( - Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, AccessPathFront apf0 | - flowFwd(mid, fromArg, argAp, apf0, ap0, config) and + flowFwd(mid, cc, argAp, apf0, ap0, config) and flowFwdStore0(mid, tc, node, apf0, apf, config) ) } @@ -1764,20 +1775,20 @@ private predicate flowFwdStore0( pragma[nomagic] private predicate flowFwdRead0( - Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, - boolean fromArg, AccessPathOption argAp, Configuration config + Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc, + AccessPathOption argAp, Configuration config ) { - flowFwd(node1, fromArg, argAp, apf0, ap0, config) and + flowFwd(node1, cc, argAp, apf0, ap0, config) and readCandFwd(node1, tc, apf0, node2, config) } pragma[nomagic] private predicate flowFwdRead( - Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, TypedContent tc | - flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and + flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and flowCand(node, _, _, apf, unbind(config)) and flowCandConsCand(tc, apf, unbind(config)) ) @@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - exists(ArgumentNode arg, boolean allowsFieldFlow | - flowFwd(arg, fromArg, argAp, apf, ap, config) and + exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | + flowFwd(arg, outercc, argAp, apf, ap, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and - flowCand(p, _, _, _, unbind(config)) + c = p.getEnclosingCallable() and + c = resolveCall(call, outercc) and + flowCand(p, _, _, _, unbind(config)) and + if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall() | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1809,13 +1823,19 @@ private predicate flowFwdIn( pragma[nomagic] private predicate flowFwdOut( - DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ReturnNodeExt ret, boolean allowsFieldFlow | - flowFwd(ret, fromArg, argAp, apf, ap, config) and + flowFwd(ret, innercc, argAp, apf, ap, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and - flowCand(node, _, _, _, unbind(config)) + innerc = ret.getEnclosingCallable() and + flowCand(node, _, _, _, unbind(config)) and + ( + resolveReturn(innercc, innerc, call) + or + innercc.(CallContextCall).matchesCall(call) + ) | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg( DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) + flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config) } /** @@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg( */ pragma[nomagic] private predicate flowFwdIsEntered( - DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config + DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and + flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } @@ -1920,7 +1940,7 @@ private predicate flow0( // flow out of a callable flowOut(_, node, _, _, ap, config) and toReturn = true and - if flowFwd(node, true, TAccessPathSome(_), _, ap, config) + if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config) then returnAp = TAccessPathSome(ap) else returnAp = TAccessPathNone() } @@ -2006,9 +2026,10 @@ private predicate flowIsReturned( DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, Configuration config ) { - exists(ReturnNodeExt ret | + exists(ReturnNodeExt ret, CallContextCall ccc | flowOut(call, ret, toReturn, returnAp, ap, config) and - flowFwd(ret, true, TAccessPathSome(_), _, ap, config) + flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and + ccc.matchesCall(call) ) } @@ -2031,7 +2052,7 @@ private newtype TSummaryCtx = exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | parameterFlow(p, ap, ret.getEnclosingCallable(), config) and flow(ret, true, TAccessPathSome(_), ap0, config) and - flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) + flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config) ) } @@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0( ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } @@ -2867,7 +2888,7 @@ private module FlowExploration { ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll index 5042dce683f..4e6eb9d86c0 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { * Holds if `node` can be the first node in a maximal subsequence of local * flow steps in a dataflow path. */ - private predicate localFlowEntry(Node node, Configuration config) { + predicate localFlowEntry(Node node, Configuration config) { nodeCand2(node, config) and ( config.isSource(node) or @@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption { * Holds if `node` is reachable with access path `ap` from a source in * the configuration `config`. * - * The Boolean `fromArg` records whether the node is reached through an + * The call context `cc` records whether the node is reached through an * argument in a call, and if so, `argAp` records the access path of that * argument. */ private predicate flowFwd( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwd0(node, fromArg, argAp, apf, ap, config) and + flowFwd0(node, cc, argAp, apf, ap, config) and flowCand(node, _, _, apf, config) } private predicate flowFwd0( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { flowCand(node, _, _, _, config) and config.isSource(node) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() or flowCand(node, _, _, _, unbind(config)) and ( - exists(Node mid | - flowFwd(mid, fromArg, argAp, apf, ap, config) and - localFlowBigStep(mid, node, true, _, config, _) + exists(Node mid, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and + localFlowBigStep(mid, node, true, _, config, localCC) ) or - exists(Node mid, AccessPathNil nil | - flowFwd(mid, fromArg, argAp, _, nil, config) and - localFlowBigStep(mid, node, false, apf, config, _) and + exists(Node mid, AccessPathNil nil, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and + localFlowBigStep(mid, node, false, apf, config, localCC) and apf = ap.(AccessPathNil).getFront() ) or exists(Node mid | flowFwd(mid, _, _, apf, ap, config) and jumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() ) or exists(Node mid, AccessPathNil nil | flowFwd(mid, _, _, _, nil, config) and additionalJumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() @@ -1704,40 +1704,51 @@ private predicate flowFwd0( ) or // store - exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) + exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config)) or // read exists(TypedContent tc | - flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and + flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and flowFwdConsCand(tc, apf, ap, config) ) or // flow into a callable - flowFwdIn(_, node, _, _, apf, ap, config) and - fromArg = true and + flowFwdIn(_, node, cc, _, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and - fromArg = false + exists(CallContextNoCall innercc, DataFlowCallable c | + flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() + ) or exists(AccessPath argAp0 | flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and - flowFwdIsEntered(call, fromArg, argAp, argAp0, config) + flowFwdIsEntered(call, cc, argAp, argAp0, config) ) ) } +pragma[nomagic] +private predicate flowFwdLocalEntry( + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + LocalCallContext localCC, Configuration config +) { + flowFwd(node, cc, argAp, apf, ap, config) and + localFlowEntry(node, config) and + localCC = getLocalCallContext(cc, node.getEnclosingCallable()) +} + pragma[nomagic] private predicate flowFwdStore( - Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, AccessPathFront apf0 | - flowFwd(mid, fromArg, argAp, apf0, ap0, config) and + flowFwd(mid, cc, argAp, apf0, ap0, config) and flowFwdStore0(mid, tc, node, apf0, apf, config) ) } @@ -1764,20 +1775,20 @@ private predicate flowFwdStore0( pragma[nomagic] private predicate flowFwdRead0( - Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, - boolean fromArg, AccessPathOption argAp, Configuration config + Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc, + AccessPathOption argAp, Configuration config ) { - flowFwd(node1, fromArg, argAp, apf0, ap0, config) and + flowFwd(node1, cc, argAp, apf0, ap0, config) and readCandFwd(node1, tc, apf0, node2, config) } pragma[nomagic] private predicate flowFwdRead( - Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, TypedContent tc | - flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and + flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and flowCand(node, _, _, apf, unbind(config)) and flowCandConsCand(tc, apf, unbind(config)) ) @@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - exists(ArgumentNode arg, boolean allowsFieldFlow | - flowFwd(arg, fromArg, argAp, apf, ap, config) and + exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | + flowFwd(arg, outercc, argAp, apf, ap, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and - flowCand(p, _, _, _, unbind(config)) + c = p.getEnclosingCallable() and + c = resolveCall(call, outercc) and + flowCand(p, _, _, _, unbind(config)) and + if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall() | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1809,13 +1823,19 @@ private predicate flowFwdIn( pragma[nomagic] private predicate flowFwdOut( - DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ReturnNodeExt ret, boolean allowsFieldFlow | - flowFwd(ret, fromArg, argAp, apf, ap, config) and + flowFwd(ret, innercc, argAp, apf, ap, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and - flowCand(node, _, _, _, unbind(config)) + innerc = ret.getEnclosingCallable() and + flowCand(node, _, _, _, unbind(config)) and + ( + resolveReturn(innercc, innerc, call) + or + innercc.(CallContextCall).matchesCall(call) + ) | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg( DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) + flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config) } /** @@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg( */ pragma[nomagic] private predicate flowFwdIsEntered( - DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config + DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and + flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } @@ -1920,7 +1940,7 @@ private predicate flow0( // flow out of a callable flowOut(_, node, _, _, ap, config) and toReturn = true and - if flowFwd(node, true, TAccessPathSome(_), _, ap, config) + if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config) then returnAp = TAccessPathSome(ap) else returnAp = TAccessPathNone() } @@ -2006,9 +2026,10 @@ private predicate flowIsReturned( DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, Configuration config ) { - exists(ReturnNodeExt ret | + exists(ReturnNodeExt ret, CallContextCall ccc | flowOut(call, ret, toReturn, returnAp, ap, config) and - flowFwd(ret, true, TAccessPathSome(_), _, ap, config) + flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and + ccc.matchesCall(call) ) } @@ -2031,7 +2052,7 @@ private newtype TSummaryCtx = exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | parameterFlow(p, ap, ret.getEnclosingCallable(), config) and flow(ret, true, TAccessPathSome(_), ap0, config) and - flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) + flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config) ) } @@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0( ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } @@ -2867,7 +2888,7 @@ private module FlowExploration { ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll index 5042dce683f..4e6eb9d86c0 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { * Holds if `node` can be the first node in a maximal subsequence of local * flow steps in a dataflow path. */ - private predicate localFlowEntry(Node node, Configuration config) { + predicate localFlowEntry(Node node, Configuration config) { nodeCand2(node, config) and ( config.isSource(node) or @@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption { * Holds if `node` is reachable with access path `ap` from a source in * the configuration `config`. * - * The Boolean `fromArg` records whether the node is reached through an + * The call context `cc` records whether the node is reached through an * argument in a call, and if so, `argAp` records the access path of that * argument. */ private predicate flowFwd( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwd0(node, fromArg, argAp, apf, ap, config) and + flowFwd0(node, cc, argAp, apf, ap, config) and flowCand(node, _, _, apf, config) } private predicate flowFwd0( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { flowCand(node, _, _, _, config) and config.isSource(node) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() or flowCand(node, _, _, _, unbind(config)) and ( - exists(Node mid | - flowFwd(mid, fromArg, argAp, apf, ap, config) and - localFlowBigStep(mid, node, true, _, config, _) + exists(Node mid, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and + localFlowBigStep(mid, node, true, _, config, localCC) ) or - exists(Node mid, AccessPathNil nil | - flowFwd(mid, fromArg, argAp, _, nil, config) and - localFlowBigStep(mid, node, false, apf, config, _) and + exists(Node mid, AccessPathNil nil, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and + localFlowBigStep(mid, node, false, apf, config, localCC) and apf = ap.(AccessPathNil).getFront() ) or exists(Node mid | flowFwd(mid, _, _, apf, ap, config) and jumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() ) or exists(Node mid, AccessPathNil nil | flowFwd(mid, _, _, _, nil, config) and additionalJumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() @@ -1704,40 +1704,51 @@ private predicate flowFwd0( ) or // store - exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) + exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config)) or // read exists(TypedContent tc | - flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and + flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and flowFwdConsCand(tc, apf, ap, config) ) or // flow into a callable - flowFwdIn(_, node, _, _, apf, ap, config) and - fromArg = true and + flowFwdIn(_, node, cc, _, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and - fromArg = false + exists(CallContextNoCall innercc, DataFlowCallable c | + flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() + ) or exists(AccessPath argAp0 | flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and - flowFwdIsEntered(call, fromArg, argAp, argAp0, config) + flowFwdIsEntered(call, cc, argAp, argAp0, config) ) ) } +pragma[nomagic] +private predicate flowFwdLocalEntry( + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + LocalCallContext localCC, Configuration config +) { + flowFwd(node, cc, argAp, apf, ap, config) and + localFlowEntry(node, config) and + localCC = getLocalCallContext(cc, node.getEnclosingCallable()) +} + pragma[nomagic] private predicate flowFwdStore( - Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, AccessPathFront apf0 | - flowFwd(mid, fromArg, argAp, apf0, ap0, config) and + flowFwd(mid, cc, argAp, apf0, ap0, config) and flowFwdStore0(mid, tc, node, apf0, apf, config) ) } @@ -1764,20 +1775,20 @@ private predicate flowFwdStore0( pragma[nomagic] private predicate flowFwdRead0( - Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, - boolean fromArg, AccessPathOption argAp, Configuration config + Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc, + AccessPathOption argAp, Configuration config ) { - flowFwd(node1, fromArg, argAp, apf0, ap0, config) and + flowFwd(node1, cc, argAp, apf0, ap0, config) and readCandFwd(node1, tc, apf0, node2, config) } pragma[nomagic] private predicate flowFwdRead( - Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, TypedContent tc | - flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and + flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and flowCand(node, _, _, apf, unbind(config)) and flowCandConsCand(tc, apf, unbind(config)) ) @@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - exists(ArgumentNode arg, boolean allowsFieldFlow | - flowFwd(arg, fromArg, argAp, apf, ap, config) and + exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | + flowFwd(arg, outercc, argAp, apf, ap, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and - flowCand(p, _, _, _, unbind(config)) + c = p.getEnclosingCallable() and + c = resolveCall(call, outercc) and + flowCand(p, _, _, _, unbind(config)) and + if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall() | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1809,13 +1823,19 @@ private predicate flowFwdIn( pragma[nomagic] private predicate flowFwdOut( - DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ReturnNodeExt ret, boolean allowsFieldFlow | - flowFwd(ret, fromArg, argAp, apf, ap, config) and + flowFwd(ret, innercc, argAp, apf, ap, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and - flowCand(node, _, _, _, unbind(config)) + innerc = ret.getEnclosingCallable() and + flowCand(node, _, _, _, unbind(config)) and + ( + resolveReturn(innercc, innerc, call) + or + innercc.(CallContextCall).matchesCall(call) + ) | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg( DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) + flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config) } /** @@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg( */ pragma[nomagic] private predicate flowFwdIsEntered( - DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config + DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and + flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } @@ -1920,7 +1940,7 @@ private predicate flow0( // flow out of a callable flowOut(_, node, _, _, ap, config) and toReturn = true and - if flowFwd(node, true, TAccessPathSome(_), _, ap, config) + if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config) then returnAp = TAccessPathSome(ap) else returnAp = TAccessPathNone() } @@ -2006,9 +2026,10 @@ private predicate flowIsReturned( DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, Configuration config ) { - exists(ReturnNodeExt ret | + exists(ReturnNodeExt ret, CallContextCall ccc | flowOut(call, ret, toReturn, returnAp, ap, config) and - flowFwd(ret, true, TAccessPathSome(_), _, ap, config) + flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and + ccc.matchesCall(call) ) } @@ -2031,7 +2052,7 @@ private newtype TSummaryCtx = exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | parameterFlow(p, ap, ret.getEnclosingCallable(), config) and flow(ret, true, TAccessPathSome(_), ap0, config) and - flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) + flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config) ) } @@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0( ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } @@ -2867,7 +2888,7 @@ private module FlowExploration { ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll index 5042dce683f..4e6eb9d86c0 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { * Holds if `node` can be the first node in a maximal subsequence of local * flow steps in a dataflow path. */ - private predicate localFlowEntry(Node node, Configuration config) { + predicate localFlowEntry(Node node, Configuration config) { nodeCand2(node, config) and ( config.isSource(node) or @@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption { * Holds if `node` is reachable with access path `ap` from a source in * the configuration `config`. * - * The Boolean `fromArg` records whether the node is reached through an + * The call context `cc` records whether the node is reached through an * argument in a call, and if so, `argAp` records the access path of that * argument. */ private predicate flowFwd( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwd0(node, fromArg, argAp, apf, ap, config) and + flowFwd0(node, cc, argAp, apf, ap, config) and flowCand(node, _, _, apf, config) } private predicate flowFwd0( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { flowCand(node, _, _, _, config) and config.isSource(node) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() or flowCand(node, _, _, _, unbind(config)) and ( - exists(Node mid | - flowFwd(mid, fromArg, argAp, apf, ap, config) and - localFlowBigStep(mid, node, true, _, config, _) + exists(Node mid, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and + localFlowBigStep(mid, node, true, _, config, localCC) ) or - exists(Node mid, AccessPathNil nil | - flowFwd(mid, fromArg, argAp, _, nil, config) and - localFlowBigStep(mid, node, false, apf, config, _) and + exists(Node mid, AccessPathNil nil, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and + localFlowBigStep(mid, node, false, apf, config, localCC) and apf = ap.(AccessPathNil).getFront() ) or exists(Node mid | flowFwd(mid, _, _, apf, ap, config) and jumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() ) or exists(Node mid, AccessPathNil nil | flowFwd(mid, _, _, _, nil, config) and additionalJumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() @@ -1704,40 +1704,51 @@ private predicate flowFwd0( ) or // store - exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) + exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config)) or // read exists(TypedContent tc | - flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and + flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and flowFwdConsCand(tc, apf, ap, config) ) or // flow into a callable - flowFwdIn(_, node, _, _, apf, ap, config) and - fromArg = true and + flowFwdIn(_, node, cc, _, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and - fromArg = false + exists(CallContextNoCall innercc, DataFlowCallable c | + flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() + ) or exists(AccessPath argAp0 | flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and - flowFwdIsEntered(call, fromArg, argAp, argAp0, config) + flowFwdIsEntered(call, cc, argAp, argAp0, config) ) ) } +pragma[nomagic] +private predicate flowFwdLocalEntry( + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + LocalCallContext localCC, Configuration config +) { + flowFwd(node, cc, argAp, apf, ap, config) and + localFlowEntry(node, config) and + localCC = getLocalCallContext(cc, node.getEnclosingCallable()) +} + pragma[nomagic] private predicate flowFwdStore( - Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, AccessPathFront apf0 | - flowFwd(mid, fromArg, argAp, apf0, ap0, config) and + flowFwd(mid, cc, argAp, apf0, ap0, config) and flowFwdStore0(mid, tc, node, apf0, apf, config) ) } @@ -1764,20 +1775,20 @@ private predicate flowFwdStore0( pragma[nomagic] private predicate flowFwdRead0( - Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, - boolean fromArg, AccessPathOption argAp, Configuration config + Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc, + AccessPathOption argAp, Configuration config ) { - flowFwd(node1, fromArg, argAp, apf0, ap0, config) and + flowFwd(node1, cc, argAp, apf0, ap0, config) and readCandFwd(node1, tc, apf0, node2, config) } pragma[nomagic] private predicate flowFwdRead( - Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, TypedContent tc | - flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and + flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and flowCand(node, _, _, apf, unbind(config)) and flowCandConsCand(tc, apf, unbind(config)) ) @@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - exists(ArgumentNode arg, boolean allowsFieldFlow | - flowFwd(arg, fromArg, argAp, apf, ap, config) and + exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | + flowFwd(arg, outercc, argAp, apf, ap, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and - flowCand(p, _, _, _, unbind(config)) + c = p.getEnclosingCallable() and + c = resolveCall(call, outercc) and + flowCand(p, _, _, _, unbind(config)) and + if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall() | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1809,13 +1823,19 @@ private predicate flowFwdIn( pragma[nomagic] private predicate flowFwdOut( - DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ReturnNodeExt ret, boolean allowsFieldFlow | - flowFwd(ret, fromArg, argAp, apf, ap, config) and + flowFwd(ret, innercc, argAp, apf, ap, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and - flowCand(node, _, _, _, unbind(config)) + innerc = ret.getEnclosingCallable() and + flowCand(node, _, _, _, unbind(config)) and + ( + resolveReturn(innercc, innerc, call) + or + innercc.(CallContextCall).matchesCall(call) + ) | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg( DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) + flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config) } /** @@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg( */ pragma[nomagic] private predicate flowFwdIsEntered( - DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config + DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and + flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } @@ -1920,7 +1940,7 @@ private predicate flow0( // flow out of a callable flowOut(_, node, _, _, ap, config) and toReturn = true and - if flowFwd(node, true, TAccessPathSome(_), _, ap, config) + if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config) then returnAp = TAccessPathSome(ap) else returnAp = TAccessPathNone() } @@ -2006,9 +2026,10 @@ private predicate flowIsReturned( DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, Configuration config ) { - exists(ReturnNodeExt ret | + exists(ReturnNodeExt ret, CallContextCall ccc | flowOut(call, ret, toReturn, returnAp, ap, config) and - flowFwd(ret, true, TAccessPathSome(_), _, ap, config) + flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and + ccc.matchesCall(call) ) } @@ -2031,7 +2052,7 @@ private newtype TSummaryCtx = exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | parameterFlow(p, ap, ret.getEnclosingCallable(), config) and flow(ret, true, TAccessPathSome(_), ap0, config) and - flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) + flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config) ) } @@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0( ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } @@ -2867,7 +2888,7 @@ private module FlowExploration { ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll index 5042dce683f..4e6eb9d86c0 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { * Holds if `node` can be the first node in a maximal subsequence of local * flow steps in a dataflow path. */ - private predicate localFlowEntry(Node node, Configuration config) { + predicate localFlowEntry(Node node, Configuration config) { nodeCand2(node, config) and ( config.isSource(node) or @@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption { * Holds if `node` is reachable with access path `ap` from a source in * the configuration `config`. * - * The Boolean `fromArg` records whether the node is reached through an + * The call context `cc` records whether the node is reached through an * argument in a call, and if so, `argAp` records the access path of that * argument. */ private predicate flowFwd( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwd0(node, fromArg, argAp, apf, ap, config) and + flowFwd0(node, cc, argAp, apf, ap, config) and flowCand(node, _, _, apf, config) } private predicate flowFwd0( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { flowCand(node, _, _, _, config) and config.isSource(node) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() or flowCand(node, _, _, _, unbind(config)) and ( - exists(Node mid | - flowFwd(mid, fromArg, argAp, apf, ap, config) and - localFlowBigStep(mid, node, true, _, config, _) + exists(Node mid, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and + localFlowBigStep(mid, node, true, _, config, localCC) ) or - exists(Node mid, AccessPathNil nil | - flowFwd(mid, fromArg, argAp, _, nil, config) and - localFlowBigStep(mid, node, false, apf, config, _) and + exists(Node mid, AccessPathNil nil, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and + localFlowBigStep(mid, node, false, apf, config, localCC) and apf = ap.(AccessPathNil).getFront() ) or exists(Node mid | flowFwd(mid, _, _, apf, ap, config) and jumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() ) or exists(Node mid, AccessPathNil nil | flowFwd(mid, _, _, _, nil, config) and additionalJumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() @@ -1704,40 +1704,51 @@ private predicate flowFwd0( ) or // store - exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) + exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config)) or // read exists(TypedContent tc | - flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and + flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and flowFwdConsCand(tc, apf, ap, config) ) or // flow into a callable - flowFwdIn(_, node, _, _, apf, ap, config) and - fromArg = true and + flowFwdIn(_, node, cc, _, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and - fromArg = false + exists(CallContextNoCall innercc, DataFlowCallable c | + flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() + ) or exists(AccessPath argAp0 | flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and - flowFwdIsEntered(call, fromArg, argAp, argAp0, config) + flowFwdIsEntered(call, cc, argAp, argAp0, config) ) ) } +pragma[nomagic] +private predicate flowFwdLocalEntry( + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + LocalCallContext localCC, Configuration config +) { + flowFwd(node, cc, argAp, apf, ap, config) and + localFlowEntry(node, config) and + localCC = getLocalCallContext(cc, node.getEnclosingCallable()) +} + pragma[nomagic] private predicate flowFwdStore( - Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, AccessPathFront apf0 | - flowFwd(mid, fromArg, argAp, apf0, ap0, config) and + flowFwd(mid, cc, argAp, apf0, ap0, config) and flowFwdStore0(mid, tc, node, apf0, apf, config) ) } @@ -1764,20 +1775,20 @@ private predicate flowFwdStore0( pragma[nomagic] private predicate flowFwdRead0( - Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, - boolean fromArg, AccessPathOption argAp, Configuration config + Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc, + AccessPathOption argAp, Configuration config ) { - flowFwd(node1, fromArg, argAp, apf0, ap0, config) and + flowFwd(node1, cc, argAp, apf0, ap0, config) and readCandFwd(node1, tc, apf0, node2, config) } pragma[nomagic] private predicate flowFwdRead( - Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, TypedContent tc | - flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and + flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and flowCand(node, _, _, apf, unbind(config)) and flowCandConsCand(tc, apf, unbind(config)) ) @@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - exists(ArgumentNode arg, boolean allowsFieldFlow | - flowFwd(arg, fromArg, argAp, apf, ap, config) and + exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | + flowFwd(arg, outercc, argAp, apf, ap, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and - flowCand(p, _, _, _, unbind(config)) + c = p.getEnclosingCallable() and + c = resolveCall(call, outercc) and + flowCand(p, _, _, _, unbind(config)) and + if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall() | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1809,13 +1823,19 @@ private predicate flowFwdIn( pragma[nomagic] private predicate flowFwdOut( - DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ReturnNodeExt ret, boolean allowsFieldFlow | - flowFwd(ret, fromArg, argAp, apf, ap, config) and + flowFwd(ret, innercc, argAp, apf, ap, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and - flowCand(node, _, _, _, unbind(config)) + innerc = ret.getEnclosingCallable() and + flowCand(node, _, _, _, unbind(config)) and + ( + resolveReturn(innercc, innerc, call) + or + innercc.(CallContextCall).matchesCall(call) + ) | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg( DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) + flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config) } /** @@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg( */ pragma[nomagic] private predicate flowFwdIsEntered( - DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config + DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and + flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } @@ -1920,7 +1940,7 @@ private predicate flow0( // flow out of a callable flowOut(_, node, _, _, ap, config) and toReturn = true and - if flowFwd(node, true, TAccessPathSome(_), _, ap, config) + if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config) then returnAp = TAccessPathSome(ap) else returnAp = TAccessPathNone() } @@ -2006,9 +2026,10 @@ private predicate flowIsReturned( DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, Configuration config ) { - exists(ReturnNodeExt ret | + exists(ReturnNodeExt ret, CallContextCall ccc | flowOut(call, ret, toReturn, returnAp, ap, config) and - flowFwd(ret, true, TAccessPathSome(_), _, ap, config) + flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and + ccc.matchesCall(call) ) } @@ -2031,7 +2052,7 @@ private newtype TSummaryCtx = exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | parameterFlow(p, ap, ret.getEnclosingCallable(), config) and flow(ret, true, TAccessPathSome(_), ap0, config) and - flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) + flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config) ) } @@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0( ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } @@ -2867,7 +2888,7 @@ private module FlowExploration { ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll index 5042dce683f..4e6eb9d86c0 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { * Holds if `node` can be the first node in a maximal subsequence of local * flow steps in a dataflow path. */ - private predicate localFlowEntry(Node node, Configuration config) { + predicate localFlowEntry(Node node, Configuration config) { nodeCand2(node, config) and ( config.isSource(node) or @@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption { * Holds if `node` is reachable with access path `ap` from a source in * the configuration `config`. * - * The Boolean `fromArg` records whether the node is reached through an + * The call context `cc` records whether the node is reached through an * argument in a call, and if so, `argAp` records the access path of that * argument. */ private predicate flowFwd( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwd0(node, fromArg, argAp, apf, ap, config) and + flowFwd0(node, cc, argAp, apf, ap, config) and flowCand(node, _, _, apf, config) } private predicate flowFwd0( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { flowCand(node, _, _, _, config) and config.isSource(node) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() or flowCand(node, _, _, _, unbind(config)) and ( - exists(Node mid | - flowFwd(mid, fromArg, argAp, apf, ap, config) and - localFlowBigStep(mid, node, true, _, config, _) + exists(Node mid, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and + localFlowBigStep(mid, node, true, _, config, localCC) ) or - exists(Node mid, AccessPathNil nil | - flowFwd(mid, fromArg, argAp, _, nil, config) and - localFlowBigStep(mid, node, false, apf, config, _) and + exists(Node mid, AccessPathNil nil, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and + localFlowBigStep(mid, node, false, apf, config, localCC) and apf = ap.(AccessPathNil).getFront() ) or exists(Node mid | flowFwd(mid, _, _, apf, ap, config) and jumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() ) or exists(Node mid, AccessPathNil nil | flowFwd(mid, _, _, _, nil, config) and additionalJumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() @@ -1704,40 +1704,51 @@ private predicate flowFwd0( ) or // store - exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) + exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config)) or // read exists(TypedContent tc | - flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and + flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and flowFwdConsCand(tc, apf, ap, config) ) or // flow into a callable - flowFwdIn(_, node, _, _, apf, ap, config) and - fromArg = true and + flowFwdIn(_, node, cc, _, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and - fromArg = false + exists(CallContextNoCall innercc, DataFlowCallable c | + flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() + ) or exists(AccessPath argAp0 | flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and - flowFwdIsEntered(call, fromArg, argAp, argAp0, config) + flowFwdIsEntered(call, cc, argAp, argAp0, config) ) ) } +pragma[nomagic] +private predicate flowFwdLocalEntry( + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + LocalCallContext localCC, Configuration config +) { + flowFwd(node, cc, argAp, apf, ap, config) and + localFlowEntry(node, config) and + localCC = getLocalCallContext(cc, node.getEnclosingCallable()) +} + pragma[nomagic] private predicate flowFwdStore( - Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, AccessPathFront apf0 | - flowFwd(mid, fromArg, argAp, apf0, ap0, config) and + flowFwd(mid, cc, argAp, apf0, ap0, config) and flowFwdStore0(mid, tc, node, apf0, apf, config) ) } @@ -1764,20 +1775,20 @@ private predicate flowFwdStore0( pragma[nomagic] private predicate flowFwdRead0( - Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, - boolean fromArg, AccessPathOption argAp, Configuration config + Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc, + AccessPathOption argAp, Configuration config ) { - flowFwd(node1, fromArg, argAp, apf0, ap0, config) and + flowFwd(node1, cc, argAp, apf0, ap0, config) and readCandFwd(node1, tc, apf0, node2, config) } pragma[nomagic] private predicate flowFwdRead( - Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, TypedContent tc | - flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and + flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and flowCand(node, _, _, apf, unbind(config)) and flowCandConsCand(tc, apf, unbind(config)) ) @@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - exists(ArgumentNode arg, boolean allowsFieldFlow | - flowFwd(arg, fromArg, argAp, apf, ap, config) and + exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | + flowFwd(arg, outercc, argAp, apf, ap, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and - flowCand(p, _, _, _, unbind(config)) + c = p.getEnclosingCallable() and + c = resolveCall(call, outercc) and + flowCand(p, _, _, _, unbind(config)) and + if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall() | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1809,13 +1823,19 @@ private predicate flowFwdIn( pragma[nomagic] private predicate flowFwdOut( - DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ReturnNodeExt ret, boolean allowsFieldFlow | - flowFwd(ret, fromArg, argAp, apf, ap, config) and + flowFwd(ret, innercc, argAp, apf, ap, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and - flowCand(node, _, _, _, unbind(config)) + innerc = ret.getEnclosingCallable() and + flowCand(node, _, _, _, unbind(config)) and + ( + resolveReturn(innercc, innerc, call) + or + innercc.(CallContextCall).matchesCall(call) + ) | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg( DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) + flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config) } /** @@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg( */ pragma[nomagic] private predicate flowFwdIsEntered( - DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config + DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and + flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } @@ -1920,7 +1940,7 @@ private predicate flow0( // flow out of a callable flowOut(_, node, _, _, ap, config) and toReturn = true and - if flowFwd(node, true, TAccessPathSome(_), _, ap, config) + if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config) then returnAp = TAccessPathSome(ap) else returnAp = TAccessPathNone() } @@ -2006,9 +2026,10 @@ private predicate flowIsReturned( DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, Configuration config ) { - exists(ReturnNodeExt ret | + exists(ReturnNodeExt ret, CallContextCall ccc | flowOut(call, ret, toReturn, returnAp, ap, config) and - flowFwd(ret, true, TAccessPathSome(_), _, ap, config) + flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and + ccc.matchesCall(call) ) } @@ -2031,7 +2052,7 @@ private newtype TSummaryCtx = exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | parameterFlow(p, ap, ret.getEnclosingCallable(), config) and flow(ret, true, TAccessPathSome(_), ap0, config) and - flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) + flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config) ) } @@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0( ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } @@ -2867,7 +2888,7 @@ private module FlowExploration { ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll index 5042dce683f..4e6eb9d86c0 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { * Holds if `node` can be the first node in a maximal subsequence of local * flow steps in a dataflow path. */ - private predicate localFlowEntry(Node node, Configuration config) { + predicate localFlowEntry(Node node, Configuration config) { nodeCand2(node, config) and ( config.isSource(node) or @@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption { * Holds if `node` is reachable with access path `ap` from a source in * the configuration `config`. * - * The Boolean `fromArg` records whether the node is reached through an + * The call context `cc` records whether the node is reached through an * argument in a call, and if so, `argAp` records the access path of that * argument. */ private predicate flowFwd( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwd0(node, fromArg, argAp, apf, ap, config) and + flowFwd0(node, cc, argAp, apf, ap, config) and flowCand(node, _, _, apf, config) } private predicate flowFwd0( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { flowCand(node, _, _, _, config) and config.isSource(node) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() or flowCand(node, _, _, _, unbind(config)) and ( - exists(Node mid | - flowFwd(mid, fromArg, argAp, apf, ap, config) and - localFlowBigStep(mid, node, true, _, config, _) + exists(Node mid, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and + localFlowBigStep(mid, node, true, _, config, localCC) ) or - exists(Node mid, AccessPathNil nil | - flowFwd(mid, fromArg, argAp, _, nil, config) and - localFlowBigStep(mid, node, false, apf, config, _) and + exists(Node mid, AccessPathNil nil, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and + localFlowBigStep(mid, node, false, apf, config, localCC) and apf = ap.(AccessPathNil).getFront() ) or exists(Node mid | flowFwd(mid, _, _, apf, ap, config) and jumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() ) or exists(Node mid, AccessPathNil nil | flowFwd(mid, _, _, _, nil, config) and additionalJumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() @@ -1704,40 +1704,51 @@ private predicate flowFwd0( ) or // store - exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) + exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config)) or // read exists(TypedContent tc | - flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and + flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and flowFwdConsCand(tc, apf, ap, config) ) or // flow into a callable - flowFwdIn(_, node, _, _, apf, ap, config) and - fromArg = true and + flowFwdIn(_, node, cc, _, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and - fromArg = false + exists(CallContextNoCall innercc, DataFlowCallable c | + flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() + ) or exists(AccessPath argAp0 | flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and - flowFwdIsEntered(call, fromArg, argAp, argAp0, config) + flowFwdIsEntered(call, cc, argAp, argAp0, config) ) ) } +pragma[nomagic] +private predicate flowFwdLocalEntry( + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + LocalCallContext localCC, Configuration config +) { + flowFwd(node, cc, argAp, apf, ap, config) and + localFlowEntry(node, config) and + localCC = getLocalCallContext(cc, node.getEnclosingCallable()) +} + pragma[nomagic] private predicate flowFwdStore( - Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, AccessPathFront apf0 | - flowFwd(mid, fromArg, argAp, apf0, ap0, config) and + flowFwd(mid, cc, argAp, apf0, ap0, config) and flowFwdStore0(mid, tc, node, apf0, apf, config) ) } @@ -1764,20 +1775,20 @@ private predicate flowFwdStore0( pragma[nomagic] private predicate flowFwdRead0( - Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, - boolean fromArg, AccessPathOption argAp, Configuration config + Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc, + AccessPathOption argAp, Configuration config ) { - flowFwd(node1, fromArg, argAp, apf0, ap0, config) and + flowFwd(node1, cc, argAp, apf0, ap0, config) and readCandFwd(node1, tc, apf0, node2, config) } pragma[nomagic] private predicate flowFwdRead( - Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, TypedContent tc | - flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and + flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and flowCand(node, _, _, apf, unbind(config)) and flowCandConsCand(tc, apf, unbind(config)) ) @@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - exists(ArgumentNode arg, boolean allowsFieldFlow | - flowFwd(arg, fromArg, argAp, apf, ap, config) and + exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | + flowFwd(arg, outercc, argAp, apf, ap, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and - flowCand(p, _, _, _, unbind(config)) + c = p.getEnclosingCallable() and + c = resolveCall(call, outercc) and + flowCand(p, _, _, _, unbind(config)) and + if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall() | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1809,13 +1823,19 @@ private predicate flowFwdIn( pragma[nomagic] private predicate flowFwdOut( - DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ReturnNodeExt ret, boolean allowsFieldFlow | - flowFwd(ret, fromArg, argAp, apf, ap, config) and + flowFwd(ret, innercc, argAp, apf, ap, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and - flowCand(node, _, _, _, unbind(config)) + innerc = ret.getEnclosingCallable() and + flowCand(node, _, _, _, unbind(config)) and + ( + resolveReturn(innercc, innerc, call) + or + innercc.(CallContextCall).matchesCall(call) + ) | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg( DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) + flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config) } /** @@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg( */ pragma[nomagic] private predicate flowFwdIsEntered( - DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config + DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and + flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } @@ -1920,7 +1940,7 @@ private predicate flow0( // flow out of a callable flowOut(_, node, _, _, ap, config) and toReturn = true and - if flowFwd(node, true, TAccessPathSome(_), _, ap, config) + if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config) then returnAp = TAccessPathSome(ap) else returnAp = TAccessPathNone() } @@ -2006,9 +2026,10 @@ private predicate flowIsReturned( DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, Configuration config ) { - exists(ReturnNodeExt ret | + exists(ReturnNodeExt ret, CallContextCall ccc | flowOut(call, ret, toReturn, returnAp, ap, config) and - flowFwd(ret, true, TAccessPathSome(_), _, ap, config) + flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and + ccc.matchesCall(call) ) } @@ -2031,7 +2052,7 @@ private newtype TSummaryCtx = exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | parameterFlow(p, ap, ret.getEnclosingCallable(), config) and flow(ret, true, TAccessPathSome(_), ap0, config) and - flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) + flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config) ) } @@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0( ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } @@ -2867,7 +2888,7 @@ private module FlowExploration { ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll index 27ab1d01feb..892250f44bb 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll @@ -512,13 +512,19 @@ abstract class CallContext extends TCallContext { abstract predicate relevantFor(DataFlowCallable callable); } -class CallContextAny extends CallContext, TAnyCallContext { +abstract class CallContextNoCall extends CallContext { } + +class CallContextAny extends CallContextNoCall, TAnyCallContext { override string toString() { result = "CcAny" } override predicate relevantFor(DataFlowCallable callable) { any() } } -abstract class CallContextCall extends CallContext { } +abstract class CallContextCall extends CallContext { + /** Holds if this call context may be `call`. */ + bindingset[call] + abstract predicate matchesCall(DataFlowCall call); +} class CallContextSpecificCall extends CallContextCall, TSpecificCall { override string toString() { @@ -529,6 +535,8 @@ class CallContextSpecificCall extends CallContextCall, TSpecificCall { recordDataFlowCallSite(getCall(), callable) } + override predicate matchesCall(DataFlowCall call) { call = this.getCall() } + DataFlowCall getCall() { this = TSpecificCall(result) } } @@ -538,9 +546,11 @@ class CallContextSomeCall extends CallContextCall, TSomeCall { override predicate relevantFor(DataFlowCallable callable) { exists(ParameterNode p | p.getEnclosingCallable() = callable) } + + override predicate matchesCall(DataFlowCall call) { any() } } -class CallContextReturn extends CallContext, TReturn { +class CallContextReturn extends CallContextNoCall, TReturn { override string toString() { exists(DataFlowCall call | this = TReturn(_, call) | result = "CcReturn(" + call + ")") } From e518cbabd678557352bcc83b8238ac6afcedf588 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 29 Jul 2020 09:44:33 +0200 Subject: [PATCH 074/133] Python: Sync data flow files --- .../dataflow/internal/DataFlowImpl.qll | 113 +++++++++++------- .../dataflow/internal/DataFlowImpl2.qll | 113 +++++++++++------- .../dataflow/internal/DataFlowImplCommon.qll | 16 ++- 3 files changed, 147 insertions(+), 95 deletions(-) diff --git a/python/ql/src/experimental/dataflow/internal/DataFlowImpl.qll b/python/ql/src/experimental/dataflow/internal/DataFlowImpl.qll index 5042dce683f..4e6eb9d86c0 100644 --- a/python/ql/src/experimental/dataflow/internal/DataFlowImpl.qll +++ b/python/ql/src/experimental/dataflow/internal/DataFlowImpl.qll @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { * Holds if `node` can be the first node in a maximal subsequence of local * flow steps in a dataflow path. */ - private predicate localFlowEntry(Node node, Configuration config) { + predicate localFlowEntry(Node node, Configuration config) { nodeCand2(node, config) and ( config.isSource(node) or @@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption { * Holds if `node` is reachable with access path `ap` from a source in * the configuration `config`. * - * The Boolean `fromArg` records whether the node is reached through an + * The call context `cc` records whether the node is reached through an * argument in a call, and if so, `argAp` records the access path of that * argument. */ private predicate flowFwd( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwd0(node, fromArg, argAp, apf, ap, config) and + flowFwd0(node, cc, argAp, apf, ap, config) and flowCand(node, _, _, apf, config) } private predicate flowFwd0( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { flowCand(node, _, _, _, config) and config.isSource(node) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() or flowCand(node, _, _, _, unbind(config)) and ( - exists(Node mid | - flowFwd(mid, fromArg, argAp, apf, ap, config) and - localFlowBigStep(mid, node, true, _, config, _) + exists(Node mid, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and + localFlowBigStep(mid, node, true, _, config, localCC) ) or - exists(Node mid, AccessPathNil nil | - flowFwd(mid, fromArg, argAp, _, nil, config) and - localFlowBigStep(mid, node, false, apf, config, _) and + exists(Node mid, AccessPathNil nil, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and + localFlowBigStep(mid, node, false, apf, config, localCC) and apf = ap.(AccessPathNil).getFront() ) or exists(Node mid | flowFwd(mid, _, _, apf, ap, config) and jumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() ) or exists(Node mid, AccessPathNil nil | flowFwd(mid, _, _, _, nil, config) and additionalJumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() @@ -1704,40 +1704,51 @@ private predicate flowFwd0( ) or // store - exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) + exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config)) or // read exists(TypedContent tc | - flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and + flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and flowFwdConsCand(tc, apf, ap, config) ) or // flow into a callable - flowFwdIn(_, node, _, _, apf, ap, config) and - fromArg = true and + flowFwdIn(_, node, cc, _, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and - fromArg = false + exists(CallContextNoCall innercc, DataFlowCallable c | + flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() + ) or exists(AccessPath argAp0 | flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and - flowFwdIsEntered(call, fromArg, argAp, argAp0, config) + flowFwdIsEntered(call, cc, argAp, argAp0, config) ) ) } +pragma[nomagic] +private predicate flowFwdLocalEntry( + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + LocalCallContext localCC, Configuration config +) { + flowFwd(node, cc, argAp, apf, ap, config) and + localFlowEntry(node, config) and + localCC = getLocalCallContext(cc, node.getEnclosingCallable()) +} + pragma[nomagic] private predicate flowFwdStore( - Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, AccessPathFront apf0 | - flowFwd(mid, fromArg, argAp, apf0, ap0, config) and + flowFwd(mid, cc, argAp, apf0, ap0, config) and flowFwdStore0(mid, tc, node, apf0, apf, config) ) } @@ -1764,20 +1775,20 @@ private predicate flowFwdStore0( pragma[nomagic] private predicate flowFwdRead0( - Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, - boolean fromArg, AccessPathOption argAp, Configuration config + Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc, + AccessPathOption argAp, Configuration config ) { - flowFwd(node1, fromArg, argAp, apf0, ap0, config) and + flowFwd(node1, cc, argAp, apf0, ap0, config) and readCandFwd(node1, tc, apf0, node2, config) } pragma[nomagic] private predicate flowFwdRead( - Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, TypedContent tc | - flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and + flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and flowCand(node, _, _, apf, unbind(config)) and flowCandConsCand(tc, apf, unbind(config)) ) @@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - exists(ArgumentNode arg, boolean allowsFieldFlow | - flowFwd(arg, fromArg, argAp, apf, ap, config) and + exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | + flowFwd(arg, outercc, argAp, apf, ap, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and - flowCand(p, _, _, _, unbind(config)) + c = p.getEnclosingCallable() and + c = resolveCall(call, outercc) and + flowCand(p, _, _, _, unbind(config)) and + if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall() | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1809,13 +1823,19 @@ private predicate flowFwdIn( pragma[nomagic] private predicate flowFwdOut( - DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ReturnNodeExt ret, boolean allowsFieldFlow | - flowFwd(ret, fromArg, argAp, apf, ap, config) and + flowFwd(ret, innercc, argAp, apf, ap, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and - flowCand(node, _, _, _, unbind(config)) + innerc = ret.getEnclosingCallable() and + flowCand(node, _, _, _, unbind(config)) and + ( + resolveReturn(innercc, innerc, call) + or + innercc.(CallContextCall).matchesCall(call) + ) | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg( DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) + flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config) } /** @@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg( */ pragma[nomagic] private predicate flowFwdIsEntered( - DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config + DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and + flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } @@ -1920,7 +1940,7 @@ private predicate flow0( // flow out of a callable flowOut(_, node, _, _, ap, config) and toReturn = true and - if flowFwd(node, true, TAccessPathSome(_), _, ap, config) + if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config) then returnAp = TAccessPathSome(ap) else returnAp = TAccessPathNone() } @@ -2006,9 +2026,10 @@ private predicate flowIsReturned( DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, Configuration config ) { - exists(ReturnNodeExt ret | + exists(ReturnNodeExt ret, CallContextCall ccc | flowOut(call, ret, toReturn, returnAp, ap, config) and - flowFwd(ret, true, TAccessPathSome(_), _, ap, config) + flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and + ccc.matchesCall(call) ) } @@ -2031,7 +2052,7 @@ private newtype TSummaryCtx = exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | parameterFlow(p, ap, ret.getEnclosingCallable(), config) and flow(ret, true, TAccessPathSome(_), ap0, config) and - flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) + flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config) ) } @@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0( ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } @@ -2867,7 +2888,7 @@ private module FlowExploration { ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } diff --git a/python/ql/src/experimental/dataflow/internal/DataFlowImpl2.qll b/python/ql/src/experimental/dataflow/internal/DataFlowImpl2.qll index 5042dce683f..4e6eb9d86c0 100644 --- a/python/ql/src/experimental/dataflow/internal/DataFlowImpl2.qll +++ b/python/ql/src/experimental/dataflow/internal/DataFlowImpl2.qll @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { * Holds if `node` can be the first node in a maximal subsequence of local * flow steps in a dataflow path. */ - private predicate localFlowEntry(Node node, Configuration config) { + predicate localFlowEntry(Node node, Configuration config) { nodeCand2(node, config) and ( config.isSource(node) or @@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption { * Holds if `node` is reachable with access path `ap` from a source in * the configuration `config`. * - * The Boolean `fromArg` records whether the node is reached through an + * The call context `cc` records whether the node is reached through an * argument in a call, and if so, `argAp` records the access path of that * argument. */ private predicate flowFwd( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwd0(node, fromArg, argAp, apf, ap, config) and + flowFwd0(node, cc, argAp, apf, ap, config) and flowCand(node, _, _, apf, config) } private predicate flowFwd0( - Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { flowCand(node, _, _, _, config) and config.isSource(node) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() or flowCand(node, _, _, _, unbind(config)) and ( - exists(Node mid | - flowFwd(mid, fromArg, argAp, apf, ap, config) and - localFlowBigStep(mid, node, true, _, config, _) + exists(Node mid, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and + localFlowBigStep(mid, node, true, _, config, localCC) ) or - exists(Node mid, AccessPathNil nil | - flowFwd(mid, fromArg, argAp, _, nil, config) and - localFlowBigStep(mid, node, false, apf, config, _) and + exists(Node mid, AccessPathNil nil, LocalCallContext localCC | + flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and + localFlowBigStep(mid, node, false, apf, config, localCC) and apf = ap.(AccessPathNil).getFront() ) or exists(Node mid | flowFwd(mid, _, _, apf, ap, config) and jumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() ) or exists(Node mid, AccessPathNil nil | flowFwd(mid, _, _, _, nil, config) and additionalJumpStep(mid, node, config) and - fromArg = false and + cc instanceof CallContextAny and argAp = TAccessPathNone() and ap = TNil(getNodeType(node)) and apf = ap.(AccessPathNil).getFront() @@ -1704,40 +1704,51 @@ private predicate flowFwd0( ) or // store - exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) + exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config)) or // read exists(TypedContent tc | - flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and + flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and flowFwdConsCand(tc, apf, ap, config) ) or // flow into a callable - flowFwdIn(_, node, _, _, apf, ap, config) and - fromArg = true and + flowFwdIn(_, node, cc, _, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and - fromArg = false + exists(CallContextNoCall innercc, DataFlowCallable c | + flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() + ) or exists(AccessPath argAp0 | flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and - flowFwdIsEntered(call, fromArg, argAp, argAp0, config) + flowFwdIsEntered(call, cc, argAp, argAp0, config) ) ) } +pragma[nomagic] +private predicate flowFwdLocalEntry( + Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, + LocalCallContext localCC, Configuration config +) { + flowFwd(node, cc, argAp, apf, ap, config) and + localFlowEntry(node, config) and + localCC = getLocalCallContext(cc, node.getEnclosingCallable()) +} + pragma[nomagic] private predicate flowFwdStore( - Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, AccessPathFront apf0 | - flowFwd(mid, fromArg, argAp, apf0, ap0, config) and + flowFwd(mid, cc, argAp, apf0, ap0, config) and flowFwdStore0(mid, tc, node, apf0, apf, config) ) } @@ -1764,20 +1775,20 @@ private predicate flowFwdStore0( pragma[nomagic] private predicate flowFwdRead0( - Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, - boolean fromArg, AccessPathOption argAp, Configuration config + Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc, + AccessPathOption argAp, Configuration config ) { - flowFwd(node1, fromArg, argAp, apf0, ap0, config) and + flowFwd(node1, cc, argAp, apf0, ap0, config) and readCandFwd(node1, tc, apf0, node2, config) } pragma[nomagic] private predicate flowFwdRead( - Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, + Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc, AccessPathOption argAp, Configuration config ) { exists(Node mid, TypedContent tc | - flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and + flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and flowCand(node, _, _, apf, unbind(config)) and flowCandConsCand(tc, apf, unbind(config)) ) @@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - exists(ArgumentNode arg, boolean allowsFieldFlow | - flowFwd(arg, fromArg, argAp, apf, ap, config) and + exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | + flowFwd(arg, outercc, argAp, apf, ap, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and - flowCand(p, _, _, _, unbind(config)) + c = p.getEnclosingCallable() and + c = resolveCall(call, outercc) and + flowCand(p, _, _, _, unbind(config)) and + if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall() | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1809,13 +1823,19 @@ private predicate flowFwdIn( pragma[nomagic] private predicate flowFwdOut( - DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, - AccessPath ap, Configuration config + DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc, + AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ReturnNodeExt ret, boolean allowsFieldFlow | - flowFwd(ret, fromArg, argAp, apf, ap, config) and + flowFwd(ret, innercc, argAp, apf, ap, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and - flowCand(node, _, _, _, unbind(config)) + innerc = ret.getEnclosingCallable() and + flowCand(node, _, _, _, unbind(config)) and + ( + resolveReturn(innercc, innerc, call) + or + innercc.(CallContextCall).matchesCall(call) + ) | ap instanceof AccessPathNil or allowsFieldFlow = true ) @@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg( DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { - flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) + flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config) } /** @@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg( */ pragma[nomagic] private predicate flowFwdIsEntered( - DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config + DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and + flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } @@ -1920,7 +1940,7 @@ private predicate flow0( // flow out of a callable flowOut(_, node, _, _, ap, config) and toReturn = true and - if flowFwd(node, true, TAccessPathSome(_), _, ap, config) + if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config) then returnAp = TAccessPathSome(ap) else returnAp = TAccessPathNone() } @@ -2006,9 +2026,10 @@ private predicate flowIsReturned( DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, Configuration config ) { - exists(ReturnNodeExt ret | + exists(ReturnNodeExt ret, CallContextCall ccc | flowOut(call, ret, toReturn, returnAp, ap, config) and - flowFwd(ret, true, TAccessPathSome(_), _, ap, config) + flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and + ccc.matchesCall(call) ) } @@ -2031,7 +2052,7 @@ private newtype TSummaryCtx = exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | parameterFlow(p, ap, ret.getEnclosingCallable(), config) and flow(ret, true, TAccessPathSome(_), ap0, config) and - flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) + flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config) ) } @@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0( ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } @@ -2867,7 +2888,7 @@ private module FlowExploration { ) { pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and - not innercc instanceof CallContextCall and + innercc instanceof CallContextNoCall and ap = mid.getAp() and config = mid.getConfiguration() } diff --git a/python/ql/src/experimental/dataflow/internal/DataFlowImplCommon.qll b/python/ql/src/experimental/dataflow/internal/DataFlowImplCommon.qll index 27ab1d01feb..892250f44bb 100644 --- a/python/ql/src/experimental/dataflow/internal/DataFlowImplCommon.qll +++ b/python/ql/src/experimental/dataflow/internal/DataFlowImplCommon.qll @@ -512,13 +512,19 @@ abstract class CallContext extends TCallContext { abstract predicate relevantFor(DataFlowCallable callable); } -class CallContextAny extends CallContext, TAnyCallContext { +abstract class CallContextNoCall extends CallContext { } + +class CallContextAny extends CallContextNoCall, TAnyCallContext { override string toString() { result = "CcAny" } override predicate relevantFor(DataFlowCallable callable) { any() } } -abstract class CallContextCall extends CallContext { } +abstract class CallContextCall extends CallContext { + /** Holds if this call context may be `call`. */ + bindingset[call] + abstract predicate matchesCall(DataFlowCall call); +} class CallContextSpecificCall extends CallContextCall, TSpecificCall { override string toString() { @@ -529,6 +535,8 @@ class CallContextSpecificCall extends CallContextCall, TSpecificCall { recordDataFlowCallSite(getCall(), callable) } + override predicate matchesCall(DataFlowCall call) { call = this.getCall() } + DataFlowCall getCall() { this = TSpecificCall(result) } } @@ -538,9 +546,11 @@ class CallContextSomeCall extends CallContextCall, TSomeCall { override predicate relevantFor(DataFlowCallable callable) { exists(ParameterNode p | p.getEnclosingCallable() = callable) } + + override predicate matchesCall(DataFlowCall call) { any() } } -class CallContextReturn extends CallContext, TReturn { +class CallContextReturn extends CallContextNoCall, TReturn { override string toString() { exists(DataFlowCall call | this = TReturn(_, call) | result = "CcReturn(" + call + ")") } From 9556937840999239728c141e6549655b5f599795 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Fri, 14 Aug 2020 11:29:58 +0200 Subject: [PATCH 075/133] Python: address review comments --- python/ql/test/experimental/dataflow/coverage/classes.py | 4 +++- .../test/experimental/dataflow/coverage/classesCallGraph.ql | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/python/ql/test/experimental/dataflow/coverage/classes.py b/python/ql/test/experimental/dataflow/coverage/classes.py index f6b39527443..de06d284361 100644 --- a/python/ql/test/experimental/dataflow/coverage/classes.py +++ b/python/ql/test/experimental/dataflow/coverage/classes.py @@ -1041,7 +1041,9 @@ def test_index(): with_index = With_index() operator.index(with_index) -# make With_index subscriptable to test slicing +def test_index_slicing(): + with_index = With_index() + [0][with_index:1] def test_index_bin(): with_index = With_index() diff --git a/python/ql/test/experimental/dataflow/coverage/classesCallGraph.ql b/python/ql/test/experimental/dataflow/coverage/classesCallGraph.ql index 0416cc7f6ea..1445e314c98 100644 --- a/python/ql/test/experimental/dataflow/coverage/classesCallGraph.ql +++ b/python/ql/test/experimental/dataflow/coverage/classesCallGraph.ql @@ -6,4 +6,5 @@ where sink.getLocation().getFile().getBaseName() = "classes.py" and exists(CallGraphConfig cfg | cfg.hasFlow(source, sink)) select source, sink -// Rewrite this to just have 1-step paths? +// Ideally, we would just have 1-step paths either from argument to parameter +// or from return to call. This gives a bit more, so should be rewritten. From aa78c6e750f21fca420d5fa053b78a53525a9b8c Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Thu, 13 Aug 2020 16:12:43 +0200 Subject: [PATCH 076/133] C++: Move to experimental And rename to `SimpleRangeAnalysisExpr` to clarify which of our range analysis libraries this belongs to. --- .../interfaces/SimpleRangeAnalysisExpr.qll} | 4 ++-- .../cpp/rangeanalysis/SimpleRangeAnalysis.qll | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) rename cpp/ql/src/{semmle/code/cpp/models/interfaces/RangeAnalysisExpr.qll => experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisExpr.qll} (89%) diff --git a/cpp/ql/src/semmle/code/cpp/models/interfaces/RangeAnalysisExpr.qll b/cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisExpr.qll similarity index 89% rename from cpp/ql/src/semmle/code/cpp/models/interfaces/RangeAnalysisExpr.qll rename to cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisExpr.qll index ac1ba558c09..94ac4cf91a7 100644 --- a/cpp/ql/src/semmle/code/cpp/models/interfaces/RangeAnalysisExpr.qll +++ b/cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisExpr.qll @@ -6,11 +6,11 @@ import cpp /** * An expression for which a range can be deduced. */ -abstract class RangeAnalysisExpr extends Expr { +abstract class SimpleRangeAnalysisExpr extends Expr { /** Gets the lower bound of the expression. */ abstract float getLowerBounds(); /** Gets the upper bound of the expression. */ abstract float getUpperBounds(); /** Holds if this expression depends on the definition `srcDef` for StackVariable `srcVar`. */ predicate dependsOnDef(RangeSsaDefinition srcDef, StackVariable srcVar) { none() } -} \ No newline at end of file +} diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll index 66ea1479b18..3bcd48e68e3 100644 --- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll @@ -44,7 +44,7 @@ import cpp private import RangeAnalysisUtils -private import semmle.code.cpp.models.interfaces.RangeAnalysisExpr +private import experimental.semmle.code.cpp.models.interfaces.SimpleRangeAnalysisExpr import RangeSSA import SimpleRangeAnalysisCached private import NanAnalysis @@ -216,7 +216,7 @@ private predicate analyzableExpr(Expr e) { exists(e.(RShiftExpr).getRightOperand().getValue()) or // A modeled expression for range analysis - e instanceof RangeAnalysisExpr + e instanceof SimpleRangeAnalysisExpr ) } @@ -334,7 +334,7 @@ private predicate exprDependsOnDef(Expr e, RangeSsaDefinition srcDef, StackVaria e = srcDef.getAUse(srcVar) or // A modeled expression for range analysis - exists(RangeAnalysisExpr rae | + exists(SimpleRangeAnalysisExpr rae | rae.dependsOnDef(srcDef, srcVar) ) } @@ -738,8 +738,8 @@ private float getLowerBoundsImpl(Expr expr) { // Use SSA to get the lower bounds for a variable use. exists(RangeSsaDefinition def, StackVariable v | expr = def.getAUse(v) | result = getDefLowerBounds(def, v) and - // Not explicitly modeled by a RangeAnalysisExpr - not expr instanceof RangeAnalysisExpr + // Not explicitly modeled by a SimpleRangeAnalysisExpr + not expr instanceof SimpleRangeAnalysisExpr ) or // unsigned `&` (tighter bounds may exist) @@ -757,7 +757,7 @@ private float getLowerBoundsImpl(Expr expr) { ) or // A modeled expression for range analysis - exists(RangeAnalysisExpr rangeAnalysisExpr | + exists(SimpleRangeAnalysisExpr rangeAnalysisExpr | rangeAnalysisExpr = expr and result = rangeAnalysisExpr.getLowerBounds() ) @@ -920,8 +920,8 @@ private float getUpperBoundsImpl(Expr expr) { // Use SSA to get the upper bounds for a variable use. exists(RangeSsaDefinition def, StackVariable v | expr = def.getAUse(v) | result = getDefUpperBounds(def, v) and - // Not explicitly modeled by a RangeAnalysisExpr - not expr instanceof RangeAnalysisExpr + // Not explicitly modeled by a SimpleRangeAnalysisExpr + not expr instanceof SimpleRangeAnalysisExpr ) or // unsigned `&` (tighter bounds may exist) @@ -941,7 +941,7 @@ private float getUpperBoundsImpl(Expr expr) { ) or // A modeled expression for range analysis - exists(RangeAnalysisExpr rangeAnalysisExpr | + exists(SimpleRangeAnalysisExpr rangeAnalysisExpr | rangeAnalysisExpr = expr and result = rangeAnalysisExpr.getUpperBounds() ) From 1c0e83a374698a63e2ddf5274cd413732d92c492 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Thu, 13 Aug 2020 16:14:23 +0200 Subject: [PATCH 077/133] C++: Autoformat fixup --- .../code/cpp/models/interfaces/SimpleRangeAnalysisExpr.qll | 3 +++ .../src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll | 4 +--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisExpr.qll b/cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisExpr.qll index 94ac4cf91a7..40f2fe9e773 100644 --- a/cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisExpr.qll +++ b/cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisExpr.qll @@ -1,6 +1,7 @@ /** * Provides a class for modeling `Expr`s with a restricted range. */ + import cpp /** @@ -9,8 +10,10 @@ import cpp abstract class SimpleRangeAnalysisExpr extends Expr { /** Gets the lower bound of the expression. */ abstract float getLowerBounds(); + /** Gets the upper bound of the expression. */ abstract float getUpperBounds(); + /** Holds if this expression depends on the definition `srcDef` for StackVariable `srcVar`. */ predicate dependsOnDef(RangeSsaDefinition srcDef, StackVariable srcVar) { none() } } diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll index 3bcd48e68e3..5f6209b7c73 100644 --- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll @@ -334,9 +334,7 @@ private predicate exprDependsOnDef(Expr e, RangeSsaDefinition srcDef, StackVaria e = srcDef.getAUse(srcVar) or // A modeled expression for range analysis - exists(SimpleRangeAnalysisExpr rae | - rae.dependsOnDef(srcDef, srcVar) - ) + exists(SimpleRangeAnalysisExpr rae | rae.dependsOnDef(srcDef, srcVar)) } /** From 18ba562c2528bdfe348ebd30d5d71767ef0ba54e Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Fri, 14 Aug 2020 12:14:05 +0200 Subject: [PATCH 078/133] C++: Fix: remember to bind `e` --- .../src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll index 5f6209b7c73..67eecb5f66d 100644 --- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll @@ -334,7 +334,7 @@ private predicate exprDependsOnDef(Expr e, RangeSsaDefinition srcDef, StackVaria e = srcDef.getAUse(srcVar) or // A modeled expression for range analysis - exists(SimpleRangeAnalysisExpr rae | rae.dependsOnDef(srcDef, srcVar)) + exists(SimpleRangeAnalysisExpr rae | rae = e | rae.dependsOnDef(srcDef, srcVar)) } /** From 1b5b374a8e4c3beed21eb3d9a915b114172f4418 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Thu, 13 Aug 2020 16:57:33 +0200 Subject: [PATCH 079/133] C++: Move getFullyConverted{Upper,Lower}Bounds Rather than being public, these internal predicates are now exposed through a `SimpleRangeAnalysisInternal` module so it's clear that they are not for general use. --- .../interfaces/SimpleRangeAnalysisExpr.qll | 26 ++++++++++++-- .../cpp/rangeanalysis/SimpleRangeAnalysis.qll | 36 +++++++++++-------- 2 files changed, 45 insertions(+), 17 deletions(-) diff --git a/cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisExpr.qll b/cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisExpr.qll index 40f2fe9e773..23d2c0f7be9 100644 --- a/cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisExpr.qll +++ b/cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisExpr.qll @@ -1,19 +1,39 @@ /** + * EXPERIMENTAL: The API of this module may change without notice. + * * Provides a class for modeling `Expr`s with a restricted range. */ import cpp +import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis /** - * An expression for which a range can be deduced. + * EXPERIMENTAL: The API of this class may change without notice. + * + * An expression for which a range can be deduced. Extend this class to add + * functionality to the range analysis library. */ abstract class SimpleRangeAnalysisExpr extends Expr { - /** Gets the lower bound of the expression. */ + /** + * Gets the lower bound of the expression. + * + * Implementations of this predicate should use + * `getFullyConvertedLowerBounds` and `getFullyConvertedUpperBounds` for + * recursive calls to get the bounds of their children. + */ abstract float getLowerBounds(); - /** Gets the upper bound of the expression. */ + /** + * Gets the upper bound of the expression. + * + * Implementations of this predicate should use + * `getFullyConvertedLowerBounds` and `getFullyConvertedUpperBounds` for + * recursive calls to get the bounds of their children. + */ abstract float getUpperBounds(); /** Holds if this expression depends on the definition `srcDef` for StackVariable `srcVar`. */ predicate dependsOnDef(RangeSsaDefinition srcDef, StackVariable srcVar) { none() } } + +import SimpleRangeAnalysisInternal diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll index 67eecb5f66d..f7b7f92c22d 100644 --- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll @@ -452,13 +452,6 @@ private float addRoundingDownSmall(float x, float small) { if (x + small) - x > small then result = (x + small).nextDown() else result = (x + small) } -/** - * Gets the truncated lower bounds of the fully converted expression. - */ -float getFullyConvertedLowerBounds(Expr expr) { - result = getTruncatedLowerBounds(expr.getFullyConverted()) -} - /** * Gets the lower bounds of the expression. * @@ -505,13 +498,6 @@ private float getTruncatedLowerBounds(Expr expr) { result = exprMinVal(expr) } -/** - * Gets the truncated upper bounds of the fully converted expression. - */ -float getFullyConvertedUpperBounds(Expr expr) { - result = getTruncatedUpperBounds(expr.getFullyConverted()) -} - /** * Gets the upper bounds of the expression. * @@ -1527,3 +1513,25 @@ private module SimpleRangeAnalysisCached { convertedExprMightOverflowPositively(expr) } } + +/** + * INTERNAL: do not use. This module contains utilities for use in the + * experimental `SimpleRangeAnalysisExpr` module. + */ +module SimpleRangeAnalysisInternal { + /** + * Gets the truncated lower bounds of the fully converted expression. + */ + float getFullyConvertedLowerBounds(Expr expr) { + result = getTruncatedLowerBounds(expr.getFullyConverted()) + } + + /** + * Gets the truncated upper bounds of the fully converted expression. + */ + float getFullyConvertedUpperBounds(Expr expr) { + result = getTruncatedUpperBounds(expr.getFullyConverted()) + } +} + +private import SimpleRangeAnalysisInternal From 1deb1e64299245989db783dcf574b97aef4bbde2 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Fri, 14 Aug 2020 09:49:42 +0200 Subject: [PATCH 080/133] C++: Add SimpleRangeAnalysisExpr.dependsOnChild --- .../interfaces/SimpleRangeAnalysisExpr.qll | 21 ++++++++++++++++++- .../cpp/rangeanalysis/SimpleRangeAnalysis.qll | 9 +++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisExpr.qll b/cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisExpr.qll index 23d2c0f7be9..c8a5417e34e 100644 --- a/cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisExpr.qll +++ b/cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisExpr.qll @@ -32,8 +32,27 @@ abstract class SimpleRangeAnalysisExpr extends Expr { */ abstract float getUpperBounds(); - /** Holds if this expression depends on the definition `srcDef` for StackVariable `srcVar`. */ + /** + * Holds if the range this expression depends on the definition `srcDef` for + * StackVariable `srcVar`. + * + * Because this predicate cannot be recursive, most implementations should + * override `dependsOnChild` instead. + */ predicate dependsOnDef(RangeSsaDefinition srcDef, StackVariable srcVar) { none() } + + /** + * Holds if this expression depends on the range of its unconverted + * subexpression `child`. This information is used to inform the range + * analysis about cyclic dependencies. Without this information, range + * analysis might work for simple cases but will go into infinite loops on + * complex code. + * + * For example, when modeling a function call whose return value depends on + * all of its arguments, implement this predicate as + * `child = this.getAnArgument()`. + */ + abstract predicate dependsOnChild(Expr child); } import SimpleRangeAnalysisInternal diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll index f7b7f92c22d..51f26c31022 100644 --- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll @@ -334,7 +334,14 @@ private predicate exprDependsOnDef(Expr e, RangeSsaDefinition srcDef, StackVaria e = srcDef.getAUse(srcVar) or // A modeled expression for range analysis - exists(SimpleRangeAnalysisExpr rae | rae = e | rae.dependsOnDef(srcDef, srcVar)) + exists(SimpleRangeAnalysisExpr rae | rae = e | + rae.dependsOnDef(srcDef, srcVar) + or + exists(Expr child | + rae.dependsOnChild(child) and + exprDependsOnDef(child, srcDef, srcVar) + ) + ) } /** From bf7732ec9d7197a19c5ca83020cf661a8fe97244 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Fri, 14 Aug 2020 12:14:38 +0200 Subject: [PATCH 081/133] C++: Silence QL compiler errors --- .../interfaces/SimpleRangeAnalysisExpr.qll | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisExpr.qll b/cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisExpr.qll index c8a5417e34e..c8c1110b3af 100644 --- a/cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisExpr.qll +++ b/cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisExpr.qll @@ -56,3 +56,23 @@ abstract class SimpleRangeAnalysisExpr extends Expr { } import SimpleRangeAnalysisInternal + +/** + * This class exists to prevent the QL front end from emitting compile errors + * inside `SimpleRangeAnalysis.qll` about certain conjuncts being empty + * because the overrides of `SimpleRangeAnalysisExpr` that happen to be in + * scope do not make use of every feature it offers. + */ +private class Empty extends SimpleRangeAnalysisExpr { + Empty() { + // This predicate is complicated enough that the QL type checker doesn't + // see it as empty but simple enough that the optimizer should. + this = this and none() + } + + override float getLowerBounds() { none() } + + override float getUpperBounds() { none() } + + override predicate dependsOnChild(Expr child) { none() } +} From ee3312503e3c9889d62338402a323d62cd2133e2 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Fri, 14 Aug 2020 10:06:12 +0200 Subject: [PATCH 082/133] C++: Add test for extensible range analysis This commit demonstrates that the range is too wide before custom modeling has been added to the test. --- .../rangeanalysis/extensibility/extensibility.c | 9 +++++++++ .../rangeanalysis/extensibility/extensibility.expected | 4 ++++ .../rangeanalysis/extensibility/extensibility.ql | 8 ++++++++ 3 files changed, 21 insertions(+) create mode 100644 cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.c create mode 100644 cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.expected create mode 100644 cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.ql diff --git a/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.c b/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.c new file mode 100644 index 00000000000..09d36110fcf --- /dev/null +++ b/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.c @@ -0,0 +1,9 @@ +/// Adds its arguments (requires custom modeling in QL) +int custom_add_function(int a, int b); + +int test_extensibility_add(int x) { + if (x >= -10 && x <= 10) { + int result = custom_add_function(x, 100); + return result; // should be 90 .. 110 + } +} diff --git a/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.expected b/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.expected new file mode 100644 index 00000000000..1b13279113f --- /dev/null +++ b/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.expected @@ -0,0 +1,4 @@ +| extensibility.c:5:7:5:7 | x | -2.147483648E9 | 2.147483647E9 | +| extensibility.c:5:19:5:19 | x | -10.0 | 2.147483647E9 | +| extensibility.c:6:38:6:38 | x | -10.0 | 10.0 | +| extensibility.c:7:12:7:17 | result | -2.147483648E9 | 2.147483647E9 | diff --git a/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.ql b/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.ql new file mode 100644 index 00000000000..cbbec752c3c --- /dev/null +++ b/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.ql @@ -0,0 +1,8 @@ +import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis +import experimental.semmle.code.cpp.models.interfaces.SimpleRangeAnalysisExpr + +from VariableAccess expr, float lower, float upper +where + lower = lowerBound(expr) and + upper = upperBound(expr) +select expr, lower, upper From f7273b86657db896223569b52d4e39713f00748b Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Fri, 14 Aug 2020 12:15:08 +0200 Subject: [PATCH 083/133] C++: Add custom modeling to extensibility.ql --- .../extensibility/extensibility.c | 4 ++-- .../extensibility/extensibility.expected | 2 +- .../extensibility/extensibility.ql | 24 +++++++++++++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.c b/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.c index 09d36110fcf..42f7574996c 100644 --- a/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.c +++ b/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.c @@ -1,9 +1,9 @@ -/// Adds its arguments (requires custom modeling in QL) +/// Adds its arguments (has custom modeling in QL) int custom_add_function(int a, int b); int test_extensibility_add(int x) { if (x >= -10 && x <= 10) { int result = custom_add_function(x, 100); - return result; // should be 90 .. 110 + return result; // 90 .. 110 } } diff --git a/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.expected b/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.expected index 1b13279113f..463ac9ea06c 100644 --- a/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.expected +++ b/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.expected @@ -1,4 +1,4 @@ | extensibility.c:5:7:5:7 | x | -2.147483648E9 | 2.147483647E9 | | extensibility.c:5:19:5:19 | x | -10.0 | 2.147483647E9 | | extensibility.c:6:38:6:38 | x | -10.0 | 10.0 | -| extensibility.c:7:12:7:17 | result | -2.147483648E9 | 2.147483647E9 | +| extensibility.c:7:12:7:17 | result | 90.0 | 110.0 | diff --git a/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.ql b/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.ql index cbbec752c3c..710a89ad7fa 100644 --- a/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.ql +++ b/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.ql @@ -1,6 +1,30 @@ import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis import experimental.semmle.code.cpp.models.interfaces.SimpleRangeAnalysisExpr +class CustomAddFunctionCall extends SimpleRangeAnalysisExpr, FunctionCall { + CustomAddFunctionCall() { this.getTarget().hasGlobalName("custom_add_function") } + + override float getLowerBounds() { + exists(float lower0, float lower1 | + lower0 = getFullyConvertedLowerBounds(this.getArgument(0)) and + lower1 = getFullyConvertedLowerBounds(this.getArgument(1)) and + // Note: this rounds toward 0, not -Inf as it should + result = lower0 + lower1 + ) + } + + override float getUpperBounds() { + exists(float upper0, float upper1 | + upper0 = getFullyConvertedUpperBounds(this.getArgument(0)) and + upper1 = getFullyConvertedUpperBounds(this.getArgument(1)) and + // Note: this rounds toward 0, not Inf as it should + result = upper0 + upper1 + ) + } + + override predicate dependsOnChild(Expr child) { child = this.getAnArgument() } +} + from VariableAccess expr, float lower, float upper where lower = lowerBound(expr) and From f90d779122a376ff50ba9f05b205181079091eb9 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Fri, 14 Aug 2020 14:05:27 +0200 Subject: [PATCH 084/133] C++: Fix SimpleRangeAnalysis for AssignOperation The range analysis wasn't producing useful bounds for `AssignOperation`s (`+=`, `-=`) unless their RHS involved a variable. This is because a shortcut was made in the `analyzableDef` predicate, which used to specify that an analyzable definition was one for which we'd specified the dependencies. But we can't distinguish between having _no dependencies_ and having _no specification of the dependencies_. The fix is to be more explicit about which definitions are analyzable. To avoid too much repetition I'm still calling out to `analyzableExpr` in the new code. --- .../code/cpp/rangeanalysis/SimpleRangeAnalysis.qll | 12 ++++++++++-- .../SimpleRangeAnalysis/lowerBound.expected | 8 ++++---- .../rangeanalysis/SimpleRangeAnalysis/test.c | 2 +- .../SimpleRangeAnalysis/upperBound.expected | 8 ++++---- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll index 56bcb5820f8..d81ba0b2be3 100644 --- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll @@ -391,9 +391,17 @@ private predicate assignmentDef(RangeSsaDefinition def, StackVariable v, Expr ex ) } -/** See comment above sourceDef. */ +/** See comment above assignmentDef. */ private predicate analyzableDef(RangeSsaDefinition def, StackVariable v) { - assignmentDef(def, v, _) or defDependsOnDef(def, v, _, _) + assignmentDef(def, v, _) + or + analyzableExpr(def.(AssignOperation)) and + v = def.getAVariable() + or + analyzableExpr(def.(CrementOperation)) and + v = def.getAVariable() + or + phiDependsOnDef(def, v, _, _) } /** diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected index 3c0d1f943e8..4fb08e4a535 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected @@ -427,10 +427,10 @@ | test.c:408:7:408:7 | i | 10 | | test.c:410:3:410:3 | i | -2147483648 | | test.c:411:3:411:3 | i | 10 | -| test.c:412:7:412:7 | i | -2147483648 | +| test.c:412:7:412:7 | i | 20 | | test.c:414:3:414:3 | i | -2147483648 | | test.c:415:3:415:3 | i | 40 | -| test.c:416:7:416:7 | i | -2147483648 | +| test.c:416:7:416:7 | i | 30 | | test.c:418:3:418:3 | i | -2147483648 | | test.c:418:7:418:7 | j | -2147483648 | | test.c:419:7:419:7 | i | 40 | @@ -438,8 +438,8 @@ | test.c:421:8:421:8 | j | 40 | | test.c:422:7:422:7 | i | 50 | | test.c:424:3:424:3 | i | -2147483648 | -| test.c:424:13:424:13 | j | -2147483648 | -| test.c:425:7:425:7 | i | -2147483648 | +| test.c:424:13:424:13 | j | 50 | +| test.c:425:7:425:7 | i | 60 | | test.c:432:12:432:12 | a | 0 | | test.c:432:17:432:17 | a | 3 | | test.c:432:33:432:33 | b | 0 | diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c index e85f44b73c2..dcb8020ff1a 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c @@ -422,7 +422,7 @@ void test17() { out(i); // 50 i = 20 + (j -= 10); - out(i); // 60 [BUG: the analysis thinks it's 2^-31 .. 2^31-1] + out(i); // 60 } // Tests for unsigned multiplication. diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected index ca253c03f56..40c6a4fe0bb 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected @@ -427,10 +427,10 @@ | test.c:408:7:408:7 | i | 10 | | test.c:410:3:410:3 | i | 2147483647 | | test.c:411:3:411:3 | i | 10 | -| test.c:412:7:412:7 | i | 2147483647 | +| test.c:412:7:412:7 | i | 20 | | test.c:414:3:414:3 | i | 2147483647 | | test.c:415:3:415:3 | i | 40 | -| test.c:416:7:416:7 | i | 2147483647 | +| test.c:416:7:416:7 | i | 30 | | test.c:418:3:418:3 | i | 2147483647 | | test.c:418:7:418:7 | j | 2147483647 | | test.c:419:7:419:7 | i | 40 | @@ -438,8 +438,8 @@ | test.c:421:8:421:8 | j | 40 | | test.c:422:7:422:7 | i | 50 | | test.c:424:3:424:3 | i | 2147483647 | -| test.c:424:13:424:13 | j | 2147483647 | -| test.c:425:7:425:7 | i | 2147483647 | +| test.c:424:13:424:13 | j | 50 | +| test.c:425:7:425:7 | i | 60 | | test.c:432:12:432:12 | a | 4294967295 | | test.c:432:17:432:17 | a | 4294967295 | | test.c:432:33:432:33 | b | 4294967295 | From fe72b559d3746a8a441fdabdb4a1b18665ab967a Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Thu, 13 Aug 2020 15:10:20 +0200 Subject: [PATCH 085/133] C++: Range analysis for unsigned AssignMulExpr This is essentially a copy-paste job of `AssignAddExpr`, together with the math from the `UnsignedMulExpr` support. --- .../cpp/rangeanalysis/SimpleRangeAnalysis.qll | 48 +++++++++++++++++++ .../SimpleRangeAnalysis/lowerBound.expected | 9 ++++ .../rangeanalysis/SimpleRangeAnalysis/test.c | 14 ++++++ .../SimpleRangeAnalysis/upperBound.expected | 9 ++++ 4 files changed, 80 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll index d81ba0b2be3..a294d333726 100644 --- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll @@ -160,6 +160,10 @@ private class UnsignedMulExpr extends MulExpr { UnsignedMulExpr() { this.getType().(IntegralType).isUnsigned() } } +private class UnsignedAssignMulExpr extends AssignMulExpr { + UnsignedAssignMulExpr() { this.getType().(IntegralType).isUnsigned() } +} + /** Set of expressions which we know how to analyze. */ private predicate analyzableExpr(Expr e) { // The type of the expression must be arithmetic. We reuse the logic in @@ -190,6 +194,8 @@ private predicate analyzableExpr(Expr e) { or e instanceof AssignSubExpr or + e instanceof UnsignedAssignMulExpr + or e instanceof CrementOperation or e instanceof RemExpr @@ -249,6 +255,14 @@ private predicate defDependsOnDef( exprDependsOnDef(assignSub.getRValue(), srcDef, srcVar) ) or + exists(UnsignedAssignMulExpr assignMul, RangeSsaDefinition nextDef | + def = assignMul and + assignMul.getLValue() = nextDef.getAUse(v) + | + defDependsOnDef(nextDef, v, srcDef, srcVar) or + exprDependsOnDef(assignMul.getRValue(), srcDef, srcVar) + ) + or exists(CrementOperation crem | def = crem and crem.getOperand() = v.getAnAccess() and @@ -298,6 +312,10 @@ private predicate exprDependsOnDef(Expr e, RangeSsaDefinition srcDef, StackVaria exprDependsOnDef(subExpr.getAnOperand(), srcDef, srcVar) ) or + exists(UnsignedAssignMulExpr mulExpr | e = mulExpr | + exprDependsOnDef(mulExpr.getAnOperand(), srcDef, srcVar) + ) + or exists(CrementOperation crementExpr | e = crementExpr | exprDependsOnDef(crementExpr.getOperand(), srcDef, srcVar) ) @@ -669,6 +687,13 @@ private float getLowerBoundsImpl(Expr expr) { result = addRoundingDown(xLow, -yHigh) ) or + exists(UnsignedAssignMulExpr mulExpr, float xLow, float yLow | + expr = mulExpr and + xLow = getFullyConvertedLowerBounds(mulExpr.getLValue()) and + yLow = getFullyConvertedLowerBounds(mulExpr.getRValue()) and + result = xLow * yLow + ) + or exists(PrefixIncrExpr incrExpr, float xLow | expr = incrExpr and xLow = getFullyConvertedLowerBounds(incrExpr.getOperand()) and @@ -845,6 +870,13 @@ private float getUpperBoundsImpl(Expr expr) { result = addRoundingUp(xHigh, -yLow) ) or + exists(UnsignedAssignMulExpr mulExpr, float xHigh, float yHigh | + expr = mulExpr and + xHigh = getFullyConvertedUpperBounds(mulExpr.getLValue()) and + yHigh = getFullyConvertedUpperBounds(mulExpr.getRValue()) and + result = xHigh * yHigh + ) + or exists(PrefixIncrExpr incrExpr, float xHigh | expr = incrExpr and xHigh = getFullyConvertedUpperBounds(incrExpr.getOperand()) and @@ -1073,6 +1105,14 @@ private float getDefLowerBoundsImpl(RangeSsaDefinition def, StackVariable v) { result = addRoundingDown(lhsLB, -rhsUB) ) or + exists(UnsignedAssignMulExpr assignMul, RangeSsaDefinition nextDef, float lhsLB, float rhsLB | + def = assignMul and + assignMul.getLValue() = nextDef.getAUse(v) and + lhsLB = getDefLowerBounds(nextDef, v) and + rhsLB = getFullyConvertedLowerBounds(assignMul.getRValue()) and + result = lhsLB * rhsLB + ) + or exists(IncrementOperation incr, float newLB | def = incr and incr.getOperand() = v.getAnAccess() and @@ -1115,6 +1155,14 @@ private float getDefUpperBoundsImpl(RangeSsaDefinition def, StackVariable v) { result = addRoundingUp(lhsUB, -rhsLB) ) or + exists(UnsignedAssignMulExpr assignMul, RangeSsaDefinition nextDef, float lhsUB, float rhsUB | + def = assignMul and + assignMul.getLValue() = nextDef.getAUse(v) and + lhsUB = getDefUpperBounds(nextDef, v) and + rhsUB = getFullyConvertedUpperBounds(assignMul.getRValue()) and + result = lhsUB * rhsUB + ) + or exists(IncrementOperation incr, float newUB | def = incr and incr.getOperand() = v.getAnAccess() and diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected index 4fb08e4a535..92b68b47a1c 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected @@ -501,6 +501,15 @@ | test.c:488:28:488:29 | ul | 10 | | test.c:488:33:488:34 | ul | 10 | | test.c:489:12:489:17 | result | 0 | +| test.c:495:7:495:8 | ui | 0 | +| test.c:495:19:495:20 | ui | 0 | +| test.c:496:5:496:6 | ui | 2 | +| test.c:496:11:496:12 | ui | 2 | +| test.c:497:12:497:13 | ui | 4 | +| test.c:501:3:501:9 | uiconst | 10 | +| test.c:504:3:504:9 | ulconst | 10 | +| test.c:505:10:505:16 | uiconst | 40 | +| test.c:505:20:505:26 | ulconst | 40 | | test.cpp:10:7:10:7 | b | -2147483648 | | test.cpp:11:5:11:5 | x | -2147483648 | | test.cpp:13:10:13:10 | x | -2147483648 | diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c index dcb8020ff1a..3e09ccc54d7 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c @@ -490,3 +490,17 @@ unsigned long mult_lower_bound(unsigned int ui, unsigned long ul) { } return 0; } + +unsigned long mul_assign(unsigned int ui) { + if (ui <= 10 && ui >= 2) { + ui *= ui + 0; + return ui; // 4 .. 100 + } + + unsigned int uiconst = 10; + uiconst *= 4; + + unsigned long ulconst = 10; + ulconst *= 4; + return uiconst + ulconst; // 40 .. 40 for both +} diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected index 40c6a4fe0bb..ebd9c88bffb 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected @@ -501,6 +501,15 @@ | test.c:488:28:488:29 | ul | 18446744073709552000 | | test.c:488:33:488:34 | ul | 18446744073709552000 | | test.c:489:12:489:17 | result | 18446744073709552000 | +| test.c:495:7:495:8 | ui | 4294967295 | +| test.c:495:19:495:20 | ui | 10 | +| test.c:496:5:496:6 | ui | 10 | +| test.c:496:11:496:12 | ui | 10 | +| test.c:497:12:497:13 | ui | 100 | +| test.c:501:3:501:9 | uiconst | 10 | +| test.c:504:3:504:9 | ulconst | 10 | +| test.c:505:10:505:16 | uiconst | 40 | +| test.c:505:20:505:26 | ulconst | 40 | | test.cpp:10:7:10:7 | b | 2147483647 | | test.cpp:11:5:11:5 | x | 2147483647 | | test.cpp:13:10:13:10 | x | 2147483647 | From 357109a410e2983814dff8298f536121356a81db Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Fri, 14 Aug 2020 14:33:12 +0200 Subject: [PATCH 086/133] C#: Use `DataFlow3` instead of `DataFlow2` in `Xml.qll` to avoid overlap `semmle.code.csharp.frameworks.system.Xml` is imported in `LibraryTypeDataFlow.qll`, and therefore part of the default namespace. This means that the use of `DataFlow2` inside `Xml.qll` overlaps with some queries. Bumping to `DataFlow3` resolves the issue. --- csharp/ql/src/semmle/code/csharp/frameworks/system/Xml.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/Xml.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/Xml.qll index 21ca1431012..c84fa47a103 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/Xml.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/Xml.qll @@ -2,7 +2,7 @@ import csharp private import semmle.code.csharp.frameworks.System -private import semmle.code.csharp.dataflow.DataFlow2 +private import semmle.code.csharp.dataflow.DataFlow3 /** The `System.Xml` namespace. */ class SystemXmlNamespace extends Namespace { @@ -163,7 +163,7 @@ class XmlReaderSettingsCreation extends ObjectCreation { } } -private class SettingsDataFlowConfig extends DataFlow2::Configuration { +private class SettingsDataFlowConfig extends DataFlow3::Configuration { SettingsDataFlowConfig() { this = "SettingsDataFlowConfig" } override predicate isSource(DataFlow::Node source) { From edc5e5fbcf2f87d50d2327f865fa0ed5138b7d2a Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Mon, 17 Aug 2020 10:58:45 +0200 Subject: [PATCH 087/133] C++: Simplify defDependsOnDef for AssignOperation These cases were unnecessarily transitive. There is no need for `defDependsOnDef` to be transitive since that's handled in `defDependsOnDefTransitively`. The dependency information from the LHS of an `AssignmentOperation` is now deduced the say way as the information from the RHS: by calling `exprDependsOnDef`. This should effectively give us the same information and recursion structure as if the operation (`x += e`) were desugared (`x = x + e`). --- .../cpp/rangeanalysis/SimpleRangeAnalysis.qll | 26 +++++++------------ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll index a294d333726..c275c7c5db0 100644 --- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll @@ -239,33 +239,27 @@ private predicate defDependsOnDef( // Definitions with a defining value. exists(Expr expr | assignmentDef(def, v, expr) | exprDependsOnDef(expr, srcDef, srcVar)) or - exists(AssignAddExpr assignAdd, RangeSsaDefinition nextDef | + exists(AssignAddExpr assignAdd | def = assignAdd and - assignAdd.getLValue() = nextDef.getAUse(v) - | - defDependsOnDef(nextDef, v, srcDef, srcVar) or - exprDependsOnDef(assignAdd.getRValue(), srcDef, srcVar) + def.getAVariable() = v and + exprDependsOnDef(assignAdd.getAnOperand(), srcDef, srcVar) ) or - exists(AssignSubExpr assignSub, RangeSsaDefinition nextDef | + exists(AssignSubExpr assignSub | def = assignSub and - assignSub.getLValue() = nextDef.getAUse(v) - | - defDependsOnDef(nextDef, v, srcDef, srcVar) or - exprDependsOnDef(assignSub.getRValue(), srcDef, srcVar) + def.getAVariable() = v and + exprDependsOnDef(assignSub.getAnOperand(), srcDef, srcVar) ) or - exists(UnsignedAssignMulExpr assignMul, RangeSsaDefinition nextDef | + exists(UnsignedAssignMulExpr assignMul | def = assignMul and - assignMul.getLValue() = nextDef.getAUse(v) - | - defDependsOnDef(nextDef, v, srcDef, srcVar) or - exprDependsOnDef(assignMul.getRValue(), srcDef, srcVar) + def.getAVariable() = v and + exprDependsOnDef(assignMul.getAnOperand(), srcDef, srcVar) ) or exists(CrementOperation crem | def = crem and - crem.getOperand() = v.getAnAccess() and + def.getAVariable() = v and exprDependsOnDef(crem.getOperand(), srcDef, srcVar) ) or From e03fe81ce780963c7494285e9e00dda8e0d57190 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Mon, 17 Aug 2020 15:07:00 +0200 Subject: [PATCH 088/133] C++: Accept float.toString changes in tests --- .../SimpleRangeAnalysis/lowerBound.expected | 4 +- .../SimpleRangeAnalysis/upperBound.expected | 38 +++++++++---------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected index 3c0d1f943e8..63bc2afb612 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected @@ -98,7 +98,7 @@ | test.c:150:25:150:26 | x3 | -2147483648 | | test.c:150:30:150:31 | c0 | -128 | | test.c:150:35:150:36 | s0 | 0 | -| test.c:154:11:154:11 | x | -9223372036854776000 | +| test.c:154:11:154:11 | x | -9223372036854775808 | | test.c:154:20:154:20 | x | 1 | | test.c:154:30:154:30 | x | 1 | | test.c:154:35:154:35 | x | 1 | @@ -492,7 +492,7 @@ | test.c:478:3:478:4 | xy | 0 | | test.c:478:8:478:8 | x | 274177 | | test.c:478:12:478:12 | y | 67280421310721 | -| test.c:479:10:479:11 | xy | 18446744073709552000 | +| test.c:479:10:479:11 | xy | 18446744073709551616 | | test.c:483:7:483:8 | ui | 0 | | test.c:484:43:484:44 | ui | 10 | | test.c:484:48:484:49 | ui | 10 | diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected index ca253c03f56..23af1f567f1 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected @@ -73,10 +73,10 @@ | test.c:105:5:105:5 | c | 127 | | test.c:106:9:106:9 | c | 127 | | test.c:109:9:109:9 | c | 127 | -| test.c:119:10:119:10 | n | 18446744073709552000 | -| test.c:124:11:124:15 | Start | 18446744073709552000 | -| test.c:127:6:127:10 | Start | 18446744073709552000 | -| test.c:127:15:127:20 | Length | 18446744073709552000 | +| test.c:119:10:119:10 | n | 18446744073709551616 | +| test.c:124:11:124:15 | Start | 18446744073709551616 | +| test.c:127:6:127:10 | Start | 18446744073709551616 | +| test.c:127:15:127:20 | Length | 18446744073709551616 | | test.c:135:22:135:22 | c | 127 | | test.c:137:20:137:20 | x | 0 | | test.c:138:11:138:11 | i | 2147483647 | @@ -98,9 +98,9 @@ | test.c:150:25:150:26 | x3 | 2147483647 | | test.c:150:30:150:31 | c0 | 127 | | test.c:150:35:150:36 | s0 | 65535 | -| test.c:154:11:154:11 | x | 9223372036854776000 | -| test.c:154:20:154:20 | x | 9223372036854776000 | -| test.c:154:30:154:30 | x | 9223372036854776000 | +| test.c:154:11:154:11 | x | 9223372036854775808 | +| test.c:154:20:154:20 | x | 9223372036854775808 | +| test.c:154:30:154:30 | x | 9223372036854775808 | | test.c:154:35:154:35 | x | 2147483647 | | test.c:161:12:161:12 | a | 2147483647 | | test.c:161:17:161:17 | a | 2147483647 | @@ -481,26 +481,26 @@ | test.c:461:5:461:9 | total | 506 | | test.c:461:14:461:14 | r | 253 | | test.c:464:10:464:14 | total | 759 | -| test.c:469:3:469:3 | x | 18446744073709552000 | -| test.c:469:7:469:7 | y | 18446744073709552000 | -| test.c:470:3:470:4 | xy | 18446744073709552000 | +| test.c:469:3:469:3 | x | 18446744073709551616 | +| test.c:469:7:469:7 | y | 18446744073709551616 | +| test.c:470:3:470:4 | xy | 18446744073709551616 | | test.c:470:8:470:8 | x | 1000000003 | | test.c:470:12:470:12 | y | 1000000003 | | test.c:471:10:471:11 | xy | 1000000006000000000 | -| test.c:476:3:476:3 | x | 18446744073709552000 | -| test.c:477:3:477:3 | y | 18446744073709552000 | -| test.c:478:3:478:4 | xy | 18446744073709552000 | +| test.c:476:3:476:3 | x | 18446744073709551616 | +| test.c:477:3:477:3 | y | 18446744073709551616 | +| test.c:478:3:478:4 | xy | 18446744073709551616 | | test.c:478:8:478:8 | x | 274177 | | test.c:478:12:478:12 | y | 67280421310721 | -| test.c:479:10:479:11 | xy | 18446744073709552000 | +| test.c:479:10:479:11 | xy | 18446744073709551616 | | test.c:483:7:483:8 | ui | 4294967295 | | test.c:484:43:484:44 | ui | 4294967295 | | test.c:484:48:484:49 | ui | 4294967295 | -| test.c:485:12:485:17 | result | 18446744065119617000 | -| test.c:487:7:487:8 | ul | 18446744073709552000 | -| test.c:488:28:488:29 | ul | 18446744073709552000 | -| test.c:488:33:488:34 | ul | 18446744073709552000 | -| test.c:489:12:489:17 | result | 18446744073709552000 | +| test.c:485:12:485:17 | result | 18446744065119617024 | +| test.c:487:7:487:8 | ul | 18446744073709551616 | +| test.c:488:28:488:29 | ul | 18446744073709551616 | +| test.c:488:33:488:34 | ul | 18446744073709551616 | +| test.c:489:12:489:17 | result | 18446744073709551616 | | test.cpp:10:7:10:7 | b | 2147483647 | | test.cpp:11:5:11:5 | x | 2147483647 | | test.cpp:13:10:13:10 | x | 2147483647 | From a2fc92b9dbafa432032464b7ffd084ba43599c08 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 17 Aug 2020 15:46:43 +0200 Subject: [PATCH 089/133] Data flow: Address review comments --- .../semmle/code/cpp/dataflow/internal/DataFlowImpl.qll | 10 +++++----- .../code/cpp/dataflow/internal/DataFlowImpl2.qll | 10 +++++----- .../code/cpp/dataflow/internal/DataFlowImpl3.qll | 10 +++++----- .../code/cpp/dataflow/internal/DataFlowImpl4.qll | 10 +++++----- .../code/cpp/dataflow/internal/DataFlowImplLocal.qll | 10 +++++----- .../code/cpp/ir/dataflow/internal/DataFlowImpl.qll | 10 +++++----- .../code/cpp/ir/dataflow/internal/DataFlowImpl2.qll | 10 +++++----- .../code/cpp/ir/dataflow/internal/DataFlowImpl3.qll | 10 +++++----- .../code/cpp/ir/dataflow/internal/DataFlowImpl4.qll | 10 +++++----- .../code/csharp/dataflow/internal/DataFlowImpl.qll | 10 +++++----- .../code/csharp/dataflow/internal/DataFlowImpl2.qll | 10 +++++----- .../code/csharp/dataflow/internal/DataFlowImpl3.qll | 10 +++++----- .../code/csharp/dataflow/internal/DataFlowImpl4.qll | 10 +++++----- .../code/csharp/dataflow/internal/DataFlowImpl5.qll | 10 +++++----- .../code/java/dataflow/internal/DataFlowImpl.qll | 10 +++++----- .../code/java/dataflow/internal/DataFlowImpl2.qll | 10 +++++----- .../code/java/dataflow/internal/DataFlowImpl3.qll | 10 +++++----- .../code/java/dataflow/internal/DataFlowImpl4.qll | 10 +++++----- .../code/java/dataflow/internal/DataFlowImpl5.qll | 10 +++++----- .../experimental/dataflow/internal/DataFlowImpl.qll | 10 +++++----- .../experimental/dataflow/internal/DataFlowImpl2.qll | 10 +++++----- 21 files changed, 105 insertions(+), 105 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll index 4e6eb9d86c0..8c210edbe5f 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll @@ -1713,15 +1713,15 @@ private predicate flowFwd0( ) or // flow into a callable - flowFwdIn(_, node, cc, _, _, apf, ap, config) and + flowFwdIn(_, node, _, cc, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - exists(CallContextNoCall innercc, DataFlowCallable c | - flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + exists(DataFlowCallable c | + flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() ) or @@ -1806,7 +1806,7 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | @@ -1857,7 +1857,7 @@ private predicate flowFwdIsEntered( DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and + flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll index 4e6eb9d86c0..8c210edbe5f 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll @@ -1713,15 +1713,15 @@ private predicate flowFwd0( ) or // flow into a callable - flowFwdIn(_, node, cc, _, _, apf, ap, config) and + flowFwdIn(_, node, _, cc, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - exists(CallContextNoCall innercc, DataFlowCallable c | - flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + exists(DataFlowCallable c | + flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() ) or @@ -1806,7 +1806,7 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | @@ -1857,7 +1857,7 @@ private predicate flowFwdIsEntered( DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and + flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll index 4e6eb9d86c0..8c210edbe5f 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll @@ -1713,15 +1713,15 @@ private predicate flowFwd0( ) or // flow into a callable - flowFwdIn(_, node, cc, _, _, apf, ap, config) and + flowFwdIn(_, node, _, cc, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - exists(CallContextNoCall innercc, DataFlowCallable c | - flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + exists(DataFlowCallable c | + flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() ) or @@ -1806,7 +1806,7 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | @@ -1857,7 +1857,7 @@ private predicate flowFwdIsEntered( DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and + flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll index 4e6eb9d86c0..8c210edbe5f 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll @@ -1713,15 +1713,15 @@ private predicate flowFwd0( ) or // flow into a callable - flowFwdIn(_, node, cc, _, _, apf, ap, config) and + flowFwdIn(_, node, _, cc, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - exists(CallContextNoCall innercc, DataFlowCallable c | - flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + exists(DataFlowCallable c | + flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() ) or @@ -1806,7 +1806,7 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | @@ -1857,7 +1857,7 @@ private predicate flowFwdIsEntered( DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and + flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll index 4e6eb9d86c0..8c210edbe5f 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll @@ -1713,15 +1713,15 @@ private predicate flowFwd0( ) or // flow into a callable - flowFwdIn(_, node, cc, _, _, apf, ap, config) and + flowFwdIn(_, node, _, cc, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - exists(CallContextNoCall innercc, DataFlowCallable c | - flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + exists(DataFlowCallable c | + flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() ) or @@ -1806,7 +1806,7 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | @@ -1857,7 +1857,7 @@ private predicate flowFwdIsEntered( DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and + flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll index 4e6eb9d86c0..8c210edbe5f 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll @@ -1713,15 +1713,15 @@ private predicate flowFwd0( ) or // flow into a callable - flowFwdIn(_, node, cc, _, _, apf, ap, config) and + flowFwdIn(_, node, _, cc, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - exists(CallContextNoCall innercc, DataFlowCallable c | - flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + exists(DataFlowCallable c | + flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() ) or @@ -1806,7 +1806,7 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | @@ -1857,7 +1857,7 @@ private predicate flowFwdIsEntered( DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and + flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll index 4e6eb9d86c0..8c210edbe5f 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll @@ -1713,15 +1713,15 @@ private predicate flowFwd0( ) or // flow into a callable - flowFwdIn(_, node, cc, _, _, apf, ap, config) and + flowFwdIn(_, node, _, cc, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - exists(CallContextNoCall innercc, DataFlowCallable c | - flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + exists(DataFlowCallable c | + flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() ) or @@ -1806,7 +1806,7 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | @@ -1857,7 +1857,7 @@ private predicate flowFwdIsEntered( DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and + flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll index 4e6eb9d86c0..8c210edbe5f 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll @@ -1713,15 +1713,15 @@ private predicate flowFwd0( ) or // flow into a callable - flowFwdIn(_, node, cc, _, _, apf, ap, config) and + flowFwdIn(_, node, _, cc, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - exists(CallContextNoCall innercc, DataFlowCallable c | - flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + exists(DataFlowCallable c | + flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() ) or @@ -1806,7 +1806,7 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | @@ -1857,7 +1857,7 @@ private predicate flowFwdIsEntered( DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and + flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll index 4e6eb9d86c0..8c210edbe5f 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll @@ -1713,15 +1713,15 @@ private predicate flowFwd0( ) or // flow into a callable - flowFwdIn(_, node, cc, _, _, apf, ap, config) and + flowFwdIn(_, node, _, cc, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - exists(CallContextNoCall innercc, DataFlowCallable c | - flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + exists(DataFlowCallable c | + flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() ) or @@ -1806,7 +1806,7 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | @@ -1857,7 +1857,7 @@ private predicate flowFwdIsEntered( DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and + flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll index 4e6eb9d86c0..8c210edbe5f 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll @@ -1713,15 +1713,15 @@ private predicate flowFwd0( ) or // flow into a callable - flowFwdIn(_, node, cc, _, _, apf, ap, config) and + flowFwdIn(_, node, _, cc, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - exists(CallContextNoCall innercc, DataFlowCallable c | - flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + exists(DataFlowCallable c | + flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() ) or @@ -1806,7 +1806,7 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | @@ -1857,7 +1857,7 @@ private predicate flowFwdIsEntered( DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and + flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll index 4e6eb9d86c0..8c210edbe5f 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll @@ -1713,15 +1713,15 @@ private predicate flowFwd0( ) or // flow into a callable - flowFwdIn(_, node, cc, _, _, apf, ap, config) and + flowFwdIn(_, node, _, cc, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - exists(CallContextNoCall innercc, DataFlowCallable c | - flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + exists(DataFlowCallable c | + flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() ) or @@ -1806,7 +1806,7 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | @@ -1857,7 +1857,7 @@ private predicate flowFwdIsEntered( DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and + flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll index 4e6eb9d86c0..8c210edbe5f 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll @@ -1713,15 +1713,15 @@ private predicate flowFwd0( ) or // flow into a callable - flowFwdIn(_, node, cc, _, _, apf, ap, config) and + flowFwdIn(_, node, _, cc, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - exists(CallContextNoCall innercc, DataFlowCallable c | - flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + exists(DataFlowCallable c | + flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() ) or @@ -1806,7 +1806,7 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | @@ -1857,7 +1857,7 @@ private predicate flowFwdIsEntered( DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and + flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll index 4e6eb9d86c0..8c210edbe5f 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll @@ -1713,15 +1713,15 @@ private predicate flowFwd0( ) or // flow into a callable - flowFwdIn(_, node, cc, _, _, apf, ap, config) and + flowFwdIn(_, node, _, cc, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - exists(CallContextNoCall innercc, DataFlowCallable c | - flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + exists(DataFlowCallable c | + flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() ) or @@ -1806,7 +1806,7 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | @@ -1857,7 +1857,7 @@ private predicate flowFwdIsEntered( DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and + flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll index 4e6eb9d86c0..8c210edbe5f 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll @@ -1713,15 +1713,15 @@ private predicate flowFwd0( ) or // flow into a callable - flowFwdIn(_, node, cc, _, _, apf, ap, config) and + flowFwdIn(_, node, _, cc, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - exists(CallContextNoCall innercc, DataFlowCallable c | - flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + exists(DataFlowCallable c | + flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() ) or @@ -1806,7 +1806,7 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | @@ -1857,7 +1857,7 @@ private predicate flowFwdIsEntered( DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and + flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll index 4e6eb9d86c0..8c210edbe5f 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -1713,15 +1713,15 @@ private predicate flowFwd0( ) or // flow into a callable - flowFwdIn(_, node, cc, _, _, apf, ap, config) and + flowFwdIn(_, node, _, cc, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - exists(CallContextNoCall innercc, DataFlowCallable c | - flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + exists(DataFlowCallable c | + flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() ) or @@ -1806,7 +1806,7 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | @@ -1857,7 +1857,7 @@ private predicate flowFwdIsEntered( DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and + flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll index 4e6eb9d86c0..8c210edbe5f 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll @@ -1713,15 +1713,15 @@ private predicate flowFwd0( ) or // flow into a callable - flowFwdIn(_, node, cc, _, _, apf, ap, config) and + flowFwdIn(_, node, _, cc, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - exists(CallContextNoCall innercc, DataFlowCallable c | - flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + exists(DataFlowCallable c | + flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() ) or @@ -1806,7 +1806,7 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | @@ -1857,7 +1857,7 @@ private predicate flowFwdIsEntered( DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and + flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll index 4e6eb9d86c0..8c210edbe5f 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll @@ -1713,15 +1713,15 @@ private predicate flowFwd0( ) or // flow into a callable - flowFwdIn(_, node, cc, _, _, apf, ap, config) and + flowFwdIn(_, node, _, cc, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - exists(CallContextNoCall innercc, DataFlowCallable c | - flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + exists(DataFlowCallable c | + flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() ) or @@ -1806,7 +1806,7 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | @@ -1857,7 +1857,7 @@ private predicate flowFwdIsEntered( DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and + flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll index 4e6eb9d86c0..8c210edbe5f 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll @@ -1713,15 +1713,15 @@ private predicate flowFwd0( ) or // flow into a callable - flowFwdIn(_, node, cc, _, _, apf, ap, config) and + flowFwdIn(_, node, _, cc, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - exists(CallContextNoCall innercc, DataFlowCallable c | - flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + exists(DataFlowCallable c | + flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() ) or @@ -1806,7 +1806,7 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | @@ -1857,7 +1857,7 @@ private predicate flowFwdIsEntered( DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and + flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll index 4e6eb9d86c0..8c210edbe5f 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll @@ -1713,15 +1713,15 @@ private predicate flowFwd0( ) or // flow into a callable - flowFwdIn(_, node, cc, _, _, apf, ap, config) and + flowFwdIn(_, node, _, cc, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - exists(CallContextNoCall innercc, DataFlowCallable c | - flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + exists(DataFlowCallable c | + flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() ) or @@ -1806,7 +1806,7 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | @@ -1857,7 +1857,7 @@ private predicate flowFwdIsEntered( DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and + flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } diff --git a/python/ql/src/experimental/dataflow/internal/DataFlowImpl.qll b/python/ql/src/experimental/dataflow/internal/DataFlowImpl.qll index 4e6eb9d86c0..8c210edbe5f 100644 --- a/python/ql/src/experimental/dataflow/internal/DataFlowImpl.qll +++ b/python/ql/src/experimental/dataflow/internal/DataFlowImpl.qll @@ -1713,15 +1713,15 @@ private predicate flowFwd0( ) or // flow into a callable - flowFwdIn(_, node, cc, _, _, apf, ap, config) and + flowFwdIn(_, node, _, cc, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - exists(CallContextNoCall innercc, DataFlowCallable c | - flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + exists(DataFlowCallable c | + flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() ) or @@ -1806,7 +1806,7 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | @@ -1857,7 +1857,7 @@ private predicate flowFwdIsEntered( DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and + flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } diff --git a/python/ql/src/experimental/dataflow/internal/DataFlowImpl2.qll b/python/ql/src/experimental/dataflow/internal/DataFlowImpl2.qll index 4e6eb9d86c0..8c210edbe5f 100644 --- a/python/ql/src/experimental/dataflow/internal/DataFlowImpl2.qll +++ b/python/ql/src/experimental/dataflow/internal/DataFlowImpl2.qll @@ -1713,15 +1713,15 @@ private predicate flowFwd0( ) or // flow into a callable - flowFwdIn(_, node, cc, _, _, apf, ap, config) and + flowFwdIn(_, node, _, cc, _, apf, ap, config) and if flowCand(node, true, _, apf, config) then argAp = TAccessPathSome(ap) else argAp = TAccessPathNone() or // flow out of a callable exists(DataFlowCall call | - exists(CallContextNoCall innercc, DataFlowCallable c | - flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and + exists(DataFlowCallable c | + flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() ) or @@ -1806,7 +1806,7 @@ private predicate flowFwdConsCand( pragma[nomagic] private predicate flowFwdIn( - DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc, + DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config ) { exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c | @@ -1857,7 +1857,7 @@ private predicate flowFwdIsEntered( DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config ) { exists(ParameterNode p, AccessPathFront apf | - flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and + flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and flowCand(p, true, TAccessPathFrontSome(_), apf, config) ) } From 789e781eb70add0d048cc236937897a28b42828c Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 17 Aug 2020 12:28:07 +0100 Subject: [PATCH 090/133] C++: Add prototypes for std::string methods to test. --- .../test/library-tests/dataflow/taint-tests/stl.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h index 4ebd5e9283a..82d3c564763 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h @@ -39,11 +39,14 @@ namespace std class basic_string { public: typedef typename Allocator::size_type size_type; + static const size_type npos = -1; explicit basic_string(const Allocator& a = Allocator()); basic_string(const charT* s, const Allocator& a = Allocator()); const charT* c_str() const; + charT* data() noexcept; + size_t length() const; typedef std::iterator iterator; typedef std::iterator const_iterator; @@ -60,6 +63,16 @@ namespace std basic_string& append(const basic_string& str); basic_string& append(const charT* s); basic_string& append(size_type n, charT c); + basic_string& assign(const basic_string& str); + basic_string& assign(size_type n, charT c); + basic_string& insert(size_type pos, const basic_string& str); + basic_string& insert(size_type pos, size_type n, charT c); + basic_string& replace(size_type pos1, size_type n1, const basic_string& str); + basic_string& replace(size_type pos1, size_type n1, size_type n2, charT c); + size_type copy(charT* s, size_type n, size_type pos = 0) const; + void clear() noexcept; + basic_string substr(size_type pos = 0, size_type n = npos) const; + void swap(basic_string& s) noexcept/*(allocator_traits::propagate_on_container_swap::value || allocator_traits::is_always_equal::value)*/; }; template basic_string operator+(const basic_string& lhs, const basic_string& rhs); From 9204940830b210beb937f9c9d599f6ccd5d9dc44 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 17 Aug 2020 16:00:26 +0100 Subject: [PATCH 091/133] C++: Add test cases for std::string methods. --- .../dataflow/taint-tests/localTaint.expected | 134 +++++++++++++++++ .../dataflow/taint-tests/string.cpp | 137 ++++++++++++++++++ .../dataflow/taint-tests/taint.expected | 12 ++ .../dataflow/taint-tests/test_diff.expected | 12 ++ 4 files changed, 295 insertions(+) diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected index 2fc40532357..5da1a754039 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -494,6 +494,140 @@ | string.cpp:183:3:183:5 | ref arg s10 | string.cpp:184:8:184:10 | s10 | | | string.cpp:183:17:183:17 | c | string.cpp:183:3:183:5 | ref arg s10 | TAINT | | string.cpp:183:17:183:17 | c | string.cpp:183:7:183:12 | call to append | TAINT | +| string.cpp:189:17:189:23 | hello | string.cpp:189:17:189:24 | call to basic_string | TAINT | +| string.cpp:189:17:189:24 | call to basic_string | string.cpp:195:17:195:18 | s1 | | +| string.cpp:189:17:189:24 | call to basic_string | string.cpp:204:17:204:18 | s1 | | +| string.cpp:190:17:190:22 | call to source | string.cpp:190:17:190:25 | call to basic_string | TAINT | +| string.cpp:190:17:190:25 | call to basic_string | string.cpp:198:17:198:18 | s2 | | +| string.cpp:191:11:191:25 | call to source | string.cpp:201:21:201:21 | c | | +| string.cpp:192:14:192:15 | call to basic_string | string.cpp:195:7:195:8 | s3 | | +| string.cpp:192:14:192:15 | call to basic_string | string.cpp:196:7:196:8 | s3 | | +| string.cpp:192:18:192:19 | call to basic_string | string.cpp:198:7:198:8 | s4 | | +| string.cpp:192:18:192:19 | call to basic_string | string.cpp:199:7:199:8 | s4 | | +| string.cpp:192:22:192:23 | call to basic_string | string.cpp:201:7:201:8 | s5 | | +| string.cpp:192:22:192:23 | call to basic_string | string.cpp:202:7:202:8 | s5 | | +| string.cpp:193:17:193:22 | call to source | string.cpp:193:17:193:25 | call to basic_string | TAINT | +| string.cpp:193:17:193:25 | call to basic_string | string.cpp:204:7:204:8 | s6 | | +| string.cpp:193:17:193:25 | call to basic_string | string.cpp:205:7:205:8 | s6 | | +| string.cpp:195:7:195:8 | ref arg s3 | string.cpp:196:7:196:8 | s3 | | +| string.cpp:198:7:198:8 | ref arg s4 | string.cpp:199:7:199:8 | s4 | | +| string.cpp:201:7:201:8 | ref arg s5 | string.cpp:202:7:202:8 | s5 | | +| string.cpp:204:7:204:8 | ref arg s6 | string.cpp:205:7:205:8 | s6 | | +| string.cpp:209:17:209:23 | hello | string.cpp:209:17:209:24 | call to basic_string | TAINT | +| string.cpp:209:17:209:24 | call to basic_string | string.cpp:214:7:214:8 | s1 | | +| string.cpp:209:17:209:24 | call to basic_string | string.cpp:215:20:215:21 | s1 | | +| string.cpp:209:17:209:24 | call to basic_string | string.cpp:219:20:219:21 | s1 | | +| string.cpp:209:17:209:24 | call to basic_string | string.cpp:222:7:222:8 | s1 | | +| string.cpp:209:17:209:24 | call to basic_string | string.cpp:226:7:226:8 | s1 | | +| string.cpp:210:17:210:22 | call to source | string.cpp:210:17:210:25 | call to basic_string | TAINT | +| string.cpp:210:17:210:25 | call to basic_string | string.cpp:218:7:218:8 | s2 | | +| string.cpp:210:17:210:25 | call to basic_string | string.cpp:223:20:223:21 | s2 | | +| string.cpp:211:11:211:25 | call to source | string.cpp:227:24:227:24 | c | | +| string.cpp:214:7:214:8 | s1 | string.cpp:214:2:214:8 | ... = ... | | +| string.cpp:214:7:214:8 | s1 | string.cpp:215:7:215:8 | s3 | | +| string.cpp:214:7:214:8 | s1 | string.cpp:216:7:216:8 | s3 | | +| string.cpp:215:7:215:8 | ref arg s3 | string.cpp:216:7:216:8 | s3 | | +| string.cpp:218:7:218:8 | s2 | string.cpp:218:2:218:8 | ... = ... | | +| string.cpp:218:7:218:8 | s2 | string.cpp:219:7:219:8 | s4 | | +| string.cpp:218:7:218:8 | s2 | string.cpp:220:7:220:8 | s4 | | +| string.cpp:219:7:219:8 | ref arg s4 | string.cpp:220:7:220:8 | s4 | | +| string.cpp:222:7:222:8 | s1 | string.cpp:222:2:222:8 | ... = ... | | +| string.cpp:222:7:222:8 | s1 | string.cpp:223:7:223:8 | s5 | | +| string.cpp:222:7:222:8 | s1 | string.cpp:224:7:224:8 | s5 | | +| string.cpp:223:7:223:8 | ref arg s5 | string.cpp:224:7:224:8 | s5 | | +| string.cpp:226:7:226:8 | s1 | string.cpp:226:2:226:8 | ... = ... | | +| string.cpp:226:7:226:8 | s1 | string.cpp:227:7:227:8 | s6 | | +| string.cpp:226:7:226:8 | s1 | string.cpp:228:7:228:8 | s6 | | +| string.cpp:227:7:227:8 | ref arg s6 | string.cpp:228:7:228:8 | s6 | | +| string.cpp:232:17:232:23 | hello | string.cpp:232:17:232:24 | call to basic_string | TAINT | +| string.cpp:232:17:232:24 | call to basic_string | string.cpp:237:7:237:8 | s1 | | +| string.cpp:232:17:232:24 | call to basic_string | string.cpp:238:24:238:25 | s1 | | +| string.cpp:232:17:232:24 | call to basic_string | string.cpp:242:24:242:25 | s1 | | +| string.cpp:232:17:232:24 | call to basic_string | string.cpp:245:7:245:8 | s1 | | +| string.cpp:232:17:232:24 | call to basic_string | string.cpp:249:7:249:8 | s1 | | +| string.cpp:233:17:233:22 | call to source | string.cpp:233:17:233:25 | call to basic_string | TAINT | +| string.cpp:233:17:233:25 | call to basic_string | string.cpp:241:7:241:8 | s2 | | +| string.cpp:233:17:233:25 | call to basic_string | string.cpp:246:24:246:25 | s2 | | +| string.cpp:234:11:234:25 | call to source | string.cpp:250:28:250:28 | c | | +| string.cpp:237:7:237:8 | s1 | string.cpp:237:2:237:8 | ... = ... | | +| string.cpp:237:7:237:8 | s1 | string.cpp:238:7:238:8 | s3 | | +| string.cpp:237:7:237:8 | s1 | string.cpp:239:7:239:8 | s3 | | +| string.cpp:238:7:238:8 | ref arg s3 | string.cpp:239:7:239:8 | s3 | | +| string.cpp:241:7:241:8 | s2 | string.cpp:241:2:241:8 | ... = ... | | +| string.cpp:241:7:241:8 | s2 | string.cpp:242:7:242:8 | s4 | | +| string.cpp:241:7:241:8 | s2 | string.cpp:243:7:243:8 | s4 | | +| string.cpp:242:7:242:8 | ref arg s4 | string.cpp:243:7:243:8 | s4 | | +| string.cpp:245:7:245:8 | s1 | string.cpp:245:2:245:8 | ... = ... | | +| string.cpp:245:7:245:8 | s1 | string.cpp:246:7:246:8 | s5 | | +| string.cpp:245:7:245:8 | s1 | string.cpp:247:7:247:8 | s5 | | +| string.cpp:246:7:246:8 | ref arg s5 | string.cpp:247:7:247:8 | s5 | | +| string.cpp:249:7:249:8 | s1 | string.cpp:249:2:249:8 | ... = ... | | +| string.cpp:249:7:249:8 | s1 | string.cpp:250:7:250:8 | s6 | | +| string.cpp:249:7:249:8 | s1 | string.cpp:251:7:251:8 | s6 | | +| string.cpp:250:7:250:8 | ref arg s6 | string.cpp:251:7:251:8 | s6 | | +| string.cpp:255:17:255:20 | {...} | string.cpp:260:10:260:11 | b1 | | +| string.cpp:255:17:255:20 | {...} | string.cpp:261:7:261:8 | b1 | | +| string.cpp:255:19:255:19 | 0 | string.cpp:255:17:255:20 | {...} | TAINT | +| string.cpp:256:17:256:20 | {...} | string.cpp:263:10:263:11 | b2 | | +| string.cpp:256:17:256:20 | {...} | string.cpp:264:7:264:8 | b2 | | +| string.cpp:256:19:256:19 | 0 | string.cpp:256:17:256:20 | {...} | TAINT | +| string.cpp:257:17:257:23 | hello | string.cpp:257:17:257:24 | call to basic_string | TAINT | +| string.cpp:257:17:257:24 | call to basic_string | string.cpp:260:2:260:3 | s1 | | +| string.cpp:257:17:257:24 | call to basic_string | string.cpp:260:14:260:15 | s1 | | +| string.cpp:257:17:257:24 | call to basic_string | string.cpp:263:14:263:15 | s1 | | +| string.cpp:258:17:258:22 | call to source | string.cpp:258:17:258:25 | call to basic_string | TAINT | +| string.cpp:258:17:258:25 | call to basic_string | string.cpp:263:2:263:3 | s2 | | +| string.cpp:260:10:260:11 | ref arg b1 | string.cpp:261:7:261:8 | b1 | | +| string.cpp:263:10:263:11 | ref arg b2 | string.cpp:264:7:264:8 | b2 | | +| string.cpp:268:17:268:23 | hello | string.cpp:268:17:268:24 | call to basic_string | TAINT | +| string.cpp:268:17:268:24 | call to basic_string | string.cpp:273:7:273:8 | s1 | | +| string.cpp:268:17:268:24 | call to basic_string | string.cpp:278:2:278:3 | s1 | | +| string.cpp:268:17:268:24 | call to basic_string | string.cpp:281:7:281:8 | s1 | | +| string.cpp:269:17:269:22 | call to source | string.cpp:269:17:269:25 | call to basic_string | TAINT | +| string.cpp:269:17:269:25 | call to basic_string | string.cpp:274:7:274:8 | s2 | | +| string.cpp:269:17:269:25 | call to basic_string | string.cpp:278:10:278:11 | s2 | | +| string.cpp:269:17:269:25 | call to basic_string | string.cpp:282:7:282:8 | s2 | | +| string.cpp:270:17:270:23 | world | string.cpp:270:17:270:24 | call to basic_string | TAINT | +| string.cpp:270:17:270:24 | call to basic_string | string.cpp:275:7:275:8 | s3 | | +| string.cpp:270:17:270:24 | call to basic_string | string.cpp:279:10:279:11 | s3 | | +| string.cpp:270:17:270:24 | call to basic_string | string.cpp:283:7:283:8 | s3 | | +| string.cpp:271:17:271:22 | call to source | string.cpp:271:17:271:25 | call to basic_string | TAINT | +| string.cpp:271:17:271:25 | call to basic_string | string.cpp:276:7:276:8 | s4 | | +| string.cpp:271:17:271:25 | call to basic_string | string.cpp:279:2:279:3 | s4 | | +| string.cpp:271:17:271:25 | call to basic_string | string.cpp:284:7:284:8 | s4 | | +| string.cpp:278:2:278:3 | ref arg s1 | string.cpp:281:7:281:8 | s1 | | +| string.cpp:278:10:278:11 | ref arg s2 | string.cpp:282:7:282:8 | s2 | | +| string.cpp:279:2:279:3 | ref arg s4 | string.cpp:284:7:284:8 | s4 | | +| string.cpp:279:10:279:11 | ref arg s3 | string.cpp:283:7:283:8 | s3 | | +| string.cpp:288:17:288:22 | call to source | string.cpp:288:17:288:25 | call to basic_string | TAINT | +| string.cpp:288:17:288:25 | call to basic_string | string.cpp:292:7:292:8 | s1 | | +| string.cpp:288:17:288:25 | call to basic_string | string.cpp:296:2:296:3 | s1 | | +| string.cpp:288:17:288:25 | call to basic_string | string.cpp:300:7:300:8 | s1 | | +| string.cpp:289:17:289:22 | call to source | string.cpp:289:17:289:25 | call to basic_string | TAINT | +| string.cpp:289:17:289:25 | call to basic_string | string.cpp:293:7:293:8 | s2 | | +| string.cpp:290:17:290:22 | call to source | string.cpp:290:17:290:25 | call to basic_string | TAINT | +| string.cpp:290:17:290:25 | call to basic_string | string.cpp:294:7:294:8 | s3 | | +| string.cpp:290:17:290:25 | call to basic_string | string.cpp:298:7:298:8 | s3 | | +| string.cpp:296:2:296:3 | ref arg s1 | string.cpp:300:7:300:8 | s1 | | +| string.cpp:297:7:297:8 | | string.cpp:297:7:297:8 | call to basic_string | TAINT | +| string.cpp:297:7:297:8 | call to basic_string | string.cpp:297:2:297:8 | ... = ... | | +| string.cpp:297:7:297:8 | call to basic_string | string.cpp:301:7:301:8 | s2 | | +| string.cpp:298:7:298:8 | s3 | string.cpp:298:2:298:8 | ... = ... | | +| string.cpp:298:7:298:8 | s3 | string.cpp:302:7:302:8 | s3 | | +| string.cpp:307:16:307:20 | 123 | string.cpp:307:16:307:21 | call to basic_string | TAINT | +| string.cpp:307:16:307:21 | call to basic_string | string.cpp:310:7:310:7 | a | | +| string.cpp:307:16:307:21 | call to basic_string | string.cpp:312:7:312:7 | a | | +| string.cpp:308:16:308:21 | call to source | string.cpp:308:16:308:24 | call to basic_string | TAINT | +| string.cpp:308:16:308:24 | call to basic_string | string.cpp:311:7:311:7 | b | | +| string.cpp:308:16:308:24 | call to basic_string | string.cpp:313:7:313:7 | b | | +| string.cpp:310:7:310:7 | ref arg a | string.cpp:312:7:312:7 | a | | +| string.cpp:311:7:311:7 | ref arg b | string.cpp:313:7:313:7 | b | | +| string.cpp:318:16:318:20 | 123 | string.cpp:318:16:318:21 | call to basic_string | TAINT | +| string.cpp:318:16:318:21 | call to basic_string | string.cpp:321:7:321:7 | a | | +| string.cpp:318:16:318:21 | call to basic_string | string.cpp:321:19:321:19 | a | | +| string.cpp:319:16:319:21 | call to source | string.cpp:319:16:319:24 | call to basic_string | TAINT | +| string.cpp:319:16:319:24 | call to basic_string | string.cpp:322:7:322:7 | b | | +| string.cpp:319:16:319:24 | call to basic_string | string.cpp:322:19:322:19 | b | | | stringstream.cpp:13:20:13:22 | call to basic_stringstream | stringstream.cpp:16:2:16:4 | ss1 | | | stringstream.cpp:13:20:13:22 | call to basic_stringstream | stringstream.cpp:22:7:22:9 | ss1 | | | stringstream.cpp:13:20:13:22 | call to basic_stringstream | stringstream.cpp:27:7:27:9 | ss1 | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp index 1b8f9c095ab..2ff9f66bc9d 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp @@ -184,3 +184,140 @@ void test_string_append() { sink(s10); // tainted } } + +void test_string_assign() { + std::string s1("hello"); + std::string s2(source()); + char c = ns_char::source(); + std::string s3, s4, s5; + std::string s6(source()); + + sink(s3.assign(s1)); + sink(s3); + + sink(s4.assign(s2)); // tainted [NOT DETECTED] + sink(s4); // tainted [NOT DETECTED] + + sink(s5.assign(10, c)); // tainted [NOT DETECTED] + sink(s5); // tainted [NOT DETECTED] + + sink(s6.assign(s1)); + sink(s6); // [FALSE POSITIVE] +} + +void test_string_insert() { + std::string s1("hello"); + std::string s2(source()); + char c = ns_char::source(); + std::string s3, s4, s5, s6; + + s3 = s1; + sink(s3.insert(0, s1)); + sink(s3); + + s4 = s2; + sink(s4.insert(0, s1)); // tainted [NOT DETECTED] + sink(s4); // tainted + + s5 = s1; + sink(s5.insert(0, s2)); // tainted [NOT DETECTED] + sink(s5); // tainted [NOT DETECTED] + + s6 = s1; + sink(s6.insert(0, 10, c)); // tainted [NOT DETECTED] + sink(s6); // tainted [NOT DETECTED] +} + +void test_string_replace() { + std::string s1("hello"); + std::string s2(source()); + char c = ns_char::source(); + std::string s3, s4, s5, s6; + + s3 = s1; + sink(s3.replace(1, 2, s1)); + sink(s3); + + s4 = s2; + sink(s4.replace(1, 2, s1)); // tainted [NOT DETECTED] + sink(s4); // tainted + + s5 = s1; + sink(s5.replace(1, 2, s2)); // tainted [NOT DETECTED] + sink(s5); // tainted [NOT DETECTED] + + s6 = s1; + sink(s6.replace(1, 2, 10, c)); // tainted [NOT DETECTED] + sink(s6); // tainted [NOT DETECTED] +} + +void test_string_copy() { + char b1[1024] = {0}; + char b2[1024] = {0}; + std::string s1("hello"); + std::string s2(source()); + + s1.copy(b1, s1.length(), 0); + sink(b1); + + s2.copy(b2, s1.length(), 0); + sink(b2); // tainted [NOT DETECTED] +} + +void test_string_swap() { + std::string s1("hello"); + std::string s2(source()); + std::string s3("world"); + std::string s4(source()); + + sink(s1); + sink(s2); // tainted + sink(s3); + sink(s4); // tainted + + s1.swap(s2); + s4.swap(s3); + + sink(s1); // tainted [NOT DETECTED] + sink(s2); // [FALSE POSITIVE] + sink(s3); // tainted [NOT DETECTED] + sink(s4); // [FALSE POSITIVE] +} + +void test_string_clear() { + std::string s1(source()); + std::string s2(source()); + std::string s3(source()); + + sink(s1); // tainted + sink(s2); // tainted + sink(s3); // tainted + + s1.clear(); + s2 = ""; + s3 = s3; + + sink(s1); // [FALSE POSITIVE] + sink(s2); + sink(s3); // tainted +} + +void test_string_data() +{ + std::string a("123"); + std::string b(source()); + + sink(a.data()); + sink(b.data()); // tainted // [FALSE POSITIVE] + sink(a.length()); + sink(b.length()); +} + +void test_string_substr() +{ + std::string a("123"); + std::string b(source()); + + sink(a.substr(0, a.length())); + sink(b.substr(0, b.length())); // tainted // [FALSE POSITIVE] +} diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected index 62fd58a3790..57375aa12d5 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -60,6 +60,18 @@ | string.cpp:171:8:171:9 | s8 | string.cpp:154:18:154:23 | call to source | | string.cpp:176:8:176:9 | s9 | string.cpp:174:13:174:18 | call to source | | string.cpp:184:8:184:10 | s10 | string.cpp:181:12:181:26 | call to source | +| string.cpp:205:7:205:8 | s6 | string.cpp:193:17:193:22 | call to source | +| string.cpp:220:7:220:8 | s4 | string.cpp:210:17:210:22 | call to source | +| string.cpp:243:7:243:8 | s4 | string.cpp:233:17:233:22 | call to source | +| string.cpp:274:7:274:8 | s2 | string.cpp:269:17:269:22 | call to source | +| string.cpp:276:7:276:8 | s4 | string.cpp:271:17:271:22 | call to source | +| string.cpp:282:7:282:8 | s2 | string.cpp:269:17:269:22 | call to source | +| string.cpp:284:7:284:8 | s4 | string.cpp:271:17:271:22 | call to source | +| string.cpp:292:7:292:8 | s1 | string.cpp:288:17:288:22 | call to source | +| string.cpp:293:7:293:8 | s2 | string.cpp:289:17:289:22 | call to source | +| string.cpp:294:7:294:8 | s3 | string.cpp:290:17:290:22 | call to source | +| string.cpp:300:7:300:8 | s1 | string.cpp:288:17:288:22 | call to source | +| string.cpp:302:7:302:8 | s3 | string.cpp:290:17:290:22 | call to source | | structlikeclass.cpp:35:8:35:9 | s1 | structlikeclass.cpp:29:22:29:27 | call to source | | structlikeclass.cpp:36:8:36:9 | s2 | structlikeclass.cpp:30:24:30:29 | call to source | | structlikeclass.cpp:37:8:37:9 | s3 | structlikeclass.cpp:29:22:29:27 | call to source | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected index ef4b311d954..20fbda5b74e 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected @@ -57,6 +57,18 @@ | string.cpp:171:8:171:9 | string.cpp:154:18:154:23 | AST only | | string.cpp:176:8:176:9 | string.cpp:174:13:174:18 | AST only | | string.cpp:184:8:184:10 | string.cpp:181:12:181:26 | AST only | +| string.cpp:205:7:205:8 | string.cpp:193:17:193:22 | AST only | +| string.cpp:220:7:220:8 | string.cpp:210:17:210:22 | AST only | +| string.cpp:243:7:243:8 | string.cpp:233:17:233:22 | AST only | +| string.cpp:274:7:274:8 | string.cpp:269:17:269:22 | AST only | +| string.cpp:276:7:276:8 | string.cpp:271:17:271:22 | AST only | +| string.cpp:282:7:282:8 | string.cpp:269:17:269:22 | AST only | +| string.cpp:284:7:284:8 | string.cpp:271:17:271:22 | AST only | +| string.cpp:292:7:292:8 | string.cpp:288:17:288:22 | AST only | +| string.cpp:293:7:293:8 | string.cpp:289:17:289:22 | AST only | +| string.cpp:294:7:294:8 | string.cpp:290:17:290:22 | AST only | +| string.cpp:300:7:300:8 | string.cpp:288:17:288:22 | AST only | +| string.cpp:302:7:302:8 | string.cpp:290:17:290:22 | AST only | | structlikeclass.cpp:35:8:35:9 | structlikeclass.cpp:29:22:29:27 | AST only | | structlikeclass.cpp:36:8:36:9 | structlikeclass.cpp:30:24:30:29 | AST only | | structlikeclass.cpp:37:8:37:9 | structlikeclass.cpp:29:22:29:27 | AST only | From a11ca06189410a765d16b7a10f0efeae0170cb95 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 17 Aug 2020 16:34:38 +0100 Subject: [PATCH 092/133] C++: Implement more std::string models. --- .../cpp/models/implementations/StdString.qll | 88 ++++++++++++++++++- .../dataflow/taint-tests/localTaint.expected | 34 +++++++ .../dataflow/taint-tests/string.cpp | 34 +++---- .../dataflow/taint-tests/taint.expected | 17 ++++ .../dataflow/taint-tests/test_diff.expected | 17 ++++ 5 files changed, 169 insertions(+), 21 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll index 06ca6ad8fd7..c80799667d1 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -8,10 +8,13 @@ class StdBasicString extends TemplateClass { } /** - * The standard function `std::string.c_str`. + * The `std::string` functions `c_str` and `data`. */ class StdStringCStr extends TaintFunction { - StdStringCStr() { this.hasQualifiedName("std", "basic_string", "c_str") } + StdStringCStr() { + this.hasQualifiedName("std", "basic_string", "c_str") or + this.hasQualifiedName("std", "basic_string", "data") + } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from string itself (qualifier) to return value @@ -40,12 +43,16 @@ class StdStringPlus extends TaintFunction { } /** - * The `std::string` functions `operator+=` and `append`. + * The `std::string` functions `operator+=`, `append`, `insert` and + * `replace`. All of these functions combine the existing string + * with a new string (or character) from one of the arguments. */ class StdStringAppend extends TaintFunction { StdStringAppend() { this.hasQualifiedName("std", "basic_string", "operator+=") or - this.hasQualifiedName("std", "basic_string", "append") + this.hasQualifiedName("std", "basic_string", "append") or + this.hasQualifiedName("std", "basic_string", "insert") or + this.hasQualifiedName("std", "basic_string", "replace") } /** @@ -67,3 +74,76 @@ class StdStringAppend extends TaintFunction { ) } } + +/** + * The standard function `std::string.assign`. + */ +class StdStringAssign extends TaintFunction { + StdStringAssign() { + this.hasQualifiedName("std", "basic_string", "assign") + } + + /** + * Gets the index of a parameter to this function that is a string (or + * character). + */ + int getAStringParameter() { + getParameter(result).getType() instanceof PointerType or + getParameter(result).getType() instanceof ReferenceType or + getParameter(result).getType() = getDeclaringType().getTemplateArgument(0) // i.e. `std::basic_string::CharT` + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // flow from parameter to string itself (qualifier) and return value + input.isParameterDeref(getAStringParameter()) and + ( + output.isQualifierObject() or + output.isReturnValueDeref() + ) + } +} + +/** + * The standard function `std::string.copy`. + */ +class StdStringCopy extends TaintFunction { + StdStringCopy() { + this.hasQualifiedName("std", "basic_string", "copy") + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // copy(dest, num, pos) + input.isQualifierObject() and + output.isParameterDeref(0) + } +} + +/** + * The standard function `std::string.substr`. + */ +class StdStringSubstr extends TaintFunction { + StdStringSubstr() { + this.hasQualifiedName("std", "basic_string", "substr") + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // substr(pos, num) + input.isQualifierObject() and + output.isReturnValue() + } +} + +/** + * The standard function `std::string.swap`. + */ +class StdStringSwap extends TaintFunction { + StdStringSwap() { this.hasQualifiedName("std", "basic_string", "swap") } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + input.isQualifierObject() and + output.isParameterDeref(0) + or + input.isParameterDeref(0) and + output.isQualifierObject() + } +} diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected index 5da1a754039..7d8e3f44091 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -510,9 +510,17 @@ | string.cpp:193:17:193:25 | call to basic_string | string.cpp:204:7:204:8 | s6 | | | string.cpp:193:17:193:25 | call to basic_string | string.cpp:205:7:205:8 | s6 | | | string.cpp:195:7:195:8 | ref arg s3 | string.cpp:196:7:196:8 | s3 | | +| string.cpp:195:17:195:18 | s1 | string.cpp:195:7:195:8 | ref arg s3 | TAINT | +| string.cpp:195:17:195:18 | s1 | string.cpp:195:10:195:15 | call to assign | TAINT | | string.cpp:198:7:198:8 | ref arg s4 | string.cpp:199:7:199:8 | s4 | | +| string.cpp:198:17:198:18 | s2 | string.cpp:198:7:198:8 | ref arg s4 | TAINT | +| string.cpp:198:17:198:18 | s2 | string.cpp:198:10:198:15 | call to assign | TAINT | | string.cpp:201:7:201:8 | ref arg s5 | string.cpp:202:7:202:8 | s5 | | +| string.cpp:201:21:201:21 | c | string.cpp:201:7:201:8 | ref arg s5 | TAINT | +| string.cpp:201:21:201:21 | c | string.cpp:201:10:201:15 | call to assign | TAINT | | string.cpp:204:7:204:8 | ref arg s6 | string.cpp:205:7:205:8 | s6 | | +| string.cpp:204:17:204:18 | s1 | string.cpp:204:7:204:8 | ref arg s6 | TAINT | +| string.cpp:204:17:204:18 | s1 | string.cpp:204:10:204:15 | call to assign | TAINT | | string.cpp:209:17:209:23 | hello | string.cpp:209:17:209:24 | call to basic_string | TAINT | | string.cpp:209:17:209:24 | call to basic_string | string.cpp:214:7:214:8 | s1 | | | string.cpp:209:17:209:24 | call to basic_string | string.cpp:215:20:215:21 | s1 | | @@ -527,18 +535,26 @@ | string.cpp:214:7:214:8 | s1 | string.cpp:215:7:215:8 | s3 | | | string.cpp:214:7:214:8 | s1 | string.cpp:216:7:216:8 | s3 | | | string.cpp:215:7:215:8 | ref arg s3 | string.cpp:216:7:216:8 | s3 | | +| string.cpp:215:20:215:21 | s1 | string.cpp:215:7:215:8 | ref arg s3 | TAINT | +| string.cpp:215:20:215:21 | s1 | string.cpp:215:10:215:15 | call to insert | TAINT | | string.cpp:218:7:218:8 | s2 | string.cpp:218:2:218:8 | ... = ... | | | string.cpp:218:7:218:8 | s2 | string.cpp:219:7:219:8 | s4 | | | string.cpp:218:7:218:8 | s2 | string.cpp:220:7:220:8 | s4 | | | string.cpp:219:7:219:8 | ref arg s4 | string.cpp:220:7:220:8 | s4 | | +| string.cpp:219:20:219:21 | s1 | string.cpp:219:7:219:8 | ref arg s4 | TAINT | +| string.cpp:219:20:219:21 | s1 | string.cpp:219:10:219:15 | call to insert | TAINT | | string.cpp:222:7:222:8 | s1 | string.cpp:222:2:222:8 | ... = ... | | | string.cpp:222:7:222:8 | s1 | string.cpp:223:7:223:8 | s5 | | | string.cpp:222:7:222:8 | s1 | string.cpp:224:7:224:8 | s5 | | | string.cpp:223:7:223:8 | ref arg s5 | string.cpp:224:7:224:8 | s5 | | +| string.cpp:223:20:223:21 | s2 | string.cpp:223:7:223:8 | ref arg s5 | TAINT | +| string.cpp:223:20:223:21 | s2 | string.cpp:223:10:223:15 | call to insert | TAINT | | string.cpp:226:7:226:8 | s1 | string.cpp:226:2:226:8 | ... = ... | | | string.cpp:226:7:226:8 | s1 | string.cpp:227:7:227:8 | s6 | | | string.cpp:226:7:226:8 | s1 | string.cpp:228:7:228:8 | s6 | | | string.cpp:227:7:227:8 | ref arg s6 | string.cpp:228:7:228:8 | s6 | | +| string.cpp:227:24:227:24 | c | string.cpp:227:7:227:8 | ref arg s6 | TAINT | +| string.cpp:227:24:227:24 | c | string.cpp:227:10:227:15 | call to insert | TAINT | | string.cpp:232:17:232:23 | hello | string.cpp:232:17:232:24 | call to basic_string | TAINT | | string.cpp:232:17:232:24 | call to basic_string | string.cpp:237:7:237:8 | s1 | | | string.cpp:232:17:232:24 | call to basic_string | string.cpp:238:24:238:25 | s1 | | @@ -553,18 +569,26 @@ | string.cpp:237:7:237:8 | s1 | string.cpp:238:7:238:8 | s3 | | | string.cpp:237:7:237:8 | s1 | string.cpp:239:7:239:8 | s3 | | | string.cpp:238:7:238:8 | ref arg s3 | string.cpp:239:7:239:8 | s3 | | +| string.cpp:238:24:238:25 | s1 | string.cpp:238:7:238:8 | ref arg s3 | TAINT | +| string.cpp:238:24:238:25 | s1 | string.cpp:238:10:238:16 | call to replace | TAINT | | string.cpp:241:7:241:8 | s2 | string.cpp:241:2:241:8 | ... = ... | | | string.cpp:241:7:241:8 | s2 | string.cpp:242:7:242:8 | s4 | | | string.cpp:241:7:241:8 | s2 | string.cpp:243:7:243:8 | s4 | | | string.cpp:242:7:242:8 | ref arg s4 | string.cpp:243:7:243:8 | s4 | | +| string.cpp:242:24:242:25 | s1 | string.cpp:242:7:242:8 | ref arg s4 | TAINT | +| string.cpp:242:24:242:25 | s1 | string.cpp:242:10:242:16 | call to replace | TAINT | | string.cpp:245:7:245:8 | s1 | string.cpp:245:2:245:8 | ... = ... | | | string.cpp:245:7:245:8 | s1 | string.cpp:246:7:246:8 | s5 | | | string.cpp:245:7:245:8 | s1 | string.cpp:247:7:247:8 | s5 | | | string.cpp:246:7:246:8 | ref arg s5 | string.cpp:247:7:247:8 | s5 | | +| string.cpp:246:24:246:25 | s2 | string.cpp:246:7:246:8 | ref arg s5 | TAINT | +| string.cpp:246:24:246:25 | s2 | string.cpp:246:10:246:16 | call to replace | TAINT | | string.cpp:249:7:249:8 | s1 | string.cpp:249:2:249:8 | ... = ... | | | string.cpp:249:7:249:8 | s1 | string.cpp:250:7:250:8 | s6 | | | string.cpp:249:7:249:8 | s1 | string.cpp:251:7:251:8 | s6 | | | string.cpp:250:7:250:8 | ref arg s6 | string.cpp:251:7:251:8 | s6 | | +| string.cpp:250:28:250:28 | c | string.cpp:250:7:250:8 | ref arg s6 | TAINT | +| string.cpp:250:28:250:28 | c | string.cpp:250:10:250:16 | call to replace | TAINT | | string.cpp:255:17:255:20 | {...} | string.cpp:260:10:260:11 | b1 | | | string.cpp:255:17:255:20 | {...} | string.cpp:261:7:261:8 | b1 | | | string.cpp:255:19:255:19 | 0 | string.cpp:255:17:255:20 | {...} | TAINT | @@ -577,7 +601,9 @@ | string.cpp:257:17:257:24 | call to basic_string | string.cpp:263:14:263:15 | s1 | | | string.cpp:258:17:258:22 | call to source | string.cpp:258:17:258:25 | call to basic_string | TAINT | | string.cpp:258:17:258:25 | call to basic_string | string.cpp:263:2:263:3 | s2 | | +| string.cpp:260:2:260:3 | s1 | string.cpp:260:10:260:11 | ref arg b1 | TAINT | | string.cpp:260:10:260:11 | ref arg b1 | string.cpp:261:7:261:8 | b1 | | +| string.cpp:263:2:263:3 | s2 | string.cpp:263:10:263:11 | ref arg b2 | TAINT | | string.cpp:263:10:263:11 | ref arg b2 | string.cpp:264:7:264:8 | b2 | | | string.cpp:268:17:268:23 | hello | string.cpp:268:17:268:24 | call to basic_string | TAINT | | string.cpp:268:17:268:24 | call to basic_string | string.cpp:273:7:273:8 | s1 | | @@ -596,9 +622,13 @@ | string.cpp:271:17:271:25 | call to basic_string | string.cpp:279:2:279:3 | s4 | | | string.cpp:271:17:271:25 | call to basic_string | string.cpp:284:7:284:8 | s4 | | | string.cpp:278:2:278:3 | ref arg s1 | string.cpp:281:7:281:8 | s1 | | +| string.cpp:278:2:278:3 | s1 | string.cpp:278:10:278:11 | ref arg s2 | TAINT | | string.cpp:278:10:278:11 | ref arg s2 | string.cpp:282:7:282:8 | s2 | | +| string.cpp:278:10:278:11 | s2 | string.cpp:278:2:278:3 | ref arg s1 | TAINT | | string.cpp:279:2:279:3 | ref arg s4 | string.cpp:284:7:284:8 | s4 | | +| string.cpp:279:2:279:3 | s4 | string.cpp:279:10:279:11 | ref arg s3 | TAINT | | string.cpp:279:10:279:11 | ref arg s3 | string.cpp:283:7:283:8 | s3 | | +| string.cpp:279:10:279:11 | s3 | string.cpp:279:2:279:3 | ref arg s4 | TAINT | | string.cpp:288:17:288:22 | call to source | string.cpp:288:17:288:25 | call to basic_string | TAINT | | string.cpp:288:17:288:25 | call to basic_string | string.cpp:292:7:292:8 | s1 | | | string.cpp:288:17:288:25 | call to basic_string | string.cpp:296:2:296:3 | s1 | | @@ -620,7 +650,9 @@ | string.cpp:308:16:308:21 | call to source | string.cpp:308:16:308:24 | call to basic_string | TAINT | | string.cpp:308:16:308:24 | call to basic_string | string.cpp:311:7:311:7 | b | | | string.cpp:308:16:308:24 | call to basic_string | string.cpp:313:7:313:7 | b | | +| string.cpp:310:7:310:7 | a | string.cpp:310:9:310:12 | call to data | TAINT | | string.cpp:310:7:310:7 | ref arg a | string.cpp:312:7:312:7 | a | | +| string.cpp:311:7:311:7 | b | string.cpp:311:9:311:12 | call to data | TAINT | | string.cpp:311:7:311:7 | ref arg b | string.cpp:313:7:313:7 | b | | | string.cpp:318:16:318:20 | 123 | string.cpp:318:16:318:21 | call to basic_string | TAINT | | string.cpp:318:16:318:21 | call to basic_string | string.cpp:321:7:321:7 | a | | @@ -628,6 +660,8 @@ | string.cpp:319:16:319:21 | call to source | string.cpp:319:16:319:24 | call to basic_string | TAINT | | string.cpp:319:16:319:24 | call to basic_string | string.cpp:322:7:322:7 | b | | | string.cpp:319:16:319:24 | call to basic_string | string.cpp:322:19:322:19 | b | | +| string.cpp:321:7:321:7 | a | string.cpp:321:9:321:14 | call to substr | TAINT | +| string.cpp:322:7:322:7 | b | string.cpp:322:9:322:14 | call to substr | TAINT | | stringstream.cpp:13:20:13:22 | call to basic_stringstream | stringstream.cpp:16:2:16:4 | ss1 | | | stringstream.cpp:13:20:13:22 | call to basic_stringstream | stringstream.cpp:22:7:22:9 | ss1 | | | stringstream.cpp:13:20:13:22 | call to basic_stringstream | stringstream.cpp:27:7:27:9 | ss1 | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp index 2ff9f66bc9d..7047c3ed5fe 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp @@ -195,11 +195,11 @@ void test_string_assign() { sink(s3.assign(s1)); sink(s3); - sink(s4.assign(s2)); // tainted [NOT DETECTED] - sink(s4); // tainted [NOT DETECTED] + sink(s4.assign(s2)); // tainted + sink(s4); // tainted - sink(s5.assign(10, c)); // tainted [NOT DETECTED] - sink(s5); // tainted [NOT DETECTED] + sink(s5.assign(10, c)); // tainted + sink(s5); // tainted sink(s6.assign(s1)); sink(s6); // [FALSE POSITIVE] @@ -220,12 +220,12 @@ void test_string_insert() { sink(s4); // tainted s5 = s1; - sink(s5.insert(0, s2)); // tainted [NOT DETECTED] - sink(s5); // tainted [NOT DETECTED] + sink(s5.insert(0, s2)); // tainted + sink(s5); // tainted s6 = s1; - sink(s6.insert(0, 10, c)); // tainted [NOT DETECTED] - sink(s6); // tainted [NOT DETECTED] + sink(s6.insert(0, 10, c)); // tainted + sink(s6); // tainted } void test_string_replace() { @@ -243,12 +243,12 @@ void test_string_replace() { sink(s4); // tainted s5 = s1; - sink(s5.replace(1, 2, s2)); // tainted [NOT DETECTED] - sink(s5); // tainted [NOT DETECTED] + sink(s5.replace(1, 2, s2)); // tainted + sink(s5); // tainted s6 = s1; - sink(s6.replace(1, 2, 10, c)); // tainted [NOT DETECTED] - sink(s6); // tainted [NOT DETECTED] + sink(s6.replace(1, 2, 10, c)); // tainted + sink(s6); // tainted } void test_string_copy() { @@ -261,7 +261,7 @@ void test_string_copy() { sink(b1); s2.copy(b2, s1.length(), 0); - sink(b2); // tainted [NOT DETECTED] + sink(b2); // tainted } void test_string_swap() { @@ -278,9 +278,9 @@ void test_string_swap() { s1.swap(s2); s4.swap(s3); - sink(s1); // tainted [NOT DETECTED] + sink(s1); // tainted sink(s2); // [FALSE POSITIVE] - sink(s3); // tainted [NOT DETECTED] + sink(s3); // tainted sink(s4); // [FALSE POSITIVE] } @@ -308,7 +308,7 @@ void test_string_data() std::string b(source()); sink(a.data()); - sink(b.data()); // tainted // [FALSE POSITIVE] + sink(b.data()); // tainted sink(a.length()); sink(b.length()); } @@ -319,5 +319,5 @@ void test_string_substr() std::string b(source()); sink(a.substr(0, a.length())); - sink(b.substr(0, b.length())); // tainted // [FALSE POSITIVE] + sink(b.substr(0, b.length())); // tainted } diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected index 57375aa12d5..4a7b7e90ba9 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -60,18 +60,35 @@ | string.cpp:171:8:171:9 | s8 | string.cpp:154:18:154:23 | call to source | | string.cpp:176:8:176:9 | s9 | string.cpp:174:13:174:18 | call to source | | string.cpp:184:8:184:10 | s10 | string.cpp:181:12:181:26 | call to source | +| string.cpp:198:10:198:15 | call to assign | string.cpp:190:17:190:22 | call to source | +| string.cpp:199:7:199:8 | s4 | string.cpp:190:17:190:22 | call to source | +| string.cpp:201:10:201:15 | call to assign | string.cpp:191:11:191:25 | call to source | +| string.cpp:202:7:202:8 | s5 | string.cpp:191:11:191:25 | call to source | | string.cpp:205:7:205:8 | s6 | string.cpp:193:17:193:22 | call to source | | string.cpp:220:7:220:8 | s4 | string.cpp:210:17:210:22 | call to source | +| string.cpp:223:10:223:15 | call to insert | string.cpp:210:17:210:22 | call to source | +| string.cpp:224:7:224:8 | s5 | string.cpp:210:17:210:22 | call to source | +| string.cpp:227:10:227:15 | call to insert | string.cpp:211:11:211:25 | call to source | +| string.cpp:228:7:228:8 | s6 | string.cpp:211:11:211:25 | call to source | | string.cpp:243:7:243:8 | s4 | string.cpp:233:17:233:22 | call to source | +| string.cpp:246:10:246:16 | call to replace | string.cpp:233:17:233:22 | call to source | +| string.cpp:247:7:247:8 | s5 | string.cpp:233:17:233:22 | call to source | +| string.cpp:250:10:250:16 | call to replace | string.cpp:234:11:234:25 | call to source | +| string.cpp:251:7:251:8 | s6 | string.cpp:234:11:234:25 | call to source | +| string.cpp:264:7:264:8 | b2 | string.cpp:258:17:258:22 | call to source | | string.cpp:274:7:274:8 | s2 | string.cpp:269:17:269:22 | call to source | | string.cpp:276:7:276:8 | s4 | string.cpp:271:17:271:22 | call to source | +| string.cpp:281:7:281:8 | s1 | string.cpp:269:17:269:22 | call to source | | string.cpp:282:7:282:8 | s2 | string.cpp:269:17:269:22 | call to source | +| string.cpp:283:7:283:8 | s3 | string.cpp:271:17:271:22 | call to source | | string.cpp:284:7:284:8 | s4 | string.cpp:271:17:271:22 | call to source | | string.cpp:292:7:292:8 | s1 | string.cpp:288:17:288:22 | call to source | | string.cpp:293:7:293:8 | s2 | string.cpp:289:17:289:22 | call to source | | string.cpp:294:7:294:8 | s3 | string.cpp:290:17:290:22 | call to source | | string.cpp:300:7:300:8 | s1 | string.cpp:288:17:288:22 | call to source | | string.cpp:302:7:302:8 | s3 | string.cpp:290:17:290:22 | call to source | +| string.cpp:311:9:311:12 | call to data | string.cpp:308:16:308:21 | call to source | +| string.cpp:322:9:322:14 | call to substr | string.cpp:319:16:319:21 | call to source | | structlikeclass.cpp:35:8:35:9 | s1 | structlikeclass.cpp:29:22:29:27 | call to source | | structlikeclass.cpp:36:8:36:9 | s2 | structlikeclass.cpp:30:24:30:29 | call to source | | structlikeclass.cpp:37:8:37:9 | s3 | structlikeclass.cpp:29:22:29:27 | call to source | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected index 20fbda5b74e..e6ccb3a2da4 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected @@ -57,18 +57,35 @@ | string.cpp:171:8:171:9 | string.cpp:154:18:154:23 | AST only | | string.cpp:176:8:176:9 | string.cpp:174:13:174:18 | AST only | | string.cpp:184:8:184:10 | string.cpp:181:12:181:26 | AST only | +| string.cpp:198:10:198:15 | string.cpp:190:17:190:22 | AST only | +| string.cpp:199:7:199:8 | string.cpp:190:17:190:22 | AST only | +| string.cpp:201:10:201:15 | string.cpp:191:11:191:25 | AST only | +| string.cpp:202:7:202:8 | string.cpp:191:11:191:25 | AST only | | string.cpp:205:7:205:8 | string.cpp:193:17:193:22 | AST only | | string.cpp:220:7:220:8 | string.cpp:210:17:210:22 | AST only | +| string.cpp:223:10:223:15 | string.cpp:210:17:210:22 | AST only | +| string.cpp:224:7:224:8 | string.cpp:210:17:210:22 | AST only | +| string.cpp:227:10:227:15 | string.cpp:211:11:211:25 | AST only | +| string.cpp:228:7:228:8 | string.cpp:211:11:211:25 | AST only | | string.cpp:243:7:243:8 | string.cpp:233:17:233:22 | AST only | +| string.cpp:246:10:246:16 | string.cpp:233:17:233:22 | AST only | +| string.cpp:247:7:247:8 | string.cpp:233:17:233:22 | AST only | +| string.cpp:250:10:250:16 | string.cpp:234:11:234:25 | AST only | +| string.cpp:251:7:251:8 | string.cpp:234:11:234:25 | AST only | +| string.cpp:264:7:264:8 | string.cpp:258:17:258:22 | AST only | | string.cpp:274:7:274:8 | string.cpp:269:17:269:22 | AST only | | string.cpp:276:7:276:8 | string.cpp:271:17:271:22 | AST only | +| string.cpp:281:7:281:8 | string.cpp:269:17:269:22 | AST only | | string.cpp:282:7:282:8 | string.cpp:269:17:269:22 | AST only | +| string.cpp:283:7:283:8 | string.cpp:271:17:271:22 | AST only | | string.cpp:284:7:284:8 | string.cpp:271:17:271:22 | AST only | | string.cpp:292:7:292:8 | string.cpp:288:17:288:22 | AST only | | string.cpp:293:7:293:8 | string.cpp:289:17:289:22 | AST only | | string.cpp:294:7:294:8 | string.cpp:290:17:290:22 | AST only | | string.cpp:300:7:300:8 | string.cpp:288:17:288:22 | AST only | | string.cpp:302:7:302:8 | string.cpp:290:17:290:22 | AST only | +| string.cpp:311:9:311:12 | string.cpp:308:16:308:21 | AST only | +| string.cpp:322:9:322:14 | string.cpp:319:16:319:21 | AST only | | structlikeclass.cpp:35:8:35:9 | structlikeclass.cpp:29:22:29:27 | AST only | | structlikeclass.cpp:36:8:36:9 | structlikeclass.cpp:30:24:30:29 | AST only | | structlikeclass.cpp:37:8:37:9 | structlikeclass.cpp:29:22:29:27 | AST only | From 0234bca6ca384d474898113502d7ad0c9085bb24 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 17 Aug 2020 17:14:25 +0100 Subject: [PATCH 093/133] C++: Fix a hole in StdStringAppend and clarify comments. --- .../code/cpp/models/implementations/StdString.qll | 8 ++++++-- .../dataflow/taint-tests/localTaint.expected | 15 +++++++++++++++ .../library-tests/dataflow/taint-tests/string.cpp | 4 ++-- .../dataflow/taint-tests/taint.expected | 2 ++ .../dataflow/taint-tests/test_diff.expected | 2 ++ 5 files changed, 27 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll index c80799667d1..a4bb6aac5f4 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -66,8 +66,11 @@ class StdStringAppend extends TaintFunction { } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { - // flow from parameter to string itself (qualifier) and return value - input.isParameterDeref(getAStringParameter()) and + // flow from string and parameter to string (qualifier) and return value + ( + input.isQualifierObject() or + input.isParameterDeref(getAStringParameter()) + ) and ( output.isQualifierObject() or output.isReturnValueDeref() @@ -140,6 +143,7 @@ class StdStringSwap extends TaintFunction { StdStringSwap() { this.hasQualifiedName("std", "basic_string", "swap") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // str1.swap(str2) input.isQualifierObject() and output.isParameterDeref(0) or diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected index 7d8e3f44091..d6852533305 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -457,6 +457,7 @@ | string.cpp:160:8:160:9 | s3 | string.cpp:161:3:161:4 | s6 | | | string.cpp:160:8:160:9 | s3 | string.cpp:162:8:162:9 | s6 | | | string.cpp:161:3:161:4 | ref arg s6 | string.cpp:162:8:162:9 | s6 | | +| string.cpp:161:3:161:4 | s6 | string.cpp:161:6:161:6 | call to operator+= | TAINT | | string.cpp:161:9:161:10 | s4 | string.cpp:161:3:161:4 | ref arg s6 | TAINT | | string.cpp:161:9:161:10 | s4 | string.cpp:161:6:161:6 | call to operator+= | TAINT | | string.cpp:164:8:164:9 | s3 | string.cpp:164:3:164:9 | ... = ... | | @@ -465,15 +466,18 @@ | string.cpp:164:8:164:9 | s3 | string.cpp:167:8:167:9 | s7 | | | string.cpp:165:3:165:4 | ref arg s7 | string.cpp:166:3:166:4 | s7 | | | string.cpp:165:3:165:4 | ref arg s7 | string.cpp:167:8:167:9 | s7 | | +| string.cpp:165:3:165:4 | s7 | string.cpp:165:6:165:6 | call to operator+= | TAINT | | string.cpp:165:9:165:14 | call to source | string.cpp:165:3:165:4 | ref arg s7 | TAINT | | string.cpp:165:9:165:14 | call to source | string.cpp:165:6:165:6 | call to operator+= | TAINT | | string.cpp:166:3:166:4 | ref arg s7 | string.cpp:167:8:167:9 | s7 | | +| string.cpp:166:3:166:4 | s7 | string.cpp:166:6:166:6 | call to operator+= | TAINT | | string.cpp:166:9:166:11 | | string.cpp:166:3:166:4 | ref arg s7 | TAINT | | string.cpp:166:9:166:11 | | string.cpp:166:6:166:6 | call to operator+= | TAINT | | string.cpp:169:8:169:9 | s3 | string.cpp:169:3:169:9 | ... = ... | | | string.cpp:169:8:169:9 | s3 | string.cpp:170:3:170:4 | s8 | | | string.cpp:169:8:169:9 | s3 | string.cpp:171:8:171:9 | s8 | | | string.cpp:170:3:170:4 | ref arg s8 | string.cpp:171:8:171:9 | s8 | | +| string.cpp:170:3:170:4 | s8 | string.cpp:170:6:170:11 | call to append | TAINT | | string.cpp:170:13:170:14 | s4 | string.cpp:170:3:170:4 | ref arg s8 | TAINT | | string.cpp:170:13:170:14 | s4 | string.cpp:170:6:170:11 | call to append | TAINT | | string.cpp:173:8:173:9 | s3 | string.cpp:173:3:173:9 | ... = ... | | @@ -482,9 +486,11 @@ | string.cpp:173:8:173:9 | s3 | string.cpp:176:8:176:9 | s9 | | | string.cpp:174:3:174:4 | ref arg s9 | string.cpp:175:3:175:4 | s9 | | | string.cpp:174:3:174:4 | ref arg s9 | string.cpp:176:8:176:9 | s9 | | +| string.cpp:174:3:174:4 | s9 | string.cpp:174:6:174:11 | call to append | TAINT | | string.cpp:174:13:174:18 | call to source | string.cpp:174:3:174:4 | ref arg s9 | TAINT | | string.cpp:174:13:174:18 | call to source | string.cpp:174:6:174:11 | call to append | TAINT | | string.cpp:175:3:175:4 | ref arg s9 | string.cpp:176:8:176:9 | s9 | | +| string.cpp:175:3:175:4 | s9 | string.cpp:175:6:175:11 | call to append | TAINT | | string.cpp:175:13:175:15 | | string.cpp:175:3:175:4 | ref arg s9 | TAINT | | string.cpp:175:13:175:15 | | string.cpp:175:6:175:11 | call to append | TAINT | | string.cpp:180:19:180:23 | abc | string.cpp:180:19:180:24 | call to basic_string | TAINT | @@ -492,6 +498,7 @@ | string.cpp:180:19:180:24 | call to basic_string | string.cpp:184:8:184:10 | s10 | | | string.cpp:181:12:181:26 | call to source | string.cpp:183:17:183:17 | c | | | string.cpp:183:3:183:5 | ref arg s10 | string.cpp:184:8:184:10 | s10 | | +| string.cpp:183:3:183:5 | s10 | string.cpp:183:7:183:12 | call to append | TAINT | | string.cpp:183:17:183:17 | c | string.cpp:183:3:183:5 | ref arg s10 | TAINT | | string.cpp:183:17:183:17 | c | string.cpp:183:7:183:12 | call to append | TAINT | | string.cpp:189:17:189:23 | hello | string.cpp:189:17:189:24 | call to basic_string | TAINT | @@ -535,24 +542,28 @@ | string.cpp:214:7:214:8 | s1 | string.cpp:215:7:215:8 | s3 | | | string.cpp:214:7:214:8 | s1 | string.cpp:216:7:216:8 | s3 | | | string.cpp:215:7:215:8 | ref arg s3 | string.cpp:216:7:216:8 | s3 | | +| string.cpp:215:7:215:8 | s3 | string.cpp:215:10:215:15 | call to insert | TAINT | | string.cpp:215:20:215:21 | s1 | string.cpp:215:7:215:8 | ref arg s3 | TAINT | | string.cpp:215:20:215:21 | s1 | string.cpp:215:10:215:15 | call to insert | TAINT | | string.cpp:218:7:218:8 | s2 | string.cpp:218:2:218:8 | ... = ... | | | string.cpp:218:7:218:8 | s2 | string.cpp:219:7:219:8 | s4 | | | string.cpp:218:7:218:8 | s2 | string.cpp:220:7:220:8 | s4 | | | string.cpp:219:7:219:8 | ref arg s4 | string.cpp:220:7:220:8 | s4 | | +| string.cpp:219:7:219:8 | s4 | string.cpp:219:10:219:15 | call to insert | TAINT | | string.cpp:219:20:219:21 | s1 | string.cpp:219:7:219:8 | ref arg s4 | TAINT | | string.cpp:219:20:219:21 | s1 | string.cpp:219:10:219:15 | call to insert | TAINT | | string.cpp:222:7:222:8 | s1 | string.cpp:222:2:222:8 | ... = ... | | | string.cpp:222:7:222:8 | s1 | string.cpp:223:7:223:8 | s5 | | | string.cpp:222:7:222:8 | s1 | string.cpp:224:7:224:8 | s5 | | | string.cpp:223:7:223:8 | ref arg s5 | string.cpp:224:7:224:8 | s5 | | +| string.cpp:223:7:223:8 | s5 | string.cpp:223:10:223:15 | call to insert | TAINT | | string.cpp:223:20:223:21 | s2 | string.cpp:223:7:223:8 | ref arg s5 | TAINT | | string.cpp:223:20:223:21 | s2 | string.cpp:223:10:223:15 | call to insert | TAINT | | string.cpp:226:7:226:8 | s1 | string.cpp:226:2:226:8 | ... = ... | | | string.cpp:226:7:226:8 | s1 | string.cpp:227:7:227:8 | s6 | | | string.cpp:226:7:226:8 | s1 | string.cpp:228:7:228:8 | s6 | | | string.cpp:227:7:227:8 | ref arg s6 | string.cpp:228:7:228:8 | s6 | | +| string.cpp:227:7:227:8 | s6 | string.cpp:227:10:227:15 | call to insert | TAINT | | string.cpp:227:24:227:24 | c | string.cpp:227:7:227:8 | ref arg s6 | TAINT | | string.cpp:227:24:227:24 | c | string.cpp:227:10:227:15 | call to insert | TAINT | | string.cpp:232:17:232:23 | hello | string.cpp:232:17:232:24 | call to basic_string | TAINT | @@ -569,24 +580,28 @@ | string.cpp:237:7:237:8 | s1 | string.cpp:238:7:238:8 | s3 | | | string.cpp:237:7:237:8 | s1 | string.cpp:239:7:239:8 | s3 | | | string.cpp:238:7:238:8 | ref arg s3 | string.cpp:239:7:239:8 | s3 | | +| string.cpp:238:7:238:8 | s3 | string.cpp:238:10:238:16 | call to replace | TAINT | | string.cpp:238:24:238:25 | s1 | string.cpp:238:7:238:8 | ref arg s3 | TAINT | | string.cpp:238:24:238:25 | s1 | string.cpp:238:10:238:16 | call to replace | TAINT | | string.cpp:241:7:241:8 | s2 | string.cpp:241:2:241:8 | ... = ... | | | string.cpp:241:7:241:8 | s2 | string.cpp:242:7:242:8 | s4 | | | string.cpp:241:7:241:8 | s2 | string.cpp:243:7:243:8 | s4 | | | string.cpp:242:7:242:8 | ref arg s4 | string.cpp:243:7:243:8 | s4 | | +| string.cpp:242:7:242:8 | s4 | string.cpp:242:10:242:16 | call to replace | TAINT | | string.cpp:242:24:242:25 | s1 | string.cpp:242:7:242:8 | ref arg s4 | TAINT | | string.cpp:242:24:242:25 | s1 | string.cpp:242:10:242:16 | call to replace | TAINT | | string.cpp:245:7:245:8 | s1 | string.cpp:245:2:245:8 | ... = ... | | | string.cpp:245:7:245:8 | s1 | string.cpp:246:7:246:8 | s5 | | | string.cpp:245:7:245:8 | s1 | string.cpp:247:7:247:8 | s5 | | | string.cpp:246:7:246:8 | ref arg s5 | string.cpp:247:7:247:8 | s5 | | +| string.cpp:246:7:246:8 | s5 | string.cpp:246:10:246:16 | call to replace | TAINT | | string.cpp:246:24:246:25 | s2 | string.cpp:246:7:246:8 | ref arg s5 | TAINT | | string.cpp:246:24:246:25 | s2 | string.cpp:246:10:246:16 | call to replace | TAINT | | string.cpp:249:7:249:8 | s1 | string.cpp:249:2:249:8 | ... = ... | | | string.cpp:249:7:249:8 | s1 | string.cpp:250:7:250:8 | s6 | | | string.cpp:249:7:249:8 | s1 | string.cpp:251:7:251:8 | s6 | | | string.cpp:250:7:250:8 | ref arg s6 | string.cpp:251:7:251:8 | s6 | | +| string.cpp:250:7:250:8 | s6 | string.cpp:250:10:250:16 | call to replace | TAINT | | string.cpp:250:28:250:28 | c | string.cpp:250:7:250:8 | ref arg s6 | TAINT | | string.cpp:250:28:250:28 | c | string.cpp:250:10:250:16 | call to replace | TAINT | | string.cpp:255:17:255:20 | {...} | string.cpp:260:10:260:11 | b1 | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp index 7047c3ed5fe..8fefb7daf52 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp @@ -216,7 +216,7 @@ void test_string_insert() { sink(s3); s4 = s2; - sink(s4.insert(0, s1)); // tainted [NOT DETECTED] + sink(s4.insert(0, s1)); // tainted sink(s4); // tainted s5 = s1; @@ -239,7 +239,7 @@ void test_string_replace() { sink(s3); s4 = s2; - sink(s4.replace(1, 2, s1)); // tainted [NOT DETECTED] + sink(s4.replace(1, 2, s1)); // tainted sink(s4); // tainted s5 = s1; diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected index 4a7b7e90ba9..89c371fe031 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -65,11 +65,13 @@ | string.cpp:201:10:201:15 | call to assign | string.cpp:191:11:191:25 | call to source | | string.cpp:202:7:202:8 | s5 | string.cpp:191:11:191:25 | call to source | | string.cpp:205:7:205:8 | s6 | string.cpp:193:17:193:22 | call to source | +| string.cpp:219:10:219:15 | call to insert | string.cpp:210:17:210:22 | call to source | | string.cpp:220:7:220:8 | s4 | string.cpp:210:17:210:22 | call to source | | string.cpp:223:10:223:15 | call to insert | string.cpp:210:17:210:22 | call to source | | string.cpp:224:7:224:8 | s5 | string.cpp:210:17:210:22 | call to source | | string.cpp:227:10:227:15 | call to insert | string.cpp:211:11:211:25 | call to source | | string.cpp:228:7:228:8 | s6 | string.cpp:211:11:211:25 | call to source | +| string.cpp:242:10:242:16 | call to replace | string.cpp:233:17:233:22 | call to source | | string.cpp:243:7:243:8 | s4 | string.cpp:233:17:233:22 | call to source | | string.cpp:246:10:246:16 | call to replace | string.cpp:233:17:233:22 | call to source | | string.cpp:247:7:247:8 | s5 | string.cpp:233:17:233:22 | call to source | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected index e6ccb3a2da4..1c7b86dfe38 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected @@ -62,11 +62,13 @@ | string.cpp:201:10:201:15 | string.cpp:191:11:191:25 | AST only | | string.cpp:202:7:202:8 | string.cpp:191:11:191:25 | AST only | | string.cpp:205:7:205:8 | string.cpp:193:17:193:22 | AST only | +| string.cpp:219:10:219:15 | string.cpp:210:17:210:22 | AST only | | string.cpp:220:7:220:8 | string.cpp:210:17:210:22 | AST only | | string.cpp:223:10:223:15 | string.cpp:210:17:210:22 | AST only | | string.cpp:224:7:224:8 | string.cpp:210:17:210:22 | AST only | | string.cpp:227:10:227:15 | string.cpp:211:11:211:25 | AST only | | string.cpp:228:7:228:8 | string.cpp:211:11:211:25 | AST only | +| string.cpp:242:10:242:16 | string.cpp:233:17:233:22 | AST only | | string.cpp:243:7:243:8 | string.cpp:233:17:233:22 | AST only | | string.cpp:246:10:246:16 | string.cpp:233:17:233:22 | AST only | | string.cpp:247:7:247:8 | string.cpp:233:17:233:22 | AST only | From 390af0d7d21ec03cbe482a7ec9d68d0d37607707 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 17 Aug 2020 17:46:25 +0100 Subject: [PATCH 094/133] C++: Autoformat. --- .../code/cpp/models/implementations/StdString.qll | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll index a4bb6aac5f4..fa2e37539eb 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -82,9 +82,7 @@ class StdStringAppend extends TaintFunction { * The standard function `std::string.assign`. */ class StdStringAssign extends TaintFunction { - StdStringAssign() { - this.hasQualifiedName("std", "basic_string", "assign") - } + StdStringAssign() { this.hasQualifiedName("std", "basic_string", "assign") } /** * Gets the index of a parameter to this function that is a string (or @@ -110,9 +108,7 @@ class StdStringAssign extends TaintFunction { * The standard function `std::string.copy`. */ class StdStringCopy extends TaintFunction { - StdStringCopy() { - this.hasQualifiedName("std", "basic_string", "copy") - } + StdStringCopy() { this.hasQualifiedName("std", "basic_string", "copy") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // copy(dest, num, pos) @@ -125,9 +121,7 @@ class StdStringCopy extends TaintFunction { * The standard function `std::string.substr`. */ class StdStringSubstr extends TaintFunction { - StdStringSubstr() { - this.hasQualifiedName("std", "basic_string", "substr") - } + StdStringSubstr() { this.hasQualifiedName("std", "basic_string", "substr") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // substr(pos, num) From d76b25ec2216bac4f18740fb0c6304f84c314dac Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 17 Aug 2020 17:47:20 +0100 Subject: [PATCH 095/133] C++: Change note. --- change-notes/1.26/analysis-cpp.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/change-notes/1.26/analysis-cpp.md b/change-notes/1.26/analysis-cpp.md index 867320915a9..bcd9b2ed66e 100644 --- a/change-notes/1.26/analysis-cpp.md +++ b/change-notes/1.26/analysis-cpp.md @@ -18,6 +18,6 @@ The following changes in version 1.26 affect C/C++ analysis in all applications. ## Changes to libraries -* The models library now models more taint flows through `std::string`. +* The models library now models many more taint flows through `std::string`. * The `SimpleRangeAnalysis` library now supports multiplications of the form `e1 * e2` when `e1` and `e2` are unsigned. From be91cec7add88307c86169ee6a18826384fd54c7 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 17 Aug 2020 20:43:25 +0100 Subject: [PATCH 096/133] C++: Add change note. --- change-notes/1.26/analysis-cpp.md | 1 + 1 file changed, 1 insertion(+) diff --git a/change-notes/1.26/analysis-cpp.md b/change-notes/1.26/analysis-cpp.md index 083229e18c4..855e51a0a59 100644 --- a/change-notes/1.26/analysis-cpp.md +++ b/change-notes/1.26/analysis-cpp.md @@ -14,6 +14,7 @@ The following changes in version 1.26 affect C/C++ analysis in all applications. | **Query** | **Expected impact** | **Change** | |----------------------------|------------------------|------------------------------------------------------------------| | Inconsistent direction of for loop (`cpp/inconsistent-loop-direction`) | Fewer false positive results | The query now accounts for intentional wrapping of an unsigned loop counter. | +| Overflow in uncontrolled allocation size (`cpp/uncontrolled-allocation-size`) | | The precision of this query has been decreased from "high" to "medium". As a result, the query is still run but results are no longer displayed on LGTM by default. | ## Changes to libraries From eba2c4331f38b949362374a4d0d129032a4b9024 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 18 Aug 2020 09:23:38 +0200 Subject: [PATCH 097/133] Add launch.json to gitignore --- csharp/.gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/csharp/.gitignore b/csharp/.gitignore index f81ecc73dff..0701c11fe1d 100644 --- a/csharp/.gitignore +++ b/csharp/.gitignore @@ -10,4 +10,5 @@ csharp.log **/bin/Release *.tlog .vs -*.user \ No newline at end of file +*.user +.vscode/launch.json \ No newline at end of file From 27345c64f3c29b37c04cf5a35a935c2f928c9273 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Tue, 18 Aug 2020 09:32:05 +0200 Subject: [PATCH 098/133] C++: Also accept PointlessComparison test changes --- .../PointlessComparison/PointlessComparison.expected | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/PointlessComparison/PointlessComparison.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/PointlessComparison/PointlessComparison.expected index 35ca55120df..ca99f8e6b03 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/PointlessComparison/PointlessComparison.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/PointlessComparison/PointlessComparison.expected @@ -43,8 +43,8 @@ | PointlessComparison.c:383:6:383:17 | ... >= ... | Comparison is always false because ... & ... <= 2. | | PointlessComparison.c:388:10:388:21 | ... > ... | Comparison is always false because ... * ... <= 408. | | PointlessComparison.c:391:12:391:20 | ... < ... | Comparison is always false because ... * ... >= 6. | -| PointlessComparison.c:414:7:414:16 | ... == ... | Comparison is always false because ... * ... >= 18446744073709552000. | -| PointlessComparison.cpp:36:6:36:33 | ... >= ... | Comparison is always false because ... >> ... <= 9223372036854776000. | +| PointlessComparison.c:414:7:414:16 | ... == ... | Comparison is always false because ... * ... >= 18446744073709551616. | +| PointlessComparison.cpp:36:6:36:33 | ... >= ... | Comparison is always false because ... >> ... <= 9223372036854775808. | | PointlessComparison.cpp:41:6:41:29 | ... >= ... | Comparison is always false because ... >> ... <= 140737488355327.5. | | PointlessComparison.cpp:42:6:42:29 | ... >= ... | Comparison is always false because ... >> ... <= 140737488355327.5. | | PointlessComparison.cpp:43:6:43:29 | ... >= ... | Comparison is always true because ... >> ... >= 140737488355327.5. | From d1b3963e2dce91d4fe8519e580737dcaaeeea066 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 18 Aug 2020 10:12:01 +0200 Subject: [PATCH 099/133] correctly treat ES2015 modules as being in strict-mode in the extractor --- .../com/semmle/js/extractor/ASTExtractor.java | 6 +++- .../CallGraphs/FullTest/non-strict.js | 8 +++++ .../CallGraphs/FullTest/strict.js | 10 +++++++ .../CallGraphs/FullTest/strict2.js | 12 ++++++++ .../CallGraphs/FullTest/tests.expected | 30 +++++++++++++++++++ 5 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 javascript/ql/test/library-tests/CallGraphs/FullTest/non-strict.js create mode 100644 javascript/ql/test/library-tests/CallGraphs/FullTest/strict.js create mode 100644 javascript/ql/test/library-tests/CallGraphs/FullTest/strict2.js diff --git a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java index 8dcc6d3a5c5..9e90fddfc85 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java @@ -669,7 +669,9 @@ public class ASTExtractor { public Label visit(Program nd, Context c) { contextManager.enterContainer(toplevelLabel); - isStrict = hasUseStrict(nd.getBody()); + boolean prevIsStrict = isStrict; + + isStrict = isStrict || hasUseStrict(nd.getBody()); // Add platform-specific globals. scopeManager.addVariables(platform.getPredefinedGlobals()); @@ -715,6 +717,8 @@ public class ASTExtractor { emitNodeSymbol(nd, toplevelLabel); + isStrict = prevIsStrict; + return toplevelLabel; } diff --git a/javascript/ql/test/library-tests/CallGraphs/FullTest/non-strict.js b/javascript/ql/test/library-tests/CallGraphs/FullTest/non-strict.js new file mode 100644 index 00000000000..eb6e20279ea --- /dev/null +++ b/javascript/ql/test/library-tests/CallGraphs/FullTest/non-strict.js @@ -0,0 +1,8 @@ +(function () { + if (true) { + function foo() { + return 3; + } + } + return foo(); // this resolves to `foo` above, because we have function-scope in non-strict mode. +})(); \ No newline at end of file diff --git a/javascript/ql/test/library-tests/CallGraphs/FullTest/strict.js b/javascript/ql/test/library-tests/CallGraphs/FullTest/strict.js new file mode 100644 index 00000000000..f3f949d1727 --- /dev/null +++ b/javascript/ql/test/library-tests/CallGraphs/FullTest/strict.js @@ -0,0 +1,10 @@ +(function () { + if (true) { + function foo() { + return 3; + } + } + return foo(); // `foo` is not defined, because we are in strict-mode. +})(); + +export default 3; // strict-mode implied because ES2015 module. \ No newline at end of file diff --git a/javascript/ql/test/library-tests/CallGraphs/FullTest/strict2.js b/javascript/ql/test/library-tests/CallGraphs/FullTest/strict2.js new file mode 100644 index 00000000000..a499b5c5a7f --- /dev/null +++ b/javascript/ql/test/library-tests/CallGraphs/FullTest/strict2.js @@ -0,0 +1,12 @@ +"use strict"; +(function () { + "use strict"; + if (true) { + function foo() { + return 3; + } + } + return foo(); // `foo` is not defined, because we are in strict-mode. +})(); + +export default 3; // strict-mode implied because ES2015 module. \ No newline at end of file diff --git a/javascript/ql/test/library-tests/CallGraphs/FullTest/tests.expected b/javascript/ql/test/library-tests/CallGraphs/FullTest/tests.expected index 90d47a02286..86cd32e4178 100644 --- a/javascript/ql/test/library-tests/CallGraphs/FullTest/tests.expected +++ b/javascript/ql/test/library-tests/CallGraphs/FullTest/tests.expected @@ -90,6 +90,11 @@ test_getAFunctionValue | m.js:3:1:3:16 | module.exports.f | m.js:1:13:1:25 | function() {} | | n.js:2:1:2:3 | m.f | m.js:1:13:1:25 | function() {} | | n.js:5:1:5:4 | m2.f | m2.js:2:6:2:18 | function() {} | +| non-strict.js:1:1:8:2 | (functi ... ode.\\n}) | non-strict.js:1:2:8:1 | functio ... mode.\\n} | +| non-strict.js:1:2:8:1 | functio ... mode.\\n} | non-strict.js:1:2:8:1 | functio ... mode.\\n} | +| non-strict.js:3:5:5:5 | functio ... ;\\n } | non-strict.js:3:5:5:5 | functio ... ;\\n } | +| non-strict.js:3:14:3:16 | foo | non-strict.js:3:5:5:5 | functio ... ;\\n } | +| non-strict.js:7:10:7:12 | foo | non-strict.js:3:5:5:5 | functio ... ;\\n } | | protoclass.js:3:1:5:1 | functio ... it();\\n} | protoclass.js:3:1:5:1 | functio ... it();\\n} | | protoclass.js:3:10:3:10 | F | protoclass.js:3:1:5:1 | functio ... it();\\n} | | protoclass.js:4:3:4:11 | this.init | protoclass.js:7:20:11:1 | functio ... m();\\n} | @@ -110,6 +115,12 @@ test_getAFunctionValue | reflection.js:7:1:7:3 | add | reflection.js:1:1:3:1 | functio ... x+y;\\n} | | reflection.js:8:1:8:3 | add | reflection.js:1:1:3:1 | functio ... x+y;\\n} | | reflection.js:8:1:8:9 | add.apply | reflection.js:5:15:5:39 | functio ... n 56; } | +| strict2.js:2:1:10:2 | (functi ... ode.\\n}) | strict2.js:2:2:10:1 | functio ... mode.\\n} | +| strict2.js:2:2:10:1 | functio ... mode.\\n} | strict2.js:2:2:10:1 | functio ... mode.\\n} | +| strict2.js:5:5:7:5 | functio ... ;\\n } | strict2.js:5:5:7:5 | functio ... ;\\n } | +| strict.js:1:1:8:2 | (functi ... ode.\\n}) | strict.js:1:2:8:1 | functio ... mode.\\n} | +| strict.js:1:2:8:1 | functio ... mode.\\n} | strict.js:1:2:8:1 | functio ... mode.\\n} | +| strict.js:3:5:5:5 | functio ... ;\\n } | strict.js:3:5:5:5 | functio ... ;\\n } | | tst3.js:1:1:1:22 | functio ... fn() {} | tst3.js:1:1:1:22 | functio ... fn() {} | | tst3.js:2:1:2:23 | functio ... n2() {} | tst3.js:2:1:2:23 | functio ... n2() {} | | tst.js:1:1:1:15 | function f() {} | tst.js:1:1:1:15 | function f() {} | @@ -225,6 +236,8 @@ test_getNumArgument | n.js:2:1:2:5 | m.f() | 0 | | n.js:4:10:4:24 | require('./m2') | 1 | | n.js:5:1:5:6 | m2.f() | 0 | +| non-strict.js:1:1:8:4 | (functi ... e.\\n})() | 0 | +| non-strict.js:7:10:7:14 | foo() | 0 | | protoclass.js:4:3:4:13 | this.init() | 0 | | protoclass.js:8:3:8:15 | this.method() | 0 | | protoclass.js:9:11:9:32 | this.me ... d(this) | 1 | @@ -233,6 +246,10 @@ test_getNumArgument | reflection.js:7:1:7:22 | add.cal ... 23, 19) | 3 | | reflection.js:7:1:7:22 | reflective call | 2 | | reflection.js:8:1:8:25 | add.app ... 3, 19]) | 2 | +| strict2.js:2:1:10:4 | (functi ... e.\\n})() | 0 | +| strict2.js:9:10:9:14 | foo() | 0 | +| strict.js:1:1:8:4 | (functi ... e.\\n})() | 0 | +| strict.js:7:10:7:14 | foo() | 0 | | tst.js:6:1:6:3 | f() | 0 | | tst.js:7:1:7:3 | g() | 0 | | tst.js:8:1:8:3 | h() | 0 | @@ -321,6 +338,8 @@ test_getCalleeNode | n.js:2:1:2:5 | m.f() | n.js:2:1:2:3 | m.f | | n.js:4:10:4:24 | require('./m2') | n.js:4:10:4:16 | require | | n.js:5:1:5:6 | m2.f() | n.js:5:1:5:4 | m2.f | +| non-strict.js:1:1:8:4 | (functi ... e.\\n})() | non-strict.js:1:1:8:2 | (functi ... ode.\\n}) | +| non-strict.js:7:10:7:14 | foo() | non-strict.js:7:10:7:12 | foo | | protoclass.js:4:3:4:13 | this.init() | protoclass.js:4:3:4:11 | this.init | | protoclass.js:8:3:8:15 | this.method() | protoclass.js:8:3:8:13 | this.method | | protoclass.js:9:11:9:32 | this.me ... d(this) | protoclass.js:9:11:9:26 | this.method.bind | @@ -330,6 +349,10 @@ test_getCalleeNode | reflection.js:7:1:7:22 | reflective call | reflection.js:7:1:7:3 | add | | reflection.js:8:1:8:25 | add.app ... 3, 19]) | reflection.js:8:1:8:9 | add.apply | | reflection.js:8:1:8:25 | reflective call | reflection.js:8:1:8:3 | add | +| strict2.js:2:1:10:4 | (functi ... e.\\n})() | strict2.js:2:1:10:2 | (functi ... ode.\\n}) | +| strict2.js:9:10:9:14 | foo() | strict2.js:9:10:9:12 | foo | +| strict.js:1:1:8:4 | (functi ... e.\\n})() | strict.js:1:1:8:2 | (functi ... ode.\\n}) | +| strict.js:7:10:7:14 | foo() | strict.js:7:10:7:12 | foo | | tst.js:6:1:6:3 | f() | tst.js:6:1:6:1 | f | | tst.js:7:1:7:3 | g() | tst.js:7:1:7:1 | g | | tst.js:8:1:8:3 | h() | tst.js:8:1:8:1 | h | @@ -408,11 +431,15 @@ test_getACallee | m.js:3:1:3:18 | module.exports.f() | m.js:1:13:1:25 | function() {} | | n.js:2:1:2:5 | m.f() | m.js:1:13:1:25 | function() {} | | n.js:5:1:5:6 | m2.f() | m2.js:2:6:2:18 | function() {} | +| non-strict.js:1:1:8:4 | (functi ... e.\\n})() | non-strict.js:1:2:8:1 | functio ... mode.\\n} | +| non-strict.js:7:10:7:14 | foo() | non-strict.js:3:5:5:5 | functio ... ;\\n } | | protoclass.js:4:3:4:13 | this.init() | protoclass.js:7:20:11:1 | functio ... m();\\n} | | protoclass.js:8:3:8:15 | this.method() | protoclass.js:13:22:13:34 | function() {} | | reflection.js:7:1:7:22 | reflective call | reflection.js:1:1:3:1 | functio ... x+y;\\n} | | reflection.js:8:1:8:25 | add.app ... 3, 19]) | reflection.js:5:15:5:39 | functio ... n 56; } | | reflection.js:8:1:8:25 | reflective call | reflection.js:1:1:3:1 | functio ... x+y;\\n} | +| strict2.js:2:1:10:4 | (functi ... e.\\n})() | strict2.js:2:2:10:1 | functio ... mode.\\n} | +| strict.js:1:1:8:4 | (functi ... e.\\n})() | strict.js:1:2:8:1 | functio ... mode.\\n} | | tst.js:6:1:6:3 | f() | tst.js:1:1:1:15 | function f() {} | | tst.js:7:1:7:3 | g() | tst.js:2:9:2:21 | function() {} | | tst.js:8:1:8:3 | h() | tst.js:3:5:3:17 | function() {} | @@ -463,6 +490,7 @@ test_getCalleeName | n.js:2:1:2:5 | m.f() | f | | n.js:4:10:4:24 | require('./m2') | require | | n.js:5:1:5:6 | m2.f() | f | +| non-strict.js:7:10:7:14 | foo() | foo | | protoclass.js:4:3:4:13 | this.init() | init | | protoclass.js:8:3:8:15 | this.method() | method | | protoclass.js:9:11:9:32 | this.me ... d(this) | bind | @@ -470,6 +498,8 @@ test_getCalleeName | reflection.js:4:5:4:12 | sneaky() | sneaky | | reflection.js:7:1:7:22 | add.cal ... 23, 19) | call | | reflection.js:8:1:8:25 | add.app ... 3, 19]) | apply | +| strict2.js:9:10:9:14 | foo() | foo | +| strict.js:7:10:7:14 | foo() | foo | | tst.js:6:1:6:3 | f() | f | | tst.js:7:1:7:3 | g() | g | | tst.js:8:1:8:3 | h() | h | From beeadea48fd51179f8e452515d6731df403609c6 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 18 Aug 2020 10:26:31 +0200 Subject: [PATCH 100/133] Add extra tests for partial methods --- .../partial/MethodIsPartial.expected | 7 ++++++ .../library-tests/partial/MethodIsPartial.ql | 7 ++++++ .../ql/test/library-tests/partial/Partial.cs | 24 ++++++++++++++----- .../library-tests/partial/Partial1.expected | 9 ++++--- .../library-tests/partial/Partial2.expected | 16 ++++++++----- .../partial/PartialMethodBody.expected | 3 +++ .../partial/PartialMethodBody.ql | 7 ++++++ 7 files changed, 58 insertions(+), 15 deletions(-) create mode 100644 csharp/ql/test/library-tests/partial/MethodIsPartial.expected create mode 100644 csharp/ql/test/library-tests/partial/MethodIsPartial.ql create mode 100644 csharp/ql/test/library-tests/partial/PartialMethodBody.expected create mode 100644 csharp/ql/test/library-tests/partial/PartialMethodBody.ql diff --git a/csharp/ql/test/library-tests/partial/MethodIsPartial.expected b/csharp/ql/test/library-tests/partial/MethodIsPartial.expected new file mode 100644 index 00000000000..8ee8f25b0c8 --- /dev/null +++ b/csharp/ql/test/library-tests/partial/MethodIsPartial.expected @@ -0,0 +1,7 @@ +| Partial.cs:3:18:3:39 | PartialMethodWithBody1 | true | +| Partial.cs:4:18:4:42 | PartialMethodWithoutBody1 | true | +| Partial.cs:5:17:5:23 | Method2 | false | +| Partial.cs:11:17:11:23 | Method3 | false | +| Partial.cs:16:18:16:42 | PartialMethodWithoutBody2 | true | +| Partial.cs:17:17:17:23 | Method4 | false | +| Partial.cs:22:17:22:23 | Method5 | false | diff --git a/csharp/ql/test/library-tests/partial/MethodIsPartial.ql b/csharp/ql/test/library-tests/partial/MethodIsPartial.ql new file mode 100644 index 00000000000..b7e50bd5a44 --- /dev/null +++ b/csharp/ql/test/library-tests/partial/MethodIsPartial.ql @@ -0,0 +1,7 @@ +import csharp + +private boolean isPartial(Method m) { if m.isPartial() then result = true else result = false } + +from Method m +where m.fromSource() +select m, isPartial(m) diff --git a/csharp/ql/test/library-tests/partial/Partial.cs b/csharp/ql/test/library-tests/partial/Partial.cs index e8efae8c52f..1d54614fc86 100644 --- a/csharp/ql/test/library-tests/partial/Partial.cs +++ b/csharp/ql/test/library-tests/partial/Partial.cs @@ -1,11 +1,23 @@ -partial class A +partial class TwoPartClass { - partial void M(); - public void M2() { } + partial void PartialMethodWithBody1(); + partial void PartialMethodWithoutBody1(); + public void Method2() { } } -partial class A +partial class TwoPartClass { - partial void M() { } - public void M3() { } + partial void PartialMethodWithBody1() { } + public void Method3() { } } + +partial class OnePartPartialClass +{ + partial void PartialMethodWithoutBody2(); + public void Method4() { } +} + +class NonPartialClass +{ + public void Method5() { } +} \ No newline at end of file diff --git a/csharp/ql/test/library-tests/partial/Partial1.expected b/csharp/ql/test/library-tests/partial/Partial1.expected index 3cc137e832f..722482cac4f 100644 --- a/csharp/ql/test/library-tests/partial/Partial1.expected +++ b/csharp/ql/test/library-tests/partial/Partial1.expected @@ -1,3 +1,6 @@ -| Partial.cs:1:15:1:15 | A | -| Partial.cs:3:18:3:18 | M | -| Partial.cs:7:15:7:15 | A | +| Partial.cs:1:15:1:26 | TwoPartClass | +| Partial.cs:3:18:3:39 | PartialMethodWithBody1 | +| Partial.cs:4:18:4:42 | PartialMethodWithoutBody1 | +| Partial.cs:8:15:8:26 | TwoPartClass | +| Partial.cs:14:15:14:33 | OnePartPartialClass | +| Partial.cs:16:18:16:42 | PartialMethodWithoutBody2 | diff --git a/csharp/ql/test/library-tests/partial/Partial2.expected b/csharp/ql/test/library-tests/partial/Partial2.expected index 079601bb497..6723b575fc7 100644 --- a/csharp/ql/test/library-tests/partial/Partial2.expected +++ b/csharp/ql/test/library-tests/partial/Partial2.expected @@ -1,6 +1,10 @@ -| Partial.cs:1:15:1:15 | A | Partial.cs:3:18:3:18 | M | -| Partial.cs:1:15:1:15 | A | Partial.cs:4:17:4:18 | M2 | -| Partial.cs:1:15:1:15 | A | Partial.cs:10:17:10:18 | M3 | -| Partial.cs:7:15:7:15 | A | Partial.cs:3:18:3:18 | M | -| Partial.cs:7:15:7:15 | A | Partial.cs:4:17:4:18 | M2 | -| Partial.cs:7:15:7:15 | A | Partial.cs:10:17:10:18 | M3 | +| Partial.cs:1:15:1:26 | TwoPartClass | Partial.cs:3:18:3:39 | PartialMethodWithBody1 | +| Partial.cs:1:15:1:26 | TwoPartClass | Partial.cs:4:18:4:42 | PartialMethodWithoutBody1 | +| Partial.cs:1:15:1:26 | TwoPartClass | Partial.cs:5:17:5:23 | Method2 | +| Partial.cs:1:15:1:26 | TwoPartClass | Partial.cs:11:17:11:23 | Method3 | +| Partial.cs:8:15:8:26 | TwoPartClass | Partial.cs:3:18:3:39 | PartialMethodWithBody1 | +| Partial.cs:8:15:8:26 | TwoPartClass | Partial.cs:4:18:4:42 | PartialMethodWithoutBody1 | +| Partial.cs:8:15:8:26 | TwoPartClass | Partial.cs:5:17:5:23 | Method2 | +| Partial.cs:8:15:8:26 | TwoPartClass | Partial.cs:11:17:11:23 | Method3 | +| Partial.cs:14:15:14:33 | OnePartPartialClass | Partial.cs:16:18:16:42 | PartialMethodWithoutBody2 | +| Partial.cs:14:15:14:33 | OnePartPartialClass | Partial.cs:17:17:17:23 | Method4 | diff --git a/csharp/ql/test/library-tests/partial/PartialMethodBody.expected b/csharp/ql/test/library-tests/partial/PartialMethodBody.expected new file mode 100644 index 00000000000..e6592704f1a --- /dev/null +++ b/csharp/ql/test/library-tests/partial/PartialMethodBody.expected @@ -0,0 +1,3 @@ +| Partial.cs:3:18:3:39 | PartialMethodWithBody1 | true | +| Partial.cs:4:18:4:42 | PartialMethodWithoutBody1 | false | +| Partial.cs:16:18:16:42 | PartialMethodWithoutBody2 | false | diff --git a/csharp/ql/test/library-tests/partial/PartialMethodBody.ql b/csharp/ql/test/library-tests/partial/PartialMethodBody.ql new file mode 100644 index 00000000000..53cb9be250a --- /dev/null +++ b/csharp/ql/test/library-tests/partial/PartialMethodBody.ql @@ -0,0 +1,7 @@ +import csharp + +private boolean hasBody(Method m) { if m.hasBody() then result = true else result = false } + +from Method m +where m.fromSource() and m.isPartial() +select m, hasBody(m) From a7d9715fd9ea4b26b6f285bdfb789c880230e80b Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Mon, 10 Aug 2020 17:36:33 +0200 Subject: [PATCH 101/133] C++: BinaryOperation.hasOperands QLDoc borrowed from JavaScript. Implementation borrowed from Java. Parameter names changed. --- cpp/ql/src/semmle/code/cpp/exprs/Expr.qll | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/exprs/Expr.qll b/cpp/ql/src/semmle/code/cpp/exprs/Expr.qll index a24c08b4f05..df347235006 100644 --- a/cpp/ql/src/semmle/code/cpp/exprs/Expr.qll +++ b/cpp/ql/src/semmle/code/cpp/exprs/Expr.qll @@ -539,6 +539,17 @@ class BinaryOperation extends Operation, @bin_op_expr { /** Gets the right operand of this binary operation. */ Expr getRightOperand() { this.hasChild(result, 1) } + /** + * Holds if `e1` and `e2` (in either order) are the two operands of this + * binary operation. + */ + predicate hasOperands(Expr e1, Expr e2) { + exists(int i | i in [0 .. 1] | + this.hasChild(e1, i) and + this.hasChild(e2, 1 - i) + ) + } + override string toString() { result = "... " + this.getOperator() + " ..." } override predicate mayBeImpure() { From 2e2f99cabfe0c0109105108868e8cc5b40699949 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Tue, 18 Aug 2020 10:39:57 +0200 Subject: [PATCH 102/133] C++: Correctly classify the MulExpr rounding bugs --- .../library-tests/rangeanalysis/SimpleRangeAnalysis/test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c index e85f44b73c2..16e9089aa0b 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c @@ -476,13 +476,13 @@ unsigned long mult_overflow() { x = 274177UL; y = 67280421310721UL; xy = x * y; - return xy; // BUG: lower bound should be <= 18446744073709551617UL + return xy; // BUG: upper bound should be >= 18446744073709551617UL } unsigned long mult_lower_bound(unsigned int ui, unsigned long ul) { if (ui >= 10) { unsigned long result = (unsigned long)ui * ui; - return result; // BUG: upper bound should be >= 18446744065119617025 (possibly a pretty-printing bug) + return result; // BUG: upper bound should be >= 18446744065119617025 } if (ul >= 10) { unsigned long result = ul * ul; From 6ae53b18652c5a275c9a6a50bee8bd8d98a05059 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 18 Aug 2020 11:10:04 +0200 Subject: [PATCH 103/133] C#: Add change notes for C# analysis --- change-notes/1.26/analysis-csharp.md | 29 ++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 change-notes/1.26/analysis-csharp.md diff --git a/change-notes/1.26/analysis-csharp.md b/change-notes/1.26/analysis-csharp.md new file mode 100644 index 00000000000..5580938dc2a --- /dev/null +++ b/change-notes/1.26/analysis-csharp.md @@ -0,0 +1,29 @@ +# Improvements to C# analysis + +The following changes in version 1.26 affect C# analysis in all applications. + +## New queries + +| **Query** | **Tags** | **Purpose** | +|-----------------------------|-----------|--------------------------------------------------------------------| + + +## Changes to existing queries + +| **Query** | **Expected impact** | **Change** | +|------------------------------|------------------------|-----------------------------------| + + +## Removal of old queries + +## Changes to code extraction + +* Partial method bodies are extracted. Previously, partial method bodies were skipped completely. + +## Changes to libraries + +## Changes to autobuilder + +## Changes to tooling support + +* The Abstract Syntax Tree of C# files can be printed in Visual Studio Code. From 03cb95c82bfbf92aa61cc498af81d60507e81b9c Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 18 Aug 2020 11:20:04 +0200 Subject: [PATCH 104/133] bump extractor version --- javascript/extractor/src/com/semmle/js/extractor/Main.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/extractor/src/com/semmle/js/extractor/Main.java b/javascript/extractor/src/com/semmle/js/extractor/Main.java index 119b6647a80..451baa73a46 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/Main.java +++ b/javascript/extractor/src/com/semmle/js/extractor/Main.java @@ -43,7 +43,7 @@ public class Main { * A version identifier that should be updated every time the extractor changes in such a way that * it may produce different tuples for the same file under the same {@link ExtractorConfig}. */ - public static final String EXTRACTOR_VERSION = "2020-04-01"; + public static final String EXTRACTOR_VERSION = "2020-08-18"; public static final Pattern NEWLINE = Pattern.compile("\n"); From b6b72729f6869b2acb83917e2be61fb0fcea6e81 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Fri, 14 Aug 2020 16:56:15 +0200 Subject: [PATCH 105/133] C++: SimpleRangeAnalysis for MulExpr by constant --- .../cpp/rangeanalysis/SimpleRangeAnalysis.qll | 135 +++++++++++------- .../SimpleRangeAnalysis/lowerBound.expected | 19 +++ .../rangeanalysis/SimpleRangeAnalysis/test.c | 22 +++ .../SimpleRangeAnalysis/upperBound.expected | 19 +++ 4 files changed, 142 insertions(+), 53 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll index c275c7c5db0..7e14996a91d 100644 --- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll @@ -156,8 +156,65 @@ float safeFloor(float v) { result = v } +/** A `MulExpr` where exactly one operand is constant. */ +private class MulByConstantExpr extends MulExpr { + float constant; + Expr operand; + + MulByConstantExpr() { + exists(Expr constantExpr | + this.hasOperands(constantExpr, operand) and + constant = constantExpr.getFullyConverted().getValue().toFloat() and + not exists(operand.getFullyConverted().getValue().toFloat()) + ) + } + + /** Gets the value of the constant operand. */ + float getConstant() { result = constant } + + /** Gets the non-constant operand. */ + Expr getOperand() { result = operand } +} + private class UnsignedMulExpr extends MulExpr { - UnsignedMulExpr() { this.getType().(IntegralType).isUnsigned() } + UnsignedMulExpr() { + this.getType().(IntegralType).isUnsigned() and + // Avoid overlap. It should be slightly cheaper to analyze + // `MulByConstantExpr`. + not this instanceof MulByConstantExpr + } +} + +/** + * Holds if `expr` is effectively a multiplication of `operand` with the + * positive constant `positive`. + */ +private predicate multipliesByPositive(Expr expr, Expr operand, float positive) { + operand = expr.(MulByConstantExpr).getOperand() and + positive = expr.(MulByConstantExpr).getConstant() and + positive >= 0.0 // includes positive zero + or + operand = expr.(UnaryPlusExpr).getOperand() and + positive = 1.0 + or + operand = expr.(CommaExpr).getRightOperand() and + positive = 1.0 + or + operand = expr.(StmtExpr).getResultExpr() and + positive = 1.0 +} + +/** + * Holds if `expr` is effectively a multiplication of `operand` with the + * negative constant `negative`. + */ +private predicate multipliesByNegative(Expr expr, Expr operand, float negative) { + operand = expr.(MulByConstantExpr).getOperand() and + negative = expr.(MulByConstantExpr).getConstant() and + negative < 0.0 // includes negative zero + or + operand = expr.(UnaryMinusExpr).getOperand() and + negative = -1.0 } private class UnsignedAssignMulExpr extends AssignMulExpr { @@ -172,9 +229,9 @@ private predicate analyzableExpr(Expr e) { ( exists(getValue(e).toFloat()) or - e instanceof UnaryPlusExpr + multipliesByPositive(e, _, _) or - e instanceof UnaryMinusExpr + multipliesByNegative(e, _, _) or e instanceof MinExpr or @@ -200,10 +257,6 @@ private predicate analyzableExpr(Expr e) { or e instanceof RemExpr or - e instanceof CommaExpr - or - e instanceof StmtExpr - or // A conversion is analyzable, provided that its child has an arithmetic // type. (Sometimes the child is a reference type, and so does not get // any bounds.) Rather than checking whether the type of the child is @@ -272,12 +325,14 @@ private predicate defDependsOnDef( * the structure of `getLowerBoundsImpl` and `getUpperBoundsImpl`. */ private predicate exprDependsOnDef(Expr e, RangeSsaDefinition srcDef, StackVariable srcVar) { - exists(UnaryMinusExpr negateExpr | e = negateExpr | - exprDependsOnDef(negateExpr.getOperand(), srcDef, srcVar) + exists(Expr operand | + multipliesByNegative(e, operand, _) and + exprDependsOnDef(operand, srcDef, srcVar) ) or - exists(UnaryPlusExpr plusExpr | e = plusExpr | - exprDependsOnDef(plusExpr.getOperand(), srcDef, srcVar) + exists(Expr operand | + multipliesByPositive(e, operand, _) and + exprDependsOnDef(operand, srcDef, srcVar) ) or exists(MinExpr minExpr | e = minExpr | exprDependsOnDef(minExpr.getAnOperand(), srcDef, srcVar)) @@ -316,14 +371,6 @@ private predicate exprDependsOnDef(Expr e, RangeSsaDefinition srcDef, StackVaria or exists(RemExpr remExpr | e = remExpr | exprDependsOnDef(remExpr.getAnOperand(), srcDef, srcVar)) or - exists(CommaExpr commaExpr | e = commaExpr | - exprDependsOnDef(commaExpr.getRightOperand(), srcDef, srcVar) - ) - or - exists(StmtExpr stmtExpr | e = stmtExpr | - exprDependsOnDef(stmtExpr.getResultExpr(), srcDef, srcVar) - ) - or exists(Conversion convExpr | e = convExpr | exprDependsOnDef(convExpr.getExpr(), srcDef, srcVar)) or // unsigned `&` @@ -592,15 +639,16 @@ deprecated predicate positive_overflow(Expr expr) { exprMightOverflowPositively( /** Only to be called by `getTruncatedLowerBounds`. */ private float getLowerBoundsImpl(Expr expr) { - exists(UnaryPlusExpr plusExpr | - expr = plusExpr and - result = getFullyConvertedLowerBounds(plusExpr.getOperand()) + exists(Expr operand, float operandLow, float positive | + multipliesByPositive(expr, operand, positive) and + operandLow = getFullyConvertedLowerBounds(operand) and + result = positive * operandLow ) or - exists(UnaryMinusExpr negateExpr, float xHigh | - expr = negateExpr and - xHigh = getFullyConvertedUpperBounds(negateExpr.getOperand()) and - result = -xHigh + exists(Expr operand, float operandHigh, float negative | + multipliesByNegative(expr, operand, negative) and + operandHigh = getFullyConvertedUpperBounds(operand) and + result = negative * operandHigh ) or exists(MinExpr minExpr | @@ -732,16 +780,6 @@ private float getLowerBoundsImpl(Expr expr) { ) ) or - exists(CommaExpr commaExpr | - expr = commaExpr and - result = getFullyConvertedLowerBounds(commaExpr.getRightOperand()) - ) - or - exists(StmtExpr stmtExpr | - expr = stmtExpr and - result = getFullyConvertedLowerBounds(stmtExpr.getResultExpr()) - ) - or // If the conversion is to an arithmetic type then we just return the // lower bound of the child. We do not need to handle truncation and // overflow here, because that is done in `getTruncatedLowerBounds`. @@ -775,15 +813,16 @@ private float getLowerBoundsImpl(Expr expr) { /** Only to be called by `getTruncatedUpperBounds`. */ private float getUpperBoundsImpl(Expr expr) { - exists(UnaryPlusExpr plusExpr | - expr = plusExpr and - result = getFullyConvertedUpperBounds(plusExpr.getOperand()) + exists(Expr operand, float operandHigh, float positive | + multipliesByPositive(expr, operand, positive) and + operandHigh = getFullyConvertedUpperBounds(operand) and + result = positive * operandHigh ) or - exists(UnaryMinusExpr negateExpr, float xLow | - expr = negateExpr and - xLow = getFullyConvertedLowerBounds(negateExpr.getOperand()) and - result = -xLow + exists(Expr operand, float operandLow, float negative | + multipliesByNegative(expr, operand, negative) and + operandLow = getFullyConvertedLowerBounds(operand) and + result = negative * operandLow ) or exists(MaxExpr maxExpr | @@ -913,16 +952,6 @@ private float getUpperBoundsImpl(Expr expr) { ) ) or - exists(CommaExpr commaExpr | - expr = commaExpr and - result = getFullyConvertedUpperBounds(commaExpr.getRightOperand()) - ) - or - exists(StmtExpr stmtExpr | - expr = stmtExpr and - result = getFullyConvertedUpperBounds(stmtExpr.getResultExpr()) - ) - or // If the conversion is to an arithmetic type then we just return the // upper bound of the child. We do not need to handle truncation and // overflow here, because that is done in `getTruncatedUpperBounds`. diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected index 92b68b47a1c..2bf4a5b9418 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected @@ -510,6 +510,25 @@ | test.c:504:3:504:9 | ulconst | 10 | | test.c:505:10:505:16 | uiconst | 40 | | test.c:505:20:505:26 | ulconst | 40 | +| test.c:509:7:509:7 | i | -2147483648 | +| test.c:509:18:509:18 | i | -1 | +| test.c:510:5:510:5 | i | -2147483648 | +| test.c:510:13:510:13 | i | -1 | +| test.c:511:9:511:9 | i | -5 | +| test.c:513:5:513:5 | i | -2147483648 | +| test.c:513:9:513:9 | i | -5 | +| test.c:514:9:514:9 | i | -30 | +| test.c:516:5:516:5 | i | -30 | +| test.c:517:9:517:9 | i | -2147483648 | +| test.c:519:5:519:5 | i | -2147483648 | +| test.c:520:9:520:9 | i | -2147483648 | +| test.c:522:7:522:7 | i | -2147483648 | +| test.c:523:5:523:5 | i | -2147483648 | +| test.c:523:9:523:9 | i | -1 | +| test.c:524:9:524:9 | i | 1 | +| test.c:526:3:526:3 | i | -2147483648 | +| test.c:526:7:526:7 | i | -2147483648 | +| test.c:527:10:527:10 | i | -2147483648 | | test.cpp:10:7:10:7 | b | -2147483648 | | test.cpp:11:5:11:5 | x | -2147483648 | | test.cpp:13:10:13:10 | x | -2147483648 | diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c index 3e09ccc54d7..c66d50eb630 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c @@ -504,3 +504,25 @@ unsigned long mul_assign(unsigned int ui) { ulconst *= 4; return uiconst + ulconst; // 40 .. 40 for both } + +int mul_by_constant(int i, int j) { + if (i >= -1 && i <= 2) { + i = 5 * i; + out(i); // -5 .. 10 + + i = i * -3; + out(i); // -30 .. 15 + + i *= 7; + out(i); // -210 .. 105 [BUG: not supported] + + i *= -11; + out(i); // -1155 .. 2310 [BUG: not supported] + } + if (i == -1) { + i = i * (int)0xffFFffFF; // fully converted literal is -1 + out(i); // 1 .. 1 + } + i = i * -1; + return i; // -2^31 .. 2^31-1 +} diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected index ebd9c88bffb..1d070d0d117 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected @@ -510,6 +510,25 @@ | test.c:504:3:504:9 | ulconst | 10 | | test.c:505:10:505:16 | uiconst | 40 | | test.c:505:20:505:26 | ulconst | 40 | +| test.c:509:7:509:7 | i | 2147483647 | +| test.c:509:18:509:18 | i | 2147483647 | +| test.c:510:5:510:5 | i | 2147483647 | +| test.c:510:13:510:13 | i | 2 | +| test.c:511:9:511:9 | i | 10 | +| test.c:513:5:513:5 | i | 2147483647 | +| test.c:513:9:513:9 | i | 10 | +| test.c:514:9:514:9 | i | 15 | +| test.c:516:5:516:5 | i | 15 | +| test.c:517:9:517:9 | i | 2147483647 | +| test.c:519:5:519:5 | i | 2147483647 | +| test.c:520:9:520:9 | i | 2147483647 | +| test.c:522:7:522:7 | i | 2147483647 | +| test.c:523:5:523:5 | i | 2147483647 | +| test.c:523:9:523:9 | i | -1 | +| test.c:524:9:524:9 | i | 1 | +| test.c:526:3:526:3 | i | 2147483647 | +| test.c:526:7:526:7 | i | 2147483647 | +| test.c:527:10:527:10 | i | 2147483647 | | test.cpp:10:7:10:7 | b | 2147483647 | | test.cpp:11:5:11:5 | x | 2147483647 | | test.cpp:13:10:13:10 | x | 2147483647 | From 99e62ceee6d41fdb335bbed5a2802ae06bdc2819 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 18 Aug 2020 11:44:24 +0200 Subject: [PATCH 106/133] C#: Add test for length argument of implicitly sized arrays --- .../expressions/ArrayCreation11.expected | 3 +++ .../library-tests/expressions/ArrayCreation11.ql | 13 +++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 csharp/ql/test/library-tests/expressions/ArrayCreation11.expected create mode 100644 csharp/ql/test/library-tests/expressions/ArrayCreation11.ql diff --git a/csharp/ql/test/library-tests/expressions/ArrayCreation11.expected b/csharp/ql/test/library-tests/expressions/ArrayCreation11.expected new file mode 100644 index 00000000000..985ce15c052 --- /dev/null +++ b/csharp/ql/test/library-tests/expressions/ArrayCreation11.expected @@ -0,0 +1,3 @@ +| expressions.cs:168:27:168:44 | array creation of type Object[] | expressions.cs:168:27:168:44 | 1 | false | +| expressions.cs:409:23:409:65 | array creation of type Int32[,] | expressions.cs:409:23:409:65 | 3 | false | +| expressions.cs:409:23:409:65 | array creation of type Int32[,] | expressions.cs:409:23:409:65 | 3 | false | diff --git a/csharp/ql/test/library-tests/expressions/ArrayCreation11.ql b/csharp/ql/test/library-tests/expressions/ArrayCreation11.ql new file mode 100644 index 00000000000..6d7a501fefa --- /dev/null +++ b/csharp/ql/test/library-tests/expressions/ArrayCreation11.ql @@ -0,0 +1,13 @@ +/** + * @name Test for array creations + */ + +import csharp + +private boolean isImplicit(Expr expr) { + if expr.isImplicit() then result = true else result = false +} + +from ArrayCreation ac, Expr expr +where ac.isImplicitlySized() and not ac.isImplicitlyTyped() and expr = ac.getALengthArgument() +select ac, expr, isImplicit(expr) From 0cf4c99986f4c8820e979132922b1c214ec501a4 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 18 Aug 2020 12:06:01 +0200 Subject: [PATCH 107/133] C#: Change compiler generated flag for length arguments of implicitly sized arrays --- .../Entities/Expressions/ArrayCreation.cs | 4 ++-- .../test/library-tests/expressions/ArrayCreation11.expected | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ArrayCreation.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ArrayCreation.cs index a4b1a4beb09..068cf2368fd 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ArrayCreation.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ArrayCreation.cs @@ -17,7 +17,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions protected abstract ArrayTypeSyntax TypeSyntax { get; } - public abstract InitializerExpressionSyntax Initializer { get; } + public abstract InitializerExpressionSyntax Initializer { get; } protected override void PopulateExpression(TextWriter trapFile) { @@ -48,7 +48,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions ExprKind.INT_LITERAL, this, child, - false, + true, size.ToString()); new Expression(info); diff --git a/csharp/ql/test/library-tests/expressions/ArrayCreation11.expected b/csharp/ql/test/library-tests/expressions/ArrayCreation11.expected index 985ce15c052..f0e5752ac75 100644 --- a/csharp/ql/test/library-tests/expressions/ArrayCreation11.expected +++ b/csharp/ql/test/library-tests/expressions/ArrayCreation11.expected @@ -1,3 +1,3 @@ -| expressions.cs:168:27:168:44 | array creation of type Object[] | expressions.cs:168:27:168:44 | 1 | false | -| expressions.cs:409:23:409:65 | array creation of type Int32[,] | expressions.cs:409:23:409:65 | 3 | false | -| expressions.cs:409:23:409:65 | array creation of type Int32[,] | expressions.cs:409:23:409:65 | 3 | false | +| expressions.cs:168:27:168:44 | array creation of type Object[] | expressions.cs:168:27:168:44 | 1 | true | +| expressions.cs:409:23:409:65 | array creation of type Int32[,] | expressions.cs:409:23:409:65 | 3 | true | +| expressions.cs:409:23:409:65 | array creation of type Int32[,] | expressions.cs:409:23:409:65 | 3 | true | From 246d9b8c701dc9470af0c9e4fabbdc909be40901 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 18 Aug 2020 12:51:36 +0200 Subject: [PATCH 108/133] update expected trap files --- .../tests/ts/output/trap/decorators.ts.trap | 12 ++++++------ .../tests/ts/output/trap/export.ts.trap | 18 +++++++++--------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/javascript/extractor/tests/ts/output/trap/decorators.ts.trap b/javascript/extractor/tests/ts/output/trap/decorators.ts.trap index 58ee0098c30..56a829b2cfc 100644 --- a/javascript/extractor/tests/ts/output/trap/decorators.ts.trap +++ b/javascript/extractor/tests/ts/output/trap/decorators.ts.trap @@ -311,10 +311,10 @@ scopenodes(#20001,#20112) scopenesting(#20112,#20000) isModule(#20001) isES2015Module(#20001) -#20113=@"var;{fun};{#20112}" -variables(#20113,"fun",#20112) -#20114=@"var;{Class};{#20112}" -variables(#20114,"Class",#20112) +#20113=@"var;{Class};{#20112}" +variables(#20113,"Class",#20112) +#20114=@"var;{fun};{#20112}" +variables(#20114,"fun",#20112) #20115=@"var;{Class2};{#20112}" variables(#20115,"Class2",#20112) #20116=@"local_type_name;{Class};{#20112}" @@ -347,7 +347,7 @@ hasLocation(#20123,#20037) enclosingStmt(#20123,#20118) exprContainers(#20123,#20001) literals("Class","Class",#20123) -decl(#20123,#20114) +decl(#20123,#20113) typedecl(#20123,#20116) #20124=* scopes(#20124,10) @@ -499,7 +499,7 @@ exprs(#20161,78,#20159,-1,"fun") hasLocation(#20161,#20086) exprContainers(#20161,#20159) literals("fun","fun",#20161) -decl(#20161,#20113) +decl(#20161,#20114) #20162=* scopes(#20162,1) scopenodes(#20159,#20162) diff --git a/javascript/extractor/tests/ts/output/trap/export.ts.trap b/javascript/extractor/tests/ts/output/trap/export.ts.trap index fe88825fc6a..34ef992309d 100644 --- a/javascript/extractor/tests/ts/output/trap/export.ts.trap +++ b/javascript/extractor/tests/ts/output/trap/export.ts.trap @@ -155,12 +155,12 @@ scopenodes(#20001,#20055) scopenesting(#20055,#20000) isModule(#20001) isES2015Module(#20001) -#20056=@"var;{f};{#20055}" -variables(#20056,"f",#20055) -#20057=@"var;{foo};{#20055}" -variables(#20057,"foo",#20055) -#20058=@"var;{C};{#20055}" -variables(#20058,"C",#20055) +#20056=@"var;{foo};{#20055}" +variables(#20056,"foo",#20055) +#20057=@"var;{C};{#20055}" +variables(#20057,"C",#20055) +#20058=@"var;{f};{#20055}" +variables(#20058,"f",#20055) #20059=@"local_type_name;{C};{#20055}" local_type_names(#20059,"C",#20055) #20060=* @@ -186,7 +186,7 @@ hasLocation(#20065,#20017) enclosingStmt(#20065,#20061) exprContainers(#20065,#20001) literals("foo","foo",#20065) -decl(#20065,#20057) +decl(#20065,#20056) #20066=* exprs(#20066,3,#20063,1,"42") hasLocation(#20066,#20021) @@ -209,7 +209,7 @@ hasLocation(#20070,#20029) enclosingStmt(#20070,#20068) exprContainers(#20070,#20001) literals("C","C",#20070) -decl(#20070,#20058) +decl(#20070,#20057) typedecl(#20070,#20059) #20071=* scopes(#20071,10) @@ -260,7 +260,7 @@ exprs(#20083,78,#20081,-1,"f") hasLocation(#20083,#20041) exprContainers(#20083,#20081) literals("f","f",#20083) -decl(#20083,#20056) +decl(#20083,#20058) #20084=* scopes(#20084,1) scopenodes(#20081,#20084) From bdf4ae5f27ef3f957c09634a29c8fad82ea5c61f Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 18 Aug 2020 13:30:16 +0200 Subject: [PATCH 109/133] C#: Increase `accessPathLimit` from 3 to 5 --- .../semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index 85cdb3522da..9813c0299ef 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -2354,7 +2354,7 @@ private predicate viableConstantBooleanParamArg( ) } -int accessPathLimit() { result = 3 } +int accessPathLimit() { result = 5 } /** * Holds if `n` does not require a `PostUpdateNode` as it either cannot be From acb08287abad1f39b2c184ed24ee665094c63555 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 18 Aug 2020 13:38:46 +0200 Subject: [PATCH 110/133] C#: Rename `isComplete()` to `isFullyConstructed()` --- csharp/ql/src/semmle/code/csharp/Implements.qll | 10 ++++++---- csharp/ql/src/semmle/code/csharp/Unification.qll | 10 ++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/Implements.qll b/csharp/ql/src/semmle/code/csharp/Implements.qll index 8f577e98872..7b535817039 100644 --- a/csharp/ql/src/semmle/code/csharp/Implements.qll +++ b/csharp/ql/src/semmle/code/csharp/Implements.qll @@ -259,7 +259,7 @@ private module Gvn { private newtype TGvnType = TLeafGvnType(LeafType t) or TMethodTypeParameterGvnType(int i) { i = any(MethodTypeParameter p).getIndex() } or - TConstructedGvnType(ConstructedGvnTypeList l) { l.isComplete() } + TConstructedGvnType(ConstructedGvnTypeList l) { l.isFullyConstructed() } private newtype TConstructedGvnTypeList = TConstructedGvnTypeNil(Unification::CompoundTypeKind k) or @@ -334,7 +334,9 @@ private module Gvn { ) } - predicate isComplete() { this.getKind().getNumberOfTypeParameters() - 1 = this.length() } + predicate isFullyConstructed() { + this.getKind().getNumberOfTypeParameters() - 1 = this.length() + } private GvnType getArg(int i) { exists(GvnType head, ConstructedGvnTypeList tail | @@ -365,7 +367,7 @@ private module Gvn { */ language[monotonicAggregates] private string toStringConstructedPart(int i, int j) { - this.isComplete() and + this.isFullyConstructed() and exists(Unification::GenericType t | t = this.getConstructedGenericDeclaringTypeAt(i) and exists(int offset, int children, string name | @@ -398,7 +400,7 @@ private module Gvn { language[monotonicAggregates] string toString() { - this.isComplete() and + this.isFullyConstructed() and exists(Unification::CompoundTypeKind k | k = this.getKind() | result = k.toStringBuiltin(this.getArg(0).toString()) or diff --git a/csharp/ql/src/semmle/code/csharp/Unification.qll b/csharp/ql/src/semmle/code/csharp/Unification.qll index 795e97164f0..4c057ad8c03 100644 --- a/csharp/ql/src/semmle/code/csharp/Unification.qll +++ b/csharp/ql/src/semmle/code/csharp/Unification.qll @@ -213,7 +213,9 @@ module Gvn { ) } - predicate isComplete() { this.getKind().getNumberOfTypeParameters() - 1 = this.length() } + predicate isFullyConstructed() { + this.getKind().getNumberOfTypeParameters() - 1 = this.length() + } GvnType getArg(int i) { exists(GvnType head, ConstructedGvnTypeList tail | @@ -244,7 +246,7 @@ module Gvn { */ language[monotonicAggregates] private string toStringConstructedPart(int i, int j) { - this.isComplete() and + this.isFullyConstructed() and exists(GenericType t | t = this.getConstructedGenericDeclaringTypeAt(i) and exists(int offset, int children, string name | @@ -277,7 +279,7 @@ module Gvn { language[monotonicAggregates] string toString() { - this.isComplete() and + this.isFullyConstructed() and exists(CompoundTypeKind k | k = this.getKind() | result = k.toStringBuiltin(this.getArg(0).toString()) or @@ -509,7 +511,7 @@ module Gvn { newtype TGvnType = TLeafGvnType(LeafType t) or TTypeParameterGvnType() or - TConstructedGvnType(ConstructedGvnTypeList l) { l.isComplete() } + TConstructedGvnType(ConstructedGvnTypeList l) { l.isFullyConstructed() } cached newtype TConstructedGvnTypeList = From b316644ac290d1e26dbcdd0ac52f71decd5b3b59 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Tue, 18 Aug 2020 14:17:42 +0200 Subject: [PATCH 111/133] C++: SimpleRangeAnalysis for *= by constant --- .../cpp/rangeanalysis/SimpleRangeAnalysis.qll | 87 ++++++++++++++++++- .../SimpleRangeAnalysis/lowerBound.expected | 9 +- .../rangeanalysis/SimpleRangeAnalysis/test.c | 13 ++- .../SimpleRangeAnalysis/upperBound.expected | 9 +- 4 files changed, 108 insertions(+), 10 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll index 7e14996a91d..b11cbc71905 100644 --- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll @@ -217,8 +217,29 @@ private predicate multipliesByNegative(Expr expr, Expr operand, float negative) negative = -1.0 } +private class AssignMulByConstantExpr extends AssignMulExpr { + float constant; + + AssignMulByConstantExpr() { constant = this.getRValue().getFullyConverted().getValue().toFloat() } + + float getConstant() { result = constant } +} + +private class AssignMulByPositiveConstantExpr extends AssignMulByConstantExpr { + AssignMulByPositiveConstantExpr() { constant >= 0.0 } +} + +private class AssignMulByNegativeConstantExpr extends AssignMulByConstantExpr { + AssignMulByNegativeConstantExpr() { constant < 0.0 } +} + private class UnsignedAssignMulExpr extends AssignMulExpr { - UnsignedAssignMulExpr() { this.getType().(IntegralType).isUnsigned() } + UnsignedAssignMulExpr() { + this.getType().(IntegralType).isUnsigned() and + // Avoid overlap. It should be slightly cheaper to analyze + // `AssignMulByConstantExpr`. + not this instanceof AssignMulByConstantExpr + } } /** Set of expressions which we know how to analyze. */ @@ -253,6 +274,8 @@ private predicate analyzableExpr(Expr e) { or e instanceof UnsignedAssignMulExpr or + e instanceof AssignMulByConstantExpr + or e instanceof CrementOperation or e instanceof RemExpr @@ -310,6 +333,12 @@ private predicate defDependsOnDef( exprDependsOnDef(assignMul.getAnOperand(), srcDef, srcVar) ) or + exists(AssignMulByConstantExpr assignMul | + def = assignMul and + def.getAVariable() = v and + exprDependsOnDef(assignMul.getLValue(), srcDef, srcVar) + ) + or exists(CrementOperation crem | def = crem and def.getAVariable() = v and @@ -365,6 +394,10 @@ private predicate exprDependsOnDef(Expr e, RangeSsaDefinition srcDef, StackVaria exprDependsOnDef(mulExpr.getAnOperand(), srcDef, srcVar) ) or + exists(AssignMulByConstantExpr mulExpr | e = mulExpr | + exprDependsOnDef(mulExpr.getLValue(), srcDef, srcVar) + ) + or exists(CrementOperation crementExpr | e = crementExpr | exprDependsOnDef(crementExpr.getOperand(), srcDef, srcVar) ) @@ -736,6 +769,18 @@ private float getLowerBoundsImpl(Expr expr) { result = xLow * yLow ) or + exists(AssignMulByPositiveConstantExpr mulExpr, float xLow | + expr = mulExpr and + xLow = getFullyConvertedLowerBounds(mulExpr.getLValue()) and + result = xLow * mulExpr.getConstant() + ) + or + exists(AssignMulByNegativeConstantExpr mulExpr, float xHigh | + expr = mulExpr and + xHigh = getFullyConvertedUpperBounds(mulExpr.getLValue()) and + result = xHigh * mulExpr.getConstant() + ) + or exists(PrefixIncrExpr incrExpr, float xLow | expr = incrExpr and xLow = getFullyConvertedLowerBounds(incrExpr.getOperand()) and @@ -910,6 +955,18 @@ private float getUpperBoundsImpl(Expr expr) { result = xHigh * yHigh ) or + exists(AssignMulByPositiveConstantExpr mulExpr, float xHigh | + expr = mulExpr and + xHigh = getFullyConvertedUpperBounds(mulExpr.getLValue()) and + result = xHigh * mulExpr.getConstant() + ) + or + exists(AssignMulByNegativeConstantExpr mulExpr, float xLow | + expr = mulExpr and + xLow = getFullyConvertedLowerBounds(mulExpr.getLValue()) and + result = xLow * mulExpr.getConstant() + ) + or exists(PrefixIncrExpr incrExpr, float xHigh | expr = incrExpr and xHigh = getFullyConvertedUpperBounds(incrExpr.getOperand()) and @@ -1136,6 +1193,20 @@ private float getDefLowerBoundsImpl(RangeSsaDefinition def, StackVariable v) { result = lhsLB * rhsLB ) or + exists(AssignMulByPositiveConstantExpr assignMul, RangeSsaDefinition nextDef, float lhsLB | + def = assignMul and + assignMul.getLValue() = nextDef.getAUse(v) and + lhsLB = getDefLowerBounds(nextDef, v) and + result = lhsLB * assignMul.getConstant() + ) + or + exists(AssignMulByNegativeConstantExpr assignMul, RangeSsaDefinition nextDef, float lhsUB | + def = assignMul and + assignMul.getLValue() = nextDef.getAUse(v) and + lhsUB = getDefUpperBounds(nextDef, v) and + result = lhsUB * assignMul.getConstant() + ) + or exists(IncrementOperation incr, float newLB | def = incr and incr.getOperand() = v.getAnAccess() and @@ -1186,6 +1257,20 @@ private float getDefUpperBoundsImpl(RangeSsaDefinition def, StackVariable v) { result = lhsUB * rhsUB ) or + exists(AssignMulByPositiveConstantExpr assignMul, RangeSsaDefinition nextDef, float lhsUB | + def = assignMul and + assignMul.getLValue() = nextDef.getAUse(v) and + lhsUB = getDefUpperBounds(nextDef, v) and + result = lhsUB * assignMul.getConstant() + ) + or + exists(AssignMulByNegativeConstantExpr assignMul, RangeSsaDefinition nextDef, float lhsLB | + def = assignMul and + assignMul.getLValue() = nextDef.getAUse(v) and + lhsLB = getDefLowerBounds(nextDef, v) and + result = lhsLB * assignMul.getConstant() + ) + or exists(IncrementOperation incr, float newUB | def = incr and incr.getOperand() = v.getAnAccess() and diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected index 2bf4a5b9418..dad84ef19b0 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected @@ -519,9 +519,9 @@ | test.c:513:9:513:9 | i | -5 | | test.c:514:9:514:9 | i | -30 | | test.c:516:5:516:5 | i | -30 | -| test.c:517:9:517:9 | i | -2147483648 | -| test.c:519:5:519:5 | i | -2147483648 | -| test.c:520:9:520:9 | i | -2147483648 | +| test.c:517:9:517:9 | i | -210 | +| test.c:519:5:519:5 | i | -210 | +| test.c:520:9:520:9 | i | -1155 | | test.c:522:7:522:7 | i | -2147483648 | | test.c:523:5:523:5 | i | -2147483648 | | test.c:523:9:523:9 | i | -1 | @@ -529,6 +529,9 @@ | test.c:526:3:526:3 | i | -2147483648 | | test.c:526:7:526:7 | i | -2147483648 | | test.c:527:10:527:10 | i | -2147483648 | +| test.c:530:3:530:3 | i | -2147483648 | +| test.c:530:10:530:11 | sc | 1 | +| test.c:532:7:532:7 | i | -128 | | test.cpp:10:7:10:7 | b | -2147483648 | | test.cpp:11:5:11:5 | x | -2147483648 | | test.cpp:13:10:13:10 | x | -2147483648 | diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c index c66d50eb630..a84ff736646 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c @@ -514,15 +514,22 @@ int mul_by_constant(int i, int j) { out(i); // -30 .. 15 i *= 7; - out(i); // -210 .. 105 [BUG: not supported] + out(i); // -210 .. 105 i *= -11; - out(i); // -1155 .. 2310 [BUG: not supported] + out(i); // -1155 .. 2310 } if (i == -1) { i = i * (int)0xffFFffFF; // fully converted literal is -1 out(i); // 1 .. 1 } i = i * -1; - return i; // -2^31 .. 2^31-1 + out( i); // -2^31 .. 2^31-1 + + signed char sc = 1; + i = (*&sc *= 2); + out(sc); // demonstrate that we couldn't analyze the LHS of the `*=` above... + out(i); // -128 .. 127 // ... but we can still bound its result by its type. + + return 0; } diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected index 1d070d0d117..7007960936f 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected @@ -519,9 +519,9 @@ | test.c:513:9:513:9 | i | 10 | | test.c:514:9:514:9 | i | 15 | | test.c:516:5:516:5 | i | 15 | -| test.c:517:9:517:9 | i | 2147483647 | -| test.c:519:5:519:5 | i | 2147483647 | -| test.c:520:9:520:9 | i | 2147483647 | +| test.c:517:9:517:9 | i | 105 | +| test.c:519:5:519:5 | i | 105 | +| test.c:520:9:520:9 | i | 2310 | | test.c:522:7:522:7 | i | 2147483647 | | test.c:523:5:523:5 | i | 2147483647 | | test.c:523:9:523:9 | i | -1 | @@ -529,6 +529,9 @@ | test.c:526:3:526:3 | i | 2147483647 | | test.c:526:7:526:7 | i | 2147483647 | | test.c:527:10:527:10 | i | 2147483647 | +| test.c:530:3:530:3 | i | 2147483647 | +| test.c:530:10:530:11 | sc | 1 | +| test.c:532:7:532:7 | i | 127 | | test.cpp:10:7:10:7 | b | 2147483647 | | test.cpp:11:5:11:5 | x | 2147483647 | | test.cpp:13:10:13:10 | x | 2147483647 | From a72d05ccdbcef4e1d0fb5e2eb6d6bbe2cb73f409 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Tue, 18 Aug 2020 15:07:35 +0200 Subject: [PATCH 112/133] C++: Change note for *= and constant * --- change-notes/1.26/analysis-cpp.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/change-notes/1.26/analysis-cpp.md b/change-notes/1.26/analysis-cpp.md index 867320915a9..6838e8ca642 100644 --- a/change-notes/1.26/analysis-cpp.md +++ b/change-notes/1.26/analysis-cpp.md @@ -20,4 +20,4 @@ The following changes in version 1.26 affect C/C++ analysis in all applications. * The models library now models more taint flows through `std::string`. * The `SimpleRangeAnalysis` library now supports multiplications of the form - `e1 * e2` when `e1` and `e2` are unsigned. + `e1 * e2` and `x *= e2` when `e1` and `e2` are unsigned or constant. From 129e528e1cbb395487e5144b44ec8de1cd4058ca Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 18 Aug 2020 15:09:08 +0200 Subject: [PATCH 113/133] Java: Use `unique` aggregate in `Node::getEnclosingCallable()` I noticed while running tuple stats on JDK that the functionality of `Node::getEnclosingCallable()` is not know to the QL compiler (possibly because it is defined recursively). Here is an example pipeline before: ``` [2020-08-18 14:45:03] (29s) Starting to evaluate predicate DataFlowImpl::flowFwdIn#ffffffff#cur_delta/8[93]@efe539 (iteration 93) [2020-08-18 14:45:04] (30s) Tuple counts for DataFlowImpl::flowFwdIn#ffffffff#cur_delta: 4034 ~4% {6} r1 = SCAN DataFlowImpl::flowFwd#ffffff#prev_delta AS I OUTPUT I.<0>, I.<5>, I.<1>, I.<2>, I.<3>, I.<4> 11410 ~4% {7} r2 = JOIN r1 WITH DataFlowImpl::flowIntoCallNodeCand2#ffffff_1502#join_rhs AS R ON FIRST 2 OUTPUT r1.<5>, r1.<2>, r1.<3>, r1.<4>, r1.<1>, R.<2>, R.<3> 11095 ~2% {7} r3 = JOIN r2 WITH DataFlowImpl::TNil#ff_1#join_rhs AS R ON FIRST 1 OUTPUT r2.<1>, r2.<2>, r2.<3>, r2.<0>, r2.<4>, r2.<5>, r2.<6> 11661 ~0% {10} r4 = JOIN r1 WITH DataFlowImpl::flowIntoCallNodeCand2#ffffff_150234#join_rhs AS R ON FIRST 2 OUTPUT r1.<0>, r1.<2>, r1.<3>, r1.<4>, r1.<5>, r1.<1>, R.<2>, R.<3>, R.<4>, R.<5> 1489 ~0% {10} r5 = SELECT r4 ON r4.<9> = true 1489 ~16% {7} r6 = SCAN r5 OUTPUT r5.<1>, r5.<2>, r5.<3>, r5.<4>, r5.<5>, r5.<6>, r5.<7> 12584 ~14% {7} r7 = r3 \/ r6 4966 ~6% {8} r8 = JOIN r7 WITH DataFlowImplCommon::Cached::TSpecificCall#ff_10#join_rhs AS R ON FIRST 1 OUTPUT r7.<5>, R.<1>, r7.<0>, r7.<1>, r7.<2>, r7.<3>, r7.<4>, r7.<6> 1115 ~6% {8} r9 = JOIN r8 WITH DataFlowImplCommon::Cached::DispatchWithCallContext::reducedViableImplInCallContext#fff_02#join_rhs AS R ON FIRST 2 OUTPUT r8.<0>, r8.<1>, r8.<2>, r8.<3>, r8.<4>, r8.<5>, r8.<6>, r8.<7> 1652 ~11% {8} r10 = JOIN r9 WITH DataFlowImplCommon::Cached::DispatchWithCallContext::prunedViableImplInCallContext#fff@staged_ext AS R ON FIRST 2 OUTPUT r9.<7>, R.<2>, r9.<2>, r9.<3>, r9.<4>, r9.<5>, r9.<6>, r9.<0> 4966 ~0% {8} r11 = JOIN r7 WITH DataFlowImplCommon::Cached::TSpecificCall#ff_10#join_rhs AS R ON FIRST 1 OUTPUT r7.<0>, r7.<1>, r7.<2>, r7.<3>, r7.<4>, r7.<5>, r7.<6>, R.<1> 3851 ~0% {8} r12 = r11 AND NOT DataFlowImplCommon::Cached::DispatchWithCallContext::reducedViableImplInCallContext#fff_02#join_rhs AS R(r11.<5>, r11.<7>) 3851 ~7% {7} r13 = SCAN r12 OUTPUT r12.<5>, r12.<0>, r12.<1>, r12.<2>, r12.<3>, r12.<4>, r12.<6> 3763916 ~0% {8} r14 = JOIN r13 WITH VirtualDispatch::viableCallable#ff AS R ON FIRST 1 OUTPUT r13.<6>, R.<1>, r13.<1>, r13.<2>, r13.<3>, r13.<4>, r13.<5>, r13.<0> 3765568 ~0% {8} r15 = r10 \/ r14 4604 ~20% {7} r16 = JOIN r7 WITH DataFlowImplCommon::Cached::TSomeCall#f@staged_ext AS R ON FIRST 1 OUTPUT r7.<5>, r7.<0>, r7.<1>, r7.<2>, r7.<3>, r7.<4>, r7.<6> 1383356 ~0% {8} r17 = JOIN r16 WITH VirtualDispatch::viableCallable#ff AS R ON FIRST 1 OUTPUT r16.<6>, R.<1>, r16.<1>, r16.<2>, r16.<3>, r16.<4>, r16.<5>, r16.<0> 5148924 ~0% {8} r18 = r15 \/ r17 1076 ~20% {7} r19 = JOIN r7 WITH DataFlowImplCommon::Cached::TAnyCallContext#f@staged_ext AS R ON FIRST 1 OUTPUT r7.<5>, r7.<0>, r7.<1>, r7.<2>, r7.<3>, r7.<4>, r7.<6> 660959 ~3% {8} r20 = JOIN r19 WITH VirtualDispatch::viableCallable#ff AS R ON FIRST 1 OUTPUT r19.<6>, R.<1>, r19.<1>, r19.<2>, r19.<3>, r19.<4>, r19.<5>, r19.<0> 5809883 ~0% {8} r21 = r18 \/ r20 1938 ~2% {7} r22 = JOIN r7 WITH DataFlowImplCommon::Cached::TReturn#fff_2#join_rhs AS R ON FIRST 1 OUTPUT r7.<5>, r7.<0>, r7.<1>, r7.<2>, r7.<3>, r7.<4>, r7.<6> 1184996 ~5% {8} r23 = JOIN r22 WITH VirtualDispatch::viableCallable#ff AS R ON FIRST 1 OUTPUT r22.<6>, R.<1>, r22.<1>, r22.<2>, r22.<3>, r22.<4>, r22.<5>, r22.<0> 6994879 ~0% {8} r24 = r21 \/ r23 11590 ~18% {8} r25 = JOIN r24 WITH DataFlowUtil::Node::getEnclosingCallable#ff AS R ON FIRST 2 OUTPUT r24.<0>, r24.<2>, r24.<3>, r24.<4>, r24.<5>, r24.<6>, r24.<7>, r24.<1> 11378 ~10% {9} r26 = JOIN r25 WITH project#DataFlowImpl::flowCand#fffff#10 AS R ON FIRST 1 OUTPUT r25.<1>, r25.<2>, r25.<3>, r25.<4>, r25.<5>, r25.<6>, r25.<0>, r25.<7>, R.<1> 11378 ~10% {9} r27 = SELECT r26 ON r26.<8> >= r26.<4> 11378 ~10% {9} r28 = SELECT r27 ON r27.<8> <= r27.<4> 11378 ~13% {8} r29 = SCAN r28 OUTPUT r28.<5>, r28.<7>, r28.<0>, r28.<1>, r28.<2>, r28.<3>, r28.<4>, r28.<6> 149 ~43% {7} r30 = JOIN r29 WITH DataFlowImplCommon::Cached::recordDataFlowCallSite#ff@staged_ext AS R ON FIRST 2 OUTPUT r29.<0>, r29.<2>, r29.<3>, r29.<4>, r29.<5>, r29.<6>, r29.<7> 149 ~45% {8} r31 = JOIN r30 WITH DataFlowImplCommon::Cached::TSpecificCall#ff@staged_ext AS R ON FIRST 1 OUTPUT r30.<1>, r30.<2>, r30.<3>, r30.<4>, r30.<5>, r30.<0>, r30.<6>, R.<1> 11378 ~10% {8} r32 = SCAN r28 OUTPUT r28.<0>, r28.<1>, r28.<2>, r28.<3>, r28.<4>, r28.<5>, r28.<6>, r28.<7> 11229 ~9% {8} r33 = r32 AND NOT DataFlowImplCommon::Cached::recordDataFlowCallSite#ff@staged_ext AS R(r32.<5>, r32.<7>) 11229 ~17% {7} r34 = SCAN r33 OUTPUT r33.<0>, r33.<1>, r33.<2>, r33.<3>, r33.<4>, r33.<5>, r33.<6> 11229 ~11% {8} r35 = JOIN r34 WITH DataFlowImplCommon::Cached::TSomeCall#f@staged_ext AS R CARTESIAN PRODUCT OUTPUT r34.<0>, r34.<1>, r34.<2>, r34.<3>, r34.<4>, r34.<5>, r34.<6>, R.<0> 11378 ~11% {8} r36 = r31 \/ r35 11378 ~11% {8} r37 = r36 AND NOT DataFlowImpl::flowFwdIn#ffffffff#prev AS R(r36.<5>, r36.<6>, r36.<0>, r36.<7>, r36.<1>, r36.<2>, r36.<3>, r36.<4>) 11378 ~9% {8} r38 = SCAN r37 OUTPUT r37.<5>, r37.<6>, r37.<0>, r37.<7>, r37.<1>, r37.<2>, r37.<3>, r37.<4> return r38 ``` And after: ``` [2020-08-18 15:02:55] (121s) Starting to evaluate predicate DataFlowImpl::flowFwdIn#ffffffff#cur_delta/8[93]@5ed760 (iteration 93) [2020-08-18 15:02:55] (121s) Tuple counts for DataFlowImpl::flowFwdIn#ffffffff#cur_delta: 3918 ~2% {6} r1 = SCAN DataFlowImpl::flowFwd#ffffff#prev_delta AS I OUTPUT I.<0>, I.<5>, I.<1>, I.<2>, I.<3>, I.<4> 16820 ~0% {7} r2 = JOIN r1 WITH DataFlowImpl::flowIntoCallNodeCand2#fffff_1402#join_rhs AS R ON FIRST 2 OUTPUT r1.<5>, r1.<2>, r1.<3>, r1.<4>, r1.<1>, R.<2>, R.<3> 16525 ~1% {7} r3 = JOIN r2 WITH DataFlowImpl::TNil#ff_1#join_rhs AS R ON FIRST 1 OUTPUT r2.<6>, r2.<1>, r2.<2>, r2.<3>, r2.<0>, r2.<4>, r2.<5> 16820 ~0% {9} r4 = JOIN r1 WITH DataFlowImpl::flowIntoCallNodeCand2#fffff_14023#join_rhs AS R ON FIRST 2 OUTPUT r1.<0>, r1.<2>, r1.<3>, r1.<4>, r1.<5>, r1.<1>, R.<2>, R.<3>, R.<4> 1211 ~0% {9} r5 = SELECT r4 ON r4.<8> = true 1211 ~0% {7} r6 = SCAN r5 OUTPUT r5.<7>, r5.<1>, r5.<2>, r5.<3>, r5.<4>, r5.<5>, r5.<6> 17736 ~6% {7} r7 = r3 \/ r6 17736 ~4% {8} r8 = JOIN r7 WITH DataFlowUtil::Node::getEnclosingCallable_dispred#ff AS R ON FIRST 1 OUTPUT r7.<1>, r7.<2>, r7.<3>, r7.<4>, r7.<5>, r7.<6>, r7.<0>, R.<1> 6757 ~3% {9} r9 = JOIN r8 WITH DataFlowImplCommon::Cached::TSpecificCall#ff_10#join_rhs AS R ON FIRST 1 OUTPUT r8.<5>, R.<1>, r8.<7>, r8.<0>, r8.<1>, r8.<2>, r8.<3>, r8.<4>, r8.<6> 112 ~62% {9} r10 = JOIN r9 WITH DataFlowImplCommon::Cached::DispatchWithCallContext::prunedViableImplInCallContext#fff@staged_ext AS R ON FIRST 3 OUTPUT r9.<0>, r9.<1>, r9.<3>, r9.<4>, r9.<5>, r9.<6>, r9.<7>, r9.<8>, r9.<2> 112 ~62% {8} r11 = JOIN r10 WITH DataFlowImplCommon::Cached::DispatchWithCallContext::reducedViableImplInCallContext#fff_02#join_rhs AS R ON FIRST 2 OUTPUT r10.<7>, r10.<2>, r10.<3>, r10.<4>, r10.<5>, r10.<6>, r10.<0>, r10.<8> 6757 ~0% {9} r12 = JOIN r8 WITH DataFlowImplCommon::Cached::TSpecificCall#ff_10#join_rhs AS R ON FIRST 1 OUTPUT r8.<5>, r8.<7>, r8.<0>, r8.<1>, r8.<2>, r8.<3>, r8.<4>, r8.<6>, R.<1> 6757 ~0% {9} r13 = JOIN r12 WITH VirtualDispatch::viableCallable#ff AS R ON FIRST 2 OUTPUT r12.<2>, r12.<3>, r12.<4>, r12.<5>, r12.<6>, r12.<0>, r12.<7>, r12.<1>, r12.<8> 4945 ~0% {9} r14 = r13 AND NOT DataFlowImplCommon::Cached::DispatchWithCallContext::reducedViableImplInCallContext#fff_02#join_rhs AS R(r13.<5>, r13.<8>) 4945 ~4% {8} r15 = SCAN r14 OUTPUT r14.<6>, r14.<0>, r14.<1>, r14.<2>, r14.<3>, r14.<4>, r14.<5>, r14.<7> 5057 ~5% {8} r16 = r11 \/ r15 7628 ~12% {8} r17 = JOIN r8 WITH DataFlowImplCommon::Cached::TSomeCall#f@staged_ext AS R ON FIRST 1 OUTPUT r8.<5>, r8.<7>, r8.<0>, r8.<1>, r8.<2>, r8.<3>, r8.<4>, r8.<6> 7628 ~9% {8} r18 = JOIN r17 WITH VirtualDispatch::viableCallable#ff AS R ON FIRST 2 OUTPUT r17.<7>, r17.<2>, r17.<3>, r17.<4>, r17.<5>, r17.<6>, r17.<0>, r17.<1> 12685 ~14% {8} r19 = r16 \/ r18 1411 ~10% {8} r20 = JOIN r8 WITH DataFlowImplCommon::Cached::TAnyCallContext#f@staged_ext AS R ON FIRST 1 OUTPUT r8.<5>, r8.<7>, r8.<0>, r8.<1>, r8.<2>, r8.<3>, r8.<4>, r8.<6> 1411 ~11% {8} r21 = JOIN r20 WITH VirtualDispatch::viableCallable#ff AS R ON FIRST 2 OUTPUT r20.<7>, r20.<2>, r20.<3>, r20.<4>, r20.<5>, r20.<6>, r20.<0>, r20.<1> 14096 ~14% {8} r22 = r19 \/ r21 17736 ~10% {8} r23 = JOIN r7 WITH DataFlowUtil::Node::getEnclosingCallable_dispred#ff AS R ON FIRST 1 OUTPUT r7.<6>, R.<1>, r7.<1>, r7.<2>, r7.<3>, r7.<4>, r7.<5>, r7.<0> 17736 ~4% {8} r24 = JOIN r23 WITH VirtualDispatch::viableCallable#ff AS R ON FIRST 2 OUTPUT r23.<2>, r23.<3>, r23.<4>, r23.<5>, r23.<6>, r23.<0>, r23.<7>, r23.<1> 1940 ~0% {8} r25 = JOIN r24 WITH DataFlowImplCommon::Cached::TReturn#fff_2#join_rhs AS R ON FIRST 1 OUTPUT r24.<6>, r24.<0>, r24.<1>, r24.<2>, r24.<3>, r24.<4>, r24.<5>, r24.<7> 16036 ~13% {8} r26 = r22 \/ r25 14256 ~8% {9} r27 = JOIN r26 WITH project#DataFlowImpl::flowCand#fffff#10 AS R ON FIRST 1 OUTPUT r26.<1>, r26.<2>, r26.<3>, r26.<4>, r26.<5>, r26.<6>, r26.<0>, r26.<7>, R.<1> 14256 ~8% {9} r28 = SELECT r27 ON r27.<8> >= r27.<4> 14256 ~8% {9} r29 = SELECT r28 ON r28.<8> <= r28.<4> 14256 ~9% {8} r30 = SCAN r29 OUTPUT r29.<5>, r29.<7>, r29.<0>, r29.<1>, r29.<2>, r29.<3>, r29.<4>, r29.<6> 122 ~28% {7} r31 = JOIN r30 WITH DataFlowImplCommon::Cached::recordDataFlowCallSite#ff@staged_ext AS R ON FIRST 2 OUTPUT r30.<0>, r30.<2>, r30.<3>, r30.<4>, r30.<5>, r30.<6>, r30.<7> 122 ~30% {8} r32 = JOIN r31 WITH DataFlowImplCommon::Cached::TSpecificCall#ff@staged_ext AS R ON FIRST 1 OUTPUT r31.<1>, r31.<2>, r31.<3>, r31.<4>, r31.<5>, r31.<0>, r31.<6>, R.<1> 14256 ~3% {8} r33 = SCAN r29 OUTPUT r29.<0>, r29.<1>, r29.<2>, r29.<3>, r29.<4>, r29.<5>, r29.<6>, r29.<7> 14134 ~3% {8} r34 = r33 AND NOT DataFlowImplCommon::Cached::recordDataFlowCallSite#ff@staged_ext AS R(r33.<5>, r33.<7>) 14134 ~12% {7} r35 = SCAN r34 OUTPUT r34.<0>, r34.<1>, r34.<2>, r34.<3>, r34.<4>, r34.<5>, r34.<6> 14134 ~7% {8} r36 = JOIN r35 WITH DataFlowImplCommon::Cached::TSomeCall#f@staged_ext AS R CARTESIAN PRODUCT OUTPUT r35.<0>, r35.<1>, r35.<2>, r35.<3>, r35.<4>, r35.<5>, r35.<6>, R.<0> 14256 ~7% {8} r37 = r32 \/ r36 14256 ~7% {8} r38 = r37 AND NOT DataFlowImpl::flowFwdIn#ffffffff#prev AS R(r37.<5>, r37.<6>, r37.<0>, r37.<7>, r37.<1>, r37.<2>, r37.<3>, r37.<4>) 14256 ~9% {8} r39 = SCAN r38 OUTPUT r38.<5>, r38.<6>, r38.<0>, r38.<7>, r38.<1>, r38.<2>, r38.<3>, r38.<4> return r39 ``` --- .../code/java/dataflow/internal/DataFlowUtil.qll | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowUtil.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowUtil.qll index b6ca8986307..ceeb4d64064 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowUtil.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowUtil.qll @@ -78,15 +78,19 @@ class Node extends TNode { result = this.(ImplicitPostUpdateNode).getPreUpdateNode().getType() } - /** Gets the callable in which this node occurs. */ - Callable getEnclosingCallable() { + private Callable getEnclosingCallableImpl() { result = this.asExpr().getEnclosingCallable() or result = this.asParameter().getCallable() or result = this.(ImplicitVarargsArray).getCall().getEnclosingCallable() or result = this.(InstanceParameterNode).getCallable() or result = this.(ImplicitInstanceAccess).getInstanceAccess().getEnclosingCallable() or result = this.(MallocNode).getClassInstanceExpr().getEnclosingCallable() or - result = this.(ImplicitPostUpdateNode).getPreUpdateNode().getEnclosingCallable() + result = this.(ImplicitPostUpdateNode).getPreUpdateNode().getEnclosingCallableImpl() + } + + /** Gets the callable in which this node occurs. */ + Callable getEnclosingCallable() { + result = unique(DataFlowCallable c | c = this.getEnclosingCallableImpl() | c) } private Type getImprovedTypeBound() { From 13577967f3373319d88accf866c387f9af9ccf52 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 18 Aug 2020 15:16:00 +0200 Subject: [PATCH 114/133] Data flow: Document `Node::getEnclosingCallable()` --- docs/ql-libraries/dataflow/dataflow.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/ql-libraries/dataflow/dataflow.md b/docs/ql-libraries/dataflow/dataflow.md index 3686b3ed4a4..46ba27acccf 100644 --- a/docs/ql-libraries/dataflow/dataflow.md +++ b/docs/ql-libraries/dataflow/dataflow.md @@ -98,6 +98,10 @@ Recommendations: also work, but the upside of `use-use` steps is that sources defined in terms of variable reads just work out of the box. It also makes certain barrier-implementations simpler. +* A predicate `DataFlowCallable Node::getEnclosingCallable()` is required, and in + order to ensure appropriate join-orders, it is important that the QL compiler knows + that this predicate is functional. It can therefore be necessary to enclose the body + of this predicate in a `unique` aggregate. The shared library does not use `localFlowStep` nor `localFlow` but users of `DataFlow.qll` may expect the existence of `DataFlow::localFlowStep` and From dd5b561f08e2437fa62ad747d9b56c39d7ec2899 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Tue, 18 Aug 2020 16:45:24 +0200 Subject: [PATCH 115/133] C++: Use getValue(e) instead of e.getValue() --- .../cpp/rangeanalysis/SimpleRangeAnalysis.qll | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll index b11cbc71905..a6d97149adf 100644 --- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll @@ -126,7 +126,7 @@ private class UnsignedBitwiseAndExpr extends BitwiseAndExpr { UnsignedBitwiseAndExpr() { ( getLeftOperand().getFullyConverted().getType().getUnderlyingType().(IntegralType).isUnsigned() or - getLeftOperand().getFullyConverted().getValue().toInt() >= 0 + getValue(getLeftOperand().getFullyConverted()).toInt() >= 0 ) and ( getRightOperand() @@ -135,7 +135,7 @@ private class UnsignedBitwiseAndExpr extends BitwiseAndExpr { .getUnderlyingType() .(IntegralType) .isUnsigned() or - getRightOperand().getFullyConverted().getValue().toInt() >= 0 + getValue(getRightOperand().getFullyConverted()).toInt() >= 0 ) } } @@ -164,8 +164,8 @@ private class MulByConstantExpr extends MulExpr { MulByConstantExpr() { exists(Expr constantExpr | this.hasOperands(constantExpr, operand) and - constant = constantExpr.getFullyConverted().getValue().toFloat() and - not exists(operand.getFullyConverted().getValue().toFloat()) + constant = getValue(constantExpr.getFullyConverted()).toFloat() and + not exists(getValue(operand.getFullyConverted()).toFloat()) ) } @@ -220,7 +220,7 @@ private predicate multipliesByNegative(Expr expr, Expr operand, float negative) private class AssignMulByConstantExpr extends AssignMulExpr { float constant; - AssignMulByConstantExpr() { constant = this.getRValue().getFullyConverted().getValue().toFloat() } + AssignMulByConstantExpr() { constant = getValue(this.getRValue().getFullyConverted()).toFloat() } float getConstant() { result = constant } } @@ -294,7 +294,7 @@ private predicate analyzableExpr(Expr e) { e instanceof UnsignedBitwiseAndExpr or // `>>` by a constant - exists(e.(RShiftExpr).getRightOperand().getValue()) + exists(getValue(e.(RShiftExpr).getRightOperand())) ) } @@ -415,7 +415,7 @@ private predicate exprDependsOnDef(Expr e, RangeSsaDefinition srcDef, StackVaria // `>>` by a constant exists(RShiftExpr rs | rs = e and - exists(rs.getRightOperand().getValue()) and + exists(getValue(rs.getRightOperand())) and exprDependsOnDef(rs.getLeftOperand(), srcDef, srcVar) ) or @@ -851,7 +851,7 @@ private float getLowerBoundsImpl(Expr expr) { exists(RShiftExpr rsExpr, float left, int right | rsExpr = expr and left = getFullyConvertedLowerBounds(rsExpr.getLeftOperand()) and - right = rsExpr.getRightOperand().getFullyConverted().getValue().toInt() and + right = getValue(rsExpr.getRightOperand().getFullyConverted()).toInt() and result = safeFloor(left / 2.pow(right)) ) } @@ -1037,7 +1037,7 @@ private float getUpperBoundsImpl(Expr expr) { exists(RShiftExpr rsExpr, float left, int right | rsExpr = expr and left = getFullyConvertedUpperBounds(rsExpr.getLeftOperand()) and - right = rsExpr.getRightOperand().getFullyConverted().getValue().toInt() and + right = getValue(rsExpr.getRightOperand().getFullyConverted()).toInt() and result = safeFloor(left / 2.pow(right)) ) } From fd0937eb01ce19393bdd0b00d027b46000c1b646 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Tue, 18 Aug 2020 16:47:29 +0200 Subject: [PATCH 116/133] C++: Accept improved IntegerOverflowTainted test --- .../CWE/CWE-190/semmle/tainted/IntegerOverflowTainted.expected | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/IntegerOverflowTainted.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/IntegerOverflowTainted.expected index d2b6499d40e..1d9a9d6ea66 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/IntegerOverflowTainted.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/IntegerOverflowTainted.expected @@ -2,5 +2,8 @@ | test3.c:13:16:13:19 | * ... | $@ flows to here and is used in an expression which might overflow negatively. | test3.c:11:15:11:18 | argv | User-provided value | | test4.cpp:13:17:13:20 | access to array | $@ flows to here and is used in an expression which might overflow negatively. | test4.cpp:9:13:9:16 | argv | User-provided value | | test5.cpp:10:9:10:15 | call to strtoul | $@ flows to here and is used in an expression which might overflow. | test5.cpp:9:7:9:9 | buf | User-provided value | +| test5.cpp:17:6:17:27 | ... * ... | $@ flows to here and is used in an expression which might overflow. | test5.cpp:9:7:9:9 | buf | User-provided value | +| test5.cpp:19:6:19:13 | ... * ... | $@ flows to here and is used in an expression which might overflow. | test5.cpp:9:7:9:9 | buf | User-provided value | +| test.c:14:15:14:35 | ... * ... | $@ flows to here and is used in an expression which might overflow. | test.c:11:29:11:32 | argv | User-provided value | | test.c:44:7:44:12 | ... -- | $@ flows to here and is used in an expression which might overflow negatively. | test.c:41:17:41:20 | argv | User-provided value | | test.c:54:7:54:12 | ... -- | $@ flows to here and is used in an expression which might overflow negatively. | test.c:51:17:51:20 | argv | User-provided value | From f79c140dc1abce69786c7f4e17d577041a46a860 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Tue, 18 Aug 2020 16:48:23 +0200 Subject: [PATCH 117/133] C++: Cosmetic: use [0, 1] instead of [0 .. 1] --- cpp/ql/src/semmle/code/cpp/exprs/Expr.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/exprs/Expr.qll b/cpp/ql/src/semmle/code/cpp/exprs/Expr.qll index df347235006..a6d8f6b877f 100644 --- a/cpp/ql/src/semmle/code/cpp/exprs/Expr.qll +++ b/cpp/ql/src/semmle/code/cpp/exprs/Expr.qll @@ -544,7 +544,7 @@ class BinaryOperation extends Operation, @bin_op_expr { * binary operation. */ predicate hasOperands(Expr e1, Expr e2) { - exists(int i | i in [0 .. 1] | + exists(int i | i in [0, 1] | this.hasChild(e1, i) and this.hasChild(e2, 1 - i) ) From 01a226bdcfe72bad1d53b581d1a846be9d814e10 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Tue, 18 Aug 2020 16:53:29 +0200 Subject: [PATCH 118/133] C++: Rename multipliesBy->effectivelyMultipliesBy From code review of #4098. --- .../cpp/rangeanalysis/SimpleRangeAnalysis.qll | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll index 0ef1d1f7104..db6293eb05d 100644 --- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll @@ -190,7 +190,7 @@ private class UnsignedMulExpr extends MulExpr { * Holds if `expr` is effectively a multiplication of `operand` with the * positive constant `positive`. */ -private predicate multipliesByPositive(Expr expr, Expr operand, float positive) { +private predicate effectivelyMultipliesByPositive(Expr expr, Expr operand, float positive) { operand = expr.(MulByConstantExpr).getOperand() and positive = expr.(MulByConstantExpr).getConstant() and positive >= 0.0 // includes positive zero @@ -209,7 +209,7 @@ private predicate multipliesByPositive(Expr expr, Expr operand, float positive) * Holds if `expr` is effectively a multiplication of `operand` with the * negative constant `negative`. */ -private predicate multipliesByNegative(Expr expr, Expr operand, float negative) { +private predicate effectivelyMultipliesByNegative(Expr expr, Expr operand, float negative) { operand = expr.(MulByConstantExpr).getOperand() and negative = expr.(MulByConstantExpr).getConstant() and negative < 0.0 // includes negative zero @@ -251,9 +251,9 @@ private predicate analyzableExpr(Expr e) { ( exists(getValue(e).toFloat()) or - multipliesByPositive(e, _, _) + effectivelyMultipliesByPositive(e, _, _) or - multipliesByNegative(e, _, _) + effectivelyMultipliesByNegative(e, _, _) or e instanceof MinExpr or @@ -359,12 +359,12 @@ private predicate defDependsOnDef( */ private predicate exprDependsOnDef(Expr e, RangeSsaDefinition srcDef, StackVariable srcVar) { exists(Expr operand | - multipliesByNegative(e, operand, _) and + effectivelyMultipliesByNegative(e, operand, _) and exprDependsOnDef(operand, srcDef, srcVar) ) or exists(Expr operand | - multipliesByPositive(e, operand, _) and + effectivelyMultipliesByPositive(e, operand, _) and exprDependsOnDef(operand, srcDef, srcVar) ) or @@ -673,13 +673,13 @@ deprecated predicate positive_overflow(Expr expr) { exprMightOverflowPositively( /** Only to be called by `getTruncatedLowerBounds`. */ private float getLowerBoundsImpl(Expr expr) { exists(Expr operand, float operandLow, float positive | - multipliesByPositive(expr, operand, positive) and + effectivelyMultipliesByPositive(expr, operand, positive) and operandLow = getFullyConvertedLowerBounds(operand) and result = positive * operandLow ) or exists(Expr operand, float operandHigh, float negative | - multipliesByNegative(expr, operand, negative) and + effectivelyMultipliesByNegative(expr, operand, negative) and operandHigh = getFullyConvertedUpperBounds(operand) and result = negative * operandHigh ) @@ -867,13 +867,13 @@ private float getLowerBoundsImpl(Expr expr) { /** Only to be called by `getTruncatedUpperBounds`. */ private float getUpperBoundsImpl(Expr expr) { exists(Expr operand, float operandHigh, float positive | - multipliesByPositive(expr, operand, positive) and + effectivelyMultipliesByPositive(expr, operand, positive) and operandHigh = getFullyConvertedUpperBounds(operand) and result = positive * operandHigh ) or exists(Expr operand, float operandLow, float negative | - multipliesByNegative(expr, operand, negative) and + effectivelyMultipliesByNegative(expr, operand, negative) and operandLow = getFullyConvertedLowerBounds(operand) and result = negative * operandLow ) From 341ab2ee0e123717b711887344698ecfaecf4b5b Mon Sep 17 00:00:00 2001 From: Jonathan Leitschuh Date: Tue, 18 Aug 2020 13:20:56 -0400 Subject: [PATCH 119/133] Fix formatting on jOOQ.qll --- java/ql/src/semmle/code/java/frameworks/jOOQ.qll | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/java/ql/src/semmle/code/java/frameworks/jOOQ.qll b/java/ql/src/semmle/code/java/frameworks/jOOQ.qll index 2eb1284ab70..5f473a18f33 100644 --- a/java/ql/src/semmle/code/java/frameworks/jOOQ.qll +++ b/java/ql/src/semmle/code/java/frameworks/jOOQ.qll @@ -10,9 +10,7 @@ import java * https://www.jooq.org/doc/current/manual/sql-building/plain-sql/ */ private class PlainSQLType extends Annotation { - PlainSQLType() { - this.getType().hasQualifiedName("org.jooq", "PlainSQL") - } + PlainSQLType() { this.getType().hasQualifiedName("org.jooq", "PlainSQL") } } /** From d7849bc13f8ac3fe23334fe127ed6e30a343ffc9 Mon Sep 17 00:00:00 2001 From: Nick Rolfe Date: Tue, 18 Aug 2020 18:39:00 +0100 Subject: [PATCH 120/133] C++: fix compilation errors in ssa.cpp --- cpp/ql/test/library-tests/ir/ssa/ssa.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/test/library-tests/ir/ssa/ssa.cpp b/cpp/ql/test/library-tests/ir/ssa/ssa.cpp index b8788c5c6aa..34886b1f343 100644 --- a/cpp/ql/test/library-tests/ir/ssa/ssa.cpp +++ b/cpp/ql/test/library-tests/ir/ssa/ssa.cpp @@ -291,7 +291,7 @@ struct A { Point *NewAliasing(int x) { Point* p = new Point; Point* q = new Point; - int j = new A(new A(x))->i; + int j = (new A(new A(x)))->i; A* a = new A; return p; } @@ -310,4 +310,4 @@ class ThisAliasTest { void setX(int arg) { this->x = arg; } -}; \ No newline at end of file +}; From 103f739d16fed34eaf3c66695e8c29e475f0940f Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 18 Aug 2020 13:03:16 +0200 Subject: [PATCH 121/133] add test for types of modules --- .../test/library-tests/ModuleTypes/import.js | 5 +++++ .../ql/test/library-tests/ModuleTypes/mjs.mjs | 1 + .../test/library-tests/ModuleTypes/require.js | 7 +++++++ .../test/library-tests/ModuleTypes/script.js | 1 + .../library-tests/ModuleTypes/tests.expected | 4 ++++ .../ql/test/library-tests/ModuleTypes/tests.ql | 18 ++++++++++++++++++ 6 files changed, 36 insertions(+) create mode 100644 javascript/ql/test/library-tests/ModuleTypes/import.js create mode 100644 javascript/ql/test/library-tests/ModuleTypes/mjs.mjs create mode 100644 javascript/ql/test/library-tests/ModuleTypes/require.js create mode 100644 javascript/ql/test/library-tests/ModuleTypes/script.js create mode 100644 javascript/ql/test/library-tests/ModuleTypes/tests.expected create mode 100644 javascript/ql/test/library-tests/ModuleTypes/tests.ql diff --git a/javascript/ql/test/library-tests/ModuleTypes/import.js b/javascript/ql/test/library-tests/ModuleTypes/import.js new file mode 100644 index 00000000000..fc9423ddb3b --- /dev/null +++ b/javascript/ql/test/library-tests/ModuleTypes/import.js @@ -0,0 +1,5 @@ +import * as fs from "fs"; + +export default function (x) { + return fs.readFileSync(x); +}; \ No newline at end of file diff --git a/javascript/ql/test/library-tests/ModuleTypes/mjs.mjs b/javascript/ql/test/library-tests/ModuleTypes/mjs.mjs new file mode 100644 index 00000000000..7c72272af5a --- /dev/null +++ b/javascript/ql/test/library-tests/ModuleTypes/mjs.mjs @@ -0,0 +1 @@ +console.log("I'm a .mjs file!"); \ No newline at end of file diff --git a/javascript/ql/test/library-tests/ModuleTypes/require.js b/javascript/ql/test/library-tests/ModuleTypes/require.js new file mode 100644 index 00000000000..982e834a4d4 --- /dev/null +++ b/javascript/ql/test/library-tests/ModuleTypes/require.js @@ -0,0 +1,7 @@ +var fs = require("fs"); + +module.exports = { + foo: function (x) { + return fs.readFileSync(x); + } +} \ No newline at end of file diff --git a/javascript/ql/test/library-tests/ModuleTypes/script.js b/javascript/ql/test/library-tests/ModuleTypes/script.js new file mode 100644 index 00000000000..020c176d43f --- /dev/null +++ b/javascript/ql/test/library-tests/ModuleTypes/script.js @@ -0,0 +1 @@ +console.log("I'm a plain script!"); \ No newline at end of file diff --git a/javascript/ql/test/library-tests/ModuleTypes/tests.expected b/javascript/ql/test/library-tests/ModuleTypes/tests.expected new file mode 100644 index 00000000000..023ac9d1a61 --- /dev/null +++ b/javascript/ql/test/library-tests/ModuleTypes/tests.expected @@ -0,0 +1,4 @@ +| import.js:1:1:5:2 | | es2015 | +| mjs.mjs:1:1:1:32 | | es2015 | +| require.js:1:1:7:1 | | node | +| script.js:1:1:1:35 | | non-module | diff --git a/javascript/ql/test/library-tests/ModuleTypes/tests.ql b/javascript/ql/test/library-tests/ModuleTypes/tests.ql new file mode 100644 index 00000000000..45d1a927177 --- /dev/null +++ b/javascript/ql/test/library-tests/ModuleTypes/tests.ql @@ -0,0 +1,18 @@ +import javascript + +query string getModuleType(TopLevel top) { + not top.isExterns() and + ( + not top instanceof Module and + result = "non-module" + or + top instanceof NodeModule and + result = "node" + or + top instanceof ES2015Module and + result = "es2015" + or + top instanceof AmdModule and + result = "amd" + ) +} From 3d5c1560e44291f3bb9ee267c1f2b050f7066167 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 18 Aug 2020 14:10:18 +0200 Subject: [PATCH 122/133] basic support for `.cjs` files --- .../com/semmle/js/extractor/AutoBuild.java | 2 +- .../semmle/js/extractor/FileExtractor.java | 2 +- .../src/com/semmle/js/extractor/Main.java | 2 +- .../semmle/js/extractor/ScriptExtractor.java | 13 +- .../extractor/tests/extensions/input/tst4.cjs | 1 + .../extensions/output/trap/tst4.cjs.trap | 141 ++++++++++++++++++ .../ql/src/semmle/javascript/NodeJS.qll | 6 +- .../javascript/NodeModuleResolutionImpl.qll | 8 +- .../library-tests/ModuleTypes/commonjs.cjs | 3 + .../library-tests/ModuleTypes/tests.expected | 1 + 10 files changed, 168 insertions(+), 11 deletions(-) create mode 100644 javascript/extractor/tests/extensions/input/tst4.cjs create mode 100644 javascript/extractor/tests/extensions/output/trap/tst4.cjs.trap create mode 100644 javascript/ql/test/library-tests/ModuleTypes/commonjs.cjs diff --git a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java index 9992e912043..28c96f806f7 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java +++ b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java @@ -144,7 +144,7 @@ import com.semmle.util.trap.TrapWriter; * *