Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Wed, 24 May 2023 17:42:38 -0400
From: Rich Felker <dalias@...c.org>
To: Jens Gustedt <Jens.Gustedt@...ia.fr>
Cc: musl@...ts.openwall.com
Subject: Re: [C23 new stdlib 3/4] C23: implement the new strfrom[dfl]
 functions

On Wed, May 24, 2023 at 09:38:53PM +0200, Jens Gustedt wrote:
> These names had been reserved in C17, so it is not necessary to hide
> these function in conditionals or to make the symbols weak.
> ---
>  include/stdlib.h      |  4 ++++
>  src/stdlib/strfromd.c | 21 +++++++++++++++++++++
>  2 files changed, 25 insertions(+)
>  create mode 100644 src/stdlib/strfromd.c
> 
> diff --git a/include/stdlib.h b/include/stdlib.h
> index 68993c04..43173e95 100644
> --- a/include/stdlib.h
> +++ b/include/stdlib.h
> @@ -29,6 +29,10 @@ float strtof (const char *__restrict, char **__restrict);
>  double strtod (const char *__restrict, char **__restrict);
>  long double strtold (const char *__restrict, char **__restrict);
>  
> +int strfromd(char *restrict, size_t, const char *restrict, double);
> +int strfromf(char *restrict, size_t, const char *restrict, float);
> +int strfroml(char *restrict, size_t, const char *restrict, long double);
> +
>  long strtol (const char *__restrict, char **__restrict, int);
>  unsigned long strtoul (const char *__restrict, char **__restrict, int);
>  long long strtoll (const char *__restrict, char **__restrict, int);
> diff --git a/src/stdlib/strfromd.c b/src/stdlib/strfromd.c
> new file mode 100644
> index 00000000..c04a1d82
> --- /dev/null
> +++ b/src/stdlib/strfromd.c
> @@ -0,0 +1,21 @@
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <string.h>
> +
> +int strfromd(char *restrict s, size_t n, const char *restrict format, double fp) {
> +	return snprintf(s, n, format, fp);
> +}
> +
> +int strfromf(char *restrict s, size_t n, const char *restrict format, float fp) {
> +	return snprintf(s, n, format, fp);
> +}
> +
> +int strfroml(char *restrict s, size_t n, const char *restrict format, long double fp) {
> +	size_t len = strlen(format);
> +	char ff[len+2];
> +	memcpy(ff, format, len-1);
> +	ff[len-1] = 'L';
> +	ff[len] = format[len-1];
> +	ff[len+1] = 0;
> +	return snprintf(s, n, ff, fp);
> +}
> -- 
> 2.34.1

The temp buffer of unbounded length is kinda a problem here,
especially if they might be used with untrusted input. This is kinda
sketchy to begin with since, AIUI, the "shall only..." language in the
spec makes it UB to pass a format that's not valid, but one could
imagine a program correctly validating formats with a regex like
/%([.][0-9]*)?[aAeEfFgG]/ but not imposing a length limit.

The safe thing to do would probably be stripping leading zeros and
then substituting "9999999999" or something if there are more than 10
digits remaining. For width (not supported here) this would
necessarily cause EOVERFLOW, but for precision, it might not. In any
case, then the entire format fits in a small fixed-length buffer and
has no risk of stack smashing.

Rich

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.