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

Re: [PATCH v2 2/2] libc: Überarbeiten des Überlaufverhalten von scanf



Am 04.03.2021 um 20:48 hat Nico Mayer geschrieben:
> From: Nico Mayer <mayerNico@xxxxxxxxxx>
> 
> ! Die bisherige Implementierung der Scanf-Funktion verwendet für das
>   Einlesen der Zahlen ausschließlich die Funktion strtoull. Hierdurch verhält
>   sich die Scanf-Funktion bei Überläufen bzw. Unterläufen bei verschiedenen
>   Datentypen falsch. Mit diesem Commit wählt jetzt die Scanf-Funktion
>   für den jeweiligen Datentyp die passende strtoxxx-Funktion aus.
> 
> Signed-off-by: Nico Mayer <mayerNico@xxxxxxxxxx>
> ---
>  src/modules/lib/stdlibc/scanf.c | 26 +++++++++++++++++++++++++-
>  1 file changed, 25 insertions(+), 1 deletion(-)
> 
> diff --git a/src/modules/lib/stdlibc/scanf.c b/src/modules/lib/stdlibc/scanf.c
> index 0f978606..6d288e36 100644
> --- a/src/modules/lib/stdlibc/scanf.c
> +++ b/src/modules/lib/stdlibc/scanf.c
> @@ -33,6 +33,7 @@
>  #include <stddef.h>
>  #include <string.h>
>  #include <ctype.h>
> +#include <stdbool.h>
>  
>  typedef int (*jscanf_getc)(void* state);
>  typedef void (*jscanf_ungetc)(void* state, char c);
> @@ -185,6 +186,7 @@ static int jscanf(const char* fmt, va_list ap,
>      int c;
>      char* endptr;
>      uint64_t value;
> +    bool is_unsigned = false;
>  
>      // 64 Bit oktal = 22 Zeichen, führende 0, Vorzeichen und \0
>      char buf[25];
> @@ -282,22 +284,30 @@ static int jscanf(const char* fmt, va_list ap,
>                      // %p - Pointer (strtoul mit Basis 16)
>                      case 'i':
>                          base = 0;
> +                        is_unsigned = false;
>                          goto convert_number;
>                      case 'o':
>                          base = 8;
> +                        is_unsigned = true;
>                          goto convert_number;
>                      case 'x':
>                      case 'X':
>                          base = 16;
> +                        is_unsigned = true;
>                          goto convert_number;
>                      case 'p':
>                          base = 16;
>                          size = sizeof(void*);
>                          len = 0;
> +                        is_unsigned = true;
>                          goto convert_number;
>                      case 'd':
> +                        base = 10;
> +                        is_unsigned = false;
> +                        goto convert_number;
>                      case 'u':
>                          base = 10;
> +                        is_unsigned = true;
>                      convert_number:
>                          if (len == 0 || len >= sizeof(buf)) {
>                              len = sizeof(buf) - 1;
> @@ -305,7 +315,21 @@ static int jscanf(const char* fmt, va_list ap,
>                          len = jscanf_read_number(buf, len, jgetc, jungetc,
>                              state, base, &eof);
>  
> -                        value = strtoull(buf, &endptr, base);
> +                        // Auswählen der richtigen strtoxxx-Funktion
> +                        if (is_unsigned) {
> +                            if (size == sizeof(int)) {
> +                                value = strtoul(buf, &endptr, base);
> +                            } else {
> +                                value = strtoull(buf, &endptr, base);
> +                            }
> +                        } else {
> +                            if (size == sizeof(int)) {
> +                                value = strtol(buf, &endptr, base);
> +                            } else {
> +                                value = strtoll(buf, &endptr, base);
> +                            }
> +                        }

Ok, den Unterschied zwischen signed und unsigned verstehe ich.

Aber den Unterschied zwischen strto(u)l und strto(u)ll nicht: Auf i386
benutzt du strtol() für int und long, aber strtoll() nicht nur für
long long, sondern auch für char und short.

Bist du sicher, dass das die Überläufe richtig macht?

>                          if ((endptr != buf + len) || (len == 0)) {
>                              if ((len == 0) && eof) {
>                                  goto input_error;

Kevin