mbox series

[v4,0/2] lib/string_helpers: Introduce parse_int_array_user()

Message ID 20220902122928.632602-1-cezary.rojewski@intel.com
Headers show
Series lib/string_helpers: Introduce parse_int_array_user() | expand

Message

Cezary Rojewski Sept. 2, 2022, 12:29 p.m. UTC
Continuation of recent upstream discussion [1] regarding user string
tokenization.

First, parse_int_array_user() is introduced to allow for splitting
specified user string into a sequence of integers. Makes use of
get_options() internally so the parsing logic is not duplicated.

With that done, redundant parts of the sound driver are removed.

Originally similar functionality was added for the SOF sound driver. As
more users are on the horizon, it is desirable to update existing
string_helpers code and provide a unified solution.


Changes in v4:
- renamed the function to parse_int_array_user()
- at the name several local variable names have been reworded to match
  the above

Changes in v3:
- relocated tokenize_user_input() implementation to string_helpers as
  requested by Matthew

Changes in v2:
- reused get_options() so no parsing logic is duplicated
- simplified __user variant with help of memdup_user_nul()
  Both suggested by Andy, thanks for thourough review


[1]: https://lore.kernel.org/alsa-devel/20220707091301.1282291-1-cezary.rojewski@intel.com/


Cezary Rojewski (2):
  lib/string_helpers: Introduce parse_int_array_user()
  ASoC: SOF: Remove strsplit_u32() and tokenize_input()

 include/linux/string_helpers.h    |   2 +
 lib/string_helpers.c              |  45 +++++++++++++
 sound/soc/sof/sof-client-probes.c | 104 ++++++------------------------
 3 files changed, 65 insertions(+), 86 deletions(-)

Comments

Amadeusz Sławiński Sept. 2, 2022, 12:23 p.m. UTC | #1
On 9/2/2022 2:29 PM, Cezary Rojewski wrote:
> Add new helper function to allow for splitting specified user string
> into a sequence of integers. Internally it makes use of get_options() so
> the returned sequence contains the integers extracted plus an additional
> element that begins the sequence and specifies the integers count.
> 
> Suggested-by: Andy Shevchenko <andy.shevchenko@gmail.com>
> Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
> Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com>
> ---
>   include/linux/string_helpers.h |  2 ++
>   lib/string_helpers.c           | 45 ++++++++++++++++++++++++++++++++++
>   2 files changed, 47 insertions(+)
> 
> diff --git a/include/linux/string_helpers.h b/include/linux/string_helpers.h
> index 4d72258d42fd..dc2e726fd820 100644
> --- a/include/linux/string_helpers.h
> +++ b/include/linux/string_helpers.h
> @@ -21,6 +21,8 @@ enum string_size_units {
>   void string_get_size(u64 size, u64 blk_size, enum string_size_units units,
>   		     char *buf, int len);
>   
> +int parse_int_array_user(const char __user *from, size_t count, int **array);
> +
>   #define UNESCAPE_SPACE		BIT(0)
>   #define UNESCAPE_OCTAL		BIT(1)
>   #define UNESCAPE_HEX		BIT(2)
> diff --git a/lib/string_helpers.c b/lib/string_helpers.c
> index 5ed3beb066e6..d0c8f6ecf84c 100644
> --- a/lib/string_helpers.c
> +++ b/lib/string_helpers.c
> @@ -131,6 +131,51 @@ void string_get_size(u64 size, u64 blk_size, const enum string_size_units units,
>   }
>   EXPORT_SYMBOL(string_get_size);
>   
> +/**
> + * parse_int_array_user - Split string into a sequence of integers
> + * @from:	The user space buffer to read from
> + * @ppos:	The current position in the buffer

There is no such parameter?

> + * @count:	The maximum number of bytes to read
> + * @tkns:	Returned pointer to sequence of integers

s/tkns/array/ ?

> + *
> + * On success @tkns is allocated and initialized with a sequence of

ditto

> + * integers extracted from the @from plus an additional element that
> + * begins the sequence and specifies the integers count.
> + *
> + * Caller takes responsibility for freeing @tkns when it is no longer

ditto

> + * needed.
> + */
> +int parse_int_array_user(const char __user *from, size_t count, int **array)
> +{
> +	int *ints, nints;
> +	char *buf;
> +	int ret = 0;
> +
> +	buf = memdup_user_nul(from, count);
> +	if (IS_ERR(buf))
> +		return PTR_ERR(buf);
> +
> +	get_options(buf, 0, &nints);
> +	if (!nints) {
> +		ret = -ENOENT;
> +		goto free_buf;
> +	}
> +
> +	ints = kcalloc(nints + 1, sizeof(*ints), GFP_KERNEL);
> +	if (!ints) {
> +		ret = -ENOMEM;
> +		goto free_buf;
> +	}
> +
> +	get_options(buf, nints + 1, ints);
> +	*array = ints;
> +
> +free_buf:
> +	kfree(buf);
> +	return ret;
> +}
> +EXPORT_SYMBOL(parse_int_array_user);
> +
>   static bool unescape_space(char **src, char **dst)
>   {
>   	char *p = *dst, *q = *src;