1

It may sound like an XY Problem but I am confused.

I want to execute some code when the user enters 6. First have a look at code:

#include<stdio.h>

int main(void) {

     short int x;
     printf("Val :");
     scanf("%d", &x);
     if (x == 6) {
          //some code
     }

     return 0;
}

SHRT_MAX in my system is 32767 and if the user manages to enter 65442 this will be converted to 6 ultimately and the code will be executed at this value while it was supposed to execute at 6. Well, it is getting executed at 6 but from the user's point of view it is the lack of security. Yeah, I can use int or long int, but if the user is cracking short int, it is not the right choice. How can I deal with this issue?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • 4
    If you're going to read a `short int` with `scanf`, you need `%hd`. – Steve Summit May 28 '23 at 13:21
  • 2
    But if you want guaranteed behavior if the user types a value bigger than the target type can hold, you need to use something other than `scanf`. Regardless of whether the target type is `short`, `int`, `long`, or `long long`, if the user types a too-big value, there's no guaranteed behavior. (In fact I'm pretty sure it's downright undefined.) – Steve Summit May 28 '23 at 13:23
  • 2
    @SteveSummit *I'm pretty sure it's downright undefined* [It **is** undefined behavior](https://port70.net/~nsz/c/c11/n1570.html#7.21.6.2p10): "... if the result of the conversion cannot be represented in the object, the behavior is undefined." **Never** use any of the `*scanf()` functions to parse numeric data. There's no way to to use any of those functions without risking undefined behavior on an out-of-range value. – Andrew Henle May 28 '23 at 13:55
  • @AndrewHenle: That is excessive. For example, if the number of digits has been checked and is known to be within a sufficient limit, `sscanf` can be relied upon. Say a string has been matched to a date format, then `sscanf` can be used to parse the various numbers in it. – Eric Postpischil May 28 '23 at 14:17
  • @EricPostpischil *That is excessive* Really? *For example, if the number of digits has been checked and is known to be within a sufficient limit* So you pretty much have to convert and verify the input data before you can use any of the `*scanf()` functions? What's the point of using `*scanf()` when you can use one of the `strto*()` functions and both validate and convert - safely - a numeric string in one step? – Andrew Henle May 28 '23 at 14:55
  • @AndrewHenle: No, you do not have to convert it. First you check that its format conforms to some pattern, then you convert it. The latter may be done using `sscanf`. The `strto*` functions cannot check that a string is in a specific format such as `YYYY-MM-DD`, for example. – Eric Postpischil May 28 '23 at 14:59
  • 1
    @EricPostpischil Probably 5-10% of the C questions here arise from one of the `*scanf()` functions. What happens when your just-out-of-college self-styled "l33t" coder gets the ticket to change that format, and three weeks after delivery to production, one of your biggest customers calls up all irate because he just had a livestock trailer unleash 100 full-grown pigs onto his factory floor *and* his account was directly debited for rush delivery of said pigs and you find out your ordering system messed up a rush order for 100 tons of pig iron because your noob screwed up the `scanf()` format? – Andrew Henle May 28 '23 at 15:07
  • 2
    See also [A Beginner's Guide Away From `scanf()`](http://sekrit.de/webdocs/c/beginners-guide-away-from-scanf.html) and [How to read/parse input in C — The FAQ](https://stackoverflow.com/q/35178520/15168). – Jonathan Leffler May 28 '23 at 18:00
  • 1
    @AndrewHenle You don't need `scanf` to introduce confusion between pigs and pig iron; it's been an [issue in folk music](https://en.wikipedia.org/wiki/Rock_Island_Line) since well before `scanf` even existed... – Steve Summit May 28 '23 at 18:03
  • Using `short int` in 2023 is a bit backwards. If you want a particular size, may as well ask, like [`int16_t`](https://en.cppreference.com/w/c/types/integer). – tadman May 28 '23 at 21:54
  • @AndrewHenle: Teaching “rules for dummies” to allow people to code without well understanding the programming language or libraries they are using is not a remedy for bad engineering or bugs, nor does it justify making false statements. As an objective matter of fact, the sentence “There's no way to to use any of those functions without risking undefined behavior on an out-of-range value” is false. Teaching people false statements is not ethical, even if the motive is to do it for their own good or the good of some hypothetical farmer. Teach the hazards truthfully. – Eric Postpischil May 29 '23 at 02:22
  • @EricPostpischil *Teaching “rules for dummies” to allow people to code without well understanding the programming language or libraries they are using is not a remedy for bad engineering or bugs* How long have you been working in environments where things have to work? You don't seem to understand that developers who get hired to work on code like that come from the same pool of people who write the plethora of `*scanf()` questions here. Avoiding code like `*scanf()` that is bug-prone is a helluva lot more important than showing off you much you know about obscure, bug-prone corner cases. – Andrew Henle May 29 '23 at 10:39
  • @AndrewHenle: You have no business commenting on what I do or do not understanding. Refrain from making *ad hominem* comments. – Eric Postpischil May 29 '23 at 12:44

1 Answers1

7

Re: SHRT_MAX in my system is 32767 and if user manages to enter 65442 this will be converted to 6

From C11 7.21.6.2 The fscanf() function /10:

If this object does not have an appropriate type, or if the result of the conversion cannot be represented in the object, the behavior is undefined.

I suggest reading a whole line fgets() and parsing it with strtol(). scanf() is not suitable for this.

This might help: Correct usage of strtol().


Sidenote: The %d format specifier expects an int *, not a short int *. Change it to %hd.

Harith
  • 4,663
  • 1
  • 5
  • 20
  • Even if I parse it to `long` using parsing function it may react the same way for overflow numbers. So should I use string comparing method to get the job done or some idea with numerical data ? i mean using premitive data types of number values ? – Mildred Gallagher Jun 02 '23 at 11:44
  • Well this also may be because I am too poor in parsing jobs or else. – Mildred Gallagher Jun 02 '23 at 11:44