mirror of
https://github.com/github/codeql.git
synced 2026-05-01 19:55:15 +02:00
Merge pull request #14909 from jketema/rm-dtt
C++: Remove `DefaultTaintTracking` library
This commit is contained in:
@@ -1,74 +0,0 @@
|
||||
#include "../shared.h"
|
||||
|
||||
using SinkFunction = void (*)(int);
|
||||
|
||||
void notSink(int notSinkParam);
|
||||
|
||||
void callsSink(int sinkParam) { // $ ir-path=31:23 ir-path=32:26 ir-path=34:17
|
||||
sink(sinkParam); // $ ast=31:28 ast=32:31 ast=34:22 ir-sink
|
||||
}
|
||||
|
||||
struct {
|
||||
SinkFunction sinkPtr, notSinkPtr;
|
||||
} globalStruct;
|
||||
|
||||
union {
|
||||
SinkFunction sinkPtr, notSinkPtr;
|
||||
} globalUnion;
|
||||
|
||||
SinkFunction globalSinkPtr;
|
||||
|
||||
void assignGlobals() {
|
||||
globalStruct.sinkPtr = callsSink;
|
||||
globalUnion.sinkPtr = callsSink;
|
||||
globalSinkPtr = callsSink;
|
||||
};
|
||||
|
||||
void testStruct() {
|
||||
globalStruct.sinkPtr(atoi(getenv("TAINTED"))); // $ MISSING: ir-path,ast
|
||||
globalStruct.notSinkPtr(atoi(getenv("TAINTED"))); // clean
|
||||
|
||||
globalUnion.sinkPtr(atoi(getenv("TAINTED"))); // $ ast ir-path
|
||||
globalUnion.notSinkPtr(atoi(getenv("TAINTED"))); // $ ast ir-path
|
||||
|
||||
globalSinkPtr(atoi(getenv("TAINTED"))); // $ ast ir-path
|
||||
}
|
||||
|
||||
class B {
|
||||
public:
|
||||
virtual void f(const char*) = 0;
|
||||
};
|
||||
|
||||
class D1 : public B {};
|
||||
|
||||
class D2 : public D1 {
|
||||
public:
|
||||
void f(const char* p) override {}
|
||||
};
|
||||
|
||||
class D3 : public D2 {
|
||||
public:
|
||||
void f(const char* p) override { // $ ir-path=58:10 ir-path=60:17 ir-path=61:28 ir-path=62:29 ir-path=63:33 SPURIOUS: ir-path=73:30
|
||||
sink(p); // $ ast=58:10 ast=60:17 ast=61:28 ast=62:29 ast=63:33 ir-sink SPURIOUS: ast=73:30
|
||||
}
|
||||
};
|
||||
|
||||
void test_dynamic_cast() {
|
||||
B* b = new D3();
|
||||
b->f(getenv("VAR")); // $ ast ir-path
|
||||
|
||||
((D2*)b)->f(getenv("VAR")); // $ ast ir-path
|
||||
static_cast<D2*>(b)->f(getenv("VAR")); // $ ast ir-path
|
||||
dynamic_cast<D2*>(b)->f(getenv("VAR")); // $ ast ir-path
|
||||
reinterpret_cast<D2*>(b)->f(getenv("VAR")); // $ ast ir-path
|
||||
|
||||
B* b2 = new D2();
|
||||
b2->f(getenv("VAR"));
|
||||
|
||||
((D2*)b2)->f(getenv("VAR"));
|
||||
static_cast<D2*>(b2)->f(getenv("VAR"));
|
||||
dynamic_cast<D2*>(b2)->f(getenv("VAR"));
|
||||
reinterpret_cast<D2*>(b2)->f(getenv("VAR"));
|
||||
|
||||
dynamic_cast<D3*>(b2)->f(getenv("VAR")); // $ SPURIOUS: ast ir-path
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
WARNING: Module TaintedWithPath has been deprecated and may be removed in future (tainted.ql:9,8-47)
|
||||
WARNING: Predicate tainted has been deprecated and may be removed in future (tainted.ql:20,49-74)
|
||||
testFailures
|
||||
failures
|
||||
@@ -1,100 +0,0 @@
|
||||
/**
|
||||
* This test provides the possibility to annotate elements when they are on a path of a taint flow to a sink.
|
||||
* This is different when compared to the tests in `../annotate_sink`, where only sink invocations are annotated.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.security.TaintTrackingImpl as AstTaintTracking
|
||||
import semmle.code.cpp.ir.dataflow.DefaultTaintTracking as IRDefaultTaintTracking
|
||||
import IRDefaultTaintTracking::TaintedWithPath as TaintedWithPath
|
||||
import TaintedWithPath::Private
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
|
||||
predicate isSinkArgument(Element sink) {
|
||||
exists(FunctionCall call |
|
||||
call.getTarget().getName() = "sink" and
|
||||
sink = call.getAnArgument()
|
||||
)
|
||||
}
|
||||
|
||||
predicate astTaint(Expr source, Element sink) { AstTaintTracking::tainted(source, sink) }
|
||||
|
||||
class SourceConfiguration extends TaintedWithPath::TaintTrackingConfiguration {
|
||||
override predicate isSink(Element e) { isSinkArgument(e) }
|
||||
}
|
||||
|
||||
predicate irTaint(Element source, TaintedWithPath::PathNode predNode, string tag) {
|
||||
exists(TaintedWithPath::PathNode sinkNode |
|
||||
TaintedWithPath::taintedWithPath(source, _, _, sinkNode) and
|
||||
predNode = getAPredecessor*(sinkNode) and
|
||||
// Make sure the path is actually reachable from this predecessor.
|
||||
// Otherwise, we could pick `predNode` to be b when `source` is
|
||||
// `source1` in this dataflow graph:
|
||||
// source1 ---> a ---> c ---> sinkNode
|
||||
// ^
|
||||
// source2 ---> b --/
|
||||
source = getElementFromPathNode(getAPredecessor*(predNode)) and
|
||||
if predNode = sinkNode then tag = "ir-sink" else tag = "ir-path"
|
||||
)
|
||||
}
|
||||
|
||||
module IRDefaultTaintTrackingTest implements TestSig {
|
||||
string getARelevantTag() { result = ["ir-path", "ir-sink"] }
|
||||
|
||||
predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(Element elem, TaintedWithPath::PathNode node, int n |
|
||||
irTaint(_, node, tag) and
|
||||
elem = getElementFromPathNode(node) and
|
||||
n = count(int startline | getAPredecessor(node).hasLocationInfo(_, startline, _, _, _)) and
|
||||
location = elem.getLocation() and
|
||||
element = elem.toString()
|
||||
|
|
||||
// Zero predecessors means it's a source, and 1 predecessor means it has a unique predecessor.
|
||||
// In either of these cases we leave out the location.
|
||||
n = [0, 1] and value = ""
|
||||
or
|
||||
// If there is more than one predecessor for this node
|
||||
// we specify the source location explicitly.
|
||||
n > 1 and
|
||||
exists(TaintedWithPath::PathNode pred | pred = getAPredecessor(node) |
|
||||
value =
|
||||
getElementFromPathNode(pred).getLocation().getStartLine().toString() + ":" +
|
||||
getElementFromPathNode(pred).getLocation().getStartColumn()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module AstTaintTrackingTest implements TestSig {
|
||||
string getARelevantTag() { result = "ast" }
|
||||
|
||||
predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(Expr source, Element tainted, int n |
|
||||
tag = "ast" and
|
||||
astTaint(source, tainted) and
|
||||
(
|
||||
isSinkArgument(tainted)
|
||||
or
|
||||
exists(Element sink |
|
||||
isSinkArgument(sink) and
|
||||
astTaint(tainted, sink)
|
||||
)
|
||||
) and
|
||||
n = strictcount(Expr otherSource | astTaint(otherSource, tainted)) and
|
||||
(
|
||||
n = 1 and value = ""
|
||||
or
|
||||
// If there is more than one source for this sink
|
||||
// we specify the source location explicitly.
|
||||
n > 1 and
|
||||
value =
|
||||
source.getLocation().getStartLine().toString() + ":" +
|
||||
source.getLocation().getStartColumn()
|
||||
) and
|
||||
location = tainted.getLocation() and
|
||||
element = tainted.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
import MakeTest<MergeTests<IRDefaultTaintTrackingTest, AstTaintTrackingTest>>
|
||||
@@ -1,129 +0,0 @@
|
||||
#include "../shared.h"
|
||||
|
||||
|
||||
struct S {
|
||||
void(*f)(const char*);
|
||||
|
||||
void apply(char* p) {
|
||||
f(p);
|
||||
}
|
||||
|
||||
void (*get())(const char*) {
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
void calls_sink_with_argv(const char* a) { // $ ir-path=96:26 ir-path=102:26
|
||||
sink(a); // $ ast=96:26 ast=98:18 ir-sink
|
||||
}
|
||||
|
||||
extern int i;
|
||||
|
||||
class BaseWithPureVirtual {
|
||||
public:
|
||||
virtual void f(const char*) = 0;
|
||||
};
|
||||
|
||||
class DerivedCallsSink : public BaseWithPureVirtual {
|
||||
public:
|
||||
void f(const char* p) override { // $ ir-path
|
||||
sink(p); // $ ast=108:10 ir-sink SPURIOUS: ast=111:10
|
||||
}
|
||||
};
|
||||
|
||||
class DerivedDoesNotCallSink : public BaseWithPureVirtual {
|
||||
public:
|
||||
void f(const char* p) override {}
|
||||
};
|
||||
|
||||
class DerivedCallsSinkDiamond1 : virtual public BaseWithPureVirtual {
|
||||
public:
|
||||
void f(const char* p) override { // $ ir-path
|
||||
sink(p); // $ ast ir-sink
|
||||
}
|
||||
};
|
||||
|
||||
class DerivedDoesNotCallSinkDiamond2 : virtual public BaseWithPureVirtual {
|
||||
public:
|
||||
void f(const char* p) override {}
|
||||
};
|
||||
|
||||
class DerivesMultiple : public DerivedCallsSinkDiamond1, public DerivedDoesNotCallSinkDiamond2 {
|
||||
void f(const char* p) override { // $ ir-path=53:37 ir-path=115:11
|
||||
DerivedCallsSinkDiamond1::f(p); // $ ir-path
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class CRTP {
|
||||
public:
|
||||
void f(const char* p) { // $ ir-path
|
||||
static_cast<T*>(this)->g(p); // $ ir-path
|
||||
}
|
||||
};
|
||||
|
||||
class CRTPCallsSink : public CRTP<CRTPCallsSink> {
|
||||
public:
|
||||
void g(const char* p) { // $ ir-path
|
||||
sink(p); // $ ast ir-sink
|
||||
}
|
||||
};
|
||||
|
||||
class Derived1 : public BaseWithPureVirtual {};
|
||||
|
||||
class Derived2 : public Derived1 {
|
||||
public:
|
||||
void f(const char* p) override {}
|
||||
};
|
||||
|
||||
class Derived3 : public Derived2 {
|
||||
public:
|
||||
void f(const char* p) override { // $ ir-path=124:19 ir-path=126:43 ir-path=128:44
|
||||
sink(p); // $ ast=124:19 ast=126:43 ast=128:44 ir-sink
|
||||
}
|
||||
};
|
||||
|
||||
class CRTPDoesNotCallSink : public CRTP<CRTPDoesNotCallSink> {
|
||||
public:
|
||||
void g(const char* p) {}
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
sink(argv[0]); // $ ast,ir-path,ir-sink
|
||||
|
||||
sink(reinterpret_cast<int>(argv)); // $ ast,ir-sink
|
||||
|
||||
calls_sink_with_argv(argv[1]); // $ ast,ir-path
|
||||
|
||||
char*** p = &argv; // $ ast,ir-path
|
||||
|
||||
sink(*p[0]); // $ ast ir-sink=96:26 ir-sink=98:18 ir-sink=98:17
|
||||
|
||||
calls_sink_with_argv(*p[i]); // $ ir-path=96:26 ir-path=98:18 ir-path=98:17 MISSING:ast
|
||||
|
||||
sink(*(argv + 1)); // $ ast ir-path ir-sink
|
||||
|
||||
BaseWithPureVirtual* b = new DerivedCallsSink;
|
||||
|
||||
b->f(argv[1]); // $ ast,ir-path
|
||||
|
||||
b = new DerivedDoesNotCallSink;
|
||||
b->f(argv[0]); // $ SPURIOUS: ast
|
||||
|
||||
BaseWithPureVirtual* b2 = new DerivesMultiple;
|
||||
|
||||
b2->f(argv[i]); // $ ast,ir-path
|
||||
|
||||
CRTP<CRTPDoesNotCallSink> crtp_not_call_sink;
|
||||
crtp_not_call_sink.f(argv[0]); // clean
|
||||
|
||||
CRTP<CRTPCallsSink> crtp_calls_sink;
|
||||
crtp_calls_sink.f(argv[0]); // $ ast,ir-path
|
||||
|
||||
Derived1* calls_sink = new Derived3;
|
||||
calls_sink->f(argv[1]); // $ ast,ir-path
|
||||
|
||||
static_cast<Derived2*>(calls_sink)->f(argv[1]); // $ ast,ir-path
|
||||
|
||||
dynamic_cast<Derived2*>(calls_sink)->f(argv[1]); // $ ast,ir-path
|
||||
}
|
||||
@@ -1,237 +0,0 @@
|
||||
#include "../shared.h"
|
||||
|
||||
int main() {
|
||||
sink(_strdup(getenv("VAR"))); // $ ir MISSING: ast
|
||||
sink(strdup(getenv("VAR"))); // $ ast,ir
|
||||
sink(unmodeled_function(getenv("VAR"))); // clean by assumption
|
||||
|
||||
char untainted_buf[100] = "";
|
||||
char buf[100] = "VAR = ";
|
||||
sink(strcat(buf, getenv("VAR"))); // $ ast,ir
|
||||
|
||||
sink(buf); // $ ast,ir
|
||||
sink(untainted_buf); // the two buffers would be conflated if we added flow through all partial chi inputs
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef unsigned int inet_addr_retval;
|
||||
inet_addr_retval inet_addr(const char *dotted_address);
|
||||
void sink(inet_addr_retval);
|
||||
|
||||
void test_indirect_arg_to_model() {
|
||||
// This test is non-sensical but carefully arranged so we get data flow into
|
||||
// inet_addr not through the function argument but through its associated
|
||||
// read side effect.
|
||||
void *env_pointer = getenv("VAR"); // env_pointer is tainted, not its data.
|
||||
inet_addr_retval a = inet_addr((const char *)&env_pointer);
|
||||
sink(a); // $ ast,ir
|
||||
}
|
||||
|
||||
namespace std {
|
||||
template< class T >
|
||||
T&& move( T&& t ) noexcept;
|
||||
}
|
||||
|
||||
void test_std_move() {
|
||||
sink(std::move(getenv("VAR"))); // $ ir MISSING: ast
|
||||
}
|
||||
|
||||
void flow_to_outparam(char ** ret, char *arg) {
|
||||
*ret = arg;
|
||||
}
|
||||
|
||||
void test_outparams() {
|
||||
char *p2 = nullptr;
|
||||
flow_to_outparam(&p2, getenv("VAR"));
|
||||
sink(p2); // $ ir MISSING: ast
|
||||
}
|
||||
|
||||
struct XY {
|
||||
int x;
|
||||
int y;
|
||||
};
|
||||
|
||||
void taint_y(XY *xyp) {
|
||||
int tainted = getenv("VAR")[0];
|
||||
xyp->y = tainted;
|
||||
}
|
||||
|
||||
void test_conflated_fields3() {
|
||||
XY xy;
|
||||
xy.x = 0;
|
||||
taint_y(&xy);
|
||||
sink(xy.x); // not tainted
|
||||
}
|
||||
|
||||
struct Point {
|
||||
int x;
|
||||
int y;
|
||||
|
||||
void callSink() {
|
||||
sink(this->x); // $ ir MISSING: ast
|
||||
sink(this->y); // not tainted
|
||||
}
|
||||
};
|
||||
|
||||
void test_conflated_fields1() {
|
||||
Point p;
|
||||
p.x = getenv("VAR")[0];
|
||||
sink(p.x); // $ ir MISSING: ast
|
||||
sink(p.y); // not tainted
|
||||
p.callSink();
|
||||
}
|
||||
|
||||
void taint_x(Point *pp) {
|
||||
pp->x = getenv("VAR")[0];
|
||||
}
|
||||
|
||||
void y_to_sink(Point *pp) {
|
||||
sink(pp->y); // not tainted
|
||||
}
|
||||
|
||||
void test_conflated_fields2() {
|
||||
Point p;
|
||||
taint_x(&p);
|
||||
y_to_sink(&p);
|
||||
}
|
||||
|
||||
void sink(Point*);
|
||||
void sink(Point);
|
||||
|
||||
void test_field_to_obj_taint_object(Point p) {
|
||||
p.x = getenv("VAR")[0];
|
||||
sink(p); // not tainted
|
||||
sink(p.x); // $ ir MISSING: ast
|
||||
}
|
||||
|
||||
void test_field_to_obj_taint_object_addrof(Point p) {
|
||||
taint_x(&p);
|
||||
sink(p); // not tainted
|
||||
sink(&p); // not tainted
|
||||
sink(p.x); // $ ir MISSING: ast
|
||||
}
|
||||
|
||||
void test_field_to_obj_taint_pointer(Point* pp) {
|
||||
pp->x = getenv("VAR")[0];
|
||||
sink(pp);// not tainted
|
||||
sink(*pp); // not tainted
|
||||
}
|
||||
|
||||
void call_sink_on_object(Point* pp) {
|
||||
sink(pp);// not tainted
|
||||
sink(*pp);// not tainted
|
||||
}
|
||||
|
||||
void test_field_to_obj_taint_call_sink(Point* pp) {
|
||||
pp->x = getenv("VAR")[0];
|
||||
call_sink_on_object(pp);
|
||||
}
|
||||
|
||||
void test_field_to_obj_taint_through_setter(Point* pp) {
|
||||
taint_x(pp);
|
||||
sink(pp);// not tainted
|
||||
sink(*pp); // not tainted
|
||||
}
|
||||
|
||||
Point* getPoint();
|
||||
|
||||
void test_field_to_obj_local_variable() {
|
||||
Point* pp = getPoint();
|
||||
pp->x = getenv("VAR")[0];
|
||||
sink(pp); // not tainted
|
||||
sink(*pp); // not tainted
|
||||
}
|
||||
|
||||
void test_field_to_obj_taint_array(Point* pp, int i) {
|
||||
pp[0].x = getenv("VAR")[0];
|
||||
sink(pp[i]); // not tainted
|
||||
sink(pp);// not tainted
|
||||
sink(*pp); // not tainted
|
||||
}
|
||||
|
||||
void test_field_to_obj_test_pointer_arith(Point* pp) {
|
||||
(pp + sizeof(*pp))->x = getenv("VAR")[0];
|
||||
sink(pp);// not tainted
|
||||
sink(pp + sizeof(*pp));// not tainted
|
||||
}
|
||||
|
||||
void sink(char **);
|
||||
|
||||
void test_pointers1()
|
||||
{
|
||||
char buffer[1024];
|
||||
char *s = getenv("VAR");
|
||||
char *ptr1, **ptr2;
|
||||
char *ptr3, **ptr4;
|
||||
|
||||
ptr1 = buffer;
|
||||
ptr2 = &ptr1;
|
||||
memcpy(buffer, s, 1024);
|
||||
ptr3 = buffer;
|
||||
ptr4 = &ptr3;
|
||||
|
||||
sink(buffer); // $ ast,ir
|
||||
sink(ptr1); // $ ast MISSING: ir
|
||||
sink(ptr2); // $ SPURIOUS: ast
|
||||
sink(*ptr2); // $ ast MISSING: ir
|
||||
sink(ptr3); // $ ast,ir
|
||||
sink(ptr4); // $ SPURIOUS: ast,ir
|
||||
sink(*ptr4); // $ ast,ir
|
||||
}
|
||||
|
||||
void test_pointers2()
|
||||
{
|
||||
char buffer[1024];
|
||||
char *s = getenv("VAR");
|
||||
char *ptr1, **ptr2;
|
||||
char *ptr3, **ptr4;
|
||||
|
||||
ptr1 = buffer;
|
||||
ptr2 = &ptr1;
|
||||
memcpy(*ptr2, s, 1024);
|
||||
ptr3 = buffer;
|
||||
ptr4 = &ptr3;
|
||||
|
||||
sink(buffer); // $ MISSING: ast,ir
|
||||
sink(ptr1); // $ ast MISSING: ir
|
||||
sink(ptr2); // $ SPURIOUS: ast,ir
|
||||
sink(*ptr2); // $ ast,ir
|
||||
sink(ptr3); // $ MISSING: ast,ir
|
||||
sink(ptr4); // clean
|
||||
sink(*ptr4); // $ MISSING: ast,ir
|
||||
}
|
||||
|
||||
// --- recv ---
|
||||
|
||||
int recv(int s, char* buf, int len, int flags);
|
||||
|
||||
void test_recv() {
|
||||
char buffer[1024];
|
||||
recv(0, buffer, sizeof(buffer), 0);
|
||||
sink(buffer); // $ ast,ir
|
||||
sink(*buffer); // $ ast,ir
|
||||
}
|
||||
|
||||
// --- send and related functions ---
|
||||
|
||||
struct iovec {
|
||||
void *iov_base;
|
||||
unsigned iov_len;
|
||||
};
|
||||
|
||||
int readv(int, const struct iovec*, int);
|
||||
|
||||
void sink(const iovec* iovs);
|
||||
void sink(iovec);
|
||||
|
||||
void test_readv_and_writev(iovec* iovs) {
|
||||
readv(0, iovs, 16);
|
||||
sink(iovs); // $ast,ir
|
||||
sink(iovs[0]); // $ast,ir
|
||||
sink(*iovs); // $ast,ir
|
||||
|
||||
char* p = (char*)iovs[1].iov_base;
|
||||
sink(p); // $ MISSING: ast,ir
|
||||
sink(*p); // $ MISSING: ast,ir
|
||||
}
|
||||
@@ -1,159 +0,0 @@
|
||||
|
||||
#include "../shared.h"
|
||||
|
||||
typedef unsigned long size_t;
|
||||
|
||||
namespace std
|
||||
{
|
||||
template<class charT> struct char_traits;
|
||||
|
||||
typedef size_t streamsize;
|
||||
|
||||
template <class T> class allocator {
|
||||
public:
|
||||
allocator() throw();
|
||||
};
|
||||
|
||||
template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> >
|
||||
class basic_string {
|
||||
public:
|
||||
explicit basic_string(const Allocator& a = Allocator());
|
||||
basic_string(const charT* s, const Allocator& a = Allocator());
|
||||
|
||||
const charT* c_str() const;
|
||||
};
|
||||
|
||||
typedef basic_string<char> string;
|
||||
|
||||
template <class charT, class traits = char_traits<charT> >
|
||||
class basic_istream /*: virtual public basic_ios<charT,traits> - not needed for this test */ {
|
||||
public:
|
||||
basic_istream<charT,traits>& operator>>(int& n);
|
||||
};
|
||||
|
||||
template <class charT, class traits = char_traits<charT> >
|
||||
class basic_ostream /*: virtual public basic_ios<charT,traits> - not needed for this test */ {
|
||||
public:
|
||||
typedef charT char_type;
|
||||
basic_ostream<charT,traits>& write(const char_type* s, streamsize n);
|
||||
|
||||
basic_ostream<charT, traits>& operator<<(int n);
|
||||
};
|
||||
|
||||
template<class charT, class traits> basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&, const charT*);
|
||||
template<class charT, class traits, class Allocator> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const basic_string<charT, traits, Allocator>& str);
|
||||
|
||||
template<class charT, class traits = char_traits<charT>>
|
||||
class basic_iostream : public basic_istream<charT, traits>, public basic_ostream<charT, traits> {
|
||||
public:
|
||||
};
|
||||
|
||||
template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>>
|
||||
class basic_stringstream : public basic_iostream<charT, traits> {
|
||||
public:
|
||||
explicit basic_stringstream(/*ios_base::openmode which = ios_base::out|ios_base::in - not needed for this test*/);
|
||||
|
||||
basic_string<charT, traits, Allocator> str() const;
|
||||
};
|
||||
|
||||
using stringstream = basic_stringstream<char>;
|
||||
}
|
||||
|
||||
char *source() { return getenv("USERDATA"); }
|
||||
void sink(const std::string &s) {};
|
||||
void sink(const std::stringstream &s) {};
|
||||
|
||||
void test_string()
|
||||
{
|
||||
char *a = source();
|
||||
std::string b("123");
|
||||
std::string c(source());
|
||||
|
||||
sink(a); // $ ast,ir
|
||||
sink(b); // clean
|
||||
sink(c); // $ ir MISSING: ast
|
||||
sink(b.c_str()); // clean
|
||||
sink(c.c_str()); // $ ir MISSING: ast
|
||||
}
|
||||
|
||||
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); // $ ir MISSING: ast
|
||||
sink(ss3); // $ ir MISSING: ast
|
||||
sink(ss4); // $ ir MISSING: ast
|
||||
sink(ss5); // $ ir MISSING: ast
|
||||
sink(ss1.str());
|
||||
sink(ss2.str()); // $ ir MISSING: ast
|
||||
sink(ss3.str()); // $ ir MISSING: ast
|
||||
sink(ss4.str()); // $ ir MISSING: ast
|
||||
sink(ss5.str()); // $ ir MISSING: ast
|
||||
}
|
||||
|
||||
void test_stringstream_int(int source)
|
||||
{
|
||||
std::stringstream ss1, ss2;
|
||||
|
||||
ss1 << 1234;
|
||||
ss2 << source;
|
||||
|
||||
sink(ss1); // clean
|
||||
sink(ss2); // $ MISSING: ast,ir
|
||||
sink(ss1.str()); // clean
|
||||
sink(ss2.str()); // $ MISSING: ast,ir
|
||||
}
|
||||
|
||||
using namespace std;
|
||||
|
||||
char *user_input() {
|
||||
return source();
|
||||
}
|
||||
|
||||
void sink(const char *filename, const char *mode);
|
||||
|
||||
void test_strings2()
|
||||
{
|
||||
string path1 = user_input();
|
||||
sink(path1.c_str(), "r"); // $ ir MISSING: ast
|
||||
|
||||
string path2;
|
||||
path2 = user_input();
|
||||
sink(path2.c_str(), "r"); // $ ir MISSING: ast
|
||||
|
||||
string path3(user_input());
|
||||
sink(path3.c_str(), "r"); // $ ir MISSING: ast
|
||||
}
|
||||
|
||||
void test_string3()
|
||||
{
|
||||
const char *cs = source();
|
||||
|
||||
// convert char * -> std::string
|
||||
std::string ss(cs);
|
||||
|
||||
sink(cs); // $ ast,ir
|
||||
sink(ss); // $ ir MISSING: ast
|
||||
}
|
||||
|
||||
void test_string4()
|
||||
{
|
||||
const char *cs = source();
|
||||
|
||||
// convert char * -> std::string
|
||||
std::string ss(cs);
|
||||
|
||||
// convert back std::string -> char *
|
||||
cs = ss.c_str();
|
||||
|
||||
sink(cs); // $ ast,ir
|
||||
sink(ss); // $ ir MISSING: ast
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
WARNING: Module TaintedWithPath has been deprecated and may be removed in future (tainted.ql:10,8-47)
|
||||
WARNING: Predicate tainted has been deprecated and may be removed in future (tainted.ql:21,3-28)
|
||||
testFailures
|
||||
failures
|
||||
@@ -1,80 +0,0 @@
|
||||
/**
|
||||
* This test provides the usual facilities to annotate taint flow when reaching a sink.
|
||||
* This is different when compared to the tests in `../annotate_path_to_sink`, where all elements on a taint path to a sink
|
||||
* are annotated.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.security.TaintTrackingImpl as AstTaintTracking
|
||||
import semmle.code.cpp.ir.dataflow.DefaultTaintTracking as IRDefaultTaintTracking
|
||||
import IRDefaultTaintTracking::TaintedWithPath as TaintedWithPath
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
|
||||
predicate argToSinkCall(Element sink) {
|
||||
exists(FunctionCall call |
|
||||
call.getTarget().getName() = "sink" and
|
||||
sink = call.getAnArgument()
|
||||
)
|
||||
}
|
||||
|
||||
predicate astTaint(Expr source, Element sink) {
|
||||
AstTaintTracking::tainted(source, sink) and argToSinkCall(sink)
|
||||
}
|
||||
|
||||
class SourceConfiguration extends TaintedWithPath::TaintTrackingConfiguration {
|
||||
override predicate isSink(Element e) { argToSinkCall(e) }
|
||||
}
|
||||
|
||||
predicate irTaint(Expr source, Element sink) {
|
||||
TaintedWithPath::taintedWithPath(source, sink, _, _)
|
||||
}
|
||||
|
||||
module IRDefaultTaintTrackingTest implements TestSig {
|
||||
string getARelevantTag() { result = "ir" }
|
||||
|
||||
predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(Expr source, Element tainted, int n |
|
||||
tag = "ir" and
|
||||
irTaint(source, tainted) and
|
||||
n = strictcount(Expr otherSource | irTaint(otherSource, tainted)) and
|
||||
(
|
||||
n = 1 and value = ""
|
||||
or
|
||||
// If there is more than one source for this sink
|
||||
// we specify the source location explicitly.
|
||||
n > 1 and
|
||||
value =
|
||||
source.getLocation().getStartLine().toString() + ":" +
|
||||
source.getLocation().getStartColumn()
|
||||
) and
|
||||
location = tainted.getLocation() and
|
||||
element = tainted.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module AstTaintTrackingTest implements TestSig {
|
||||
string getARelevantTag() { result = "ast" }
|
||||
|
||||
predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(Expr source, Element tainted, int n |
|
||||
tag = "ast" and
|
||||
astTaint(source, tainted) and
|
||||
n = strictcount(Expr otherSource | astTaint(otherSource, tainted)) and
|
||||
(
|
||||
n = 1 and value = ""
|
||||
or
|
||||
// If there is more than one source for this sink
|
||||
// we specify the source location explicitly.
|
||||
n > 1 and
|
||||
value =
|
||||
source.getLocation().getStartLine().toString() + ":" +
|
||||
source.getLocation().getStartColumn()
|
||||
) and
|
||||
location = tainted.getLocation() and
|
||||
element = tainted.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
import MakeTest<MergeTests<IRDefaultTaintTrackingTest, AstTaintTrackingTest>>
|
||||
@@ -1,4 +0,0 @@
|
||||
WARNING: Predicate taintedIncludingGlobalVars has been deprecated and may be removed in future (global.ql:8,3-47)
|
||||
WARNING: Predicate taintedIncludingGlobalVars has been deprecated and may be removed in future (global.ql:12,3-53)
|
||||
failures
|
||||
testFailures
|
||||
@@ -1,41 +0,0 @@
|
||||
import cpp
|
||||
import semmle.code.cpp.security.Security
|
||||
import semmle.code.cpp.security.TaintTrackingImpl as AstTaintTracking
|
||||
import semmle.code.cpp.ir.dataflow.DefaultTaintTracking as IRDefaultTaintTracking
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
|
||||
predicate astTaint(Expr source, Element sink, string globalVar) {
|
||||
AstTaintTracking::taintedIncludingGlobalVars(source, sink, globalVar) and globalVar != ""
|
||||
}
|
||||
|
||||
predicate irTaint(Expr source, Element sink, string globalVar) {
|
||||
IRDefaultTaintTracking::taintedIncludingGlobalVars(source, sink, globalVar) and globalVar != ""
|
||||
}
|
||||
|
||||
module IRGlobalDefaultTaintTrackingTest implements TestSig {
|
||||
string getARelevantTag() { result = "ir" }
|
||||
|
||||
predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(Element tainted |
|
||||
tag = "ir" and
|
||||
irTaint(_, tainted, value) and
|
||||
location = tainted.getLocation() and
|
||||
element = tainted.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module AstGlobalDefaultTaintTrackingTest implements TestSig {
|
||||
string getARelevantTag() { result = "ast" }
|
||||
|
||||
predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(Element tainted |
|
||||
tag = "ast" and
|
||||
astTaint(_, tainted, value) and
|
||||
location = tainted.getLocation() and
|
||||
element = tainted.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
import MakeTest<MergeTests<IRGlobalDefaultTaintTrackingTest, AstGlobalDefaultTaintTrackingTest>>
|
||||
@@ -1,24 +0,0 @@
|
||||
char *getenv(const char *name);
|
||||
void sink(const char *sinkparam); // $ ast,ir=global1 ast,ir=global2
|
||||
|
||||
void throughLocal() {
|
||||
char * local = getenv("VAR");
|
||||
sink(local);
|
||||
}
|
||||
|
||||
char * global1 = 0;
|
||||
|
||||
void readWriteGlobal1() {
|
||||
sink(global1); // $ ast,ir=global1
|
||||
global1 = getenv("VAR");
|
||||
}
|
||||
|
||||
static char * global2 = 0;
|
||||
|
||||
void readGlobal2() {
|
||||
sink(global2); // $ ast,ir=global2
|
||||
}
|
||||
|
||||
void writeGlobal2() {
|
||||
global2 = getenv("VAR");
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
// Common declarations in this test dir should go in this file. Otherwise, some
|
||||
// declarations will have multiple locations, which leads to confusing test
|
||||
// output.
|
||||
|
||||
void sink(const char *sinkparam);
|
||||
void sink(int sinkparam);
|
||||
|
||||
int atoi(const char *nptr);
|
||||
char *getenv(const char *name);
|
||||
char *strcat(char * s1, const char * s2);
|
||||
|
||||
char *strdup(const char *string);
|
||||
char *_strdup(const char *string);
|
||||
char *unmodeled_function(const char *const_string);
|
||||
|
||||
typedef unsigned long size_t;
|
||||
void *memcpy(void *s1, const void *s2, size_t n);
|
||||
@@ -1,91 +0,0 @@
|
||||
WARNING: Predicate taintedIncludingGlobalVars has been deprecated and may be removed in future (tainted.ql:5,3-29)
|
||||
| test.cpp:23:23:23:28 | call to getenv | test.cpp:8:24:8:25 | s1 | |
|
||||
| test.cpp:23:23:23:28 | call to getenv | test.cpp:23:14:23:19 | envStr | |
|
||||
| test.cpp:23:23:23:28 | call to getenv | test.cpp:23:23:23:28 | call to getenv | |
|
||||
| test.cpp:23:23:23:28 | call to getenv | test.cpp:23:23:23:40 | (const char *)... | |
|
||||
| test.cpp:23:23:23:28 | call to getenv | test.cpp:25:6:25:29 | ! ... | |
|
||||
| test.cpp:23:23:23:28 | call to getenv | test.cpp:25:7:25:12 | call to strcmp | |
|
||||
| test.cpp:23:23:23:28 | call to getenv | test.cpp:25:7:25:29 | (bool)... | |
|
||||
| test.cpp:23:23:23:28 | call to getenv | test.cpp:25:14:25:19 | envStr | |
|
||||
| test.cpp:23:23:23:28 | call to getenv | test.cpp:29:6:29:28 | ! ... | |
|
||||
| test.cpp:23:23:23:28 | call to getenv | test.cpp:29:7:29:12 | call to strcmp | |
|
||||
| test.cpp:23:23:23:28 | call to getenv | test.cpp:29:7:29:28 | (bool)... | |
|
||||
| test.cpp:23:23:23:28 | call to getenv | test.cpp:29:14:29:19 | envStr | |
|
||||
| test.cpp:38:23:38:28 | call to getenv | test.cpp:8:24:8:25 | s1 | |
|
||||
| test.cpp:38:23:38:28 | call to getenv | test.cpp:38:14:38:19 | envStr | |
|
||||
| test.cpp:38:23:38:28 | call to getenv | test.cpp:38:23:38:28 | call to getenv | |
|
||||
| test.cpp:38:23:38:28 | call to getenv | test.cpp:38:23:38:40 | (const char *)... | |
|
||||
| test.cpp:38:23:38:28 | call to getenv | test.cpp:40:14:40:19 | envStr | |
|
||||
| test.cpp:49:23:49:28 | call to getenv | test.cpp:8:24:8:25 | s1 | envStrGlobal |
|
||||
| test.cpp:49:23:49:28 | call to getenv | test.cpp:45:13:45:24 | envStrGlobal | |
|
||||
| test.cpp:49:23:49:28 | call to getenv | test.cpp:45:13:45:24 | envStrGlobal | envStrGlobal |
|
||||
| test.cpp:49:23:49:28 | call to getenv | test.cpp:49:14:49:19 | envStr | |
|
||||
| test.cpp:49:23:49:28 | call to getenv | test.cpp:49:23:49:28 | call to getenv | |
|
||||
| test.cpp:49:23:49:28 | call to getenv | test.cpp:49:23:49:40 | (const char *)... | |
|
||||
| test.cpp:49:23:49:28 | call to getenv | test.cpp:50:15:50:24 | envStr_ptr | |
|
||||
| test.cpp:49:23:49:28 | call to getenv | test.cpp:50:15:50:24 | envStr_ptr | envStrGlobal |
|
||||
| test.cpp:49:23:49:28 | call to getenv | test.cpp:50:28:50:40 | & ... | envStrGlobal |
|
||||
| test.cpp:49:23:49:28 | call to getenv | test.cpp:50:29:50:40 | envStrGlobal | envStrGlobal |
|
||||
| test.cpp:49:23:49:28 | call to getenv | test.cpp:52:2:52:12 | * ... | |
|
||||
| test.cpp:49:23:49:28 | call to getenv | test.cpp:52:3:52:12 | envStr_ptr | |
|
||||
| test.cpp:49:23:49:28 | call to getenv | test.cpp:52:16:52:21 | envStr | |
|
||||
| test.cpp:49:23:49:28 | call to getenv | test.cpp:54:6:54:35 | ! ... | envStrGlobal |
|
||||
| test.cpp:49:23:49:28 | call to getenv | test.cpp:54:7:54:12 | call to strcmp | envStrGlobal |
|
||||
| test.cpp:49:23:49:28 | call to getenv | test.cpp:54:7:54:35 | (bool)... | envStrGlobal |
|
||||
| test.cpp:49:23:49:28 | call to getenv | test.cpp:54:14:54:25 | envStrGlobal | envStrGlobal |
|
||||
| test.cpp:60:29:60:34 | call to getenv | test.cpp:10:27:10:27 | s | |
|
||||
| test.cpp:60:29:60:34 | call to getenv | test.cpp:60:18:60:25 | userName | |
|
||||
| test.cpp:60:29:60:34 | call to getenv | test.cpp:60:29:60:34 | call to getenv | |
|
||||
| test.cpp:60:29:60:34 | call to getenv | test.cpp:60:29:60:47 | (const char *)... | |
|
||||
| test.cpp:60:29:60:34 | call to getenv | test.cpp:64:25:64:32 | userName | |
|
||||
| test.cpp:68:28:68:33 | call to getenv | test.cpp:11:20:11:21 | s1 | |
|
||||
| test.cpp:68:28:68:33 | call to getenv | test.cpp:11:36:11:37 | s2 | |
|
||||
| test.cpp:68:28:68:33 | call to getenv | test.cpp:67:7:67:13 | copying | |
|
||||
| test.cpp:68:28:68:33 | call to getenv | test.cpp:68:17:68:24 | userName | |
|
||||
| test.cpp:68:28:68:33 | call to getenv | test.cpp:68:28:68:33 | call to getenv | |
|
||||
| test.cpp:68:28:68:33 | call to getenv | test.cpp:68:28:68:46 | (const char *)... | |
|
||||
| test.cpp:68:28:68:33 | call to getenv | test.cpp:69:10:69:13 | copy | |
|
||||
| test.cpp:68:28:68:33 | call to getenv | test.cpp:70:5:70:10 | call to strcpy | |
|
||||
| test.cpp:68:28:68:33 | call to getenv | test.cpp:70:12:70:15 | copy | |
|
||||
| test.cpp:68:28:68:33 | call to getenv | test.cpp:70:18:70:25 | userName | |
|
||||
| test.cpp:68:28:68:33 | call to getenv | test.cpp:71:12:71:15 | copy | |
|
||||
| test.cpp:75:20:75:25 | call to getenv | test.cpp:15:22:15:25 | nptr | |
|
||||
| test.cpp:75:20:75:25 | call to getenv | test.cpp:75:15:75:18 | call to atoi | |
|
||||
| test.cpp:75:20:75:25 | call to getenv | test.cpp:75:20:75:25 | call to getenv | |
|
||||
| test.cpp:75:20:75:25 | call to getenv | test.cpp:75:20:75:45 | (const char *)... | |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:8:24:8:25 | s1 | |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:11:20:11:21 | s1 | |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:11:36:11:37 | s2 | |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:83:17:83:24 | userName | |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:83:28:83:33 | call to getenv | |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:83:28:83:46 | (const char *)... | |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:85:8:85:11 | copy | |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:86:2:86:7 | call to strcpy | |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:86:9:86:12 | copy | |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:86:15:86:22 | userName | |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:6:88:27 | ! ... | |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:7:88:12 | call to strcmp | |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:7:88:27 | (bool)... | |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:14:88:17 | (const char *)... | |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:14:88:17 | copy | |
|
||||
| test.cpp:100:12:100:15 | call to gets | test.cpp:98:8:98:14 | pointer | |
|
||||
| test.cpp:100:12:100:15 | call to gets | test.cpp:100:2:100:8 | pointer | |
|
||||
| test.cpp:100:12:100:15 | call to gets | test.cpp:100:12:100:15 | call to gets | |
|
||||
| test.cpp:100:17:100:22 | buffer | test.cpp:93:18:93:18 | s | |
|
||||
| test.cpp:100:17:100:22 | buffer | test.cpp:97:7:97:12 | buffer | |
|
||||
| test.cpp:100:17:100:22 | buffer | test.cpp:100:17:100:22 | buffer | |
|
||||
| test.cpp:106:28:106:33 | call to getenv | test.cpp:8:24:8:25 | s1 | |
|
||||
| test.cpp:106:28:106:33 | call to getenv | test.cpp:11:20:11:21 | s1 | |
|
||||
| test.cpp:106:28:106:33 | call to getenv | test.cpp:11:36:11:37 | s2 | |
|
||||
| test.cpp:106:28:106:33 | call to getenv | test.cpp:106:17:106:24 | userName | |
|
||||
| test.cpp:106:28:106:33 | call to getenv | test.cpp:106:28:106:33 | call to getenv | |
|
||||
| test.cpp:106:28:106:33 | call to getenv | test.cpp:106:28:106:46 | (const char *)... | |
|
||||
| test.cpp:106:28:106:33 | call to getenv | test.cpp:108:8:108:11 | copy | |
|
||||
| test.cpp:106:28:106:33 | call to getenv | test.cpp:109:2:109:7 | call to strcpy | |
|
||||
| test.cpp:106:28:106:33 | call to getenv | test.cpp:109:9:109:12 | copy | |
|
||||
| test.cpp:106:28:106:33 | call to getenv | test.cpp:109:15:109:22 | userName | |
|
||||
| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:6:111:27 | ! ... | |
|
||||
| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:7:111:12 | call to strcmp | |
|
||||
| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:7:111:27 | (bool)... | |
|
||||
| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:14:111:17 | (const char *)... | |
|
||||
| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:14:111:17 | copy | |
|
||||
@@ -1,7 +0,0 @@
|
||||
import semmle.code.cpp.security.TaintTrackingImpl
|
||||
|
||||
from Expr source, Element tainted, string globalVar
|
||||
where
|
||||
taintedIncludingGlobalVars(source, tainted, globalVar) and
|
||||
not tainted.getLocation().getFile().getExtension() = "h"
|
||||
select source, tainted, globalVar
|
||||
@@ -1,51 +0,0 @@
|
||||
WARNING: Module TaintedWithPath has been deprecated and may be removed in future (tainted_diff.ql:5,35-54)
|
||||
WARNING: Module TaintedWithPath has been deprecated and may be removed in future (tainted_diff.ql:12,7-26)
|
||||
WARNING: Module TaintedWithPath has been deprecated and may be removed in future (tainted_diff.ql:16,3-22)
|
||||
WARNING: Predicate taintedIncludingGlobalVars has been deprecated and may be removed in future (tainted_diff.ql:11,3-34)
|
||||
WARNING: Predicate taintedIncludingGlobalVars has been deprecated and may be removed in future (tainted_diff.ql:17,7-38)
|
||||
| test.cpp:23:23:23:28 | call to getenv | test.cpp:8:24:8:25 | s1 | AST only |
|
||||
| test.cpp:23:23:23:28 | call to getenv | test.cpp:23:14:23:19 | envStr | AST only |
|
||||
| test.cpp:38:23:38:28 | call to getenv | test.cpp:8:24:8:25 | s1 | AST only |
|
||||
| test.cpp:38:23:38:28 | call to getenv | test.cpp:38:14:38:19 | envStr | AST only |
|
||||
| test.cpp:49:23:49:28 | call to getenv | test.cpp:8:24:8:25 | s1 | AST only |
|
||||
| test.cpp:49:23:49:28 | call to getenv | test.cpp:45:13:45:24 | envStrGlobal | AST only |
|
||||
| test.cpp:49:23:49:28 | call to getenv | test.cpp:49:14:49:19 | envStr | AST only |
|
||||
| test.cpp:49:23:49:28 | call to getenv | test.cpp:50:15:50:24 | envStr_ptr | AST only |
|
||||
| test.cpp:49:23:49:28 | call to getenv | test.cpp:50:28:50:40 | & ... | AST only |
|
||||
| test.cpp:49:23:49:28 | call to getenv | test.cpp:50:29:50:40 | envStrGlobal | AST only |
|
||||
| test.cpp:49:23:49:28 | call to getenv | test.cpp:52:2:52:12 | * ... | AST only |
|
||||
| test.cpp:49:23:49:28 | call to getenv | test.cpp:52:3:52:12 | envStr_ptr | AST only |
|
||||
| test.cpp:49:23:49:28 | call to getenv | test.cpp:54:6:54:35 | ! ... | AST only |
|
||||
| test.cpp:49:23:49:28 | call to getenv | test.cpp:54:7:54:12 | call to strcmp | AST only |
|
||||
| test.cpp:49:23:49:28 | call to getenv | test.cpp:54:7:54:35 | (bool)... | AST only |
|
||||
| test.cpp:49:23:49:28 | call to getenv | test.cpp:54:14:54:25 | envStrGlobal | AST only |
|
||||
| test.cpp:60:29:60:34 | call to getenv | test.cpp:10:27:10:27 | s | AST only |
|
||||
| test.cpp:60:29:60:34 | call to getenv | test.cpp:60:18:60:25 | userName | AST only |
|
||||
| test.cpp:68:28:68:33 | call to getenv | test.cpp:11:20:11:21 | s1 | AST only |
|
||||
| test.cpp:68:28:68:33 | call to getenv | test.cpp:11:36:11:37 | s2 | AST only |
|
||||
| test.cpp:68:28:68:33 | call to getenv | test.cpp:67:7:67:13 | copying | AST only |
|
||||
| test.cpp:68:28:68:33 | call to getenv | test.cpp:68:17:68:24 | userName | AST only |
|
||||
| test.cpp:68:28:68:33 | call to getenv | test.cpp:69:10:69:13 | copy | AST only |
|
||||
| test.cpp:68:28:68:33 | call to getenv | test.cpp:70:5:70:10 | call to strcpy | AST only |
|
||||
| test.cpp:68:28:68:33 | call to getenv | test.cpp:70:12:70:15 | copy | AST only |
|
||||
| test.cpp:68:28:68:33 | call to getenv | test.cpp:71:12:71:15 | array to pointer conversion | IR only |
|
||||
| test.cpp:75:20:75:25 | call to getenv | test.cpp:15:22:15:25 | nptr | AST only |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:8:24:8:25 | s1 | AST only |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:11:20:11:21 | s1 | AST only |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:11:36:11:37 | s2 | AST only |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:83:17:83:24 | userName | AST only |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:85:8:85:11 | copy | AST only |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:86:2:86:7 | call to strcpy | AST only |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:86:9:86:12 | copy | AST only |
|
||||
| test.cpp:100:12:100:15 | call to gets | test.cpp:98:8:98:14 | pointer | AST only |
|
||||
| test.cpp:100:12:100:15 | call to gets | test.cpp:100:2:100:8 | pointer | AST only |
|
||||
| test.cpp:100:17:100:22 | buffer | test.cpp:93:18:93:18 | s | AST only |
|
||||
| test.cpp:100:17:100:22 | buffer | test.cpp:97:7:97:12 | buffer | AST only |
|
||||
| test.cpp:100:17:100:22 | buffer | test.cpp:100:17:100:22 | array to pointer conversion | IR only |
|
||||
| test.cpp:106:28:106:33 | call to getenv | test.cpp:8:24:8:25 | s1 | AST only |
|
||||
| test.cpp:106:28:106:33 | call to getenv | test.cpp:11:20:11:21 | s1 | AST only |
|
||||
| test.cpp:106:28:106:33 | call to getenv | test.cpp:11:36:11:37 | s2 | AST only |
|
||||
| test.cpp:106:28:106:33 | call to getenv | test.cpp:106:17:106:24 | userName | AST only |
|
||||
| test.cpp:106:28:106:33 | call to getenv | test.cpp:108:8:108:11 | copy | AST only |
|
||||
| test.cpp:106:28:106:33 | call to getenv | test.cpp:109:2:109:7 | call to strcpy | AST only |
|
||||
| test.cpp:106:28:106:33 | call to getenv | test.cpp:109:9:109:12 | copy | AST only |
|
||||
@@ -1,20 +0,0 @@
|
||||
import semmle.code.cpp.security.TaintTrackingImpl as AST
|
||||
import semmle.code.cpp.ir.dataflow.DefaultTaintTracking as IR
|
||||
import cpp
|
||||
|
||||
class SourceConfiguration extends IR::TaintedWithPath::TaintTrackingConfiguration {
|
||||
override predicate isSink(Element e) { any() }
|
||||
}
|
||||
|
||||
from Expr source, Element tainted, string side
|
||||
where
|
||||
AST::taintedIncludingGlobalVars(source, tainted, _) and
|
||||
not IR::TaintedWithPath::taintedWithPath(source, tainted, _, _) and
|
||||
not tainted.getLocation().getFile().getExtension() = "h" and
|
||||
side = "AST only"
|
||||
or
|
||||
IR::TaintedWithPath::taintedWithPath(source, tainted, _, _) and
|
||||
not AST::taintedIncludingGlobalVars(source, tainted, _) and
|
||||
not tainted.getLocation().getFile().getExtension() = "h" and
|
||||
side = "IR only"
|
||||
select source, tainted, side
|
||||
@@ -1,48 +0,0 @@
|
||||
WARNING: Module TaintedWithPath has been deprecated and may be removed in future (tainted_ir.ql:3,35-50)
|
||||
WARNING: Module TaintedWithPath has been deprecated and may be removed in future (tainted_ir.ql:9,3-18)
|
||||
| test.cpp:23:23:23:28 | call to getenv | test.cpp:23:23:23:28 | call to getenv |
|
||||
| test.cpp:23:23:23:28 | call to getenv | test.cpp:23:23:23:40 | (const char *)... |
|
||||
| test.cpp:23:23:23:28 | call to getenv | test.cpp:25:6:25:29 | ! ... |
|
||||
| test.cpp:23:23:23:28 | call to getenv | test.cpp:25:7:25:12 | call to strcmp |
|
||||
| test.cpp:23:23:23:28 | call to getenv | test.cpp:25:7:25:29 | (bool)... |
|
||||
| test.cpp:23:23:23:28 | call to getenv | test.cpp:25:14:25:19 | envStr |
|
||||
| test.cpp:23:23:23:28 | call to getenv | test.cpp:29:6:29:28 | ! ... |
|
||||
| test.cpp:23:23:23:28 | call to getenv | test.cpp:29:7:29:12 | call to strcmp |
|
||||
| test.cpp:23:23:23:28 | call to getenv | test.cpp:29:7:29:28 | (bool)... |
|
||||
| test.cpp:23:23:23:28 | call to getenv | test.cpp:29:14:29:19 | envStr |
|
||||
| test.cpp:38:23:38:28 | call to getenv | test.cpp:38:23:38:28 | call to getenv |
|
||||
| test.cpp:38:23:38:28 | call to getenv | test.cpp:38:23:38:40 | (const char *)... |
|
||||
| test.cpp:38:23:38:28 | call to getenv | test.cpp:40:14:40:19 | envStr |
|
||||
| test.cpp:49:23:49:28 | call to getenv | test.cpp:49:23:49:28 | call to getenv |
|
||||
| test.cpp:49:23:49:28 | call to getenv | test.cpp:49:23:49:40 | (const char *)... |
|
||||
| test.cpp:49:23:49:28 | call to getenv | test.cpp:52:16:52:21 | envStr |
|
||||
| test.cpp:60:29:60:34 | call to getenv | test.cpp:60:29:60:34 | call to getenv |
|
||||
| test.cpp:60:29:60:34 | call to getenv | test.cpp:60:29:60:47 | (const char *)... |
|
||||
| test.cpp:60:29:60:34 | call to getenv | test.cpp:64:25:64:32 | userName |
|
||||
| test.cpp:68:28:68:33 | call to getenv | test.cpp:68:28:68:33 | call to getenv |
|
||||
| test.cpp:68:28:68:33 | call to getenv | test.cpp:68:28:68:46 | (const char *)... |
|
||||
| test.cpp:68:28:68:33 | call to getenv | test.cpp:70:18:70:25 | userName |
|
||||
| test.cpp:68:28:68:33 | call to getenv | test.cpp:71:12:71:15 | array to pointer conversion |
|
||||
| test.cpp:68:28:68:33 | call to getenv | test.cpp:71:12:71:15 | copy |
|
||||
| test.cpp:75:20:75:25 | call to getenv | test.cpp:75:15:75:18 | call to atoi |
|
||||
| test.cpp:75:20:75:25 | call to getenv | test.cpp:75:20:75:25 | call to getenv |
|
||||
| test.cpp:75:20:75:25 | call to getenv | test.cpp:75:20:75:45 | (const char *)... |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:83:28:83:33 | call to getenv |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:83:28:83:46 | (const char *)... |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:86:15:86:22 | userName |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:6:88:27 | ! ... |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:7:88:12 | call to strcmp |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:7:88:27 | (bool)... |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:14:88:17 | (const char *)... |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:14:88:17 | copy |
|
||||
| test.cpp:100:12:100:15 | call to gets | test.cpp:100:12:100:15 | call to gets |
|
||||
| test.cpp:100:17:100:22 | buffer | test.cpp:100:17:100:22 | array to pointer conversion |
|
||||
| test.cpp:100:17:100:22 | buffer | test.cpp:100:17:100:22 | buffer |
|
||||
| test.cpp:106:28:106:33 | call to getenv | test.cpp:106:28:106:33 | call to getenv |
|
||||
| test.cpp:106:28:106:33 | call to getenv | test.cpp:106:28:106:46 | (const char *)... |
|
||||
| test.cpp:106:28:106:33 | call to getenv | test.cpp:109:15:109:22 | userName |
|
||||
| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:6:111:27 | ! ... |
|
||||
| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:7:111:12 | call to strcmp |
|
||||
| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:7:111:27 | (bool)... |
|
||||
| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:14:111:17 | (const char *)... |
|
||||
| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:14:111:17 | copy |
|
||||
@@ -1,11 +0,0 @@
|
||||
import semmle.code.cpp.ir.dataflow.DefaultTaintTracking
|
||||
|
||||
class SourceConfiguration extends TaintedWithPath::TaintTrackingConfiguration {
|
||||
override predicate isSink(Element e) { any() }
|
||||
}
|
||||
|
||||
from Expr source, Element tainted
|
||||
where
|
||||
TaintedWithPath::taintedWithPath(source, tainted, _, _) and
|
||||
not tainted.getLocation().getFile().getExtension() = "h"
|
||||
select source, tainted
|
||||
@@ -1,114 +0,0 @@
|
||||
// Test for the general-purpose taint-tracking
|
||||
// mechanism that is used by several of the security queries.
|
||||
|
||||
///// Library functions //////
|
||||
|
||||
typedef unsigned long size_t;
|
||||
|
||||
int strcmp(const char *s1, const char *s2);
|
||||
char *getenv(const char *name);
|
||||
size_t strlen(const char *s);
|
||||
char *strcpy(char *s1, const char *s2);
|
||||
|
||||
void *malloc(size_t size);
|
||||
|
||||
int atoi(const char *nptr);
|
||||
|
||||
//// Test code /////
|
||||
|
||||
bool isAdmin = false;
|
||||
|
||||
void test1()
|
||||
{
|
||||
const char *envStr = getenv("USERINFO");
|
||||
|
||||
if (!strcmp(envStr, "admin")) {
|
||||
isAdmin = true;
|
||||
}
|
||||
|
||||
if (!strcmp(envStr, "none")) {
|
||||
isAdmin = false;
|
||||
}
|
||||
}
|
||||
|
||||
extern const char *specialUser;
|
||||
|
||||
void test2()
|
||||
{
|
||||
const char *envStr = getenv("USERINFO");
|
||||
|
||||
if (!strcmp(envStr, specialUser)) {
|
||||
isAdmin = true;
|
||||
}
|
||||
}
|
||||
|
||||
const char *envStrGlobal;
|
||||
|
||||
void test3()
|
||||
{
|
||||
const char *envStr = getenv("USERINFO");
|
||||
const char **envStr_ptr = &envStrGlobal;
|
||||
|
||||
*envStr_ptr = envStr;
|
||||
|
||||
if (!strcmp(envStrGlobal, "admin")) {
|
||||
isAdmin = true;
|
||||
}
|
||||
}
|
||||
|
||||
void bugWithBinop() {
|
||||
const char *userName = getenv("USER_NAME");
|
||||
|
||||
// The following is tainted, but should not cause
|
||||
// the whole program to be considered tainted.
|
||||
int bytes = strlen(userName) + 1;
|
||||
}
|
||||
|
||||
char* copying() {
|
||||
const char *userName = getenv("USER_NAME");
|
||||
char copy[1024];
|
||||
strcpy(copy, userName);
|
||||
return copy; // copy should be tainted
|
||||
}
|
||||
|
||||
void guard() {
|
||||
int len = atoi(getenv("FOOBAZ_BRANCHING"));
|
||||
if (len > 1000) return;
|
||||
char **node = (char **) malloc(len * sizeof(char *));
|
||||
}
|
||||
|
||||
const char *alias_global;
|
||||
|
||||
void mallocBuffer() {
|
||||
const char *userName = getenv("USER_NAME");
|
||||
char *alias = (char*)malloc(4096);
|
||||
char *copy = (char*)malloc(4096);
|
||||
strcpy(copy, userName);
|
||||
alias_global = alias; // to force a Chi node on all aliased memory
|
||||
if (!strcmp(copy, "admin")) { // copy should be tainted
|
||||
isAdmin = true;
|
||||
}
|
||||
}
|
||||
|
||||
char *gets(char *s);
|
||||
|
||||
void test_gets()
|
||||
{
|
||||
char buffer[1024];
|
||||
char *pointer;
|
||||
|
||||
pointer = gets(buffer);
|
||||
}
|
||||
|
||||
const char *alias_global_new;
|
||||
|
||||
void newBuffer() {
|
||||
const char *userName = getenv("USER_NAME");
|
||||
char *alias = new char[4096];
|
||||
char *copy = new char[4096];
|
||||
strcpy(copy, userName);
|
||||
alias_global_new = alias; // to force a Chi node on all aliased memory
|
||||
if (!strcmp(copy, "admin")) { // copy should be tainted
|
||||
isAdmin = true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user