[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-09-23 Thread David CARLIER via Phabricator via cfe-commits
This revision was not accepted when it landed; it landed in state "Needs 
Review".
This revision was automatically updated to reflect the committed changes.
Closed by commit rC342832: [CStringSyntaxChecker] Check strlcat sizeof check 
(authored by devnexen, committed by ).

Repository:
  rC Clang

https://reviews.llvm.org/D49722

Files:
  lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
  test/Analysis/cstring-syntax.c

Index: test/Analysis/cstring-syntax.c
===
--- test/Analysis/cstring-syntax.c
+++ test/Analysis/cstring-syntax.c
@@ -7,6 +7,7 @@
 char  *strncat(char *, const char *, size_t);
 size_t strlen (const char *s);
 size_t strlcpy(char *, const char *, size_t);
+size_t strlcat(char *, const char *, size_t);
 
 void testStrncat(const char *src) {
   char dest[10];
@@ -27,9 +28,27 @@
   strlcpy(dest, src, sizeof(dest));
   strlcpy(dest, src, destlen);
   strlcpy(dest, src, 10);
-  strlcpy(dest, src, 20); // expected-warning {{The third argument is larger than the size of the input buffer. Replace with the value 'sizeof(dest)` or lower}}
-  strlcpy(dest, src, badlen); // expected-warning {{The third argument is larger than the size of the input buffer. Replace with the value 'sizeof(dest)` or lower}}
+  strlcpy(dest, src, 20); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value sizeof(dest) or lower}}
+  strlcpy(dest, src, badlen); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value sizeof(dest) or lower}}
   strlcpy(dest, src, ulen);
   strlcpy(dest + 5, src, 5);
-  strlcpy(dest + 5, src, 10); // expected-warning {{The third argument is larger than the size of the input buffer.}}
+  strlcpy(dest + 5, src, 10); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value sizeof() or lower}}
+}
+
+void testStrlcat(const char *src) {
+  char dest[10];
+  size_t badlen = 20;
+  size_t ulen;
+  strlcpy(dest, "a", sizeof("a") - 1);
+  strlcat(dest, "", (sizeof("") - 1) - sizeof(dest) - 1);
+  strlcpy(dest, "012345678", sizeof(dest));
+  strlcat(dest, "910", sizeof(dest));
+  strlcpy(dest, "0123456789", sizeof(dest));
+  strlcpy(dest, "0123456789", sizeof(dest));
+  strlcat(dest, "0123456789", badlen / 2);
+  strlcat(dest, "0123456789", badlen); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value sizeof(dest) or lower}}
+  strlcat(dest, "0123456789", badlen - strlen(dest) - 1);
+  strlcat(dest, src, ulen);
+  strlcpy(dest, src, 5);
+  strlcat(dest + 5, src, badlen); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value sizeof() or lower}}
 }
Index: lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
+++ lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
@@ -90,7 +90,16 @@
   ///   strlcpy(dst, "abcd", 4);
   ///   strlcpy(dst + 3, "abcd", 2);
   ///   strlcpy(dst, "abcd", cpy);
-  bool containsBadStrlcpyPattern(const CallExpr *CE);
+  /// Identify erroneous patterns in the last argument to strlcat - the number
+  /// of bytes to copy.
+  /// The bad pattern checked is when the last argument is basically
+  /// pointing to the destination buffer size or argument larger or
+  /// equal to.
+  ///   char dst[2];
+  ///   strlcat(dst, src2, sizeof(dst));
+  ///   strlcat(dst, src2, 2);
+  ///   strlcat(dst, src2, 10);
+  bool containsBadStrlcpyStrlcatPattern(const CallExpr *CE);
 
 public:
   WalkAST(const CheckerBase *Checker, BugReporter &BR, AnalysisDeclContext *AC)
@@ -142,15 +151,19 @@
   return false;
 }
 
-bool WalkAST::containsBadStrlcpyPattern(const CallExpr *CE) {
+bool WalkAST::containsBadStrlcpyStrlcatPattern(const CallExpr *CE) {
   if (CE->getNumArgs() != 3)
 return false;
+  const FunctionDecl *FD = CE->getDirectCallee();
+  bool Append = CheckerContext::isCLibraryFunction(FD, "strlcat");
   const Expr *DstArg = CE->getArg(0);
   const Expr *LenArg = CE->getArg(2);
 
   const auto *DstArgDecl = dyn_cast(DstArg->IgnoreParenImpCasts());
   const auto *LenArgDecl = dyn_cast(LenArg->IgnoreParenLValueCasts());
   uint64_t DstOff = 0;
+  if (isSizeof(LenArg, DstArg))
+return false;
   // - size_t dstlen = sizeof(dst)
   if (LenArgDecl) {
 const auto *LenArgVal = dyn_cast(LenArgDecl->getDecl());
@@ -181,8 +194,14 @@
   if (const auto *Buffer = dyn_cast(DstArgDecl->getType())) {
 ASTContext &C = BR.getContext();
 uint64_t BufferLen = C.getTypeSize(Buffer) / 8;
-if ((BufferLen - DstOff) < ILRawVal)
-  return true;
+auto RemainingBufferLen = BufferLen - DstOff;
+if (Append) {
+  if (RemainingBufferLen <= ILRawVal)

[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-09-23 Thread Fangrui Song via Phabricator via cfe-commits
MaskRay accepted this revision.
MaskRay added a comment.

LG


https://reviews.llvm.org/D49722



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


[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-09-23 Thread David CARLIER via Phabricator via cfe-commits
devnexen updated this revision to Diff 166628.

https://reviews.llvm.org/D49722

Files:
  lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
  test/Analysis/cstring-syntax.c

Index: test/Analysis/cstring-syntax.c
===
--- test/Analysis/cstring-syntax.c
+++ test/Analysis/cstring-syntax.c
@@ -7,6 +7,7 @@
 char  *strncat(char *, const char *, size_t);
 size_t strlen (const char *s);
 size_t strlcpy(char *, const char *, size_t);
+size_t strlcat(char *, const char *, size_t);
 
 void testStrncat(const char *src) {
   char dest[10];
@@ -27,9 +28,27 @@
   strlcpy(dest, src, sizeof(dest));
   strlcpy(dest, src, destlen);
   strlcpy(dest, src, 10);
-  strlcpy(dest, src, 20); // expected-warning {{The third argument is larger than the size of the input buffer. Replace with the value 'sizeof(dest)` or lower}}
-  strlcpy(dest, src, badlen); // expected-warning {{The third argument is larger than the size of the input buffer. Replace with the value 'sizeof(dest)` or lower}}
+  strlcpy(dest, src, 20); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value sizeof(dest) or lower}}
+  strlcpy(dest, src, badlen); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value sizeof(dest) or lower}}
   strlcpy(dest, src, ulen);
   strlcpy(dest + 5, src, 5);
-  strlcpy(dest + 5, src, 10); // expected-warning {{The third argument is larger than the size of the input buffer.}}
+  strlcpy(dest + 5, src, 10); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value sizeof() or lower}}
+}
+
+void testStrlcat(const char *src) {
+  char dest[10];
+  size_t badlen = 20;
+  size_t ulen;
+  strlcpy(dest, "a", sizeof("a") - 1);
+  strlcat(dest, "", (sizeof("") - 1) - sizeof(dest) - 1);
+  strlcpy(dest, "012345678", sizeof(dest));
+  strlcat(dest, "910", sizeof(dest));
+  strlcpy(dest, "0123456789", sizeof(dest));
+  strlcpy(dest, "0123456789", sizeof(dest));
+  strlcat(dest, "0123456789", badlen / 2);
+  strlcat(dest, "0123456789", badlen); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value sizeof(dest) or lower}}
+  strlcat(dest, "0123456789", badlen - strlen(dest) - 1);
+  strlcat(dest, src, ulen);
+  strlcpy(dest, src, 5);
+  strlcat(dest + 5, src, badlen); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value sizeof() or lower}}
 }
Index: lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
+++ lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
@@ -90,7 +90,16 @@
   ///   strlcpy(dst, "abcd", 4);
   ///   strlcpy(dst + 3, "abcd", 2);
   ///   strlcpy(dst, "abcd", cpy);
-  bool containsBadStrlcpyPattern(const CallExpr *CE);
+  /// Identify erroneous patterns in the last argument to strlcat - the number
+  /// of bytes to copy.
+  /// The bad pattern checked is when the last argument is basically
+  /// pointing to the destination buffer size or argument larger or
+  /// equal to.
+  ///   char dst[2];
+  ///   strlcat(dst, src2, sizeof(dst));
+  ///   strlcat(dst, src2, 2);
+  ///   strlcat(dst, src2, 10);
+  bool containsBadStrlcpyStrlcatPattern(const CallExpr *CE);
 
 public:
   WalkAST(const CheckerBase *Checker, BugReporter &BR, AnalysisDeclContext *AC)
@@ -142,15 +151,19 @@
   return false;
 }
 
-bool WalkAST::containsBadStrlcpyPattern(const CallExpr *CE) {
+bool WalkAST::containsBadStrlcpyStrlcatPattern(const CallExpr *CE) {
   if (CE->getNumArgs() != 3)
 return false;
+  const FunctionDecl *FD = CE->getDirectCallee();
+  bool Append = CheckerContext::isCLibraryFunction(FD, "strlcat");
   const Expr *DstArg = CE->getArg(0);
   const Expr *LenArg = CE->getArg(2);
 
   const auto *DstArgDecl = dyn_cast(DstArg->IgnoreParenImpCasts());
   const auto *LenArgDecl = dyn_cast(LenArg->IgnoreParenLValueCasts());
   uint64_t DstOff = 0;
+  if (isSizeof(LenArg, DstArg))
+return false;
   // - size_t dstlen = sizeof(dst)
   if (LenArgDecl) {
 const auto *LenArgVal = dyn_cast(LenArgDecl->getDecl());
@@ -181,8 +194,14 @@
   if (const auto *Buffer = dyn_cast(DstArgDecl->getType())) {
 ASTContext &C = BR.getContext();
 uint64_t BufferLen = C.getTypeSize(Buffer) / 8;
-if ((BufferLen - DstOff) < ILRawVal)
-  return true;
+auto RemainingBufferLen = BufferLen - DstOff;
+if (Append) {
+  if (RemainingBufferLen <= ILRawVal)
+return true;
+} else {
+  if (RemainingBufferLen < ILRawVal)
+return true;
+}
   }
 }
   }
@@ -219,8 +238,9 @@
  "C String API", os.str(), Loc,
  

[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-09-23 Thread David CARLIER via Phabricator via cfe-commits
devnexen added inline comments.



Comment at: lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp:275
+os << "sizeof(" << DstName << ")";
+  else
+os << "sizeof()";

MaskRay wrote:
> devnexen wrote:
> > MaskRay wrote:
> > > Why can't this `else if` case be folded into the `strlcpy` case? There 
> > > are lots of duplication.
> > > 
> > > `strlcpy` does not check `DstName.empty()` but this one does. Is there 
> > > any cases I am missing?
> > strlcpy does but agreed with your first statement, this handling case for 
> > both are more different than my initial plan defined them.
> Not sure the description of `strlcat` should be different from `strlcpy`... 
> For both of them, `len` should be less or equal to the  size of `dst`. They 
> may just use the same description.
> 
> I think your description of `strlcat` (`"The third argument allows to 
> potentially copy more bytes than it should. ")` is better while the existing 
> description of `strlcpy` is problematic:
> 
> os << "The third argument is larger than the size of the input buffer. ";
> 
> input => output
Fair enough. Code reduction is always nice anyway.


https://reviews.llvm.org/D49722



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


[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-09-23 Thread Fangrui Song via Phabricator via cfe-commits
MaskRay added inline comments.



Comment at: lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp:275
+os << "sizeof(" << DstName << ")";
+  else
+os << "sizeof()";

devnexen wrote:
> MaskRay wrote:
> > Why can't this `else if` case be folded into the `strlcpy` case? There are 
> > lots of duplication.
> > 
> > `strlcpy` does not check `DstName.empty()` but this one does. Is there any 
> > cases I am missing?
> strlcpy does but agreed with your first statement, this handling case for 
> both are more different than my initial plan defined them.
Not sure the description of `strlcat` should be different from `strlcpy`... For 
both of them, `len` should be less or equal to the  size of `dst`. They may 
just use the same description.

I think your description of `strlcat` (`"The third argument allows to 
potentially copy more bytes than it should. ")` is better while the existing 
description of `strlcpy` is problematic:

os << "The third argument is larger than the size of the input buffer. ";

input => output


https://reviews.llvm.org/D49722



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


[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-09-22 Thread David CARLIER via Phabricator via cfe-commits
devnexen updated this revision to Diff 166626.

https://reviews.llvm.org/D49722

Files:
  lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
  test/Analysis/cstring-syntax.c

Index: test/Analysis/cstring-syntax.c
===
--- test/Analysis/cstring-syntax.c
+++ test/Analysis/cstring-syntax.c
@@ -7,6 +7,7 @@
 char  *strncat(char *, const char *, size_t);
 size_t strlen (const char *s);
 size_t strlcpy(char *, const char *, size_t);
+size_t strlcat(char *, const char *, size_t);
 
 void testStrncat(const char *src) {
   char dest[10];
@@ -33,3 +34,21 @@
   strlcpy(dest + 5, src, 5);
   strlcpy(dest + 5, src, 10); // expected-warning {{The third argument is larger than the size of the input buffer.}}
 }
+
+void testStrlcat(const char *src) {
+  char dest[10];
+  size_t badlen = 20;
+  size_t ulen;
+  strlcpy(dest, "a", sizeof("a") - 1);
+  strlcat(dest, "", (sizeof("") - 1) - sizeof(dest) - 1);
+  strlcpy(dest, "012345678", sizeof(dest));
+  strlcat(dest, "910", sizeof(dest));
+  strlcpy(dest, "0123456789", sizeof(dest));
+  strlcpy(dest, "0123456789", sizeof(dest));
+  strlcat(dest, "0123456789", badlen / 2);
+  strlcat(dest, "0123456789", badlen); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value sizeof(dest) or lower}}
+  strlcat(dest, "0123456789", badlen - strlen(dest) - 1);
+  strlcat(dest, src, ulen);
+  strlcpy(dest, src, 5);
+  strlcat(dest + 5, src, badlen); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value sizeof() or lower}}
+}
Index: lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
+++ lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
@@ -90,7 +90,16 @@
   ///   strlcpy(dst, "abcd", 4);
   ///   strlcpy(dst + 3, "abcd", 2);
   ///   strlcpy(dst, "abcd", cpy);
-  bool containsBadStrlcpyPattern(const CallExpr *CE);
+  /// Identify erroneous patterns in the last argument to strlcat - the number
+  /// of bytes to copy.
+  /// The bad pattern checked is when the last argument is basically
+  /// pointing to the destination buffer size or argument larger or
+  /// equal to.
+  ///   char dst[2];
+  ///   strlcat(dst, src2, sizeof(dst));
+  ///   strlcat(dst, src2, 2);
+  ///   strlcat(dst, src2, 10);
+  bool containsBadStrlcpyStrlcatPattern(const CallExpr *CE);
 
 public:
   WalkAST(const CheckerBase *Checker, BugReporter &BR, AnalysisDeclContext *AC)
@@ -142,15 +151,19 @@
   return false;
 }
 
-bool WalkAST::containsBadStrlcpyPattern(const CallExpr *CE) {
+bool WalkAST::containsBadStrlcpyStrlcatPattern(const CallExpr *CE) {
   if (CE->getNumArgs() != 3)
 return false;
+  const FunctionDecl *FD = CE->getDirectCallee();
+  bool Append = CheckerContext::isCLibraryFunction(FD, "strlcat");
   const Expr *DstArg = CE->getArg(0);
   const Expr *LenArg = CE->getArg(2);
 
   const auto *DstArgDecl = dyn_cast(DstArg->IgnoreParenImpCasts());
   const auto *LenArgDecl = dyn_cast(LenArg->IgnoreParenLValueCasts());
   uint64_t DstOff = 0;
+  if (isSizeof(LenArg, DstArg))
+return false;
   // - size_t dstlen = sizeof(dst)
   if (LenArgDecl) {
 const auto *LenArgVal = dyn_cast(LenArgDecl->getDecl());
@@ -181,8 +194,14 @@
   if (const auto *Buffer = dyn_cast(DstArgDecl->getType())) {
 ASTContext &C = BR.getContext();
 uint64_t BufferLen = C.getTypeSize(Buffer) / 8;
-if ((BufferLen - DstOff) < ILRawVal)
-  return true;
+auto RemainingBufferLen = BufferLen - DstOff;
+if (Append) {
+  if (RemainingBufferLen <= ILRawVal)
+return true;
+} else {
+  if (RemainingBufferLen < ILRawVal)
+return true;
+}
   }
 }
   }
@@ -219,8 +238,9 @@
  "C String API", os.str(), Loc,
  LenArg->getSourceRange());
 }
