PDA

View Full Version : Strcpy isn't working -- :(




bobber205
Mar 15, 2007, 07:16 PM
This is legal at school in Visual Studio.

if (which >= 1 && which <= numEntries) {
which = which -1;
cout << "New First Name: ";
cin >> temp;
strcpy(firstnames[index[which]], temp);
cout << endl;

cout << "New Last Name: ";
cin >> temp;
strcpy(lastnames[index[which]], temp);
cout << endl;

cout << "New Phone Number: ";
cin >> temp;
strcpy(phonenumbers[index[which]], temp);
cout << endl;

cout << "New Birthday: ";
cin >> temp;
strcpy(birthdays[index[which]], temp);
cout << endl;



}
else cout << "INVALID Number." << endl;



But in Xcode I'm getting a


invalid types 'char (*)[50][char* ()(const char*, int)]' for array subscript


Any ideas why? What function should I use?

What's a good reference for what C++ functions I can and can't use in Xcode's compiler?



MarkCollette
Mar 15, 2007, 07:36 PM
1. Exactly what datatypes are: which, index, firstnames, lastnames, phonenumbers, birthdays?

2. What aren't you using structures or classes, instead of these parallel arrays?

3. Why are you using strcpy(), instead of strncpy()?

4. Why are you (I think) using char arrays, instead of string objects?

bobber205
Mar 15, 2007, 08:00 PM
EDIT:

The index array was not passed to that function.

[SOLVED]

Sorry. :(

colocolo
Mar 15, 2007, 09:52 PM
1. Exactly what datatypes are: which, index, firstnames, lastnames, phonenumbers, birthdays?

2. What aren't you using structures or classes, instead of these parallel arrays?

3. Why are you using strcpy(), instead of strncpy()?

4. Why are you (I think) using char arrays, instead of string objects?

Im guessing he's just just doing some basic data structure course in C at school, so he would be required to learn the basics of arrays first, before moving into structs. Clearly its not Objective-C or C++, so classes are out of the question :)

MarkCollette
Mar 16, 2007, 12:04 AM
Im guessing he's just just doing some basic data structure course in C at school, so he would be required to learn the basics of arrays first, before moving into structs. Clearly its not Objective-C or C++, so classes are out of the question :)

Yeah, you're probably right. Except it is C++, since he's using cin and cout :)

gnasher729
Mar 16, 2007, 08:11 AM
3. Why are you using strcpy(), instead of strncpy()?

Never, ever use strncpy. It doesn't do what you think it does.

When you copy into a buffer that is big enough, both strcpy and strncpy work fine. strcpy is better, because strncpy will _always_ fill the rest of the buffer with zeroes, which is painfully slow if you have a generously nice big buffer. If the buffer is not big enough, strcpy overwrites memory which will crash. strncpy doesn't overwrite memory, but it copies a string without the trailing '\0'. So if you try to use the result, _anything_ can happen. The result is, your program is likely to crash, but not where the bug is. Instead things will go wrong some time later.

darkwing
Mar 16, 2007, 10:00 AM
Never, ever use strncpy. It doesn't do what you think it does.

When you copy into a buffer that is big enough, both strcpy and strncpy work fine. strcpy is better, because strncpy will _always_ fill the rest of the buffer with zeroes, which is painfully slow if you have a generously nice big buffer. If the buffer is not big enough, strcpy overwrites memory which will crash. strncpy doesn't overwrite memory, but it copies a string without the trailing '\0'. So if you try to use the result, _anything_ can happen. The result is, your program is likely to crash, but not where the bug is. Instead things will go wrong some time later.

This is a good point. I do rather wish that strncpy would return a pointer to the terminating \0 like stpcpy() does. It could return NULL if there isn't a terminating \0. I guess they wanted consistency with strcpy().

MarkCollette
Mar 16, 2007, 10:48 AM
Never, ever use strncpy. It doesn't do what you think it does.

When you copy into a buffer that is big enough, both strcpy and strncpy work fine. strcpy is better, because strncpy will _always_ fill the rest of the buffer with zeroes, which is painfully slow if you have a generously nice big buffer. If the buffer is not big enough, strcpy overwrites memory which will crash. strncpy doesn't overwrite memory, but it copies a string without the trailing '\0'. So if you try to use the result, _anything_ can happen. The result is, your program is likely to crash, but not where the bug is. Instead things will go wrong some time later.

I didn't know that strncpy() padded with extra zeros if possible. But I do know that the simply workaround for potentially not adding the zero byte is to simply always have one extra slot at the end, and just put a '\0' in there, forcing termination.

szark
Mar 16, 2007, 11:22 AM
Never, ever use strncpy. It doesn't do what you think it does.

strncpy does exactly what I expect it to - allow me to copy a smaller string into the middle of a larger string without automatically truncating it. :)

Flynnstone
Mar 16, 2007, 03:02 PM
This is legal at school in Visual Studio.

But in Xcode I'm getting a


invalid types 'char (*)[50][char* ()(const char*, int)]' for array subscript



Could this be part of the reason that Windows software seems to be prone to buffer overrun problems?

savar
Mar 16, 2007, 03:23 PM
Never, ever use strncpy. It doesn't do what you think it does.

When you copy into a buffer that is big enough, both strcpy and strncpy work fine. strcpy is better, because strncpy will _always_ fill the rest of the buffer with zeroes, which is painfully slow if you have a generously nice big buffer. If the buffer is not big enough, strcpy overwrites memory which will crash. strncpy doesn't overwrite memory, but it copies a string without the trailing '\0'. So if you try to use the result, _anything_ can happen. The result is, your program is likely to crash, but not where the bug is. Instead things will go wrong some time later.

Strange advice... most security experts would say exactly the opposite. Copying data without doing bounds checking is dangerous, especially if that data was supplied by a user. Your program might not crash; it might smash the stack and then execute harmful shell code.

MarkCollette
Mar 16, 2007, 04:22 PM
Strange advice... most security experts would say exactly the opposite. Copying data without doing bounds checking is dangerous, especially if that data was supplied by a user. Your program might not crash; it might smash the stack and then execute harmful shell code.

I think the piont of that bad advice was that it's better for a situation to fail fast, at development time, then limp on into production.

wittegijt
Mar 16, 2007, 06:41 PM
I think the piont of that bad advice was that it's better for a situation to fail fast, at development time, then limp on into production.

If writing outside a buffer was guaranteed to crash your app, yes. But it is not. Check your bounds and use strncpy:)

Wittegijt.

MarkCollette
Mar 16, 2007, 07:00 PM
If writing outside a buffer was guaranteed to crash your app, yes. But it is not. Check your bounds and use strncpy:)

Wittegijt.

True, but you can typically turn on array bounds checking when developing.

gnasher729
Mar 16, 2007, 07:42 PM
Strange advice... most security experts would say exactly the opposite. Copying data without doing bounds checking is dangerous, especially if that data was supplied by a user. Your program might not crash; it might smash the stack and then execute harmful shell code.

Security experts will tell you that strncpy lulls you into a false sense of security. You think you are secure but you are not. Now in reality you either make sure that the destination buffer is big enough before you call strcpy (in which case strncpy is pointless), or you write a function yourself that will do something sensible, unlike what strncpy does, if there is not enough space.

Lets say dst has space for ten chars. If you just call

strncpy (dst, src, 10);
len = strlen (dst);

strncpy won't overwrite anything, but len can be greater than 10, or the call to strlen can even crash, so strncpy doesn't gain anything. Any use of strncpy in some code makes me very, very worried.

gnasher729
Mar 16, 2007, 07:44 PM
True, but you can typically turn on array bounds checking when developing.

Good idea. What compiler switch do I use for that in XCode?

gnasher729
Mar 16, 2007, 08:15 PM
I think the piont of that bad advice was that it's better for a situation to fail fast, at development time, then limp on into production.

It can be worse.

Say you have a struct

typedef struct { char c [12]; int n; } mystruct;

and call strncpy (c, "this is a very very long string", 12);

On a PowerPC, the next byte in memory following the array c is the most significant byte of n. As long as 0 <= n <= 16000000 or so, the most significant byte of n is a zero, so there is a zero byte following the array c and c will behave as if it contained a valid string of 12 characters plus a trailing zero.

Compile your code for an Intel Macintosh. The next byte in memory following array c is now the least significant byte of n. If n has a value from 1 to 255, c doesn't behave like a string of 12 characters anymore. This is a great opportunity for a bug in your program that only happens in an Intel version, and is an absolute nightmare to find.

For example:

mystruct s;
strncpy (s.c, "This is a very very long string", sizeof (s.c));
for (s.n = 1; s.n <= 255; ++s.n)
if (strchr (s.c, s.n) != NULL)
printf ("s.c contains the character %c\n". s.n);

On a PowerPC, it will print that s.c contains the letters T, h, i, s, space, a, v and e. On an Intel Mac, it will print that s.c contains _all_ 255 letters which is strange because strlen (s.c) will return 12 after the loop is finished.

lazydog
Mar 17, 2007, 06:27 AM
Security experts will tell you that strncpy lulls you into a false sense of security. You think you are secure but you are not. Now in reality you either make sure that the destination buffer is big enough before you call strcpy (in which case strncpy is pointless), or you write a function yourself that will do something sensible, unlike what strncpy does, if there is not enough space.

Lets say dst has space for ten chars. If you just call

strncpy (dst, src, 10);
len = strlen (dst);

strncpy won't overwrite anything, but len can be greater than 10, or the call to strlen can even crash, so strncpy doesn't gain anything. Any use of strncpy in some code makes me very, very worried.


strncpy isn't useless. Like szark said, you can use it to copy one string into a portion of another string, ie strncpy( dst, src, strlen( src ) )

In your above code if dst plays the role of a C string, ie is null terminated and is 10 characters long including the null character, then doing:-

strncpy( dst, src, 10 )

is a silly thing to do and it's the programmers fault and not strncpy() when the null character is overwritten.

b e n

MarkCollette
Mar 17, 2007, 08:40 AM
It can be worse.

Say you have a struct

typedef struct { char c [12]; int n; } mystruct;

and call strncpy (c, "this is a very very long string", 12);

Not if you actually do what I said to do in this post (http://forums.macrumors.com/showpost.php?p=3449477&postcount=8).

typedef struct { char c [13]; int n; } mystruct;

strncpy (mystruct.c, "this is a very very long string", 12);
mystruct.c[12] = '\0';

pilotError
Mar 17, 2007, 09:39 AM
If your really worried about buffer overflows, and your string is null terminated, you can just use sizeof()

strncpy(mystruct.c, "this is a very very long string", sizeof(mystruct.c) - 1);

I though the GNU compilers deprecated a bunch of the original string copy functions and provided alternatives to avoid the whole buffer overflow thing.

I did a quick man check and didn't see them.

I also see a mac specific strlcpy in the man pages.

Catfish_Man
Mar 18, 2007, 11:29 AM
Or we could just STOP USING C FOR GENERAL APPLICATION PROGRAMMING and save ourselves multiple huge classes of bugs, as well as speeding up development. It's a system programming language, folks. It's not suited for string processing. :mad:

gnasher729
Mar 18, 2007, 03:52 PM
If your really worried about buffer overflows, and your string is null terminated, you can just use sizeof()

strncpy(mystruct.c, "this is a very very long string", sizeof(mystruct.c) - 1);



You didn't think this through, did you?

If mystruct.c has n bytes, then the first n-1 bytes will be filled with data from the string, the last byte has its previous, probably unspecified value. So the behavior now depends on whatever was at that memory location earlier, which is generally unpredictable and may for example depend on which compiler optimisations you have turned on. This can give you another debugging nightmare: The possibility that a bug only turns up in a release version and doesn't happen in your debugging version.

gnasher729
Mar 18, 2007, 03:56 PM
strncpy isn't useless. Like szark said, you can use it to copy one string into a portion of another string, ie strncpy( dst, src, strlen( src ) )

In your above code if dst plays the role of a C string, ie is null terminated and is 10 characters long including the null character, then doing:-

strncpy( dst, src, 10 )

is a silly thing to do and it's the programmers fault and not strncpy() when the null character is overwritten.

b e n

That was the point of my first post: Don't use strncpy. Yes, it is not its fault that it is ugly and useless, just don't use it.

lazydog
Mar 18, 2007, 04:24 PM
You didn't think this through, did you?

If mystruct.c has n bytes, then the first n-1 bytes will be filled with data from the string, the last byte has its previous, probably unspecified value. So the behavior now depends on whatever was at that memory location earlier, which is generally unpredictable and may for example depend on which compiler optimisations you have turned on. This can give you another debugging nightmare: The possibility that a bug only turns up in a release version and doesn't happen in your debugging version.

I think the whole point was, that with mystruct.c[12] = '\0'; (as MarkCollete suggested) then strncpy(mystruct.c, "this is a very very long string", sizeof(mystruct.c) - 1); is fine.

Just my opinion but your examples for not using strncpy look like example of bad progamming technique/errors/bugs. You might as well say strcpy is a security problem because somebody might do this:-


char* fish = malloc( 20 ) ;


strcpy( fish, "a very long message that will spill over fish" ) ;


Anyway, not everybody uses strncpy to copy 'whole' C strings, and not all strings are null terminated.

b e n

EDIT: Also in some secure situations (though I admit I've never had to do this myself), it's important to overwrite the previous contents of strings so as not to leave keys etc in memory.

pilotError
Mar 19, 2007, 09:31 AM
You didn't think this through, did you?

My point was if you wanted to avoid the buffer overflows, use the sizeof. I think he's capable of null terminating the string.

Then again, None of us should be programming in C, its a systems programming language you know! :p

Good quote from the Red Hat man pages:


BUGS
If the destination string of a strcpy() is not large enough (that is,
if the programmer was stupid/lazy, and failed to check the size before
copying) then anything might happen. Overflowing fixed length strings
is a favourite cracker technique.

wittegijt
Mar 19, 2007, 01:20 PM
Or we could just STOP USING C FOR GENERAL APPLICATION PROGRAMMING and save ourselves multiple huge classes of bugs, as well as speeding up development. It's a system programming language, folks. It's not suited for string processing. :mad:

What is a system programming language and why does it not need to handle strings??? I always thought C was a general purpose language, and that's the way I've used it.

Very:confused:

Wittegijt.

MarkCollette
Mar 19, 2007, 01:29 PM
What is a system programming language and why does it not need to handle strings??? I always thought C was a general purpose language, and that's the way I've used it.

Very:confused:

Wittegijt.

It means that we've found better ways of developing software, but those other approaches have overhead that one may not want when writing low level software.