Web lists-archives.com

Re: Integer overflow in functions from scanf() family in MinGW, Cygwin, Borland/Embarcadero C environments (Windows)

On 2017-03-05 12:48, Lukas' Home Page wrote:
> I find out a strange and bad beaviour in functions from scanf() family when
> reading one-byte int variable in MinGW, Cygwin and Borland/Embarcadero C
> environments (on Windows, on Linux this doesn't happen). This bug is
> corelated with MSVCRT library which isn't written in C99 standard (it's
> written in C89 i think).
> So, the point is, when you're reading one byte using scanf() function, AND
> you are using %hhu format specifier, you have Integer Overflow bug in your
> code, because MinGW links to old MSVCRT (C89 version) even if you compile
> with -std=c99 parameter.
> This works, because scanf() in old MSVCRT library doesn't know "h" format
> specifier. BUT! The problem is, that scanf try to interpret format specifier
> anyway, omits unsupported "h" specifier and it's loading full integer ("u")
> to memory (it should omit not supported part of format - whole "%hhu" format
> part, not just only "h"). The C99 specification says on 361 page: "If a
> conversion specification is invalid, the behavior is undefined." - but it is
> UNSUPPORTED PART OF FORMAT (not only single specifier, but whole part).

Dealing safely with anything other than int, double, and width limited strings 
using scanf requires a lot of care, by the implementation and the developer.
Undefined behaviour puts the onus on you as a developer to avoid invoking 
whatever behaviour the implementation defaults to.
I can suggest looking into the inttypes.h SCNu* macros and stdint.h.
Options -Wall and -Wextra should produce format warnings.
Cygwin uses newlib and Mingw may use its own scanf library.
Cygwin provides a Mingw port, so any problems should be reported upstream.

> In exploit (below), compiler doesn't even display warnings (event if you
> compile program with -std=c99 and -Wextra parameters). I compile on Windows
> 7 using that command:
> gcc main.c -o main.exe -Wextra
> #include <stdio.h>
> #include <stdbool.h>
> typedef volatile unsigned char uint8_t;
> int main()
> {
>     bool allowAccess = false; // allowAccess should be always FALSE
>     uint8_t userNumber;
>     char format[] = "%hhu";
>     char buffer[] = "257\n";
>     sscanf(buffer, format, &userNumber);
>     if (allowAccess)
>     {
>         printf("Access granted: secret information - Lech Walesa was a Bolek
> agent\n");
>     }
>     printf("Entered number is: %d\n", userNumber);
>     return 0;
> }

Take care. Thanks, Brian Inglis, Calgary, Alberta, Canada

Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple