Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > strcpy overlapping memory

Reply
Thread Tools

strcpy overlapping memory

 
 
arnuld
Guest
Posts: n/a
 
      12-07-2010
> On Mon, 06 Dec 2010 17:21:25 -0800, Keith Thompson wrote:

>> "BartC" <> writes:
>> Pretend it's ""?

>
> Why?


Can't speak for what Bart saw and I had this issue many times in real
life code, which was being maintained by me but written by some
programmers a few years back and I was checking for Segfaults (at some
other place in code) but then later came to know it was causing troubles
not because pointer was NULL to strcpy() but because it was pointing to
an empty string which was crashing the program at some random locations
in code. Now I had to put 2 checks: one for NULL and one for whether
string is empty :-/


>> (And what would the application then do?)

>
> Presumably it would crash -- and the developer would then fix the bug so
> it doesn't crash next time.


Yeah right. Thats what I did but I cursed original programmer a lot.



> Passing a null pointer to strcpy() *is* necessarily an error. strlen()
> could have been defined to return the length of string pointed to by its
> arguments, or 0 if the argument is a null pointer. But it wasn't
> defined that way. If you want such a function, feel free to write it.


I don't get you here. Whats the problem and whats the solution, swept
above my head.



> NULL isn't a pointer to an empty string. It's a pointer value that
> doesn't point to anything, and that's a valuable distinction that I
> shouldn't be ignored by the standard library.


If its ignored it means its a C Standard Library






--
www.lispmachine.wordpress.com
 
Reply With Quote
 
 
 
 
Keith Thompson
Guest
Posts: n/a
 
      12-07-2010
arnuld <> writes:
>> On Mon, 06 Dec 2010 11:26:01 -0800, Keith Thompson wrote:
>> Check for NULL and do what?
>>
>> If strcpy(s, NULL) quietly does nothing, the implementation isn't doing
>> you any favors. A seg fault or equivalent is the best thing it can do
>> to help you track down the error in your program.

>
> In my case, strcpy(s, NULL) Segfaults. I have done this mistake of not
> checking arguments for NULL before passing them to strcpy(). Is there
> anything wrong in checking for NULL before using Std Lib's string
> functions ?


It's best to write your code so you don't pass a null pointer in
the first place. For example, if both arguments are the names
of array objects, there's no need to check. Similarly, if both
arguments are pointer objects that cannot have null pointer values
due to the program logic, you also don't need to check.

You *must not* pass a null pointer to strcpy(). If checking is
the best way to avoid that, by all means check.

There is on possible drawback. Suppose you have some
string-processing function that calls strcpy(). If your function
decides to treat null pointers as if they were pointers to empty
strings, that encourages a certain sloppiness on the part of any
callers.

To put it another way, trying to use a null pointer as if it
pointed to a string is a logical error. IMHO, catching that error
is usually better than pretending it's not there.

--
Keith Thompson (The_Other_Keith) kst- <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
 
 
 
Keith Thompson
Guest
Posts: n/a
 
      12-07-2010
arnuld <> writes:
>> On Mon, 06 Dec 2010 17:21:25 -0800, Keith Thompson wrote:
>>> "BartC" <> writes:
>>> Pretend it's ""?

>>
>> Why?

>
> Can't speak for what Bart saw and I had this issue many times in real
> life code, which was being maintained by me but written by some
> programmers a few years back and I was checking for Segfaults (at some
> other place in code) but then later came to know it was causing troubles
> not because pointer was NULL to strcpy() but because it was pointing to
> an empty string which was crashing the program at some random locations
> in code. Now I had to put 2 checks: one for NULL and one for whether
> string is empty :-/


It's impossible to tell from your description what the problem was.
A pointer to an empty string is a perfectly valid argument for a
function that operates on strings. It may or may not have been a
valid argument for the particular function you were dealing with.
(For example, a function that parses a string representing a number
can't do anything sensible with an empty string.)

[...]

>> Passing a null pointer to strcpy() *is* necessarily an error. strlen()
>> could have been defined to return the length of string pointed to by its
>> arguments, or 0 if the argument is a null pointer. But it wasn't
>> defined that way. If you want such a function, feel free to write it.

>
> I don't get you here. Whats the problem and whats the solution, swept
> above my head.


I see I mixed up strcpy() and strlen() in the above; I hope that didn't
cause too much confusion.

strlen()'s argument is char* expression that needs to be a pointer to a
string. A null pointer doesn't point to a string, passing a null
pointer to strlen() is a logical error. The ideal solution is not to
try to call strlen() with a null pointer in the first place. If you
have a char* variable for which you need the length of the string it
points to, if your program logic is designed correctly, there should
be no possibility that it's a null or otherwise invalid pointer.

That's an ideal situation. There are times when run-time checks are
necessary. And what your program should do if the pointer is null
depends on the requirements of the program:

char *s = /* ... */; /* may or may not be a null pointer
if (s != NULL) {
len = strlen(s);
/* ... */
}
else {
/*
* What's the right thing to do here? It's impossible to
* tell without more information.
*/
}

In most cases, the logical error occurred when s was set to a null
pointer value.

>> NULL isn't a pointer to an empty string. It's a pointer value that
>> doesn't point to anything, and that's a valuable distinction that I
>> shouldn't be ignored by the standard library.

>
> If its ignored it means its a C Standard Library


Hmm?

--
Keith Thompson (The_Other_Keith) kst- <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
ImpalerCore
Guest
Posts: n/a
 
      12-07-2010
On Dec 7, 11:48*am, Keith Thompson <ks...@mib.org> wrote:
> arnuld <sunr...@invalid.address> writes:
> >> On Mon, 06 Dec 2010 11:26:01 -0800, Keith Thompson wrote:
> >> Check for NULL and do what?

>
> >> If strcpy(s, NULL) quietly does nothing, the implementation isn't doing
> >> you any favors. *A seg fault or equivalent is the best thing it can do
> >> to help you track down the error in your program.

>
> > In my case, strcpy(s, NULL) Segfaults. I have done this mistake of not
> > checking arguments for NULL before passing them to strcpy(). Is there
> > anything wrong in checking for NULL before using Std Lib's string
> > functions ?

>
> It's best to write your code so you don't pass a null pointer in
> the first place. *For example, if both arguments are the names
> of array objects, there's no need to check. *Similarly, if both
> arguments are pointer objects that cannot have null pointer values
> due to the program logic, you also don't need to check.
>
> You *must not* pass a null pointer to strcpy(). *If checking is
> the best way to avoid that, by all means check.
>
> There is on possible drawback. *Suppose you have some
> string-processing function that calls strcpy(). *If your function
> decides to treat null pointers as if they were pointers to empty
> strings, that encourages a certain sloppiness on the part of any
> callers.


There is a negative side to your story. When a library function
(calling it 'my_str_func') that uses strcpy or the other str family of
functions that bomb on NULL don't perform any systematic validation of
its arguments, you've condemned all users of 'my_str_func' to handle
the checking apriori. And most of us know that the track record of
many developers will either ignore argument checking, implement it
erroneously, or do it inconsistently. Even those that perform all the
necessary checks, the amount of issues with "checking code" to support
validation is a huge maintenance burden that is proportional to the
number of users and the number of called instances of the
'my_str_func' library function.

If the checking is done internal to the 'my_str_func' library
function, many of those issues go away. Of course the new issue is
that no one can agree on what the response to NULL pointer argument
errors should be, (ignore, abort, print an error message, return a
error value, set a global errno, etc). And unfortunately, the best
response is dependent on the situation (development, test or
production) and programmer preferences.

> To put it another way, trying to use a null pointer as if it
> pointed to a string is a logical error. *IMHO, catching that error
> is usually better than pretending it's not there.


I agree that ultimately this is what most developers want, but this
gets back to the whole dichotomy of whether to design library
functions that are "robust" to developer mistakes.

Do you want strcpy within 'my_str_func' to crash the application when
the developer goofs (great for development, poor for the user
experience), or gloss over the error (maybe with an annoying message)
and rely on tester or user observations to detect some software flaw
(poor for development, can be better [handle error gracefully] or poor
[corrupting data] for users depending on situation and perspective)?

It's not a clear cut picture, at least to me. I think the glib
'g_return_if_fail' and 'g_return_val_if_fail' macros are pretty good
if you want to incorporate the early-return style of error checking
within 'my_str_func'. To get the flexibility, I use a modified
version of these macros to use global function pointers to abstract
the reporting (useful to alert developers and annoy users like
printing a message to stderr, or adding it to a queue of error
messages shown in a window) and response (abort or do nothing) steps.
For example, in development or test, I can make the response step
abort to make it feel more like design by contract, but in production
it can be a no-op or prompt to save the user's work and quit. It's
not perfect, but it's more flexible than using assert and feels better
than the alternatives I've tried.

Best regards,
John D.
 
Reply With Quote
 
Michael Press
Guest
Posts: n/a
 
      12-08-2010
In article <4cfe2d12$0$23761$>,
arnuld <> wrote:

> > On Mon, 06 Dec 2010 17:21:25 -0800, Keith Thompson wrote:

>
> >> "BartC" <> writes:
> >> Pretend it's ""?

> >
> > Why?

>
> Can't speak for what Bart saw and I had this issue many times in real
> life code, which was being maintained by me but written by some
> programmers a few years back and I was checking for Segfaults (at some
> other place in code) but then later came to know it was causing troubles
> not because pointer was NULL to strcpy() but because it was pointing to
> an empty string which was crashing the program at some random locations
> in code. Now I had to put 2 checks: one for NULL and one for whether
> string is empty :-/


Next step you took was a global search in the code for `strcpy',
and the usual suspects.

--
Michael Press
 
Reply With Quote
 
JohnF
Guest
Posts: n/a
 
      12-08-2010
James Dow Allen <> wrote:
> JohnF <> wrote:
>> It also somewhat tarnishes my picture of C the way it's often
>> described as a "portable assembly language". In that picture, I'd
>> kind of hope that strcpy would just assemble to some straightforward
>> move instruction, along with whatever '\000' end-of-string check
>> is available in the particular instruction set. If they want
>> to add optimizations, they could at least reserve them for -O3,
>> or something like that.

>
> As someone who also views C as a "portable assembly language"
> [...] A key meaning in that phrase is C's determinism


Never heard that before. What, precisely, is "determinism"
supposed to mean in this context?

> and if the end-result of strcpy() (when used
> according to its rules!) is completely defined,
> what's to complain about?


My personal (repeat, >>personal<<) complaint would be
that if C instructions aren't compiled/assembled in
a straightforward way to machine instructions, then
I can't reliably visualize the code I'm generating.
Although different instruction sets do differ, they
nevertheless typically have lots in common. As an
old assembly programmer, I kind of know what I should
be able to expect from something calling itself
a "portable assembly language". In particular, I kind
of know how something calling itself strcpy should
be compiled. And that implicit understanding tells me
that strcpy(s,s+n) ought to be safe (as long, of course,
as strlen(s)>n). And it also tells me, of course, that
the reverse strcpy(s+n,s) is totally ridiculous.

> It isn't clear whether you were unaware of strcpy()'s
> overlap caveat or were but chose to ignore it (?!).


Hint: read this thread's Subject
As explained just above, I relied on the "portable
assembly language" idea to infer that strcpy(s,s+n)
would behave universally predictably and safely.
Won't make that mistake again. And I'd never have
made that mistake with, say, C++. But I'd like to have
thought that C (without optional -O3 type optimizations)
would compile straightforwardly/transparently/etc.

> (the one-liner for strcpy() is famous!) and 99+% of
> the time squeezing maximum efficiency is unnecessary.


Yeah, that's another good point. strcpy is typically (99+%)
used for parsing input, formatting output, etc, not within
heavy computational tasks. So optimizing strcpy is pretty
much a total waste, e.g.,
for (answer=0,i=0; i<10zillion; i++)
whatever;
format and display answer
in some way using sprintf,strcpy,etc;
What genius wastes his time optimizing the strcpy?

>> And one other thing continues to surprise me: if they're adding
>> all this code to check args, I'd of thought they'd at least check
>> for NULL's.

>
> If your debuggable code accidentally passes NULL,
> Segfault is exactly what you want


Might be what >>you<< want, but it's hard to speak for everybody.
Of course, I always check (except for blunders), and so don't
really care what it does. But I have lots of functions that take
optional char *args, which can be NULL or "\0" for default
behavior (and where I don't want to use variable arg lists).
Some checks would be unnecessary if strcpy, etc, just behaved
"nicely" when passed NULL's. But, again, I couldn't really
care less. My remark was just an observation, not a complaint.

> (BTW, NULL == "" on some early Dig Equip C systems. This seemed not
> necessarily bad, but obviously didn't "catch on"!


Can't recall what tops10 C did (I worked on the third ka10 processor
ever built), but vms's string (and other) descriptors were typically
a total pain in the neck.
--
John Forkosh ( mailto: where j=john and f=forkosh )
 
Reply With Quote
 
Seebs
Guest
Posts: n/a
 
      12-08-2010
On 2010-12-08, JohnF <> wrote:
> My personal (repeat, >>personal<<) complaint would be
> that if C instructions aren't compiled/assembled in
> a straightforward way to machine instructions, then
> I can't reliably visualize the code I'm generating.


You're doing it wrong. Don't visualize it as assembly, visualize
it as the abstract machine.

> Although different instruction sets do differ, they
> nevertheless typically have lots in common. As an
> old assembly programmer, I kind of know what I should
> be able to expect from something calling itself
> a "portable assembly language".


No, you don't.

> In particular, I kind
> of know how something calling itself strcpy should
> be compiled.


No, you don't.

Your expectations are wrong. You have misunderstood the
point of the "portable assembly language".

In particular, library functions are not instructions, they're
potentially extremely elaborate hunks of functionality. C gives
you a pretty good guess as to what happens for "x += 2". It isn't
supposed to tell you which single machine instruction is used
to handle printf("%-02x", a->b[3].c()).

-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet-
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
I am not speaking for my employer, although they do rent some of my opinions.
 
Reply With Quote
 
arnuld
Guest
Posts: n/a
 
      12-10-2010
> On Tue, 07 Dec 2010 10:14:57 -0800, Keith Thompson wrote:

> It's impossible to tell from your description what the problem was. A
> pointer to an empty string is a perfectly valid argument for a function
> that operates on strings. It may or may not have been a valid argument
> for the particular function you were dealing with. (For example, a
> function that parses a string representing a number can't do anything
> sensible with an empty string.)


It *was* about parsing a string . Only difference is, I was using that
program as input to my program and my program always said "Invalid
Input". Only later I figured out when input to that program was either
NULL or empty string then it used ti output strange. I even saw inverted
question mark being sent to my program , which made me realize the
words like "uninitialized memory" and "garbage".




> strlen()'s argument is char* expression that needs to be a pointer to a
> string. A null pointer doesn't point to a string, passing a null
> pointer to strlen() is a logical error. The ideal solution is not to
> try to call strlen() with a null pointer in the first place. If you
> have a char* variable for which you need the length of the string it
> points to, if your program logic is designed correctly, there should be
> no possibility that it's a null or otherwise invalid pointer.
>
> That's an ideal situation. There are times when run-time checks are
> necessary. And what your program should do if the pointer is null
> depends on the requirements of the program:
>
> char *s = /* ... */; /* may or may not be a null pointer if (s !=
> NULL) {
> len = strlen(s);
> /* ... */
> }
> else {
> /*
> * What's the right thing to do here? It's impossible to * tell
> without more information.
> */
> }
>
> In most cases, the logical error occurred when s was set to a null
> pointer value.



>> If its ignored it means its a C Standard Library


> Hmm?


I meant, there are so many traps and gotcha(s) in C that I smile whenever
I get a chance to look upon them. Sometimes (many times ?) I feel because
of my Common=Sense I get segfaults or semantic errors (one fine
example will be using = instead of == and to void that I always use
something like if 1 == x rather than if x == 1





--
www.lispmachine.wordpress.com
 
Reply With Quote
 
arnuld
Guest
Posts: n/a
 
      12-10-2010
> On Tue, 07 Dec 2010 10:14:57 -0800, Keith Thompson wrote:


> That's an ideal situation. There are times when run-time checks are
> necessary. And what your program should do if the pointer is null
> depends on the requirements of the program:
>
> char *s = /* ... */; /* may or may not be a null pointer if (s !=
> NULL) {
> len = strlen(s);
> /* ... */
> }
> else {
> /*
> * What's the right thing to do here? It's impossible to * tell
> without more information.
> */
> }
>
> In most cases, the logical error occurred when s was set to a null
> pointer value.



What about this situation where size of dest is lesser than size of
source. It does Segfault but it Segfaults after printing "WOW..."
statement, can't understand why. It should not print the message because
it has already Segfaulted in strcpy().



#include <stdio.h>
#include <string.h>

int main(void)
{
char* src = "000000000000000000000000";
char dest[6] = {0};

strcpy(dest, src);

printf("WOW!... SRC is larger thab DEST but strcpy still works\n");

return 0;
}



===================== OUTPUT =========================
[arnuld@dune programs]$ gcc -ansi -pedantic -Wall -Wextra strcpy.c
[arnuld@dune programs]$ ./a.out
WOW!... SRC is larger thab DEST but strcpy still works
Segmentation fault
[arnuld@dune programs]$


--
www.lispmachine.wordpress.com
 
Reply With Quote
 
tm
Guest
Posts: n/a
 
      12-10-2010
On 7 Dez., 01:46, "BartC" <b...@freeuk.com> wrote:
> "Keith Thompson" <ks...@mib.org> wrote in message
>
> news:...
>
> > JohnF <j...@please.see.sig.for.email.com> writes:
> > [...]
> >> * *And one other thing continues to surprise me: if they're adding
> >> all this code to check args, I'd of thought they'd at least check
> >> for NULL's. I've had more than a few programs segfault due to a
> >> blunder during development passing strcpy a NULL arg. With all this
> >> strcpy arg checking going on, couldn't they check for NULL?

>
> > Check for NULL and do what?

>
> Pretend it's ""?


I remember that under HPUX NULL and "" were interchangeable.
A very very bad idea. It made the job of porting a program
from HPUX to SGI harder. Strings were initialized with NULL
all over the place and nobody cared. The development team
(they mainly used HPUX) was not even aware of the difference
between NULL and "". And when I explained it to them, they
could hardly believe there is a difference. It really
hindered their understanding of pointers and strings.

I had to introduce a layer of macros and functions for
every string function (strcmp, strlen, strcpy, ...) like

size_t my_strlen (const char *s)
{
if (s == NULL) {
return 0;
} else {
return strlen(s);
}
}

#define strlen(s) my_strlen(s)

Greetings Thomas Mertes

--
Seed7 Homepage: http://seed7.sourceforge.net
Seed7 - The extensible programming language: User defined statements
and operators, abstract data types, templates without special
syntax, OO with interfaces and multiple dispatch, statically typed,
interpreted or compiled, portable, runs under linux/unix/windows.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
strcpy and the copy constructor RonHiler C++ 8 10-19-2004 06:30 AM
C++ Compiler with a -Wwarn-use-of-strcpy or similar option?? Paul Sheer C++ 4 09-14-2004 08:38 PM
C++ Compiler with a -Wwarn-use-of-strcpy or similar option?? Paul Sheer C++ 7 09-10-2004 05:07 PM
strcpy Mike Mimic C++ 9 05-17-2004 08:12 PM
Declarations of structs, and arrays seem to be overlapping in memory..?! David Thorp C Programming 4 09-01-2003 11:46 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57