473,387 Members | 1,585 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

this calls and checks strtol() correctly?

Does this part of C code call and check strtol() correctly?

port = strtol(argv[2], &endptr, 10);
if (argv[2] == endptr){
fprintf(stderr, "%s\n", "Invalid port number form");
return 1;
}
if (port == 0 && errno == EINVAL){
perror("strtol()");
return 1;
}
if ((port == LONG_MAX || port == LONG_MIN) && errno == ERANGE){
perror("strtol()");
return 1;
}

Thank you for your time
Jun 29 '08 #1
8 3258
lovecreatesbea...@gmail.com wrote:
Does this part of C code call and check strtol() correctly?
Reset errno before calling strtol().

errno = 0;
port = strtol(argv[2], &endptr, 10);
if (argv[2] == endptr){
fprintf(stderr, "%s\n", "Invalid port number form");
return 1;
}
if (port == 0 && errno == EINVAL){
perror("strtol()");
return 1;
}
if ((port == LONG_MAX || port == LONG_MIN) && errno == ERANGE){
perror("strtol()");
return 1;
}

Thank you for your time
You might want to add a test for *endptr != '\0'
If argv[2] contains "443foo", *endptr will be 'f' after the strtol()
call (and port will be 433)
Jun 29 '08 #2
On Sun, 29 Jun 2008 01:34:53 -0700, lovecreatesbea...@gmail.com wrote:
Does this part of C code call and check strtol() correctly?
Probably not.
port = strtol(argv[2], &endptr, 10);
strtol won't set errno to 0 if there's no error. You need to do that
yourself before calling it. I'll pretend you did set it to 0 when for the
rest.
if (argv[2] == endptr){
endptr == argv[2] only argv[2] doesn't start with a number. If it does,
for example if argv[2] is "10xab", then endptr will point to the 'x'. You
probably don't want to consider that a valid number.
fprintf(stderr, "%s\n", "Invalid port number form");
return 1;
}
if (port == 0 && errno == EINVAL){
The check may fail to compile on systems that don't define EINVAL, and on
those that do, the block will never be entered.
perror("strtol()");
return 1;
}
if ((port == LONG_MAX || port == LONG_MIN) && errno == ERANGE){
This is not invalid but you can simplify it to checking if
errno == ERANGE. If it's set to that, you already know that
(port == LONG_MAX || port == LONG_MIN).
perror("strtol()");
return 1;
}

Thank you for your time
Jun 29 '08 #3
lovecreatesbea...@gmail.com wrote:
Does this part of C code call and check strtol() correctly?

port = strtol(argv[2], &endptr, 10);
if (argv[2] == endptr){
fprintf(stderr, "%s\n", "Invalid port number form");
return 1;
}
if (port == 0 && errno == EINVAL){
perror("strtol()");
return 1;
}
if ((port == LONG_MAX || port == LONG_MIN) && errno == ERANGE){
perror("strtol()");
return 1;
}

Thank you for your time

Not tested yet, but here is a function I wrote a couple of days ago, to
do the same:

