Search code examples
cscanf

Is `scanf("%d", ...)` as bad as `gets`?


For many years, gets has been universally disparaged as being an unsafe function. (The canonical SO question is Why is the gets function so dangerous that it should not be used?). The gets function is so bad that it has been removed from the C11 language standard. Supporters of gets (there are few if any) would argue that it is perfectly fine to use it if you know about the structure of the input.

Why do people who disparage gets and acknowledge the folly of relying on the structure of the input allow the usage of %d as a scanf conversion specifier? That's a sociological question, and the real question is: why is %d in a scanf format string unsafe?


Solution

  • No, scanf("%d", …) is not as bad as gets.

    gets is as bad as it gets because it is not possible to use it safely, in virtually any environment. Buffer overflow is likely, cannot be prevented, and is quite likely to lead to arbitrarily bad consequences.

    The worst thing that can happen with scanf("%d", …), on the other hand, is integer overflow. While this is theoretically also undefined behavior, in practice it virtually always results in either (a) quiet wraparound, (b) overflow to INT_MAX or INT_MIN, or (c) a runtime exception which may terminate the calling program.

    It is extremely difficult to imagine a scenario under which an attacker could exploit a program using scanf("%d", …). Exploits involving gets, on the other hand, are commonplace.

    (Although not the question asked, it's true that scanf("%s", …) is precisely as dangerous as gets. It's a fair question why the former isn't always disparaged as strenuously as the latter.)