[runtime] Add MONO_ATTR_FORMAT_PRINTF macro
authorAleksey Kliger <aleksey@xamarin.com>
Fri, 30 Sep 2016 21:35:17 +0000 (17:35 -0400)
committerAleksey Kliger <aleksey@xamarin.com>
Fri, 30 Sep 2016 22:31:14 +0000 (18:31 -0400)
Expands to __attribute__((format(printf,X,Y))) with gcc and clang.

Use it to check that printf-like format strings get the correct number
and type of arguments.

mono/metadata/mempool-internals.h
mono/metadata/metadata-internals.h
mono/utils/checked-build.h
mono/utils/mono-compiler.h
mono/utils/mono-error-internals.h
mono/utils/mono-logger-internals.h

index ee07963fad720b71df7d3afde7b197fa3a198e4c..4896a237fe49060fcad67b280e3ac7c9820dc638 100644 (file)
@@ -61,7 +61,7 @@ char*
 mono_mempool_strdup_vprintf (MonoMemPool *pool, const char *format, va_list args);
 
 char*
-mono_mempool_strdup_printf (MonoMemPool *pool, const char *format, ...);
+mono_mempool_strdup_printf (MonoMemPool *pool, const char *format, ...) MONO_ATTR_FORMAT_PRINTF(2,3);;
 
 long
 mono_mempool_get_bytes_allocated (void);
index 8852d29458c056eb80ac39ae39e9f5798e30774c..9d2e569dfd7d4ceb58dfd0ab61019c2faa393d6b 100644 (file)
@@ -643,7 +643,7 @@ char*
 mono_image_strdup_vprintf (MonoImage *image, const char *format, va_list args);
 
 char*
-mono_image_strdup_printf (MonoImage *image, const char *format, ...);
+mono_image_strdup_printf (MonoImage *image, const char *format, ...) MONO_ATTR_FORMAT_PRINTF(2,3);;
 
 GList*
 g_list_prepend_image (MonoImage *image, GList *list, gpointer data);
index 869d55c69e2d05640a5fd2b23be2fc3fc374ee7b..b1c4b544d778174caee6468793ed922a33c57f2e 100644 (file)
@@ -207,7 +207,7 @@ void check_metadata_store_local(void *from, void *to);
 
 void checked_build_thread_transition(const char *transition, void *info, int from_state, int suspend_count, int next_state, int suspend_count_delta);
 
-G_GNUC_NORETURN void mono_fatal_with_history(const char *msg, ...);
+G_GNUC_NORETURN void mono_fatal_with_history(const char *msg, ...) MONO_ATTR_FORMAT_PRINTF(1,2);
 
 #else
 
index d03ba8051aa565a53319b35aad89cecae2b9f450..1f4f889904500d13befec05cd6944c83de19d698 100644 (file)
 #define MONO_ATTR_USED
 #endif
 
+#ifdef __GNUC__
+#define MONO_ATTR_FORMAT_PRINTF(fmt_pos,arg_pos) __attribute__((format(printf,fmt_pos,arg_pos)))
+#else
+#define MONO_ATTR_FORMAT_PRINTF(fmt_pos,arg_pos)
+#endif
+
 #ifdef HAVE_KW_THREAD
 
 #define MONO_HAVE_FAST_TLS
index e143901748d710d2e2f8bce87d31b0bf32dbe102..fb9fdcacb7e84ef33c2587dbf9f067bfd6627350 100644 (file)
@@ -57,64 +57,64 @@ mono_error_dup_strings (MonoError *error, gboolean dup_strings);
 
 /* This function is not very useful as you can't provide any details beyond the message.*/
 void
-mono_error_set_error (MonoError *error, int error_code, const char *msg_format, ...);
+mono_error_set_error (MonoError *error, int error_code, const char *msg_format, ...) MONO_ATTR_FORMAT_PRINTF(3,4);
 
 void
-mono_error_set_assembly_load (MonoError *error, const char *assembly_name, const char *msg_format, ...);
+mono_error_set_assembly_load (MonoError *error, const char *assembly_name, const char *msg_format, ...) MONO_ATTR_FORMAT_PRINTF(3,4);
 
 void
 mono_error_set_assembly_load_simple (MonoError *error, const char *assembly_name, gboolean refection_only);
 
 void
-mono_error_set_type_load_class (MonoError *error, MonoClass *klass, const char *msg_format, ...);
+mono_error_set_type_load_class (MonoError *error, MonoClass *klass, const char *msg_format, ...) MONO_ATTR_FORMAT_PRINTF(3,4);
 
 void
-mono_error_set_type_load_name (MonoError *error, const char *type_name, const char *assembly_name, const char *msg_format, ...);
+mono_error_set_type_load_name (MonoError *error, const char *type_name, const char *assembly_name, const char *msg_format, ...) MONO_ATTR_FORMAT_PRINTF(4,5);
 
 void
