From: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
To: linux-sparse@vger.kernel.org
Cc: Ben Dooks <ben.dooks@codethink.co.uk>,
Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
Subject: [PATCH 02/13] format-check: more complete parsing of the length & type modifiers
Date: Wed, 14 Oct 2020 01:22:20 +0200 [thread overview]
Message-ID: <20201013232231.10349-3-luc.vanoostenryck@gmail.com> (raw)
In-Reply-To: <20201013232231.10349-1-luc.vanoostenryck@gmail.com>
Reorganize the parsing the length modifiers to follow more closely
the specs and handle some missing cases like 'hh' or '%[ieEaA]'.
Also, treats 'L' and 'll' synonymously as done by GCC.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
verify-format.c | 265 +++++++++++++++++++++++++++---------------------
1 file changed, 151 insertions(+), 114 deletions(-)
diff --git a/verify-format.c b/verify-format.c
index 4b4730285237..ae5bb2e6e985 100644
--- a/verify-format.c
+++ b/verify-format.c
@@ -44,6 +44,14 @@
#include "expression.h"
#include "verify-format.h"
+enum length_mod {
+ LEN_none,
+ LEN_hh, LEN_h,
+ LEN_l, LEN_ll,
+ LEN_L,
+ LEN_j, LEN_z, LEN_t,
+};
+
struct format_type {
const char *format;
int (*test)(struct format_type *fmt,
@@ -113,140 +121,169 @@ static struct format_type printf_fmt_ptr_ref = {
.test = printf_fmt_pointer,
};
-static int is_float_spec(char t)
-{
- return t == 'f' || t == 'g' || t == 'F' || t == 'G';
-}
-
static struct format_type *parse_printf_get_fmt(struct format_type *type,
const char *msg, const char **msgout)
{
const char *ptr = msg;
- int szmod=0;
+ int szmod = LEN_none;
type->test = NULL;
*msgout = ptr;
- if (*ptr == 's') {
- ptr++;
- type->test = printf_fmt_string;
- type->type = &const_string_ctype;
- } else if (*ptr == 'c') {
- ptr++;
- type->test = printf_fmt_numtype;
- type->type = &char_ctype;
- } else if (*ptr == 'p') {
- ptr++;
- type->test = printf_fmt_print_pointer;
- /* check for pointer being printed as hex explicitly */
- if (*ptr == 'x' || *ptr == 'X') {
+ switch (*ptr++) {
+ case 'h':
+ szmod = LEN_h;
+ if (*ptr == 'h') {
+ szmod = LEN_hh;
ptr++;
- } else if (isalpha(*ptr)) {
- /* probably some extra specifiers after %p */
+ }
+ break;
+ case 'l':
+ szmod = LEN_l;
+ if (*ptr == 'l') {
+ szmod = LEN_ll;
ptr++;
- type->test = printf_fmt_pointer;
}
- } else if (*ptr == 'z') {
- // todo - we should construct pointer to int/etc //
+ break;
+ case 'q':
+ szmod = LEN_ll;
+ break;
+ case 'L':
+ szmod = LEN_L;
+ break;
+ case 'j':
+ szmod = LEN_j;
+ break;
+ case 'z':
+ szmod = LEN_z;
+ break;
+ case 't':
+ szmod = LEN_t;
+ break;
+ default:
+ ptr--;
+ break;
+ }
- ptr++;
- if (*ptr == 'd' || *ptr == 'i') {
- ptr++;
- type->test = printf_fmt_numtype;
+ switch (*ptr++) {
+ case 'd': case 'i':
+ type->test = printf_fmt_numtype;
+ switch (szmod) {
+ case LEN_hh:
+ case LEN_h:
+ case LEN_none:
+ type->type = &int_ctype;
+ break;
+ case LEN_l:
+ type->type = &long_ctype;
+ break;
+ case LEN_L:
+ case LEN_ll:
+ type->type = &llong_ctype;
+ break;
+ case LEN_j:
+ type->type = intmax_ctype;
+ break;
+ case LEN_z:
type->type = ssize_t_ctype;
- } else if (*ptr == 'u' || *ptr == 'x' || *ptr == 'X' ||
- *ptr == 'o') {
- ptr++;
- type->test = printf_fmt_numtype;
- type->type = size_t_ctype;
+ break;
+ case LEN_t:
+ type->type = ptrdiff_ctype;
+ break;
+ default:
+ type->test = NULL;
}
- } else {
- if (*ptr == 'l') {
- szmod++;
- ptr++;
- if (*ptr == 'l') {
- szmod++;
- ptr++;
- }
- } else if (*ptr == 'L') {
- szmod++;
- ptr++;
- } else {
- if (*ptr == 'h') { // short/char to int
- szmod = -1;
- ptr++;
- if (*ptr == 'h') // promotion from char
- ptr++;
- }
- if (*ptr == 't') { // ptrdiff_t
- szmod = 2;
- ptr++;
- }
- if (*ptr == 'j') { // intmax_t
- // todo - replace iwth intmax_ctype when added
- szmod = 1;
- ptr++;
- }
+ break;
+ case 'u': case 'o': case 'x': case 'X':
+ type->test = printf_fmt_numtype;
+ switch (szmod) {
+ case LEN_hh:
+ case LEN_h:
+ case LEN_none:
+ type->type = &uint_ctype;
+ break;
+ case LEN_l:
+ type->type = &ulong_ctype;
+ break;
+ case LEN_L:
+ case LEN_ll:
+ type->type = &ullong_ctype;
+ break;
+ case LEN_j:
+ type->type = uintmax_ctype;
+ break;
+ case LEN_z:
+ type->type = size_t_ctype;
+ break;
+ case LEN_t:
+ type->type = ptrdiff_ctype;
+ break;
+ default:
+ type->test = NULL;
}
-
- if (*ptr == 'x' || *ptr == 'X' || *ptr == 'u' || *ptr == 'o') {
- ptr++;
- type->test = printf_fmt_numtype;
- switch (szmod) {
- case -1:
- type->type = &ushort_ctype;
- break;
- case 0:
- type->type = &uint_ctype;
- break;
- case 1:
- type->type = &ulong_ctype;
- break;
- case 2:
- type->type = &ullong_ctype;
- break;
- default:
- type->test = NULL;
- }
- } else if (*ptr == 'i' || *ptr == 'd') {
- ptr++;
- type->test = printf_fmt_numtype;
- switch (szmod) {
- case -1:
- type->type = &short_ctype;
- break;
- case 0:
- type->type = &int_ctype;
- break;
- case 1:
- type->type = &long_ctype;
- break;
- case 2:
- type->type = &llong_ctype;
- break;
- default:
- type->test = NULL;
- }
- } else if (*ptr == 'L' && is_float_spec(ptr[1])) {
- type->test = printf_fmt_numtype;
+ break;
+ case 'e': case 'E': case 'f': case 'F': case 'g': case 'G':
+ case 'a': case 'A':
+ type->test = printf_fmt_numtype;
+ switch (szmod) {
+ case LEN_none:
+ type->type = &double_ctype;
+ break;
+ case LEN_L:
type->type = &ldouble_ctype;
- ptr += 2;
- } else if (is_float_spec(*ptr)) {
- type->test = printf_fmt_numtype;
- type->type = szmod == 1 ? &ldouble_ctype : &double_ctype;
- ptr++;
- } else if (*ptr == 's') {
- type->test = printf_fmt_string;
+ break;
+ default:
+ break;
+ }
+ break;
+ case 'c':
+ type->test = printf_fmt_numtype;
+ switch (szmod) {
+ case LEN_none:
+ type->type = &int_ctype;
+ break;
+ case LEN_L:
+ case LEN_l:
+ type->type = wint_ctype;
+ break;
+ default:
+ break;
+ }
+ break;
+ case 's':
+ type->test = printf_fmt_string;
+ switch (szmod) {
+ case LEN_none:
+ type->type = &const_string_ctype;
+ break;
+ case LEN_L:
+ case LEN_l:
type->type = &const_wstring_ctype;
+ break;
+ default:
+ break;
+ }
+ break;
+ case 'p':
+ type->test = printf_fmt_print_pointer;
+ /* check for pointer being printed as hex explicitly */
+ if (*ptr == 'x' || *ptr == 'X') {
ptr++;
- } else if (*ptr == 'n') { /* pointer to an de-referenced int/etc */
- // todo - we should construct pointer to int/etc //
- // also should not have any flags or widths for this
- type->test = printf_fmt_pointer;
+ } else if (isalpha(*ptr)) {
+ /* probably some extra specifiers after %p */
ptr++;
- } else {
- // anything else here?
+ type->test = printf_fmt_pointer;
}
+ break;
+ case 'n':
+ /* pointer to an de-referenced int/etc */
+ // todo - we should construct pointer to int/etc //
+ // also should not have any flags or widths for this
+ type->test = printf_fmt_pointer;
+ break;
+ default:
+ // anything else here?
+ break;
}
if (type->test == NULL)
--
2.28.0
next prev parent reply other threads:[~2020-10-14 9:21 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-10-13 23:22 [PATCH 00/13] format-check: add specific type checking Luc Van Oostenryck
2020-10-13 23:22 ` [PATCH 01/13] format-check: void * is not OK for strings, fix the test Luc Van Oostenryck
2020-10-13 23:22 ` Luc Van Oostenryck [this message]
2020-10-13 23:22 ` [PATCH 03/13] format-check: add helper type_class() Luc Van Oostenryck
2020-10-13 23:22 ` [PATCH 04/13] format-check: merge 'fmt_string' & 'string' Luc Van Oostenryck
2020-10-13 23:22 ` [PATCH 05/13] format-check: remove unneeded member: target Luc Van Oostenryck
2020-10-13 23:22 ` [PATCH 06/13] format-check: add a function to check to type of strings Luc Van Oostenryck
2020-10-13 23:22 ` [PATCH 07/13] format-check: add a function to check to type of 'n' arguments Luc Van Oostenryck
2020-10-13 23:22 ` [PATCH 08/13] format-check: add a function to check to type of pointers Luc Van Oostenryck
2020-10-13 23:22 ` [PATCH 09/13] format-check: remove printf_fmt_print_pointer() Luc Van Oostenryck
2020-10-13 23:22 ` [PATCH 10/13] format-check: add a function to check the type of floats Luc Van Oostenryck
2020-10-13 23:22 ` [PATCH 11/13] format-check: add a function to check the type of integers Luc Van Oostenryck
2020-10-13 23:22 ` [PATCH 12/13] format-check: remove wrappers around type checking methods Luc Van Oostenryck
2020-10-13 23:22 ` [PATCH 13/13] format-check: simplify calling of parse_printf_get_fmt() Luc Van Oostenryck
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20201013232231.10349-3-luc.vanoostenryck@gmail.com \
--to=luc.vanoostenryck@gmail.com \
--cc=ben.dooks@codethink.co.uk \
--cc=linux-sparse@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).