aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/PrintfFormatString.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2010-01-29 02:40:24 +0000
committerTed Kremenek <kremenek@apple.com>2010-01-29 02:40:24 +0000
commit26ac2e07b46bfb4d4f00752c96481c0a98c79c69 (patch)
treebed4398bf05a6886cb93ab9fa70f66e0f3c1848e /lib/Analysis/PrintfFormatString.cpp
parenteb60edffa147e061278c436e513b0df9b4c4e7f6 (diff)
Alternate format string checking: issue a warning for invalid conversion specifiers.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@94792 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/PrintfFormatString.cpp')
-rw-r--r--lib/Analysis/PrintfFormatString.cpp31
1 files changed, 18 insertions, 13 deletions
diff --git a/lib/Analysis/PrintfFormatString.cpp b/lib/Analysis/PrintfFormatString.cpp
index 3045fdd990..3f03420657 100644
--- a/lib/Analysis/PrintfFormatString.cpp
+++ b/lib/Analysis/PrintfFormatString.cpp
@@ -21,17 +21,17 @@ namespace {
class FormatSpecifierResult {
FormatSpecifier FS;
const char *Start;
- bool HasError;
+ bool Stop;
public:
- FormatSpecifierResult(bool err = false)
- : Start(0), HasError(err) {}
+ FormatSpecifierResult(bool stop = false)
+ : Start(0), Stop(stop) {}
FormatSpecifierResult(const char *start,
const FormatSpecifier &fs)
- : FS(fs), Start(start), HasError(false) {}
+ : FS(fs), Start(start), Stop(false) {}
const char *getStart() const { return Start; }
- bool hasError() const { return HasError; }
+ bool shouldStop() const { return Stop; }
bool hasValue() const { return Start != 0; }
const FormatSpecifier &getValue() const {
assert(hasValue());
@@ -194,11 +194,10 @@ ParseFormatSpecifier(clang::analyze_printf::FormatStringHandler &H,
// Finally, look for the conversion specifier.
const char *conversionPosition = I++;
- ConversionSpecifier::Kind k;
+ ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier;
switch (*conversionPosition) {
default:
- H.HandleInvalidConversionSpecifier(conversionPosition);
- return true;
+ break;
// C99: 7.19.6.1 (section 8).
case 'd': k = ConversionSpecifier::dArg; break;
case 'i': k = ConversionSpecifier::iArg; break;
@@ -223,6 +222,11 @@ ParseFormatSpecifier(clang::analyze_printf::FormatStringHandler &H,
case '@': k = ConversionSpecifier::ObjCObjArg; break;
}
FS.setConversionSpecifier(ConversionSpecifier(conversionPosition, k));
+
+ if (k == ConversionSpecifier::InvalidSpecifier) {
+ H.HandleInvalidConversionSpecifier(FS, Beg, I - Beg);
+ return false; // Keep processing format specifiers.
+ }
return FormatSpecifierResult(Start, FS);
}
@@ -232,13 +236,14 @@ bool ParseFormatString(FormatStringHandler &H,
// Keep looking for a format specifier until we have exhausted the string.
while (I != E) {
const FormatSpecifierResult &FSR = ParseFormatSpecifier(H, I, E);
- // Did an error of any kind occur when parsing the specifier? If so,
- // don't do any more processing.
- if (FSR.hasError())
+ // Did a fail-stop error of any kind occur when parsing the specifier?
+ // If so, don't do any more processing.
+ if (FSR.shouldStop())
return true;;
- // Done processing the string?
+ // Did we exhaust the string or encounter an error that
+ // we can recover from?
if (!FSR.hasValue())
- break;
+ continue;
// We have a format specifier. Pass it to the callback.
if (!H.HandleFormatSpecifier(FSR.getValue(), FSR.getStart(),
I - FSR.getStart()))