Fix <rdar://problem/6880975> [format string] Assertion failed: (Arg < NumArgs && "Arg access out of range!").

For format string checking, only check the type of the format
specifier for non-vararg functions.

llvm-svn: 71672
This commit is contained in:
Ted Kremenek 2009-05-13 16:06:05 +00:00
parent 4a71ae268b
commit 4554f9b134
2 changed files with 34 additions and 27 deletions

View File

@ -917,36 +917,38 @@ void Sema::CheckPrintfString(const StringLiteral *FExpr,
case '*': {
++numConversions;
if (!HasVAListArg && numConversions > numDataArgs) {
SourceLocation Loc = getLocationOfStringLiteralByte(FExpr, StrIdx);
if (!HasVAListArg) {
if (numConversions > numDataArgs) {
SourceLocation Loc = getLocationOfStringLiteralByte(FExpr, StrIdx);
if (Str[StrIdx-1] == '.')
Diag(Loc, diag::warn_printf_asterisk_precision_missing_arg)
<< OrigFormatExpr->getSourceRange();
else
Diag(Loc, diag::warn_printf_asterisk_width_missing_arg)
<< OrigFormatExpr->getSourceRange();
if (Str[StrIdx-1] == '.')
Diag(Loc, diag::warn_printf_asterisk_precision_missing_arg)
<< OrigFormatExpr->getSourceRange();
else
Diag(Loc, diag::warn_printf_asterisk_width_missing_arg)
<< OrigFormatExpr->getSourceRange();
// Don't do any more checking. We'll just emit spurious errors.
return;
}
// Perform type checking on width/precision specifier.
const Expr *E = TheCall->getArg(format_idx+numConversions);
if (const BuiltinType *BT = E->getType()->getAsBuiltinType())
if (BT->getKind() == BuiltinType::Int)
break;
// Don't do any more checking. We'll just emit spurious errors.
return;
SourceLocation Loc = getLocationOfStringLiteralByte(FExpr, StrIdx);
if (Str[StrIdx-1] == '.')
Diag(Loc, diag::warn_printf_asterisk_precision_wrong_type)
<< E->getType() << E->getSourceRange();
else
Diag(Loc, diag::warn_printf_asterisk_width_wrong_type)
<< E->getType() << E->getSourceRange();
break;
}
// Perform type checking on width/precision specifier.
const Expr *E = TheCall->getArg(format_idx+numConversions);
if (const BuiltinType *BT = E->getType()->getAsBuiltinType())
if (BT->getKind() == BuiltinType::Int)
break;
SourceLocation Loc = getLocationOfStringLiteralByte(FExpr, StrIdx);
if (Str[StrIdx-1] == '.')
Diag(Loc, diag::warn_printf_asterisk_precision_wrong_type)
<< E->getType() << E->getSourceRange();
else
Diag(Loc, diag::warn_printf_asterisk_width_wrong_type)
<< E->getType() << E->getSourceRange();
break;
}
// Characters which can terminate a format conversion

View File

@ -125,3 +125,8 @@ void test9(char *P) {
printf(P, 42);
printf("%n", &x); // expected-warning {{use of '%n' in format string discouraged }}
}
void torture(va_list v8) {
vprintf ("%*.*d", v8); // no-warning
}