tags:

views:

757

answers:

9

We all know the trouble overflows can cause, and this is why strn* exist - and most of the time they make sense. However, I have seen code which uses strncmp to compare commandline parameters like so:

if(... strncmp(argv[i], "--help", 6) == 0

Now, I would have thought that this is unnecessary and perhaps even dangerous (for longer parameters it would be easy to miscount the characters in the literal).

strncmp stops on nulls, and the code already assumes argv[i] is null-terminated. Any string literal is guaranteed to be null-terminated, so why not use strcmp?

Perhaps I'm missing something, but I've seen this a few times and this time it intrigued me enough to ask.

+4  A: 

yes it is perfectly safe and considered standard practice. String literals are guaranteed to be properly null terminated.

Evan Teran
+1  A: 

As far as I know, you're absolutely right--there's no reason to use strncmp instead of strcmp. Perhaps people are just being overcautious (not necessarily a bad thing).

MattK
A: 

Yes, the presence of literal limits the size of compared data to the size of the literal. stncmp is redundant here.

Some may say that strncmp is a good habit to get into, but this is outweighted by the trouble of counting chars.

Arkadiy
+1  A: 

I would probably write something like this in C(if I was using strncmp a lot & didn't want to do character counting):

if(... strncmp(argv[i], "--help", sizeof("--help") - 1) == 0
Paul Nathan
but that iterates the string twice unnecessarily. At least use (sizeof("--help") - 1). And yes, sizeof works correctly on string literals since their size is known at compile time.
Evan Teran
Also, no, strlen does not count the null.
Evan Teran
I wasn't sure about sizeof against string literals. In general, I'd suggest C++ and std::string. :-)
Paul Nathan
A: 

It's probably not done for safety. It could have been done to check only the start of command line parameter. Many programs just check the beginning of the command line switches and ignore the rest.

Mehrdad Afshari
+3  A: 

You're right.

Moreover, the example you provided would match "--help" but also everything that begins with "--help" (like "--help-me").

A rare case in which overzealous == wrong.

rjack
+5  A: 

Are you sure that the code is not intended to match on "--helpmedosoemthingwithareallylongoptionname"?

MSN

MSN
This seems like a distinct possibility.
Andrew Medico
that's a very good point. I don't *think* so in this case since all commandline args are done this way
Draemon
+1  A: 

As others have said, strcmp() is perfectly safe to use with literals. If you want to use strncmp(), try this:

strncmp(argv[i], "--help", sizeof("--help"))

Let the compiler do the counting for you!

This will only match the exact string "--help". If you want to match all strings which begin with "--help" (as your code does), use sizeof() - 1 to not include the last '\0'.

Christoph
you mean sizeof("--help") - 1, since sizeof will include the null terminator.
Evan Teran
@Evan: depends on what you want to do - already edited my answer ;)
Christoph
A: 

er... technically couldn't something like this happen?

char *cp1 = "help";
cp1[4] = '!'; // BAD PRACTICE! don't try to mutate a string constant!
// Especially if you remove the terminating null!
  ...
strcmp(some_variable, "help"); 
// if compiler is "smart" enough to use the same memory to implement
// both instances of "help", you are screwed...

I guess this is a pathological case and/or garbage-in, garbage out ("Doc, it hurts when I whack my head against the wall!" "Then don't do it!")...

(p.s. I'm just raising the issue -- if you feel this post muddies the waters, comment appropriately & I'll delete it)

Jason S
Since the string modification is forbidden, I don't think you can say that other code is wrong because it is affected by it. It's like saying there's an error in one program because it can be executed by exploiting a buffer overflow in another.
Draemon
If the two strings were stored in the same place, then the modification affects both strings, and the comparison will still be equal - or you get a core dump. Of course, the behaviour is undefined; anything is possible - Google for 'nasal demons' if you like.
Jonathan Leffler