// semmle-extractor-options: -std=c++17 struct Point { int x; int y; }; struct Rect { Point topLeft; Point bottomRight; }; int ChiPhiNode(Point* p, bool which1, bool which2) { if (which1) { p->x++; } else { p->y++; } if (which2) { p->x++; } else { p->y++; } return p->x + p->y; } int UnreachableViaGoto() { goto skip; return 1; skip: return 0; } int UnreachableIf(bool b) { int x = 5; int y = 10; if (b) { if (x == y) { return 1; } else { return 0; } } else { if (x < y) { return 0; } else { return 1; } } } int DoWhileFalse() { int i = 0; do { i++; } while (false); return i; } void chiNodeAtEndOfLoop(int n, char* p) { while (n-- > 0) * p++ = 0; } void Escape(void* p); void ScalarPhi(bool b) { int x = 0; int y = 1; int z = 2; if (b) { x = 3; y = 4; } else { x = 5; } int x_merge = x; int y_merge = y; int z_merge = z; } void MustExactlyOverlap(Point a) { Point b = a; } void MustExactlyOverlapEscaped(Point a) { Point b = a; Escape(&a); } void MustTotallyOverlap(Point a) { int x = a.x; int y = a.y; } void MustTotallyOverlapEscaped(Point a) { int x = a.x; int y = a.y; Escape(&a); } void MayPartiallyOverlap(int x, int y) { Point a = { x, y }; Point b = a; } void MayPartiallyOverlapEscaped(int x, int y) { Point a = { x, y }; Point b = a; Escape(&a); } void MergeMustExactlyOverlap(bool c, int x1, int x2) { Point a = {}; if (c) { a.x = x1; } else { a.x = x2; } int x = a.x; // Both reaching defs must exactly overlap. Point b = a; } void MergeMustExactlyWithMustTotallyOverlap(bool c, Point p, int x1) { Point a = {}; if (c) { a.x = x1; } else { a = p; } int x = a.x; // Only one (non-Chi) reaching def must exactly overlap, but we should still get a Phi for it. } void MergeMustExactlyWithMayPartiallyOverlap(bool c, Point p, int x1) { Point a = {}; if (c) { a.x = x1; } else { a = p; } Point b = a; // Only one reaching def must exactly overlap, but we should still get a Phi for it. } void MergeMustTotallyOverlapWithMayPartiallyOverlap(bool c, Rect r, int x1) { Rect a = {}; if (c) { a.topLeft.x = x1; } else { a = r; } Point b = a.topLeft; // Neither reaching def must exactly overlap, so we'll just get a Phi of the virtual variable. } struct Wrapper { int f; }; void WrapperStruct(Wrapper w) { Wrapper x = w; // MustExactlyOverlap int a = w.f; // MustTotallyOverlap, because the types don't match w.f = 5; a = w.f; // MustExactlyOverlap x = w; // MustTotallyOverlap } int AsmStmt(int *p) { __asm__(""); return *p; } static void AsmStmtWithOutputs(unsigned int& a, unsigned int& b, unsigned int& c, unsigned int& d) { __asm__ __volatile__ ( "cpuid\n\t" : "+a" (a), "+b" (b) : "c" (c), "d" (d) ); } int strcmp(const char *, const char *); int strlen(const char *); int abs(int); int PureFunctions(char *str1, char *str2, int x) { int ret = strcmp(str1, str2); ret += strlen(str1); ret += abs(x); return ret; } void *memcpy(void *dst, void *src, int size); int ModeledCallTarget(int x) { int y; memcpy(&y, &x, sizeof(int)); return y; } void InitArray() { char a_pad[32] = ""; char a_nopad[4] = "foo"; char a_infer[] = "blah"; char b[2]; char c[2] = {}; char d[2] = { 0 }; char e[2] = { 0, 1 }; char f[3] = { 0 }; } extern void ExternalFunc(); char StringLiteralAliasing() { ExternalFunc(); const char* s = "Literal"; return s[2]; // Should be defined by `AliasedDefinition`, not `Chi` or `CallSideEffect`. } class Constructible { public: Constructible(int x) {}; void g() {} }; void ExplicitConstructorCalls() { Constructible c(1); c.g(); c.g(); Constructible c2 = Constructible(2); c2.g(); } char *VoidStarIndirectParameters(char *src, int size) { char *dst = new char[size]; *src = 'a'; memcpy(dst, src, size); return dst; } char StringLiteralAliasing2(bool b) { if (b) { ExternalFunc(); } else { ExternalFunc(); } const char* s = "Literal"; return s[2]; } void *malloc(int size); void *MallocAliasing(void *s, int size) { void *buf = malloc(size); memcpy(buf, s, size); return buf; } Point *pp; void EscapedButNotConflated(bool c, Point p, int x1) { Point a = {}; pp = &a; // `a` escapes here and therefore belongs to the aliased vvar if (c) { a.x = x1; } int x = a.x; // The phi node here is not conflated } struct A { int i; A(int x) {} A(A*) {} A() {} }; Point *NewAliasing(int x) { Point* p = new Point; Point* q = new Point; int j = (new A(new A(x)))->i; A* a = new A; return p; } void unknownFunction(int argc, char **argv); int main(int argc, char **argv) { unknownFunction(argc, argv); unknownFunction(argc, argv); return **argv; // Chi chain goes through side effects from unknownFunction } class ThisAliasTest { int x, y; void setX(int arg) { this->x = arg; } }; void sink(char **); void sink(char *); // This test case comes from DefaultTaintTracking. void DoubleIndirectionEscapes(char *s) { char buffer[1024]; char *ptr1, **ptr2; char *ptr3, **ptr4; ptr1 = buffer; ptr2 = &ptr1; memcpy(*ptr2, s, 1024); sink(buffer); // $ MISSING: ast,ir sink(ptr1); // $ ast MISSING: ir sink(ptr2); // $ SPURIOUS: ast sink(*ptr2); // $ ast MISSING: ir } int UnreachablePhiOperand(int x, int y) { bool b = true; int ret; if(b) { ret = x; } else { ret = y; } return ret; } int UnreachablePhiOperand2(int x, int y, int z, bool b1) { bool b2 = true; int ret; if(b1) { ret = x; } else { if(b2) { ret = y; } else { ret = z; } } return ret; } int DegeneratePhi(int x, int y, bool b1) { bool b2 = true; int ret1; int ret2 = x; if(b1) { ret1 = x; } else { if(b2) { ret1 = x; } else { ret2 = y; } } return ret1 + ret2; } int FusedBlockPhiOperand(int x, int y, int z, bool b1) { bool b2 = true; int ret; if(b1) { ret = x; } else { if(b2) { ret = y; } else { ret = z; } ; // creates a NoOp instruction with its own basic block } return ret; } void vla(int n1, int n2, int n3, bool b1) { int b[n1]; int c[n1][n2]; *b = 0; b[0] = 1; **(c + 1) = 0; if(b1) { int b[n1]; } else { int b[n2]; } } void nested_array_designators() { int x[1][2] = {[0][0] = 1234, [0][1] = 5678}; } [[noreturn]] void noreturnFunc(); int noreturnTest(int x) { if (x < 10) { return x; } else { noreturnFunc(); } } int noreturnTest2(int x) { if (x < 10) { noreturnFunc(); } return x; } void Conditional(bool a, int x, int y) { int z = a ? x : y; } static void NonEscapingParams(void *a, void *b) { } static void EscapingParams(void *a, void *b) { Escape(a); Escape(b); }