|
| 1 | +From c0e9ddf59e73e21afe15fca4e94cf7b4b7359bf2 Mon Sep 17 00:00:00 2001 |
| 2 | +Message-ID: <c0e9ddf59e73e21afe15fca4e94cf7b4b7359bf2.1755776786.git.aboya@igalia.com> |
| 3 | +From: Andreas Schwab <schwab@suse.de> |
| 4 | +Date: Thu, 1 Oct 2020 13:59:13 +0200 |
| 5 | +Subject: [PATCH] __vfscanf_internal: fix aliasing violation (bug 26690) |
| 6 | + |
| 7 | +As noted in <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97264>, the cast |
| 8 | +in the call to the read_int function is an aliasing violation. Change the |
| 9 | +type of local variable f to a pointer to unsigned, which allows to |
| 10 | +eliminate most casts while only adding three new ones. |
| 11 | +--- |
| 12 | + stdio-common/vfscanf-internal.c | 22 +++++++++++----------- |
| 13 | + 1 file changed, 11 insertions(+), 11 deletions(-) |
| 14 | + |
| 15 | +diff --git a/stdio-common/vfscanf-internal.c b/stdio-common/vfscanf-internal.c |
| 16 | +index 95b46dcbeb..3a323547f9 100644 |
| 17 | +--- a/stdio-common/vfscanf-internal.c |
| 18 | ++++ b/stdio-common/vfscanf-internal.c |
| 19 | +@@ -277,7 +277,7 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr, |
| 20 | + #endif |
| 21 | + { |
| 22 | + va_list arg; |
| 23 | +- const CHAR_T *f = format; |
| 24 | ++ const UCHAR_T *f = (const UCHAR_T *) format; |
| 25 | + UCHAR_T fc; /* Current character of the format. */ |
| 26 | + WINT_T done = 0; /* Assignments done. */ |
| 27 | + size_t read_in = 0; /* Chars read in. */ |
| 28 | +@@ -415,10 +415,11 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr, |
| 29 | + #endif |
| 30 | + |
| 31 | + #ifndef COMPILE_WSCANF |
| 32 | +- if (!isascii ((unsigned char) *f)) |
| 33 | ++ if (!isascii (*f)) |
| 34 | + { |
| 35 | + /* Non-ASCII, may be a multibyte. */ |
| 36 | +- int len = __mbrlen (f, strlen (f), &state); |
| 37 | ++ int len = __mbrlen ((const char *) f, strlen ((const char *) f), |
| 38 | ++ &state); |
| 39 | + if (len > 0) |
| 40 | + { |
| 41 | + do |
| 42 | +@@ -426,7 +427,7 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr, |
| 43 | + c = inchar (); |
| 44 | + if (__glibc_unlikely (c == EOF)) |
| 45 | + input_error (); |
| 46 | +- else if (c != (unsigned char) *f++) |
| 47 | ++ else if (c != *f++) |
| 48 | + { |
| 49 | + ungetc_not_eof (c, s); |
| 50 | + conv_error (); |
| 51 | +@@ -484,9 +485,9 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr, |
| 52 | + char_buffer_rewind (&charbuf); |
| 53 | + |
| 54 | + /* Check for a positional parameter specification. */ |
| 55 | +- if (ISDIGIT ((UCHAR_T) *f)) |
| 56 | ++ if (ISDIGIT (*f)) |
| 57 | + { |
| 58 | +- argpos = read_int ((const UCHAR_T **) &f); |
| 59 | ++ argpos = read_int (&f); |
| 60 | + if (*f == L_('$')) |
| 61 | + ++f; |
| 62 | + else |
| 63 | +@@ -521,8 +522,8 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr, |
| 64 | + |
| 65 | + /* Find the maximum field width. */ |
| 66 | + width = 0; |
| 67 | +- if (ISDIGIT ((UCHAR_T) *f)) |
| 68 | +- width = read_int ((const UCHAR_T **) &f); |
| 69 | ++ if (ISDIGIT (*f)) |
| 70 | ++ width = read_int (&f); |
| 71 | + got_width: |
| 72 | + if (width == 0) |
| 73 | + width = -1; |
| 74 | +@@ -2522,12 +2523,11 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr, |
| 75 | + } |
| 76 | + |
| 77 | + while ((fc = *f++) != '\0' && fc != ']') |
| 78 | +- if (fc == '-' && *f != '\0' && *f != ']' |
| 79 | +- && (unsigned char) f[-2] <= (unsigned char) *f) |
| 80 | ++ if (fc == '-' && *f != '\0' && *f != ']' && f[-2] <= *f) |
| 81 | + { |
| 82 | + /* Add all characters from the one before the '-' |
| 83 | + up to (but not including) the next format char. */ |
| 84 | +- for (fc = (unsigned char) f[-2]; fc < (unsigned char) *f; ++fc) |
| 85 | ++ for (fc = f[-2]; fc < *f; ++fc) |
| 86 | + ((char *)charbuf.scratch.data)[fc] = 1; |
| 87 | + } |
| 88 | + else |
| 89 | +-- |
| 90 | +2.50.1 |
| 91 | + |
0 commit comments