Does strlen() in a strncmp() expression defeat the purpose of using strncmp() over strcmp()?
Asked Answered
P

6

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?

Pansophy answered 14/2, 2013 at 22:11 Comment(0)
M
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.

Miliaria answered 14/2, 2013 at 22:19 Comment(2)
I'd upvote you, but I don't have enough reputation. :p Thanks for your detailed answer!Pansophy
Some/most compilers can calculate strlen("status") as a constant value. Otherwise, agree.Rossiter
K
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.

Koan answered 14/2, 2013 at 22:13 Comment(1)
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.Dorey
M
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.

Morbific answered 14/2, 2013 at 22:27 Comment(1)
Very good point which I forgot to mention. Thanks for your response!Pansophy
A
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")) { ... }
Ankerite answered 7/3, 2013 at 21:35 Comment(1)
user_input[sizeof(user_input)-1] != '\0', else you are outside user_input array.Dorey
B
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).

Britney answered 14/2, 2013 at 22:27 Comment(2)
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!Pansophy
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...");Britney
P
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".

Peacemaker answered 14/2, 2013 at 22:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.