Consolidate #args checking for scanf/printf format strings.

llvm-svn: 109427
This commit is contained in:
Ted Kremenek 2010-07-26 19:45:42 +00:00
parent 6005082354
commit 6adb7e35ab
1 changed files with 31 additions and 30 deletions

View File

@ -1169,6 +1169,11 @@ protected:
SourceLocation getLocationOfByte(const char *x); SourceLocation getLocationOfByte(const char *x);
const Expr *getDataArg(unsigned i) const; const Expr *getDataArg(unsigned i) const;
bool CheckNumArgs(const analyze_format_string::FormatSpecifier &FS,
const analyze_format_string::ConversionSpecifier &CS,
const char *startSpecifier, unsigned specifierLen,
unsigned argIndex);
}; };
} }
@ -1270,6 +1275,30 @@ CheckFormatHandler::HandleInvalidConversionSpecifier(unsigned argIndex,
return keepGoing; return keepGoing;
} }
bool
CheckFormatHandler::CheckNumArgs(
const analyze_format_string::FormatSpecifier &FS,
const analyze_format_string::ConversionSpecifier &CS,
const char *startSpecifier, unsigned specifierLen, unsigned argIndex) {
if (argIndex >= NumDataArgs) {
if (FS.usesPositionalArg()) {
S.Diag(getLocationOfByte(CS.getStart()),
diag::warn_printf_positional_arg_exceeds_data_args)
<< (argIndex+1) << NumDataArgs
<< getSpecifierRange(startSpecifier, specifierLen);
}
else {
S.Diag(getLocationOfByte(CS.getStart()),
diag::warn_printf_insufficient_data_args)
<< getSpecifierRange(startSpecifier, specifierLen);
}
return false;
}
return true;
}
//===--- CHECK: Printf format string checking ------------------------------===// //===--- CHECK: Printf format string checking ------------------------------===//
namespace { namespace {
@ -1538,22 +1567,8 @@ CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier
if (HasVAListArg) if (HasVAListArg)
return true; return true;
if (argIndex >= NumDataArgs) { if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex))
if (FS.usesPositionalArg()) {
S.Diag(getLocationOfByte(CS.getStart()),
diag::warn_printf_positional_arg_exceeds_data_args)
<< (argIndex+1) << NumDataArgs
<< getSpecifierRange(startSpecifier, specifierLen);
}
else {
S.Diag(getLocationOfByte(CS.getStart()),
diag::warn_printf_insufficient_data_args)
<< getSpecifierRange(startSpecifier, specifierLen);
}
// Don't do any more checking.
return false; return false;
}
// Now type check the data expression that matches the // Now type check the data expression that matches the
// format specifier. // format specifier.
@ -1714,22 +1729,8 @@ bool CheckScanfHandler::HandleScanfSpecifier(
if (HasVAListArg) if (HasVAListArg)
return true; return true;
if (argIndex >= NumDataArgs) { if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex))
if (FS.usesPositionalArg()) {
S.Diag(getLocationOfByte(CS.getStart()),
diag::warn_printf_positional_arg_exceeds_data_args)
<< (argIndex+1) << NumDataArgs
<< getSpecifierRange(startSpecifier, specifierLen);
}
else {
S.Diag(getLocationOfByte(CS.getStart()),
diag::warn_printf_insufficient_data_args)
<< getSpecifierRange(startSpecifier, specifierLen);
}
// Don't do any more checking.
return false; return false;
}
// FIXME: Check that the argument type matches the format specifier. // FIXME: Check that the argument type matches the format specifier.