forked from OSchip/llvm-project
Hook up 'invalid conversion' warning for scanf format strings.
llvm-svn: 108750
This commit is contained in:
parent
f699594de8
commit
ce81542d61
|
@ -2936,7 +2936,7 @@ def warn_printf_insufficient_data_args : Warning<
|
|||
"more '%%' conversions than data arguments">, InGroup<Format>;
|
||||
def warn_printf_data_arg_not_used : Warning<
|
||||
"data argument not used by format string">, InGroup<FormatExtraArgs>;
|
||||
def warn_printf_invalid_conversion : Warning<
|
||||
def warn_format_invalid_conversion : Warning<
|
||||
"invalid conversion specifier '%0'">, InGroup<Format>;
|
||||
def warn_printf_incomplete_specifier : Warning<
|
||||
"incomplete format specifier">, InGroup<Format>;
|
||||
|
|
|
@ -1160,6 +1160,11 @@ public:
|
|||
void HandleNullChar(const char *nullCharacter);
|
||||
|
||||
protected:
|
||||
bool HandleInvalidConversionSpecifier(unsigned argIndex, SourceLocation Loc,
|
||||
const char *startSpec,
|
||||
unsigned specifierLen,
|
||||
const char *csStart, unsigned csLen);
|
||||
|
||||
SourceRange getFormatStringRange();
|
||||
CharSourceRange getSpecifierRange(const char *startSpecifier,
|
||||
unsigned specifierLen);
|
||||
|
@ -1237,6 +1242,36 @@ void CheckFormatHandler::DoneProcessing() {
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CheckFormatHandler::HandleInvalidConversionSpecifier(unsigned argIndex,
|
||||
SourceLocation Loc,
|
||||
const char *startSpec,
|
||||
unsigned specifierLen,
|
||||
const char *csStart,
|
||||
unsigned csLen) {
|
||||
|
||||
bool keepGoing = true;
|
||||
if (argIndex < NumDataArgs) {
|
||||
// Consider the argument coverered, even though the specifier doesn't
|
||||
// make sense.
|
||||
CoveredArgs.set(argIndex);
|
||||
}
|
||||
else {
|
||||
// If argIndex exceeds the number of data arguments we
|
||||
// don't issue a warning because that is just a cascade of warnings (and
|
||||
// they may have intended '%%' anyway). We don't want to continue processing
|
||||
// the format string after this point, however, as we will like just get
|
||||
// gibberish when trying to match arguments.
|
||||
keepGoing = false;
|
||||
}
|
||||
|
||||
S.Diag(Loc, diag::warn_format_invalid_conversion)
|
||||
<< llvm::StringRef(csStart, csLen)
|
||||
<< getSpecifierRange(startSpec, specifierLen);
|
||||
|
||||
return keepGoing;
|
||||
}
|
||||
|
||||
//===--- CHECK: Printf format string checking ------------------------------===//
|
||||
|
||||
namespace {
|
||||
|
@ -1281,31 +1316,13 @@ bool CheckPrintfHandler::HandleInvalidPrintfConversionSpecifier(
|
|||
const analyze_printf::PrintfSpecifier &FS,
|
||||
const char *startSpecifier,
|
||||
unsigned specifierLen) {
|
||||
|
||||
unsigned argIndex = FS.getArgIndex();
|
||||
bool keepGoing = true;
|
||||
if (argIndex < NumDataArgs) {
|
||||
// Consider the argument coverered, even though the specifier doesn't
|
||||
// make sense.
|
||||
CoveredArgs.set(argIndex);
|
||||
}
|
||||
else {
|
||||
// If argIndex exceeds the number of data arguments we
|
||||
// don't issue a warning because that is just a cascade of warnings (and
|
||||
// they may have intended '%%' anyway). We don't want to continue processing
|
||||
// the format string after this point, however, as we will like just get
|
||||
// gibberish when trying to match arguments.
|
||||
keepGoing = false;
|
||||
}
|
||||
|
||||
const analyze_printf::ConversionSpecifier &CS =
|
||||
FS.getConversionSpecifier();
|
||||
SourceLocation Loc = getLocationOfByte(CS.getStart());
|
||||
S.Diag(Loc, diag::warn_printf_invalid_conversion)
|
||||
<< llvm::StringRef(CS.getStart(), CS.getLength())
|
||||
<< getSpecifierRange(startSpecifier, specifierLen);
|
||||
FS.getConversionSpecifier();
|
||||
|
||||
return keepGoing;
|
||||
return HandleInvalidConversionSpecifier(FS.getArgIndex(),
|
||||
getLocationOfByte(CS.getStart()),
|
||||
startSpecifier, specifierLen,
|
||||
CS.getStart(), CS.getLength());
|
||||
}
|
||||
|
||||
bool CheckPrintfHandler::HandleAmount(
|
||||
|
@ -1596,6 +1613,11 @@ public:
|
|||
bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS,
|
||||
const char *startSpecifier,
|
||||
unsigned specifierLen);
|
||||
|
||||
bool HandleInvalidScanfConversionSpecifier(
|
||||
const analyze_scanf::ScanfSpecifier &FS,
|
||||
const char *startSpecifier,
|
||||
unsigned specifierLen);
|
||||
|
||||
void HandleIncompleteScanList(const char *start, const char *end);
|
||||
};
|
||||
|
@ -1607,6 +1629,20 @@ void CheckScanfHandler::HandleIncompleteScanList(const char *start,
|
|||
<< getSpecifierRange(start, end - start);
|
||||
}
|
||||
|
||||
bool CheckScanfHandler::HandleInvalidScanfConversionSpecifier(
|
||||
const analyze_scanf::ScanfSpecifier &FS,
|
||||
const char *startSpecifier,
|
||||
unsigned specifierLen) {
|
||||
|
||||
const analyze_scanf::ConversionSpecifier &CS =
|
||||
FS.getConversionSpecifier();
|
||||
|
||||
return HandleInvalidConversionSpecifier(FS.getArgIndex(),
|
||||
getLocationOfByte(CS.getStart()),
|
||||
startSpecifier, specifierLen,
|
||||
CS.getStart(), CS.getLength());
|
||||
}
|
||||
|
||||
bool CheckScanfHandler::HandleScanfSpecifier(
|
||||
const analyze_scanf::ScanfSpecifier &FS,
|
||||
const char *startSpecifier,
|
||||
|
|
|
@ -15,4 +15,5 @@ void test(const char *s, int *i) {
|
|||
|
||||
unsigned short s_x;
|
||||
scanf ("%" "hu" "\n", &s_x); // no-warning
|
||||
scanf("%y", i); // expected-warning{{invalid conversion specifier 'y'}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue