Reputation: 1842
Whilst going through some c++ code as part of a PCI DSS certification review I came across the following:
I have a method in some library we use and one of its parameters is a char *, lets say this is
void foo(char* arg);
The point in the code where it calls this method looked like:
char mystring[256];
strcpy(mystring, "some value");
....
foo(mystring);
as part of the review we are getting rid of any strcpy calls (although in this example it is a bit trivial as the "some value" clearly fits in mystring)
So we get:
char mystring[256];
strncpy(mystring, "some value", sizeof(mystring));
mystring[sizeof(mystring)-1] = '\0';
....
foo(mystring);
This because I thought
foo("some value")
would pass a const char *
To my surprise however, the compiler (gcc 4) is quite happy with this. It doesn't even give any warnings when I add -Wall or -Wcast-qual
My question is this: can I in this case safely call foo("some value") when I don't know what foo is actually doing (if anything) to its argument?
Upvotes: 1
Views: 1543
Reputation: 42805
BTW, you're using strncpy
wrong. The size parameter should be the size of the destination buffer minus one:
char mystring[256];
strncpy(mystring, "some value", 255);
mystring[255] = '\0';
The goal is to keep from overflowing the buffer.
Upvotes: 2
Reputation: 254431
Can I in this case safely call
foo("some value")
when I don't know whatfoo
is actually doing (if anything) to its argument?
No. A string literal is constant, and attempting to modify it gives undefined behaviour.
For historical reasons, there is an obsolete conversion to a non-const char*
which some compilers will allow - although that conversion is no longer valid since C++11. You should not rely on that, and hopefully you can turn up the warning level on your compiler to prevent it.
To my surprise however, the compiler (gcc 4) is quite happy with this.
That is surprising. My GCC 4.6.3 gives a warning by default; I'd need to specify -Wno-write-strings
to silence it.
Upvotes: 9
Reputation: 21763
No, it's not safe if you cannot guarantee foo won't modify the argument. Compilers can implicitly cast a string literal to char *
for backwards compatibility with C code (unfortunately). You will have to copy the literal to a modifiable char buffer and pass that instead.
Upvotes: 11