Sender: rich AT phekda DOT freeserve DOT co DOT uk Message-ID: <3DF76AAD.DC2F0E0A@phekda.freeserve.co.uk> Date: Wed, 11 Dec 2002 16:41:17 +0000 From: Richard Dawe X-Mailer: Mozilla 4.77 [en] (X11; U; Linux 2.2.23 i586) X-Accept-Language: de,fr MIME-Version: 1.0 To: djgpp-workers AT delorie DOT com Subject: Re: scanf buffer overflow; support 'hh' conversion specifier [PATCH] References: Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Reply-To: djgpp-workers AT delorie DOT com Hello. Eli Zaretskii wrote: > > Richard Dawe wrote: [snip] > > "The conversion specifiers A, E, F, G, and X are also valid and behave the > > same as, respectively, a, e, f, g, and x." > > > > So we can't treat X as some Borland special-case, if we want to comply > > with the C standard. > > Oh, yes we can: if the result is the same, the users won't notice. > > Do you see any difference between what v2.03 does with X and what C99 > says it should? Yes: 2.03: Ignores the 'h' conversion width specifier and treats it like 'l', but honours 'll'. This causes a buffer overflow (memory corruption) problem when the width is less than 32b short). Note that the problem would also occur if 2.03 supported the 'hh' conversion width specifier for chars. C99: X should behave like x. Should honour conversion width specifiers. The 2.03-behaviour is caused by this code to handle captial type specifiers (D, etc.) from src/libc/ansi/stdio/doscan.c:102-115: /* The following if clause is an extension of ANSI/Posix spec: it allows to use %D, %U, %I etc. to store value in a long (rather than an int) and %lD, %lU etc. to store value in a long long. This extension is supported by some compilers (e.g. Borland C). Old pre-ANSI compilers, such as Turbo C 2.0, also interpreted %E, %F and %G to store in a double (rather than a float), but this contradicts the ANSI Standard, so we don't support it. */ if (ch == 'd' || ch == 'i' || ch == 'o' || ch == 'u' || ch == 'x') { if (size==LONG && ch != 'x') /* ANSI: %lX is long, not long long */ size = LONGDOUBLE; else if (size != LONGDOUBLE) size = LONG; } 2.03 & %hX: size == SHORT => size == LONG after this code -> memory corruption. (Something similar would happen for %hhX, if 2.03 supported it.) Bye, Rich =] -- Richard Dawe [ http://www.phekda.freeserve.co.uk/richdawe/ ]