-  } else if (CheckerContext::isCLibraryFunction(FD, "strlcpy")) {
-if (containsBadStrlcpyPattern(CE)) {
+  } else if (CheckerContext::isCLibraryFunction(FD, "strlcpy") ||
+ CheckerContext::isCLibraryFunction(FD, "strlcat")) {
+if (containsBadStrlcpyStrlcatPattern(CE)) {
   const Expr *DstArg = CE->getArg(0);
   const Expr *LenArg = CE->getArg(2);
   PathDiagnosticLocation Loc =
@@ -230,13 +250,27 @@
 
   SmallString<256> S;
   llvm::raw_svector_ostream os(S);
-  os << "The third argument is larger than the size of the input buffer. ";
-  if (!DstName.empty())
-os << "Replace with the value 'sizeof(" << DstName << ")` or lower";
-
-  BR.EmitBasicReport(FD, Checker, "Anti-pattern in the argument",
- "C String API", os.str(), Loc,
- LenArg->getSourceRange());
+  if (CheckerContext::isCLibraryFunction(FD, "str

[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-09-22 Thread David CARLIER via Phabricator via cfe-commits
devnexen added inline comments.



Comment at: lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp:275
+os << "sizeof(" << DstName << ")";
+  else
+os << "sizeof()";

MaskRay wrote:
> Why can't this `else if` case be folded into the `strlcpy` case? There are 
> lots of duplication.
> 
> `strlcpy` does not check `DstName.empty()` but this one does. Is there any 
> cases I am missing?
strlcpy does but agreed with your first statement, this handling case for both 
are more different than my initial plan defined them.


https://reviews.llvm.org/D49722



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


[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-09-22 Thread Fangrui Song via Phabricator via cfe-commits
MaskRay added inline comments.



Comment at: lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp:275
+os << "sizeof(" << DstName << ")";
+  else
+os << "sizeof()";

Why can't this `else if` case be folded into the `strlcpy` case? There are lots 
of duplication.

`strlcpy` does not check `DstName.empty()` but this one does. Is there any 
cases I am missing?


https://reviews.llvm.org/D49722



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


[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-09-22 Thread David CARLIER via Phabricator via cfe-commits
devnexen added a comment.

ping :)


https://reviews.llvm.org/D49722



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


[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-09-14 Thread David CARLIER via Phabricator via cfe-commits
devnexen updated this revision to Diff 165604.

https://reviews.llvm.org/D49722

Files:
  lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
  test/Analysis/cstring-syntax.c

Index: test/Analysis/cstring-syntax.c
===
--- test/Analysis/cstring-syntax.c
+++ test/Analysis/cstring-syntax.c
@@ -7,6 +7,7 @@
 char  *strncat(char *, const char *, size_t);
 size_t strlen (const char *s);
 size_t strlcpy(char *, const char *, size_t);
+size_t strlcat(char *, const char *, size_t);
 
 void testStrncat(const char *src) {
   char dest[10];
@@ -33,3 +34,21 @@
   strlcpy(dest + 5, src, 5);
   strlcpy(dest + 5, src, 10); // expected-warning {{The third argument is larger than the size of the input buffer.}}
 }
+
+void testStrlcat(const char *src) {
+  char dest[10];
+  size_t badlen = 20;
+  size_t ulen;
+  strlcpy(dest, "a", sizeof("a") - 1);
+  strlcat(dest, "", (sizeof("") - 1) - sizeof(dest) - 1);
+  strlcpy(dest, "012345678", sizeof(dest));
+  strlcat(dest, "910", sizeof(dest));
+  strlcpy(dest, "0123456789", sizeof(dest));
+  strlcpy(dest, "0123456789", sizeof(dest));
+  strlcat(dest, "0123456789", badlen / 2);
+  strlcat(dest, "0123456789", badlen); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value sizeof(dest) or lower}}
+  strlcat(dest, "0123456789", badlen - strlen(dest) - 1);
+  strlcat(dest, src, ulen);
+  strlcpy(dest, src, 5);
+  strlcat(dest + 5, src, badlen); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value sizeof() or lower}}
+}
Index: lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
+++ lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
@@ -90,7 +90,16 @@
   ///   strlcpy(dst, "abcd", 4);
   ///   strlcpy(dst + 3, "abcd", 2);
   ///   strlcpy(dst, "abcd", cpy);
-  bool containsBadStrlcpyPattern(const CallExpr *CE);
+  /// Identify erroneous patterns in the last argument to strlcat - the number
+  /// of bytes to copy.
+  /// The bad pattern checked is when the last argument is basically
+  /// pointing to the destination buffer size or argument larger or
+  /// equal to.
+  ///   char dst[2];
+  ///   strlcat(dst, src2, sizeof(dst));
+  ///   strlcat(dst, src2, 2);
+  ///   strlcat(dst, src2, 10);
+  bool containsBadStrlcpyStrlcatPattern(const CallExpr *CE);
 
 public:
   WalkAST(const CheckerBase *Checker, BugReporter &BR, AnalysisDeclContext *AC)
@@ -142,15 +151,19 @@
   return false;
 }
 
-bool WalkAST::containsBadStrlcpyPattern(const CallExpr *CE) {
+bool WalkAST::containsBadStrlcpyStrlcatPattern(const CallExpr *CE) {
   if (CE->getNumArgs() != 3)
 return false;
+  const FunctionDecl *FD = CE->getDirectCallee();
+  bool Append = CheckerContext::isCLibraryFunction(FD, "strlcat");
   const Expr *DstArg = CE->getArg(0);
   const Expr *LenArg = CE->getArg(2);
 
   const auto *DstArgDecl = dyn_cast(DstArg->IgnoreParenImpCasts());
   const auto *LenArgDecl = dyn_cast(LenArg->IgnoreParenLValueCasts());
   uint64_t DstOff = 0;
+  if (isSizeof(LenArg, DstArg))
+return false;
   // - size_t dstlen = sizeof(dst)
   if (LenArgDecl) {
 const auto *LenArgVal = dyn_cast(LenArgDecl->getDecl());
@@ -181,8 +194,14 @@
   if (const auto *Buffer = dyn_cast(DstArgDecl->getType())) {
 ASTContext &C = BR.getContext();
 uint64_t BufferLen = C.getTypeSize(Buffer) / 8;
-if ((BufferLen - DstOff) < ILRawVal)
-  return true;
+auto RemainingBufferLen = BufferLen - DstOff;
+if (Append) {
+  if (RemainingBufferLen <= ILRawVal)
+return true;
+} else {
+  if (RemainingBufferLen < ILRawVal)
+return true;
+}
   }
 }
   }
@@ -220,7 +239,7 @@
  LenArg->getSourceRange());
 }
   } else if (CheckerContext::isCLibraryFunction(FD, "strlcpy")) {
-if (containsBadStrlcpyPattern(CE)) {
+if (containsBadStrlcpyStrlcatPattern(CE)) {
   const Expr *DstArg = CE->getArg(0);
   const Expr *LenArg = CE->getArg(2);
   PathDiagnosticLocation Loc =
@@ -234,6 +253,29 @@
   if (!DstName.empty())
 os << "Replace with the value 'sizeof(" << DstName << ")` or lower";
 
+  BR.EmitBasicReport(FD, Checker, "Anti-pattern in the argument",
+ "C String API", os.str(), Loc,
+ LenArg->getSourceRange());
+}
+  } else if (CheckerContext::isCLibraryFunction(FD, "strlcat")) {
+if (containsBadStrlcpyStrlcatPattern(CE)) {
+  const Expr *DstArg = CE->getArg(0);
+  const Expr *LenArg = CE->getArg(2);
+  PathDiagnosticLocation Loc =
+PathDiagnosticLocation::createBegin(LenArg, BR.getSourceManager(), AC);
+
+  StringRef DstName = getPrintableName(DstArg);
+
+  SmallS

[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-09-14 Thread Fangrui Song via Phabricator via cfe-commits
MaskRay added inline comments.



Comment at: test/Analysis/cstring-syntax.c:49
+  strlcat(dest, "0123456789", badlen / 2);
+  strlcat(dest, "0123456789", badlen); // expected-warning {{The third 
argument allows to potentially copy more bytes than it should. Replace with the 
value 'badlen' - strlen(dest) - 1 or lower}}
+  strlcat(dest, "0123456789", badlen - strlen(dest) - 1);

devnexen wrote:
> NoQ wrote:
> > The suggested fix is a bit weird.
> > 
> > The correct code for appending `src` to `dst` is either `strlcat(dst, src, 
> > sizeof(dst));` (the approach suggested by the man page) or `strlcat(dst + 
> > strlen(dst) + 1, src, sizeof(dst) - strlen(dst) - 1)` (which is equivalent 
> > but faster if you already know `strlen(dst)`). In both cases you can 
> > specify a smaller value but not a larger value.
> In fact in this case the message is misleading/a bit wrong.
I think `strlcat` is very clumsy to you if you need to add an offset to 
`dest`...

For
`strlcat(dst + strlen(dst) + 1, src, sizeof(dst) - strlen(dst) - 1)`

I suppose you meant:

`strlcpy(dst + strlen(dst), src, sizeof(dst) - strlen(dst))`

... but the suggestion does not look very appealing. `strlcat(dst, ..., 
sizeof(dst)` if good enough as a suggested fix.


https://reviews.llvm.org/D49722



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


[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-09-14 Thread David CARLIER via Phabricator via cfe-commits
devnexen added inline comments.



Comment at: lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp:199
+if (Append)
+  RemainingBufferLen -= 1;
+if (RemainingBufferLen < ILRawVal)

MaskRay wrote:
> `RemainingBufferLen` is `uint64_t`. Can the `-= 1` overflow?
That s a good point. I may redo as it was before.


https://reviews.llvm.org/D49722



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


[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-09-14 Thread Fangrui Song via Phabricator via cfe-commits
MaskRay added inline comments.



Comment at: lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp:164
+  // - sizeof(dst)
+  if (Append && isSizeof(LenArg, DstArg))
+return true;

george.karpenkov wrote:
> george.karpenkov wrote:
> > george.karpenkov wrote:
> > > I am confused on what is happening in this branch and why is it bad. 
> > > Could we add a commend?
> > Sorry I'm still confused about this branch: could you clarify?
> Ah, OK, I see it needs one more byte due to null-termination.
I think the `if (isSizeof(LenArg, DstArg))` check is fine so it returns `false`.

`strlcat(dst, src, sizeof dst)` is good.



Comment at: lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp:199
+if (Append)
+  RemainingBufferLen -= 1;
+if (RemainingBufferLen < ILRawVal)

`RemainingBufferLen` is `uint64_t`. Can the `-= 1` overflow?


https://reviews.llvm.org/D49722



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


[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-09-06 Thread David CARLIER via Phabricator via cfe-commits
devnexen updated this revision to Diff 164355.
devnexen added a comment.

- Correcting misleading message and advising proper fix.


https://reviews.llvm.org/D49722

Files:
  lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
  test/Analysis/cstring-syntax.c

Index: test/Analysis/cstring-syntax.c
===
--- test/Analysis/cstring-syntax.c
+++ test/Analysis/cstring-syntax.c
@@ -7,6 +7,7 @@
 char  *strncat(char *, const char *, size_t);
 size_t strlen (const char *s);
 size_t strlcpy(char *, const char *, size_t);
+size_t strlcat(char *, const char *, size_t);
 
 void testStrncat(const char *src) {
   char dest[10];
@@ -33,3 +34,21 @@
   strlcpy(dest + 5, src, 5);
   strlcpy(dest + 5, src, 10); // expected-warning {{The third argument is larger than the size of the input buffer.}}
 }
+
+void testStrlcat(const char *src) {
+  char dest[10];
+  size_t badlen = 20;
+  size_t ulen;
+  strlcpy(dest, "a", sizeof("a") - 1);
+  strlcat(dest, "", (sizeof("") - 1) - sizeof(dest) - 1);
+  strlcpy(dest, "012345678", sizeof(dest));
+  strlcat(dest, "910", sizeof(dest));
+  strlcpy(dest, "0123456789", sizeof(dest));
+  strlcpy(dest, "0123456789", sizeof(dest));
+  strlcat(dest, "0123456789", badlen / 2);
+  strlcat(dest, "0123456789", badlen); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value sizeof(dest) - strlen(dest) - 1 or lower}}
+  strlcat(dest, "0123456789", badlen - strlen(dest) - 1);
+  strlcat(dest, src, ulen);
+  strlcpy(dest, src, 5);
+  strlcat(dest + 5, src, badlen); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value sizeof() - strlen() - 1 or lower}}
+}
Index: lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
+++ lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
@@ -90,7 +90,16 @@
   ///   strlcpy(dst, "abcd", 4);
   ///   strlcpy(dst + 3, "abcd", 2);
   ///   strlcpy(dst, "abcd", cpy);
-  bool containsBadStrlcpyPattern(const CallExpr *CE);
+  /// Identify erroneous patterns in the last argument to strlcat - the number
+  /// of bytes to copy.
+  /// The bad pattern checked is when the last argument is basically
+  /// pointing to the destination buffer size or argument larger or
+  /// equal to.
+  ///   char dst[2];
+  ///   strlcat(dst, src2, sizeof(dst));
+  ///   strlcat(dst, src2, 2);
+  ///   strlcat(dst, src2, 10);
+  bool containsBadStrlcpyStrlcatPattern(const CallExpr *CE);
 
 public:
   WalkAST(const CheckerBase *Checker, BugReporter &BR, AnalysisDeclContext *AC)
@@ -142,15 +151,19 @@
   return false;
 }
 
-bool WalkAST::containsBadStrlcpyPattern(const CallExpr *CE) {
+bool WalkAST::containsBadStrlcpyStrlcatPattern(const CallExpr *CE) {
   if (CE->getNumArgs() != 3)
 return false;
+  const FunctionDecl *FD = CE->getDirectCallee();
+  bool Append = CheckerContext::isCLibraryFunction(FD, "strlcat");
   const Expr *DstArg = CE->getArg(0);
   const Expr *LenArg = CE->getArg(2);
 
   const auto *DstArgDecl = dyn_cast(DstArg->IgnoreParenImpCasts());
   const auto *LenArgDecl = dyn_cast(LenArg->IgnoreParenLValueCasts());
   uint64_t DstOff = 0;
+  if (isSizeof(LenArg, DstArg))
+return false;
   // - size_t dstlen = sizeof(dst)
   if (LenArgDecl) {
 const auto *LenArgVal = dyn_cast(LenArgDecl->getDecl());
@@ -181,7 +194,10 @@
   if (const auto *Buffer = dyn_cast(DstArgDecl->getType())) {
 ASTContext &C = BR.getContext();
 uint64_t BufferLen = C.getTypeSize(Buffer) / 8;
-if ((BufferLen - DstOff) < ILRawVal)
+auto RemainingBufferLen = BufferLen - DstOff;
+if (Append)
+  RemainingBufferLen -= 1;
+if (RemainingBufferLen < ILRawVal)
   return true;
   }
 }
@@ -220,7 +236,7 @@
  LenArg->getSourceRange());
 }
   } else if (CheckerContext::isCLibraryFunction(FD, "strlcpy")) {
-if (containsBadStrlcpyPattern(CE)) {
+if (containsBadStrlcpyStrlcatPattern(CE)) {
   const Expr *DstArg = CE->getArg(0);
   const Expr *LenArg = CE->getArg(2);
   PathDiagnosticLocation Loc =
@@ -234,6 +250,29 @@
   if (!DstName.empty())
 os << "Replace with the value 'sizeof(" << DstName << ")` or lower";
 
+  BR.EmitBasicReport(FD, Checker, "Anti-pattern in the argument",
+ "C String API", os.str(), Loc,
+ LenArg->getSourceRange());
+}
+  } else if (CheckerContext::isCLibraryFunction(FD, "strlcat")) {
+if (containsBadStrlcpyStrlcatPattern(CE)) {
+  const Expr *DstArg = CE->getArg(0);
+  const Expr *LenArg = CE->getArg(2);
+  PathDiagnosticLocation Loc =
+PathDiagnosticLocation::createBegin(LenArg, BR.getSourceManager(), AC);
+
+  StringRef DstName = getPrintableName(DstArg

[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-09-06 Thread David CARLIER via Phabricator via cfe-commits
devnexen added inline comments.



Comment at: test/Analysis/cstring-syntax.c:49
+  strlcat(dest, "0123456789", badlen / 2);
+  strlcat(dest, "0123456789", badlen); // expected-warning {{The third 
argument allows to potentially copy more bytes than it should. Replace with the 
value 'badlen' - strlen(dest) - 1 or lower}}
+  strlcat(dest, "0123456789", badlen - strlen(dest) - 1);

NoQ wrote:
> The suggested fix is a bit weird.
> 
> The correct code for appending `src` to `dst` is either `strlcat(dst, src, 
> sizeof(dst));` (the approach suggested by the man page) or `strlcat(dst + 
> strlen(dst) + 1, src, sizeof(dst) - strlen(dst) - 1)` (which is equivalent 
> but faster if you already know `strlen(dst)`). In both cases you can specify 
> a smaller value but not a larger value.
In fact in this case the message is misleading/a bit wrong.


https://reviews.llvm.org/D49722



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


[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-09-06 Thread Artem Dergachev via Phabricator via cfe-commits
NoQ added inline comments.



Comment at: test/Analysis/cstring-syntax.c:49
+  strlcat(dest, "0123456789", badlen / 2);
+  strlcat(dest, "0123456789", badlen); // expected-warning {{The third 
argument allows to potentially copy more bytes than it should. Replace with the 
value 'badlen' - strlen(dest) - 1 or lower}}
+  strlcat(dest, "0123456789", badlen - strlen(dest) - 1);

The suggested fix is a bit weird.

The correct code for appending `src` to `dst` is either `strlcat(dst, src, 
sizeof(dst));` (the approach suggested by the man page) or `strlcat(dst + 
strlen(dst) + 1, src, sizeof(dst) - strlen(dst) - 1)` (which is equivalent but 
faster if you already know `strlen(dst)`). In both cases you can specify a 
smaller value but not a larger value.


https://reviews.llvm.org/D49722



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


[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-09-06 Thread David CARLIER via Phabricator via cfe-commits
devnexen added a comment.

ping @george.karpenkov after that I won t bother you for a long time :)


https://reviews.llvm.org/D49722



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


[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-09-03 Thread David CARLIER via Phabricator via cfe-commits
devnexen added a comment.

ping


https://reviews.llvm.org/D49722



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


[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-08-27 Thread David CARLIER via Phabricator via cfe-commits
devnexen added a comment.

ping


https://reviews.llvm.org/D49722



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


[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-08-22 Thread David CARLIER via Phabricator via cfe-commits
devnexen updated this revision to Diff 162139.
devnexen added a comment.

- Returns immediately for both case when sizeof destination.
- Adding few more cases.


https://reviews.llvm.org/D49722

Files:
  lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
  test/Analysis/cstring-syntax.c

Index: test/Analysis/cstring-syntax.c
===
--- test/Analysis/cstring-syntax.c
+++ test/Analysis/cstring-syntax.c
@@ -7,6 +7,7 @@
 char  *strncat(char *, const char *, size_t);
 size_t strlen (const char *s);
 size_t strlcpy(char *, const char *, size_t);
+size_t strlcat(char *, const char *, size_t);
 
 void testStrncat(const char *src) {
   char dest[10];
@@ -33,3 +34,21 @@
   strlcpy(dest + 5, src, 5);
   strlcpy(dest + 5, src, 10); // expected-warning {{The third argument is larger than the size of the input buffer.}}
 }
+
+void testStrlcat(const char *src) {
+  char dest[10];
+  size_t badlen = 20;
+  size_t ulen;
+  strlcpy(dest, "a", sizeof("a") - 1);
+  strlcat(dest, "", (sizeof("") - 1) - sizeof(dest) - 1);
+  strlcpy(dest, "012345678", sizeof(dest));
+  strlcat(dest, "910", sizeof(dest));
+  strlcpy(dest, "0123456789", sizeof(dest));
+  strlcpy(dest, "0123456789", sizeof(dest));
+  strlcat(dest, "0123456789", badlen / 2);
+  strlcat(dest, "0123456789", badlen); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value 'badlen' - strlen(dest) - 1 or lower}}
+  strlcat(dest, "0123456789", badlen - strlen(dest) - 1);
+  strlcat(dest, src, ulen);
+  strlcpy(dest, src, 5);
+  strlcat(dest + 5, src, badlen); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value 'badlen' - strlen() - 1 or lower}}
+}
Index: lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
+++ lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
@@ -90,7 +90,16 @@
   ///   strlcpy(dst, "abcd", 4);
   ///   strlcpy(dst + 3, "abcd", 2);
   ///   strlcpy(dst, "abcd", cpy);
-  bool containsBadStrlcpyPattern(const CallExpr *CE);
+  /// Identify erroneous patterns in the last argument to strlcat - the number
+  /// of bytes to copy.
+  /// The bad pattern checked is when the last argument is basically
+  /// pointing to the destination buffer size or argument larger or
+  /// equal to.  
+  ///   char dst[2];
+  ///   strlcat(dst, src2, sizeof(dst));
+  ///   strlcat(dst, src2, 2);
+  ///   strlcat(dst, src2, 10);
+  bool containsBadStrlcpyStrlcatPattern(const CallExpr *CE);
 
 public:
   WalkAST(const CheckerBase *Checker, BugReporter &BR, AnalysisDeclContext *AC)
@@ -142,15 +151,19 @@
   return false;
 }
 
-bool WalkAST::containsBadStrlcpyPattern(const CallExpr *CE) {
+bool WalkAST::containsBadStrlcpyStrlcatPattern(const CallExpr *CE) {
   if (CE->getNumArgs() != 3)
 return false;
+  const FunctionDecl *FD = CE->getDirectCallee();
+  bool Append = CheckerContext::isCLibraryFunction(FD, "strlcat");
   const Expr *DstArg = CE->getArg(0);
   const Expr *LenArg = CE->getArg(2);
 
   const auto *DstArgDecl = dyn_cast(DstArg->IgnoreParenImpCasts());
   const auto *LenArgDecl = dyn_cast(LenArg->IgnoreParenLValueCasts());
   uint64_t DstOff = 0;
+  if (isSizeof(LenArg, DstArg))
+return false;
   // - size_t dstlen = sizeof(dst)
   if (LenArgDecl) {
 const auto *LenArgVal = dyn_cast(LenArgDecl->getDecl());
@@ -181,7 +194,10 @@
   if (const auto *Buffer = dyn_cast(DstArgDecl->getType())) {
 ASTContext &C = BR.getContext();
 uint64_t BufferLen = C.getTypeSize(Buffer) / 8;
-if ((BufferLen - DstOff) < ILRawVal)
+auto RemainingBufferLen = BufferLen - DstOff;
+if (Append)
+  RemainingBufferLen -= 1;
+if (RemainingBufferLen < ILRawVal)
   return true;
   }
 }
@@ -220,7 +236,7 @@
  LenArg->getSourceRange());
 }
   } else if (CheckerContext::isCLibraryFunction(FD, "strlcpy")) {
-if (containsBadStrlcpyPattern(CE)) {
+if (containsBadStrlcpyStrlcatPattern(CE)) {
   const Expr *DstArg = CE->getArg(0);
   const Expr *LenArg = CE->getArg(2);
   PathDiagnosticLocation Loc =
@@ -234,6 +250,34 @@
   if (!DstName.empty())
 os << "Replace with the value 'sizeof(" << DstName << ")` or lower";
 
+  BR.EmitBasicReport(FD, Checker, "Anti-pattern in the argument",
+ "C String API", os.str(), Loc,
+ LenArg->getSourceRange());
+}
+  } else if (CheckerContext::isCLibraryFunction(FD, "strlcat")) {
+if (containsBadStrlcpyStrlcatPattern(CE)) {
+  const Expr *DstArg = CE->getArg(0);
+  const Expr *LenArg = CE->getArg(2);
+  PathDiagnosticLocation Loc =
+PathDiagnosticLocation::createBegin(LenArg, BR.getSourceManager(), AC);
+
+  StringRef DstNam

[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-08-22 Thread George Karpenkov via Phabricator via cfe-commits
george.karpenkov reopened this revision.
george.karpenkov added a comment.
This revision is now accepted and ready to land.

This is not correct, `strlcat(dest, "mystr", sizeof(dest))` is perfectly fine, 
as can be seen in many examples including strlcat man page.


Repository:
  rL LLVM

https://reviews.llvm.org/D49722



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


[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-08-15 Thread Artem Dergachev via Phabricator via cfe-commits
NoQ added inline comments.



Comment at: cfe/trunk/test/Analysis/cstring-syntax.c:45
+  strlcpy(dest, "012345678", sizeof(dest));
+  strlcat(dest, "910", sizeof(dest)); // expected-warning {{The third argument 
allows to potentially copy more bytes than it should. Replace with the value  
  - strlen(dest) - 1 or lower}}
+  strlcpy(dest, "0123456789", sizeof(dest));

There seem to be two spaces around ``.


Repository:
  rL LLVM

https://reviews.llvm.org/D49722



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


[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-08-13 Thread David CARLIER via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL339641: [CStringSyntaxChecker] Check strlcat sizeof check 
(authored by devnexen, committed by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D49722?vs=160272&id=160513#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D49722

Files:
  cfe/trunk/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
  cfe/trunk/test/Analysis/cstring-syntax.c

Index: cfe/trunk/test/Analysis/cstring-syntax.c
===
--- cfe/trunk/test/Analysis/cstring-syntax.c
+++ cfe/trunk/test/Analysis/cstring-syntax.c
@@ -7,6 +7,7 @@
 char  *strncat(char *, const char *, size_t);
 size_t strlen (const char *s);
 size_t strlcpy(char *, const char *, size_t);
+size_t strlcat(char *, const char *, size_t);
 
 void testStrncat(const char *src) {
   char dest[10];
@@ -33,3 +34,19 @@
   strlcpy(dest + 5, src, 5);
   strlcpy(dest + 5, src, 10); // expected-warning {{The third argument is larger than the size of the input buffer.}}
 }
+
+void testStrlcat(const char *src) {
+  char dest[10];
+  size_t badlen = 10;
+  size_t ulen;
+  strlcpy(dest, "a", sizeof("a") - 1);
+  strlcat(dest, "", (sizeof("") - 1) - sizeof(dest) - 1);
+  strlcpy(dest, "012345678", sizeof(dest));
+  strlcat(dest, "910", sizeof(dest)); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value- strlen(dest) - 1 or lower}}
+  strlcpy(dest, "0123456789", sizeof(dest));
+  strlcat(dest, "0123456789", badlen); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value 'badlen' - strlen(dest) - 1 or lower}}
+  strlcat(dest, "0123456789", badlen - strlen(dest) - 1);
+  strlcat(dest, src, ulen);
+  strlcpy(dest, src, 5);
+  strlcat(dest + 5, src, badlen); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value 'badlen' - strlen() - 1 or lower}}
+}
Index: cfe/trunk/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
===
--- cfe/trunk/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
@@ -90,7 +90,16 @@
   ///   strlcpy(dst, "abcd", 4);
   ///   strlcpy(dst + 3, "abcd", 2);
   ///   strlcpy(dst, "abcd", cpy);
-  bool containsBadStrlcpyPattern(const CallExpr *CE);
+  /// Identify erroneous patterns in the last argument to strlcat - the number
+  /// of bytes to copy.
+  /// The bad pattern checked is when the last argument is basically
+  /// pointing to the destination buffer size or argument larger or
+  /// equal to.  
+  ///   char dst[2];
+  ///   strlcat(dst, src2, sizeof(dst));
+  ///   strlcat(dst, src2, 2);
+  ///   strlcat(dst, src2, 10);
+  bool containsBadStrlcpyStrlcatPattern(const CallExpr *CE);
 
 public:
   WalkAST(const CheckerBase *Checker, BugReporter &BR, AnalysisDeclContext *AC)
@@ -142,15 +151,21 @@
   return false;
 }
 
-bool WalkAST::containsBadStrlcpyPattern(const CallExpr *CE) {
+bool WalkAST::containsBadStrlcpyStrlcatPattern(const CallExpr *CE) {
   if (CE->getNumArgs() != 3)
 return false;
+  const FunctionDecl *FD = CE->getDirectCallee();
+  bool Append = CheckerContext::isCLibraryFunction(FD, "strlcat");
   const Expr *DstArg = CE->getArg(0);
   const Expr *LenArg = CE->getArg(2);
 
   const auto *DstArgDecl = dyn_cast(DstArg->IgnoreParenImpCasts());
   const auto *LenArgDecl = dyn_cast(LenArg->IgnoreParenLValueCasts());
   uint64_t DstOff = 0;
+  // - sizeof(dst)
+  // strlcat appends at most size - strlen(dst) - 1
+  if (Append && isSizeof(LenArg, DstArg))
+return true;
   // - size_t dstlen = sizeof(dst)
   if (LenArgDecl) {
 const auto *LenArgVal = dyn_cast(LenArgDecl->getDecl());
@@ -181,7 +196,10 @@
   if (const auto *Buffer = dyn_cast(DstArgDecl->getType())) {
 ASTContext &C = BR.getContext();
 uint64_t BufferLen = C.getTypeSize(Buffer) / 8;
-if ((BufferLen - DstOff) < ILRawVal)
+auto RemainingBufferLen = BufferLen - DstOff;
+if (Append)
+  RemainingBufferLen -= 1;
+if (RemainingBufferLen < ILRawVal)
   return true;
   }
 }
@@ -220,7 +238,7 @@
  LenArg->getSourceRange());
 }
   } else if (CheckerContext::isCLibraryFunction(FD, "strlcpy")) {
-if (containsBadStrlcpyPattern(CE)) {
+if (containsBadStrlcpyStrlcatPattern(CE)) {
   const Expr *DstArg = CE->getArg(0);
   const Expr *LenArg = CE->getArg(2);
   PathDiagnosticLocation Loc =
@@ -238,6 +256,34 @@
  "C String API", os.str(), Loc,
  LenArg->getSourceRange());
 }
+  } else if (CheckerContext::isCLibraryFunction(FD, "strlcat")) {
+if (containsBadStrlcpyStrlcatPattern(CE)) {
+  

[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-08-12 Thread David CARLIER via Phabricator via cfe-commits
devnexen updated this revision to Diff 160272.

https://reviews.llvm.org/D49722

Files:
  lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
  test/Analysis/cstring-syntax.c

Index: test/Analysis/cstring-syntax.c
===
--- test/Analysis/cstring-syntax.c
+++ test/Analysis/cstring-syntax.c
@@ -7,6 +7,7 @@
 char  *strncat(char *, const char *, size_t);
 size_t strlen (const char *s);
 size_t strlcpy(char *, const char *, size_t);
+size_t strlcat(char *, const char *, size_t);
 
 void testStrncat(const char *src) {
   char dest[10];
@@ -33,3 +34,19 @@
   strlcpy(dest + 5, src, 5);
   strlcpy(dest + 5, src, 10); // expected-warning {{The third argument is larger than the size of the input buffer.}}
 }
+
+void testStrlcat(const char *src) {
+  char dest[10];
+  size_t badlen = 10;
+  size_t ulen;
+  strlcpy(dest, "a", sizeof("a") - 1);
+  strlcat(dest, "", (sizeof("") - 1) - sizeof(dest) - 1);
+  strlcpy(dest, "012345678", sizeof(dest));
+  strlcat(dest, "910", sizeof(dest)); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value- strlen(dest) - 1 or lower}}
+  strlcpy(dest, "0123456789", sizeof(dest));
+  strlcat(dest, "0123456789", badlen); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value 'badlen' - strlen(dest) - 1 or lower}}
+  strlcat(dest, "0123456789", badlen - strlen(dest) - 1);
+  strlcat(dest, src, ulen);
+  strlcpy(dest, src, 5);
+  strlcat(dest + 5, src, badlen); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value 'badlen' - strlen() - 1 or lower}}
+}
Index: lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
+++ lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
@@ -90,7 +90,16 @@
   ///   strlcpy(dst, "abcd", 4);
   ///   strlcpy(dst + 3, "abcd", 2);
   ///   strlcpy(dst, "abcd", cpy);
-  bool containsBadStrlcpyPattern(const CallExpr *CE);
+  /// Identify erroneous patterns in the last argument to strlcat - the number
+  /// of bytes to copy.
+  /// The bad pattern checked is when the last argument is basically
+  /// pointing to the destination buffer size or argument larger or
+  /// equal to.  
+  ///   char dst[2];
+  ///   strlcat(dst, src2, sizeof(dst));
+  ///   strlcat(dst, src2, 2);
+  ///   strlcat(dst, src2, 10);
+  bool containsBadStrlcpyStrlcatPattern(const CallExpr *CE);
 
 public:
   WalkAST(const CheckerBase *Checker, BugReporter &BR, AnalysisDeclContext *AC)
@@ -142,15 +151,21 @@
   return false;
 }
 
-bool WalkAST::containsBadStrlcpyPattern(const CallExpr *CE) {
+bool WalkAST::containsBadStrlcpyStrlcatPattern(const CallExpr *CE) {
   if (CE->getNumArgs() != 3)
 return false;
+  const FunctionDecl *FD = CE->getDirectCallee();
+  bool Append = CheckerContext::isCLibraryFunction(FD, "strlcat");
   const Expr *DstArg = CE->getArg(0);
   const Expr *LenArg = CE->getArg(2);
 
   const auto *DstArgDecl = dyn_cast(DstArg->IgnoreParenImpCasts());
   const auto *LenArgDecl = dyn_cast(LenArg->IgnoreParenLValueCasts());
   uint64_t DstOff = 0;
+  // - sizeof(dst)
+  // strlcat appends at most size - strlen(dst) - 1
+  if (Append && isSizeof(LenArg, DstArg))
+return true;
   // - size_t dstlen = sizeof(dst)
   if (LenArgDecl) {
 const auto *LenArgVal = dyn_cast(LenArgDecl->getDecl());
@@ -181,7 +196,10 @@
   if (const auto *Buffer = dyn_cast(DstArgDecl->getType())) {
 ASTContext &C = BR.getContext();
 uint64_t BufferLen = C.getTypeSize(Buffer) / 8;
-if ((BufferLen - DstOff) < ILRawVal)
+auto RemainingBufferLen = BufferLen - DstOff;
+if (Append)
+  RemainingBufferLen -= 1;
+if (RemainingBufferLen < ILRawVal)
   return true;
   }
 }
@@ -220,7 +238,7 @@
  LenArg->getSourceRange());
 }
   } else if (CheckerContext::isCLibraryFunction(FD, "strlcpy")) {
-if (containsBadStrlcpyPattern(CE)) {
+if (containsBadStrlcpyStrlcatPattern(CE)) {
   const Expr *DstArg = CE->getArg(0);
   const Expr *LenArg = CE->getArg(2);
   PathDiagnosticLocation Loc =
@@ -234,6 +252,34 @@
   if (!DstName.empty())
 os << "Replace with the value 'sizeof(" << DstName << ")` or lower";
 
+  BR.EmitBasicReport(FD, Checker, "Anti-pattern in the argument",
+ "C String API", os.str(), Loc,
+ LenArg->getSourceRange());
+}
+  } else if (CheckerContext::isCLibraryFunction(FD, "strlcat")) {
+if (containsBadStrlcpyStrlcatPattern(CE)) {
+  const Expr *DstArg = CE->getArg(0);
+  const Expr *LenArg = CE->getArg(2);
+  PathDiagnosticLocation Loc =
+PathDiagnosticLocation::createBegin(LenArg, BR.getSourceManager(), A

[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-08-10 Thread George Karpenkov via Phabricator via cfe-commits
george.karpenkov requested changes to this revision.
george.karpenkov added inline comments.
This revision now requires changes to proceed.



Comment at: lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp:164
+  // - sizeof(dst)
+  if (Append && isSizeof(LenArg, DstArg))
+return true;

george.karpenkov wrote:
> george.karpenkov wrote:
> > I am confused on what is happening in this branch and why is it bad. Could 
> > we add a commend?
> Sorry I'm still confused about this branch: could you clarify?
Ah, OK, I see it needs one more byte due to null-termination.



Comment at: lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp:199
 uint64_t BufferLen = C.getTypeSize(Buffer) / 8;
-if ((BufferLen - DstOff) < ILRawVal)
-  return true;
+auto RemainingBufferLen = BufferLen - DstOff;
+if (Append) {

Probably better expressed as:

```
if (Append)
  RemainingBufferLen -= 1;
```

Then you don't need branching.


https://reviews.llvm.org/D49722



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


[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-08-10 Thread George Karpenkov via Phabricator via cfe-commits
george.karpenkov added inline comments.



Comment at: lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp:164
+  // - sizeof(dst)
+  if (Append && isSizeof(LenArg, DstArg))
+return true;

george.karpenkov wrote:
> I am confused on what is happening in this branch and why is it bad. Could we 
> add a commend?
Sorry I'm still confused about this branch: could you clarify?


https://reviews.llvm.org/D49722



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


[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-08-09 Thread David CARLIER via Phabricator via cfe-commits
devnexen added a comment.

ping but will be for 8.0 :)


https://reviews.llvm.org/D49722



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


[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-07-30 Thread David CARLIER via Phabricator via cfe-commits
devnexen added a comment.

ping :)


https://reviews.llvm.org/D49722



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


[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-07-30 Thread David CARLIER via Phabricator via cfe-commits
devnexen updated this revision to Diff 158062.

https://reviews.llvm.org/D49722

Files:
  lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
  test/Analysis/cstring-syntax.c

Index: test/Analysis/cstring-syntax.c
===
--- test/Analysis/cstring-syntax.c
+++ test/Analysis/cstring-syntax.c
@@ -7,6 +7,7 @@
 char  *strncat(char *, const char *, size_t);
 size_t strlen (const char *s);
 size_t strlcpy(char *, const char *, size_t);
+size_t strlcat(char *, const char *, size_t);
 
 void testStrncat(const char *src) {
   char dest[10];
@@ -33,3 +34,19 @@
   strlcpy(dest + 5, src, 5);
   strlcpy(dest + 5, src, 10); // expected-warning {{The third argument is larger than the size of the input buffer.}}
 }
+
+void testStrlcat(const char *src) {
+  char dest[10];
+  size_t badlen = 10;
+  size_t ulen;
+  strlcpy(dest, "a", sizeof("a") - 1);
+  strlcat(dest, "", (sizeof("") - 1) - sizeof(dest) - 1);
+  strlcpy(dest, "012345678", sizeof(dest));
+  strlcat(dest, "910", sizeof(dest)); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value- strlen(dest) - 1 or lower}}
+  strlcpy(dest, "0123456789", sizeof(dest));
+  strlcat(dest, "0123456789", badlen); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value 'badlen' - strlen(dest) - 1 or lower}}
+  strlcat(dest, "0123456789", badlen - strlen(dest) - 1);
+  strlcat(dest, src, ulen);
+  strlcpy(dest, src, 5);
+  strlcat(dest + 5, src, badlen); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value 'badlen' - strlen() - 1 or lower}}
+}
Index: lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
+++ lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
@@ -90,7 +90,16 @@
   ///   strlcpy(dst, "abcd", 4);
   ///   strlcpy(dst + 3, "abcd", 2);
   ///   strlcpy(dst, "abcd", cpy);
-  bool containsBadStrlcpyPattern(const CallExpr *CE);
+  /// Identify erroneous patterns in the last argument to strlcat - the number
+  /// of bytes to copy.
+  /// The bad pattern checked is when the last argument is basically
+  /// pointing to the destination buffer size or argument larger or
+  /// equal to.  
+  ///   char dst[2];
+  ///   strlcat(dst, src2, sizeof(dst));
+  ///   strlcat(dst, src2, 2);
+  ///   strlcat(dst, src2, 10);
+  bool containsBadStrlcpyStrlcatPattern(const CallExpr *CE);
 
 public:
   WalkAST(const CheckerBase *Checker, BugReporter &BR, AnalysisDeclContext *AC)
@@ -142,15 +151,21 @@
   return false;
 }
 
-bool WalkAST::containsBadStrlcpyPattern(const CallExpr *CE) {
+bool WalkAST::containsBadStrlcpyStrlcatPattern(const CallExpr *CE) {
   if (CE->getNumArgs() != 3)
 return false;
+  const FunctionDecl *FD = CE->getDirectCallee();
+  bool Append = CheckerContext::isCLibraryFunction(FD, "strlcat");
   const Expr *DstArg = CE->getArg(0);
   const Expr *LenArg = CE->getArg(2);
 
   const auto *DstArgDecl = dyn_cast(DstArg->IgnoreParenImpCasts());
   const auto *LenArgDecl = dyn_cast(LenArg->IgnoreParenLValueCasts());
   uint64_t DstOff = 0;
+  // - sizeof(dst)
+  // strlcat appends at most size - strlen(dst) - 1
+  if (Append && isSizeof(LenArg, DstArg))
+return true;
   // - size_t dstlen = sizeof(dst)
   if (LenArgDecl) {
 const auto *LenArgVal = dyn_cast(LenArgDecl->getDecl());
@@ -181,8 +196,14 @@
   if (const auto *Buffer = dyn_cast(DstArgDecl->getType())) {
 ASTContext &C = BR.getContext();
 uint64_t BufferLen = C.getTypeSize(Buffer) / 8;
-if ((BufferLen - DstOff) < ILRawVal)
-  return true;
+auto RemainingBufferLen = BufferLen - DstOff;
+if (Append) {
+  if (RemainingBufferLen <= ILRawVal)
+return true;
+} else {
+  if (RemainingBufferLen < ILRawVal)
+return true;
+}
   }
 }
   }
@@ -220,7 +241,7 @@
  LenArg->getSourceRange());
 }
   } else if (CheckerContext::isCLibraryFunction(FD, "strlcpy")) {
-if (containsBadStrlcpyPattern(CE)) {
+if (containsBadStrlcpyStrlcatPattern(CE)) {
   const Expr *DstArg = CE->getArg(0);
   const Expr *LenArg = CE->getArg(2);
   PathDiagnosticLocation Loc =
@@ -234,6 +255,34 @@
   if (!DstName.empty())
 os << "Replace with the value 'sizeof(" << DstName << ")` or lower";
 
+  BR.EmitBasicReport(FD, Checker, "Anti-pattern in the argument",
+ "C String API", os.str(), Loc,
+ LenArg->getSourceRange());
+}
+  } else if (CheckerContext::isCLibraryFunction(FD, "strlcat")) {
+if (containsBadStrlcpyStrlcatPattern(CE)) {
+  const Expr *DstArg = CE->getArg(0);
+  const Expr *LenArg = CE->getArg(2);
+  PathD

[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-07-30 Thread George Karpenkov via Phabricator via cfe-commits
george.karpenkov requested changes to this revision.
george.karpenkov added inline comments.
This revision now requires changes to proceed.



Comment at: lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp:154
 
-bool WalkAST::containsBadStrlcpyPattern(const CallExpr *CE) {
+bool WalkAST::containsBadStrlcpyStrlcatPattern(const CallExpr *CE, bool 
Append) {
   if (CE->getNumArgs() != 3)

`Append` can be deduced from a call expression; I think it would be better to 
drop it from the parameter list and calculate again in the function body.



Comment at: lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp:164
+  // - sizeof(dst)
+  if (Append && isSizeof(LenArg, DstArg))
+return true;

I am confused on what is happening in this branch and why is it bad. Could we 
add a commend?



Comment at: lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp:196
 uint64_t BufferLen = C.getTypeSize(Buffer) / 8;
-if ((BufferLen - DstOff) < ILRawVal)
-  return true;
+BufferLen -= DstOff;
+if (Append) {

Better to introduce a new variable, e.g. `RemainingBufferLen`


https://reviews.llvm.org/D49722



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


[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-07-30 Thread David CARLIER via Phabricator via cfe-commits
devnexen added a comment.

ping :)


https://reviews.llvm.org/D49722



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


[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-07-25 Thread David CARLIER via Phabricator via cfe-commits
devnexen updated this revision to Diff 157381.

https://reviews.llvm.org/D49722

Files:
  lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
  test/Analysis/cstring-syntax.c

Index: test/Analysis/cstring-syntax.c
===
--- test/Analysis/cstring-syntax.c
+++ test/Analysis/cstring-syntax.c
@@ -7,6 +7,7 @@
 char  *strncat(char *, const char *, size_t);
 size_t strlen (const char *s);
 size_t strlcpy(char *, const char *, size_t);
+size_t strlcat(char *, const char *, size_t);
 
 void testStrncat(const char *src) {
   char dest[10];
@@ -33,3 +34,19 @@
   strlcpy(dest + 5, src, 5);
   strlcpy(dest + 5, src, 10); // expected-warning {{The third argument is larger than the size of the input buffer.}}
 }
+
+void testStrlcat(const char *src) {
+  char dest[10];
+  size_t badlen = 10;
+  size_t ulen;
+  strlcpy(dest, "a", sizeof("a") - 1);
+  strlcat(dest, "", (sizeof("") - 1) - sizeof(dest) - 1);
+  strlcpy(dest, "012345678", sizeof(dest));
+  strlcat(dest, "910", sizeof(dest)); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value- strlen(dest) - 1 or lower}}
+  strlcpy(dest, "0123456789", sizeof(dest));
+  strlcat(dest, "0123456789", badlen); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value 'badlen' - strlen(dest) - 1 or lower}}
+  strlcat(dest, "0123456789", badlen - strlen(dest) - 1);
+  strlcat(dest, src, ulen);
+  strlcpy(dest, src, 5);
+  strlcat(dest + 5, src, badlen); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value 'badlen' - strlen() - 1 or lower}}
+}
Index: lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
+++ lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
@@ -90,7 +90,16 @@
   ///   strlcpy(dst, "abcd", 4);
   ///   strlcpy(dst + 3, "abcd", 2);
   ///   strlcpy(dst, "abcd", cpy);
-  bool containsBadStrlcpyPattern(const CallExpr *CE);
+  /// Identify erroneous patterns in the last argument to strlcat - the number
+  /// of bytes to copy.
+  /// The bad pattern checked is when the last argument is basically
+  /// pointing to the destination buffer size or argument larger or
+  /// equal to.  
+  ///   char dst[2];
+  ///   strlcat(dst, src2, sizeof(dst));
+  ///   strlcat(dst, src2, 2);
+  ///   strlcat(dst, src2, 10);
+  bool containsBadStrlcpyStrlcatPattern(const CallExpr *CE, bool Append = false);
 
 public:
   WalkAST(const CheckerBase *Checker, BugReporter &BR, AnalysisDeclContext *AC)
@@ -142,15 +151,18 @@
   return false;
 }
 
-bool WalkAST::containsBadStrlcpyPattern(const CallExpr *CE) {
+bool WalkAST::containsBadStrlcpyStrlcatPattern(const CallExpr *CE, bool Append) {
   if (CE->getNumArgs() != 3)
 return false;
   const Expr *DstArg = CE->getArg(0);
   const Expr *LenArg = CE->getArg(2);
 
   const auto *DstArgDecl = dyn_cast(DstArg->IgnoreParenImpCasts());
   const auto *LenArgDecl = dyn_cast(LenArg->IgnoreParenLValueCasts());
   uint64_t DstOff = 0;
+  // - sizeof(dst)
+  if (Append && isSizeof(LenArg, DstArg))
+return true;
   // - size_t dstlen = sizeof(dst)
   if (LenArgDecl) {
 const auto *LenArgVal = dyn_cast(LenArgDecl->getDecl());
@@ -181,8 +193,14 @@
   if (const auto *Buffer = dyn_cast(DstArgDecl->getType())) {
 ASTContext &C = BR.getContext();
 uint64_t BufferLen = C.getTypeSize(Buffer) / 8;
-if ((BufferLen - DstOff) < ILRawVal)
-  return true;
+BufferLen -= DstOff;
+if (Append) {
+  if (BufferLen <= ILRawVal)
+return true;
+} else {
+  if (BufferLen < ILRawVal)
+return true;
+}
   }
 }
   }
@@ -220,7 +238,7 @@
  LenArg->getSourceRange());
 }
   } else if (CheckerContext::isCLibraryFunction(FD, "strlcpy")) {
-if (containsBadStrlcpyPattern(CE)) {
+if (containsBadStrlcpyStrlcatPattern(CE)) {
   const Expr *DstArg = CE->getArg(0);
   const Expr *LenArg = CE->getArg(2);
   PathDiagnosticLocation Loc =
@@ -234,6 +252,34 @@
   if (!DstName.empty())
 os << "Replace with the value 'sizeof(" << DstName << ")` or lower";
 
+  BR.EmitBasicReport(FD, Checker, "Anti-pattern in the argument",
+ "C String API", os.str(), Loc,
+ LenArg->getSourceRange());
+}
+  } else if (CheckerContext::isCLibraryFunction(FD, "strlcat")) {
+if (containsBadStrlcpyStrlcatPattern(CE, true)) {
+  const Expr *DstArg = CE->getArg(0);
+  const Expr *LenArg = CE->getArg(2);
+  PathDiagnosticLocation Loc =
+PathDiagnosticLocation::createBegin(LenArg, BR.getSourceManager(), AC);
+
+  StringRef DstName = getPrintableName(DstArg);
+  StringRe

[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-07-25 Thread George Karpenkov via Phabricator via cfe-commits
george.karpenkov requested changes to this revision.
george.karpenkov added a comment.
This revision now requires changes to proceed.

This has too much duplication with respect to your previous patch, and even 
Phabricator highlights it in yellow.


Repository:
  rC Clang

https://reviews.llvm.org/D49722



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


[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-07-25 Thread David CARLIER via Phabricator via cfe-commits
devnexen added a comment.

Hopefully will try to push it before the freeze just announced, that s my last 
change in this area (except potential fixes) :)


Repository:
  rC Clang

https://reviews.llvm.org/D49722



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


[PATCH] D49722: [CStringSyntaxChecker] Check strlcat sizeof check

2018-07-24 Thread David CARLIER via Phabricator via cfe-commits
devnexen created this revision.
devnexen added reviewers: george.karpenkov, NoQ.
devnexen created this object with visibility "All Users".
Herald added a subscriber: cfe-commits.

- Assuming strlcat is used with strlcpy we check as we can if the last argument 
does not equal os not larger than the buffer.
- Advising the proper usual pattern.


Repository:
  rC Clang

https://reviews.llvm.org/D49722

Files:
  lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
  test/Analysis/cstring-syntax.c

Index: test/Analysis/cstring-syntax.c
===
--- test/Analysis/cstring-syntax.c
+++ test/Analysis/cstring-syntax.c
@@ -7,6 +7,7 @@
 char  *strncat(char *, const char *, size_t);
 size_t strlen (const char *s);
 size_t strlcpy(char *, const char *, size_t);
+size_t strlcat(char *, const char *, size_t);
 
 void testStrncat(const char *src) {
   char dest[10];
@@ -33,3 +34,19 @@
   strlcpy(dest + 5, src, 5);
   strlcpy(dest + 5, src, 10); // expected-warning {{The third argument is larger than the size of the input buffer.}}
 }
+
+void testStrlcat(const char *src) {
+  char dest[10];
+  size_t badlen = 10;
+  size_t ulen;
+  strlcpy(dest, "a", sizeof("a") - 1);
+  strlcat(dest, "", (sizeof("") - 1) - sizeof(dest) - 1);
+  strlcpy(dest, "012345678", sizeof(dest));
+  strlcat(dest, "910", sizeof(dest)); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value- strlen(dest) - 1 or lower}}
+  strlcpy(dest, "0123456789", sizeof(dest));
+  strlcat(dest, "0123456789", badlen); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value 'badlen' - strlen(dest) - 1 or lower}}
+  strlcat(dest, "0123456789", badlen - strlen(dest) - 1);
+  strlcat(dest, src, ulen);
+  strlcpy(dest, src, 5);
+  strlcat(dest + 5, src, badlen); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value 'badlen' - strlen() - 1 or lower}}
+}
Index: lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
+++ lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
@@ -92,6 +92,17 @@
   ///   strlcpy(dst, "abcd", cpy);
   bool containsBadStrlcpyPattern(const CallExpr *CE);
 
+  /// Identify erroneous patterns in the last argument to strlcat - the number
+  /// of bytes to copy.
+  /// The bad pattern checked is when the last argument is basically
+  /// pointing to the destination buffer size or argument larger or
+  /// equal to.  
+  ///   char dst[2];
+  ///   strlcat(dst, src2, sizeof(dst));
+  ///   strlcat(dst, src2, 2);
+  ///   strlcat(dst, src2, 10);
+  bool containsBadStrlcatPattern(const CallExpr *CE);
+
 public:
   WalkAST(const CheckerBase *Checker, BugReporter &BR, AnalysisDeclContext *AC)
   : Checker(Checker), BR(BR), AC(AC) {}
@@ -190,6 +201,57 @@
   return false;
 }
 
+bool WalkAST::containsBadStrlcatPattern(const CallExpr *CE) {
+  if (CE->getNumArgs() != 3)
+return false;
+  const Expr *DstArg = CE->getArg(0);
+  const Expr *LenArg = CE->getArg(2);
+
+  const auto *DstArgDecl = dyn_cast(DstArg->IgnoreParenImpCasts());
+  const auto *LenArgDecl = dyn_cast(LenArg->IgnoreParenLValueCasts());
+  uint64_t DstOff = 0;
+  // - sizeof(dst)
+  if (isSizeof(LenArg, DstArg))
+return true;
+  // - size_t dstlen = sizeof(dst)
+  if (LenArgDecl) {
+const auto *LenArgVal = dyn_cast(LenArgDecl->getDecl());
+if (LenArgVal->getInit())
+  LenArg = LenArgVal->getInit();
+  }
+
+  // - integral value
+  // We try to figure out if the last argument is possibly longer or equal
+  // than the destination can possibly handle if its size can be defined.
+  if (const auto *IL = dyn_cast(LenArg->IgnoreParenImpCasts())) {
+uint64_t ILRawVal = IL->getValue().getZExtValue();
+
+// Case when there is pointer arithmetic on the destination buffer
+// especially when we offset from the base decreasing the
+// buffer length accordingly.
+if (!DstArgDecl) {
+  if (const auto *BE = dyn_cast(DstArg->IgnoreParenImpCasts())) {
+DstArgDecl = dyn_cast(BE->getLHS()->IgnoreParenImpCasts());
+if (BE->getOpcode() == BO_Add) {
+  if ((IL = dyn_cast(BE->getRHS()->IgnoreParenImpCasts( {
+DstOff = IL->getValue().getZExtValue();
+  }
+}
+  }
+}
+if (DstArgDecl) {
+  if (const auto *Buffer = dyn_cast(DstArgDecl->getType())) {
+ASTContext &C = BR.getContext();
+uint64_t BufferLen = C.getTypeSize(Buffer) / 8;
+if ((BufferLen - DstOff) <= ILRawVal)
+  return true;
+  }
+}
+  }
+
+  return false;
+}
+
 void WalkAST::VisitCallExpr(CallExpr *CE) {
   const FunctionDecl *FD = CE->getDirectCallee();
   if (!FD)
@@ -234,6 +296,34 @@
   if (!DstName.empty())