[PATCH] D44143: Create properly seeded random generator check

2018-03-06 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 created this revision.
boga95 added a reviewer: clang-tools-extra.
boga95 added a project: clang-tools-extra.
Herald added subscribers: cfe-commits, mgorny.

This check flags all pseudo-random number engines and engine adaptors 
instantiations when it initialized or seeded with default argument or a 
constant expression. Pseudo-random number engines seeded with a predictable 
value may cause vulnerabilities e.g. in security protocols.
This is a CERT security rule, see MSC51-CPP 
.

Example:

  void foo() {
  std::mt19937 engine1; // Bad, always generate the same sequence
  std::mt19937 engine2(1); // Bad
  engine1.seed(); // Bad
  engine2.seed(1); // Bad
  
  std::time_t t;
  engine1.seed(std::time(&t)); // Bad, system time might be controlled by 
user
  
  std::random_device dev;
  std::mt19937 engine3(dev()); // Good
  }


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D44143

Files:
  clang-tidy/cert/CERTTidyModule.cpp
  clang-tidy/cert/CMakeLists.txt
  clang-tidy/cert/ProperlySeededRandomGeneratorCheck.cpp
  clang-tidy/cert/ProperlySeededRandomGeneratorCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/cert-properly-seeded-random-generator.rst
  test/clang-tidy/cert-properly-seeded-random-generator.cpp

