diff options
-rw-r--r-- | clang/lib/Sema/Sema.cpp | 27 | ||||
-rw-r--r-- | clang/lib/Sema/Sema.h | 16 | ||||
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 32 | ||||
-rw-r--r-- | clang/test/Sema/format-strings.c | 4 |
4 files changed, 50 insertions, 29 deletions
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index f43264d133d..80ce2ccd0ef 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -88,17 +88,22 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer) // do extra checking. IdentifierTable &IT = PP.getIdentifierTable(); - KnownFunctionIDs[id_printf] = &IT.get("printf"); - KnownFunctionIDs[id_fprintf] = &IT.get("fprintf"); - KnownFunctionIDs[id_sprintf] = &IT.get("sprintf"); - KnownFunctionIDs[id_snprintf] = &IT.get("snprintf"); - KnownFunctionIDs[id_asprintf] = &IT.get("asprintf"); - KnownFunctionIDs[id_NSLog] = &IT.get("NSLog"); - KnownFunctionIDs[id_vsnprintf] = &IT.get("vsnprintf"); - KnownFunctionIDs[id_vasprintf] = &IT.get("vasprintf"); - KnownFunctionIDs[id_vfprintf] = &IT.get("vfprintf"); - KnownFunctionIDs[id_vsprintf] = &IT.get("vsprintf"); - KnownFunctionIDs[id_vprintf] = &IT.get("vprintf"); + KnownFunctionIDs[id_printf] = &IT.get("printf"); + KnownFunctionIDs[id_fprintf] = &IT.get("fprintf"); + KnownFunctionIDs[id_sprintf] = &IT.get("sprintf"); + KnownFunctionIDs[id_sprintf_chk] = &IT.get("__builtin___sprintf_chk"); + KnownFunctionIDs[id_snprintf] = &IT.get("snprintf"); + KnownFunctionIDs[id_snprintf_chk] = &IT.get("__builtin___snprintf_chk"); + KnownFunctionIDs[id_asprintf] = &IT.get("asprintf"); + KnownFunctionIDs[id_NSLog] = &IT.get("NSLog"); + KnownFunctionIDs[id_vsnprintf] = &IT.get("vsnprintf"); + KnownFunctionIDs[id_vasprintf] = &IT.get("vasprintf"); + KnownFunctionIDs[id_vfprintf] = &IT.get("vfprintf"); + KnownFunctionIDs[id_vsprintf] = &IT.get("vsprintf"); + KnownFunctionIDs[id_vsprintf_chk] = &IT.get("__builtin___vsprintf_chk"); + KnownFunctionIDs[id_vsnprintf] = &IT.get("vsnprintf"); + KnownFunctionIDs[id_vsnprintf_chk] = &IT.get("__builtin___vsnprintf_chk"); + KnownFunctionIDs[id_vprintf] = &IT.get("vprintf"); SuperID = &IT.get("super"); diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 49d69ad92da..696a6f41941 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -127,16 +127,20 @@ public: // Enum values used by KnownFunctionIDs (see below). enum { - id_printf, + id_NSLog, + id_asprintf, id_fprintf, - id_sprintf, + id_printf, id_snprintf, - id_asprintf, - id_NSLog, - id_vsnprintf, + id_snprintf_chk, + id_sprintf, + id_sprintf_chk, id_vasprintf, - id_vfprintf, + id_vfprintf, + id_vsnprintf, + id_vsnprintf_chk, id_vsprintf, + id_vsprintf_chk, id_vprintf, id_num_known_functions }; diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index f870e26b6a3..27f3abe68a6 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -66,7 +66,11 @@ Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCallRaw) { if (SemaBuiltinObjectSize(TheCall.get())) return true; } - + + // FIXME: This mechanism should be abstracted to be less fragile and + // more efficient. For example, just map function ids to custom + // handlers. + // Search the KnownFunctionIDs for the identifier. unsigned i = 0, e = id_num_known_functions; for (; i != e; ++i) { if (KnownFunctionIDs[i] == FnInfo) break; } @@ -81,17 +85,21 @@ Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCallRaw) { switch (i) { default: assert(false && "No format string argument index."); - case id_printf: format_idx = 0; break; - case id_fprintf: format_idx = 1; break; - case id_sprintf: format_idx = 1; break; - case id_snprintf: format_idx = 2; break; - case id_asprintf: format_idx = 1; break; - case id_NSLog: format_idx = 0; break; - case id_vsnprintf: format_idx = 2; HasVAListArg = true; break; - case id_vasprintf: format_idx = 1; HasVAListArg = true; break; - case id_vfprintf: format_idx = 1; HasVAListArg = true; break; - case id_vsprintf: format_idx = 1; HasVAListArg = true; break; - case id_vprintf: format_idx = 0; HasVAListArg = true; break; + case id_NSLog: format_idx = 0; break; + case id_asprintf: format_idx = 1; break; + case id_fprintf: format_idx = 1; break; + case id_printf: format_idx = 0; break; + case id_snprintf: format_idx = 2; break; + case id_snprintf_chk: format_idx = 4; break; + case id_sprintf: format_idx = 1; break; + case id_sprintf_chk: format_idx = 3; break; + case id_vasprintf: format_idx = 1; HasVAListArg = true; break; + case id_vfprintf: format_idx = 1; HasVAListArg = true; break; + case id_vsnprintf: format_idx = 2; HasVAListArg = true; break; + case id_vsnprintf_chk: format_idx = 4; HasVAListArg = true; break; + case id_vsprintf: format_idx = 1; HasVAListArg = true; break; + case id_vsprintf_chk: format_idx = 3; HasVAListArg = true; break; + case id_vprintf: format_idx = 0; HasVAListArg = true; break; } CheckPrintfArguments(TheCall.get(), HasVAListArg, format_idx); diff --git a/clang/test/Sema/format-strings.c b/clang/test/Sema/format-strings.c index ec070a291b1..16d4943cda5 100644 --- a/clang/test/Sema/format-strings.c +++ b/clang/test/Sema/format-strings.c @@ -22,9 +22,13 @@ void check_string_literal( FILE* fp, const char* s, char *buf, ... ) { vasprintf(&b,s,ap); // no-warning sprintf(buf,s); // expected-warning {{format string is not a string literal}} snprintf(buf,2,s); // expected-warning {{format string is not a string lit}} + __builtin___sprintf_chk(buf,0,-1,s); // expected-warning {{format string is not a string literal}} + __builtin___snprintf_chk(buf,2,0,-1,s); // expected-warning {{format string is not a string lit}} vsprintf(buf,s,ap); // no-warning vsnprintf(buf,2,s,ap); // no-warning vsnprintf(buf,2,global_fmt,ap); // expected-warning {{format string is not a string literal}} + __builtin___vsnprintf_chk(buf,2,0,-1,s,ap); // no-warning + __builtin___vsnprintf_chk(buf,2,0,-1,global_fmt,ap); // expected-warning {{format string is not a string literal}} } void check_writeback_specifier() |