From: Ted Kremenek Date: Thu, 9 Sep 2010 04:33:05 +0000 (+0000) Subject: Check format strings when a called function has more than one FormatAttr (one for... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c82faca0be59b072b38bed375e21bd24f1f72647;p=clang Check format strings when a called function has more than one FormatAttr (one for 'scanf' and one for 'printf'). Fixes . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@113472 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 1a7bd1d07f..0ed2f33e0e 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -341,8 +341,12 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) { // more efficient. For example, just map function ids to custom // handlers. - // Printf checking. - if (const FormatAttr *Format = FDecl->getAttr()) { + // Printf and scanf checking. + for (specific_attr_iterator + i = FDecl->specific_attr_begin(), + e = FDecl->specific_attr_end(); i != e ; ++i) { + + const FormatAttr *Format = *i; const bool b = Format->getType() == "scanf"; if (b || CheckablePrintfAttr(Format, TheCall)) { bool HasVAListArg = Format->getFirstArg() == 0; @@ -353,12 +357,11 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) { } } - specific_attr_iterator - i = FDecl->specific_attr_begin(), - e = FDecl->specific_attr_end(); - - for (; i != e; ++i) + for (specific_attr_iterator + i = FDecl->specific_attr_begin(), + e = FDecl->specific_attr_end(); i != e; ++i) { CheckNonNullArguments(*i, TheCall); + } return false; } diff --git a/test/Sema/format-strings.c b/test/Sema/format-strings.c index 9e8007b9b0..1bfab25531 100644 --- a/test/Sema/format-strings.c +++ b/test/Sema/format-strings.c @@ -302,9 +302,18 @@ void pr7981(wint_t c, wchar_t c2) { } // -Wformat-security says NULL is not a string literal -void r8269537() { +void rdar8269537() { // This is likely to crash in most cases, but -Wformat-nonliteral technically // doesn't warn in this case. printf(0); // no-warning } +// Handle functions with multiple format attributes. +extern void rdar8332221_vprintf_scanf(const char *, va_list, const char *, ...) + __attribute__((__format__(__printf__, 1, 0))) + __attribute__((__format__(__scanf__, 3, 4))); + +void rdar8332221(va_list ap, int *x, long *y) { + rdar8332221_vprintf_scanf("%", ap, "%d", x); // expected-warning{{incomplete format specifier}} +} +