This patch is NOT meant for merge. Just a simple proof-of-concept so reviewers can quickly reproduce the difference between placing a G_GNUC_PRINTF attribute in *.c versus *.h file.
What it tests ------------- * Two identical printf-style helpers (my_printf) are provided: - v1: attribute lives in foo-v1.c - v2: attribute lives in foo-v2.h * Two callers (bar-v1.c, bar-v2.c) intentionally pass too few arguments: `my_printf("%d %d %d\n", 1)`. * A trivial Makefile builds each variant and shows whether GCC emits the missing-argument warning. Expected result --------------- $ make -C poc run // Compiling version 1 (Place G_GNUC_PRINTF in 'foo-v1.c') No warning will appear, sliently cause security flaw // Compiling version 2 (Place G_GNUC_PRINTF in 'foo-v2.h') bar-v2.c:4:17: warning: more '%' conversions than data arguments [-Wformat-insufficient-args] Signed-off-by: Sean Wei <me@sean.taipei> --- poc/foo-v1.h | 3 +++ poc/foo-v1.c | 10 ++++++++++ poc/bar-v1.c | 6 ++++++ poc/foo-v2.h | 3 +++ poc/foo-v2.c | 10 ++++++++++ poc/bar-v2.c | 6 ++++++ poc/Makefile | 39 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 77 insertions(+) create mode 100644 poc/foo-v1.h create mode 100644 poc/foo-v1.c create mode 100644 poc/bar-v1.c create mode 100644 poc/foo-v2.h create mode 100644 poc/foo-v2.c create mode 100644 poc/bar-v2.c create mode 100644 poc/Makefile diff --git a/poc/foo-v1.h b/poc/foo-v1.h new file mode 100644 index 0000000000..37b5403ba6 --- /dev/null +++ b/poc/foo-v1.h @@ -0,0 +1,3 @@ +#define G_GNUC_PRINTF(n, m) __attribute__((format(printf, n, m))) + +void my_printf(const char *fmt, ...); diff --git a/poc/foo-v1.c b/poc/foo-v1.c new file mode 100644 index 0000000000..ce89f95e3e --- /dev/null +++ b/poc/foo-v1.c @@ -0,0 +1,10 @@ +#include <stdio.h> +#include <stdarg.h> +#include "foo-v2.h" + +void G_GNUC_PRINTF(1, 2) my_printf(const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); +} diff --git a/poc/bar-v1.c b/poc/bar-v1.c new file mode 100644 index 0000000000..6e707e13b4 --- /dev/null +++ b/poc/bar-v1.c @@ -0,0 +1,6 @@ +#include "foo-v1.h" + +int main() { + my_printf("%d %d %d\n", 1); // missing arguments + return 0; +} diff --git a/poc/foo-v2.h b/poc/foo-v2.h new file mode 100644 index 0000000000..8bb56d3181 --- /dev/null +++ b/poc/foo-v2.h @@ -0,0 +1,3 @@ +#define G_GNUC_PRINTF(n, m) __attribute__((format(printf, n, m))) + +void G_GNUC_PRINTF(1, 2) my_printf(const char *fmt, ...); diff --git a/poc/foo-v2.c b/poc/foo-v2.c new file mode 100644 index 0000000000..3f18632ee6 --- /dev/null +++ b/poc/foo-v2.c @@ -0,0 +1,10 @@ +#include <stdio.h> +#include <stdarg.h> +#include "foo-v1.h" + +void my_printf(const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); +} diff --git a/poc/bar-v2.c b/poc/bar-v2.c new file mode 100644 index 0000000000..e06fd87056 --- /dev/null +++ b/poc/bar-v2.c @@ -0,0 +1,6 @@ +#include "foo-v2.h" + +int main() { + my_printf("%d %d %d\n", 1); // missing arguments + return 0; +} diff --git a/poc/Makefile b/poc/Makefile new file mode 100644 index 0000000000..5725c9ff63 --- /dev/null +++ b/poc/Makefile @@ -0,0 +1,39 @@ +CC ?= gcc +CFLAGS ?= -Wall + +TARGET = prog-v1 prog-v2 +SRCS = foo-v1.c foo-v2.c bar-v1.c bar-v2.c +OBJS = $(SRCS:.c=.o) + +.PHONY: run + +run: clean prog-v1 prog-v2 + + +prog-v1: + @echo + @echo + @echo "### Compiling version 1 ###" + @echo "Place G_GNUC_PRINTF in 'foo.c' only" + @echo "No warning will appear, sliently cause security flaw" + @echo + $(CC) $(CFLAGS) -c foo-v1.c -o foo-v1.o + $(CC) $(CFLAGS) -c bar-v1.c -o bar-v1.o + @echo + $(CC) foo-v1.o bar-v1.o -o $@ + +prog-v2: + @echo + @echo + @echo "### Compiling version 2###" + @echo "Place G_GNUC_PRINTF in 'foo.h' instead" + @echo "Show warning for missing arguments" + @echo + $(CC) $(CFLAGS) -c foo-v2.c -o foo-v2.o + $(CC) $(CFLAGS) -c bar-v2.c -o bar-v2.o + @echo + $(CC) foo-v2.o bar-v2.o -o $@ + +clean: + @echo "### Clean all artifacts ###" + rm -f $(TARGET) $(OBJS) -- 2.49.0