Thomson
Thomson

Reputation: 21694

Advantages of strncmp over strcmp?

Seems strncmp is usually recommended than strcmp, what are the advantages? I think it could be related to security. If this is the case, is it still applicable if one of the input string is known to be literal constant, like "LiteralString"?

UPDATE: I mean under the same user scenario where whole strings need to be compared, and strncmp can be used as below. I am wondering it makes sense or not.

strncmp(inputString, "LiternalString", strlen("LiternalString"));

Upvotes: 20

Views: 39214

Answers (8)

Surajeet Bharati
Surajeet Bharati

Reputation: 1433

The problem with strcmp is that sometimes, if by mistake, arguments that are passed are not valid C-strings (meaning that p1 or p2 is not terminated with a null character i.e. not NULL-terminated String), then, strcmp continues comparing until it reaches non-accessible memory and crashes or sometimes results to an unexpected behaviour.

Using strncmp you can limit the search, so that it doesn't reach non-accessible memory.

But, from that, it should not be concluded that strcmp is insecure to use. Both the functions work well in the way they are intended to work. Programmer should read man page for that function before using it and must be sincere enough while passing parameters to such library functions.

You can also read THIS which contains an almost similar question.

Upvotes: 28

chux
chux

Reputation: 154228

... under the same user scenario where whole strings need to be compared, ...

 strncmp(inputString, "LiternalString", strlen("LiternalString"));

Consider the case where string inputString is longer than the string literal.

const char *inputString = "LiternalString_XYZ";
int cmp = strncmp(inputString, "LiternalString", strlen("LiternalString"));
printf("%d\n", cmp); // prints 0.

But OP wanted whole strings compared.

const char *inputString = "LiternalString_XYZ";
int cmp = strcmp(inputString, "LiternalString");
printf("%d\n", cmp); // prints non-zero.

Conclusion to OP's direct question

I am wondering it makes sense or not.

No. To compare whole strings, strncmp() fails to consistently provide the correct result. Use strcmp().


Further

strncmp(s1,s2,n) can limit the search, so that it doesn't reach non-accessible memory if n was properly computed - which was not done in OP's code and problematic to do right when the best n is different for s1 and s2.

The size limit n applies to both s1 and s2 thus making this function useful for comparing prefixes, but not `"safer".

In OP's case, there is no reason to limit the search due to "safety" on account of the string length of the string literal as string literals always contains a terminating null character.

If anything, n should have been based on some property of inputString.

Code like strncmp(s1, string_literal, strlen(s1)) is functionally incorrect as the compare misses the null character. A wee bit better is strncmp(s1, string_literal, strlen(s1)+1), but that is functionally the same as the simpler strcmp(s1, string_literal) with no reduction in "safety".


The below offer some improve "safety" in case foo() did not properly form strings, but can provide the wrong answer if N != M as above.

char s1[N];
foo(s1); // populate s1 somehow
int cmp = strncmp(s1, string_literal, sizeof s1);

char s1[N];
char s2[M];
foo(s1); // populate s1 somehow
foo(s2); // populate s2 somehow
int cmp = strncmp(s1, s2, min(sizeof s1, sizeof s2));

Yet in those cases, the problem is in foo(), not here.
For me, if foo() was so questionable, I'd use the following

s1[sizeof s1 - 1] = '\0';
s2[sizeof s2 - 1] = '\0';
int cmp = strcmp(s1, s2);

or detect that foo() did not form a string.

char s1[N];
foo(s1);
if (memchr(s1, '\0', sizeof s1) == NULL) Oops();

Moral of the story: strncmp() is not a "safer" version of strcmp(). It is a tool for a different job: comparing string prefixes.

Upvotes: 7

user9455050
user9455050

Reputation: 11

int ret1, ret2;
char dev1[]  = { "ABC" };
char dev2[4] = { "ABC" };

dev2[3] = 'D';
ret1 = strncmp(dev1,dev2,strlen(dev1));  // # of characters
ret2 = strncmp(dev1,dev2,sizeof(dev1));  // # of characters plus '\0'

assume: dev1 is null terminated and dev2 is probably not. ret1 = 0 (false positive result), rather than ret2=-1 (valid result)

fazit: strncmp is not just a safer way for strcmp. depends on how you make use of it.

i´d use strcmp on strings, and strncmp on substring search.

Upvotes: 1

user3099889
user3099889

Reputation: 11

Just post an anti-strncmp use case here. Think about the following code.

#include <stdio.h>
#include <dirent.h>

int main()
{
    //I want to list all files under current folder, include hidden files.
    DIR *dir;
    struct dirent *dp;
    char * file_name;
    dir = opendir(".");
    while ((dp=readdir(dir)) != NULL) {
        printf("debug: %s\n", dp->d_name);
        if ( !strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..") )
        //It doesn't work if you replace strcmp with strncmp here.
        //if ( !strncmp(dp->d_name, ".", 1) || !strncmp(dp->d_name, "..", 2) )  
        {
        } else {
            file_name = dp->d_name;
            printf("file_name: \"%s\"\n",file_name);
        }
    }
    closedir(dir);
    return 0;
}

Upvotes: 1

R.. GitHub STOP HELPING ICE
R.. GitHub STOP HELPING ICE

Reputation: 215557

strncmp does not have "advantages over strcmp"; rather they solve different problems. strcmp is for determining if two strings are equal (and if not, possibly how to order/sort them with respect to each other). strncmp is (mainly) for determining whether a string begins with a particular prefix. For example:

if (strncmp(str, "--option=", 9)==0)

will determine if str begins with "--option=". This cannot be achieved by strcmp without either modifying the string to be checked (which may not be a valid operation) or making a useless copy of it. It also cannot be achieved with memcmp unless you already know str points to an object at least 9 bytes in length; otherwise the call to memcmp would have undefined behavior.

There are other usage cases for strncmp too, such as working with non-C-string data.

Upvotes: 21

nishant naveen
nishant naveen

Reputation: 1

I could see only one advantage, that strncmp will take slightly less time to execute than strcmp as we will always compare prefix of string to comapre rather than entire string.

I don't think that there is any security aspect involved in strcmp and strncmp algorithm. They are same except that in strncmp only first 'n' characters are compared.

Upvotes: -3

M.L.
M.L.

Reputation: 738

strcmp could lead to storage volation and segmentation fault in case where one of arguments is not null-terminated string. Take a look why you should use strncpy instead of strcpy. Consequences are unlikely to happen in strcmp, but issue is the same. strnxxx function family try to prevent reading/writing not acquired memory.

Disadvantage of using strn is extra compare and decrement operation on counter.

In few words: strncmp is safer then strcmp, but it is slower too.

Upvotes: -2

Some programmer dude
Some programmer dude

Reputation: 409442

It all depends on your use-cases. Use strncmp if you only need to compare a fixed number of characters, use strcmp if you need to compare a whole string.

That's about it.

Upvotes: 10

Related Questions