From 4554f9b134307c7aa44686ce6982a0af5a9fc0f2 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Wed, 13 May 2009 16:06:05 +0000 Subject: [PATCH] Fix [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 --- clang/lib/Sema/SemaChecking.cpp | 56 +++++++++++++++++--------------- clang/test/Sema/format-strings.c | 5 +++ 2 files changed, 34 insertions(+), 27 deletions(-) diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 67d9a1acbf6d..22dcc49b5545 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -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 diff --git a/clang/test/Sema/format-strings.c b/clang/test/Sema/format-strings.c index 50903b0cf836..1826c7457e30 100644 --- a/clang/test/Sema/format-strings.c +++ b/clang/test/Sema/format-strings.c @@ -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 +} +