Re: [PATCH 3/6] evaluate: check variadic argument types against formatting info

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Apr 03, 2019 at 04:35:49PM +0100, Ben Dooks wrote:
> 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.

...

> diff --git a/evaluate.c b/evaluate.c
> index d9cd41d..d6e8415 100644
> --- a/evaluate.c
> +++ b/evaluate.c
> @@ -2319,6 +2319,420 @@ static struct symbol *evaluate_alignof(struct expression *expr)
>  	return size_t_ctype;
>  }
>  
> +struct format_type;

This line can be removed.

> +struct format_type {
> +	const char	*format;
> +	int		(*test)(struct format_type *fmt, struct expression **expr, struct symbol *ctype, struct symbol **target, const char **typediff);
> +	void		*data;

The only use of this field is for a struct symbol *. Better to change
its type and even rename it to 'type' (and *if* some other data type
will be needed for some extension, a type will most probably also be
needed).

> +static struct format_type *parse_printf_get_fmt(const char *msg, const char **msgout)
> +{
> +	struct format_type *type = &ret;
> +	const char *ptr = msg;
> +	int szmod=0;
> +
> +	type->test = NULL;
> +	*msgout = ptr;
> +
> +	if (*ptr == 's') {
> +		ptr++;
> +		type->test = printf_fmt_string;
> +	} else if (*ptr == 'c') {
> +		ptr++;
> +		type->test = printf_fmt_numtype;
> +		type->data = &char_ctype;
> +	} else if (*ptr == 'p') {
> +		ptr++;
> +		type->test = printf_fmt_print_pointer;
> +		//todo - check if there's anything after these?
> +		if (*ptr == 'x' || *ptr == 'X') {
> +			ptr++;
> +		} else if (isalpha(*ptr)) {
> +			// probably sxomething that /is/ being de-referenced
> +			ptr++;
> +			type->test = printf_fmt_pointer;
> +		}

OK.

> +	} else {
> +		if (*ptr == 'l') {
> +			szmod++;
> +			ptr++;
> +			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
> +				szmod = 1;

This won't be OK on 32-bit (where intmax_t is long long) but
Sparse will need to know about intmax_ctype.
Maybe, for now, just add a comment about it?

> +		if (*ptr == 'x' || *ptr == 'X' || *ptr == 'u' || *ptr == 'o') {
> +			ptr++;
> +			type->test = printf_fmt_numtype;
> +			switch (szmod) {
> +			case -1:
> +				type->data = &ushort_ctype;
> +				break;
> +			case 0:
> +				type->data = &uint_ctype;
> +				break;
> +			case 1:
> +				type->data = &ulong_ctype;
> +				break;
> +			case 2:
> +				type->data = &ullong_ctype;
> +				break;
> +			default:
> +				type->test = NULL;
> +			}
> +		} else if (*ptr == 'i' || *ptr == 'd') {
> +			ptr++;
> +			type->test = printf_fmt_numtype;
> +			switch (szmod) {
> +			case -1:
> +				type->data = &short_ctype;
> +				break;
> +			case 0:
> +				type->data = &int_ctype;
> +				break;
> +			case 1:
> +				type->data = &long_ctype;
> +				break;
> +			case 2:
> +				type->data = &llong_ctype;
> +				break;
> +			default:
> +				type->test = NULL;
> +			}
> +		} else if (*ptr == 'f' || *ptr == 'g' || *ptr == 'F' || *ptr == 'G') {
> +			type->test = printf_fmt_numtype;
> +			type->data = &double_ctype;
> +			ptr++;
> +		} else if (*ptr == 'L') {
> +			type->test = printf_fmt_numtype;
> +			type->data = &ldouble_ctype;

This should be combined with the f/g/F/G just above, since 'L' is a size
specifier.

The remaining looks good but I'll need a bit more time to look closer
at it.

-- Luc



[Index of Archives]     [Newbies FAQ]     [LKML]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Trinity Fuzzer Tool]

  Powered by Linux