0

I'm trying to range check a user supplied command line parameter in a C++ program and I'm not sure how to do it.

If I enter a number that's higher, it gets converted to a lower number.

What's the preferred method to do the below? Is there a constant that I can reference? And if so, is there a better way to do this range checking?

#include <iostream>
#include <stdlib.h>

using namespace std;

int main(int argc, char** argv)
{
    if (argc < 2) {
        cout << endl << "usage: " << argv[0] << " <port number>" << endl << endl;
        return 1;
    }

    int32_t port = atoi(argv[1]);
    
    if (port < 1 || port > 65535) {
        cout << endl << "port number should be between 1 and 65535" << endl << endl;

        return 1;
    }

    cout << "port: " << port << endl;

    return 0;
}
Gary
  • 909
  • 9
  • 26
  • 1
    [`std::numeric_limits::max()`](https://en.cppreference.com/w/cpp/types/numeric_limits) – Ted Lyngmo Apr 11 '21 at 00:22
  • "_If I enter a number that's higher, it gets converted to a lower number._" - Perhaps - but you will for sure get [undefined behavior](https://en.cppreference.com/w/cpp/language/ub). – Ted Lyngmo Apr 11 '21 at 00:23
  • How do I check for undefined behavior? – Gary Apr 11 '21 at 00:34
  • 1
    You need to give an example of what values are causing you trouble. Your code will work perfectly fine for values up to 2,147,483,647. Numbers larger than that will overflow, and you can't do anything about that. If you want to check for pathological values, then you will need to check the length of the string before converting. – Tim Roberts Apr 11 '21 at 00:35
  • @Gary https://en.wikipedia.org/wiki/Undefined_behavior – Ted Lyngmo Apr 11 '21 at 01:36
  • 1
    Don´t use `std::atoi()`, use something like `std::strtoll()`that actually does proper error checking. – Galik Apr 11 '21 at 01:53
  • [Why shouldn't I use atoi()?](https://stackoverflow.com/q/17710018/995714) – phuclv Apr 11 '21 at 02:31
  • You can't check for undefined behaviour in code because .... ummm .... the behaviour is undefined. That means it can't be tested for. – Peter Apr 11 '21 at 04:51

2 Answers2

1

Clearly, any number more than 5 digits is bogus, and atoi will handle any number less.

#include <iostream>
#include <stdlib.h>

using namespace std;

int main(int argc, char** argv)
{
    if (argc < 2) {
        cout << "Usage: " << argv[0] << " <port number>" << endl;;
        return 1;
    }

    int32_t port = atoi(argv[1]);
    
    if (strlen(argv[1] > 5 || port < 1 || port > 65535) {
        cout << "Port number should be between 1 and 65535" << endl;
        return 1;
    }

    cout << "port: " << port << endl;

    return 0;
}
Tim Roberts
  • 48,973
  • 4
  • 21
  • 30
-1
#include <iostream>
#include <stdlib.h>
#include <cstring>

using namespace std;

int main(int argc, char** argv)
{
    if (argc < 2) {
        cout << endl << "usage: " << argv[0] << " <port number>" << endl << endl;
        return 1;
    }

    int32_t port = 0;

    port = atoi(argv[1]);

    if ( strlen(argv[1]) > 5 || port < 1 || port > 65535 ) {
        cout << endl << "port number should be between 1 and 65535" << endl << endl;

        return 1;
    }

    cout << "port: " << port << endl;

    return 0;
}

This is final program (above) per recommendations by the community; this appears to address all issues; thank you!

Gary
  • 909
  • 9
  • 26
  • 1
    That is, of course, silly. It is impossible for an `int32_t` to hold a number larger than `numeric_limits::max()`. – Tim Roberts Apr 11 '21 at 00:33
  • How would I do proper range checking? – Gary Apr 11 '21 at 00:35
  • You need to DEFINE "proper range checking", because in my mind your original code is doing exactly that. – Tim Roberts Apr 11 '21 at 00:35
  • Okay, sorry... to be more clear, how do I address the situation where a user inputs a number like 99999999999999999999999999999999 that clearly goes beyond any normal bounds. I'd like to prevent this. Now, C++ is converting this number to another value so that port has a value within range (sometimes). – Gary Apr 11 '21 at 00:36
  • Is it really worth the trouble? How much stupidity do you need to defend against. Just tell people "don't do that". However, I'll post an answer below. – Tim Roberts Apr 11 '21 at 00:40
  • You're right, I'm just trying to learn how to do this and this seemed like a good way to express what I'm trying to accomplish. – Gary Apr 11 '21 at 00:41
  • `atoi` doesn't ever throw a c++ exception, so your `try/catch` is pointless. – Mike Vine Apr 11 '21 at 00:45
  • If you want to use a language that catches string to integer conversion overflows as an exception look into the Ada programming language. – Jim Rogers Apr 11 '21 at 00:52