1

Consider val being a user input. I expect val to be between 0-65535

Instead of checking if val is not withing acceptable range before denying it, I was wondering if

is this :

uint16_t count = atoi(val);

the same as this :

uint16_t count = (uint16_t)atoi(val);

Is this an acceptable way of "securing" the user input? I do not intend to send a feedback to the user, I just want to make sure it won't explode if someone submits -123 or 999999. It does not matter if count equals 2 because someone submitted 65538

Weather Vane
  • 33,872
  • 7
  • 36
  • 56
Musa
  • 1,334
  • 1
  • 11
  • 21
  • 3
    Yes, it's the same. – HolyBlackCat Oct 24 '22 at 19:23
  • @HolyBlackCat -- yes, it's the same, unless you have a busybody compiler that insists on a cast because you might not have been smart enough to understand the first version of the code when you wrote it. – Pete Becker Oct 24 '22 at 19:26
  • 3
    Note: `atoi` returns 0 on failure and 0 exists in your range of acceptable values. You may want to use [`strtoul`](https://en.cppreference.com/w/c/string/byte/strtoul) to get better error checking. – user4581301 Oct 24 '22 at 19:29
  • 1
    @WeatherVane ```val``` is an ascii. I would need to put it inside a ```uint32_t``` to perform meaningful tests. As I said, i do not intend to send user feedbacks. @user4581301 a fallback to zero in case of a failure is perfect in my case. Thank you all! – Musa Oct 24 '22 at 19:32
  • 1
    I deleted the comment after reading that you don't care whether the input value makes sense: only that it does not cause damage. Otherwise check its range *before* converting. – Weather Vane Oct 24 '22 at 19:34
  • *Is this an acceptable way of "securing" the user input?* Totally depends on your definition of secure. No out-of range integer values will be processed, but if some something is consistently inputting garbage that's a sign of an error elsewhere in the system that needs to be investigated. Log it and someone will eventually thank you for the breadcrumb trail. – user4581301 Oct 25 '22 at 15:43
  • [Why shouldn't I use atoi()?](https://stackoverflow.com/q/17710018/995714) – phuclv Oct 25 '22 at 16:04

2 Answers2

1

Is this:

uint16_t count = atoi(val);

The same as this:

uint16_t count = (uint16_t)atoi(val);

They behave exactly the same. For the former, by assigning an int to a uint16_t, it is being implicitly converted anyway.

Since a uint16_t cannot contain any more than 65536 or less than 0, the conversion safely stores the modulus of the int value in the uint16_t variable.

user16217248
  • 3,119
  • 19
  • 19
  • 37
  • 2
    And the behavior is well-defined because unsigned integers perform modular arithmetic during the conversion. – Barmar Oct 24 '22 at 19:40
  • 3
    Conversion to `uint16_t` wraps; it does not clamp. “Clamp” means that any out-of-range values are mapped to the nearer endpoint. E.g., any value less than zero would produces zero, and any value greater than 65,535 would produce 65,535. – Eric Postpischil Oct 24 '22 at 20:45
1

They are almost the same. The C standard’s specifications of how they will behave in execution are the same, and the C standard does not specify any difference between them other than the grammar, but neither does it require implementations to treat them identically in all regards.

For example, a compiler or code analyzer might warn you that uint16_t count = atoi(val); potentially alters a value during assignment while it lets uint16_t count = (uint16_t)atoi(val); pass without warning because a cast is usually taken as an indication that the programmer deliberately wants a conversion.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312