diff options
author | Akira Hatanaka <ahatanaka@apple.com> | 2018-07-10 00:50:25 +0000 |
---|---|---|
committer | Akira Hatanaka <ahatanaka@apple.com> | 2018-07-10 00:50:25 +0000 |
commit | 189359d1ff8a167271fcbe5c7a91c42c94dc253d (patch) | |
tree | 9fd0b4a0e37cd101d2910fbb76292a38493ba024 /clang/lib/Analysis | |
parent | 1faf953d7513154002a1b075cc308ec7fc301cff (diff) | |
download | bcm5719-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.cpp | 78 |
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"); } } |