From patchwork Thu Nov 1 18:11:13 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Dooks X-Patchwork-Id: 10664411 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8FD6D1734 for ; Thu, 1 Nov 2018 18:11:28 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 80C9E2C32A for ; Thu, 1 Nov 2018 18:11:28 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7052C2C327; Thu, 1 Nov 2018 18:11:28 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0931A2C326 for ; Thu, 1 Nov 2018 18:11:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726174AbeKBDPa (ORCPT ); Thu, 1 Nov 2018 23:15:30 -0400 Received: from imap1.codethink.co.uk ([176.9.8.82]:52027 "EHLO imap1.codethink.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727532AbeKBDPa (ORCPT ); Thu, 1 Nov 2018 23:15:30 -0400 Received: from [148.252.241.226] (helo=rainbowdash) by imap1.codethink.co.uk with esmtpsa (Exim 4.84_2 #1 (Debian)) id 1gIHRF-0006Nk-HT; Thu, 01 Nov 2018 18:11:25 +0000 Received: from ben by rainbowdash with local (Exim 4.91) (envelope-from ) id 1gIHRD-00012c-Kn; Thu, 01 Nov 2018 18:11:23 +0000 From: Ben Dooks To: linux-sparse@vger.kernel.org Cc: Luc Van Oostenryck Subject: [PATCH 1/5] ptrlist: add ptr_list_nth_entry() Date: Thu, 1 Nov 2018 18:11:13 +0000 Message-Id: <20181101181117.3877-2-ben.dooks@codethink.co.uk> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181101181117.3877-1-ben.dooks@codethink.co.uk> References: <20181101181117.3877-1-ben.dooks@codethink.co.uk> MIME-Version: 1.0 Sender: linux-sparse-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-sparse@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Luc Van Oostenryck Usually ptr lists are accessed iteratively via the FOR/END macros but in few case we may need to access a given element in a list, like for example when accessing a given argument of a function. Create an helper doing that instead of open coding it. [ben.dooks@codethink.co.uk: applied to current working tree] Signed-off-by: Luc Van Oostenryck --- ptrlist.c | 22 ++++++++++++++++++++++ ptrlist.h | 2 ++ 2 files changed, 24 insertions(+) diff --git a/ptrlist.c b/ptrlist.c index 8402f8d..fce185d 100644 --- a/ptrlist.c +++ b/ptrlist.c @@ -29,6 +29,28 @@ int ptr_list_size(struct ptr_list *head) return nr; } +/// +// get the nth element of a ptrlist +// @head: the head of the list +// @return: the nth element of the list or ``NULL`` if the list is too short. +void *ptr_list_nth_entry(struct ptr_list *list, unsigned int idx) +{ + struct ptr_list *head = list; + + if (!head) + return NULL; + + do { + unsigned int nr = list->nr; + + if (idx < nr) + return list->list[idx]; + else + idx -= nr; + } while ((list = list->next) != head); + return NULL; +} + /* * Linearize the entries of a list up to a total of 'max', * and return the nr of entries linearized. diff --git a/ptrlist.h b/ptrlist.h index 78625c8..41d3281 100644 --- a/ptrlist.h +++ b/ptrlist.h @@ -46,6 +46,8 @@ extern void __free_ptr_list(struct ptr_list **); extern int ptr_list_size(struct ptr_list *); extern int linearize_ptr_list(struct ptr_list *, void **, int); +extern void *ptr_list_nth_entry(struct ptr_list *, unsigned int idx); + /* * Hey, who said that you can't do overloading in C? * From patchwork Thu Nov 1 18:11:14 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Dooks X-Patchwork-Id: 10664419 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 30A1F17DF for ; Thu, 1 Nov 2018 18:11:31 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 236D32C307 for ; Thu, 1 Nov 2018 18:11:31 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 17BD02C326; Thu, 1 Nov 2018 18:11:31 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 53B1D2C324 for ; Thu, 1 Nov 2018 18:11:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727244AbeKBDPc (ORCPT ); Thu, 1 Nov 2018 23:15:32 -0400 Received: from imap1.codethink.co.uk ([176.9.8.82]:52025 "EHLO imap1.codethink.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727420AbeKBDPc (ORCPT ); Thu, 1 Nov 2018 23:15:32 -0400 Received: from [148.252.241.226] (helo=rainbowdash) by imap1.codethink.co.uk with esmtpsa (Exim 4.84_2 #1 (Debian)) id 1gIHRF-0006Nm-Hl; Thu, 01 Nov 2018 18:11:25 +0000 Received: from ben by rainbowdash with local (Exim 4.91) (envelope-from ) id 1gIHRD-00012e-Lq; Thu, 01 Nov 2018 18:11:23 +0000 From: Ben Dooks To: linux-sparse@vger.kernel.org Cc: Ben Dooks Subject: [PATCH 2/5] evaluate: check variadic argument types against formatting info Date: Thu, 1 Nov 2018 18:11:14 +0000 Message-Id: <20181101181117.3877-3-ben.dooks@codethink.co.uk> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181101181117.3877-1-ben.dooks@codethink.co.uk> References: <20181101181117.3877-1-ben.dooks@codethink.co.uk> MIME-Version: 1.0 Sender: linux-sparse-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-sparse@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The variadic argumnet code did not check any of the variadic arguments as it did not previously know the possible type. Now we have the possible formatting information stored in the ctype, we can do some checks on the printf formatting types. Signed-off-by: Ben Dooks --- Fixes since v1: - Split out the format-string -> symbol code - Use symbol_list for the symbols from format parsing - Changed to follow the new parsing code and ctype use - Merged the unsigned-int/long types together Fixes since v2: - Check for printf_va_start before checking variadic-list - Tidy the type code and fix a couple of bugs with %l and %ll - Fix function names in working through printf arguments. - Tidy documentation Fixes since v3: - Added positional arguments - Also added precision and width specifiers Notes: - Awaiting new pointer-list accessing code - %p still generates an address-space mismatch - how do we deal with the kernel's attempt to make printk format all types? expr: updated handling for formats --- evaluate.c | 297 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 297 insertions(+) diff --git a/evaluate.c b/evaluate.c index b96696d..ffb4af6 100644 --- a/evaluate.c +++ b/evaluate.c @@ -2243,6 +2243,297 @@ static struct symbol *evaluate_alignof(struct expression *expr) return size_t_ctype; } +struct format_type { + const char *format; + int (*test)(void *data, struct expression **expr, struct symbol *ctype, struct symbol **target, const char **typediff); + void *data; +}; + +struct format_state { + struct expression *expr; + unsigned int va_start; + unsigned int fmt_index; + unsigned int arg_index; + unsigned int used_position: 1; +}; + +static int printf_fmt_inttype(void *data, struct expression **expr, struct symbol *ctype, struct symbol **target, const char **typediff) +{ + struct symbol *type = data; + *target = type; + return ctype == type; +} + +// todo - comparing pointers isn't easy... +static int printf_fmt_string(void *data, struct expression **expr, struct symbol *ctype, struct symbol **target, const char **typediff) +{ + *target = &string_ctype; + return check_assignment_types(*target, expr, typediff); +} + +static int printf_fmt_pointer(void *data, struct expression **expr, struct symbol *ctype, struct symbol **target, const char **typediff) +{ + *target = &ptr_ctype; + // todo - deal with not caring about address-space // + return check_assignment_types(*target, expr, typediff); +} + +static int printf_fmt_print_pointer(void *data, struct expression **expr, struct symbol *ctype, struct symbol **target, const char **typediff) +{ + *target = &ptr_ctype; + return check_assignment_types(*target, expr, typediff); +} + +struct format_type printf_fmts[] = { + { "c", .test = printf_fmt_inttype, &char_ctype }, + // todo lc (wchar_t) + // todo h/hh (char types) + { "f", .test = printf_fmt_inttype, &double_ctype }, + { "g", .test = printf_fmt_inttype, &double_ctype }, + // todo j (intmax/unitmax) + { "s", .test = printf_fmt_string, }, + // todo n (pointer to integer) + { "p", .test = printf_fmt_print_pointer, }, + { "px", .test = printf_fmt_print_pointer, }, + // todo q (modifier?) + { "d", .test = printf_fmt_inttype, &int_ctype }, + { "ld", .test = printf_fmt_inttype, &long_ctype }, + { "lld", .test = printf_fmt_inttype, &llong_ctype }, + { "u", .test = printf_fmt_inttype, &uint_ctype }, + { "lu", .test = printf_fmt_inttype, &ulong_ctype }, + { "llu", .test = printf_fmt_inttype, &ullong_ctype }, + { "L", .test = printf_fmt_inttype, &ldouble_ctype }, + { "x", .test = printf_fmt_inttype, &uint_ctype }, + { "lx", .test = printf_fmt_inttype, &ulong_ctype }, + { "llx", .test = printf_fmt_inttype, &ullong_ctype }, + { "X", .test = printf_fmt_inttype, &int_ctype }, + { "lX", .test = printf_fmt_inttype, &ulong_ctype }, + { "llX", .test = printf_fmt_inttype, &ullong_ctype }, + { "L", .test = printf_fmt_inttype, &ldouble_ctype }, + // todo z/Z sizeof ? + { }, +}; + +static struct format_type printf_fmt_ptr_ref = { "p", .test = printf_fmt_pointer, }; + +static struct expression *get_expression_n(struct expression_list *head, int nr) +{ + return ptr_list_nth_entry((struct ptr_list *)head, nr); +} + +static struct format_type *parse_printf_get_fmt(char *msg, char **msgout) +{ + struct format_type *type; + char *end; + int len; + + for (end = msg; *end > ' '; end++); + *msgout = end+1; + + len = (end - msg); + for (type = printf_fmts; type->format != NULL; type++) + if (!strncmp(msg, type->format, len)) + return type; + + return NULL; +} + +static int is_printf_flag(char ch) +{ + return ch == '0' || ch == '+' || ch == '-' || ch == ' ' || ch == '#'; +} + +static int printf_check_position(char **fmt) +{ + char *ptr= *fmt; + + while (isdigit(*ptr)) + ptr++; + if (*ptr == '$') { + char *pos = *fmt; + *fmt = ptr+1; + return atoi(pos); + } + return -1; +} + +static void parse_format_printf_checkpos(struct format_state *state, const char *which) +{ + if (state->used_position) + warning(state->expr->pos, + "format %d: %s: no position specified", + state->arg_index-1, which); +} + +static int parse_format_printf_argfield(char **fmtptr, struct format_state *state, struct expression_list *head, int *pos, const char *which) +{ + struct expression *expr; + char *fmt = *fmtptr; + int argpos = -1; + + /* check for simple digit-string width/precision specifier first */ + if (*fmt != '*') { + while (isdigit(*fmt)) + fmt++; + *fmtptr = fmt; + return 0; + } + + fmt++; + argpos = printf_check_position(&fmt); + + if (argpos > 0) { + argpos += state->va_start - 1; + state->used_position = 1; + } else { + argpos = (*pos)++; + state->arg_index++; + parse_format_printf_checkpos(state, which); + } + + *fmtptr = fmt; + expr = get_expression_n(head, argpos-1); + if (!expr) { + warning(state->expr->pos, "%s: no argument at position %d", which, argpos); + return 1; + } + + /* todo - verify we got an actual integer argument */ + return 0; +} + +/* printf format parsing code + * + * TODO: + * - fix up type checking of castable types (such as int vs long vs long long) + * - validate all arguments specified are also used... + * - possibly remove return code from this function + */ +static int parse_format_printf(const char **fmtstring, struct format_state *state, struct expression_list *head) +{ + char buff[strlen(*fmtstring)+1]; + struct format_type *type; + struct expression *expr; + const char *string = *fmtstring; + char *fmtpost = NULL, *fmt = buff; + int pos = state->arg_index; + int error = 0; + int ret; + + /* trivial check for %% */ + string++; + if (string[0] == '%') { + *fmtstring = string; + return 0; + } + + state->arg_index++; + state->fmt_index++; + + strcpy(buff, string); + ret = printf_check_position(&fmt); + if (ret == 0) { + /* we got an invalid position argument */ + error++; + } else if (ret < 0) { + parse_format_printf_checkpos(state, "position"); + } else { + state->used_position = 1; + pos = ret + state->va_start - 1; + } + + /* get rid of any formatting flag bits */ + while (is_printf_flag(*fmt)) + fmt++; + + /* now there is the posibility of a width specifier */ + if (parse_format_printf_argfield(&fmt, state, head, &pos, "width")) + error++; + + /* now we might have the precision specifier */ + if (*fmt == '.') { + fmt++; + if (parse_format_printf_argfield(&fmt, state, head, &pos, "position")) + error++; + } + + type = parse_printf_get_fmt(fmt, &fmtpost); + *fmtstring += fmtpost - buff; + fmtpost[-1] = '\0'; + + if (!type && fmt[0] == 'p') + type = &printf_fmt_ptr_ref; /* probably some extension */ + + if (type) { + struct symbol *ctype, *source, *target = NULL; + const char *typediff = "different types"; + int ret; + + expr = get_expression_n(head, pos-1); + if (!expr) + return -2; + + ctype = evaluate_expression(expr); + if (!ctype) + return -3; + + source = degenerate(expr); + ret = (type->test)(type->data, &expr, ctype, &target, &typediff); + + if (ret == 0) { + warning(expr->pos, "incorrect type in argument %d (%s)", pos, typediff); + info(expr->pos, " expected %s", show_typename(target)); + info(expr->pos, " got %s", show_typename(source)); + } + } else { + warning(expr->pos, "cannot evaluate type '%s'", buff); + return -1; + } + + return 1; +} + +/* attempt to run through a printf format string and work out the types + * it specifies. The format is parsed from the __attribute__(format()) + * in the parser code which stores the positions of the message and arg + * start in the ctype. + */ +static void evaluate_format_printf(struct symbol *fn, struct expression_list *head) +{ + struct format_state state = { }; + struct expression *expr; + const char *fmt_string = NULL; + + expr = get_expression_n(head, fn->ctype.printf_msg-1); + if (!expr) + return; + if (expr->string && expr->string->length) + fmt_string = expr->string->data; + if (!fmt_string) { + struct symbol *sym = evaluate_expression(expr); + + /* attempt to find initialiser for this */ + if (sym && sym->initializer && sym->initializer->string) + fmt_string = sym->initializer->string->data; + } + + state.expr = expr; + state.va_start = fn->ctype.printf_va_start; + state.arg_index = fn->ctype.printf_va_start; + + if (!fmt_string) { + warning(expr->pos, "not a format string?"); + } else { + const char *string = fmt_string; + + for (; string[0] != '\0'; string++) { + if (string[0] != '%') + continue; + parse_format_printf(&string, &state, head); + } + } +} + static int evaluate_arguments(struct symbol *fn, struct expression_list *head) { struct expression *expr; @@ -2250,6 +2541,12 @@ static int evaluate_arguments(struct symbol *fn, struct expression_list *head) struct symbol *argtype; int i = 1; + /* do this first, otherwise the arugment info may get lost or changed + * later on in the evaluation loop. + */ + if (fn->ctype.printf_va_start) + evaluate_format_printf(fn, head); + PREPARE_PTR_LIST(argument_types, argtype); FOR_EACH_PTR (head, expr) { struct expression **p = THIS_ADDRESS(expr); From patchwork Thu Nov 1 18:11:15 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Dooks X-Patchwork-Id: 10664415 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1D40A46E4 for ; Thu, 1 Nov 2018 18:11:29 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0CF4B2C307 for ; Thu, 1 Nov 2018 18:11:29 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 019872C324; Thu, 1 Nov 2018 18:11:28 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 936162C326 for ; Thu, 1 Nov 2018 18:11:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727532AbeKBDPb (ORCPT ); Thu, 1 Nov 2018 23:15:31 -0400 Received: from imap1.codethink.co.uk ([176.9.8.82]:52038 "EHLO imap1.codethink.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727573AbeKBDPb (ORCPT ); Thu, 1 Nov 2018 23:15:31 -0400 Received: from [148.252.241.226] (helo=rainbowdash) by imap1.codethink.co.uk with esmtpsa (Exim 4.84_2 #1 (Debian)) id 1gIHRF-0006No-Sk; Thu, 01 Nov 2018 18:11:25 +0000 Received: from ben by rainbowdash with local (Exim 4.91) (envelope-from ) id 1gIHRD-00012g-N5; Thu, 01 Nov 2018 18:11:23 +0000 From: Ben Dooks To: linux-sparse@vger.kernel.org Cc: Ben Dooks Subject: [PATCH 3/5] add -Wformat Date: Thu, 1 Nov 2018 18:11:15 +0000 Message-Id: <20181101181117.3877-4-ben.dooks@codethink.co.uk> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181101181117.3877-1-ben.dooks@codethink.co.uk> References: <20181101181117.3877-1-ben.dooks@codethink.co.uk> MIME-Version: 1.0 Sender: linux-sparse-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-sparse@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add option to enable/disable format checking (and default it to on) Signed-off-by: Ben Dooks --- evaluate.c | 2 +- lib.c | 2 ++ lib.h | 1 + sparse.1 | 9 +++++++++ 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/evaluate.c b/evaluate.c index ffb4af6..9868e9c 100644 --- a/evaluate.c +++ b/evaluate.c @@ -2544,7 +2544,7 @@ static int evaluate_arguments(struct symbol *fn, struct expression_list *head) /* do this first, otherwise the arugment info may get lost or changed * later on in the evaluation loop. */ - if (fn->ctype.printf_va_start) + if (Wformat && fn->ctype.printf_va_start) evaluate_format_printf(fn, head); PREPARE_PTR_LIST(argument_types, argtype); diff --git a/lib.c b/lib.c index 645132a..47b4f05 100644 --- a/lib.c +++ b/lib.c @@ -232,6 +232,7 @@ int Wdesignated_init = 1; int Wdo_while = 0; int Winit_cstring = 0; int Wenum_mismatch = 1; +int Wformat = 1; int Wsparse_error = 0; int Wmemcpy_max_count = 1; int Wnon_pointer_null = 1; @@ -525,6 +526,7 @@ static const struct warning { { "do-while", &Wdo_while }, { "enum-mismatch", &Wenum_mismatch }, { "init-cstring", &Winit_cstring }, + { "format", &Wformat }, { "memcpy-max-count", &Wmemcpy_max_count }, { "non-pointer-null", &Wnon_pointer_null }, { "old-initializer", &Wold_initializer }, diff --git a/lib.h b/lib.h index a9b70b0..6434329 100644 --- a/lib.h +++ b/lib.h @@ -124,6 +124,7 @@ extern int Wdefault_bitfield_sign; extern int Wdesignated_init; extern int Wdo_while; extern int Wenum_mismatch; +extern int Wformat; extern int Wsparse_error; extern int Winit_cstring; extern int Wmemcpy_max_count; diff --git a/sparse.1 b/sparse.1 index e183204..4e81bdc 100644 --- a/sparse.1 +++ b/sparse.1 @@ -219,6 +219,15 @@ trouble. Sparse does not issue these warnings by default. . .TP +.B \-Wformat +Warn about parameter mis-match to any variadic function which specifies +where the format string is with the +.BI __attribute__((format( type, message, va_start ))) +attribute. + +Sparse issues these warnings by default. To turn them off, use +\fB\-Wno\-format\fR +.TP .B \-Wmemcpy\-max\-count Warn about call of \fBmemcpy()\fR, \fBmemset()\fR, \fBcopy_from_user()\fR, or \fBcopy_to_user()\fR with a large compile-time byte count. From patchwork Thu Nov 1 18:11:16 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Dooks X-Patchwork-Id: 10664413 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id AF37417DF for ; Thu, 1 Nov 2018 18:11:28 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A2DF62C307 for ; Thu, 1 Nov 2018 18:11:28 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 965C92C327; Thu, 1 Nov 2018 18:11:28 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 33E0C2C324 for ; Thu, 1 Nov 2018 18:11:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727703AbeKBDPa (ORCPT ); Thu, 1 Nov 2018 23:15:30 -0400 Received: from imap1.codethink.co.uk ([176.9.8.82]:52037 "EHLO imap1.codethink.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727564AbeKBDPa (ORCPT ); Thu, 1 Nov 2018 23:15:30 -0400 Received: from [148.252.241.226] (helo=rainbowdash) by imap1.codethink.co.uk with esmtpsa (Exim 4.84_2 #1 (Debian)) id 1gIHRF-0006Nn-RG; Thu, 01 Nov 2018 18:11:25 +0000 Received: from ben by rainbowdash with local (Exim 4.91) (envelope-from ) id 1gIHRD-00012i-OF; Thu, 01 Nov 2018 18:11:23 +0000 From: Ben Dooks To: linux-sparse@vger.kernel.org Cc: Ben Dooks Subject: [PATCH 4/5] validation: add clean command Date: Thu, 1 Nov 2018 18:11:16 +0000 Message-Id: <20181101181117.3877-5-ben.dooks@codethink.co.uk> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181101181117.3877-1-ben.dooks@codethink.co.uk> References: <20181101181117.3877-1-ben.dooks@codethink.co.uk> MIME-Version: 1.0 Sender: linux-sparse-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-sparse@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add command to clean the output files up post working. Signed-off-by: Ben Dooks --- validation/test-suite | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/validation/test-suite b/validation/test-suite index 5e10942..c5f726f 100755 --- a/validation/test-suite +++ b/validation/test-suite @@ -157,6 +157,7 @@ echo "Usage: $prog_name [command] [command arguments]" echo echo "commands:" echo " none runs the whole test suite" +echo " clean clean all output files" echo " single file runs the test in 'file'" echo " format file [name [cmd]] helps writing a new test case using cmd" echo @@ -372,6 +373,16 @@ arg_file() case "$1" in '') do_test_suite + ;; + clean) + rm *.output.diff + rm *.output.got + rm *.output.expected + rm *.error.diff + rm *.error.got + rm *.error.expected + + ;; single) arg_file "$2" From patchwork Thu Nov 1 18:11:17 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Dooks X-Patchwork-Id: 10664417 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 86EE61734 for ; Thu, 1 Nov 2018 18:11:30 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7ADF72C307 for ; Thu, 1 Nov 2018 18:11:30 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6F96B2C327; Thu, 1 Nov 2018 18:11:30 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B5CAE2C307 for ; Thu, 1 Nov 2018 18:11:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727564AbeKBDPc (ORCPT ); Thu, 1 Nov 2018 23:15:32 -0400 Received: from imap1.codethink.co.uk ([176.9.8.82]:52039 "EHLO imap1.codethink.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727617AbeKBDPc (ORCPT ); Thu, 1 Nov 2018 23:15:32 -0400 Received: from [148.252.241.226] (helo=rainbowdash) by imap1.codethink.co.uk with esmtpsa (Exim 4.84_2 #1 (Debian)) id 1gIHRF-0006Np-Sm; Thu, 01 Nov 2018 18:11:25 +0000 Received: from ben by rainbowdash with local (Exim 4.91) (envelope-from ) id 1gIHRD-00012k-PS; Thu, 01 Nov 2018 18:11:23 +0000 From: Ben Dooks To: linux-sparse@vger.kernel.org Cc: Ben Dooks Subject: [PATCH 5/5] tests: add varargs printf format tests Date: Thu, 1 Nov 2018 18:11:17 +0000 Message-Id: <20181101181117.3877-6-ben.dooks@codethink.co.uk> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181101181117.3877-1-ben.dooks@codethink.co.uk> References: <20181101181117.3877-1-ben.dooks@codethink.co.uk> MIME-Version: 1.0 Sender: linux-sparse-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-sparse@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add some tests for the new printf format checking code. Note, these do not all pass yet. Signed-off-by: Ben Dooks --- validation/varargs-format-addrspace1.c | 60 ++++++++++++++++++++++++++ validation/varargs-format-bad.c | 14 +++++- validation/varargs-format-checking.c | 19 ++++++++ validation/varargs-format-position.c | 29 +++++++++++++ validation/varargs-format-prefix.c | 18 ++++++++ validation/varargs-format-tests.c | 35 +++++++++++++++ 6 files changed, 173 insertions(+), 2 deletions(-) create mode 100644 validation/varargs-format-addrspace1.c create mode 100644 validation/varargs-format-checking.c create mode 100644 validation/varargs-format-position.c create mode 100644 validation/varargs-format-prefix.c create mode 100644 validation/varargs-format-tests.c diff --git a/validation/varargs-format-addrspace1.c b/validation/varargs-format-addrspace1.c new file mode 100644 index 0000000..3c1f37a --- /dev/null +++ b/validation/varargs-format-addrspace1.c @@ -0,0 +1,60 @@ + +extern int variadic(char *msg, ...) __attribute__((format (printf, 1, 2))); +extern int variadic2(char *msg, int , ...) __attribute__((format (printf, 1, 3))); +extern int variadic3(int, char *msg, ...) __attribute__((format (printf, 2, 3))); + +static void test(void) { + void __attribute__((noderef, address_space(1))) *a; + void *b; + + variadic("%s\n", a); + variadic("%s\n", b); + variadic("%s %s\n", b, a); + variadic2("%s %s\n", 1, b, a); + variadic3(1, "%s %s\n", b, a); + variadic3(1, "%s %p\n", b, a); +} + +static char __msg[] = "%s %p"; + +static void test2(void) { + void __attribute__((noderef, address_space(1))) *a; + void *b; + int (*ptr)(char *msg, ...) __attribute__((format (printf, 1, 2))) = variadic; + int (*ptr2)(char *msg, ...) __attribute__((format (printf, 1, 2))); + + variadic(__msg, a, b); + ptr("hello %s %s", a, b); + ptr2("hello %s %s", a, b); +} + +/* + * check-name: variadic formatting test with addres-space to %s + * + * check-error-start +varargs-format-addrspace1.c:10:26: warning: incorrect type in argument 2 (different address spaces) +varargs-format-addrspace1.c:10:26: expected string +varargs-format-addrspace1.c:10:26: got void [noderef] *a +varargs-format-addrspace1.c:12:32: warning: incorrect type in argument 3 (different address spaces) +varargs-format-addrspace1.c:12:32: expected string +varargs-format-addrspace1.c:12:32: got void [noderef] *a +varargs-format-addrspace1.c:13:36: warning: incorrect type in argument 4 (different address spaces) +varargs-format-addrspace1.c:13:36: expected string +varargs-format-addrspace1.c:13:36: got void [noderef] *a +varargs-format-addrspace1.c:14:36: warning: incorrect type in argument 4 (different address spaces) +varargs-format-addrspace1.c:14:36: expected string +varargs-format-addrspace1.c:14:36: got void [noderef] *a +varargs-format-addrspace1.c:15:36: warning: incorrect type in argument 4 (different address spaces) +varargs-format-addrspace1.c:15:36: expected void * +varargs-format-addrspace1.c:15:36: got void [noderef] *a +varargs-format-addrspace1.c:26:25: warning: incorrect type in argument 2 (different address spaces) +varargs-format-addrspace1.c:26:25: expected string +varargs-format-addrspace1.c:26:25: got void [noderef] *a +varargs-format-addrspace1.c:27:25: warning: incorrect type in argument 2 (different address spaces) +varargs-format-addrspace1.c:27:25: expected string +varargs-format-addrspace1.c:27:25: got void [noderef] *a +varargs-format-addrspace1.c:28:25: warning: incorrect type in argument 2 (different address spaces) +varargs-format-addrspace1.c:28:25: expected string +varargs-format-addrspace1.c:28:25: got void [noderef] *a + * check-error-end + */ diff --git a/validation/varargs-format-bad.c b/validation/varargs-format-bad.c index a8b9cdb..2b96aba 100644 --- a/validation/varargs-format-bad.c +++ b/validation/varargs-format-bad.c @@ -1,9 +1,19 @@ extern int variadic(char *msg, ...) __attribute__((format (printf, 0, 0))); extern int variadic2(char *msg, int , ...) __attribute__((format (printf, 2, 2))); -extern int variadic3(char *msg, int , ...) __attribute__((format (printf, 2, 3))); +extern int variadic3(char *msg, int , ...) __attribute__((format (printf, 2, 1))); static void test(void) { - variadic3("test", 1); } +/* + * check-name: variadic formatting test with bad formatting parameters + * + * check-error-start +varargs-format-bad.c:2:72: warning: bad format positions +varargs-format-bad.c:3:79: warning: bad format positions +varargs-format-bad.c:4:79: warning: format cannot be after va_args +* check-error-end + */ + + diff --git a/validation/varargs-format-checking.c b/validation/varargs-format-checking.c new file mode 100644 index 0000000..672b497 --- /dev/null +++ b/validation/varargs-format-checking.c @@ -0,0 +1,19 @@ + +extern void pf(char *msg, ...) __attribute__((format (printf, 1, 2))); + +static void test(void) { + pf("%u %lu %llu\n", 1U, 1UL, 1ULL); + pf("%d %ld %lld\n", 1, 1L, 1LL); + pf("%x %lx %llx\n", 1U, 1UL, 1ULL); + pf("%d %ld %lld\n", 1, 1L, 1L); +} + +/* + * check-name: variadic formatting test type checking + * + * check-error-start +varargs-type-checking.c:8:36: warning: incorrect type in argument 4 (different types) +varargs-type-checking.c:8:36: expected long long +varargs-type-checking.c:8:36: got long + * check-error-end + */ diff --git a/validation/varargs-format-position.c b/validation/varargs-format-position.c new file mode 100644 index 0000000..4473d47 --- /dev/null +++ b/validation/varargs-format-position.c @@ -0,0 +1,29 @@ + +extern void pf(char *msg, ...) __attribute__((format (printf, 1, 2))); + +static void test(void) { + pf("%2$d %u\n", 1U, 1L); + pf("%3$d %2$u\n", 1U, 1); + pf("%1$d %2$d\n", 1L, 1); +} + +/* + * check-name: variadic formatting test position checking + * + * check-error-start +varargs-format-position.c:5:29: warning: incorrect type in argument 3 (different types) +varargs-format-position.c:5:29: expected int +varargs-format-position.c:5:29: got long +varargs-format-position.c:5:12: warning: format 3: position: no position specified +varargs-format-position.c:5:29: warning: incorrect type in argument 3 (different types) +varargs-format-position.c:5:29: expected unsigned int +varargs-format-position.c:5:29: got long +varargs-format-position.c:6:31: warning: incorrect type in argument 3 (different types) +varargs-format-position.c:6:31: expected unsigned int +varargs-format-position.c:6:31: got int +varargs-format-position.c:7:27: warning: incorrect type in argument 2 (different types) +varargs-format-position.c:7:27: expected int +varargs-format-position.c:7:27: got long + * check-error-end + * + */ diff --git a/validation/varargs-format-prefix.c b/validation/varargs-format-prefix.c new file mode 100644 index 0000000..a91d1ba --- /dev/null +++ b/validation/varargs-format-prefix.c @@ -0,0 +1,18 @@ + +extern int __attribute__((format (printf, 1, 2))) variadic(char *msg, ...); + +static int test(void) { + void __attribute__((noderef, address_space(1))) *a; + + variadic("%s\n", a); +} + +/* + * check-name: variadic formatting test prefix based __attribute__ + * + * check-error-start +varargs-format-prefix.c:7:26: warning: incorrect type in argument 2 (different address spaces) +varargs-format-prefix.c:7:26: expected string +varargs-format-prefix.c:7:26: got void [noderef] *a + * check-error-end + */ diff --git a/validation/varargs-format-tests.c b/validation/varargs-format-tests.c new file mode 100644 index 0000000..e2b8196 --- /dev/null +++ b/validation/varargs-format-tests.c @@ -0,0 +1,35 @@ + +extern void pf(char *msg, ...) __attribute__((format (printf, 1, 2))); + +static int test(void) +{ + pf("%*d\n", 5, 10); /* value 10, print width is 5 */ + pf("%2$*1$d\n", 5, 10); /* value 10, print width is 5 */ + pf("%3$*2$d\n", 1, 5, 10); /* ok, skipping the '1' */ + pf("%3$-*2$d\n", 1, 5, 10); /* ok, skipping the '1' */ + pf("%3$*2$-d\n", 1, 5, 10); /* ok, skipping the '1' (breaks) */ + pf("%3$ *2$d\n", 1, 5, 10); /* ok, skipping the '1' */ + pf("%3$+*2$d\n", 1, 5, 10); /* ok, skipping the '1' */ + pf("%3$0+*2$d\n", 1, 5, 10); /* ok, skipping the '1' */ + pf("%3$+0*2$d\n", 1, 5, 10); /* ok, skipping the '1' */ + pf("%3$+#*2$d\n", 1, 5, 10); /* ok, skipping the '1' */ + pf("%3$+#*2$.5d\n", 1, 5, 10); /* ok, skipping the '1' */ + + /* go with some precision as well as width strings */ + pf("%2$+*1$.6d\n", 5, 10); /* ok */ + pf("%2$+*1$.*3$d\n", 5, 10, 6); /* ok */ + pf("%2$+*3$.*1$d\n", 6, 10, 5); /* ok */ + pf("%2$+*1$.*d\n", 5, 10, 6); /* not ok */ + + pf("%s", "msg"); + return 0; +} + +/* + * check-name: variadic formatting tests for width/precisions + * + * check-error-start +varargs-format-tests.c:9:32: warning: cannot evaluate type '3$*2$-d' +varargs-format-tests.c:22:12: warning: format 3: position: no position specified + * check-error-end + */