/**
\fn int xatoi(const char *str)
safe atoi() replacement

\remark exit on failure
*/
extern int xatoi(const char *str)
{
long l;
char *endptr;

assert(str != NULL);

errno = 0;
l = strtol(str, &endptr, 10);

/* handle EINVAL and ERANGE */
if (errno) {
fprintf(stderr,
"Error: conversion of '%s' to type int failed,
%s\n",
str,
strerror(errno));
exit(EXIT_FAILURE);
}
/* Not a number? */
if (endptr == str) {
fprintf(stderr,
"Error: conversion of '%s' failed, not a
number\n", str);
exit(EXIT_FAILURE);
}
/* require next char after number to be in [ \0\n\t\r] */
assert(*endptr == '\0' || *endptr == ' ' || *endptr == '\n' ||
*endptr == '\r' || *endptr == '\t' );

/* check for over- and underflow */
assert(l <= INT_MAX);
assert(l >= INT_MIN);

return (int) l;
}

--
Tor <bw****@wvtqvm.vw | tr i-za-h a-z>
Jun 29 '08 #4
On Sun, 29 Jun 2008 01:51:34 -0700 (PDT), ba******@gmail.com wrote:
>You might want to add a test for *endptr != '\0'
If argv[2] contains "443foo", *endptr will be 'f' after the strtol()
call (and port will be 433)
In general (not for argv[2]) you may want to accept trailing
whitespace, e.g. because strtol accepts leading whitespace.
--
Roland Pibinger
"The best software is simple, elegant, and full of drama" - Grady Booch
Jun 29 '08 #5
On Jun 29, 5:01 pm, Harald van D?k <true...@gmail.comwrote:
On Sun, 29 Jun 2008 01:34:53 -0700, lovecreatesbea...@gmail.com wrote:
Does this part of C code call and check strtol() correctly?

Probably not.
port = strtol(argv[2], &endptr, 10);

strtol won't set errno to 0 if there's no error. You need to do that
yourself before calling it. I'll pretend you did set it to 0 when for the
rest.
if (argv[2] == endptr){

endptr == argv[2] only argv[2] doesn't start with a number. If it does,
for example if argv[2] is "10xab", then endptr will point to the 'x'. You
probably don't want to consider that a valid number.
fprintf(stderr, "%s\n", "Invalid port number form");
return 1;
}
if (port == 0 && errno == EINVAL){

The check may fail to compile on systems that don't define EINVAL, and on
those that do, the block will never be entered.
perror("strtol()");
return 1;
}
if ((port == LONG_MAX || port == LONG_MIN) && errno == ERANGE){

This is not invalid but you can simplify it to checking if
errno == ERANGE. If it's set to that, you already know that
(port == LONG_MAX || port == LONG_MIN).
perror("strtol()");
return 1;
}
Thank you. I come up with this new one.

errno = 0;
port = strtol(argv[2], &endptr, 10);
if (errno == ERANGE){
perror("strtol() bbb");
return 1;
}
if (endptr == argv[2]){
fprintf(stderr, "%s\n", "Invalid form");
return 1;
}
if (*endptr != '\0'){
while (endptr != argv[2] + strlen(argv[2])){
if (!isspace(*endptr++)){
fprintf(stderr, "%s\n", "Invalid
form");
return 1;
}
}
}
Jun 29 '08 #6
On Jun 29, 7:39*pm, rpbg...@yahoo.com (Roland Pibinger) wrote:
On Sun, 29 Jun 2008 01:51:34 -0700 (PDT), badc0...@gmail.com wrote:
You might want to add a test for *endptr != '\0'
If argv[2] contains "443foo", *endptr will be 'f' after the strtol()
call (and port will be 433)

In general (not for argv[2]) you may want to accept trailing
whitespace, e.g. because strtol accepts leading whitespace.
Only " 443 " is considered valid in the code in my last post, while
both "443foo" and "443 foo" are invalid.
Jun 29 '08 #7
On Sun, 29 Jun 2008 07:50:17 -0700 (PDT),
"lovecreatesbea...@gmail.com" <lo***************@gmail.comwrote:

snip
>Thank you. I come up with this new one.

errno = 0;
port = strtol(argv[2], &endptr, 10);
port must be at least as large as a long. If it is an int or shorter,
you could still have undefined behavior depending on the value of
argv[2].
if (errno == ERANGE){
perror("strtol() bbb");
return 1;
}
if (endptr == argv[2]){
fprintf(stderr, "%s\n", "Invalid form");
return 1;
}
if (*endptr != '\0'){
You don't really need this if statement. Should *endptr equal
'\0', then endptr must equal argv[2]+strlen(argv[2]). In this case,
the following while statement will evaluate to false and the loop will
not be entered.
while (endptr != argv[2] + strlen(argv[2])){
if (!isspace(*endptr++)){
fprintf(stderr, "%s\n", "Invalid
form");
return 1;
}
}
}

Remove del for email
Jun 29 '08 #8
On Jun 30, 6:01 am, Barry Schwarz <schwa...@dqel.comwrote:
On Sun, 29 Jun 2008 07:50:17 -0700 (PDT),

"lovecreatesbea...@gmail.com" <lovecreatesbea...@gmail.comwrote:
errno = 0;
port = strtol(argv[2], &endptr, 10);

port must be at least as large as a long. If it is an int or shorter,
you could still have undefined behavior depending on the value of
argv[2].
Yes, it's defined as the type of the return type of strtol().
if (errno == ERANGE){
perror("strtol() bbb");
return 1;
}
if (endptr == argv[2]){
fprintf(stderr, "%s\n", "Invalid form");
return 1;
}
if (*endptr != '\0'){

You don't really need this if statement. Should *endptr equal
'\0', then endptr must equal argv[2]+strlen(argv[2]). In this case,
the following while statement will evaluate to false and the loop will
not be entered.
while (endptr != argv[2] + strlen(argv[2])){
if (!isspace(*endptr++)){
fprintf(stderr, "%s\n", "Invalid
form");
return 1;
}
}
}
Thank you.

I made it have more indent with that outer if statement. Removing it
seems better.
Jun 30 '08 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
by: Amadeus W.M. | last post by:
Does strtol raise any exceptions? Thanks!
13
by: Matthias Kluwe | last post by:
Hi! In C, my everyday usage of strtol looked like using char *end; strtol( text, &end, 10 ); to read an int/long and then checking end == ( text + strlen( text ) );
5
by: William Payne | last post by:
Hello, I am in the process of converting a C++ program to a C program. The user of the program is supposed to supply an integer on the command line and in the C++ version of the program I was using...
11
by: nrk | last post by:
Isn't: char s = "--4"; char *endptr; strtol(s, &endptr, 0); supposed to return 0 and set endptr to s? I have run into an implementation (not gcc, gcc does what I expect) that is returning...
16
by: David Scarlett | last post by:
Another two questions... Is behaviour defined when the first argument of strtol is NULL? And if the string contains only digits, is the 2nd argument (assuming it wasn't NULL) guaranteed to be...
3
by: whisper | last post by:
Hello: I am trying to write code to read in a bunch of lines from stdin, each containing a (variable) number of integers and writing each integer in a separate line to stdout. I came up the...
11
by: Bore Biko | last post by:
Dear, I have function that transform time from secconds to string formated as dd:hh:mm:ss (days:hours:minutes:seconds), but it doesent work correctly... Here s code compiled with gcc it goes...
6
by: Nicola Mezzetti | last post by:
Greetings, I write to ask information about how to disable the preprocessor checks on macros when compiling with command line Borland C++ compiler. Waiting for a reply, i thank you all for the...
12
by: Somebody | last post by:
Hi, I'm trying to write the function below and have it working, but I benchmarked it against strcmp() and its much slower. My test is to compare 2 strings that are identitical 100,000,000 times....
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.