-mono_error_set_method_load (MonoError *error, MonoClass *klass, const char *method_name, const char *msg_format, ...);
+mono_error_set_method_load (MonoError *error, MonoClass *klass, const char *method_name, const char *msg_format, ...) MONO_ATTR_FORMAT_PRINTF(4,5);
 
 void
-mono_error_set_field_load (MonoError *error, MonoClass *klass, const char *field_name, const char *msg_format, ...);
+mono_error_set_field_load (MonoError *error, MonoClass *klass, const char *field_name, const char *msg_format, ...)  MONO_ATTR_FORMAT_PRINTF(4,5);
 
 void
-mono_error_set_bad_image (MonoError *error, MonoImage *image, const char *msg_format, ...);
+mono_error_set_bad_image (MonoError *error, MonoImage *image, const char *msg_format, ...) MONO_ATTR_FORMAT_PRINTF(3,4);
 
 void
-mono_error_set_bad_image_name (MonoError *error, const char *file_name, const char *msg_format, ...);
+mono_error_set_bad_image_name (MonoError *error, const char *file_name, const char *msg_format, ...) MONO_ATTR_FORMAT_PRINTF(3,4);
 
 void
-mono_error_set_out_of_memory (MonoError *error, const char *msg_format, ...);
+mono_error_set_out_of_memory (MonoError *error, const char *msg_format, ...) MONO_ATTR_FORMAT_PRINTF(2,3);
 
 void
-mono_error_set_argument (MonoError *error, const char *argument, const char *msg_format, ...);
+mono_error_set_argument (MonoError *error, const char *argument, const char *msg_format, ...) MONO_ATTR_FORMAT_PRINTF(3,4);
 
 void
-mono_error_set_argument_null (MonoError *oerror, const char *argument, const char *msg_format, ...);
+mono_error_set_argument_null (MonoError *oerror, const char *argument, const char *msg_format, ...) MONO_ATTR_FORMAT_PRINTF(3,4);
 
 void
-mono_error_set_not_verifiable (MonoError *oerror, MonoMethod *method, const char *msg_format, ...);
+mono_error_set_not_verifiable (MonoError *oerror, MonoMethod *method, const char *msg_format, ...) MONO_ATTR_FORMAT_PRINTF(3,4);
 
 void
-mono_error_set_generic_error (MonoError *error, const char * name_space, const char *name, const char *msg_format, ...);
+mono_error_set_generic_error (MonoError *error, const char * name_space, const char *name, const char *msg_format, ...) MONO_ATTR_FORMAT_PRINTF(4,5);
 
 void
-mono_error_set_execution_engine (MonoError *error, const char *msg_format, ...);
+mono_error_set_execution_engine (MonoError *error, const char *msg_format, ...) MONO_ATTR_FORMAT_PRINTF(2,3);
 
 void
-mono_error_set_not_implemented (MonoError *error, const char *msg_format, ...);
+mono_error_set_not_implemented (MonoError *error, const char *msg_format, ...) MONO_ATTR_FORMAT_PRINTF(2,3);
 
 void
-mono_error_set_not_supported (MonoError *error, const char *msg_format, ...);
+mono_error_set_not_supported (MonoError *error, const char *msg_format, ...) MONO_ATTR_FORMAT_PRINTF(2,3);
 
 void
-mono_error_set_invalid_operation (MonoError *error, const char *msg_format, ...);
+mono_error_set_invalid_operation (MonoError *error, const char *msg_format, ...) MONO_ATTR_FORMAT_PRINTF(2,3);
 
 void
 mono_error_set_exception_instance (MonoError *error, MonoException *exc);
 
 void
-mono_error_set_invalid_program (MonoError *oerror, const char *msg_format, ...);
+mono_error_set_invalid_program (MonoError *oerror, const char *msg_format, ...) MONO_ATTR_FORMAT_PRINTF(2,3);
 
 MonoException*
 mono_error_prepare_exception (MonoError *error, MonoError *error_out);
index b10ad2236ae86988690847952b78e67a7091fae0..d1e2599c30dd1e489a3cf8ff2884e09241d2b62f 100644 (file)
@@ -2,6 +2,7 @@
 #define __MONO_LOGGER_INTERNAL_H__
 
 #include <glib.h>
+#include <mono/utils/mono-compiler.h>
 #include "mono-logger.h"
 
 G_BEGIN_DECLS
@@ -74,8 +75,8 @@ mono_tracev (GLogLevelFlags level, MonoTraceMask mask, const char *format, va_li
  * Traces a new message, depending on the current logging level
  * and trace mask.
  */
-G_GNUC_UNUSED static void
-mono_trace (GLogLevelFlags level, MonoTraceMask mask, const char *format, ...) 
+G_GNUC_UNUSED MONO_ATTR_FORMAT_PRINTF(3,4) static void
+mono_trace (GLogLevelFlags level, MonoTraceMask mask, const char *format, ...)
 {
        if(G_UNLIKELY (level <= mono_internal_current_level && mask & mono_internal_current_mask)) {
                va_list args;