[PATCH] _scanf.c: Implement 'm' modifier for 'c' and '[' conversions.

Will Newton will.newton at gmail.com
Tue Oct 23 14:12:09 UTC 2012


Ping?

On Tue, Oct 16, 2012 at 12:00 PM, Will Newton <will.newton at gmail.com> wrote:
> The current code implements the 'm' modifier only for 's'
> conversions and would cause a segfault if it was used for 'c'
> or '[' conversions. This patch extends the code to cover these
> cases too.
>
> Signed-off-by: Will Newton <will.newton at imgtec.com>
> ---
>  libc/stdio/_scanf.c |   51 ++++++++++++++++++++++++++++++++-------------------
>  1 files changed, 32 insertions(+), 19 deletions(-)
>
> diff --git a/libc/stdio/_scanf.c b/libc/stdio/_scanf.c
> index 952853c..c862afb 100644
> --- a/libc/stdio/_scanf.c
> +++ b/libc/stdio/_scanf.c
> @@ -1355,7 +1355,21 @@ int VFSCANF (FILE *__restrict fp, const Wchar
> *__restrict format, va_list arg)
>                                 (psfs.conv_num >= CONV_c)
>  #endif /* __UCLIBC_HAS_WCHAR__ */
>                         {
> +                               /* We might have to handle the allocation ourselves */
> +                               int len;
> +                               unsigned char **ptr;
> +
>                                 b = (psfs.store ? ((unsigned char *) psfs.cur_ptr) : buf);
> +                               /* With 'm', we actually got a pointer to a pointer */
> +                               ptr = (void *)b;
> +
> +                               i = 0;
> +                               if (psfs.flags & FLAG_MALLOC) {
> +                                       len = 0;
> +                                       b = NULL;
> +                               } else
> +                                       len = -1;
> +
>                                 fail = 1;
>
>                                 if (psfs.conv_num == CONV_c) {
> @@ -1363,31 +1377,25 @@ int VFSCANF (FILE *__restrict fp, const Wchar
> *__restrict format, va_list arg)
>                                                 sc.width = 1;
>                                         }
>
> +                                       if (psfs.flags & FLAG_MALLOC)
> +                                               b = malloc(sc.width);
> +
>                                         while (__scan_getc(&sc) >= 0) {
>                                                 zero_conversions = 0;
> -                                               *b = sc.cc;
> -                                               b += psfs.store;
> +                                               b[i] = sc.cc;
> +                                               i += psfs.store;
>                                         }
>                                         __scan_ungetc(&sc);
>                                         if (sc.width > 0) {     /* Failed to read all required. */
>                                                 goto DONE;
>                                         }
> +                                       if (psfs.flags & FLAG_MALLOC)
> +                                               *ptr = b;
>                                         psfs.cnt += psfs.store;
>                                         goto NEXT_FMT;
>                                 }
>
>                                 if (psfs.conv_num == CONV_s) {
> -                                       /* We might have to handle the allocation ourselves */
> -                                       int len;
> -                                       /* With 'm', we actually got a pointer to a pointer */
> -                                       unsigned char **ptr = (void *)b;
> -
> -                                       i = 0;
> -                                       if (psfs.flags & FLAG_MALLOC) {
> -                                               len = 0;
> -                                               b = NULL;
> -                                       } else
> -                                               len = -1;
>
>                                         /* Yes, believe it or not, a %s conversion can store nuls. */
>                                         while ((__scan_getc(&sc) >= 0) && !isspace(sc.cc)) {
> @@ -1403,10 +1411,6 @@ int VFSCANF (FILE *__restrict fp, const Wchar
> *__restrict format, va_list arg)
>                                                 fail = 0;
>                                         }
>
> -                                       if (psfs.flags & FLAG_MALLOC)
> -                                               *ptr = b;
> -                                       /* The code below takes care of terminating NUL */
> -                                       b += i;
>                                 } else {
>  #ifdef __UCLIBC_HAS_WCHAR__
>                                         assert((psfs.conv_num == CONV_LEFTBRACKET) || \
> @@ -1462,8 +1466,14 @@ int VFSCANF (FILE *__restrict fp, const Wchar
> *__restrict format, va_list arg)
>                                                 if (!scanset[sc.cc]) {
>                                                         break;
>                                                 }
> -                                               *b = sc.cc;
> -                                               b += psfs.store;
> +                                               if (i == len) {
> +                                                       /* Pick a size that won't trigger a lot of
> +                                                        * mallocs early on ... */
> +                                                       len += 256;
> +                                                       b = realloc(b, len + 1);
> +                                               }
> +                                               b[i] = sc.cc;
> +                                               i += psfs.store;
>                                                 fail = 0;
>                                         }
>                                 }
> @@ -1473,6 +1483,9 @@ int VFSCANF (FILE *__restrict fp, const Wchar
> *__restrict format, va_list arg)
>                                 if (fail) {     /* nothing stored! */
>                                         goto DONE;
>                                 }
> +                               if (psfs.flags & FLAG_MALLOC)
> +                                       *ptr = b;
> +                               b += i;
>                                 *b = 0;         /* Nul-terminate string. */
>                                 psfs.cnt += psfs.store;
>                                 goto NEXT_FMT;
> --
> 1.7.1


More information about the uClibc mailing list