From patchwork Fri Oct 26 15:26:30 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Dooks X-Patchwork-Id: 10657597 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 CE97F13BF for ; Fri, 26 Oct 2018 15:26:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C399D2BA6B for ; Fri, 26 Oct 2018 15:26:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B6DCB2C968; Fri, 26 Oct 2018 15:26:37 +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 502992BA6B for ; Fri, 26 Oct 2018 15:26:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726179AbeJ0AEF (ORCPT ); Fri, 26 Oct 2018 20:04:05 -0400 Received: from imap1.codethink.co.uk ([176.9.8.82]:58292 "EHLO imap1.codethink.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726159AbeJ0AEF (ORCPT ); Fri, 26 Oct 2018 20:04:05 -0400 Received: from [148.252.241.226] (helo=rainbowdash) by imap1.codethink.co.uk with esmtpsa (Exim 4.84_2 #1 (Debian)) id 1gG40Q-0007d0-1Y; Fri, 26 Oct 2018 16:26:34 +0100 Received: from ben by rainbowdash with local (Exim 4.91) (envelope-from ) id 1gG40P-0007vL-M2; Fri, 26 Oct 2018 16:26:33 +0100 From: Ben Dooks To: linux-sparse@vger.kernel.org Cc: Ben Dooks Subject: [PATCH 1/3] initial parsing of __attribute__((format)) Date: Fri, 26 Oct 2018 16:26:30 +0100 Message-Id: <20181026152632.30318-2-ben.dooks@codethink.co.uk> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181026152632.30318-1-ben.dooks@codethink.co.uk> References: <20181026152632.30318-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 --- parse.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- symbol.h | 2 ++ 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/parse.c b/parse.c index 02a55a7..bb0545c 100644 --- a/parse.c +++ b/parse.c @@ -84,7 +84,7 @@ static attr_t attribute_address_space, attribute_context, attribute_designated_init, attribute_transparent_union, ignore_attribute, - attribute_mode, attribute_force; + attribute_mode, attribute_force, attribute_format; typedef struct symbol *to_mode_t(struct symbol *); @@ -353,6 +353,10 @@ static struct symbol_op attr_force_op = { .attribute = attribute_force, }; +static struct symbol_op attr_format = { + .attribute = attribute_format, +}; + static struct symbol_op address_space_op = { .attribute = attribute_address_space, }; @@ -407,6 +411,10 @@ static struct symbol_op mode_word_op = { .to_mode = to_word_mode }; +static struct symbol_op attr_printf_op = { + .type = KW_FORMAT, +}; + /* Using NS_TYPEDEF will also make the keyword a reserved one */ static struct init_keyword { const char *name; @@ -513,6 +521,8 @@ static struct init_keyword { { "bitwise", NS_KEYWORD, MOD_BITWISE, .op = &attr_bitwise_op }, { "__bitwise__",NS_KEYWORD, MOD_BITWISE, .op = &attr_bitwise_op }, { "address_space",NS_KEYWORD, .op = &address_space_op }, + { "format", NS_KEYWORD, .op = &attr_format }, + { "printf", NS_KEYWORD, .op = &attr_printf_op }, { "mode", NS_KEYWORD, .op = &mode_op }, { "context", NS_KEYWORD, .op = &context_op }, { "designated_init", NS_KEYWORD, .op = &designated_init_op }, @@ -1051,6 +1061,69 @@ static struct token *attribute_address_space(struct token *token, struct symbol return token; } +static struct token *attribute_format(struct token *token, struct symbol *attr, struct decl_state *ctx) +{ + struct expression *args[3]; + struct symbol *fmt_sym = NULL; + int argc = 0; + + /* expecting format ( type, start, va_args at) */ + + token = expect(token, '(', "after format attribute"); + while (!match_op(token, ')')) { + struct expression *expr = NULL; + + if (argc == 0) { + if (token_type(token) == TOKEN_IDENT) + fmt_sym = lookup_keyword(token->ident, NS_KEYWORD); + + if (!fmt_sym || !fmt_sym->op || + fmt_sym->op != &attr_printf_op) { + sparse_error(token->pos, + "unknown format type '%s'\n", + show_ident(token->ident)); + fmt_sym = NULL; + } + } + + token = conditional_expression(token, &expr); + if (!expr) + break; + if (argc < 3) + args[argc++] = expr; + if (!match_op(token, ',')) + break; + token = token->next; + } + + if (argc != 3 || !fmt_sym) + warning(token->pos, + "expected format type and start/position values"); + else { + struct symbol *base_type = ctx->ctype.base_type; + long long start, at; + + start = get_expression_value(args[2]); + at = get_expression_value(args[1]); + + if (start <= 0 || at <= 0) + warning(token->pos, "bad format positions"); + else if (!base_type) + sparse_error(token->pos, "no base context for format"); + else if (base_type->type != SYM_FN) + warning(token->pos, "attribute format can only be used on functions"); + else if (!base_type->variadic) + warning(token->pos, "attribute format used on non variadic function"); + else { + base_type->printf_va_start = start; + base_type->printf_msg = at; + } + } + + token = expect(token, ')', "after format attribute"); + return token; +} + static struct symbol *to_QI_mode(struct symbol *ctype) { if (ctype->ctype.base_type != &int_type) diff --git a/symbol.h b/symbol.h index 3274496..5f1b85d 100644 --- a/symbol.h +++ b/symbol.h @@ -86,6 +86,7 @@ enum keyword { KW_SHORT = 1 << 7, KW_LONG = 1 << 8, KW_EXACT = 1 << 9, + KW_FORMAT = 1 << 10, }; struct context { @@ -185,6 +186,7 @@ struct symbol { struct entrypoint *ep; long long value; /* Initial value */ struct symbol *definition; + long long printf_va_start, printf_msg; }; }; union /* backend */ { From patchwork Fri Oct 26 15:26:31 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Dooks X-Patchwork-Id: 10657593 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 B028D14BD for ; Fri, 26 Oct 2018 15:26:36 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A685D2C437 for ; Fri, 26 Oct 2018 15:26:36 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 978FF2C968; Fri, 26 Oct 2018 15:26:36 +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 4BDB62C968 for ; Fri, 26 Oct 2018 15:26:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726113AbeJ0AED (ORCPT ); Fri, 26 Oct 2018 20:04:03 -0400 Received: from imap1.codethink.co.uk ([176.9.8.82]:58294 "EHLO imap1.codethink.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726195AbeJ0AED (ORCPT ); Fri, 26 Oct 2018 20:04:03 -0400 Received: from [148.252.241.226] (helo=rainbowdash) by imap1.codethink.co.uk with esmtpsa (Exim 4.84_2 #1 (Debian)) id 1gG40Q-0007d3-3V; Fri, 26 Oct 2018 16:26:34 +0100 Received: from ben by rainbowdash with local (Exim 4.91) (envelope-from ) id 1gG40P-0007vN-NE; Fri, 26 Oct 2018 16:26:33 +0100 From: Ben Dooks To: linux-sparse@vger.kernel.org Cc: Ben Dooks Subject: [PATCH 2/3] tokenize: check if string is not NULL Date: Fri, 26 Oct 2018 16:26:31 +0100 Message-Id: <20181026152632.30318-3-ben.dooks@codethink.co.uk> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181026152632.30318-1-ben.dooks@codethink.co.uk> References: <20181026152632.30318-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 --- tokenize.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tokenize.c b/tokenize.c index 99b9580..c32f8c7 100644 --- a/tokenize.c +++ b/tokenize.c @@ -124,7 +124,7 @@ const char *show_string(const struct string *string) char *ptr; int i; - if (!string->length) + if (!string || !string->length) return ""; ptr = buffer; *ptr++ = '"'; From patchwork Fri Oct 26 15:26:32 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Dooks X-Patchwork-Id: 10657595 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 32548180E for ; Fri, 26 Oct 2018 15:26:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 25E0F2BA6B for ; Fri, 26 Oct 2018 15:26:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1A4242C968; Fri, 26 Oct 2018 15:26:37 +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 A40962BA6B for ; Fri, 26 Oct 2018 15:26:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726195AbeJ0AEE (ORCPT ); Fri, 26 Oct 2018 20:04:04 -0400 Received: from imap1.codethink.co.uk ([176.9.8.82]:58291 "EHLO imap1.codethink.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726179AbeJ0AEE (ORCPT ); Fri, 26 Oct 2018 20:04:04 -0400 Received: from [148.252.241.226] (helo=rainbowdash) by imap1.codethink.co.uk with esmtpsa (Exim 4.84_2 #1 (Debian)) id 1gG40Q-0007d4-1u; Fri, 26 Oct 2018 16:26:34 +0100 Received: from ben by rainbowdash with local (Exim 4.91) (envelope-from ) id 1gG40P-0007vR-OH; Fri, 26 Oct 2018 16:26:33 +0100 From: Ben Dooks To: linux-sparse@vger.kernel.org Cc: Ben Dooks Subject: [PATCH 3/3] initial variadic argument code Date: Fri, 26 Oct 2018 16:26:32 +0100 Message-Id: <20181026152632.30318-4-ben.dooks@codethink.co.uk> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181026152632.30318-1-ben.dooks@codethink.co.uk> References: <20181026152632.30318-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 --- evaluate.c | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 157 insertions(+), 1 deletion(-) diff --git a/evaluate.c b/evaluate.c index b96696d..82ddf9f 100644 --- a/evaluate.c +++ b/evaluate.c @@ -2243,11 +2243,154 @@ static struct symbol *evaluate_alignof(struct expression *expr) return size_t_ctype; } +static int decompose_format_printf(const char *string, struct symbol **result) +{ + int count = 0; + + for (; string[0] != '\0'; string++) { + if (string[0] == '%') { + int len = 0; + struct symbol *sym = NULL; + if (string[1] == '%') { + string++; + continue; + } + + /* get rid of any formatting width bits */ + while (isdigit(string[1]) || string[1] == '+' || string[1] == '-') + string++; + + switch (string[1]) { + case 'C': + /* TODO - same as lc */ + break; + case 'c': + /* TODO - can take l modifier */ + sym = &char_ctype; + break; + case 'f': + case 'g': + sym = &double_ctype; + break; + case 'h': + /* TODO hh */ + len = -1; + break; + case 'j': /* ignore intmax/uintmax for the moment */ + break; + case 'L': + sym = &ldouble_ctype; + break; + case 'l': + len++; + break; + case 'p': + /* TODO - deal with void * not being de-referenced in some cases*/ + sym = &ptr_ctype; + break; + case 'q': + len = 2; + break; + case 's': + sym = &string_ctype; + break; + case 'n': + /* TODO - actually pointer to integer */ + sym = &ptr_ctype; + break; + /* note, d is out of alpha order */ + case 'd': + switch (len) { + case -1: sym = &short_ctype; break; + case 0: sym = &int_ctype; break; + case 1: sym = &long_ctype; break; + case 2: sym = &llong_ctype; break; + case 3: sym = &lllong_ctype; break; + } + break; + case 'u': + switch (len) { + case -1: sym = &ushort_ctype; break; + case 0: sym = &uint_ctype; break; + case 1: sym = &ulong_ctype; break; + case 2: sym = &ullong_ctype; break; + case 3: sym = &ulllong_ctype; break; + } + break; + case 'x': + case 'X': + switch (len) { + case 0: sym = &uint_ctype; break; + case 1: sym = &ulong_ctype; break; + case 2: sym = &ullong_ctype; break; + case 3: sym = &ulllong_ctype; break; + } + break; + case 'z': + case 'Z': + sym = &uint_ctype; /* TODO */ + break; + } + + if (result && sym) + *result++ = sym; + if (sym) + count++; + + while (string[0] != ' ' && string[0] != '\0') + string++; + + string--; + } + } + + return count; +} + + +static int evaluate_format_printf(struct symbol *fn, struct expression *expr, struct symbol ***result) +{ + const char *fmt_string = NULL; + + if (!expr) + return -1; + 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; + } + + if (fmt_string) { + struct symbol **syms = NULL; + int count; + + count = decompose_format_printf(fmt_string, NULL); + if (count <= 0) + return count; + + syms = calloc(sizeof(struct symbol *), count); + if (!syms) + return -1; + + count = decompose_format_printf(fmt_string, syms); + *result = syms; + return count; + } + + return -1; +} + static int evaluate_arguments(struct symbol *fn, struct expression_list *head) { struct expression *expr; struct symbol_list *argument_types = fn->arguments; + struct symbol **variadic = NULL; struct symbol *argtype; + int variadic_limit = 0; int i = 1; PREPARE_PTR_LIST(argument_types, argtype); @@ -2259,7 +2402,18 @@ static int evaluate_arguments(struct symbol *fn, struct expression_list *head) if (!ctype) return 0; - target = argtype; + if (i == fn->printf_msg) { + int ret = evaluate_format_printf(fn, *p, &variadic); + if (ret < 0) + warning((*p)->pos, "cannot parse format"); + else if (ret > 0) + variadic_limit = fn->printf_va_start + ret; + } + + if (i >= fn->printf_va_start && i <= variadic_limit) + target = variadic[i - fn->printf_va_start]; + else + target = argtype; if (!target) { struct symbol *type; int class = classify_type(ctype, &type); @@ -2286,6 +2440,8 @@ static int evaluate_arguments(struct symbol *fn, struct expression_list *head) NEXT_PTR_LIST(argtype); } END_FOR_EACH_PTR(expr); FINISH_PTR_LIST(argtype); + + free(variadic); return 1; }