Index: test/clang-tidy/cert-properly-seeded-random-generator.cpp
===
--- /dev/null
+++ test/clang-tidy/cert-properly-seeded-random-generator.cpp
@@ -0,0 +1,172 @@
+// RUN: %check_clang_tidy %s cert-properly-seeded-random-generator %t -- -- -std=c++11
+
+namespace std {
+
+template 
+struct linear_congruential_engine {
+  linear_congruential_engine(int _ = 0);
+  void seed(int _ = 0);
+};
+using default_random_engine = linear_congruential_engine;
+
+using size_t = int;
+template 
+struct mersenne_twister_engine {
+  mersenne_twister_engine(int _ = 0);
+  void seed(int _ = 0);
+};
+using mt19937 = mersenne_twister_engine;
+
+template 
+struct subtract_with_carry_engine {
+  subtract_with_carry_engine(int _ = 0);
+  void seed(int _ = 0);
+};
+using ranlux24_base = subtract_with_carry_engine;
+
+template 
+struct discard_block_engine {
+  discard_block_engine();
+  discard_block_engine(int _);
+  void seed();
+  void seed(int _);
+};
+using ranlux24 = discard_block_engine;
+
+template 
+struct independent_bits_engine {
+  independent_bits_engine();
+  independent_bits_engine(int _);
+  void seed();
+  void seed(int _);
+};
+using independent_bits = independent_bits_engine;
+
+template 
+struct shuffle_order_engine {
+  shuffle_order_engine();
+  shuffle_order_engine(int _);
+  void seed();
+  void seed(int _);
+};
+using shuffle_order = shuffle_order_engine;
+
+struct random_device {
+  random_device();
+  int operator()();
+};
+} // namespace std
+
+void f() {
+  const int seed = 2;
+  // One instantiation for every engine
+  std::default_random_engine engine1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator must be seeded with a random_device instead of default argument
+  std::default_random_engine engine2(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator must be seeded with a random_device instead of a constant [cert-properly-seeded-random-generator]
+  std::default_random_engine engine3(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator must be seeded with a random_device instead of a constant [cert-properly-seeded-random-generator]
+  engine1.seed();
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator must be seeded with a random_device instead of default argument [cert-properly-seeded-random-generator]
+  engine1.seed(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator must be seeded with a random_device instead of a constant [cert-properly-seeded-random-generator]
+  engine1.seed(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator must be seeded with a random_device instead of a constant [cert-properly-seeded-random-generator]
+
+  std::mt19937 engine4;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator must be seeded with a random_device instead of default argument
+  std::mt19937 engine5(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator must be seeded with a random_device instead of a constant [cert-properly-seeded-random-generator]
+  std::mt19937 engine6(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator must be seeded with a random_device instead of a constant [cert-properly-seeded-random-generator]
+  engine4.seed();
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator must be seeded with a random_device instead of default argument [cert-properly-seeded-random-generator]
+  engine4.seed(1);
+  // CHECK-MESSAGE

[PATCH] D44143: Create properly seeded random generator check

2018-03-10 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 updated this revision to Diff 137915.
boga95 marked an inline comment as done.
boga95 added a comment.

Add capability to provide a user-configurable list of disallowed types which 
will trigger warning. Now it also detects C srand function. Rename check to 
cert-msc51-cpp. Add cert-msc32-c check. Change warning messages. Other minor 
fixes.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D44143

Files:
  clang-tidy/cert/CERTTidyModule.cpp
  clang-tidy/cert/CMakeLists.txt
  clang-tidy/cert/ProperlySeededRandomGeneratorCheck.cpp
  clang-tidy/cert/ProperlySeededRandomGeneratorCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/cert-msc32-c.rst
  docs/clang-tidy/checks/cert-msc51-cpp.rst
  test/clang-tidy/cert-msc32-c.c
  test/clang-tidy/cert-msc51-cpp.cpp

Index: test/clang-tidy/cert-msc51-cpp.cpp
===
--- /dev/null
+++ test/clang-tidy/cert-msc51-cpp.cpp
@@ -0,0 +1,201 @@
+// RUN: %check_clang_tidy %s cert-msc51-cpp %t -- -config="{CheckOptions: [{key: cert-msc51-cpp.DisallowedSeedTypes, value: 'some_type,time_t'}]}" -- -std=c++11
+
+namespace std {
+
+template 
+struct linear_congruential_engine {
+  linear_congruential_engine(int _ = 0);
+  void seed(int _ = 0);
+};
+using default_random_engine = linear_congruential_engine;
+
+using size_t = int;
+template 
+struct mersenne_twister_engine {
+  mersenne_twister_engine(int _ = 0);
+  void seed(int _ = 0);
+};
+using mt19937 = mersenne_twister_engine;
+
+template 
+struct subtract_with_carry_engine {
+  subtract_with_carry_engine(int _ = 0);
+  void seed(int _ = 0);
+};
+using ranlux24_base = subtract_with_carry_engine;
+
+template 
+struct discard_block_engine {
+  discard_block_engine();
+  discard_block_engine(int _);
+  void seed();
+  void seed(int _);
+};
+using ranlux24 = discard_block_engine;
+
+template 
+struct independent_bits_engine {
+  independent_bits_engine();
+  independent_bits_engine(int _);
+  void seed();
+  void seed(int _);
+};
+using independent_bits = independent_bits_engine;
+
+template 
+struct shuffle_order_engine {
+  shuffle_order_engine();
+  shuffle_order_engine(int _);
+  void seed();
+  void seed(int _);
+};
+using shuffle_order = shuffle_order_engine;
+
+struct random_device {
+  random_device();
+  int operator()();
+};
+} // namespace std
+
+using time_t = unsigned int;
+time_t time(time_t *t);
+
+void f() {
+  const int seed = 2;
+  time_t t;
+
+  // One instantiation for every engine
+  std::default_random_engine engine1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+  std::default_random_engine engine2(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::default_random_engine engine3(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::default_random_engine engine4(time(&t));
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine1.seed();
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+  engine1.seed(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine1.seed(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine1.seed(time(&t));
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+
+  std::mt19937 engine5;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+  std::mt19937 engine6(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::mt19937 engine7(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::mt19937 engine8(time(&t));
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine5.seed();
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random

[PATCH] D44143: [clang-tidy] Create properly seeded random generator check

2018-03-12 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 added a subscriber: szepet.
boga95 marked 4 inline comments as done.
boga95 added inline comments.



Comment at: test/clang-tidy/cert-properly-seeded-random-generator.cpp:76
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator must be 
seeded with a random_device instead of a constant 
[cert-properly-seeded-random-generator]
+  engine1.seed(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator must be 
seeded with a random_device instead of a constant 
[cert-properly-seeded-random-generator]

Quuxplusone wrote:
> Is the diagnostic suppressed if `seed` is a template parameter? (Not that I'd 
> do this. It's just a corner case I thought of.)
Hopefully, it is not suppressed.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D44143



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D44143: [clang-tidy] Create properly seeded random generator check

2018-06-24 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 marked 12 inline comments as done.
boga95 added a comment.

I think I resolved all of the comments. Do I forget anything?




Comment at: clang-tidy/cert/CERTTidyModule.cpp:44
 "cert-dcl54-cpp");
-CheckFactories.registerCheck(
-"cert-dcl58-cpp");
+
CheckFactories.registerCheck("cert-dcl58-cpp");
 CheckFactories.registerCheck(

aaron.ballman wrote:
> This change looks unrelated to the patch.
Clang format did it when I apply it to the whole file. 



Comment at: clang-tidy/cert/ProperlySeededRandomGeneratorCheck.cpp:74
+  callExpr(has(implicitCastExpr(has(
+   declRefExpr(hasDeclaration(namedDecl(hasName("srand"
+  .bind("srand"),

aaron.ballman wrote:
> I think that in C mode, this is fine, but in C++ mode it should register 
> `::std::srand`.
It is not match for ##::std::srand##, just for ##::srand##. I found some 
examples, but I think they don't work neither.






Comment at: docs/clang-tidy/checks/cert-msc51-cpp.rst:29
+  }
+
+Options

Eugene.Zelenko wrote:
> Is there guideline documentation available online? If so, please add link. 
> See other checks documentation as example.
There is a guideline [[ 
http://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html | here 
]].


https://reviews.llvm.org/D44143



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D55734: [analyzer] Revise GenericTaintChecker's internal representation

2019-01-27 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 marked 4 inline comments as done.
boga95 added a comment.

Is it ready to land?




Comment at: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp:212
+  llvm::StringSwitch(Name)
+  .Case("atoi", TaintPropagationRule({0}, {ReturnValueIndex}))
+  .Case("atol", TaintPropagationRule({0}, {ReturnValueIndex}))

NoQ wrote:
> `llvm::ArrayRef` has a fancy feature: it can be constructed not only from an 
> initializer list, but also from a single element. This could have allowed 
> skipping `{}` in these constructors when there is just one value in the list. 
> That's what i would have done, but i guess it's up to you to decide which 
> approach is prettier.
Those who don't know that feature will be confused. I should make changes in 
the constructor to support it. I'm going to leave it.



Comment at: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp:224
+  .Case("read", TaintPropagationRule({0, 2}, {1, ReturnValueIndex}))
+  .Case("pread", TaintPropagationRule({0, 2, 3}, {1, 
ReturnValueIndex}))
+  .Case("gets", TaintPropagationRule({}, {0, ReturnValueIndex}))

NoQ wrote:
> Now `pread` doesn't produce a tainted result when only the buffer is tainted 
> but other arguments are not. Is it a functional change? I guess we should be 
> able to add tests for it. You can also commit this patch with `{0, 1, 2, 3}` 
> and remove `1` in the next patch that also adds a test.
I changed it to `{0, 1, 2, 3}`. I don't want to make any change in the behavior 
in this patch. I think who made it use InvalidArgIndex because the previous 
implementation wasn't expressive enough.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55734/new/

https://reviews.llvm.org/D55734



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D55734: [analyzer] Revise GenericTaintChecker's internal representation

2019-01-28 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 added a comment.

Yes, thank you.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55734/new/

https://reviews.llvm.org/D55734



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D54918: Apply clang-format to GenericTaintChecker.cpp

2018-11-26 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 created this revision.
boga95 added a reviewer: gerazo.
boga95 added a project: clang.
Herald added a subscriber: cfe-commits.

I would like to add some patch for this checker later and I found that it isn't 
well formatted.


Repository:
  rC Clang

https://reviews.llvm.org/D54918

Files:
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp

Index: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -28,10 +28,13 @@
 using namespace ento;
 
 namespace {
-class GenericTaintChecker : public Checker< check::PostStmt,
-check::PreStmt > {
+class GenericTaintChecker
+: public Checker, check::PreStmt> {
 public:
-  static void *getTag() { static int Tag; return &Tag; }
+  static void *getTag() {
+static int Tag;
+return &Tag;
+  }
 
   void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
 
@@ -69,8 +72,8 @@
   static Optional getPointedToSVal(CheckerContext &C, const Expr *Arg);
 
   /// Functions defining the attack surface.
-  typedef ProgramStateRef (GenericTaintChecker::*FnCheck)(const CallExpr *,
-   CheckerContext &C) const;
+  typedef ProgramStateRef (GenericTaintChecker::*FnCheck)(
+  const CallExpr *, CheckerContext &C) const;
   ProgramStateRef postScanf(const CallExpr *CE, CheckerContext &C) const;
   ProgramStateRef postSocket(const CallExpr *CE, CheckerContext &C) const;
   ProgramStateRef postRetTaint(const CallExpr *CE, CheckerContext &C) const;
@@ -120,16 +123,15 @@
 
 TaintPropagationRule() {}
 
-TaintPropagationRule(unsigned SArg,
- unsigned DArg, bool TaintRet = false) {
+TaintPropagationRule(unsigned SArg, unsigned DArg, bool TaintRet = false) {
   SrcArgs.push_back(SArg);
   DstArgs.push_back(DArg);
   if (TaintRet)
 DstArgs.push_back(ReturnValueIndex);
 }
 
-TaintPropagationRule(unsigned SArg1, unsigned SArg2,
- unsigned DArg, bool TaintRet = false) {
+TaintPropagationRule(unsigned SArg1, unsigned SArg2, unsigned DArg,
+ bool TaintRet = false) {
   SrcArgs.push_back(SArg1);
   SrcArgs.push_back(SArg2);
   DstArgs.push_back(DArg);
@@ -139,18 +141,17 @@
 
 /// Get the propagation rule for a given function.
 static TaintPropagationRule
-  getTaintPropagationRule(const FunctionDecl *FDecl,
-  StringRef Name,
-  CheckerContext &C);
+getTaintPropagationRule(const FunctionDecl *FDecl, StringRef Name,
+CheckerContext &C);
 
 inline void addSrcArg(unsigned A) { SrcArgs.push_back(A); }
-inline void addDstArg(unsigned A)  { DstArgs.push_back(A); }
+inline void addDstArg(unsigned A) { DstArgs.push_back(A); }
 
 inline bool isNull() const { return SrcArgs.empty(); }
 
 inline bool isDestinationArgument(unsigned ArgNum) const {
-  return (std::find(DstArgs.begin(),
-DstArgs.end(), ArgNum) != DstArgs.end());
+  return (std::find(DstArgs.begin(), DstArgs.end(), ArgNum) !=
+  DstArgs.end());
 }
 
 static inline bool isTaintedOrPointsToTainted(const Expr *E,
@@ -169,7 +170,6 @@
 /// Pre-process a function which propagates taint according to the
 /// taint rule.
 ProgramStateRef process(const CallExpr *CE, CheckerContext &C) const;
-
   };
 };
 
@@ -177,17 +177,18 @@
 const unsigned GenericTaintChecker::InvalidArgIndex;
 
 const char GenericTaintChecker::MsgUncontrolledFormatString[] =
-  "Untrusted data is used as a format string "
-  "(CWE-134: Uncontrolled Format String)";
+"Untrusted data is used as a format string "
+"(CWE-134: Uncontrolled Format String)";
 
 const char GenericTaintChecker::MsgSanitizeSystemArgs[] =
-  "Untrusted data is passed to a system call "
-  "(CERT/STR02-C. Sanitize data passed to complex subsystems)";
+"Untrusted data is passed to a system call "
+"(CERT/STR02-C. Sanitize data passed to complex subsystems)";
 
 const char GenericTaintChecker::MsgTaintedBufferSize[] =
-  "Untrusted data is used to specify the buffer size "
-  "(CERT/STR31-C. Guarantee that storage for strings has sufficient space for "
-  "character data and the null terminator)";
+"Untrusted data is used to specify the buffer size "
+"(CERT/STR31-C. Guarantee that storage for strings has sufficient space "
+"for "
+"character data and the null terminator)";
 
 } // end of anonymous namespace
 
@@ -199,33 +200,32 @@
 
 GenericTaintChecker::TaintPropagationRule
 GenericTaintChecker::TaintPropagationRule::getTaintPropagationRule(
- const FunctionDecl *FDecl,
- Strin

[PATCH] D54918: Apply clang-format to GenericTaintChecker.cpp

2018-11-29 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 added a comment.

If you find it ok, can you please commit it? @xazax.hun


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D54918/new/

https://reviews.llvm.org/D54918



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D58828: [analyzer] Fix taint propagation in GenericTaintChecker

2019-03-01 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 created this revision.
boga95 added reviewers: gerazo, xazax.hun, Szelethus, a_sidorin, dcoughlin, 
george.karpenkov, NoQ.
boga95 added a project: clang.
Herald added subscribers: cfe-commits, Charusso, dkrupp, donat.nagy, 
mikhail.ramalho, a.sidorin, rnkovacs, szepet, baloghadamsoftware, whisperity.

The `gets` function has no SrcArgs. Because the default value for isTainted was 
false, it didn't mark its DstArgs as tainted.


Repository:
  rC Clang

https://reviews.llvm.org/D58828

Files:
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  test/Analysis/taint-generic.c


Index: test/Analysis/taint-generic.c
===
--- test/Analysis/taint-generic.c
+++ test/Analysis/taint-generic.c
@@ -2,6 +2,7 @@
 // RUN: %clang_analyze_cc1  -DFILE_IS_STRUCT 
-analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 
-Wno-format-security -verify %s
 
 int scanf(const char *restrict format, ...);
+char *gets(char *str);
 int getchar(void);
 
 typedef struct _FILE FILE;
@@ -142,6 +143,12 @@
   system(buffern2); // expected-warning {{Untrusted data is passed to a system 
call}}
 }
 
+void testGets() {
+  char str[50];
+  gets(str);
+  system(str); // expected-warning {{Untrusted data is passed to a system 
call}}
+}
+
 void testTaintedBufferSize() {
   size_t ts;
   scanf("%zd", &ts);
Index: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -458,7 +458,7 @@
   ProgramStateRef State = C.getState();
 
   // Check for taint in arguments.
-  bool IsTainted = false;
+  bool IsTainted = true;
   for (unsigned ArgNum : SrcArgs) {
 if (ArgNum >= CE->getNumArgs())
   return State;


Index: test/Analysis/taint-generic.c
===
--- test/Analysis/taint-generic.c
+++ test/Analysis/taint-generic.c
@@ -2,6 +2,7 @@
 // RUN: %clang_analyze_cc1  -DFILE_IS_STRUCT -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -Wno-format-security -verify %s
 
 int scanf(const char *restrict format, ...);
+char *gets(char *str);
 int getchar(void);
 
 typedef struct _FILE FILE;
@@ -142,6 +143,12 @@
   system(buffern2); // expected-warning {{Untrusted data is passed to a system call}}
 }
 
+void testGets() {
+  char str[50];
+  gets(str);
+  system(str); // expected-warning {{Untrusted data is passed to a system call}}
+}
+
 void testTaintedBufferSize() {
   size_t ts;
   scanf("%zd", &ts);
Index: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -458,7 +458,7 @@
   ProgramStateRef State = C.getState();
 
   // Check for taint in arguments.
-  bool IsTainted = false;
+  bool IsTainted = true;
   for (unsigned ArgNum : SrcArgs) {
 if (ArgNum >= CE->getNumArgs())
   return State;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D59055: [analyzer] Prepare generic taint checker for new sources

2019-03-06 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 created this revision.
boga95 added reviewers: gerazo, xazax.hun, Szelethus, a_sidorin, dcoughlin, 
george.karpenkov, NoQ.
boga95 added a project: clang.
Herald added subscribers: cfe-commits, Charusso, dkrupp, donat.nagy, 
mikhail.ramalho, a.sidorin, rnkovacs, szepet, baloghadamsoftware, whisperity.

Previously the taint propagation rules and the taint sources were checked in 
different steps.
Taint propagation goes in two steps: addSourcesPre marked the tainted arguments 
and the return value, then the propagateFromPre set the tainted flag. After 
that addSourcesPost set the tainted flag for the source function's(scanf, 
socket, e.g) arguments or return value.
There is no reason why it should be that way. A source function can be 
interpreted as a propagation rule when no srcArg is defined.
I modified the TaintPropagationRule to support source functions and merged them 
with the propagation rules.


Repository:
  rC Clang

https://reviews.llvm.org/D59055

Files:
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp

Index: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -62,9 +62,6 @@
   /// Propagate taint generated at pre-visit.
   bool propagateFromPre(const CallExpr *CE, CheckerContext &C) const;
 
-  /// Add taint sources on a post visit.
-  void addSourcesPost(const CallExpr *CE, CheckerContext &C) const;
-
   /// Check if the region the expression evaluates to is the standard input,
   /// and thus, is tainted.
   static bool isStdin(const Expr *E, CheckerContext &C);
@@ -72,16 +69,6 @@
   /// Given a pointer argument, return the value it points to.
   static Optional getPointedToSVal(CheckerContext &C, const Expr *Arg);
 
-  /// Functions defining the attack surface.
-  using FnCheck = ProgramStateRef (GenericTaintChecker::*)(
-  const CallExpr *, CheckerContext &C) const;
-  ProgramStateRef postScanf(const CallExpr *CE, CheckerContext &C) const;
-  ProgramStateRef postSocket(const CallExpr *CE, CheckerContext &C) const;
-  ProgramStateRef postRetTaint(const CallExpr *CE, CheckerContext &C) const;
-
-  /// Taint the scanned input if the file is tainted.
-  ProgramStateRef preFscanf(const CallExpr *CE, CheckerContext &C) const;
-
   /// Check for CWE-134: Uncontrolled Format String.
   static const char MsgUncontrolledFormatString[];
   bool checkUncontrolledFormatString(const CallExpr *CE,
@@ -118,6 +105,9 @@
   struct TaintPropagationRule {
 enum class VariadicType { None, Src, Dst };
 
+using PropagationFuncType = bool (*)(bool IsTainted, const CallExpr *,
+ CheckerContext &C);
+
 /// List of arguments which can be taint sources and should be checked.
 ArgVector SrcArgs;
 /// List of arguments which should be tainted on function return.
@@ -127,16 +117,21 @@
 /// Show when a function has variadic parameters. If it has, it marks all
 /// of them as source or destination.
 VariadicType VarType;
+/// Special function for tainted source determination. If defined, it can
+/// override the default behavior.
+PropagationFuncType PropagationFunc;
 
 TaintPropagationRule()
-: VariadicIndex(InvalidArgIndex), VarType(VariadicType::None) {}
+: VariadicIndex(InvalidArgIndex), VarType(VariadicType::None),
+  PropagationFunc(nullptr) {}
 
 TaintPropagationRule(std::initializer_list &&Src,
  std::initializer_list &&Dst,
  VariadicType Var = VariadicType::None,
- unsigned VarIndex = InvalidArgIndex)
+ unsigned VarIndex = InvalidArgIndex,
+ PropagationFuncType Func = nullptr)
 : SrcArgs(std::move(Src)), DstArgs(std::move(Dst)),
-  VariadicIndex(VarIndex), VarType(Var) {}
+  VariadicIndex(VarIndex), VarType(Var), PropagationFunc(Func) {}
 
 /// Get the propagation rule for a given function.
 static TaintPropagationRule
@@ -170,6 +165,10 @@
 /// Pre-process a function which propagates taint according to the
 /// taint rule.
 ProgramStateRef process(const CallExpr *CE, CheckerContext &C) const;
+
+// Functions for custom taintedness propagation.
+static bool postSocket(bool IsTainted, const CallExpr *CE,
+   CheckerContext &C);
   };
 };
 
@@ -206,25 +205,42 @@
   // Check for exact name match for functions without builtin substitutes.
   TaintPropagationRule Rule =
   llvm::StringSwitch(Name)
+  // Source functions
+  // TODO: Add support for vfscanf & family.
+  .Case("fdopen", TaintPropagationRule({}, {ReturnValueIndex}))
+  .Case("fopen", TaintPropagationRule({}, {ReturnValueIndex}))
+  .Case("freopen", TaintPropagationRule({}, {ReturnValueIndex}))
+  .Case("g

[PATCH] D59055: [analyzer] Prepare generic taint checker for new sources

2019-03-08 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 added a comment.

Yes, they do. Thanks for the review.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59055/new/

https://reviews.llvm.org/D59055



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D59516: [analyzer] Make GenericTaintChecker configurable

2019-03-18 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 created this revision.
boga95 added reviewers: NoQ, Szelethus, xazax.hun, dkrupp.
boga95 added a project: clang.
Herald added subscribers: cfe-commits, Charusso, donat.nagy, mikhail.ramalho, 
a.sidorin, rnkovacs, szepet, baloghadamsoftware, whisperity.

One can pass a configuration file to the checker with the following argument: 
`-analyzer-config 
alpha.security.taint.TaintPropagation:Config=/path/to/the/file/taint-generic-config.yaml`.
 The config file can contain:

- Propagations: One can define functions which propagate or create the 
taintedness. It has five fields:
  - Name: The name of the function. Mandatory field.
  - SrcArgs: A list of arguments. If any of them tainted, the destination 
arguments will be marked tainted. It's not defined, the destination arguments 
always will be marked as tainted.
  - DstArgs: A list of arguments. Set the tainted flag for the arguments, if 
they are marked. The return value's index is 4294967294(it is temporary).
  - VarType: It's an enum with three possible values: `None`, `Src`, `Dst`. The 
default value is `None` and do nothing.
  - VarIndex: It's the first variadic argument for the function. If `VarType == 
Src` and any of them is tainted, the destination arguments will be marked ad 
tainted. If `VarType == Dst` and they are marked, all argument from the 
VarIndex will be marked as tainted.
- Filters: One can define function remove the tainted flag if it is passed to 
the proper argument.
  - Name: The name of the function. Mandatory field.
  - Args: A list of arguments. If a tainted value is passed to it, the tainted 
flag will be removed. Mandatory field.
- Sinks: A list of function which will give a warning if it gets a tainted 
value.
  - Name: The name of the function. Mandatory field.
  - Args: A list of arguments. If any of those arguments get a tainted value, 
it will give a warning. Mandatory field.

For the propagations, it uses the config to deduce the `TaintPropagationRules` 
from the function's name.
The filter functions are understandable as functions which mark their arguments 
not tainted. I improved the information flow from pre-visit to post-visit, 
therefore, the `TaintTagType` could be passed to the `setTaint` function. 
Currently, it only works if the argument is a pointer.


Repository:
  rC Clang

https://reviews.llvm.org/D59516

Files:
  include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
  include/clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  lib/StaticAnalyzer/Core/ProgramState.cpp
  test/Analysis/Inputs/taint-generic-config.yaml
  test/Analysis/taint-generic.c

Index: test/Analysis/taint-generic.c
===
--- test/Analysis/taint-generic.c
+++ test/Analysis/taint-generic.c
@@ -1,5 +1,5 @@
-// RUN: %clang_analyze_cc1  -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -Wno-format-security -verify %s
-// RUN: %clang_analyze_cc1  -DFILE_IS_STRUCT -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -Wno-format-security -verify %s
+// RUN: %clang_analyze_cc1  -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -analyzer-config alpha.security.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config.yaml -Wno-format-security -verify %s
+// RUN: %clang_analyze_cc1  -DFILE_IS_STRUCT -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -analyzer-config alpha.security.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config.yaml -Wno-format-security -verify %s
 
 int scanf(const char *restrict format, ...);
 char *gets(char *str);
@@ -295,3 +295,49 @@
   if (i < rhs)
 *(volatile int *) 0; // no-warning
 }
+
+// Test configuration
+int mySource1();
+void mySource2(int*);
+void myScanf(const char*, ...);
+int myPropagator(int, int*);
+int mySnprintf(char*, size_t, const char*, ...);
+void myFilter(int*);
+void mySink(int, int, int);
+
+void testConfigurationSources1() {
+  int x = mySource1();
+  Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationSources2() {
+  int x;
+  mySource2(&x);
+  Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationSources3() {
+  int x, y;
+  myScanf("%d %d", &x, &y);
+  Buffer[y] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationPropagation() {
+  int x = mySource1();
+  int y;
+  myPropagator(x, &y);
+  Buffer[y] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationFilter() {
+  int x = mySource1();
+  myFilter(&x);
+  Buffer[x] = 1; // no-warning
+}
+
+void testConfigurationSinks() {
+  int x = mySource1();
+  mySink(x, 1, 2); // expected-warning {{Untrusted data is passed to a user defined sink}}
+  mySink(1, x, 2); // no-warning
+  mySink(1, 2, x); // expected-warning {{Untrusted data is passed to a user defined sink}}
+}
Index: test/An

[PATCH] D59555: [analyzer] Add yaml parser to GenericTaintChecker

2019-03-19 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 created this revision.
boga95 added reviewers: Szelethus, xazax.hun, dkrupp, NoQ.
Herald added subscribers: cfe-commits, Charusso, donat.nagy, mikhail.ramalho, 
a.sidorin, rnkovacs, szepet, baloghadamsoftware, whisperity.
Herald added a project: clang.

Parse the yaml configuration file and store it in static variables. The user 
can define taint propagation rules, custom sink, and filter functions. E.g:

  # A list of source/propagation function
  Propagations:
# int x = mySource1(); // x is tainted
- Name: mySource1
  DstArgs:  [4294967294] # Index for return value
  
# int x;
# mySource2(&x); // x is tainted
- Name: mySource2
  DstArgs:  [0]
  
# int x, y;
# myScanf("%d %d", &x, &y); // x and y are tainted
- Name: myScanf
  VarType:  Dst
  VarIndex: 1
  
# int x; // x is tainted
# int y;
# myPropagator(x, &y); // y is tainted
- Name: myPropagator
  SrcArgs:  [0]
  DstArgs:  [1]
  
# const unsigned size = 100;
# char buf[size];
# int x, y;
# int n = mySprintf(buf, size, "%d %d", x, y); // If size, x or y is tainted
# // the return value and the buf will be tainted
- Name: mySnprintf
  SrcArgs:  [1]
  DstArgs:  [0, 4294967294]
  VarType:  Src
  VarIndex: 3
  
  # A list of filter functions
  Filters:
# int x; // x is tainted
# myFilter(&x); // x is not tainted anymore
- Name: myFilter
  Args: [0]
  
  # A list of sink functions
  Sinks:
# int x, y; // x and y are tainted
# mySink(x, 0, 1); // It will warn
# mySink(0, 1, y); // It will warn
# mySink(0, x, 1); // It won't warn
- Name: mySink
  Args: [0, 2]


Repository:
  rC Clang

https://reviews.llvm.org/D59555

Files:
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp

Index: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -13,14 +13,16 @@
 // aggressively, even if the involved symbols are under constrained.
 //
 //===--===//
-#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
 #include "clang/AST/Attr.h"
 #include "clang/Basic/Builtins.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
 #include "clang/StaticAnalyzer/Core/Checker.h"
 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/YAMLTraits.h"
 #include 
 #include 
 #include 
@@ -41,11 +43,38 @@
 
   void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
 
-private:
+  using ArgVector = SmallVector;
+
+  enum class VariadicType { None, Src, Dst };
+
+  /// The ``TaintConfiguration`` is used to parse configuration file.
+  struct TaintConfiguration {
+using NameArgsPair = std::pair;
+
+struct Propagation {
+  std::string Name;
+  ArgVector SrcArgs;
+  ArgVector DstArgs;
+  VariadicType VarType;
+  unsigned VarIndex;
+};
+
+std::vector Propagations;
+std::vector Filters;
+std::vector Sinks;
+  };
+
+  /// Get and read the config file.
+  static void getConfiguration(StringRef ConfigFile);
+
+  /// Parse the config.
+  static void parseConfiguration(TaintConfiguration &&Config);
+
   static const unsigned InvalidArgIndex = UINT_MAX;
   /// Denotes the return vale.
   static const unsigned ReturnValueIndex = UINT_MAX - 1;
 
+private:
   mutable std::unique_ptr BT;
   void initBugType() const {
 if (!BT)
@@ -91,8 +120,6 @@
   bool generateReportIfTainted(const Expr *E, const char Msg[],
CheckerContext &C) const;
 
-  using ArgVector = SmallVector;
-
   /// A struct used to specify taint propagation rules for a function.
   ///
   /// If any of the possible taint source arguments is tainted, all of the
@@ -103,8 +130,6 @@
   /// ReturnValueIndex is added to the dst list, the return value will be
   /// tainted.
   struct TaintPropagationRule {
-enum class VariadicType { None, Src, Dst };
-
 using PropagationFuncType = bool (*)(bool IsTainted, const CallExpr *,
  CheckerContext &C);
 
@@ -125,8 +150,7 @@
 : VariadicIndex(InvalidArgIndex), VarType(VariadicType::None),
   PropagationFunc(nullptr) {}
 
-TaintPropagationRule(std::initializer_list &&Src,
- std::initializer_list &&Dst,
+TaintPropagationRule(ArgVector &&Src, ArgVector &&Dst,
  VariadicType Var = VariadicType::None,
  unsigned VarIndex = InvalidArgIndex,
  PropagationFu

[PATCH] D59637: [analyzer] Use the custom propagation rules and sinks in GenericTaintChecker

2019-03-21 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 created this revision.
boga95 added reviewers: NoQ, Szelethus, xazax.hun, dkrupp.
Herald added subscribers: cfe-commits, Charusso, donat.nagy, mikhail.ramalho, 
a.sidorin, rnkovacs, szepet, baloghadamsoftware, whisperity.
Herald added a project: clang.

The `TaintPropagationRule` deduction uses the custom rules from the config.
Check custom sinks when looking for errors. Give an error when at least one of 
the specified arguments is tainted.
Emit error message and omit a parameter if it's out of bound.


Repository:
  rC Clang

https://reviews.llvm.org/D59637

Files:
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  test/Analysis/Inputs/taint-generic-config.yaml
  test/Analysis/taint-generic.c

Index: test/Analysis/taint-generic.c
===
--- test/Analysis/taint-generic.c
+++ test/Analysis/taint-generic.c
@@ -1,5 +1,5 @@
-// RUN: %clang_analyze_cc1  -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -Wno-format-security -verify %s
-// RUN: %clang_analyze_cc1  -DFILE_IS_STRUCT -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -Wno-format-security -verify %s
+// RUN: %clang_analyze_cc1  -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -analyzer-config alpha.security.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config.yaml -Wno-format-security -verify %s
+// RUN: %clang_analyze_cc1  -DFILE_IS_STRUCT -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -analyzer-config alpha.security.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config.yaml -Wno-format-security -verify %s
 
 int scanf(const char *restrict format, ...);
 char *gets(char *str);
@@ -295,3 +295,43 @@
   if (i < rhs)
 *(volatile int *) 0; // no-warning
 }
+
+
+// Test configuration
+int mySource1();
+void mySource2(int*);
+void myScanf(const char*, ...);
+int myPropagator(int, int*);
+int mySnprintf(char*, size_t, const char*, ...);
+void mySink(int, int, int);
+
+void testConfigurationSources1() {
+  int x = mySource1();
+  Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationSources2() {
+  int x;
+  mySource2(&x);
+  Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationSources3() {
+  int x, y;
+  myScanf("%d %d", &x, &y);
+  Buffer[y] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationPropagation() {
+  int x = mySource1();
+  int y;
+  myPropagator(x, &y);
+  Buffer[y] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationSinks() {
+  int x = mySource1();
+  mySink(x, 1, 2); // expected-warning {{Untrusted data is passed to a user defined sink}}
+  mySink(1, x, 2); // no-warning
+  mySink(1, 2, x); // expected-warning {{Untrusted data is passed to a user defined sink}}
+}
Index: test/Analysis/Inputs/taint-generic-config.yaml
===
--- /dev/null
+++ test/Analysis/Inputs/taint-generic-config.yaml
@@ -0,0 +1,51 @@
+# A list of source/propagation function
+Propagations:
+  # int x = mySource1(); // x is tainted
+  - Name: mySource1
+DstArgs:  [4294967294] # Index for return value
+
+  # int x;
+  # mySource2(&x); // x is tainted
+  - Name: mySource2
+DstArgs:  [0]
+
+  # int x, y;
+  # myScanf("%d %d", &x, &y); // x and y are tainted
+  - Name: myScanf
+VarType:  Dst
+VarIndex: 1
+
+  # int x; // x is tainted
+  # int y;
+  # myPropagator(x, &y); // y is tainted
+  - Name: myPropagator
+SrcArgs:  [0]
+DstArgs:  [1]
+
+  # const unsigned size = 100;
+  # char buf[size];
+  # int x, y;
+  # int n = mySprintf(buf, size, "%d %d", x, y); // If size, x or y is tainted
+  # // the return value and the buf will be tainted
+  - Name: mySnprintf
+SrcArgs:  [1]
+DstArgs:  [0, 4294967294]
+VarType:  Src
+VarIndex: 3
+
+# A list of filter functions
+Filters:
+  # int x; // x is tainted
+  # myFilter(&x); // x is not tainted anymore
+  - Name: myFilter
+Args: [0]
+
+# A list of sink functions
+Sinks:
+  # int x, y; // x and y are tainted
+  # mySink(x, 0, 1); // It will warn
+  # mySink(0, 1, y); // It will warn
+  # mySink(0, x, 1); // It won't warn
+  - Name: mySink
+Args: [0, 2]
+
Index: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -116,6 +116,11 @@
   bool checkTaintedBufferSize(const CallExpr *CE, const FunctionDecl *FDecl,
   CheckerContext &C) const;
 
+  /// Check if tainted data is used as a custom sink's parameter.
+  static const char MsgCustomSink[];
+  bool checkCustomSinks(const CallExpr *CE, StringRef Name,
+CheckerContext &C) const;
+
   /// Generate a report

[PATCH] D59516: [analyzer] Add custom filter functions for GenericTaintChecker

2019-03-21 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 updated this revision to Diff 191668.
boga95 retitled this revision from "[analyzer] Make GenericTaintChecker 
configurable" to "[analyzer] Add custom filter functions for 
GenericTaintChecker".

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59516/new/

https://reviews.llvm.org/D59516

Files:
  include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
  include/clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  lib/StaticAnalyzer/Core/ProgramState.cpp
  test/Analysis/taint-generic.c

Index: test/Analysis/taint-generic.c
===
--- test/Analysis/taint-generic.c
+++ test/Analysis/taint-generic.c
@@ -296,13 +296,13 @@
 *(volatile int *) 0; // no-warning
 }
 
-
 // Test configuration
 int mySource1();
 void mySource2(int*);
 void myScanf(const char*, ...);
 int myPropagator(int, int*);
 int mySnprintf(char*, size_t, const char*, ...);
+void myFilter(int*);
 void mySink(int, int, int);
 
 void testConfigurationSources1() {
@@ -329,6 +329,12 @@
   Buffer[y] = 1; // expected-warning {{Out of bound memory access }}
 }
 
+void testConfigurationFilter() {
+  int x = mySource1();
+  myFilter(&x);
+  Buffer[x] = 1; // no-warning
+}
+
 void testConfigurationSinks() {
   int x = mySource1();
   mySink(x, 1, 2); // expected-warning {{Untrusted data is passed to a user defined sink}}
Index: lib/StaticAnalyzer/Core/ProgramState.cpp
===
--- lib/StaticAnalyzer/Core/ProgramState.cpp
+++ lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -658,20 +658,20 @@
   return true;
 }
 
-ProgramStateRef ProgramState::addTaint(const Stmt *S,
+ProgramStateRef ProgramState::setTaint(const Stmt *S,
const LocationContext *LCtx,
TaintTagType Kind) const {
   if (const Expr *E = dyn_cast_or_null(S))
 S = E->IgnoreParens();
 
-  return addTaint(getSVal(S, LCtx), Kind);
+  return setTaint(getSVal(S, LCtx), Kind);
 }
 
-ProgramStateRef ProgramState::addTaint(SVal V,
+ProgramStateRef ProgramState::setTaint(SVal V,
TaintTagType Kind) const {
   SymbolRef Sym = V.getAsSymbol();
   if (Sym)
-return addTaint(Sym, Kind);
+return setTaint(Sym, Kind);
 
   // If the SVal represents a structure, try to mass-taint all values within the
   // structure. For now it only works efficiently on lazy compound values that
@@ -685,22 +685,22 @@
   if (auto LCV = V.getAs()) {
 if (Optional binding = getStateManager().StoreMgr->getDefaultBinding(*LCV)) {
   if (SymbolRef Sym = binding->getAsSymbol())
-return addPartialTaint(Sym, LCV->getRegion(), Kind);
+return setPartialTaint(Sym, LCV->getRegion(), Kind);
 }
   }
 
   const MemRegion *R = V.getAsRegion();
-  return addTaint(R, Kind);
+  return setTaint(R, Kind);
 }
 
-ProgramStateRef ProgramState::addTaint(const MemRegion *R,
+ProgramStateRef ProgramState::setTaint(const MemRegion *R,
TaintTagType Kind) const {
   if (const SymbolicRegion *SR = dyn_cast_or_null(R))
-return addTaint(SR->getSymbol(), Kind);
+return setTaint(SR->getSymbol(), Kind);
   return this;
 }
 
-ProgramStateRef ProgramState::addTaint(SymbolRef Sym,
+ProgramStateRef ProgramState::setTaint(SymbolRef Sym,
TaintTagType Kind) const {
   // If this is a symbol cast, remove the cast before adding the taint. Taint
   // is cast agnostic.
@@ -712,7 +712,7 @@
   return NewState;
 }
 
-ProgramStateRef ProgramState::addPartialTaint(SymbolRef ParentSym,
+ProgramStateRef ProgramState::setPartialTaint(SymbolRef ParentSym,
   const SubRegion *SubRegion,
   TaintTagType Kind) const {
   // Ignore partial taint if the entire parent symbol is already tainted.
@@ -721,7 +721,7 @@
 
   // Partial taint applies if only a portion of the symbol is tainted.
   if (SubRegion == SubRegion->getBaseRegion())
-return addTaint(ParentSym, Kind);
+return setTaint(ParentSym, Kind);
 
   const TaintedSubRegions *SavedRegs = get(ParentSym);
   TaintedSubRegions Regs =
@@ -779,7 +779,7 @@
   continue;
 
 if (const TaintTagType *Tag = get(*SI)) {
-  if (*Tag == Kind)
+  if (*Tag != TaintTagNotTainted && *Tag == Kind)
 return true;
 }
 
Index: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -31,6 +31,28 @@
 using namespace ento;
 
 namespace {
+/// A struct to store tainted argument and taint type as a pair in the program
+/// state.
+struct TaintArgTypePair {
+  unsigned Arg;
+  TaintTagType TagType;
+
+  bool operator==(co

[PATCH] D59555: [analyzer] Add yaml parser to GenericTaintChecker

2019-03-25 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 marked an inline comment as done.
boga95 added a comment.

Why is it better not to use `static` functions/variables? Has it any 
performance impact?




Comment at: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp:73-75
   static const unsigned InvalidArgIndex = UINT_MAX;
   /// Denotes the return vale.
   static const unsigned ReturnValueIndex = UINT_MAX - 1;

Szelethus wrote:
> We should definitely change these, not only is the large integer number 
> impossible to remember, but this value could differ on different platforms.
I tried to use int, but I got a lot of warnings because of the `getNumArgs()` 
returns an unsigned value.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59555/new/

https://reviews.llvm.org/D59555



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D59516: [analyzer] Add custom filter functions for GenericTaintChecker

2019-03-26 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 added a comment.

I add a new taint type, which represents a lack of taintedness. That's why I 
changed the name of `addTaint()` to `setTaint()`. Of course, it's not an 
important change, I can move it to another patch.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59516/new/

https://reviews.llvm.org/D59516



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D59861: [analyzer] NFC: Replace Taint API with a usual inter-checker communication API?

2019-03-27 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 added a comment.

Thanks, it will make my changes more cleaner.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59861/new/

https://reviews.llvm.org/D59861



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D59555: [analyzer] Add yaml parser to GenericTaintChecker

2019-04-01 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 updated this revision to Diff 193175.
boga95 marked an inline comment as done.
boga95 added a comment.

Rebase after https://reviews.llvm.org/D59861.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59555/new/

https://reviews.llvm.org/D59555

Files:
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp

Index: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -15,14 +15,16 @@
 //===--===//
 
 #include "Taint.h"
-#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
 #include "clang/AST/Attr.h"
 #include "clang/Basic/Builtins.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
 #include "clang/StaticAnalyzer/Core/Checker.h"
 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/YAMLTraits.h"
 #include 
 #include 
 #include 
@@ -47,11 +49,38 @@
   void printState(raw_ostream &Out, ProgramStateRef State,
   const char *NL, const char *Sep) const override;
 
-private:
+  using ArgVector = SmallVector;
+
+  enum class VariadicType { None, Src, Dst };
+
+  /// The ``TaintConfiguration`` is used to parse configuration file.
+  struct TaintConfiguration {
+using NameArgsPair = std::pair;
+
+struct Propagation {
+  std::string Name;
+  ArgVector SrcArgs;
+  ArgVector DstArgs;
+  VariadicType VarType;
+  unsigned VarIndex;
+};
+
+std::vector Propagations;
+std::vector Filters;
+std::vector Sinks;
+  };
+
+  /// Get and read the config file.
+  static void getConfiguration(StringRef ConfigFile);
+
+  /// Parse the config.
+  static void parseConfiguration(TaintConfiguration &&Config);
+
   static const unsigned InvalidArgIndex = UINT_MAX;
   /// Denotes the return vale.
   static const unsigned ReturnValueIndex = UINT_MAX - 1;
 
+private:
   mutable std::unique_ptr BT;
   void initBugType() const {
 if (!BT)
@@ -97,8 +126,6 @@
   bool generateReportIfTainted(const Expr *E, const char Msg[],
CheckerContext &C) const;
 
-  using ArgVector = SmallVector;
-
   /// A struct used to specify taint propagation rules for a function.
   ///
   /// If any of the possible taint source arguments is tainted, all of the
@@ -109,8 +136,6 @@
   /// ReturnValueIndex is added to the dst list, the return value will be
   /// tainted.
   struct TaintPropagationRule {
-enum class VariadicType { None, Src, Dst };
-
 using PropagationFuncType = bool (*)(bool IsTainted, const CallExpr *,
  CheckerContext &C);
 
@@ -131,8 +156,7 @@
 : VariadicIndex(InvalidArgIndex), VarType(VariadicType::None),
   PropagationFunc(nullptr) {}
 
-TaintPropagationRule(std::initializer_list &&Src,
- std::initializer_list &&Dst,
+TaintPropagationRule(ArgVector &&Src, ArgVector &&Dst,
  VariadicType Var = VariadicType::None,
  unsigned VarIndex = InvalidArgIndex,
  PropagationFuncType Func = nullptr)
@@ -176,6 +200,19 @@
 static bool postSocket(bool IsTainted, const CallExpr *CE,
CheckerContext &C);
   };
+
+  using NameRuleMap = llvm::StringMap;
+  using NameArgMap = llvm::StringMap;
+
+  /// Defines a map between the propagation function's name and
+  /// TaintPropagationRule.
+  static NameRuleMap CustomPropagations;
+
+  /// Defines a map between the filter function's name and filtering args.
+  static NameArgMap CustomFilters;
+
+  /// Defines a map between the sink function's name and sinking args.
+  static NameArgMap CustomSinks;
 };
 
 const unsigned GenericTaintChecker::ReturnValueIndex;
@@ -194,14 +231,105 @@
 "(CERT/STR31-C. Guarantee that storage for strings has sufficient space "
 "for character data and the null terminator)";
 
+GenericTaintChecker::NameRuleMap GenericTaintChecker::CustomPropagations;
+
+GenericTaintChecker::NameArgMap GenericTaintChecker::CustomFilters;
+
+GenericTaintChecker::NameArgMap GenericTaintChecker::CustomSinks;
 } // end of anonymous namespace
 
+using TaintConfig = GenericTaintChecker::TaintConfiguration;
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(TaintConfig::Propagation)
+LLVM_YAML_IS_SEQUENCE_VECTOR(TaintConfig::NameArgsPair)
+
+namespace llvm {
+namespace yaml {
+template <> struct MappingTraits {
+  static void mapping(IO &IO, TaintConfig &Config) {
+IO.mapOptional("Propagations", Config.Propagations);
+IO.mapOptional("Filters", Config.Filters);
+IO.mapOptional("Si

[PATCH] D59637: [analyzer] Use the custom propagation rules and sinks in GenericTaintChecker

2019-04-04 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 updated this revision to Diff 193676.
boga95 added a comment.

Rebase after https://reviews.llvm.org/D59861.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59637/new/

https://reviews.llvm.org/D59637

Files:
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  test/Analysis/Inputs/taint-generic-config.yaml
  test/Analysis/taint-generic.c

Index: test/Analysis/taint-generic.c
===
--- test/Analysis/taint-generic.c
+++ test/Analysis/taint-generic.c
@@ -1,5 +1,5 @@
-// RUN: %clang_analyze_cc1  -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -Wno-format-security -verify %s
-// RUN: %clang_analyze_cc1  -DFILE_IS_STRUCT -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -Wno-format-security -verify %s
+// RUN: %clang_analyze_cc1  -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -analyzer-config alpha.security.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config.yaml -Wno-format-security -verify %s
+// RUN: %clang_analyze_cc1  -DFILE_IS_STRUCT -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -analyzer-config alpha.security.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config.yaml -Wno-format-security -verify %s
 
 int scanf(const char *restrict format, ...);
 char *gets(char *str);
@@ -295,3 +295,43 @@
   if (i < rhs)
 *(volatile int *) 0; // no-warning
 }
+
+
+// Test configuration
+int mySource1();
+void mySource2(int*);
+void myScanf(const char*, ...);
+int myPropagator(int, int*);
+int mySnprintf(char*, size_t, const char*, ...);
+void mySink(int, int, int);
+
+void testConfigurationSources1() {
+  int x = mySource1();
+  Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationSources2() {
+  int x;
+  mySource2(&x);
+  Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationSources3() {
+  int x, y;
+  myScanf("%d %d", &x, &y);
+  Buffer[y] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationPropagation() {
+  int x = mySource1();
+  int y;
+  myPropagator(x, &y);
+  Buffer[y] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationSinks() {
+  int x = mySource1();
+  mySink(x, 1, 2); // expected-warning {{Untrusted data is passed to a user defined sink}}
+  mySink(1, x, 2); // no-warning
+  mySink(1, 2, x); // expected-warning {{Untrusted data is passed to a user defined sink}}
+}
Index: test/Analysis/Inputs/taint-generic-config.yaml
===
--- /dev/null
+++ test/Analysis/Inputs/taint-generic-config.yaml
@@ -0,0 +1,51 @@
+# A list of source/propagation function
+Propagations:
+  # int x = mySource1(); // x is tainted
+  - Name: mySource1
+DstArgs:  [4294967294] # Index for return value
+
+  # int x;
+  # mySource2(&x); // x is tainted
+  - Name: mySource2
+DstArgs:  [0]
+
+  # int x, y;
+  # myScanf("%d %d", &x, &y); // x and y are tainted
+  - Name: myScanf
+VarType:  Dst
+VarIndex: 1
+
+  # int x; // x is tainted
+  # int y;
+  # myPropagator(x, &y); // y is tainted
+  - Name: myPropagator
+SrcArgs:  [0]
+DstArgs:  [1]
+
+  # const unsigned size = 100;
+  # char buf[size];
+  # int x, y;
+  # int n = mySprintf(buf, size, "%d %d", x, y); // If size, x or y is tainted
+  # // the return value and the buf will be tainted
+  - Name: mySnprintf
+SrcArgs:  [1]
+DstArgs:  [0, 4294967294]
+VarType:  Src
+VarIndex: 3
+
+# A list of filter functions
+Filters:
+  # int x; // x is tainted
+  # myFilter(&x); // x is not tainted anymore
+  - Name: myFilter
+Args: [0]
+
+# A list of sink functions
+Sinks:
+  # int x, y; // x and y are tainted
+  # mySink(x, 0, 1); // It will warn
+  # mySink(0, 1, y); // It will warn
+  # mySink(0, x, 1); // It won't warn
+  - Name: mySink
+Args: [0, 2]
+
Index: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -122,6 +122,11 @@
   bool checkTaintedBufferSize(const CallExpr *CE, const FunctionDecl *FDecl,
   CheckerContext &C) const;
 
+  /// Check if tainted data is used as a custom sink's parameter.
+  static const char MsgCustomSink[];
+  bool checkCustomSinks(const CallExpr *CE, StringRef Name,
+CheckerContext &C) const;
+
   /// Generate a report if the expression is tainted or points to tainted data.
   bool generateReportIfTainted(const Expr *E, const char Msg[],
CheckerContext &C) const;
@@ -231,6 +236,9 @@
 "(CERT/STR31-C. Guarantee that storage for strings has sufficient space "
 "for character data and the null terminator)";
 
+const char GenericTaint

[PATCH] D59516: [analyzer] Add custom filter functions for GenericTaintChecker

2019-04-04 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 updated this revision to Diff 193705.
boga95 added a comment.

Rebase after https://reviews.llvm.org/D59861.
Fix custom filter test case: functions without definition always remove 
taintedness.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59516/new/

https://reviews.llvm.org/D59516

Files:
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  lib/StaticAnalyzer/Checkers/Taint.cpp
  lib/StaticAnalyzer/Checkers/Taint.h
  test/Analysis/Inputs/taint-generic-config.yaml
  test/Analysis/taint-generic.c

Index: test/Analysis/taint-generic.c
===
--- test/Analysis/taint-generic.c
+++ test/Analysis/taint-generic.c
@@ -296,13 +296,15 @@
 *(volatile int *) 0; // no-warning
 }
 
-
 // Test configuration
 int mySource1();
 void mySource2(int*);
 void myScanf(const char*, ...);
 int myPropagator(int, int*);
 int mySnprintf(char*, size_t, const char*, ...);
+void myFilter1(int* x) {}
+void myFilter2(const int*);
+void myFilter3(int);
 void mySink(int, int, int);
 
 void testConfigurationSources1() {
@@ -329,6 +331,24 @@
   Buffer[y] = 1; // expected-warning {{Out of bound memory access }}
 }
 
+void testConfigurationFilter1() {
+  int x = mySource1();
+  myFilter1(&x);
+  Buffer[x] = 1; // no-warning
+}
+
+void testConfigurationFilter2() {
+  int x = mySource1();
+  myFilter2(&x); // Pass by const int*
+  Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationFilter3() {
+  int x = mySource1();
+  myFilter3(x); // Pass by value
+  Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
+}
+
 void testConfigurationSinks() {
   int x = mySource1();
   mySink(x, 1, 2); // expected-warning {{Untrusted data is passed to a user defined sink}}
Index: test/Analysis/Inputs/taint-generic-config.yaml
===
--- test/Analysis/Inputs/taint-generic-config.yaml
+++ test/Analysis/Inputs/taint-generic-config.yaml
@@ -36,8 +36,8 @@
 # A list of filter functions
 Filters:
   # int x; // x is tainted
-  # myFilter(&x); // x is not tainted anymore
-  - Name: myFilter
+  # myFilter1(&x); // x is not tainted anymore
+  - Name: myFilter1
 Args: [0]
 
 # A list of sink functions
Index: lib/StaticAnalyzer/Checkers/Taint.h
===
--- lib/StaticAnalyzer/Checkers/Taint.h
+++ lib/StaticAnalyzer/Checkers/Taint.h
@@ -24,37 +24,35 @@
 /// taint.
 using TaintTagType = unsigned;
 
-static constexpr TaintTagType TaintTagGeneric = 0;
+static constexpr TaintTagType TaintTagNotTainted = 0;
+static constexpr TaintTagType TaintTagGeneric = 1;
 
 /// Create a new state in which the value of the statement is marked as tainted.
-LLVM_NODISCARD ProgramStateRef
-addTaint(ProgramStateRef State, const Stmt *S, const LocationContext *LCtx,
- TaintTagType Kind = TaintTagGeneric);
+LLVM_NODISCARD ProgramStateRef addTaint(ProgramStateRef State, const Stmt *S,
+const LocationContext *LCtx,
+TaintTagType Kind = TaintTagGeneric);
 
 /// Create a new state in which the value is marked as tainted.
-LLVM_NODISCARD ProgramStateRef
-addTaint(ProgramStateRef State, SVal V,
- TaintTagType Kind = TaintTagGeneric);
+LLVM_NODISCARD ProgramStateRef addTaint(ProgramStateRef State, SVal V,
+TaintTagType Kind = TaintTagGeneric);
 
 /// Create a new state in which the symbol is marked as tainted.
-LLVM_NODISCARD ProgramStateRef
-addTaint(ProgramStateRef State, SymbolRef Sym,
- TaintTagType Kind = TaintTagGeneric);
+LLVM_NODISCARD ProgramStateRef addTaint(ProgramStateRef State, SymbolRef Sym,
+TaintTagType Kind = TaintTagGeneric);
 
 /// Create a new state in which the pointer represented by the region
 /// is marked as tainted.
-LLVM_NODISCARD ProgramStateRef
-addTaint(ProgramStateRef State, const MemRegion *R,
- TaintTagType Kind = TaintTagGeneric);
+LLVM_NODISCARD ProgramStateRef addTaint(ProgramStateRef State,
+const MemRegion *R,
+TaintTagType Kind = TaintTagGeneric);
 
 /// Create a new state in a which a sub-region of a given symbol is tainted.
 /// This might be necessary when referring to regions that can not have an
 /// individual symbol, e.g. if they are represented by the default binding of
 /// a LazyCompoundVal.
-LLVM_NODISCARD ProgramStateRef
-addPartialTaint(ProgramStateRef State,
-SymbolRef ParentSym, const SubRegion *SubRegion,
-TaintTagType Kind = TaintTagGeneric);
+LLVM_NODISCARD ProgramStateRef addPartialTaint(
+ProgramStateRef State, SymbolRef ParentSym, const SubRegion *SubRegion,
+TaintTagType Kind = TaintTagGeneric);
 
 /// Check if the statement has a tainted value in the given state.
 bool isTaint

[PATCH] D52281: Use std::invoke in generic code

2018-09-19 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 created this revision.
boga95 added a project: clang-tools-extra.
Herald added subscribers: cfe-commits, mgorny.

In generic code (e.g.: in a type dependent expression), the `std::invoke` 
should be used, in order to support functors, function pointers, pointers to 
members, regular functions, and other C++ and STL features: link 

The check replace the appropriate calls with calls to std::invoke. This should 
work only in C++17 and newer codebases.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D52281

Files:
  clang-tidy/modernize/CMakeLists.txt
  clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tidy/modernize/ReplaceGenericFunctorCallCheck.cpp
  clang-tidy/modernize/ReplaceGenericFunctorCallCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/modernize-replace-generic-functor-call.rst
  test/clang-tidy/modernize-replace-generic-functor-call.cpp

Index: test/clang-tidy/modernize-replace-generic-functor-call.cpp
===
--- /dev/null
+++ test/clang-tidy/modernize-replace-generic-functor-call.cpp
@@ -0,0 +1,56 @@
+// RUN: %check_clang_tidy %s modernize-replace-generic-functor-call %t -- -- -std=c++17
+
+namespace std {
+
+template 
+T max(T a, T b) {
+  return a < b ? b : a;
+}
+
+struct function {
+  void operator()();
+};
+
+} // namespace std
+
+struct Foo {
+  static void print_() {}
+  void print() const {}
+  int num_;
+};
+
+// Something that triggers the check
+template 
+void func2(T func) {
+  func(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: Use ::std::invoke to invoke type dependent callable objects. [modernize-replace-generic-functor-call]
+  // CHECK-FIXES: ::std::invoke(func, 1);
+  func();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: Use ::std::invoke to invoke type dependent callable objects. [modernize-replace-generic-functor-call]
+  // CHECK-FIXES: ::std::invoke(func);
+
+  Foo foo;
+  (foo.*func)(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: Use ::std::invoke to invoke type dependent callable objects. [modernize-replace-generic-functor-call]
+  // CHECK-FIXES: ::std::invoke(foo, func, 1);
+  (foo.*func)();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: Use ::std::invoke to invoke type dependent callable objects. [modernize-replace-generic-functor-call]
+  // CHECK-FIXES: ::std::invoke(foo, func);
+  (Foo().*func)(1, 2);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: Use ::std::invoke to invoke type dependent callable objects. [modernize-replace-generic-functor-call]
+  // CHECK-FIXES: ::std::invoke(Foo(), func, 1, 2);
+}
+
+// Something that doesn't triggers the check
+void func3() {}
+
+void g(std::function func, int (*fp)(int), void (Foo::*mfp)(int)) {
+  func3();// Regular function call
+  std::max(1, 2); // Template function call
+  Foo::print_();  // Static function call
+  []() {}();  // Lambda call
+  func(); // Call through std::function
+  fp(3);  // Call through function pointer
+  Foo foo;
+  (foo.*(mfp))(1); // Call through member function pointer
+}
Index: docs/clang-tidy/checks/modernize-replace-generic-functor-call.rst
===
--- /dev/null
+++ docs/clang-tidy/checks/modernize-replace-generic-functor-call.rst
@@ -0,0 +1,31 @@
+.. title:: clang-tidy - modernize-replace-generic-functor-call
+
+modernize-replace-generic-functor-call
+==
+
+This check finds and replace the functor, function pointer and pointer to member
+calls to the proper ``std::invoke()`` call. It works only in C++17 or newer.
+
+Examples:
+
+.. code-block:: c++
+
+  template
+  void f(T1 func, T2 mfp) {
+func(2); // Replace to ::std::invoke(func, 2)
+Foo foo;
+(foo.*mfp)(1, 2); // Replace to ::std::invoke(foo, mfp, 1, 2)
+(Foo().*mfp)(3); // Replace to ::std::invoke(Foo(), mfp, 3)
+  }
+
+  // Neither of them is type dependent, no diagnose
+  void g(std::function func, int (*fp)(int), void (Foo::*mfp)(int)) {
+func3();
+std::max(1,2);
+Foo::print_();
+[](){}();
+func();
+fp(3);
+Foo foo;
+(foo.*(mfp))(1);
+  }
Index: docs/clang-tidy/checks/list.rst
===
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -163,6 +163,7 @@
modernize-raw-string-literal
modernize-redundant-void-arg
modernize-replace-auto-ptr
+   modernize-replace-generic-functor-call
modernize-replace-random-shuffle
modernize-return-braced-init-list
modernize-shrink-to-fit
Index: docs/ReleaseNotes.rst
===
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -57,6 +57,12 @@
 Improvements to clang-tidy
 --
 
+- New `modernize-replace-generic-functor-call
+  

[PATCH] D52281: [clang-tidy] Add modernize check to use std::invoke in generic code

2018-09-22 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 updated this revision to Diff 166604.

https://reviews.llvm.org/D52281

Files:
  clang-tidy/modernize/CMakeLists.txt
  clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tidy/modernize/ReplaceGenericFunctorCallCheck.cpp
  clang-tidy/modernize/ReplaceGenericFunctorCallCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/modernize-replace-generic-functor-call.rst
  test/clang-tidy/modernize-replace-generic-functor-call.cpp

Index: test/clang-tidy/modernize-replace-generic-functor-call.cpp
===
--- /dev/null
+++ test/clang-tidy/modernize-replace-generic-functor-call.cpp
@@ -0,0 +1,56 @@
+// RUN: %check_clang_tidy %s modernize-replace-generic-functor-call %t -- -- -std=c++17
+
+namespace std {
+
+template 
+T max(T a, T b) {
+  return a < b ? b : a;
+}
+
+struct function {
+  void operator()();
+};
+
+} // namespace std
+
+struct Foo {
+  static void print_() {}
+  void print() const {}
+  int num_;
+};
+
+// Something that triggers the check
+template 
+void func2(T func) {
+  func(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: Use ::std::invoke to invoke type dependent callable objects. [modernize-replace-generic-functor-call]
+  // CHECK-FIXES: ::std::invoke(func, 1);
+  func();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: Use ::std::invoke to invoke type dependent callable objects. [modernize-replace-generic-functor-call]
+  // CHECK-FIXES: ::std::invoke(func);
+
+  Foo foo;
+  (foo.*func)(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: Use ::std::invoke to invoke type dependent callable objects. [modernize-replace-generic-functor-call]
+  // CHECK-FIXES: ::std::invoke(foo, func, 1);
+  (foo.*func)();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: Use ::std::invoke to invoke type dependent callable objects. [modernize-replace-generic-functor-call]
+  // CHECK-FIXES: ::std::invoke(foo, func);
+  (Foo().*func)(1, 2);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: Use ::std::invoke to invoke type dependent callable objects. [modernize-replace-generic-functor-call]
+  // CHECK-FIXES: ::std::invoke(Foo(), func, 1, 2);
+}
+
+// Something that doesn't triggers the check
+void func3() {}
+
+void g(std::function func, int (*fp)(int), void (Foo::*mfp)(int)) {
+  func3();// Regular function call
+  std::max(1, 2); // Template function call
+  Foo::print_();  // Static function call
+  []() {}();  // Lambda call
+  func(); // Call through std::function
+  fp(3);  // Call through function pointer
+  Foo foo;
+  (foo.*(mfp))(1); // Call through member function pointer
+}
Index: docs/clang-tidy/checks/modernize-replace-generic-functor-call.rst
===
--- /dev/null
+++ docs/clang-tidy/checks/modernize-replace-generic-functor-call.rst
@@ -0,0 +1,39 @@
+.. title:: clang-tidy - modernize-replace-generic-functor-call
+
+modernize-replace-generic-functor-call
+==
+
+Replaces type dependent functor, function pointer and pointer to member call
+to the proper ``std::invoke()`` in C++17 or newer codebases.
+  
+Examples:
+
+.. code-block:: c++
+
+  template
+  void f(T1 functionPointer, T2 memberFunctionPointer) {
+functionPointer(2); // Replace to ::std::invoke(functionPointer, 2)
+
+Foo foo;
+(foo.*memberFunctionPointer)(1, 2); // Replace to ::std::invoke(foo, memberFunctionPointer, 1, 2)
+
+(Foo().*memberFunctionPointer)(3); // Replace to ::std::invoke(Foo(), memberFunctionPointer, 3)
+  }
+
+  // Neither of them is type dependent, no diagnose
+  void g(std::function func, int (*functionPointer)(int), void (Foo::*memberFunctionPointer)(int)) {
+freeFunction();
+
+std::max(1,2);
+
+Foo::print_();
+
+[](){}();
+
+func();
+
+functionPointer(3);
+
+Foo foo;
+(foo.*(memberFunctionPointer))(1);
+  }
Index: docs/clang-tidy/checks/list.rst
===
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -171,6 +171,7 @@
modernize-raw-string-literal
modernize-redundant-void-arg
modernize-replace-auto-ptr
+   modernize-replace-generic-functor-call
modernize-replace-random-shuffle
modernize-return-braced-init-list
modernize-shrink-to-fit
Index: docs/ReleaseNotes.rst
===
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -142,6 +142,12 @@
 
   Checks on ``switch`` and ``if`` - ``else if`` constructs that do not cover all possible code paths.
 
+- New :doc:`modernize-replace-generic-functor-call
+  ` check.
+
+  Replaces type dependent functor, function pointer and pointer to member call
+  to the proper ``std::invoke()`` in C++17 or newer codebases.
+  
 - New :doc:`modernize-use-uncaught-exceptions
   ` check.
 
Index: clang-tidy/modernize/ReplaceGenericFunctorCallCheck.h
=

[PATCH] D52281: [clang-tidy] Add modernize check to use std::invoke in generic code

2018-09-25 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 updated this revision to Diff 166994.
boga95 marked 12 inline comments as done.

https://reviews.llvm.org/D52281

Files:
  clang-tidy/modernize/CMakeLists.txt
  clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tidy/modernize/ReplaceGenericFunctorCallCheck.cpp
  clang-tidy/modernize/ReplaceGenericFunctorCallCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/modernize-replace-generic-functor-call.rst
  test/clang-tidy/modernize-replace-generic-functor-call.cpp

Index: test/clang-tidy/modernize-replace-generic-functor-call.cpp
===
--- /dev/null
+++ test/clang-tidy/modernize-replace-generic-functor-call.cpp
@@ -0,0 +1,56 @@
+// RUN: %check_clang_tidy %s modernize-replace-generic-functor-call %t -- -- -std=c++17
+
+namespace std {
+
+template 
+T max(T a, T b) {
+  return a < b ? b : a;
+}
+
+struct function {
+  void operator()();
+};
+
+} // namespace std
+
+struct Foo {
+  static void print_() {}
+  void print() const {}
+  int num_;
+};
+
+// Something that triggers the check
+template 
+void func2(T func) {
+  func(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: Use ::std::invoke to invoke type dependent callable objects. [modernize-replace-generic-functor-call]
+  // CHECK-FIXES: ::std::invoke(func, 1);
+  func();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: Use ::std::invoke to invoke type dependent callable objects. [modernize-replace-generic-functor-call]
+  // CHECK-FIXES: ::std::invoke(func);
+
+  Foo foo;
+  (foo.*func)(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: Use ::std::invoke to invoke type dependent callable objects. [modernize-replace-generic-functor-call]
+  // CHECK-FIXES: ::std::invoke(foo, func, 1);
+  (foo.*func)();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: Use ::std::invoke to invoke type dependent callable objects. [modernize-replace-generic-functor-call]
+  // CHECK-FIXES: ::std::invoke(foo, func);
+  (Foo().*func)(1, 2);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: Use ::std::invoke to invoke type dependent callable objects. [modernize-replace-generic-functor-call]
+  // CHECK-FIXES: ::std::invoke(Foo(), func, 1, 2);
+}
+
+// Something that doesn't triggers the check
+void func3() {}
+
+void g(std::function func, int (*fp)(int), void (Foo::*mfp)(int)) {
+  func3();// Regular function call
+  std::max(1, 2); // Template function call
+  Foo::print_();  // Static function call
+  []() {}();  // Lambda call
+  func(); // Call through std::function
+  fp(3);  // Call through function pointer
+  Foo foo;
+  (foo.*(mfp))(1); // Call through member function pointer
+}
Index: docs/clang-tidy/checks/modernize-replace-generic-functor-call.rst
===
--- /dev/null
+++ docs/clang-tidy/checks/modernize-replace-generic-functor-call.rst
@@ -0,0 +1,39 @@
+.. title:: clang-tidy - modernize-replace-generic-functor-call
+
+modernize-replace-generic-functor-call
+==
+
+Replaces type dependent functor, function pointer and pointer to member call
+to the proper ``std::invoke()`` in C++17 or newer codebases.
+  
+Examples:
+
+.. code-block:: c++
+
+  template
+  void f(T1 functionPointer, T2 memberFunctionPointer) {
+functionPointer(2); // Replace to ::std::invoke(functionPointer, 2)
+
+Foo foo;
+(foo.*memberFunctionPointer)(1, 2); // Replace to ::std::invoke(foo, memberFunctionPointer, 1, 2)
+
+(Foo().*memberFunctionPointer)(3); // Replace to ::std::invoke(Foo(), memberFunctionPointer, 3)
+  }
+
+  // Neither of them is type dependent, no diagnose
+  void g(std::function func, int (*functionPointer)(int), void (Foo::*memberFunctionPointer)(int)) {
+freeFunction();
+
+std::max(1,2);
+
+Foo::print_();
+
+[](){}();
+
+func();
+
+functionPointer(3);
+
+Foo foo;
+(foo.*(memberFunctionPointer))(1);
+  }
Index: docs/clang-tidy/checks/list.rst
===
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -171,6 +171,7 @@
modernize-raw-string-literal
modernize-redundant-void-arg
modernize-replace-auto-ptr
+   modernize-replace-generic-functor-call
modernize-replace-random-shuffle
modernize-return-braced-init-list
modernize-shrink-to-fit
Index: docs/ReleaseNotes.rst
===
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -142,6 +142,12 @@
 
   Checks on ``switch`` and ``if`` - ``else if`` constructs that do not cover all possible code paths.
 
+- New :doc:`modernize-replace-generic-functor-call
+  ` check.
+
+  Replaces type dependent functor, function pointer and pointer to member call
+  to the proper ``std::invoke()`` in C++17 or newer codebases.
+  
 - New :doc:`modernize-use-uncaught-exceptions
   ` check.
 
Index: clang-tidy/modernize/Repl

[PATCH] D52281: [clang-tidy] Add modernize check to use std::invoke in generic code

2018-10-02 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 updated this revision to Diff 167991.
boga95 marked 7 inline comments as done.

https://reviews.llvm.org/D52281

Files:
  clang-tidy/modernize/CMakeLists.txt
  clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tidy/modernize/ReplaceGenericFunctorCallCheck.cpp
  clang-tidy/modernize/ReplaceGenericFunctorCallCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/modernize-replace-generic-functor-call.rst
  test/clang-tidy/modernize-replace-generic-functor-call.cpp

Index: test/clang-tidy/modernize-replace-generic-functor-call.cpp
===
--- /dev/null
+++ test/clang-tidy/modernize-replace-generic-functor-call.cpp
@@ -0,0 +1,56 @@
+// RUN: %check_clang_tidy %s modernize-replace-generic-functor-call %t -- -- -std=c++17
+
+namespace std {
+
+template 
+T max(T a, T b) {
+  return a < b ? b : a;
+}
+
+struct function {
+  void operator()();
+};
+
+} // namespace std
+
+struct Foo {
+  static void print_() {}
+  void print() const {}
+  int num_;
+};
+
+// Something that triggers the check
+template 
+void func2(T func) {
+  func(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use ::std::invoke to invoke type dependent callable objects [modernize-replace-generic-functor-call]
+  // CHECK-FIXES: ::std::invoke(func, 1);
+  func();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use ::std::invoke to invoke type dependent callable objects [modernize-replace-generic-functor-call]
+  // CHECK-FIXES: ::std::invoke(func);
+
+  Foo foo;
+  (foo.*func)(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use ::std::invoke to invoke type dependent callable objects [modernize-replace-generic-functor-call]
+  // CHECK-FIXES: ::std::invoke(foo, func, 1);
+  (foo.*func)();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use ::std::invoke to invoke type dependent callable objects [modernize-replace-generic-functor-call]
+  // CHECK-FIXES: ::std::invoke(foo, func);
+  (Foo().*func)(1, 2);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use ::std::invoke to invoke type dependent callable objects [modernize-replace-generic-functor-call]
+  // CHECK-FIXES: ::std::invoke(Foo(), func, 1, 2);
+}
+
+// Something that doesn't triggers the check
+void func3() {}
+
+void g(std::function func, int (*fp)(int), void (Foo::*mfp)(int)) {
+  func3();// Regular function call
+  std::max(1, 2); // Template function call
+  Foo::print_();  // Static function call
+  []() {}();  // Lambda call
+  func(); // Call through std::function
+  fp(3);  // Call through function pointer
+  Foo foo;
+  (foo.*(mfp))(1); // Call through member function pointer
+}
Index: docs/clang-tidy/checks/modernize-replace-generic-functor-call.rst
===
--- /dev/null
+++ docs/clang-tidy/checks/modernize-replace-generic-functor-call.rst
@@ -0,0 +1,39 @@
+.. title:: clang-tidy - modernize-replace-generic-functor-call
+
+modernize-replace-generic-functor-call
+==
+
+Replaces type dependent functor, function pointer and pointer to member call
+to the proper ``std::invoke()`` in C++17 or newer codebases.
+  
+Examples:
+
+.. code-block:: c++
+
+  template
+  void f(T1 functionPointer, T2 memberFunctionPointer) {
+functionPointer(2); // Replace to ::std::invoke(functionPointer, 2)
+
+Foo foo;
+(foo.*memberFunctionPointer)(1, 2); // Replace to ::std::invoke(foo, memberFunctionPointer, 1, 2)
+
+(Foo().*memberFunctionPointer)(3); // Replace to ::std::invoke(Foo(), memberFunctionPointer, 3)
+  }
+
+  // Neither of them is type dependent, no diagnose
+  void g(std::function func, int (*functionPointer)(int), void (Foo::*memberFunctionPointer)(int)) {
+freeFunction();
+
+std::max(1,2);
+
+Foo::print_();
+
+[](){}();
+
+func();
+
+functionPointer(3);
+
+Foo foo;
+(foo.*(memberFunctionPointer))(1);
+  }
Index: docs/clang-tidy/checks/list.rst
===
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -171,6 +171,7 @@
modernize-raw-string-literal
modernize-redundant-void-arg
modernize-replace-auto-ptr
+   modernize-replace-generic-functor-call
modernize-replace-random-shuffle
modernize-return-braced-init-list
modernize-shrink-to-fit
Index: docs/ReleaseNotes.rst
===
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -142,6 +142,12 @@
 
   Checks on ``switch`` and ``if`` - ``else if`` constructs that do not cover all possible code paths.
 
+- New :doc:`modernize-replace-generic-functor-call
+  ` check.
+
+  Replaces type dependent functor, function pointer and pointer to member call
+  to the proper ``std::invoke()`` in C++17 or newer codebases.
+  
 - New :doc:`modernize-use-uncaught-exceptions
   ` check.
 
Index: clang-tidy/modernize/ReplaceGen

[PATCH] D59555: [analyzer] Add yaml parser to GenericTaintChecker

2019-06-06 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 updated this revision to Diff 203339.

Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59555/new/

https://reviews.llvm.org/D59555

Files:
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  lib/StaticAnalyzer/Checkers/Yaml.h
  test/Analysis/Inputs/taint-generic-config.yaml
  test/Analysis/taint-generic.c

Index: test/Analysis/taint-generic.c
===
--- test/Analysis/taint-generic.c
+++ test/Analysis/taint-generic.c
@@ -1,5 +1,5 @@
-// RUN: %clang_analyze_cc1  -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -Wno-format-security -verify %s
-// RUN: %clang_analyze_cc1  -DFILE_IS_STRUCT -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -Wno-format-security -verify %s
+// RUN: %clang_analyze_cc1  -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -analyzer-config alpha.security.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config.yaml -Wno-format-security -verify %s
+// RUN: %clang_analyze_cc1  -DFILE_IS_STRUCT -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -analyzer-config alpha.security.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config.yaml -Wno-format-security -verify %s
 
 int scanf(const char *restrict format, ...);
 char *gets(char *str);
Index: test/Analysis/Inputs/taint-generic-config.yaml
===
--- /dev/null
+++ test/Analysis/Inputs/taint-generic-config.yaml
@@ -0,0 +1,51 @@
+# A list of source/propagation function
+Propagations:
+  # int x = mySource1(); // x is tainted
+  - Name: mySource1
+DstArgs:  [-1] # Index for return value
+
+  # int x;
+  # mySource2(&x); // x is tainted
+  - Name: mySource2
+DstArgs:  [0]
+
+  # int x, y;
+  # myScanf("%d %d", &x, &y); // x and y are tainted
+  - Name:  myScanf
+VariadicType:  Dst
+VariadicIndex: 1
+
+  # int x; // x is tainted
+  # int y;
+  # myPropagator(x, &y); // y is tainted
+  - Name: myPropagator
+SrcArgs:  [0]
+DstArgs:  [1]
+
+  # constexpr unsigned size = 100;
+  # char buf[size];
+  # int x, y;
+  # int n = mySprintf(buf, size, "%d %d", x, y); // If size, x or y is tainted
+  # // the return value and the buf will be tainted
+  - Name:  mySnprintf
+SrcArgs:   [1]
+DstArgs:   [0, -1]
+VariadicType:  Src
+VariadicIndex: 3
+
+# A list of filter functions
+Filters:
+  # int x; // x is tainted
+  # myFilter(&x); // x is not tainted anymore
+  - Name: myFilter
+Args: [0]
+
+# A list of sink functions
+Sinks:
+  # int x, y; // x and y are tainted
+  # mySink(x, 0, 1); // It will warn
+  # mySink(0, 1, y); // It will warn
+  # mySink(0, x, 1); // It won't warn
+  - Name: mySink
+Args: [0, 2]
+
Index: lib/StaticAnalyzer/Checkers/Yaml.h
===
--- /dev/null
+++ lib/StaticAnalyzer/Checkers/Yaml.h
@@ -0,0 +1,29 @@
+#include "llvm/ADT/APInt.h"
+#include "llvm/Support/YAMLTraits.h"
+
+/// Read the given file from the filesystem and parse it as a yaml file. The
+/// template parameter must have a yaml MappingTraits.
+template 
+llvm::Optional getConfiguration(llvm::StringRef ConfigFile) {
+  if (ConfigFile.trim().empty())
+return {};
+
+  llvm::vfs::FileSystem *FS = llvm::vfs::getRealFileSystem().get();
+  llvm::ErrorOr> Buffer =
+  FS->getBufferForFile(ConfigFile.str());
+
+  if (std::error_code ec = Buffer.getError()) {
+llvm::errs() << "Error when getting TaintPropagation's config file '"
+ << ConfigFile << "': " << ec.message() << '\n';
+return {};
+  }
+
+  llvm::yaml::Input Input(Buffer.get()->getBuffer());
+  T Config;
+  Input >> Config;
+
+  if (std::error_code ec = Input.error())
+return {};
+
+  return Config;
+}
Index: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -15,16 +15,19 @@
 //===--===//
 
 #include "Taint.h"
-#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "Yaml.h"
 #include "clang/AST/Attr.h"
 #include "clang/Basic/Builtins.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
 #include "clang/StaticAnalyzer/Core/Checker.h"
 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
-#include 
-#include 
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/YAMLTraits.h"
+#include 
 #include 
 
 using namespace clang;
@@ -44,14 +47,49 @@
 
   void checkPreStmt(const

[PATCH] D59555: [analyzer] Add yaml parser to GenericTaintChecker

2019-07-16 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 updated this revision to Diff 210073.
boga95 marked 11 inline comments as done.
boga95 added a comment.

Report diagnostic error in case of an invalid filename or an ill-formed yaml 
file.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59555/new/

https://reviews.llvm.org/D59555

Files:
  include/clang/StaticAnalyzer/Checkers/Checkers.td
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  lib/StaticAnalyzer/Checkers/Yaml.h
  test/Analysis/Inputs/taint-generic-config.yaml
  test/Analysis/taint-generic.c

Index: test/Analysis/taint-generic.c
===
--- test/Analysis/taint-generic.c
+++ test/Analysis/taint-generic.c
@@ -1,5 +1,5 @@
-// RUN: %clang_analyze_cc1  -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -Wno-format-security -verify %s
-// RUN: %clang_analyze_cc1  -DFILE_IS_STRUCT -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -Wno-format-security -verify %s
+// RUN: %clang_analyze_cc1  -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -analyzer-config alpha.security.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config.yaml -Wno-format-security -verify %s
+// RUN: %clang_analyze_cc1  -DFILE_IS_STRUCT -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -analyzer-config alpha.security.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config.yaml -Wno-format-security -verify %s
 
 int scanf(const char *restrict format, ...);
 char *gets(char *str);
Index: test/Analysis/Inputs/taint-generic-config.yaml
===
--- /dev/null
+++ test/Analysis/Inputs/taint-generic-config.yaml
@@ -0,0 +1,51 @@
+# A list of source/propagation function
+Propagations:
+  # int x = mySource1(); // x is tainted
+  - Name: mySource1
+DstArgs:  [-1] # Index for return value
+
+  # int x;
+  # mySource2(&x); // x is tainted
+  - Name: mySource2
+DstArgs:  [0]
+
+  # int x, y;
+  # myScanf("%d %d", &x, &y); // x and y are tainted
+  - Name:  myScanf
+VariadicType:  Dst
+VariadicIndex: 1
+
+  # int x; // x is tainted
+  # int y;
+  # myPropagator(x, &y); // y is tainted
+  - Name: myPropagator
+SrcArgs:  [0]
+DstArgs:  [1]
+
+  # constexpr unsigned size = 100;
+  # char buf[size];
+  # int x, y;
+  # int n = mySprintf(buf, size, "%d %d", x, y); // If size, x or y is tainted
+  # // the return value and the buf will be tainted
+  - Name:  mySnprintf
+SrcArgs:   [1]
+DstArgs:   [0, -1]
+VariadicType:  Src
+VariadicIndex: 3
+
+# A list of filter functions
+Filters:
+  # int x; // x is tainted
+  # myFilter(&x); // x is not tainted anymore
+  - Name: myFilter
+Args: [0]
+
+# A list of sink functions
+Sinks:
+  # int x, y; // x and y are tainted
+  # mySink(x, 0, 1); // It will warn
+  # mySink(0, 1, y); // It will warn
+  # mySink(0, x, 1); // It won't warn
+  - Name: mySink
+Args: [0, 2]
+
Index: lib/StaticAnalyzer/Checkers/Yaml.h
===
--- /dev/null
+++ lib/StaticAnalyzer/Checkers/Yaml.h
@@ -0,0 +1,36 @@
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/Support/YAMLTraits.h"
+
+/// Read the given file from the filesystem and parse it as a yaml file. The
+/// template parameter must have a yaml MappingTraits.
+template 
+llvm::Optional getConfiguration(clang::ento::CheckerManager &Mgr,
+   Checker *Chk, llvm::StringRef Option,
+   llvm::StringRef ConfigFile) {
+  if (ConfigFile.trim().empty())
+return {};
+
+  llvm::vfs::FileSystem *FS = llvm::vfs::getRealFileSystem().get();
+  llvm::ErrorOr> Buffer =
+  FS->getBufferForFile(ConfigFile.str());
+
+  if (std::error_code ec = Buffer.getError()) {
+Mgr.reportInvalidCheckerOptionValue(Chk, Option,
+"a valid filename instead of '" +
+std::string(ConfigFile) + "'");
+return {};
+  }
+
+  llvm::yaml::Input Input(Buffer.get()->getBuffer());
+  T Config;
+  Input >> Config;
+
+  if (std::error_code ec = Input.error()) {
+Mgr.reportInvalidCheckerOptionValue(Chk, Option,
+"a valid yaml file: " + ec.message());
+return {};
+  }
+
+  return Config;
+}
Index: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -15,16 +15,19 @@
 //===--===//
 
 #include "Taint.h"
-#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "Yaml.h"
 #include "clang/AST/Attr.h"
 #include "clang/Basic/Builtins.h"
+#includ

[PATCH] D59555: [analyzer] Add yaml parser to GenericTaintChecker

2019-07-17 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 updated this revision to Diff 210258.
boga95 marked an inline comment as done.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59555/new/

https://reviews.llvm.org/D59555

Files:
  include/clang/StaticAnalyzer/Checkers/Checkers.td
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  lib/StaticAnalyzer/Checkers/Yaml.h
  test/Analysis/Inputs/taint-generic-config.yaml
  test/Analysis/taint-generic.c

Index: test/Analysis/taint-generic.c
===
--- test/Analysis/taint-generic.c
+++ test/Analysis/taint-generic.c
@@ -1,5 +1,27 @@
-// RUN: %clang_analyze_cc1  -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -Wno-format-security -verify %s
-// RUN: %clang_analyze_cc1  -DFILE_IS_STRUCT -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -Wno-format-security -verify %s
+// RUN: %clang_analyze_cc1 -Wno-format-security -verify %s \
+// RUN:   -analyzer-checker=alpha.security.taint \
+// RUN:   -analyzer-checker=core \
+// RUN:   -analyzer-checker=alpha.security.ArrayBoundV2 \
+// RUN:   -analyzer-config \
+// RUN: alpha.security.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config.yaml
+
+// RUN: %clang_analyze_cc1 -Wno-format-security -verify %s \
+// RUN:   -DFILE_IS_STRUCT \
+// RUN:   -analyzer-checker=alpha.security.taint \
+// RUN:   -analyzer-checker=core \
+// RUN:   -analyzer-checker=alpha.security.ArrayBoundV2 \
+// RUN:   -analyzer-config \
+// RUN: alpha.security.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config.yaml
+
+// RUN: not %clang_analyze_cc1 -verify %s \
+// RUN:   -analyzer-checker=alpha.security.taint \
+// RUN:   -analyzer-config \
+// RUN: alpha.security.taint.TaintPropagation:Config=justguessit \
+// RUN:   2>&1 | FileCheck %s -check-prefix=CHECK-INVALID-FILE
+
+// CHECK-INVALID-FILE: (frontend): invalid input for checker option
+// CHECK-INVALID-FILE-SAME:'alpha.security.taint.TaintPropagation:Config',
+// CHECK-INVALID-FILE-SAME:that expects a valid filename
 
 int scanf(const char *restrict format, ...);
 char *gets(char *str);
Index: test/Analysis/Inputs/taint-generic-config.yaml
===
--- /dev/null
+++ test/Analysis/Inputs/taint-generic-config.yaml
@@ -0,0 +1,51 @@
+# A list of source/propagation function
+Propagations:
+  # int x = mySource1(); // x is tainted
+  - Name: mySource1
+DstArgs:  [-1] # Index for return value
+
+  # int x;
+  # mySource2(&x); // x is tainted
+  - Name: mySource2
+DstArgs:  [0]
+
+  # int x, y;
+  # myScanf("%d %d", &x, &y); // x and y are tainted
+  - Name:  myScanf
+VariadicType:  Dst
+VariadicIndex: 1
+
+  # int x; // x is tainted
+  # int y;
+  # myPropagator(x, &y); // y is tainted
+  - Name: myPropagator
+SrcArgs:  [0]
+DstArgs:  [1]
+
+  # constexpr unsigned size = 100;
+  # char buf[size];
+  # int x, y;
+  # int n = mySprintf(buf, size, "%d %d", x, y); // If size, x or y is tainted
+  # // the return value and the buf will be tainted
+  - Name:  mySnprintf
+SrcArgs:   [1]
+DstArgs:   [0, -1]
+VariadicType:  Src
+VariadicIndex: 3
+
+# A list of filter functions
+Filters:
+  # int x; // x is tainted
+  # myFilter(&x); // x is not tainted anymore
+  - Name: myFilter
+Args: [0]
+
+# A list of sink functions
+Sinks:
+  # int x, y; // x and y are tainted
+  # mySink(x, 0, 1); // It will warn
+  # mySink(0, 1, y); // It will warn
+  # mySink(0, x, 1); // It won't warn
+  - Name: mySink
+Args: [0, 2]
+
Index: lib/StaticAnalyzer/Checkers/Yaml.h
===
--- /dev/null
+++ lib/StaticAnalyzer/Checkers/Yaml.h
@@ -0,0 +1,48 @@
+//== Yaml.h --- -*- C++ -*--=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// This file contains a simple interface allow to open and parse yaml files.
+//
+//===--===//
+
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/Support/YAMLTraits.h"
+
+/// Read the given file from the filesystem and parse it as a yaml file. The
+/// template parameter must have a yaml MappingTraits.
+template 
+llvm::Optional getConfiguration(clang::ento::CheckerManager &Mgr,
+   Checker *Chk, llvm::StringRef Option,
+   llvm::StringRef ConfigFile) {
+  if (ConfigFile.trim().empty())
+return {};
+
+  llvm::vfs::FileSystem *FS = llvm::vfs::getRealFileSystem().get();
+  llvm::ErrorOr> Buffer =
+  FS->getBufferForFile(ConfigFile.st

[PATCH] D59555: [analyzer] Add yaml parser to GenericTaintChecker

2019-07-17 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 updated this revision to Diff 210260.
boga95 marked 2 inline comments as done.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59555/new/

https://reviews.llvm.org/D59555

Files:
  include/clang/StaticAnalyzer/Checkers/Checkers.td
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  lib/StaticAnalyzer/Checkers/Yaml.h
  test/Analysis/Inputs/taint-generic-config.yaml
  test/Analysis/taint-generic.c

Index: test/Analysis/taint-generic.c
===
--- test/Analysis/taint-generic.c
+++ test/Analysis/taint-generic.c
@@ -1,5 +1,27 @@
-// RUN: %clang_analyze_cc1  -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -Wno-format-security -verify %s
-// RUN: %clang_analyze_cc1  -DFILE_IS_STRUCT -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -Wno-format-security -verify %s
+// RUN: %clang_analyze_cc1 -Wno-format-security -verify %s \
+// RUN:   -analyzer-checker=alpha.security.taint \
+// RUN:   -analyzer-checker=core \
+// RUN:   -analyzer-checker=alpha.security.ArrayBoundV2 \
+// RUN:   -analyzer-config \
+// RUN: alpha.security.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config.yaml
+
+// RUN: %clang_analyze_cc1 -Wno-format-security -verify %s \
+// RUN:   -DFILE_IS_STRUCT \
+// RUN:   -analyzer-checker=alpha.security.taint \
+// RUN:   -analyzer-checker=core \
+// RUN:   -analyzer-checker=alpha.security.ArrayBoundV2 \
+// RUN:   -analyzer-config \
+// RUN: alpha.security.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config.yaml
+
+// RUN: not %clang_analyze_cc1 -verify %s \
+// RUN:   -analyzer-checker=alpha.security.taint \
+// RUN:   -analyzer-config \
+// RUN: alpha.security.taint.TaintPropagation:Config=justguessit \
+// RUN:   2>&1 | FileCheck %s -check-prefix=CHECK-INVALID-FILE
+
+// CHECK-INVALID-FILE: (frontend): invalid input for checker option
+// CHECK-INVALID-FILE-SAME:'alpha.security.taint.TaintPropagation:Config',
+// CHECK-INVALID-FILE-SAME:that expects a valid filename
 
 int scanf(const char *restrict format, ...);
 char *gets(char *str);
Index: test/Analysis/Inputs/taint-generic-config.yaml
===
--- /dev/null
+++ test/Analysis/Inputs/taint-generic-config.yaml
@@ -0,0 +1,51 @@
+# A list of source/propagation function
+Propagations:
+  # int x = mySource1(); // x is tainted
+  - Name: mySource1
+DstArgs:  [-1] # Index for return value
+
+  # int x;
+  # mySource2(&x); // x is tainted
+  - Name: mySource2
+DstArgs:  [0]
+
+  # int x, y;
+  # myScanf("%d %d", &x, &y); // x and y are tainted
+  - Name:  myScanf
+VariadicType:  Dst
+VariadicIndex: 1
+
+  # int x; // x is tainted
+  # int y;
+  # myPropagator(x, &y); // y is tainted
+  - Name: myPropagator
+SrcArgs:  [0]
+DstArgs:  [1]
+
+  # constexpr unsigned size = 100;
+  # char buf[size];
+  # int x, y;
+  # int n = mySprintf(buf, size, "%d %d", x, y); // If size, x or y is tainted
+  # // the return value and the buf will be tainted
+  - Name:  mySnprintf
+SrcArgs:   [1]
+DstArgs:   [0, -1]
+VariadicType:  Src
+VariadicIndex: 3
+
+# A list of filter functions
+Filters:
+  # int x; // x is tainted
+  # myFilter(&x); // x is not tainted anymore
+  - Name: myFilter
+Args: [0]
+
+# A list of sink functions
+Sinks:
+  # int x, y; // x and y are tainted
+  # mySink(x, 0, 1); // It will warn
+  # mySink(0, 1, y); // It will warn
+  # mySink(0, x, 1); // It won't warn
+  - Name: mySink
+Args: [0, 2]
+
Index: lib/StaticAnalyzer/Checkers/Yaml.h
===
--- /dev/null
+++ lib/StaticAnalyzer/Checkers/Yaml.h
@@ -0,0 +1,48 @@
+//== Yaml.h --- -*- C++ -*--=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// This file contains a simple interface allow to open and parse yaml files.
+//
+//===--===//
+
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/Support/YAMLTraits.h"
+
+/// Read the given file from the filesystem and parse it as a yaml file. The
+/// template parameter must have a yaml MappingTraits.
+template 
+llvm::Optional getConfiguration(clang::ento::CheckerManager &Mgr,
+   Checker *Chk, llvm::StringRef Option,
+   llvm::StringRef ConfigFile) {
+  if (ConfigFile.trim().empty())
+return {};
+
+  llvm::vfs::FileSystem *FS = llvm::vfs::getRealFileSystem().get();
+  llvm::ErrorOr> Buffer =
+  FS->getBufferForFile(ConfigFile.st

[PATCH] D59555: [analyzer] Add yaml parser to GenericTaintChecker

2019-07-18 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 updated this revision to Diff 210540.
boga95 marked 7 inline comments as done.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59555/new/

https://reviews.llvm.org/D59555

Files:
  include/clang/StaticAnalyzer/Checkers/Checkers.td
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  lib/StaticAnalyzer/Checkers/Yaml.h
  test/Analysis/Inputs/taint-generic-config-ill-formed.yaml
  test/Analysis/Inputs/taint-generic-config-invalid-arg.yaml
  test/Analysis/Inputs/taint-generic-config.yaml
  test/Analysis/taint-generic.c

Index: test/Analysis/taint-generic.c
===
--- test/Analysis/taint-generic.c
+++ test/Analysis/taint-generic.c
@@ -1,5 +1,49 @@
-// RUN: %clang_analyze_cc1  -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -Wno-format-security -verify %s
-// RUN: %clang_analyze_cc1  -DFILE_IS_STRUCT -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -Wno-format-security -verify %s
+// RUN: %clang_analyze_cc1 -Wno-format-security -verify %s \
+// RUN:   -analyzer-checker=alpha.security.taint \
+// RUN:   -analyzer-checker=core \
+// RUN:   -analyzer-checker=alpha.security.ArrayBoundV2 \
+// RUN:   -analyzer-config \
+// RUN: alpha.security.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config.yaml
+
+// RUN: %clang_analyze_cc1 -Wno-format-security -verify %s \
+// RUN:   -DFILE_IS_STRUCT \
+// RUN:   -analyzer-checker=alpha.security.taint \
+// RUN:   -analyzer-checker=core \
+// RUN:   -analyzer-checker=alpha.security.ArrayBoundV2 \
+// RUN:   -analyzer-config \
+// RUN: alpha.security.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config.yaml
+
+// RUN: not %clang_analyze_cc1 -verify %s \
+// RUN:   -analyzer-checker=alpha.security.taint \
+// RUN:   -analyzer-config \
+// RUN: alpha.security.taint.TaintPropagation:Config=justguessit \
+// RUN:   2>&1 | FileCheck %s -check-prefix=CHECK-INVALID-FILE
+
+// CHECK-INVALID-FILE: (frontend): invalid input for checker option
+// CHECK-INVALID-FILE-SAME:'alpha.security.taint.TaintPropagation:Config',
+// CHECK-INVALID-FILE-SAME:that expects a valid filename instead of
+// CHECK-INVALID-FILE-SAME:'justguessit'
+
+// RUN: not %clang_analyze_cc1 -verify %s \
+// RUN:   -analyzer-checker=alpha.security.taint \
+// RUN:   -analyzer-config \
+// RUN: alpha.security.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config-ill-formed.yaml \
+// RUN:   2>&1 | FileCheck %s -check-prefix=CHECK-ILL-FORMED
+
+// CHECK-ILL-FORMED: (frontend): invalid input for checker option
+// CHECK-ILL-FORMED-SAME:'alpha.security.taint.TaintPropagation:Config',
+// CHECK-ILL-FORMED-SAME:that expects a valid yaml file: Invalid argument
+
+// RUN: not %clang_analyze_cc1 -verify %s \
+// RUN:   -analyzer-checker=alpha.security.taint \
+// RUN:   -analyzer-config \
+// RUN: alpha.security.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config-invalid-arg.yaml \
+// RUN:   2>&1 | FileCheck %s -check-prefix=CHECK-INVALID-ARG
+
+// CHECK-INVALID-ARG: (frontend): invalid input for checker option
+// CHECK-INVALID-ARG-SAME:'alpha.security.taint.TaintPropagation:Config',
+// CHECK-INVALID-ARG-SAME:that expects an argument number for propagation
+// CHECK-INVALID-ARG-SAME:rules greater or equal to -1
 
 int scanf(const char *restrict format, ...);
 char *gets(char *str);
Index: test/Analysis/Inputs/taint-generic-config.yaml
===
--- /dev/null
+++ test/Analysis/Inputs/taint-generic-config.yaml
@@ -0,0 +1,50 @@
+# A list of source/propagation function
+Propagations:
+  # int x = mySource1(); // x is tainted
+  - Name: mySource1
+DstArgs:  [-1] # Index for return value
+
+  # int x;
+  # mySource2(&x); // x is tainted
+  - Name: mySource2
+DstArgs:  [0]
+
+  # int x, y;
+  # myScanf("%d %d", &x, &y); // x and y are tainted
+  - Name:  myScanf
+VariadicType:  Dst
+VariadicIndex: 1
+
+  # int x; // x is tainted
+  # int y;
+  # myPropagator(x, &y); // y is tainted
+  - Name: myPropagator
+SrcArgs:  [0]
+DstArgs:  [1]
+
+  # constexpr unsigned size = 100;
+  # char buf[size];
+  # int x, y;
+  # int n = mySprintf(buf, size, "%d %d", x, y); // If size, x or y is tainted
+  # // the return value and the buf will be tainted
+  - Name:  mySnprintf
+SrcArgs:   [1]
+DstArgs:   [0, -1]
+VariadicType:  Src
+VariadicIndex: 3
+
+# A list of filter functions
+Filters:
+  # int x; // x is tainted
+  # myFilter(&x); // x is not tainted anymore
+  - Name: myFilter
+Args: [0]
+
+# A list of sink functions
+Sinks:
+  # int x, y; // x and y are tainted
+  # mySink(x, 0, 1); // It will warn
+  # mySink(0, 1, y); // It will warn
+  # mySink(0, x, 1); // It won't warn
+  - Name: mySink
+Args: [0, 2]
Index: test/Analysis/Inputs/taint-generic-config-invalid-arg.y

[PATCH] D59555: [analyzer] Add yaml parser to GenericTaintChecker

2019-07-27 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 updated this revision to Diff 212065.
boga95 marked 16 inline comments as done.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59555/new/

https://reviews.llvm.org/D59555

Files:
  include/clang/StaticAnalyzer/Checkers/Checkers.td
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  lib/StaticAnalyzer/Checkers/Yaml.h
  test/Analysis/Inputs/taint-generic-config-ill-formed.yaml
  test/Analysis/Inputs/taint-generic-config-invalid-arg.yaml
  test/Analysis/Inputs/taint-generic-config.yaml
  test/Analysis/taint-generic.c

Index: test/Analysis/taint-generic.c
===
--- test/Analysis/taint-generic.c
+++ test/Analysis/taint-generic.c
@@ -1,5 +1,49 @@
-// RUN: %clang_analyze_cc1  -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -Wno-format-security -verify %s
-// RUN: %clang_analyze_cc1  -DFILE_IS_STRUCT -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -Wno-format-security -verify %s
+// RUN: %clang_analyze_cc1 -Wno-format-security -verify %s \
+// RUN:   -analyzer-checker=alpha.security.taint \
+// RUN:   -analyzer-checker=core \
+// RUN:   -analyzer-checker=alpha.security.ArrayBoundV2 \
+// RUN:   -analyzer-config \
+// RUN: alpha.security.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config.yaml
+
+// RUN: %clang_analyze_cc1 -Wno-format-security -verify %s \
+// RUN:   -DFILE_IS_STRUCT \
+// RUN:   -analyzer-checker=alpha.security.taint \
+// RUN:   -analyzer-checker=core \
+// RUN:   -analyzer-checker=alpha.security.ArrayBoundV2 \
+// RUN:   -analyzer-config \
+// RUN: alpha.security.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config.yaml
+
+// RUN: not %clang_analyze_cc1 -verify %s \
+// RUN:   -analyzer-checker=alpha.security.taint \
+// RUN:   -analyzer-config \
+// RUN: alpha.security.taint.TaintPropagation:Config=justguessit \
+// RUN:   2>&1 | FileCheck %s -check-prefix=CHECK-INVALID-FILE
+
+// CHECK-INVALID-FILE: (frontend): invalid input for checker option
+// CHECK-INVALID-FILE-SAME:'alpha.security.taint.TaintPropagation:Config',
+// CHECK-INVALID-FILE-SAME:that expects a valid filename instead of
+// CHECK-INVALID-FILE-SAME:'justguessit'
+
+// RUN: not %clang_analyze_cc1 -verify %s \
+// RUN:   -analyzer-checker=alpha.security.taint \
+// RUN:   -analyzer-config \
+// RUN: alpha.security.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config-ill-formed.yaml \
+// RUN:   2>&1 | FileCheck %s -check-prefix=CHECK-ILL-FORMED
+
+// CHECK-ILL-FORMED: (frontend): invalid input for checker option
+// CHECK-ILL-FORMED-SAME:'alpha.security.taint.TaintPropagation:Config',
+// CHECK-ILL-FORMED-SAME:that expects a valid yaml file: Invalid argument
+
+// RUN: not %clang_analyze_cc1 -verify %s \
+// RUN:   -analyzer-checker=alpha.security.taint \
+// RUN:   -analyzer-config \
+// RUN: alpha.security.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config-invalid-arg.yaml \
+// RUN:   2>&1 | FileCheck %s -check-prefix=CHECK-INVALID-ARG
+
+// CHECK-INVALID-ARG: (frontend): invalid input for checker option
+// CHECK-INVALID-ARG-SAME:'alpha.security.taint.TaintPropagation:Config',
+// CHECK-INVALID-ARG-SAME:that expects an argument number for propagation
+// CHECK-INVALID-ARG-SAME:rules greater or equal to -1
 
 int scanf(const char *restrict format, ...);
 char *gets(char *str);
Index: test/Analysis/Inputs/taint-generic-config.yaml
===
--- /dev/null
+++ test/Analysis/Inputs/taint-generic-config.yaml
@@ -0,0 +1,50 @@
+# A list of source/propagation function
+Propagations:
+  # int x = mySource1(); // x is tainted
+  - Name: mySource1
+DstArgs:  [-1] # Index for return value
+
+  # int x;
+  # mySource2(&x); // x is tainted
+  - Name: mySource2
+DstArgs:  [0]
+
+  # int x, y;
+  # myScanf("%d %d", &x, &y); // x and y are tainted
+  - Name:  myScanf
+VariadicType:  Dst
+VariadicIndex: 1
+
+  # int x; // x is tainted
+  # int y;
+  # myPropagator(x, &y); // y is tainted
+  - Name: myPropagator
+SrcArgs:  [0]
+DstArgs:  [1]
+
+  # constexpr unsigned size = 100;
+  # char buf[size];
+  # int x, y;
+  # int n = mySprintf(buf, size, "%d %d", x, y); // If size, x or y is tainted
+  # // the return value and the buf will be tainted
+  - Name:  mySnprintf
+SrcArgs:   [1]
+DstArgs:   [0, -1]
+VariadicType:  Src
+VariadicIndex: 3
+
+# A list of filter functions
+Filters:
+  # int x; // x is tainted
+  # myFilter(&x); // x is not tainted anymore
+  - Name: myFilter
+Args: [0]
+
+# A list of sink functions
+Sinks:
+  # int x, y; // x and y are tainted
+  # mySink(x, 0, 1); // It will warn
+  # mySink(0, 1, y); // It will warn
+  # mySink(0, x, 1); // It won't warn
+  - Name: mySink
+Args: [0, 2]
Index: test/Analysis/Inputs/taint-generic-config-invalid-arg.

[PATCH] D59555: [analyzer] Add yaml parser to GenericTaintChecker

2019-07-28 Thread Borsik Gábor via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL367190: [analyzer] Add yaml parser to GenericTaintChecker 
(authored by boga95, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D59555?vs=212065&id=212094#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59555/new/

https://reviews.llvm.org/D59555

Files:
  cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td
  cfe/trunk/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  cfe/trunk/lib/StaticAnalyzer/Checkers/Yaml.h
  cfe/trunk/test/Analysis/Inputs/taint-generic-config-ill-formed.yaml
  cfe/trunk/test/Analysis/Inputs/taint-generic-config-invalid-arg.yaml
  cfe/trunk/test/Analysis/Inputs/taint-generic-config.yaml
  cfe/trunk/test/Analysis/analyzer-config.c
  cfe/trunk/test/Analysis/taint-generic.c

Index: cfe/trunk/lib/StaticAnalyzer/Checkers/Yaml.h
===
--- cfe/trunk/lib/StaticAnalyzer/Checkers/Yaml.h
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/Yaml.h
@@ -0,0 +1,59 @@
+//== Yaml.h  -*- C++ -*--=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// This file defines convenience functions for handling YAML configuration files
+// for checkers/packages.
+//
+//===--===//
+
+#ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKER_YAML_H
+#define LLVM_CLANG_LIB_STATICANALYZER_CHECKER_YAML_H
+
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "llvm/Support/YAMLTraits.h"
+
+namespace clang {
+namespace ento {
+
+/// Read the given file from the filesystem and parse it as a yaml file. The
+/// template parameter must have a yaml MappingTraits.
+/// Emit diagnostic error in case of any failure.
+template 
+llvm::Optional getConfiguration(CheckerManager &Mgr, Checker *Chk,
+   StringRef Option, StringRef ConfigFile) {
+  if (ConfigFile.trim().empty())
+return None;
+
+  llvm::vfs::FileSystem *FS = llvm::vfs::getRealFileSystem().get();
+  llvm::ErrorOr> Buffer =
+  FS->getBufferForFile(ConfigFile.str());
+
+  if (std::error_code ec = Buffer.getError()) {
+Mgr.reportInvalidCheckerOptionValue(Chk, Option,
+"a valid filename instead of '" +
+std::string(ConfigFile) + "'");
+return None;
+  }
+
+  llvm::yaml::Input Input(Buffer.get()->getBuffer());
+  T Config;
+  Input >> Config;
+
+  if (std::error_code ec = Input.error()) {
+Mgr.reportInvalidCheckerOptionValue(Chk, Option,
+"a valid yaml file: " + ec.message());
+return None;
+  }
+
+  return Config;
+}
+
+} // namespace ento
+} // namespace clang
+
+#endif // LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_MOVE_H
Index: cfe/trunk/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- cfe/trunk/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -15,16 +15,18 @@
 //===--===//
 
 #include "Taint.h"
-#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "Yaml.h"
 #include "clang/AST/Attr.h"
 #include "clang/Basic/Builtins.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
 #include "clang/StaticAnalyzer/Core/Checker.h"
 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
-#include 
-#include 
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/YAMLTraits.h"
+#include 
 #include 
 
 using namespace clang;
@@ -44,14 +46,51 @@
 
   void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
 
-  void printState(raw_ostream &Out, ProgramStateRef State,
-  const char *NL, const char *Sep) const override;
+  void printState(raw_ostream &Out, ProgramStateRef State, const char *NL,
+  const char *Sep) const override;
 
-private:
-  static const unsigned InvalidArgIndex = UINT_MAX;
+  using ArgVector = SmallVector;
+  using SignedArgVector = SmallVector;
+
+  enum class VariadicType { None, Src, Dst };
+
+  /// Used to parse the configuration file.
+  struct TaintConfiguration {
+using NameArgsPair = std::pair;
+
+struct Propagation {
+  std::string Name;
+  

[PATCH] D59637: [analyzer] Use the custom propagation rules and sinks in GenericTaintChecker

2019-07-28 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 updated this revision to Diff 212119.
boga95 added a subscriber: steakhal.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59637/new/

https://reviews.llvm.org/D59637

Files:
  clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  clang/test/Analysis/taint-generic.c

Index: clang/test/Analysis/taint-generic.c
===
--- clang/test/Analysis/taint-generic.c
+++ clang/test/Analysis/taint-generic.c
@@ -338,3 +338,43 @@
   if (i < rhs)
 *(volatile int *) 0; // no-warning
 }
+
+
+// Test configuration
+int mySource1();
+void mySource2(int*);
+void myScanf(const char*, ...);
+int myPropagator(int, int*);
+int mySnprintf(char*, size_t, const char*, ...);
+void mySink(int, int, int);
+
+void testConfigurationSources1() {
+  int x = mySource1();
+  Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationSources2() {
+  int x;
+  mySource2(&x);
+  Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationSources3() {
+  int x, y;
+  myScanf("%d %d", &x, &y);
+  Buffer[y] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationPropagation() {
+  int x = mySource1();
+  int y;
+  myPropagator(x, &y);
+  Buffer[y] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationSinks() {
+  int x = mySource1();
+  mySink(x, 1, 2); // expected-warning {{Untrusted data is passed to a user defined sink}}
+  mySink(1, x, 2); // no-warning
+  mySink(1, 2, x); // expected-warning {{Untrusted data is passed to a user defined sink}}
+}
Index: clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -132,6 +132,11 @@
   bool checkTaintedBufferSize(const CallExpr *CE, const FunctionDecl *FDecl,
   CheckerContext &C) const;
 
+  /// Check if tainted data is used as a custom sink's parameter.
+  static const char MsgCustomSink[];
+  bool checkCustomSinks(const CallExpr *CE, StringRef Name,
+CheckerContext &C) const;
+
   /// Generate a report if the expression is tainted or points to tainted data.
   bool generateReportIfTainted(const Expr *E, const char Msg[],
CheckerContext &C) const;
@@ -175,7 +180,8 @@
 
 /// Get the propagation rule for a given function.
 static TaintPropagationRule
-getTaintPropagationRule(const FunctionDecl *FDecl, StringRef Name,
+getTaintPropagationRule(const GenericTaintChecker *Checker,
+const FunctionDecl *FDecl, StringRef Name,
 CheckerContext &C);
 
 void addSrcArg(unsigned A) { SrcArgs.push_back(A); }
@@ -240,6 +246,10 @@
 "Untrusted data is used to specify the buffer size "
 "(CERT/STR31-C. Guarantee that storage for strings has sufficient space "
 "for character data and the null terminator)";
+
+const char GenericTaintChecker::MsgCustomSink[] =
+"Untrusted data is passed to a user defined sink";
+;
 } // end of anonymous namespace
 
 using TaintConfig = GenericTaintChecker::TaintConfiguration;
@@ -330,7 +340,8 @@
 
 GenericTaintChecker::TaintPropagationRule
 GenericTaintChecker::TaintPropagationRule::getTaintPropagationRule(
-const FunctionDecl *FDecl, StringRef Name, CheckerContext &C) {
+const GenericTaintChecker *Checker, const FunctionDecl *FDecl,
+StringRef Name, CheckerContext &C) {
   // TODO: Currently, we might lose precision here: we always mark a return
   // value as tainted even if it's just a pointer, pointing to tainted data.
 
@@ -424,6 +435,10 @@
   // or smart memory copy:
   // - memccpy - copying until hitting a special character.
 
+  auto It = Checker->CustomPropagations.find(Name);
+  if (It != Checker->CustomPropagations.end())
+return It->getValue();
+
   return TaintPropagationRule();
 }
 
@@ -464,7 +479,7 @@
 
   // First, try generating a propagation rule for this function.
   TaintPropagationRule Rule =
-  TaintPropagationRule::getTaintPropagationRule(FDecl, Name, C);
+  TaintPropagationRule::getTaintPropagationRule(this, FDecl, Name, C);
   if (!Rule.isNull()) {
 State = Rule.process(CE, C);
 if (!State)
@@ -536,6 +551,9 @@
   if (checkTaintedBufferSize(CE, FDecl, C))
 return true;
 
+  if (checkCustomSinks(CE, Name, C))
+return true;
+
   return false;
 }
 
@@ -572,8 +590,12 @@
   // Check for taint in arguments.
   bool IsTainted = true;
   for (unsigned ArgNum : SrcArgs) {
-if (ArgNum >= CE->getNumArgs())
-  return State;
+if (ArgNum >= CE->getNumArgs()) {
+  StringRef Name = C.getCalleeName(C.getCalleeDecl(CE));
+  llvm::errs() << "Skip out of bound SrcArg: " << Name << ":" << ArgNum
+   << '\n';
+  continue;
+

[PATCH] D59637: [analyzer] Use the custom propagation rules and sinks in GenericTaintChecker

2019-07-31 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 marked 2 inline comments as done.
boga95 added a comment.

I think it shouldn't give compile error in case of incorrect configuration now 
(maybe warning) because:

- Without qualified names, I can create a code which cannot be configured 
properly.



- It can throw an error without configuration, for example:

  void read(int*); // There is an existing propagation rule for it

I suggest to let it unchanged now, and I will change it when the checker can 
handle qualified names.
On the other hand, I think we should make this type of error configurable (from 
the command line). So the user can select between warnings and errors.




Comment at: clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp:836
+   CheckerContext &C) const {
+  auto It = CustomSinks.find(Name);
+  if (It == CustomSinks.end())

Szelethus wrote:
> Hmmm, how do we do with qualified names (`MyClass::generateTaint()`, 
> `std::cin >>`)?
These patches focus on C style functions. I have implemented the uses of 
qualified names, but I intended to make a separate patch for that. 


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59637/new/

https://reviews.llvm.org/D59637



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D59637: [analyzer] Use the custom propagation rules and sinks in GenericTaintChecker

2019-08-14 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 updated this revision to Diff 215268.
boga95 marked an inline comment as done.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59637/new/

https://reviews.llvm.org/D59637

Files:
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  test/Analysis/taint-generic.c

Index: test/Analysis/taint-generic.c
===
--- test/Analysis/taint-generic.c
+++ test/Analysis/taint-generic.c
@@ -338,3 +338,43 @@
   if (i < rhs)
 *(volatile int *) 0; // no-warning
 }
+
+
+// Test configuration
+int mySource1();
+void mySource2(int*);
+void myScanf(const char*, ...);
+int myPropagator(int, int*);
+int mySnprintf(char*, size_t, const char*, ...);
+void mySink(int, int, int);
+
+void testConfigurationSources1() {
+  int x = mySource1();
+  Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationSources2() {
+  int x;
+  mySource2(&x);
+  Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationSources3() {
+  int x, y;
+  myScanf("%d %d", &x, &y);
+  Buffer[y] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationPropagation() {
+  int x = mySource1();
+  int y;
+  myPropagator(x, &y);
+  Buffer[y] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationSinks() {
+  int x = mySource1();
+  mySink(x, 1, 2); // expected-warning {{Untrusted data is passed to a user defined sink}}
+  mySink(1, x, 2); // no-warning
+  mySink(1, 2, x); // expected-warning {{Untrusted data is passed to a user defined sink}}
+}
Index: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -115,25 +115,30 @@
   static Optional getPointedToSVal(CheckerContext &C, const Expr *Arg);
 
   /// Check for CWE-134: Uncontrolled Format String.
-  static const char MsgUncontrolledFormatString[];
+  static const llvm::StringLiteral MsgUncontrolledFormatString;
   bool checkUncontrolledFormatString(const CallExpr *CE,
  CheckerContext &C) const;
 
   /// Check for:
   /// CERT/STR02-C. "Sanitize data passed to complex subsystems"
   /// CWE-78, "Failure to Sanitize Data into an OS Command"
-  static const char MsgSanitizeSystemArgs[];
+  static const llvm::StringLiteral MsgSanitizeSystemArgs;
   bool checkSystemCall(const CallExpr *CE, StringRef Name,
CheckerContext &C) const;
 
   /// Check if tainted data is used as a buffer size ins strn.. functions,
   /// and allocators.
-  static const char MsgTaintedBufferSize[];
+  static const llvm::StringLiteral MsgTaintedBufferSize;
   bool checkTaintedBufferSize(const CallExpr *CE, const FunctionDecl *FDecl,
   CheckerContext &C) const;
 
+  /// Check if tainted data is used as a custom sink's parameter.
+  static const llvm::StringLiteral MsgCustomSink;
+  bool checkCustomSinks(const CallExpr *CE, StringRef Name,
+CheckerContext &C) const;
+
   /// Generate a report if the expression is tainted or points to tainted data.
-  bool generateReportIfTainted(const Expr *E, const char Msg[],
+  bool generateReportIfTainted(const Expr *E, const StringRef Msg,
CheckerContext &C) const;
 
   /// A struct used to specify taint propagation rules for a function.
@@ -175,7 +180,8 @@
 
 /// Get the propagation rule for a given function.
 static TaintPropagationRule
-getTaintPropagationRule(const FunctionDecl *FDecl, StringRef Name,
+getTaintPropagationRule(const GenericTaintChecker *Checker,
+const FunctionDecl *FDecl, StringRef Name,
 CheckerContext &C);
 
 void addSrcArg(unsigned A) { SrcArgs.push_back(A); }
@@ -228,18 +234,22 @@
 const unsigned GenericTaintChecker::ReturnValueIndex;
 const unsigned GenericTaintChecker::InvalidArgIndex;
 
-const char GenericTaintChecker::MsgUncontrolledFormatString[] =
+const llvm::StringLiteral GenericTaintChecker::MsgUncontrolledFormatString =
 "Untrusted data is used as a format string "
 "(CWE-134: Uncontrolled Format String)";
 
-const char GenericTaintChecker::MsgSanitizeSystemArgs[] =
+const llvm::StringLiteral GenericTaintChecker::MsgSanitizeSystemArgs =
 "Untrusted data is passed to a system call "
 "(CERT/STR02-C. Sanitize data passed to complex subsystems)";
 
-const char GenericTaintChecker::MsgTaintedBufferSize[] =
+const llvm::StringLiteral GenericTaintChecker::MsgTaintedBufferSize =
 "Untrusted data is used to specify the buffer size "
 "(CERT/STR31-C. Guarantee that storage for strings has sufficient space "
 "for character data and the null terminator)";
+
+const llvm::StringLiteral GenericTaintChecker::MsgCustomSink =
+"Untrusted data is passed

[PATCH] D59555: [analyzer] Add yaml parser to GenericTaintChecker

2019-05-16 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 added a comment.

Sorry for the late answer, I was working on my thesis which is about taint 
analysis. During that, I implemented several cool features (namespaces, 
std::cin, std::string, etc.) for the checker. I will share them soon.

I thought about the API notes and I think it will fit very well into the 
checker. If my understanding is clear, the checker would be configured with 
attributes and/or a yaml file which contains the attributes. Therefore, the 
implementation will become simpler, because the checker will only read the 
attributes. I made a draft for the possible usage of the attributes:

  [[taint::dst(-1)]]
  int mySource(); // The return value will become tainted
  
  [[taint::src(0, 1)]] [[taint::dst(2)]]
  void myPropagator(int*, int*, int*);
  
  [[taint::src(0)]] [[taint::varDst(2)]]
  int myFscanf(FILE*, const char*, ...); // The variadic arguments will become 
tainted, if the first argument is tainted
  
  [[taint::dst(0, -1)]] [[taint::varSrc(2)]]
  int mySprintf(char*, const char*, ... ); // The first argument and the return 
value will become tainted, if any of the variadic arguments is tainted

I think we can use the current yaml configuration in order to not block my 
progress. I think most of the current implementation can be reused for the API 
notes. I will be able to easily change the interface after the API notes are 
ready.




Comment at: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp:73-75
   static const unsigned InvalidArgIndex = UINT_MAX;
   /// Denotes the return vale.
   static const unsigned ReturnValueIndex = UINT_MAX - 1;

Szelethus wrote:
> boga95 wrote:
> > Szelethus wrote:
> > > We should definitely change these, not only is the large integer number 
> > > impossible to remember, but this value could differ on different 
> > > platforms.
> > I tried to use int, but I got a lot of warnings because of the 
> > `getNumArgs()` returns an unsigned value.
> What warnings? I thought we have `-Wsign-conversion` disabled.
I got `-Wsign-compare` warnings, but it compiles. I will change it in the next 
[[ https://reviews.llvm.org/D59637 | review ]] because that's contains the yaml 
file and the related tests.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59555/new/

https://reviews.llvm.org/D59555



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D59555: [analyzer] Add yaml parser to GenericTaintChecker

2019-05-17 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 updated this revision to Diff 10.
boga95 edited the summary of this revision.
boga95 added a comment.

I changed the parsing, therefore the return value index is represented by -1.
I added a test configuration file and parse it when testing to prove the 
configuration doesn't break the code.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59555/new/

https://reviews.llvm.org/D59555

Files:
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  test/Analysis/Inputs/taint-generic-config.yaml
  test/Analysis/taint-generic.c

Index: test/Analysis/taint-generic.c
===
--- test/Analysis/taint-generic.c
+++ test/Analysis/taint-generic.c
@@ -1,5 +1,5 @@
-// RUN: %clang_analyze_cc1  -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -Wno-format-security -verify %s
-// RUN: %clang_analyze_cc1  -DFILE_IS_STRUCT -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -Wno-format-security -verify %s
+// RUN: %clang_analyze_cc1  -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -analyzer-config alpha.security.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config.yaml -Wno-format-security -verify %s
+// RUN: %clang_analyze_cc1  -DFILE_IS_STRUCT -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -analyzer-config alpha.security.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config.yaml -Wno-format-security -verify %s
 
 int scanf(const char *restrict format, ...);
 char *gets(char *str);
Index: test/Analysis/Inputs/taint-generic-config.yaml
===
--- /dev/null
+++ test/Analysis/Inputs/taint-generic-config.yaml
@@ -0,0 +1,51 @@
+# A list of source/propagation function
+Propagations:
+  # int x = mySource1(); // x is tainted
+  - Name: mySource1
+DstArgs:  [-1] # Index for return value
+
+  # int x;
+  # mySource2(&x); // x is tainted
+  - Name: mySource2
+DstArgs:  [0]
+
+  # int x, y;
+  # myScanf("%d %d", &x, &y); // x and y are tainted
+  - Name: myScanf
+VarType:  Dst
+VarIndex: 1
+
+  # int x; // x is tainted
+  # int y;
+  # myPropagator(x, &y); // y is tainted
+  - Name: myPropagator
+SrcArgs:  [0]
+DstArgs:  [1]
+
+  # constexpr unsigned size = 100;
+  # char buf[size];
+  # int x, y;
+  # int n = mySprintf(buf, size, "%d %d", x, y); // If size, x or y is tainted
+  # // the return value and the buf will be tainted
+  - Name: mySnprintf
+SrcArgs:  [1]
+DstArgs:  [0, -1]
+VarType:  Src
+VarIndex: 3
+
+# A list of filter functions
+Filters:
+  # int x; // x is tainted
+  # myFilter(&x); // x is not tainted anymore
+  - Name: myFilter
+Args: [0]
+
+# A list of sink functions
+Sinks:
+  # int x, y; // x and y are tainted
+  # mySink(x, 0, 1); // It will warn
+  # mySink(0, 1, y); // It will warn
+  # mySink(0, x, 1); // It won't warn
+  - Name: mySink
+Args: [0, 2]
+
Index: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -15,16 +15,17 @@
 //===--===//
 
 #include "Taint.h"
-#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
 #include "clang/AST/Attr.h"
 #include "clang/Basic/Builtins.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
 #include "clang/StaticAnalyzer/Core/Checker.h"
 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/YAMLTraits.h"
 #include 
-#include 
 #include 
 
 using namespace clang;
@@ -44,14 +45,45 @@
 
   void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
 
-  void printState(raw_ostream &Out, ProgramStateRef State,
-  const char *NL, const char *Sep) const override;
+  void printState(raw_ostream &Out, ProgramStateRef State, const char *NL,
+  const char *Sep) const override;
 
-private:
-  static const unsigned InvalidArgIndex = UINT_MAX;
+  using ArgVector = SmallVector;
+  using SignedArgVector = SmallVector;
+
+  enum class VariadicType { None, Src, Dst };
+
+  /// The ``TaintConfiguration`` is used to parse configuration file.
+  struct TaintConfiguration {
+using NameArgsPair = std::pair;
+
+struct Propagation {
+  std::string Name;
+  SignedArgVector SrcArgs;
+  SignedArgVector DstArgs;
+  VariadicType VarType;
+  unsigned VarIndex;
+};
+
+std::vector Propagations;
+std::vector Filters;
+std::vector Sinks;
+  };
+
+  /// Get and read the config file.
+  

[PATCH] D59555: [analyzer] Add yaml parser to GenericTaintChecker

2019-05-23 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 marked 3 inline comments as done.
boga95 added a comment.

I already thought about it. It would make the code much cleaner, but it would 
have a little performance impact (Does it matter?).
It's straightforward to read the supported functions from another yaml file. 
Besides that, it can support multiple config files too.




Comment at: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp:73-75
   static const unsigned InvalidArgIndex = UINT_MAX;
   /// Denotes the return vale.
   static const unsigned ReturnValueIndex = UINT_MAX - 1;

boga95 wrote:
> Szelethus wrote:
> > boga95 wrote:
> > > Szelethus wrote:
> > > > We should definitely change these, not only is the large integer number 
> > > > impossible to remember, but this value could differ on different 
> > > > platforms.
> > > I tried to use int, but I got a lot of warnings because of the 
> > > `getNumArgs()` returns an unsigned value.
> > What warnings? I thought we have `-Wsign-conversion` disabled.
> I got `-Wsign-compare` warnings, but it compiles. I will change it in the 
> next [[ https://reviews.llvm.org/D59637 | review ]] because that's contains 
> the yaml file and the related tests.
Now, this is just for internal representation. The -1 value is mapped to this.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59555/new/

https://reviews.llvm.org/D59555



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D55734: Refactoring GenericTaintChecker.cpp

2018-12-15 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 created this revision.
boga95 added reviewers: gerazo, xazax.hun, Szelethus, a_sidorin, dcoughlin, 
george.karpenkov.
Herald added subscribers: cfe-commits, rnkovacs.

Use a more optimal data structure to represent taint propagation rules.


Repository:
  rC Clang

https://reviews.llvm.org/D55734

Files:
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp

Index: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -23,6 +23,8 @@
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
 #include 
+#include 
+#include 
 
 using namespace clang;
 using namespace ento;
@@ -69,8 +71,8 @@
   static Optional getPointedToSVal(CheckerContext &C, const Expr *Arg);
 
   /// Functions defining the attack surface.
-  typedef ProgramStateRef (GenericTaintChecker::*FnCheck)(const CallExpr *,
-   CheckerContext &C) const;
+  using FnCheck = ProgramStateRef (GenericTaintChecker::*)(
+  const CallExpr *, CheckerContext &C) const;
   ProgramStateRef postScanf(const CallExpr *CE, CheckerContext &C) const;
   ProgramStateRef postSocket(const CallExpr *CE, CheckerContext &C) const;
   ProgramStateRef postRetTaint(const CallExpr *CE, CheckerContext &C) const;
@@ -100,7 +102,7 @@
   bool generateReportIfTainted(const Expr *E, const char Msg[],
CheckerContext &C) const;
 
-  typedef SmallVector ArgVector;
+  using ArgVector = SmallVector;
 
   /// A struct used to specify taint propagation rules for a function.
   ///
@@ -112,30 +114,27 @@
   /// ReturnValueIndex is added to the dst list, the return value will be
   /// tainted.
   struct TaintPropagationRule {
+enum class VariadicType { None, Src, Dst };
+
 /// List of arguments which can be taint sources and should be checked.
 ArgVector SrcArgs;
 /// List of arguments which should be tainted on function return.
 ArgVector DstArgs;
-// TODO: Check if using other data structures would be more optimal.
-
-TaintPropagationRule() {}
-
-TaintPropagationRule(unsigned SArg,
- unsigned DArg, bool TaintRet = false) {
-  SrcArgs.push_back(SArg);
-  DstArgs.push_back(DArg);
-  if (TaintRet)
-DstArgs.push_back(ReturnValueIndex);
-}
-
-TaintPropagationRule(unsigned SArg1, unsigned SArg2,
- unsigned DArg, bool TaintRet = false) {
-  SrcArgs.push_back(SArg1);
-  SrcArgs.push_back(SArg2);
-  DstArgs.push_back(DArg);
-  if (TaintRet)
-DstArgs.push_back(ReturnValueIndex);
-}
+/// Index for the first variadic parameter if exist.
+unsigned VariadicIndex;
+/// Show when a function has variadic parameters. If it has, it mark all
+/// of them as source or destination.
+VariadicType VarType;
+
+TaintPropagationRule()
+: VariadicIndex(InvalidArgIndex), VarType(VariadicType::None) {}
+
+TaintPropagationRule(std::initializer_list &&Src,
+ std::initializer_list &&Dst,
+ VariadicType Var = VariadicType::None,
+ unsigned VarIndex = InvalidArgIndex)
+: SrcArgs(std::move(Src)), DstArgs(std::move(Dst)),
+  VariadicIndex(VarIndex), VarType(Var) {}
 
 /// Get the propagation rule for a given function.
 static TaintPropagationRule
@@ -144,9 +143,12 @@
   CheckerContext &C);
 
 inline void addSrcArg(unsigned A) { SrcArgs.push_back(A); }
-inline void addDstArg(unsigned A)  { DstArgs.push_back(A); }
+inline void addDstArg(unsigned A) { DstArgs.push_back(A); }
 
-inline bool isNull() const { return SrcArgs.empty(); }
+inline bool isNull() const {
+  return SrcArgs.empty() && DstArgs.empty() &&
+ VariadicType::None == VarType;
+}
 
 inline bool isDestinationArgument(unsigned ArgNum) const {
   return (std::find(DstArgs.begin(),
@@ -169,7 +171,6 @@
 /// Pre-process a function which propagates taint according to the
 /// taint rule.
 ProgramStateRef process(const CallExpr *CE, CheckerContext &C) const;
-
   };
 };
 
@@ -206,26 +207,27 @@
   // value as tainted even if it's just a pointer, pointing to tainted data.
 
   // Check for exact name match for functions without builtin substitutes.
-  TaintPropagationRule Rule = llvm::StringSwitch(Name)
-.Case("atoi", TaintPropagationRule(0, ReturnValueIndex))
-.Case("atol", TaintPropagationRule(0, ReturnValueIndex))
-.Case("atoll", TaintPropagationRule(0, ReturnValueIndex))
-.Case("getc", TaintPropagationRule(0, ReturnValueIndex))
-.Case("fgetc", TaintPropagationRule(0, ReturnValueIndex))
-.Case("getc_unlocked", TaintPropagationRule(0, ReturnValueI

[PATCH] D55734: [analyzer] Refactoring GenericTaintChecker.cpp

2018-12-15 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 updated this revision to Diff 178351.
boga95 added a comment.

Upload diff with full context.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55734/new/

https://reviews.llvm.org/D55734

Files:
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp

Index: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -23,6 +23,8 @@
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
 #include 
+#include 
+#include 
 
 using namespace clang;
 using namespace ento;
@@ -69,8 +71,8 @@
   static Optional getPointedToSVal(CheckerContext &C, const Expr *Arg);
 
   /// Functions defining the attack surface.
-  typedef ProgramStateRef (GenericTaintChecker::*FnCheck)(const CallExpr *,
-   CheckerContext &C) const;
+  using FnCheck = ProgramStateRef (GenericTaintChecker::*)(
+  const CallExpr *, CheckerContext &C) const;
   ProgramStateRef postScanf(const CallExpr *CE, CheckerContext &C) const;
   ProgramStateRef postSocket(const CallExpr *CE, CheckerContext &C) const;
   ProgramStateRef postRetTaint(const CallExpr *CE, CheckerContext &C) const;
@@ -100,7 +102,7 @@
   bool generateReportIfTainted(const Expr *E, const char Msg[],
CheckerContext &C) const;
 
-  typedef SmallVector ArgVector;
+  using ArgVector = SmallVector;
 
   /// A struct used to specify taint propagation rules for a function.
   ///
@@ -112,30 +114,27 @@
   /// ReturnValueIndex is added to the dst list, the return value will be
   /// tainted.
   struct TaintPropagationRule {
+enum class VariadicType { None, Src, Dst };
+
 /// List of arguments which can be taint sources and should be checked.
 ArgVector SrcArgs;
 /// List of arguments which should be tainted on function return.
 ArgVector DstArgs;
-// TODO: Check if using other data structures would be more optimal.
-
-TaintPropagationRule() {}
-
-TaintPropagationRule(unsigned SArg,
- unsigned DArg, bool TaintRet = false) {
-  SrcArgs.push_back(SArg);
-  DstArgs.push_back(DArg);
-  if (TaintRet)
-DstArgs.push_back(ReturnValueIndex);
-}
-
-TaintPropagationRule(unsigned SArg1, unsigned SArg2,
- unsigned DArg, bool TaintRet = false) {
-  SrcArgs.push_back(SArg1);
-  SrcArgs.push_back(SArg2);
-  DstArgs.push_back(DArg);
-  if (TaintRet)
-DstArgs.push_back(ReturnValueIndex);
-}
+/// Index for the first variadic parameter if exist.
+unsigned VariadicIndex;
+/// Show when a function has variadic parameters. If it has, it mark all
+/// of them as source or destination.
+VariadicType VarType;
+
+TaintPropagationRule()
+: VariadicIndex(InvalidArgIndex), VarType(VariadicType::None) {}
+
+TaintPropagationRule(std::initializer_list &&Src,
+ std::initializer_list &&Dst,
+ VariadicType Var = VariadicType::None,
+ unsigned VarIndex = InvalidArgIndex)
+: SrcArgs(std::move(Src)), DstArgs(std::move(Dst)),
+  VariadicIndex(VarIndex), VarType(Var) {}
 
 /// Get the propagation rule for a given function.
 static TaintPropagationRule
@@ -144,9 +143,12 @@
   CheckerContext &C);
 
 inline void addSrcArg(unsigned A) { SrcArgs.push_back(A); }
-inline void addDstArg(unsigned A)  { DstArgs.push_back(A); }
+inline void addDstArg(unsigned A) { DstArgs.push_back(A); }
 
-inline bool isNull() const { return SrcArgs.empty(); }
+inline bool isNull() const {
+  return SrcArgs.empty() && DstArgs.empty() &&
+ VariadicType::None == VarType;
+}
 
 inline bool isDestinationArgument(unsigned ArgNum) const {
   return (std::find(DstArgs.begin(),
@@ -169,7 +171,6 @@
 /// Pre-process a function which propagates taint according to the
 /// taint rule.
 ProgramStateRef process(const CallExpr *CE, CheckerContext &C) const;
-
   };
 };
 
@@ -206,26 +207,27 @@
   // value as tainted even if it's just a pointer, pointing to tainted data.
 
   // Check for exact name match for functions without builtin substitutes.
-  TaintPropagationRule Rule = llvm::StringSwitch(Name)
-.Case("atoi", TaintPropagationRule(0, ReturnValueIndex))
-.Case("atol", TaintPropagationRule(0, ReturnValueIndex))
-.Case("atoll", TaintPropagationRule(0, ReturnValueIndex))
-.Case("getc", TaintPropagationRule(0, ReturnValueIndex))
-.Case("fgetc", TaintPropagationRule(0, ReturnValueIndex))
-.Case("getc_unlocked", TaintPropagationRule(0, ReturnValueIndex))
-.Case("getw", TaintPropagationRule(0, ReturnValueIndex))
-.Case("toupper", TaintPropagat

[PATCH] D55734: [analyzer] Refactoring GenericTaintChecker.cpp

2018-12-15 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 added a comment.

I use std::move which is in the ``.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55734/new/

https://reviews.llvm.org/D55734



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D55734: [analyzer] Refactoring GenericTaintChecker.cpp

2018-12-15 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 updated this revision to Diff 178368.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55734/new/

https://reviews.llvm.org/D55734

Files:
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp

Index: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -23,6 +23,8 @@
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
 #include 
+#include 
+#include 
 
 using namespace clang;
 using namespace ento;
@@ -69,8 +71,8 @@
   static Optional getPointedToSVal(CheckerContext &C, const Expr *Arg);
 
   /// Functions defining the attack surface.
-  typedef ProgramStateRef (GenericTaintChecker::*FnCheck)(const CallExpr *,
-   CheckerContext &C) const;
+  using FnCheck = ProgramStateRef (GenericTaintChecker::*)(
+  const CallExpr *, CheckerContext &C) const;
   ProgramStateRef postScanf(const CallExpr *CE, CheckerContext &C) const;
   ProgramStateRef postSocket(const CallExpr *CE, CheckerContext &C) const;
   ProgramStateRef postRetTaint(const CallExpr *CE, CheckerContext &C) const;
@@ -100,7 +102,7 @@
   bool generateReportIfTainted(const Expr *E, const char Msg[],
CheckerContext &C) const;
 
-  typedef SmallVector ArgVector;
+  using ArgVector = SmallVector;
 
   /// A struct used to specify taint propagation rules for a function.
   ///
@@ -112,30 +114,27 @@
   /// ReturnValueIndex is added to the dst list, the return value will be
   /// tainted.
   struct TaintPropagationRule {
+enum class VariadicType { None, Src, Dst };
+
 /// List of arguments which can be taint sources and should be checked.
 ArgVector SrcArgs;
 /// List of arguments which should be tainted on function return.
 ArgVector DstArgs;
-// TODO: Check if using other data structures would be more optimal.
-
-TaintPropagationRule() {}
-
-TaintPropagationRule(unsigned SArg,
- unsigned DArg, bool TaintRet = false) {
-  SrcArgs.push_back(SArg);
-  DstArgs.push_back(DArg);
-  if (TaintRet)
-DstArgs.push_back(ReturnValueIndex);
-}
-
-TaintPropagationRule(unsigned SArg1, unsigned SArg2,
- unsigned DArg, bool TaintRet = false) {
-  SrcArgs.push_back(SArg1);
-  SrcArgs.push_back(SArg2);
-  DstArgs.push_back(DArg);
-  if (TaintRet)
-DstArgs.push_back(ReturnValueIndex);
-}
+/// Index for the first variadic parameter if exist.
+unsigned VariadicIndex;
+/// Show when a function has variadic parameters. If it has, it mark all
+/// of them as source or destination.
+VariadicType VarType;
+
+TaintPropagationRule()
+: VariadicIndex(InvalidArgIndex), VarType(VariadicType::None) {}
+
+TaintPropagationRule(std::initializer_list &&Src,
+ std::initializer_list &&Dst,
+ VariadicType Var = VariadicType::None,
+ unsigned VarIndex = InvalidArgIndex)
+: SrcArgs(std::move(Src)), DstArgs(std::move(Dst)),
+  VariadicIndex(VarIndex), VarType(Var) {}
 
 /// Get the propagation rule for a given function.
 static TaintPropagationRule
@@ -144,9 +143,12 @@
   CheckerContext &C);
 
 inline void addSrcArg(unsigned A) { SrcArgs.push_back(A); }
-inline void addDstArg(unsigned A)  { DstArgs.push_back(A); }
+inline void addDstArg(unsigned A) { DstArgs.push_back(A); }
 
-inline bool isNull() const { return SrcArgs.empty(); }
+inline bool isNull() const {
+  return SrcArgs.empty() && DstArgs.empty() &&
+ VariadicType::None == VarType;
+}
 
 inline bool isDestinationArgument(unsigned ArgNum) const {
   return (std::find(DstArgs.begin(),
@@ -169,7 +171,6 @@
 /// Pre-process a function which propagates taint according to the
 /// taint rule.
 ProgramStateRef process(const CallExpr *CE, CheckerContext &C) const;
-
   };
 };
 
@@ -206,26 +207,27 @@
   // value as tainted even if it's just a pointer, pointing to tainted data.
 
   // Check for exact name match for functions without builtin substitutes.
-  TaintPropagationRule Rule = llvm::StringSwitch(Name)
-.Case("atoi", TaintPropagationRule(0, ReturnValueIndex))
-.Case("atol", TaintPropagationRule(0, ReturnValueIndex))
-.Case("atoll", TaintPropagationRule(0, ReturnValueIndex))
-.Case("getc", TaintPropagationRule(0, ReturnValueIndex))
-.Case("fgetc", TaintPropagationRule(0, ReturnValueIndex))
-.Case("getc_unlocked", TaintPropagationRule(0, ReturnValueIndex))
-.Case("getw", TaintPropagationRule(0, ReturnValueIndex))
-.Case("toupper", TaintPropagationRule(0, ReturnValueIndex))
-.Case("tolower", Taint

[PATCH] D55734: [analyzer] Refactoring GenericTaintChecker.cpp

2018-12-15 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 updated this revision to Diff 178373.
boga95 added a comment.

Rebase patch on the earlier version. Remove unnecessary inline specifiers. Fix 
typo.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55734/new/

https://reviews.llvm.org/D55734

Files:
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp

Index: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -23,15 +23,20 @@
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
 #include 
+#include 
+#include 
 
 using namespace clang;
 using namespace ento;
 
 namespace {
-class GenericTaintChecker : public Checker< check::PostStmt,
-check::PreStmt > {
+class GenericTaintChecker
+: public Checker, check::PreStmt> {
 public:
-  static void *getTag() { static int Tag; return &Tag; }
+  static void *getTag() {
+static int Tag;
+return &Tag;
+  }
 
   void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
 
@@ -43,7 +48,7 @@
   static const unsigned ReturnValueIndex = UINT_MAX - 1;
 
   mutable std::unique_ptr BT;
-  inline void initBugType() const {
+  void initBugType() const {
 if (!BT)
   BT.reset(new BugType(this, "Use of Untrusted Data", "Untrusted Data"));
   }
@@ -69,8 +74,8 @@
   static Optional getPointedToSVal(CheckerContext &C, const Expr *Arg);
 
   /// Functions defining the attack surface.
-  typedef ProgramStateRef (GenericTaintChecker::*FnCheck)(const CallExpr *,
-   CheckerContext &C) const;
+  using FnCheck = ProgramStateRef (GenericTaintChecker::*)(
+  const CallExpr *, CheckerContext &C) const;
   ProgramStateRef postScanf(const CallExpr *CE, CheckerContext &C) const;
   ProgramStateRef postSocket(const CallExpr *CE, CheckerContext &C) const;
   ProgramStateRef postRetTaint(const CallExpr *CE, CheckerContext &C) const;
@@ -100,7 +105,7 @@
   bool generateReportIfTainted(const Expr *E, const char Msg[],
CheckerContext &C) const;
 
-  typedef SmallVector ArgVector;
+  using ArgVector = SmallVector;
 
   /// A struct used to specify taint propagation rules for a function.
   ///
@@ -112,50 +117,48 @@
   /// ReturnValueIndex is added to the dst list, the return value will be
   /// tainted.
   struct TaintPropagationRule {
+enum class VariadicType { None, Src, Dst };
+
 /// List of arguments which can be taint sources and should be checked.
 ArgVector SrcArgs;
 /// List of arguments which should be tainted on function return.
 ArgVector DstArgs;
-// TODO: Check if using other data structures would be more optimal.
-
-TaintPropagationRule() {}
-
-TaintPropagationRule(unsigned SArg,
- unsigned DArg, bool TaintRet = false) {
-  SrcArgs.push_back(SArg);
-  DstArgs.push_back(DArg);
-  if (TaintRet)
-DstArgs.push_back(ReturnValueIndex);
-}
-
-TaintPropagationRule(unsigned SArg1, unsigned SArg2,
- unsigned DArg, bool TaintRet = false) {
-  SrcArgs.push_back(SArg1);
-  SrcArgs.push_back(SArg2);
-  DstArgs.push_back(DArg);
-  if (TaintRet)
-DstArgs.push_back(ReturnValueIndex);
-}
+/// Index for the first variadic parameter if exist.
+unsigned VariadicIndex;
+/// Show when a function has variadic parameters. If it has, it marks all
+/// of them as source or destination.
+VariadicType VarType;
+
+TaintPropagationRule()
+: VariadicIndex(InvalidArgIndex), VarType(VariadicType::None) {}
+
+TaintPropagationRule(std::initializer_list &&Src,
+ std::initializer_list &&Dst,
+ VariadicType Var = VariadicType::None,
+ unsigned VarIndex = InvalidArgIndex)
+: SrcArgs(std::move(Src)), DstArgs(std::move(Dst)),
+  VariadicIndex(VarIndex), VarType(Var) {}
 
 /// Get the propagation rule for a given function.
 static TaintPropagationRule
-  getTaintPropagationRule(const FunctionDecl *FDecl,
-  StringRef Name,
-  CheckerContext &C);
+getTaintPropagationRule(const FunctionDecl *FDecl, StringRef Name,
+CheckerContext &C);
 
-inline void addSrcArg(unsigned A) { SrcArgs.push_back(A); }
-inline void addDstArg(unsigned A)  { DstArgs.push_back(A); }
+void addSrcArg(unsigned A) { SrcArgs.push_back(A); }
+void addDstArg(unsigned A) { DstArgs.push_back(A); }
 
-inline bool isNull() const { return SrcArgs.empty(); }
+bool isNull() const {
+  return SrcArgs.empty() && DstArgs.empty() &&
+ VariadicType::None == VarType;
+}
 
-inline bool isDes

[PATCH] D54918: [analyzer] Apply clang-format to GenericTaintChecker.cpp

2018-12-17 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 added a comment.

I don't have commit access. Can you please do it on my behalf?


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D54918/new/

https://reviews.llvm.org/D54918



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D55734: [analyzer] Revise GenericTaintChecker's internal representation

2018-12-17 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 updated this revision to Diff 178537.
boga95 marked 4 inline comments as done.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55734/new/

https://reviews.llvm.org/D55734

Files:
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp

Index: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -23,15 +23,20 @@
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
 #include 
+#include 
+#include 
 
 using namespace clang;
 using namespace ento;
 
 namespace {
-class GenericTaintChecker : public Checker< check::PostStmt,
-check::PreStmt > {
+class GenericTaintChecker
+: public Checker, check::PreStmt> {
 public:
-  static void *getTag() { static int Tag; return &Tag; }
+  static void *getTag() {
+static int Tag;
+return &Tag;
+  }
 
   void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
 
@@ -43,7 +48,7 @@
   static const unsigned ReturnValueIndex = UINT_MAX - 1;
 
   mutable std::unique_ptr BT;
-  inline void initBugType() const {
+  void initBugType() const {
 if (!BT)
   BT.reset(new BugType(this, "Use of Untrusted Data", "Untrusted Data"));
   }
@@ -69,8 +74,8 @@
   static Optional getPointedToSVal(CheckerContext &C, const Expr *Arg);
 
   /// Functions defining the attack surface.
-  typedef ProgramStateRef (GenericTaintChecker::*FnCheck)(const CallExpr *,
-   CheckerContext &C) const;
+  using FnCheck = ProgramStateRef (GenericTaintChecker::*)(
+  const CallExpr *, CheckerContext &C) const;
   ProgramStateRef postScanf(const CallExpr *CE, CheckerContext &C) const;
   ProgramStateRef postSocket(const CallExpr *CE, CheckerContext &C) const;
   ProgramStateRef postRetTaint(const CallExpr *CE, CheckerContext &C) const;
@@ -100,7 +105,7 @@
   bool generateReportIfTainted(const Expr *E, const char Msg[],
CheckerContext &C) const;
 
-  typedef SmallVector ArgVector;
+  using ArgVector = SmallVector;
 
   /// A struct used to specify taint propagation rules for a function.
   ///
@@ -112,50 +117,48 @@
   /// ReturnValueIndex is added to the dst list, the return value will be
   /// tainted.
   struct TaintPropagationRule {
+enum class VariadicType { None, Src, Dst };
+
 /// List of arguments which can be taint sources and should be checked.
 ArgVector SrcArgs;
 /// List of arguments which should be tainted on function return.
 ArgVector DstArgs;
-// TODO: Check if using other data structures would be more optimal.
-
-TaintPropagationRule() {}
-
-TaintPropagationRule(unsigned SArg,
- unsigned DArg, bool TaintRet = false) {
-  SrcArgs.push_back(SArg);
-  DstArgs.push_back(DArg);
-  if (TaintRet)
-DstArgs.push_back(ReturnValueIndex);
-}
-
-TaintPropagationRule(unsigned SArg1, unsigned SArg2,
- unsigned DArg, bool TaintRet = false) {
-  SrcArgs.push_back(SArg1);
-  SrcArgs.push_back(SArg2);
-  DstArgs.push_back(DArg);
-  if (TaintRet)
-DstArgs.push_back(ReturnValueIndex);
-}
+/// Index for the first variadic parameter if exist.
+unsigned VariadicIndex;
+/// Show when a function has variadic parameters. If it has, it marks all
+/// of them as source or destination.
+VariadicType VarType;
+
+TaintPropagationRule()
+: VariadicIndex(InvalidArgIndex), VarType(VariadicType::None) {}
+
+TaintPropagationRule(std::initializer_list &&Src,
+ std::initializer_list &&Dst,
+ VariadicType Var = VariadicType::None,
+ unsigned VarIndex = InvalidArgIndex)
+: SrcArgs(std::move(Src)), DstArgs(std::move(Dst)),
+  VariadicIndex(VarIndex), VarType(Var) {}
 
 /// Get the propagation rule for a given function.
 static TaintPropagationRule
-  getTaintPropagationRule(const FunctionDecl *FDecl,
-  StringRef Name,
-  CheckerContext &C);
+getTaintPropagationRule(const FunctionDecl *FDecl, StringRef Name,
+CheckerContext &C);
 
-inline void addSrcArg(unsigned A) { SrcArgs.push_back(A); }
-inline void addDstArg(unsigned A)  { DstArgs.push_back(A); }
+void addSrcArg(unsigned A) { SrcArgs.push_back(A); }
+void addDstArg(unsigned A) { DstArgs.push_back(A); }
 
-inline bool isNull() const { return SrcArgs.empty(); }
+bool isNull() const {
+  return SrcArgs.empty() && DstArgs.empty() &&
+ VariadicType::None == VarType;
+}
 
-inline bool isDestinationArgument(unsigned ArgNum) const {
-  return (std::find(DstA

[PATCH] D55734: [analyzer] Revise GenericTaintChecker's internal representation

2018-12-23 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 updated this revision to Diff 179436.
boga95 marked 7 inline comments as done.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55734/new/

https://reviews.llvm.org/D55734

Files:
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp

Index: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -23,15 +23,20 @@
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
 #include 
+#include 
+#include 
 
 using namespace clang;
 using namespace ento;
 
 namespace {
-class GenericTaintChecker : public Checker< check::PostStmt,
-check::PreStmt > {
+class GenericTaintChecker
+: public Checker, check::PreStmt> {
 public:
-  static void *getTag() { static int Tag; return &Tag; }
+  static void *getTag() {
+static int Tag;
+return &Tag;
+  }
 
   void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
 
@@ -43,7 +48,7 @@
   static const unsigned ReturnValueIndex = UINT_MAX - 1;
 
   mutable std::unique_ptr BT;
-  inline void initBugType() const {
+  void initBugType() const {
 if (!BT)
   BT.reset(new BugType(this, "Use of Untrusted Data", "Untrusted Data"));
   }
@@ -69,8 +74,8 @@
   static Optional getPointedToSVal(CheckerContext &C, const Expr *Arg);
 
   /// Functions defining the attack surface.
-  typedef ProgramStateRef (GenericTaintChecker::*FnCheck)(const CallExpr *,
-   CheckerContext &C) const;
+  using FnCheck = ProgramStateRef (GenericTaintChecker::*)(
+  const CallExpr *, CheckerContext &C) const;
   ProgramStateRef postScanf(const CallExpr *CE, CheckerContext &C) const;
   ProgramStateRef postSocket(const CallExpr *CE, CheckerContext &C) const;
   ProgramStateRef postRetTaint(const CallExpr *CE, CheckerContext &C) const;
@@ -100,7 +105,7 @@
   bool generateReportIfTainted(const Expr *E, const char Msg[],
CheckerContext &C) const;
 
-  typedef SmallVector ArgVector;
+  using ArgVector = SmallVector;
 
   /// A struct used to specify taint propagation rules for a function.
   ///
@@ -112,50 +117,47 @@
   /// ReturnValueIndex is added to the dst list, the return value will be
   /// tainted.
   struct TaintPropagationRule {
+enum class VariadicType { None, Src, Dst };
+
 /// List of arguments which can be taint sources and should be checked.
 ArgVector SrcArgs;
 /// List of arguments which should be tainted on function return.
 ArgVector DstArgs;
-// TODO: Check if using other data structures would be more optimal.
-
-TaintPropagationRule() {}
-
-TaintPropagationRule(unsigned SArg,
- unsigned DArg, bool TaintRet = false) {
-  SrcArgs.push_back(SArg);
-  DstArgs.push_back(DArg);
-  if (TaintRet)
-DstArgs.push_back(ReturnValueIndex);
-}
-
-TaintPropagationRule(unsigned SArg1, unsigned SArg2,
- unsigned DArg, bool TaintRet = false) {
-  SrcArgs.push_back(SArg1);
-  SrcArgs.push_back(SArg2);
-  DstArgs.push_back(DArg);
-  if (TaintRet)
-DstArgs.push_back(ReturnValueIndex);
-}
+/// Index for the first variadic parameter if exist.
+unsigned VariadicIndex;
+/// Show when a function has variadic parameters. If it has, it marks all
+/// of them as source or destination.
+VariadicType VarType;
+
+TaintPropagationRule()
+: VariadicIndex(InvalidArgIndex), VarType(VariadicType::None) {}
+
+TaintPropagationRule(std::initializer_list &&Src,
+ std::initializer_list &&Dst,
+ VariadicType Var = VariadicType::None,
+ unsigned VarIndex = InvalidArgIndex)
+: SrcArgs(std::move(Src)), DstArgs(std::move(Dst)),
+  VariadicIndex(VarIndex), VarType(Var) {}
 
 /// Get the propagation rule for a given function.
 static TaintPropagationRule
-  getTaintPropagationRule(const FunctionDecl *FDecl,
-  StringRef Name,
-  CheckerContext &C);
+getTaintPropagationRule(const FunctionDecl *FDecl, StringRef Name,
+CheckerContext &C);
 
-inline void addSrcArg(unsigned A) { SrcArgs.push_back(A); }
-inline void addDstArg(unsigned A)  { DstArgs.push_back(A); }
+void addSrcArg(unsigned A) { SrcArgs.push_back(A); }
+void addDstArg(unsigned A) { DstArgs.push_back(A); }
 
-inline bool isNull() const { return SrcArgs.empty(); }
+bool isNull() const {
+  return SrcArgs.empty() && DstArgs.empty() &&
+ VariadicType::None == VarType;
+}
 
-inline bool isDestinationArgument(unsigned ArgNum) const {
-  return (std::find(DstA

[PATCH] D59516: [analyzer] Add custom filter functions for GenericTaintChecker

2019-09-12 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 updated this revision to Diff 219981.
boga95 marked 4 inline comments as done.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59516/new/

https://reviews.llvm.org/D59516

Files:
  clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  clang/lib/StaticAnalyzer/Checkers/Taint.cpp
  clang/lib/StaticAnalyzer/Checkers/Taint.h
  clang/test/Analysis/Inputs/taint-generic-config.yaml
  clang/test/Analysis/taint-generic.c

Index: clang/test/Analysis/taint-generic.c
===
--- clang/test/Analysis/taint-generic.c
+++ clang/test/Analysis/taint-generic.c
@@ -346,6 +346,12 @@
 void myScanf(const char*, ...);
 int myPropagator(int, int*);
 int mySnprintf(char*, size_t, const char*, ...);
+void myFilter1(int*);
+void myFilter2(int* x) {
+  if (*x < 0)
+*x = 0;
+}
+void myFilter3(const int*);
 void mySink(int, int, int);
 
 void testConfigurationSources1() {
@@ -372,6 +378,24 @@
   Buffer[y] = 1; // expected-warning {{Out of bound memory access }}
 }
 
+void testConfigurationFilter1() {
+  int x = mySource1();
+  myFilter1(&x);
+  Buffer[x] = 1; // no-warning
+}
+
+void testConfigurationFilter2() {
+  int x = mySource1();
+  myFilter2(&x);
+  Buffer[x] = 1; // no-warning
+}
+
+void testConfigurationFilter3() {
+  int x = mySource1();
+  myFilter3(&x);
+  Buffer[x] = 1; // no-warning
+}
+
 void testConfigurationSinks() {
   int x = mySource1();
   mySink(x, 1, 2);
Index: clang/test/Analysis/Inputs/taint-generic-config.yaml
===
--- clang/test/Analysis/Inputs/taint-generic-config.yaml
+++ clang/test/Analysis/Inputs/taint-generic-config.yaml
@@ -36,8 +36,12 @@
 # A list of filter functions
 Filters:
   # int x; // x is tainted
-  # myFilter(&x); // x is not tainted anymore
-  - Name: myFilter
+  # myFilter1(&x); // x is not tainted anymore
+  - Name: myFilter1
+Args: [0]
+  - Name: myFilter2
+Args: [0]
+  - Name: myFilter3
 Args: [0]
 
 # A list of sink functions
Index: clang/lib/StaticAnalyzer/Checkers/Taint.h
===
--- clang/lib/StaticAnalyzer/Checkers/Taint.h
+++ clang/lib/StaticAnalyzer/Checkers/Taint.h
@@ -24,37 +24,35 @@
 /// taint.
 using TaintTagType = unsigned;
 
-static constexpr TaintTagType TaintTagGeneric = 0;
+static constexpr TaintTagType TaintTagNotTainted = 0;
+static constexpr TaintTagType TaintTagGeneric = 1;
 
 /// Create a new state in which the value of the statement is marked as tainted.
-LLVM_NODISCARD ProgramStateRef
-addTaint(ProgramStateRef State, const Stmt *S, const LocationContext *LCtx,
- TaintTagType Kind = TaintTagGeneric);
+LLVM_NODISCARD ProgramStateRef addTaint(ProgramStateRef State, const Stmt *S,
+const LocationContext *LCtx,
+TaintTagType Kind = TaintTagGeneric);
 
 /// Create a new state in which the value is marked as tainted.
-LLVM_NODISCARD ProgramStateRef
-addTaint(ProgramStateRef State, SVal V,
- TaintTagType Kind = TaintTagGeneric);
+LLVM_NODISCARD ProgramStateRef addTaint(ProgramStateRef State, SVal V,
+TaintTagType Kind = TaintTagGeneric);
 
 /// Create a new state in which the symbol is marked as tainted.
-LLVM_NODISCARD ProgramStateRef
-addTaint(ProgramStateRef State, SymbolRef Sym,
- TaintTagType Kind = TaintTagGeneric);
+LLVM_NODISCARD ProgramStateRef addTaint(ProgramStateRef State, SymbolRef Sym,
+TaintTagType Kind = TaintTagGeneric);
 
 /// Create a new state in which the pointer represented by the region
 /// is marked as tainted.
-LLVM_NODISCARD ProgramStateRef
-addTaint(ProgramStateRef State, const MemRegion *R,
- TaintTagType Kind = TaintTagGeneric);
+LLVM_NODISCARD ProgramStateRef addTaint(ProgramStateRef State,
+const MemRegion *R,
+TaintTagType Kind = TaintTagGeneric);
 
 /// Create a new state in a which a sub-region of a given symbol is tainted.
 /// This might be necessary when referring to regions that can not have an
 /// individual symbol, e.g. if they are represented by the default binding of
 /// a LazyCompoundVal.
-LLVM_NODISCARD ProgramStateRef
-addPartialTaint(ProgramStateRef State,
-SymbolRef ParentSym, const SubRegion *SubRegion,
-TaintTagType Kind = TaintTagGeneric);
+LLVM_NODISCARD ProgramStateRef addPartialTaint(
+ProgramStateRef State, SymbolRef ParentSym, const SubRegion *SubRegion,
+TaintTagType Kind = TaintTagGeneric);
 
 /// Check if the statement has a tainted value in the given state.
 bool isTainted(ProgramStateRef State, const Stmt *S,
@@ -99,4 +97,3 @@
 } // namespace clang
 
 #endif
-
Index: clang/lib/StaticAnalyzer/Checkers/Taint.cpp
===
--- clang/lib/S

[PATCH] D59516: [analyzer] Add custom filter functions for GenericTaintChecker

2019-09-16 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 updated this revision to Diff 220385.
boga95 marked 4 inline comments as done.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59516/new/

https://reviews.llvm.org/D59516

Files:
  clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  clang/lib/StaticAnalyzer/Checkers/Taint.cpp
  clang/lib/StaticAnalyzer/Checkers/Taint.h
  clang/test/Analysis/Inputs/taint-generic-config.yaml
  clang/test/Analysis/taint-generic.c

Index: clang/test/Analysis/taint-generic.c
===
--- clang/test/Analysis/taint-generic.c
+++ clang/test/Analysis/taint-generic.c
@@ -56,6 +56,8 @@
 extern FILE *stdin;
 #endif
 
+#define bool int
+
 int fscanf(FILE *restrict stream, const char *restrict format, ...);
 int sprintf(char *str, const char *format, ...);
 void setproctitle(const char *fmt, ...);
@@ -346,6 +348,7 @@
 void myScanf(const char*, ...);
 int myPropagator(int, int*);
 int mySnprintf(char*, size_t, const char*, ...);
+bool isOutOfRange(const int*);
 void mySink(int, int, int);
 
 void testConfigurationSources1() {
@@ -372,6 +375,13 @@
   Buffer[y] = 1; // expected-warning {{Out of bound memory access }}
 }
 
+void testConfigurationFilter() {
+  int x = mySource1();
+  if (isOutOfRange(&x)) // the filter function
+return;
+  Buffer[x] = 1; // no-warning
+}
+
 void testConfigurationSinks() {
   int x = mySource1();
   mySink(x, 1, 2);
Index: clang/test/Analysis/Inputs/taint-generic-config.yaml
===
--- clang/test/Analysis/Inputs/taint-generic-config.yaml
+++ clang/test/Analysis/Inputs/taint-generic-config.yaml
@@ -36,8 +36,8 @@
 # A list of filter functions
 Filters:
   # int x; // x is tainted
-  # myFilter(&x); // x is not tainted anymore
-  - Name: myFilter
+  # isOutOfRange(&x); // x is not tainted anymore
+  - Name: isOutOfRange
 Args: [0]
 
 # A list of sink functions
Index: clang/lib/StaticAnalyzer/Checkers/Taint.h
===
--- clang/lib/StaticAnalyzer/Checkers/Taint.h
+++ clang/lib/StaticAnalyzer/Checkers/Taint.h
@@ -27,34 +27,39 @@
 static constexpr TaintTagType TaintTagGeneric = 0;
 
 /// Create a new state in which the value of the statement is marked as tainted.
-LLVM_NODISCARD ProgramStateRef
-addTaint(ProgramStateRef State, const Stmt *S, const LocationContext *LCtx,
- TaintTagType Kind = TaintTagGeneric);
+LLVM_NODISCARD ProgramStateRef addTaint(ProgramStateRef State, const Stmt *S,
+const LocationContext *LCtx,
+TaintTagType Kind = TaintTagGeneric);
 
 /// Create a new state in which the value is marked as tainted.
-LLVM_NODISCARD ProgramStateRef
-addTaint(ProgramStateRef State, SVal V,
- TaintTagType Kind = TaintTagGeneric);
+LLVM_NODISCARD ProgramStateRef addTaint(ProgramStateRef State, SVal V,
+TaintTagType Kind = TaintTagGeneric);
 
 /// Create a new state in which the symbol is marked as tainted.
-LLVM_NODISCARD ProgramStateRef
-addTaint(ProgramStateRef State, SymbolRef Sym,
- TaintTagType Kind = TaintTagGeneric);
+LLVM_NODISCARD ProgramStateRef addTaint(ProgramStateRef State, SymbolRef Sym,
+TaintTagType Kind = TaintTagGeneric);
 
 /// Create a new state in which the pointer represented by the region
 /// is marked as tainted.
-LLVM_NODISCARD ProgramStateRef
-addTaint(ProgramStateRef State, const MemRegion *R,
- TaintTagType Kind = TaintTagGeneric);
+LLVM_NODISCARD ProgramStateRef addTaint(ProgramStateRef State,
+const MemRegion *R,
+TaintTagType Kind = TaintTagGeneric);
+
+LLVM_NODISCARD ProgramStateRef removeTaint(ProgramStateRef State, SVal V);
+
+LLVM_NODISCARD ProgramStateRef removeTaint(ProgramStateRef State,
+   const MemRegion *R);
+
+LLVM_NODISCARD ProgramStateRef removeTaint(ProgramStateRef State,
+   SymbolRef Sym);
 
 /// Create a new state in a which a sub-region of a given symbol is tainted.
 /// This might be necessary when referring to regions that can not have an
 /// individual symbol, e.g. if they are represented by the default binding of
 /// a LazyCompoundVal.
-LLVM_NODISCARD ProgramStateRef
-addPartialTaint(ProgramStateRef State,
-SymbolRef ParentSym, const SubRegion *SubRegion,
-TaintTagType Kind = TaintTagGeneric);
+LLVM_NODISCARD ProgramStateRef addPartialTaint(
+ProgramStateRef State, SymbolRef ParentSym, const SubRegion *SubRegion,
+TaintTagType Kind = TaintTagGeneric);
 
 /// Check if the statement has a tainted value in the given state.
 bool isTainted(ProgramStateRef State, const Stmt *S,
@@ -99,4 +104,3 @@
 } // namespace clang
 
 #endif
-
Index: clang/lib/StaticAnalyzer/Checkers/Tain

[PATCH] D52281: [clang-tidy] Add modernize check to use std::invoke in generic code

2019-09-17 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 abandoned this revision.
boga95 marked 4 inline comments as done.
boga95 added inline comments.



Comment at: clang-tidy/modernize/ReplaceGenericFunctorCallCheck.cpp:72
+
+const Expr *Obj = BinOp->getLHS();
+const std::string ObjName =

I found an interesting behavior with source location:

```
const SourceManager *Source = Result.SourceManager;

const char *StartPos = Source->getCharacterData(Obj->getLocStart());
const char *EndPos = Source->getCharacterData(Obj->getLocEnd());
```
`StartPos` and `EndPos` point to the exact same location. Is this the expected 
behavior or it is a bug?



Comment at: clang-tidy/modernize/ReplaceGenericFunctorCallCheck.cpp:70
+const auto *Paren = dyn_cast(MFunctor->getCallee());
+const auto *BinOp = dyn_cast(Paren->getSubExpr());
+

aaron.ballman wrote:
> How do you know `Paren` won't be null? If it cannot be null, please use 
> `cast<>` instead, otherwise, you should be checking for null before 
> dereferencing.
It cannot be null because of the matcher.



Comment at: test/clang-tidy/modernize-replace-generic-functor-call.cpp:24
+template 
+void func2(T func) {
+  func(1);

JonasToth wrote:
> Please add tests that include the usage of macros to do the function call.
> In my opinions these should be excluded from the FIXITs and only the warning 
> should be emitted.
Please show me some example of that.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D52281/new/

https://reviews.llvm.org/D52281



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D52281: [clang-tidy] Add modernize check to use std::invoke in generic code

2019-09-18 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 marked an inline comment as done.
boga95 added a comment.

Resolving the problems properly seemed quite difficult. I just finished 
university and started to work, therefore I don't have enough free time to 
finish the checker. Sorry about that.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D52281/new/

https://reviews.llvm.org/D52281



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D59516: [analyzer] Add custom filter functions for GenericTaintChecker

2019-10-03 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 marked 7 inline comments as done.
boga95 added a comment.

Ping




Comment at: clang/test/Analysis/taint-generic.c:393-397
+void testConfigurationFilter3() {
+  int x = mySource1();
+  myFilter3(&x);
+  Buffer[x] = 1; // no-warning
+}

NoQ wrote:
> In this example `myFilter3` promises not to alter the value of `x` due to 
> `const`-qualifier on the pointee type of the parameter. Additionally, the 
> function has no chance of preventing the program from reaching the buffer 
> overflow line, other than crashing the program (given that it's C and there 
> are no exceptions). Therefore i'd say this is also a false negative.
> 
> A better motivational example that doesn't immediately look like a false 
> negative may look like this:
> ```lang=c
> void testConfigurationFilter3() {
>   int x = mySource1();
>   if (isOutOfRange(x)) // the filter function
> return;
>   Buffer[x] = 1; // no-warning
> }
> ```
> In this case the function looks at the value of `x` (there's really no need 
> to pass it by pointer) and notifies the caller through its return value that 
> it is unsafe to access the buffer with such index. This is probably the only 
> situation where a "filter" annotation is actually worth it.
It could work with C++ despite it hasn't supported any specific feature (yet).

I pass it by `const int*` because it currently doesn't support the value 
semantics :(. It has been already in my TODO list.



Comment at: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp:53-56
+  void Profile(llvm::FoldingSetNodeID &ID) const {
+ID.AddInteger(Arg);
+ID.AddInteger(TagType);
+  }

Szelethus wrote:
> Interesting, isn't this predefined for `std::pair`?
Unfortunately, it's not. 



Comment at: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp:474-476
+  const FunctionDecl *FDecl = C.getCalleeDecl(CE);
+  if (!FDecl || FDecl->getKind() != Decl::Function)
+return;

Szelethus wrote:
> When do these happen? For implicit functions in C? 
For example, a lambda doesn't have an FunctionDecl.



Comment at: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp:478-480
+  StringRef Name = C.getCalleeName(FDecl);
+  if (Name.empty())
+return;

Szelethus wrote:
> And this? Lambdas maybe?
I haven't found any example of this. It's just a copy-paste refactoring so I 
don't know the intentions behind that.

I think the checker should work perfectly without it.



Comment at: lib/StaticAnalyzer/Checkers/Taint.h:25-28
 using TaintTagType = unsigned;
 
-static constexpr TaintTagType TaintTagGeneric = 0;
+static constexpr TaintTagType TaintTagNotTainted = 0;
+static constexpr TaintTagType TaintTagGeneric = 1;

Szelethus wrote:
> Is there a **very** good reason behind us not using an `enum` instead?
Unfortunately, enums cannot put into FoldingSet. It has to be a primitive type 
or a struct with the necessary functions. I can use enums and cast them to 
unsigned and back, but it isn't convenient.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59516/new/

https://reviews.llvm.org/D59516



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D44143: [clang-tidy] Create properly seeded random generator check

2018-04-27 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 updated this revision to Diff 144336.

https://reviews.llvm.org/D44143

Files:
  clang-tidy/cert/CERTTidyModule.cpp
  clang-tidy/cert/CMakeLists.txt
  clang-tidy/cert/ProperlySeededRandomGeneratorCheck.cpp
  clang-tidy/cert/ProperlySeededRandomGeneratorCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/cert-msc32-c.rst
  docs/clang-tidy/checks/cert-msc51-cpp.rst
  test/clang-tidy/cert-msc32-c.c
  test/clang-tidy/cert-msc51-cpp.cpp

Index: test/clang-tidy/cert-msc51-cpp.cpp
===
--- /dev/null
+++ test/clang-tidy/cert-msc51-cpp.cpp
@@ -0,0 +1,201 @@
+// RUN: %check_clang_tidy %s cert-msc51-cpp %t -- -config="{CheckOptions: [{key: cert-msc51-cpp.DisallowedSeedTypes, value: 'some_type,time_t'}]}" -- -std=c++11
+
+namespace std {
+
+template 
+struct linear_congruential_engine {
+  linear_congruential_engine(int _ = 0);
+  void seed(int _ = 0);
+};
+using default_random_engine = linear_congruential_engine;
+
+using size_t = int;
+template 
+struct mersenne_twister_engine {
+  mersenne_twister_engine(int _ = 0);
+  void seed(int _ = 0);
+};
+using mt19937 = mersenne_twister_engine;
+
+template 
+struct subtract_with_carry_engine {
+  subtract_with_carry_engine(int _ = 0);
+  void seed(int _ = 0);
+};
+using ranlux24_base = subtract_with_carry_engine;
+
+template 
+struct discard_block_engine {
+  discard_block_engine();
+  discard_block_engine(int _);
+  void seed();
+  void seed(int _);
+};
+using ranlux24 = discard_block_engine;
+
+template 
+struct independent_bits_engine {
+  independent_bits_engine();
+  independent_bits_engine(int _);
+  void seed();
+  void seed(int _);
+};
+using independent_bits = independent_bits_engine;
+
+template 
+struct shuffle_order_engine {
+  shuffle_order_engine();
+  shuffle_order_engine(int _);
+  void seed();
+  void seed(int _);
+};
+using shuffle_order = shuffle_order_engine;
+
+struct random_device {
+  random_device();
+  int operator()();
+};
+} // namespace std
+
+using time_t = unsigned int;
+time_t time(time_t *t);
+
+void f() {
+  const int seed = 2;
+  time_t t;
+
+  // One instantiation for every engine
+  std::default_random_engine engine1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+  std::default_random_engine engine2(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::default_random_engine engine3(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::default_random_engine engine4(time(&t));
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine1.seed();
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+  engine1.seed(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine1.seed(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine1.seed(time(&t));
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+
+  std::mt19937 engine5;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+  std::mt19937 engine6(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::mt19937 engine7(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::mt19937 engine8(time(&t));
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine5.seed();
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+  engine5.seed(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine5.seed(seed);
+  // CHECK-MESSAGES: :[

[PATCH] D44143: [clang-tidy] Create properly seeded random generator check

2018-06-25 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 updated this revision to Diff 152778.
boga95 marked 3 inline comments as done.
boga95 added a comment.

Add std::srand check to C++ tests. Format patch.


https://reviews.llvm.org/D44143

Files:
  clang-tidy/cert/CERTTidyModule.cpp
  clang-tidy/cert/CMakeLists.txt
  clang-tidy/cert/ProperlySeededRandomGeneratorCheck.cpp
  clang-tidy/cert/ProperlySeededRandomGeneratorCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/cert-msc32-c.rst
  docs/clang-tidy/checks/cert-msc51-cpp.rst
  test/clang-tidy/cert-msc32-c.c
  test/clang-tidy/cert-msc51-cpp.cpp

Index: test/clang-tidy/cert-msc51-cpp.cpp
===
--- /dev/null
+++ test/clang-tidy/cert-msc51-cpp.cpp
@@ -0,0 +1,210 @@
+// RUN: %check_clang_tidy %s cert-msc51-cpp %t -- -config="{CheckOptions: [{key: cert-msc51-cpp.DisallowedSeedTypes, value: 'some_type,time_t'}]}" -- -std=c++11
+
+namespace std {
+
+void srand(int seed);
+
+template 
+struct linear_congruential_engine {
+  linear_congruential_engine(int _ = 0);
+  void seed(int _ = 0);
+};
+using default_random_engine = linear_congruential_engine;
+
+using size_t = int;
+template 
+struct mersenne_twister_engine {
+  mersenne_twister_engine(int _ = 0);
+  void seed(int _ = 0);
+};
+using mt19937 = mersenne_twister_engine;
+
+template 
+struct subtract_with_carry_engine {
+  subtract_with_carry_engine(int _ = 0);
+  void seed(int _ = 0);
+};
+using ranlux24_base = subtract_with_carry_engine;
+
+template 
+struct discard_block_engine {
+  discard_block_engine();
+  discard_block_engine(int _);
+  void seed();
+  void seed(int _);
+};
+using ranlux24 = discard_block_engine;
+
+template 
+struct independent_bits_engine {
+  independent_bits_engine();
+  independent_bits_engine(int _);
+  void seed();
+  void seed(int _);
+};
+using independent_bits = independent_bits_engine;
+
+template 
+struct shuffle_order_engine {
+  shuffle_order_engine();
+  shuffle_order_engine(int _);
+  void seed();
+  void seed(int _);
+};
+using shuffle_order = shuffle_order_engine;
+
+struct random_device {
+  random_device();
+  int operator()();
+};
+} // namespace std
+
+using time_t = unsigned int;
+time_t time(time_t *t);
+
+void f() {
+  const int seed = 2;
+  time_t t;
+
+  std::srand(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::srand(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::srand(time(&t));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+
+  // One instantiation for every engine
+  std::default_random_engine engine1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+  std::default_random_engine engine2(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::default_random_engine engine3(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::default_random_engine engine4(time(&t));
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine1.seed();
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+  engine1.seed(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine1.seed(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine1.seed(time(&t));
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+
+  std::mt19937 engine5;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+  std::mt19937 engine6(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::mt19937 engine7(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with 

[PATCH] D44143: [clang-tidy] Create properly seeded random generator check

2018-06-27 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 updated this revision to Diff 153169.
boga95 marked 3 inline comments as done.

https://reviews.llvm.org/D44143

Files:
  clang-tidy/cert/CERTTidyModule.cpp
  clang-tidy/cert/CMakeLists.txt
  clang-tidy/cert/ProperlySeededRandomGeneratorCheck.cpp
  clang-tidy/cert/ProperlySeededRandomGeneratorCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/cert-msc32-c.rst
  docs/clang-tidy/checks/cert-msc51-cpp.rst
  test/clang-tidy/cert-msc32-c.c
  test/clang-tidy/cert-msc51-cpp.cpp

Index: test/clang-tidy/cert-msc51-cpp.cpp
===
--- /dev/null
+++ test/clang-tidy/cert-msc51-cpp.cpp
@@ -0,0 +1,210 @@
+// RUN: %check_clang_tidy %s cert-msc51-cpp %t -- -config="{CheckOptions: [{key: cert-msc51-cpp.DisallowedSeedTypes, value: 'some_type,time_t'}]}" -- -std=c++11
+
+namespace std {
+
+void srand(int seed);
+
+template 
+struct linear_congruential_engine {
+  linear_congruential_engine(int _ = 0);
+  void seed(int _ = 0);
+};
+using default_random_engine = linear_congruential_engine;
+
+using size_t = int;
+template 
+struct mersenne_twister_engine {
+  mersenne_twister_engine(int _ = 0);
+  void seed(int _ = 0);
+};
+using mt19937 = mersenne_twister_engine;
+
+template 
+struct subtract_with_carry_engine {
+  subtract_with_carry_engine(int _ = 0);
+  void seed(int _ = 0);
+};
+using ranlux24_base = subtract_with_carry_engine;
+
+template 
+struct discard_block_engine {
+  discard_block_engine();
+  discard_block_engine(int _);
+  void seed();
+  void seed(int _);
+};
+using ranlux24 = discard_block_engine;
+
+template 
+struct independent_bits_engine {
+  independent_bits_engine();
+  independent_bits_engine(int _);
+  void seed();
+  void seed(int _);
+};
+using independent_bits = independent_bits_engine;
+
+template 
+struct shuffle_order_engine {
+  shuffle_order_engine();
+  shuffle_order_engine(int _);
+  void seed();
+  void seed(int _);
+};
+using shuffle_order = shuffle_order_engine;
+
+struct random_device {
+  random_device();
+  int operator()();
+};
+} // namespace std
+
+using time_t = unsigned int;
+time_t time(time_t *t);
+
+void f() {
+  const int seed = 2;
+  time_t t;
+
+  std::srand(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::srand(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::srand(time(&t));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+
+  // One instantiation for every engine
+  std::default_random_engine engine1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+  std::default_random_engine engine2(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::default_random_engine engine3(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::default_random_engine engine4(time(&t));
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine1.seed();
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+  engine1.seed(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine1.seed(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine1.seed(time(&t));
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+
+  std::mt19937 engine5;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+  std::mt19937 engine6(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::mt19937 engine7(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51

[PATCH] D44143: [clang-tidy] Create properly seeded random generator check

2018-06-27 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 updated this revision to Diff 153172.
boga95 marked 3 inline comments as done.

https://reviews.llvm.org/D44143

Files:
  clang-tidy/cert/CERTTidyModule.cpp
  clang-tidy/cert/CMakeLists.txt
  clang-tidy/cert/ProperlySeededRandomGeneratorCheck.cpp
  clang-tidy/cert/ProperlySeededRandomGeneratorCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/cert-msc32-c.rst
  docs/clang-tidy/checks/cert-msc51-cpp.rst
  test/clang-tidy/cert-msc32-c.c
  test/clang-tidy/cert-msc51-cpp.cpp

Index: test/clang-tidy/cert-msc51-cpp.cpp
===
--- /dev/null
+++ test/clang-tidy/cert-msc51-cpp.cpp
@@ -0,0 +1,210 @@
+// RUN: %check_clang_tidy %s cert-msc51-cpp %t -- -config="{CheckOptions: [{key: cert-msc51-cpp.DisallowedSeedTypes, value: 'some_type,time_t'}]}" -- -std=c++11
+
+namespace std {
+
+void srand(int seed);
+
+template 
+struct linear_congruential_engine {
+  linear_congruential_engine(int _ = 0);
+  void seed(int _ = 0);
+};
+using default_random_engine = linear_congruential_engine;
+
+using size_t = int;
+template 
+struct mersenne_twister_engine {
+  mersenne_twister_engine(int _ = 0);
+  void seed(int _ = 0);
+};
+using mt19937 = mersenne_twister_engine;
+
+template 
+struct subtract_with_carry_engine {
+  subtract_with_carry_engine(int _ = 0);
+  void seed(int _ = 0);
+};
+using ranlux24_base = subtract_with_carry_engine;
+
+template 
+struct discard_block_engine {
+  discard_block_engine();
+  discard_block_engine(int _);
+  void seed();
+  void seed(int _);
+};
+using ranlux24 = discard_block_engine;
+
+template 
+struct independent_bits_engine {
+  independent_bits_engine();
+  independent_bits_engine(int _);
+  void seed();
+  void seed(int _);
+};
+using independent_bits = independent_bits_engine;
+
+template 
+struct shuffle_order_engine {
+  shuffle_order_engine();
+  shuffle_order_engine(int _);
+  void seed();
+  void seed(int _);
+};
+using shuffle_order = shuffle_order_engine;
+
+struct random_device {
+  random_device();
+  int operator()();
+};
+} // namespace std
+
+using time_t = unsigned int;
+time_t time(time_t *t);
+
+void f() {
+  const int seed = 2;
+  time_t t;
+
+  std::srand(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::srand(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::srand(time(&t));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+
+  // One instantiation for every engine
+  std::default_random_engine engine1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+  std::default_random_engine engine2(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::default_random_engine engine3(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::default_random_engine engine4(time(&t));
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine1.seed();
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+  engine1.seed(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine1.seed(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine1.seed(time(&t));
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+
+  std::mt19937 engine5;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+  std::mt19937 engine6(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::mt19937 engine7(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51

[PATCH] D44143: [clang-tidy] Create properly seeded random generator check

2018-07-01 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 updated this revision to Diff 153655.

https://reviews.llvm.org/D44143

Files:
  clang-tidy/cert/CERTTidyModule.cpp
  clang-tidy/cert/CMakeLists.txt
  clang-tidy/cert/ProperlySeededRandomGeneratorCheck.cpp
  clang-tidy/cert/ProperlySeededRandomGeneratorCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/cert-msc32-c.rst
  docs/clang-tidy/checks/cert-msc51-cpp.rst
  test/clang-tidy/cert-msc32-c.c
  test/clang-tidy/cert-msc51-cpp.cpp

Index: test/clang-tidy/cert-msc51-cpp.cpp
===
--- /dev/null
+++ test/clang-tidy/cert-msc51-cpp.cpp
@@ -0,0 +1,210 @@
+// RUN: %check_clang_tidy %s cert-msc51-cpp %t -- -config="{CheckOptions: [{key: cert-msc51-cpp.DisallowedSeedTypes, value: 'some_type,time_t'}]}" -- -std=c++11
+
+namespace std {
+
+void srand(int seed);
+
+template 
+struct linear_congruential_engine {
+  linear_congruential_engine(int _ = 0);
+  void seed(int _ = 0);
+};
+using default_random_engine = linear_congruential_engine;
+
+using size_t = int;
+template 
+struct mersenne_twister_engine {
+  mersenne_twister_engine(int _ = 0);
+  void seed(int _ = 0);
+};
+using mt19937 = mersenne_twister_engine;
+
+template 
+struct subtract_with_carry_engine {
+  subtract_with_carry_engine(int _ = 0);
+  void seed(int _ = 0);
+};
+using ranlux24_base = subtract_with_carry_engine;
+
+template 
+struct discard_block_engine {
+  discard_block_engine();
+  discard_block_engine(int _);
+  void seed();
+  void seed(int _);
+};
+using ranlux24 = discard_block_engine;
+
+template 
+struct independent_bits_engine {
+  independent_bits_engine();
+  independent_bits_engine(int _);
+  void seed();
+  void seed(int _);
+};
+using independent_bits = independent_bits_engine;
+
+template 
+struct shuffle_order_engine {
+  shuffle_order_engine();
+  shuffle_order_engine(int _);
+  void seed();
+  void seed(int _);
+};
+using shuffle_order = shuffle_order_engine;
+
+struct random_device {
+  random_device();
+  int operator()();
+};
+} // namespace std
+
+using time_t = unsigned int;
+time_t time(time_t *t);
+
+void f() {
+  const int seed = 2;
+  time_t t;
+
+  std::srand(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::srand(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::srand(time(&t));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+
+  // One instantiation for every engine
+  std::default_random_engine engine1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+  std::default_random_engine engine2(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::default_random_engine engine3(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::default_random_engine engine4(time(&t));
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine1.seed();
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+  engine1.seed(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine1.seed(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  engine1.seed(time(&t));
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp]
+
+  std::mt19937 engine5;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp]
+  std::mt19937 engine6(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::mt19937 engine7(seed);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp]
+  std::mt19937 engine8(time(&t));

[PATCH] D44143: [clang-tidy] Create properly seeded random generator check

2018-07-04 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 added a comment.

How can I commit it?




Comment at: docs/clang-tidy/checks/cert-msc51-cpp.rst:7
+This check flags all pseudo-random number engines, engine adaptor
+instantiations and `srand()` when initialized or seeded with default argument,
+constant expression or any user-configurable type. Pseudo-random number

aaron.ballman wrote:
> Please add double backticks around `srand()` instead of single backticks.
Should I use double backticks in release notes too?


https://reviews.llvm.org/D44143



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D59516: [analyzer] Add custom filter functions for GenericTaintChecker

2019-10-09 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 marked 2 inline comments as done.
boga95 added a comment.

Ping


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59516/new/

https://reviews.llvm.org/D59516



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D71524: [analyzer] Support tainted objects in GenericTaintChecker

2020-04-12 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 updated this revision to Diff 256839.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D71524/new/

https://reviews.llvm.org/D71524

Files:
  clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  clang/lib/StaticAnalyzer/Checkers/Taint.cpp
  clang/test/Analysis/Inputs/system-header-simulator-cxx.h
  clang/test/Analysis/diagnostics/explicit-suppression.cpp
  clang/test/Analysis/taint-generic.cpp

Index: clang/test/Analysis/taint-generic.cpp
===
--- clang/test/Analysis/taint-generic.cpp
+++ clang/test/Analysis/taint-generic.cpp
@@ -1,5 +1,7 @@
 // RUN: %clang_analyze_cc1  -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -analyzer-config alpha.security.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config.yaml -Wno-format-security -verify -std=c++11 %s
 
+#include "Inputs/system-header-simulator-cxx.h"
+
 #define BUFSIZE 10
 int Buffer[BUFSIZE];
 
@@ -124,3 +126,64 @@
   foo.myMemberScanf("%d", &x);
   Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
 }
+
+// Test I/O
+void testCin() {
+  int x, y;
+  std::cin >> x >> y;
+  Buffer[y] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testWcin() {
+  int x, y;
+  std::wcin >> x >> y;
+  Buffer[y] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void mySink(const std::string &, int, const char *);
+
+void testFstream() {
+  std::string str;
+  std::ifstream file("example.txt");
+  file >> str;
+  mySink(str, 0, ""); // expected-warning {{Untrusted data is passed to a user-defined sink}}
+}
+
+void testIfstream() {
+  std::string str;
+  std::fstream file("example.txt");
+  file >> str;
+  mySink(str, 0, ""); // expected-warning {{Untrusted data is passed to a user-defined sink}}
+}
+
+void testStdstring() {
+  std::string str1;
+  std::cin >> str1;
+
+  std::string &str2 = str1;
+  mySink(str2, 0, ""); // expected-warning {{Untrusted data is passed to a user-defined sink}}
+
+  const std::string &str3 = str1;
+  mySink(str3, 0, ""); // expected-warning {{Untrusted data is passed to a user-defined sink}}
+}
+
+void testTaintedThis() {
+  std::string str;
+  mySink(std::string(), 0, str.c_str()); // no-warning
+
+  std::cin >> str;
+  mySink(std::string(), 0, str.c_str()); // expected-warning {{Untrusted data is passed to a user-defined sink}}
+}
+
+void testOverloadedAssignmentOp() {
+  std::string str1, str2;
+  std::cin >> str1;
+  str2 = str1;
+  mySink(str2, 0, ""); // expected-warning {{Untrusted data is passed to a user-defined sink}}
+}
+
+void testGetline() {
+  std::string str;
+  std::getline(std::cin, str);
+  mySink(str, 0, ""); // expected-warning {{Untrusted data is passed to a user-defined sink}}
+}
Index: clang/test/Analysis/diagnostics/explicit-suppression.cpp
===
--- clang/test/Analysis/diagnostics/explicit-suppression.cpp
+++ clang/test/Analysis/diagnostics/explicit-suppression.cpp
@@ -19,6 +19,6 @@
 void testCopyNull(C *I, C *E) {
   std::copy(I, E, (C *)0);
 #ifndef SUPPRESSED
-  // expected-warning@../Inputs/system-header-simulator-cxx.h:699 {{Called C++ object pointer is null}}
+  // expected-warning@../Inputs/system-header-simulator-cxx.h:742 {{Called C++ object pointer is null}}
 #endif
 }
Index: clang/test/Analysis/Inputs/system-header-simulator-cxx.h
===
--- clang/test/Analysis/Inputs/system-header-simulator-cxx.h
+++ clang/test/Analysis/Inputs/system-header-simulator-cxx.h
@@ -579,6 +579,9 @@
 void resize(size_type count);
 void shrink_to_fit();
 void swap(basic_string &other);
+  private:
+unsigned size;
+char *ptr;
   };
 
   typedef basic_string string;
@@ -588,6 +591,46 @@
   typedef basic_string u32string;
 #endif
 
+  template 
+  class char_traits {};
+
+  class ios_base {};
+
+  template  >
+  class basic_ios : public ios_base {};
+
+  template  >
+  class basic_istream : virtual public basic_ios {};
+  template  >
+  class basic_ostream : virtual public basic_ios {};
+
+  using istream = basic_istream;
+  using ostream = basic_ostream;
+  using wistream = basic_istream;
+
+  istream &operator>>(istream &is, int &val);
+  wistream &operator>>(wistream &is, int &val);
+
+  extern istream cin;
+  extern istream wcin;
+
+  template  >
+  class basic_fstream : public basic_istream, public basic_ostream {
+  public:
+basic_fstream(const char *) {}
+  };
+  template  >
+  class basic_ifstream : public basic_istream {
+  public:
+basic_ifstream(const char *) {}
+  };
+
+  using ifstream = basic_ifstream;
+  using fstream = basic_ifstream;
+
+  istream &operator>>(istream &is, string &val);
+  istream &getline(istream &is, string &str);
+
   class exception {
   public:
 exception() throw();
Index: clang/lib/StaticAnalyzer/Checkers/Taint.cpp
===
--- clang/l

[PATCH] D59637: [analyzer] Use the custom propagation rules and sinks in GenericTaintChecker

2019-08-30 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 added a comment.

Should I do anything or it is ready?


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59637/new/

https://reviews.llvm.org/D59637



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D59637: [analyzer] Use the custom propagation rules and sinks in GenericTaintChecker

2019-09-02 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 updated this revision to Diff 218395.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59637/new/

https://reviews.llvm.org/D59637

Files:
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  test/Analysis/taint-generic.c

Index: test/Analysis/taint-generic.c
===
--- test/Analysis/taint-generic.c
+++ test/Analysis/taint-generic.c
@@ -338,3 +338,43 @@
   if (i < rhs)
 *(volatile int *) 0; // no-warning
 }
+
+
+// Test configuration
+int mySource1();
+void mySource2(int*);
+void myScanf(const char*, ...);
+int myPropagator(int, int*);
+int mySnprintf(char*, size_t, const char*, ...);
+void mySink(int, int, int);
+
+void testConfigurationSources1() {
+  int x = mySource1();
+  Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationSources2() {
+  int x;
+  mySource2(&x);
+  Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationSources3() {
+  int x, y;
+  myScanf("%d %d", &x, &y);
+  Buffer[y] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationPropagation() {
+  int x = mySource1();
+  int y;
+  myPropagator(x, &y);
+  Buffer[y] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationSinks() {
+  int x = mySource1();
+  mySink(x, 1, 2); // expected-warning {{Untrusted data is passed to a user-defined sink}}
+  mySink(1, x, 2); // no-warning
+  mySink(1, 2, x); // expected-warning {{Untrusted data is passed to a user-defined sink}}
+}
Index: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -115,25 +115,38 @@
   static Optional getPointedToSVal(CheckerContext &C, const Expr *Arg);
 
   /// Check for CWE-134: Uncontrolled Format String.
-  static const char MsgUncontrolledFormatString[];
+  static constexpr llvm::StringLiteral MsgUncontrolledFormatString =
+  "Untrusted data is used as a format string "
+  "(CWE-134: Uncontrolled Format String)";
   bool checkUncontrolledFormatString(const CallExpr *CE,
  CheckerContext &C) const;
 
   /// Check for:
   /// CERT/STR02-C. "Sanitize data passed to complex subsystems"
   /// CWE-78, "Failure to Sanitize Data into an OS Command"
-  static const char MsgSanitizeSystemArgs[];
+  static constexpr llvm::StringLiteral MsgSanitizeSystemArgs =
+  "Untrusted data is passed to a system call "
+  "(CERT/STR02-C. Sanitize data passed to complex subsystems)";
   bool checkSystemCall(const CallExpr *CE, StringRef Name,
CheckerContext &C) const;
 
   /// Check if tainted data is used as a buffer size ins strn.. functions,
   /// and allocators.
-  static const char MsgTaintedBufferSize[];
+  static constexpr llvm::StringLiteral MsgTaintedBufferSize =
+  "Untrusted data is used to specify the buffer size "
+  "(CERT/STR31-C. Guarantee that storage for strings has sufficient space "
+  "for character data and the null terminator)";
   bool checkTaintedBufferSize(const CallExpr *CE, const FunctionDecl *FDecl,
   CheckerContext &C) const;
 
+  /// Check if tainted data is used as a custom sink's parameter.
+  static constexpr llvm::StringLiteral MsgCustomSink =
+  "Untrusted data is passed to a user-defined sink";
+  bool checkCustomSinks(const CallExpr *CE, StringRef Name,
+CheckerContext &C) const;
+
   /// Generate a report if the expression is tainted or points to tainted data.
-  bool generateReportIfTainted(const Expr *E, const char Msg[],
+  bool generateReportIfTainted(const Expr *E, const StringRef Msg,
CheckerContext &C) const;
 
   /// A struct used to specify taint propagation rules for a function.
@@ -175,7 +188,8 @@
 
 /// Get the propagation rule for a given function.
 static TaintPropagationRule
-getTaintPropagationRule(const FunctionDecl *FDecl, StringRef Name,
+getTaintPropagationRule(const GenericTaintChecker *Checker,
+const FunctionDecl *FDecl, StringRef Name,
 CheckerContext &C);
 
 void addSrcArg(unsigned A) { SrcArgs.push_back(A); }
@@ -227,19 +241,6 @@
 
 const unsigned GenericTaintChecker::ReturnValueIndex;
 const unsigned GenericTaintChecker::InvalidArgIndex;
-
-const char GenericTaintChecker::MsgUncontrolledFormatString[] =
-"Untrusted data is used as a format string "
-"(CWE-134: Uncontrolled Format String)";
-
-const char GenericTaintChecker::MsgSanitizeSystemArgs[] =
-"Untrusted data is passed to a system call "
-"(CERT/STR02-C. Sanitize data passed to complex subsystems)";
-
-const char GenericTaintChecker::MsgTaintedBufferSize[] =
-"Untrusted data is used to specify the buffer s

[PATCH] D59637: [analyzer] Use the custom propagation rules and sinks in GenericTaintChecker

2019-09-06 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 updated this revision to Diff 219172.
boga95 marked 7 inline comments as done.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59637/new/

https://reviews.llvm.org/D59637

Files:
  clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  clang/test/Analysis/taint-generic.c

Index: clang/test/Analysis/taint-generic.c
===
--- clang/test/Analysis/taint-generic.c
+++ clang/test/Analysis/taint-generic.c
@@ -338,3 +338,45 @@
   if (i < rhs)
 *(volatile int *) 0; // no-warning
 }
+
+
+// Test configuration
+int mySource1();
+void mySource2(int*);
+void myScanf(const char*, ...);
+int myPropagator(int, int*);
+int mySnprintf(char*, size_t, const char*, ...);
+void mySink(int, int, int);
+
+void testConfigurationSources1() {
+  int x = mySource1();
+  Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationSources2() {
+  int x;
+  mySource2(&x);
+  Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationSources3() {
+  int x, y;
+  myScanf("%d %d", &x, &y);
+  Buffer[y] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationPropagation() {
+  int x = mySource1();
+  int y;
+  myPropagator(x, &y);
+  Buffer[y] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationSinks() {
+  int x = mySource1();
+  mySink(x, 1, 2);
+  // expected-warning@-1 {{Untrusted data is passed to a user-defined sink}}
+  mySink(1, x, 2); // no-warning
+  mySink(1, 2, x);
+  // expected-warning@-1 {{Untrusted data is passed to a user-defined sink}}
+}
Index: clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -115,27 +115,44 @@
   static Optional getPointedToSVal(CheckerContext &C, const Expr *Arg);
 
   /// Check for CWE-134: Uncontrolled Format String.
-  static const char MsgUncontrolledFormatString[];
+  static constexpr llvm::StringLiteral MsgUncontrolledFormatString =
+  "Untrusted data is used as a format string "
+  "(CWE-134: Uncontrolled Format String)";
   bool checkUncontrolledFormatString(const CallExpr *CE,
  CheckerContext &C) const;
 
   /// Check for:
   /// CERT/STR02-C. "Sanitize data passed to complex subsystems"
   /// CWE-78, "Failure to Sanitize Data into an OS Command"
-  static const char MsgSanitizeSystemArgs[];
+  static constexpr llvm::StringLiteral MsgSanitizeSystemArgs =
+  "Untrusted data is passed to a system call "
+  "(CERT/STR02-C. Sanitize data passed to complex subsystems)";
   bool checkSystemCall(const CallExpr *CE, StringRef Name,
CheckerContext &C) const;
 
   /// Check if tainted data is used as a buffer size ins strn.. functions,
   /// and allocators.
-  static const char MsgTaintedBufferSize[];
+  static constexpr llvm::StringLiteral MsgTaintedBufferSize =
+  "Untrusted data is used to specify the buffer size "
+  "(CERT/STR31-C. Guarantee that storage for strings has sufficient space "
+  "for character data and the null terminator)";
   bool checkTaintedBufferSize(const CallExpr *CE, const FunctionDecl *FDecl,
   CheckerContext &C) const;
 
+  /// Check if tainted data is used as a custom sink's parameter.
+  static constexpr llvm::StringLiteral MsgCustomSink =
+  "Untrusted data is passed to a user-defined sink";
+  bool checkCustomSinks(const CallExpr *CE, StringRef Name,
+CheckerContext &C) const;
+
   /// Generate a report if the expression is tainted or points to tainted data.
-  bool generateReportIfTainted(const Expr *E, const char Msg[],
+  bool generateReportIfTainted(const Expr *E, StringRef Msg,
CheckerContext &C) const;
 
+  struct TaintPropagationRule;
+  using NameRuleMap = llvm::StringMap;
+  using NameArgMap = llvm::StringMap;
+
   /// A struct used to specify taint propagation rules for a function.
   ///
   /// If any of the possible taint source arguments is tainted, all of the
@@ -175,7 +192,8 @@
 
 /// Get the propagation rule for a given function.
 static TaintPropagationRule
-getTaintPropagationRule(const FunctionDecl *FDecl, StringRef Name,
+getTaintPropagationRule(const NameRuleMap &CustomPropagations,
+const FunctionDecl *FDecl, StringRef Name,
 CheckerContext &C);
 
 void addSrcArg(unsigned A) { SrcArgs.push_back(A); }
@@ -211,9 +229,6 @@
CheckerContext &C);
   };
 
-  using NameRuleMap = llvm::StringMap;
-  using NameArgMap = llvm::StringMap;
-
   /// Defines a map between the propagation function's name and
   /// TaintPropagationRule.
   NameRuleMap CustomPropagations;
@@ -2

[PATCH] D59637: [analyzer] Use the custom propagation rules and sinks in GenericTaintChecker

2019-09-08 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 closed this revision.
boga95 marked 10 inline comments as done.
boga95 added a comment.

Closed by 080ecafdd8b3e990e5ad19202d089c91c9c9b164 
.




Comment at: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp:251
+const llvm::StringLiteral GenericTaintChecker::MsgCustomSink =
+"Untrusted data is passed to a user defined sink";
+;

NoQ wrote:
> It should be "user-defined" because it's a single adjective.
> 
> I recommend against using the word "sink" in user-facing messages because 
> it's too jargony. Do we have a better word for this?
Currently, I don't have any better idea. I will think about it.



Comment at: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp:118
   /// Check for CWE-134: Uncontrolled Format String.
-  static const char MsgUncontrolledFormatString[];
+  static constexpr llvm::StringLiteral MsgUncontrolledFormatString =
+  "Untrusted data is used as a format string "

steakhal wrote:
> Shouldn't we still need an out-of-class initializer part for each static 
> constexpr class member variable?
> These would provide the memory locations for the declarations.
> ```
> constexpr llvm::StringLiteral 
> GenericTaintChecker::MsgUncontrolledFormatString;
> constexpr llvm::StringLiteral GenericTaintChecker::MsgSanitizeSystemArgs;
> constexpr llvm::StringLiteral GenericTaintChecker::MsgTaintedBufferSize;
> constexpr llvm::StringLiteral GenericTaintChecker::MsgCustomSink;
> ```
Constexpr values cannot be initialized out of the class, that's why I moved 
them to here.



Comment at: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp:191
 static TaintPropagationRule
-getTaintPropagationRule(const FunctionDecl *FDecl, StringRef Name,
+getTaintPropagationRule(const GenericTaintChecker *Checker,
+const FunctionDecl *FDecl, StringRef Name,

steakhal wrote:
> Szelethus wrote:
> > How about only passing `CustomPropagations`?
> I would even consider to move this function out of the whole class. (Not only 
> this function, but the others as well. Like isStdin, etc.)
> I think pure, free-functions (in an anonymous namespace) are easier to reason 
> about.
I could do that in a separate patch if necessary.



Comment at: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp:605
 // Mark the given argument.
-assert(ArgNum < CE->getNumArgs());
 State = State->add(ArgNum);

Szelethus wrote:
> I get that there isn't much substance to this assert, but why remove it? We 
> might as well populate the lines in between that and the branch.
I think there is no need for this. Maybe I can make the ArgNum const.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59637/new/

https://reviews.llvm.org/D59637



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D71524: [analyzer] Support tainted objects in GenericTaintChecker

2020-09-20 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 marked 9 inline comments as done.
boga95 added a comment.

Ping




Comment at: clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp:289-293
+  {"c_str", {"std::__cxx11::basic_string", {{0}, {ReturnValueIndex,
+  {"data", {"std::__cxx11::basic_string", {{0}, {ReturnValueIndex,
+  {"size", {"std::__cxx11::basic_string", {{0}, {ReturnValueIndex,
+  {"length", {"std::__cxx11::basic_string", {{0}, {ReturnValueIndex,
+  {"getline", {"std::", {{0}, {1, ReturnValueIndex};

NoQ wrote:
> Szelethus wrote:
> > Hmm, is this the appropriate place to put these? It seems like this job is 
> > handled in `getTaintPropagationRule`. I thought `CustomPropagations` are 
> > reserved for the config file.
> So `0` stands for `this`? Can we have a named constant please? ^.^
We are planning to move all of the propagation rules into a configuration file.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D71524/new/

https://reviews.llvm.org/D71524

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D71524: [analyzer] Support tainted objects in GenericTaintChecker

2020-09-30 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 marked an inline comment as done.
boga95 added a comment.

In D71524#2291925 , @steakhal wrote:

> In D71524#2284386 , @Szelethus wrote:
>
>> I figured you're still working on this, sorry! I'd really like to chat about 
>> my earlier comment D71524#1917251 , 
>> as it kind of challenges the high level idea.
>
> What about marking the `std::cin` object itself as tainted and any object 
> created by `ifstream::ifstream(const char*)` or similar functions.
> Then propagate taint via the extraction operator (`operator>>`) only if the 
> stream was tainted.
> This way we could reduce the false-positives of this crude heuristic. What do 
> you think?

As far as I remember I tried to make `std::cin` tainted, but it was 
complicated. I run the checker against many projects and there wasn't any false 
positive related to this heuristic.
We can restrict the `operator>>`  to `std::basic_stream` and cover only the 
standard library. I think most of the programmers will use this in a 
conventional way, therefore it should work for their implementation too.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D71524/new/

https://reviews.llvm.org/D71524

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D71524: [analyzer] Support tainted objects in GenericTaintChecker

2020-02-23 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 updated this revision to Diff 246120.
boga95 marked 5 inline comments as done.
Herald added a subscriber: martong.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D71524/new/

https://reviews.llvm.org/D71524

Files:
  clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  clang/lib/StaticAnalyzer/Checkers/Taint.cpp
  clang/test/Analysis/taint-generic.cpp

Index: clang/test/Analysis/taint-generic.cpp
===
--- clang/test/Analysis/taint-generic.cpp
+++ clang/test/Analysis/taint-generic.cpp
@@ -124,3 +124,126 @@
   foo.myMemberScanf("%d", &x);
   Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
 }
+
+
+// Test I/O
+namespace std {
+  template class char_traits {};
+
+  class ios_base {};
+
+  template>
+  class basic_ios : public ios_base {};
+
+  template>
+  class basic_istream : virtual public basic_ios {};
+  template>
+  class basic_ostream : virtual public basic_ios {};
+
+  using istream = basic_istream;
+  using ostream = basic_ostream;
+  using wistream = basic_istream;
+
+  istream& operator>>(istream& is, int& val);
+  wistream& operator>>(wistream& is, int& val);
+
+  extern istream cin;
+  extern istream wcin;
+
+  template>
+  class basic_fstream :
+public basic_istream, public basic_ostream {
+  public:
+  basic_fstream(const char*) {}
+  };
+  template>
+  class basic_ifstream : public basic_istream {
+  public:
+basic_ifstream(const char*) {}
+  };
+
+  using ifstream = basic_ifstream;
+  using fstream = basic_ifstream;
+
+  template class allocator {};
+
+namespace __cxx11 {
+template<
+  class CharT,
+  class Traits = std::char_traits,
+  class Allocator = std::allocator>
+class basic_string {
+public:
+  const char* c_str();
+  basic_string operator=(const basic_string&);
+private:
+  unsigned size;
+  char* ptr;
+};
+  }
+
+  using string = __cxx11::basic_string;
+
+  istream& operator>>(istream& is, string& val);
+  istream& getline(istream& is, string& str);
+}
+
+void testCin() {
+  int x, y;
+  std::cin >> x >> y;
+  Buffer[y] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testWcin() {
+  int x, y;
+  std::wcin >> x >> y;
+  Buffer[y] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void mySink(const std::string&, int, const char*);
+
+void testFstream() {
+  std::string str;
+  std::ifstream file("example.txt");
+  file >> str;
+  mySink(str, 0, ""); // expected-warning {{Untrusted data is passed to a user-defined sink}}
+}
+
+void testIfstream() {
+  std::string str;
+  std::fstream file("example.txt");
+  file >> str;
+  mySink(str, 0, ""); // expected-warning {{Untrusted data is passed to a user-defined sink}}
+}
+
+void testStdstring() {
+  std::string str1;
+  std::cin >> str1;
+
+  std::string& str2 = str1;
+  mySink(str2, 0, ""); // expected-warning {{Untrusted data is passed to a user-defined sink}}
+
+  const std::string& str3 = str1;
+  mySink(str3, 0, ""); // expected-warning {{Untrusted data is passed to a user-defined sink}}
+}
+
+void testTaintedThis() {
+  std::string str;
+  mySink(std::string(), 0, str.c_str()); // no-warning
+
+  std::cin >> str;
+  mySink(std::string(), 0, str.c_str()); // expected-warning {{Untrusted data is passed to a user-defined sink}}
+}
+
+void testOverloadedAssignmentOp() {
+  std::string str1, str2;
+  std::cin >> str1;
+  str2 = str1;
+  mySink(str2, 0, ""); // expected-warning {{Untrusted data is passed to a user-defined sink}}
+}
+
+void testGetline() {
+  std::string str;
+  std::getline(std::cin, str);
+  mySink(str, 0, ""); // expected-warning {{Untrusted data is passed to a user-defined sink}}
+}
Index: clang/lib/StaticAnalyzer/Checkers/Taint.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/Taint.cpp
+++ clang/lib/StaticAnalyzer/Checkers/Taint.cpp
@@ -152,6 +152,14 @@
 return isTainted(State, Sym, Kind);
   if (const MemRegion *Reg = V.getAsRegion())
 return isTainted(State, Reg, Kind);
+  if (auto LCV = V.getAs()) {
+if (Optional binding =
+State->getStateManager().getStoreManager().getDefaultBinding(
+*LCV)) {
+  if (SymbolRef Sym = binding->getAsSymbol())
+return isTainted(State, Sym, Kind);
+}
+  }
   return false;
 }
 
Index: clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -135,6 +135,9 @@
   bool checkPre(const CallExpr *CE, const FunctionData &FData,
 CheckerContext &C) const;
 
+  /// Add taint sources for operator>> on pre-visit.
+  bool addOverloadedOpPre(const CallExpr *CE, CheckerContext &C) const;
+
   /// Add taint sources on a pre-visit. Returns true on matching.
   bool addSourcesPre(const CallEx

[PATCH] D71524: [analyzer] Support tainted objects in GenericTaintChecker

2020-02-24 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 marked 6 inline comments as done.
boga95 added a comment.

@steakhal's revision is on the top of this. Changing the order will only cause 
unnecessary work on both sides.




Comment at: clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp:103-132
   struct FunctionData {
 FunctionData() = delete;
 FunctionData(const FunctionData &) = default;
 FunctionData(FunctionData &&) = default;
 FunctionData &operator=(const FunctionData &) = delete;
 FunctionData &operator=(FunctionData &&) = delete;
 

Szelethus wrote:
> Szelethus wrote:
> > I know this isn't really relevant, but isn't this redundant with 
> > `CallDescription`?
> Ah, okay, so `CallDescription` doesn't really have the `FunctionDecl`, but 
> this still feels like a duplication of functionalities.
We have already thought about that and it is on our TODO list.



Comment at: clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp:139
 
+  /// Add taint sources for extraction operator on pre-visit.
+  bool addOverloadedOpPre(const CallExpr *CE, CheckerContext &C) const;

Szelethus wrote:
> Extraction operator? Is that a thing?
I can call it `operator>>` if you think that is better.



Comment at: clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp:202
   using ConfigDataMap =
   std::unordered_multimap>;
   using NameRuleMap = ConfigDataMap;

Szelethus wrote:
> http://llvm.org/docs/ProgrammersManual.html#other-map-like-container-options
> 
> > We never use hash_set and unordered_set because they are generally very 
> > expensive (each insertion requires a malloc) and very non-portable.
I didn't find any multimap among the alternatives. I think the performance 
won't be an issue here, because the elements are inserted at the beginning of 
the analysis if there is any. Otherwise, we are planning to replace it with 
CallDescriptionMap.



Comment at: clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp:268
CheckerContext &C) {
-  if (isTainted(State, E, C.getLocationContext()) || isStdin(E, C))
+  if (isTainted(State, E, C.getLocationContext()) || isStdin(E, C) ||
+  isStdstream(E, C))

xazax.hun wrote:
> If we consider `Stdin`  and `Stdstream` to be tainted does it make sense to 
> fold them into `isTainted` so we never miss checking for them?
Then we have to pass the `CheckerContext` to the `isTainted` functions. I think 
this function wraps it well.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D71524/new/

https://reviews.llvm.org/D71524



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D59516: [analyzer] Add custom filter functions for GenericTaintChecker

2019-11-16 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 marked 2 inline comments as done.
boga95 added a comment.

I did the required changes and tried to commit it, but I couldn't. I heard the 
codebase was migrated to GitHub. Maybe it affected my commit access.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59516/new/

https://reviews.llvm.org/D59516



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D59516: [analyzer] Add custom filter functions for GenericTaintChecker

2019-11-23 Thread Borsik Gábor via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
boga95 marked 2 inline comments as done.
Closed by commit rG89bc4c662c6c: [analyzer] Add custom filter functions for 
GenericTaintChecker (authored by boga95).

Changed prior to commit:
  https://reviews.llvm.org/D59516?vs=220385&id=230771#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59516/new/

https://reviews.llvm.org/D59516

Files:
  clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  clang/lib/StaticAnalyzer/Checkers/Taint.cpp
  clang/lib/StaticAnalyzer/Checkers/Taint.h
  clang/test/Analysis/Inputs/taint-generic-config.yaml
  clang/test/Analysis/taint-generic.c

Index: clang/test/Analysis/taint-generic.c
===
--- clang/test/Analysis/taint-generic.c
+++ clang/test/Analysis/taint-generic.c
@@ -56,6 +56,8 @@
 extern FILE *stdin;
 #endif
 
+#define bool _Bool
+
 int fscanf(FILE *restrict stream, const char *restrict format, ...);
 int sprintf(char *str, const char *format, ...);
 void setproctitle(const char *fmt, ...);
@@ -346,6 +348,7 @@
 void myScanf(const char*, ...);
 int myPropagator(int, int*);
 int mySnprintf(char*, size_t, const char*, ...);
+bool isOutOfRange(const int*);
 void mySink(int, int, int);
 
 void testConfigurationSources1() {
@@ -372,6 +375,13 @@
   Buffer[y] = 1; // expected-warning {{Out of bound memory access }}
 }
 
+void testConfigurationFilter() {
+  int x = mySource1();
+  if (isOutOfRange(&x)) // the filter function
+return;
+  Buffer[x] = 1; // no-warning
+}
+
 void testConfigurationSinks() {
   int x = mySource1();
   mySink(x, 1, 2);
Index: clang/test/Analysis/Inputs/taint-generic-config.yaml
===
--- clang/test/Analysis/Inputs/taint-generic-config.yaml
+++ clang/test/Analysis/Inputs/taint-generic-config.yaml
@@ -36,8 +36,8 @@
 # A list of filter functions
 Filters:
   # int x; // x is tainted
-  # myFilter(&x); // x is not tainted anymore
-  - Name: myFilter
+  # isOutOfRange(&x); // x is not tainted anymore
+  - Name: isOutOfRange
 Args: [0]
 
 # A list of sink functions
Index: clang/lib/StaticAnalyzer/Checkers/Taint.h
===
--- clang/lib/StaticAnalyzer/Checkers/Taint.h
+++ clang/lib/StaticAnalyzer/Checkers/Taint.h
@@ -27,34 +27,39 @@
 static constexpr TaintTagType TaintTagGeneric = 0;
 
 /// Create a new state in which the value of the statement is marked as tainted.
-LLVM_NODISCARD ProgramStateRef
-addTaint(ProgramStateRef State, const Stmt *S, const LocationContext *LCtx,
- TaintTagType Kind = TaintTagGeneric);
+LLVM_NODISCARD ProgramStateRef addTaint(ProgramStateRef State, const Stmt *S,
+const LocationContext *LCtx,
+TaintTagType Kind = TaintTagGeneric);
 
 /// Create a new state in which the value is marked as tainted.
-LLVM_NODISCARD ProgramStateRef
-addTaint(ProgramStateRef State, SVal V,
- TaintTagType Kind = TaintTagGeneric);
+LLVM_NODISCARD ProgramStateRef addTaint(ProgramStateRef State, SVal V,
+TaintTagType Kind = TaintTagGeneric);
 
 /// Create a new state in which the symbol is marked as tainted.
-LLVM_NODISCARD ProgramStateRef
-addTaint(ProgramStateRef State, SymbolRef Sym,
- TaintTagType Kind = TaintTagGeneric);
+LLVM_NODISCARD ProgramStateRef addTaint(ProgramStateRef State, SymbolRef Sym,
+TaintTagType Kind = TaintTagGeneric);
 
 /// Create a new state in which the pointer represented by the region
 /// is marked as tainted.
-LLVM_NODISCARD ProgramStateRef
-addTaint(ProgramStateRef State, const MemRegion *R,
- TaintTagType Kind = TaintTagGeneric);
+LLVM_NODISCARD ProgramStateRef addTaint(ProgramStateRef State,
+const MemRegion *R,
+TaintTagType Kind = TaintTagGeneric);
+
+LLVM_NODISCARD ProgramStateRef removeTaint(ProgramStateRef State, SVal V);
+
+LLVM_NODISCARD ProgramStateRef removeTaint(ProgramStateRef State,
+   const MemRegion *R);
+
+LLVM_NODISCARD ProgramStateRef removeTaint(ProgramStateRef State,
+   SymbolRef Sym);
 
 /// Create a new state in a which a sub-region of a given symbol is tainted.
 /// This might be necessary when referring to regions that can not have an
 /// individual symbol, e.g. if they are represented by the default binding of
 /// a LazyCompoundVal.
-LLVM_NODISCARD ProgramStateRef
-addPartialTaint(ProgramStateRef State,
-SymbolRef ParentSym, const SubRegion *SubRegion,
-TaintTagType Kind = TaintTagGeneric);
+LLVM_NODISCARD ProgramStateRef addPartialTaint(
+ProgramStateRef State, SymbolRef ParentSym, const SubRegion *Sub

[PATCH] D70596: [analyzer][docs] NFC: Extend documentation for MallocOverflow checker

2019-11-23 Thread Borsik Gábor via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG79e2325f145d: [analyzer][docs] NFC: Extend documentation for 
MallocOverflow checker (authored by boga95).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D70596/new/

https://reviews.llvm.org/D70596

Files:
  clang/docs/analyzer/checkers.rst


Index: clang/docs/analyzer/checkers.rst
===
--- clang/docs/analyzer/checkers.rst
+++ clang/docs/analyzer/checkers.rst
@@ -1974,6 +1974,12 @@
void *p = malloc(n * sizeof(int)); // warn
  }
 
+ void test2(int n) {
+   if (n > 100) // gives an upper-bound
+ return;
+   void *p = malloc(n * sizeof(int)); // no warning
+ }
+
 .. _alpha-security-MmapWriteExec:
 
 alpha.security.MmapWriteExec (C)


Index: clang/docs/analyzer/checkers.rst
===
--- clang/docs/analyzer/checkers.rst
+++ clang/docs/analyzer/checkers.rst
@@ -1974,6 +1974,12 @@
void *p = malloc(n * sizeof(int)); // warn
  }
 
+ void test2(int n) {
+   if (n > 100) // gives an upper-bound
+ return;
+   void *p = malloc(n * sizeof(int)); // no warning
+ }
+
 .. _alpha-security-MmapWriteExec:
 
 alpha.security.MmapWriteExec (C)
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D70878: [analyzer] Add support for namespaces to GenericTaintChecker

2019-12-01 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 created this revision.
boga95 added reviewers: NoQ, Szelethus.
boga95 added a project: clang.
Herald added subscribers: cfe-commits, Charusso, donat.nagy, mikhail.ramalho, 
a.sidorin, szepet, baloghadamsoftware.

Now the user can define a `Scope` for every configured function:

- Functions without `Scope` match for every function regardless of the 
namespace.
- Functions with `Scope` will match if the full name of the function is start 
with the `Scope`.
- Multiple functions can exist with the same name.

I also added support for member functions.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D70878

Files:
  clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  clang/test/Analysis/Inputs/taint-generic-config.yaml
  clang/test/Analysis/taint-generic.cpp

Index: clang/test/Analysis/taint-generic.cpp
===
--- /dev/null
+++ clang/test/Analysis/taint-generic.cpp
@@ -0,0 +1,126 @@
+// RUN: %clang_analyze_cc1  -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -analyzer-config alpha.security.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config.yaml -Wno-format-security -verify -std=c++11 %s
+
+#define BUFSIZE 10
+int Buffer[BUFSIZE];
+
+int scanf(const char*, ...);
+int mySource1();
+int mySource3();
+
+bool isOutOfRange2(const int*);
+
+void mySink2(int);
+
+// Test configuration
+namespace myNamespace {
+  void scanf(const char*, ...);
+  void myScanf(const char*, ...);
+  int mySource3();
+
+  bool isOutOfRange(const int*);
+  bool isOutOfRange2(const int*);
+
+  void mySink(int, int, int);
+  void mySink2(int);
+}
+
+namespace myAnotherNamespace {
+  int mySource3();
+
+  bool isOutOfRange2(const int*);
+
+  void mySink2(int);
+}
+
+void testConfigurationNamespacePropagation1() {
+  int x;
+  // The built-in functions should be matched only for functions in
+  // the global namespace
+  myNamespace::scanf("%d", &x);
+  Buffer[x] = 1; // no-warning
+
+  scanf("%d", &x);
+  Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationNamespacePropagation2() {
+  int x = mySource3();
+  Buffer[x] = 1; // no-warning
+
+  int y = myNamespace::mySource3();
+  Buffer[y] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationNamespacePropagation3() {
+  int x = myAnotherNamespace::mySource3();
+  Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationNamespacePropagation4() {
+  int x;
+  // Configured functions without scope should match for all function.
+  myNamespace::myScanf("%d", &x);
+  Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationNamespaceFilter1() {
+  int x = mySource1();
+  if (myNamespace::isOutOfRange2(&x))
+return;
+  Buffer[x] = 1; // no-warning
+
+  int y = mySource1();
+  if (isOutOfRange2(&y))
+return;
+  Buffer[y] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationNamespaceFilter2() {
+  int x = mySource1();
+  if (myAnotherNamespace::isOutOfRange2(&x))
+return;
+  Buffer[x] = 1; // no-warning
+}
+
+void testConfigurationNamespaceFilter3() {
+  int x = mySource1();
+  if (myNamespace::isOutOfRange(&x))
+return;
+  Buffer[x] = 1; // no-warning
+}
+
+void testConfigurationNamespaceSink1() {
+  int x = mySource1();
+  mySink2(x); // no-warning
+
+  int y = mySource1();
+  myNamespace::mySink2(y);
+  // expected-warning@-1 {{Untrusted data is passed to a user-defined sink}}
+}
+
+void testConfigurationNamespaceSink2() {
+  int x = mySource1();
+  myAnotherNamespace::mySink2(x);
+  // expected-warning@-1 {{Untrusted data is passed to a user-defined sink}}
+}
+
+void testConfigurationNamespaceSink3() {
+  int x = mySource1();
+  myNamespace::mySink(x, 0, 1);
+  // expected-warning@-1 {{Untrusted data is passed to a user-defined sink}}
+}
+
+struct Foo {
+void scanf(const char*, int*);
+void myMemberScanf(const char*, int*);
+};
+
+void testConfigurationMemberFunc() {
+  int x;
+  Foo foo;
+  foo.scanf("%d", &x);
+  Buffer[x] = 1; // no-warning
+
+  foo.myMemberScanf("%d", &x);
+  Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
+}
Index: clang/test/Analysis/Inputs/taint-generic-config.yaml
===
--- clang/test/Analysis/Inputs/taint-generic-config.yaml
+++ clang/test/Analysis/Inputs/taint-generic-config.yaml
@@ -9,12 +9,29 @@
   - Name: mySource2
 DstArgs:  [0]
 
+  # int x = myNamespace::mySource3(); // x is tainted
+  - Name: mySource3
+Scope:"myNamespace::"
+DstArgs:  [-1]
+
+  # int x = myAnotherNamespace::mySource3(); // x is tainted
+  - Name: mySource3
+Scope:"myAnotherNamespace::"
+DstArgs:  [-1]
+
   # int x, y;
   # myScanf("%d %d", &x, &y); // x and y are tainted
   - Name:  myScanf
 VariadicType:  Dst
 VariadicIndex: 1
 
+  # in

[PATCH] D70878: [analyzer] Add support for namespaces to GenericTaintChecker

2019-12-15 Thread Borsik Gábor via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
boga95 marked 2 inline comments as done.
Closed by commit rG273e67425243: [analyzer] Add support for namespaces to 
GenericTaintChecker (authored by boga95).

Changed prior to commit:
  https://reviews.llvm.org/D70878?vs=231621&id=233957#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D70878/new/

https://reviews.llvm.org/D70878

Files:
  clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  clang/test/Analysis/Inputs/taint-generic-config.yaml
  clang/test/Analysis/taint-generic.cpp

Index: clang/test/Analysis/taint-generic.cpp
===
--- /dev/null
+++ clang/test/Analysis/taint-generic.cpp
@@ -0,0 +1,126 @@
+// RUN: %clang_analyze_cc1  -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -analyzer-config alpha.security.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config.yaml -Wno-format-security -verify -std=c++11 %s
+
+#define BUFSIZE 10
+int Buffer[BUFSIZE];
+
+int scanf(const char*, ...);
+int mySource1();
+int mySource3();
+
+bool isOutOfRange2(const int*);
+
+void mySink2(int);
+
+// Test configuration
+namespace myNamespace {
+  void scanf(const char*, ...);
+  void myScanf(const char*, ...);
+  int mySource3();
+
+  bool isOutOfRange(const int*);
+  bool isOutOfRange2(const int*);
+
+  void mySink(int, int, int);
+  void mySink2(int);
+}
+
+namespace myAnotherNamespace {
+  int mySource3();
+
+  bool isOutOfRange2(const int*);
+
+  void mySink2(int);
+}
+
+void testConfigurationNamespacePropagation1() {
+  int x;
+  // The built-in functions should be matched only for functions in
+  // the global namespace
+  myNamespace::scanf("%d", &x);
+  Buffer[x] = 1; // no-warning
+
+  scanf("%d", &x);
+  Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationNamespacePropagation2() {
+  int x = mySource3();
+  Buffer[x] = 1; // no-warning
+
+  int y = myNamespace::mySource3();
+  Buffer[y] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationNamespacePropagation3() {
+  int x = myAnotherNamespace::mySource3();
+  Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationNamespacePropagation4() {
+  int x;
+  // Configured functions without scope should match for all function.
+  myNamespace::myScanf("%d", &x);
+  Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationNamespaceFilter1() {
+  int x = mySource1();
+  if (myNamespace::isOutOfRange2(&x))
+return;
+  Buffer[x] = 1; // no-warning
+
+  int y = mySource1();
+  if (isOutOfRange2(&y))
+return;
+  Buffer[y] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testConfigurationNamespaceFilter2() {
+  int x = mySource1();
+  if (myAnotherNamespace::isOutOfRange2(&x))
+return;
+  Buffer[x] = 1; // no-warning
+}
+
+void testConfigurationNamespaceFilter3() {
+  int x = mySource1();
+  if (myNamespace::isOutOfRange(&x))
+return;
+  Buffer[x] = 1; // no-warning
+}
+
+void testConfigurationNamespaceSink1() {
+  int x = mySource1();
+  mySink2(x); // no-warning
+
+  int y = mySource1();
+  myNamespace::mySink2(y);
+  // expected-warning@-1 {{Untrusted data is passed to a user-defined sink}}
+}
+
+void testConfigurationNamespaceSink2() {
+  int x = mySource1();
+  myAnotherNamespace::mySink2(x);
+  // expected-warning@-1 {{Untrusted data is passed to a user-defined sink}}
+}
+
+void testConfigurationNamespaceSink3() {
+  int x = mySource1();
+  myNamespace::mySink(x, 0, 1);
+  // expected-warning@-1 {{Untrusted data is passed to a user-defined sink}}
+}
+
+struct Foo {
+void scanf(const char*, int*);
+void myMemberScanf(const char*, int*);
+};
+
+void testConfigurationMemberFunc() {
+  int x;
+  Foo foo;
+  foo.scanf("%d", &x);
+  Buffer[x] = 1; // no-warning
+
+  foo.myMemberScanf("%d", &x);
+  Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
+}
Index: clang/test/Analysis/Inputs/taint-generic-config.yaml
===
--- clang/test/Analysis/Inputs/taint-generic-config.yaml
+++ clang/test/Analysis/Inputs/taint-generic-config.yaml
@@ -9,12 +9,29 @@
   - Name: mySource2
 DstArgs:  [0]
 
+  # int x = myNamespace::mySource3(); // x is tainted
+  - Name: mySource3
+Scope:"myNamespace::"
+DstArgs:  [-1]
+
+  # int x = myAnotherNamespace::mySource3(); // x is tainted
+  - Name: mySource3
+Scope:"myAnotherNamespace::"
+DstArgs:  [-1]
+
   # int x, y;
   # myScanf("%d %d", &x, &y); // x and y are tainted
   - Name:  myScanf
 VariadicType:  Dst
 VariadicIndex: 1
 
+  # int x, y;
+  # Foo::myScanf("%d %d", &x, &y); // x and y are tainted
+  - Name:  myMemberScanf
+Scope: "Foo::"
+VariadicType:  Dst
+VariadicIndex: 1
+
   

[PATCH] D71524: [analyzer] Support tainted objects in GenericTaintChecker

2019-12-15 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 created this revision.
boga95 added reviewers: NoQ, Szelethus.
Herald added subscribers: cfe-commits, Charusso, donat.nagy, mikhail.ramalho, 
a.sidorin, szepet, baloghadamsoftware.
Herald added a project: clang.

I extended the supported C++ features:

- The `this` pointer can be tainted (0. argument)
- All `std::basic_istream` objects are tainted unconditionally (`std::cin`, 
`std::ifstream`, etc.)
- `std::getline` and some member function of `std::string` propagates taint
- Extraction operator and copy assignment propagate taint


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D71524

Files:
  clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  clang/lib/StaticAnalyzer/Checkers/Taint.cpp
  clang/test/Analysis/taint-generic.cpp

Index: clang/test/Analysis/taint-generic.cpp
===
--- clang/test/Analysis/taint-generic.cpp
+++ clang/test/Analysis/taint-generic.cpp
@@ -124,3 +124,126 @@
   foo.myMemberScanf("%d", &x);
   Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
 }
+
+
+// Test I/O
+namespace std {
+  template class char_traits {};
+
+  class ios_base {};
+
+  template>
+  class basic_ios : public ios_base {};
+
+  template>
+  class basic_istream : virtual public basic_ios {};
+  template>
+  class basic_ostream : virtual public basic_ios {};
+
+  using istream = basic_istream;
+  using ostream = basic_ostream;
+  using wistream = basic_istream;
+
+  istream& operator>>(istream& is, int& val);
+  wistream& operator>>(wistream& is, int& val);
+
+  extern istream cin;
+  extern istream wcin;
+
+  template>
+  class basic_fstream :
+public basic_istream, public basic_ostream {
+  public:
+  basic_fstream(const char*) {}
+  };
+  template>
+  class basic_ifstream : public basic_istream {
+  public:
+basic_ifstream(const char*) {}
+  };
+
+  using ifstream = basic_ifstream;
+  using fstream = basic_ifstream;
+
+  template class allocator {};
+
+namespace __cxx11 {
+template<
+  class CharT,
+  class Traits = std::char_traits,
+  class Allocator = std::allocator>
+class basic_string {
+public:
+  const char* c_str();
+  basic_string operator=(const basic_string&);
+private:
+  unsigned size;
+  char* ptr;
+};
+  }
+
+  using string = __cxx11::basic_string;
+
+  istream& operator>>(istream& is, string& val);
+  istream& getline(istream& is, string& str);
+}
+
+void testCin() {
+  int x, y;
+  std::cin >> x >> y;
+  Buffer[y] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testWcin() {
+  int x, y;
+  std::wcin >> x >> y;
+  Buffer[y] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void mySink(const std::string&, int, const char*);
+
+void testFstream() {
+  std::string str;
+  std::ifstream file("example.txt");
+  file >> str;
+  mySink(str, 0, ""); // expected-warning {{Untrusted data is passed to a user-defined sink}}
+}
+
+void testIfstream() {
+  std::string str;
+  std::fstream file("example.txt");
+  file >> str;
+  mySink(str, 0, ""); // expected-warning {{Untrusted data is passed to a user-defined sink}}
+}
+
+void testStdstring() {
+  std::string str1;
+  std::cin >> str1;
+
+  std::string& str2 = str1;
+  mySink(str2, 0, ""); // expected-warning {{Untrusted data is passed to a user-defined sink}}
+
+  const std::string& str3 = str1;
+  mySink(str3, 0, ""); // expected-warning {{Untrusted data is passed to a user-defined sink}}
+}
+
+void testTaintedThis() {
+  std::string str;
+  mySink(std::string(), 0, str.c_str()); // no-warning
+
+  std::cin >> str;
+  mySink(std::string(), 0, str.c_str()); // expected-warning {{Untrusted data is passed to a user-defined sink}}
+}
+
+void testOverloadedAssignmentOp() {
+  std::string str1, str2;
+  std::cin >> str1;
+  str2 = str1;
+  mySink(str2, 0, ""); // expected-warning {{Untrusted data is passed to a user-defined sink}}
+}
+
+void testGetline() {
+  std::string str;
+  std::getline(std::cin, str);
+  mySink(str, 0, ""); // expected-warning {{Untrusted data is passed to a user-defined sink}}
+}
Index: clang/lib/StaticAnalyzer/Checkers/Taint.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/Taint.cpp
+++ clang/lib/StaticAnalyzer/Checkers/Taint.cpp
@@ -152,6 +152,14 @@
 return isTainted(State, Sym, Kind);
   if (const MemRegion *Reg = V.getAsRegion())
 return isTainted(State, Reg, Kind);
+  if (auto LCV = V.getAs()) {
+if (Optional binding =
+State->getStateManager().getStoreManager().getDefaultBinding(
+*LCV)) {
+  if (SymbolRef Sym = binding->getAsSymbol())
+return isTainted(State, Sym, Kind);
+}
+  }
   return false;
 }
 
Index: clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ clang/lib/StaticAnaly

[PATCH] D71524: [analyzer] Support tainted objects in GenericTaintChecker

2020-03-08 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 updated this revision to Diff 249019.
boga95 marked 2 inline comments as done.
boga95 added a comment.

Rebase to master.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D71524/new/

https://reviews.llvm.org/D71524

Files:
  clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  clang/lib/StaticAnalyzer/Checkers/Taint.cpp
  clang/test/Analysis/taint-generic.cpp

Index: clang/test/Analysis/taint-generic.cpp
===
--- clang/test/Analysis/taint-generic.cpp
+++ clang/test/Analysis/taint-generic.cpp
@@ -124,3 +124,127 @@
   foo.myMemberScanf("%d", &x);
   Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
 }
+
+// Test I/O
+namespace std {
+template 
+class char_traits {};
+
+class ios_base {};
+
+template >
+class basic_ios : public ios_base {};
+
+template >
+class basic_istream : virtual public basic_ios {};
+template >
+class basic_ostream : virtual public basic_ios {};
+
+using istream = basic_istream;
+using ostream = basic_ostream;
+using wistream = basic_istream;
+
+istream &operator>>(istream &is, int &val);
+wistream &operator>>(wistream &is, int &val);
+
+extern istream cin;
+extern istream wcin;
+
+template >
+class basic_fstream : public basic_istream, public basic_ostream {
+public:
+  basic_fstream(const char *) {}
+};
+template >
+class basic_ifstream : public basic_istream {
+public:
+  basic_ifstream(const char *) {}
+};
+
+using ifstream = basic_ifstream;
+using fstream = basic_ifstream;
+
+template 
+class allocator {};
+
+namespace __cxx11 {
+template <
+class CharT,
+class Traits = std::char_traits,
+class Allocator = std::allocator>
+class basic_string {
+public:
+  const char *c_str();
+  basic_string operator=(const basic_string &);
+
+private:
+  unsigned size;
+  char *ptr;
+};
+} // namespace __cxx11
+
+using string = __cxx11::basic_string;
+
+istream &operator>>(istream &is, string &val);
+istream &getline(istream &is, string &str);
+} // namespace std
+
+void testCin() {
+  int x, y;
+  std::cin >> x >> y;
+  Buffer[y] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void testWcin() {
+  int x, y;
+  std::wcin >> x >> y;
+  Buffer[y] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void mySink(const std::string &, int, const char *);
+
+void testFstream() {
+  std::string str;
+  std::ifstream file("example.txt");
+  file >> str;
+  mySink(str, 0, ""); // expected-warning {{Untrusted data is passed to a user-defined sink}}
+}
+
+void testIfstream() {
+  std::string str;
+  std::fstream file("example.txt");
+  file >> str;
+  mySink(str, 0, ""); // expected-warning {{Untrusted data is passed to a user-defined sink}}
+}
+
+void testStdstring() {
+  std::string str1;
+  std::cin >> str1;
+
+  std::string &str2 = str1;
+  mySink(str2, 0, ""); // expected-warning {{Untrusted data is passed to a user-defined sink}}
+
+  const std::string &str3 = str1;
+  mySink(str3, 0, ""); // expected-warning {{Untrusted data is passed to a user-defined sink}}
+}
+
+void testTaintedThis() {
+  std::string str;
+  mySink(std::string(), 0, str.c_str()); // no-warning
+
+  std::cin >> str;
+  mySink(std::string(), 0, str.c_str()); // expected-warning {{Untrusted data is passed to a user-defined sink}}
+}
+
+void testOverloadedAssignmentOp() {
+  std::string str1, str2;
+  std::cin >> str1;
+  str2 = str1;
+  mySink(str2, 0, ""); // expected-warning {{Untrusted data is passed to a user-defined sink}}
+}
+
+void testGetline() {
+  std::string str;
+  std::getline(std::cin, str);
+  mySink(str, 0, ""); // expected-warning {{Untrusted data is passed to a user-defined sink}}
+}
Index: clang/lib/StaticAnalyzer/Checkers/Taint.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/Taint.cpp
+++ clang/lib/StaticAnalyzer/Checkers/Taint.cpp
@@ -152,6 +152,14 @@
 return isTainted(State, Sym, Kind);
   if (const MemRegion *Reg = V.getAsRegion())
 return isTainted(State, Reg, Kind);
+  if (auto LCV = V.getAs()) {
+if (Optional binding =
+State->getStateManager().getStoreManager().getDefaultBinding(
+*LCV)) {
+  if (SymbolRef Sym = binding->getAsSymbol())
+return isTainted(State, Sym, Kind);
+}
+  }
   return false;
 }
 
Index: clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -138,6 +138,9 @@
   bool checkPre(const CallEvent &Call, const FunctionData &FData,
 CheckerContext &C) const;
 
+  /// Add taint sources for operator>> on pre-visit.
+  static bool addOverloadedOpPre(const CallEvent &Call, CheckerContext &C);
+
   /// Add taint sources on a pre-visit. Returns true on matching.
   bool addSourcesPre(const CallEvent &Call, const FunctionData &FData,
   

[PATCH] D71524: [analyzer] Support tainted objects in GenericTaintChecker

2020-01-27 Thread Borsik Gábor via Phabricator via cfe-commits
boga95 added a comment.

Ping


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D71524/new/

https://reviews.llvm.org/D71524



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits