summaryrefslogtreecommitdiffstats
path: root/clang/lib/Analysis
diff options
context:
space:
mode:
authorAkira Hatanaka <ahatanaka@apple.com>2018-07-10 00:50:25 +0000
committerAkira Hatanaka <ahatanaka@apple.com>2018-07-10 00:50:25 +0000
commit189359d1ff8a167271fcbe5c7a91c42c94dc253d (patch)
tree9fd0b4a0e37cd101d2910fbb76292a38493ba024 /clang/lib/Analysis
parent1faf953d7513154002a1b075cc308ec7fc301cff (diff)
downloadbcm5719-llvm-189359d1ff8a167271fcbe5c7a91c42c94dc253d.tar.gz
bcm5719-llvm-189359d1ff8a167271fcbe5c7a91c42c94dc253d.zip
Fix parsing of privacy annotations in os_log format strings.
Privacy annotations shouldn't have to appear in the first comma-delimited string in order to be recognized. Also, they should be ignored if they are preceded or followed by non-whitespace characters. rdar://problem/40706280 llvm-svn: 336629
Diffstat (limited to 'clang/lib/Analysis')
-rw-r--r--clang/lib/Analysis/PrintfFormatString.cpp78
1 files changed, 49 insertions, 29 deletions
diff --git a/clang/lib/Analysis/PrintfFormatString.cpp b/clang/lib/Analysis/PrintfFormatString.cpp
index 688b2031a3f..2e5841ecae9 100644
--- a/clang/lib/Analysis/PrintfFormatString.cpp
+++ b/clang/lib/Analysis/PrintfFormatString.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Analysis/Analyses/FormatString.h"
+#include "clang/Analysis/Analyses/OSLog.h"
#include "FormatStringParsing.h"
#include "clang/Basic/TargetInfo.h"
@@ -119,36 +120,55 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
return true;
}
- const char *OSLogVisibilityFlagsStart = nullptr,
- *OSLogVisibilityFlagsEnd = nullptr;
if (*I == '{') {
- OSLogVisibilityFlagsStart = I++;
- // Find the end of the modifier.
- while (I != E && *I != '}') {
- I++;
- }
- if (I == E) {
- if (Warn)
- H.HandleIncompleteSpecifier(Start, E - Start);
- return true;
- }
- assert(*I == '}');
- OSLogVisibilityFlagsEnd = I++;
-
- // Just see if 'private' or 'public' is the first word. os_log itself will
- // do any further parsing.
- const char *P = OSLogVisibilityFlagsStart + 1;
- while (P < OSLogVisibilityFlagsEnd && isspace(*P))
- P++;
- const char *WordStart = P;
- while (P < OSLogVisibilityFlagsEnd && (isalnum(*P) || *P == '_'))
- P++;
- const char *WordEnd = P;
- StringRef Word(WordStart, WordEnd - WordStart);
- if (Word == "private") {
- FS.setIsPrivate(WordStart);
- } else if (Word == "public") {
- FS.setIsPublic(WordStart);
+ ++I;
+ unsigned char PrivacyFlags = 0;
+ StringRef MatchedStr;
+
+ do {
+ StringRef Str(I, E - I);
+ std::string Match = "^[\t\n\v\f\r ]*(private|public)[\t\n\v\f\r ]*(,|})";
+ llvm::Regex R(Match);
+ SmallVector<StringRef, 2> Matches;
+
+ if (R.match(Str, &Matches)) {
+ MatchedStr = Matches[1];
+ I += Matches[0].size();
+
+ // Set the privacy flag if there is a privacy annotation in the
+ // comma-delimited segment. This overrides any privacy annotations that
+ // appeared in previous comma-delimited segments.
+ if (MatchedStr.equals("private"))
+ PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPrivate;
+ else if (MatchedStr.equals("public"))
+ PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPublic;
+ } else {
+ size_t CommaOrBracePos =
+ Str.find_if([](char c) { return c == ',' || c == '}'; });
+ I += CommaOrBracePos + 1;
+
+ if (CommaOrBracePos == StringRef::npos) {
+ // Neither a comma nor the closing brace was found.
+ if (Warn)
+ H.HandleIncompleteSpecifier(Start, E - Start);
+ return true;
+ }
+ }
+ // Continue until the closing brace is found.
+ } while (*(I - 1) == ',');
+
+ // Set the privacy flag.
+ switch (PrivacyFlags) {
+ case 0:
+ break;
+ case clang::analyze_os_log::OSLogBufferItem::IsPrivate:
+ FS.setIsPrivate(MatchedStr.data());
+ break;
+ case clang::analyze_os_log::OSLogBufferItem::IsPublic:
+ FS.setIsPublic(MatchedStr.data());
+ break;
+ default:
+ llvm_unreachable("Unexpected privacy flag value");
}
}
OpenPOWER on IntegriCloud