7

By my understanding, strcmp() (no 'n'), upon seeing a null character in either argument, immediately stops processing and returns a result.
Therefore, if one of the arguments is known with 100% certainty to be null-terminated (e.g. it is a string literal), there is no security benefit whatsoever in using strncmp() (with 'n') with a call to strlen() as part of the third argument to limit the comparison to the known string length, because strcmp() will already never read more characters than are in that known-terminating string.

In fact, it seems to me that a call to strncmp() whose length argument is a strlen() on one of the first two arguments is only different from the strcmp() case in that it wastes time linear in the size of the known-terminating string by evaluating the strlen() expression.

Consider:

Sample code A:

if (strcmp(user_input, "status") == 0)
    reply_with_status();

Sample code B:

if (strncmp(user_input, "status", strlen("status")+1) == 0)
    reply_with_status();

Is there any benefit to the former over the latter? Because I see it in other people's code a lot.

Do I have a flawed understanding of how these functions work?

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
cvp
  • 73
  • 1
  • 3

6 Answers6

5

In your particular example, I would say it's detrimental to use strncmp because of:

  • Using strlen does the scan anyway
  • Repetition of the string literal "status"
  • Addition of 1 to make sure that strings are indeed equal

All these add to clutter, and in neither case would you be protected from overflowing user_input if it indeed was shorter than 6 characters and contained the same characters as the test string.

That would be exceptional. If you know that your input string always has more memory than the number of characters in your test strings, then don't worry. Otherwise, you might need to worry, or at least consider it. strncmp is useful for testing stuff inside large buffers.

My preference is for code readability.

paddy
  • 60,864
  • 6
  • 61
  • 103
4

Yes it does. If you use strlen in a strncmp, it will traverse the pointer until it sees a null in the string. That makes it functionally equivalent to strcmp.

Gabe Sechan
  • 90,003
  • 9
  • 87
  • 127
  • i would state the same then +1. when i use strncmp second argument is max size of user_input ( often just sizeof(user_input) when user_input is char []), it is a guardian. – philippe lhardy Mar 07 '13 at 21:41
4

In the particular case you've given, it's indeed useless. However, a slight alteration is more common:

if (strncmp(user_input, "status", strlen("status")) == 0)
    reply_with_status();

This version just checks if user_input starts with "status", so it has different semantics.

caf
  • 233,326
  • 40
  • 323
  • 462
2

Beyond tricks to check if the beginning of a string matches an input, strncmp is only going to be useful when you are not 100% sure that a string is null terminated before the end of its allocated space.

So, if you had a fixed size buffer that you took your user input in with you could use:

strncmp(user_input, "status", sizeof(user_input))

Therefore ensuring that your comparison does not overflow.

However in this case you do have to be careful, since if your user_input wasn't null terminated, then it will really be checking if user_input matches the beginning of status.

A better way might be to say:

if (user_input[sizeof(user_input) - 1] != '\0') {
  // handle it, since it is _not_ equal to your string
  // unless filling the buffer is valid
}
else if (strcmp(user_input, "status")) { ... }
jmh
  • 8,856
  • 1
  • 18
  • 26
0

Now, I agree that this isn't particularly useful use of strncmp(), and I can't see any benefit in this over strcmp().

However, if we change the code by removing the +1 after strlen, then it starts to be useful.

 strncmp(user_input, "status", strlen("status"))

since that compares the first 6 characters of user_input with `"status" - which, at least sometimes is meaningful.

So, if the +1 is there, it becomes a regular strcmp - and it's just a waste of time calculating the length. But without the +1, it's quite a useful comparison (under the right circumstances).

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • Very good point. This is how those "type enough of the command word to distinguish it" input systems are implemented, nón? `if (!strncmp(command, "st", 2)) /* ... */`, assuming you have no other commands which begin with "st". Thanks for your response! – cvp Feb 14 '13 at 22:30
  • Yes, although that tends to be more like this pseudo-code `count = 0; for(i : all_commands) { if (match_cmd(command, i)) { matched = i; count++; } } if (count == 1) execute_command(i); else print("need to type more...");` – Mats Petersson Feb 14 '13 at 22:40
0

strncmp() has limited use. The normal strcmp() will stop if it encounters a NUL on any of the two strings. (and in that case the strings are different) Strncmp() would stop and return zero ("the strings are equal in the first N characters")

One possible use of stncmp() is parsing options, upto the non-signifacant part, eg

if (!strncmp("-st", argv[xx], 3)) {}

, which would return zero for "-string" or "-state" or "-st0", but not for "-sadistic".

wildplasser
  • 43,142
  • 8
  • 66
  • 109