buffer overflow

R

Roman Mashak

Hello,

can't realize what's happening in this code snippet:

int main(int argc, char *argv[])
{
char buf[256];
strcpy(buf, argv[1]);
...
}

Debugger shows argv[1] as NULL and as a result I get 'segmentation fault' on
'strcpy' call. I can't figure out why NULL is not a proper in this case,
standard doesn't prohibit it in string functions (at least I have not found
it).

With best regards, Roman Mashak. E-mail: (e-mail address removed)
 
C

Chris Dollin

Roman said:
can't realize what's happening in this code snippet:

int main(int argc, char *argv[])
{
char buf[256];
strcpy(buf, argv[1]);
...
}

Debugger shows argv[1] as NULL and as a result I get 'segmentation fault' on
'strcpy' call. I can't figure out why NULL is not a proper in this case,
standard doesn't prohibit it in string functions (at least I have not found
it).

I think you'll find that it says unless otherwise specified,
pointer arguments to library functions provoke undefined
behaviour if null.

It's 7.1.4, /Use of library functions/, in the n1124.pdf draft.
 
R

Richard Tobin

Debugger shows argv[1] as NULL and as a result I get 'segmentation fault' on
'strcpy' call. I can't figure out why NULL is not a proper in this case,
standard doesn't prohibit it in string functions (at least I have not found
it).

The standard requires the argument to be a string, and NULL is not a
string.

-- Richard
 
C

CBFalconer

Roman said:
can't realize what's happening in this code snippet:

int main(int argc, char *argv[])
{
char buf[256];
strcpy(buf, argv[1]);
...
}

Debugger shows argv[1] as NULL and as a result I get 'segmentation
fault' on 'strcpy' call. I can't figure out why NULL is not a proper
in this case, standard doesn't prohibit it in string functions (at
least I have not found it).

However the standard does require a proper string to copy into
buf. A string is a sequence of bytes, possibly empty, followed by
a '\0' byte. A NULL pointer doesn't point to anything, so there is
no place for that '\0'. So you need a statement such as:

if (argv[1]) strcpy(buf, argv[1]);
else buf[0] = '\0';

Of course argv[1] may not even exist, so you should also guard by:

if (argc > 1) ...
 
S

SM Ryan

# Debugger shows argv[1] as NULL and as a result I get 'segmentation fault' on
# 'strcpy' call. I can't figure out why NULL is not a proper in this case,
# standard doesn't prohibit it in string functions (at least I have not found
# it).

Arbitrary restriction of C, the source cannot be null. You have
code to ensure you won't call str... functions with null arguments.
 
C

Clever Monkey

Roman said:
Hello,

can't realize what's happening in this code snippet:

int main(int argc, char *argv[])
{
char buf[256]
strcpy(buf, argv[1]);
...
}

Debugger shows argv[1] as NULL and as a result I get 'segmentation fault' on
'strcpy' call. I can't figure out why NULL is not a proper in this case,
standard doesn't prohibit it in string functions (at least I have not found
it).
As others have suggested, what happens if argv[1] is a null pointer?
Check the docs for strcpy() and friends.

Ask yourself what happens if strlen(argv[1]) >= 256?
 
R

Richard Tobin

SM Ryan said:
Arbitrary restriction of C, the source [of strcpy()] cannot be null.

Not entirely arbitrary. What would you want it to *do*? Do you want
to treat NULL the same as an empty string?

-- Richard
 
I

Ian Malone

CBFalconer said:
Of course argv[1] may not even exist, so you should also guard by:

if (argc > 1) ...

Shouldn't the argv[argc] be NULL and argc > 0?
(Not 100% sure, and regardless the general case
would require you to check)
 
B

Bill Medland

Ian said:
CBFalconer said:
Of course argv[1] may not even exist, so you should also guard by:

if (argc > 1) ...

Shouldn't the argv[argc] be NULL and argc > 0?
(Not 100% sure, and regardless the general case
would require you to check)
Yes and no.
The (argc > 1) is presumably meant to test that there is indeed a program
parameter to copy and that's why it needs to be > 1, not > 0.

The argv[argc] == NULL came as a little bit of a suprise to me; it's an
interesting fact to know.
 
I

Ian Malone

Bill said:
Ian said:
CBFalconer said:
Of course argv[1] may not even exist, so you should also guard by:

if (argc > 1) ...
Shouldn't the argv[argc] be NULL and argc > 0?
(Not 100% sure, and regardless the general case
would require you to check)
Yes and no.
The (argc > 1) is presumably meant to test that there is indeed a program
parameter to copy and that's why it needs to be > 1, not > 0.

The argv[argc] == NULL came as a little bit of a suprise to me; it's an
interesting fact to know.

I've just checked C9X FCD and it specifies argc non-negative,
but appears to allow argc == 0. (Not massively surprised to
know CBFalconer was right.)
 
M

Mark McIntyre

CBFalconer said:
Of course argv[1] may not even exist, so you should also guard by:

if (argc > 1) ...

Shouldn't the argv[argc] be NULL and argc > 0?

No, some platforms provide no information on the commandline. ISTR
that earlier versions of MacOS did this, and you had to fetch the args
with a function called something intuitiive like GetCommandLineArgs().
(Not 100% sure, and regardless the general case
would require you to check)

Yup.

--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
 
B

Bill Medland

Mark said:
CBFalconer said:
Of course argv[1] may not even exist, so you should also guard by:

if (argc > 1) ...

Shouldn't the argv[argc] be NULL and argc > 0?

No, some platforms provide no information on the commandline. ISTR
that earlier versions of MacOS did this, and you had to fetch the args
with a function called something intuitiive like GetCommandLineArgs().
(Not 100% sure, and regardless the general case
would require you to check)

Yup.
Well, actually the standard states that argv[argc] MUST be null. (I'd
always assumed that it wasn't even accessible).
 
T

Tor Rustad

Roman Mashak skrev:
can't realize what's happening in this code snippet:

int main(int argc, char *argv[])
{
char buf[256];
strcpy(buf, argv[1]);
...
}

Debugger shows argv[1] as NULL and as a result I get 'segmentation fault' on
'strcpy' call.

Null pointer reference is undefined behavior, and here you even try to
modify it!
I can't figure out why NULL is not a proper in this case,
standard doesn't prohibit it in string functions (at least I have not found
it).

The standard does prohibit it, NULL is a null pointer constant, which
is unequal to a pointer of any object. The strcpy(s1, s2) function copy
the string s2 into an array of char object... and a null pointer is
garanteed to be different from _any_ such object.

Null pointers are very useful, they tell you that this pointer is
"invalid", i.e. the pointer does not point to a valid object.

p = malloc(10);
free(p);
p = NULL; /* <-- mark this pointer as invalid */

function (p); /* <-- We like to detect an invalid pointer here */
....


Under the Hood

A typical implementation will put not only the null pointer, but let
say some memory above it, to catch null pointer assignments. On MS-DOS,
0x000 - 0xFFF was reserved for this, on modern OS'es, a process use
virtual address space and typically reserve a bigger space for trapping
null pointers. If your program try to access this "invalid" space... a
HW trap is generated... which can be catched by the kernel... or a
debugger... and your program seg faults.

This is an extreamly useful mechanism for catching program faults.
 
N

newbie

This is undefined. You are passing in a NULL pointer and not a pointer
to a string where the first character is the NULL character ('\0').
 
I

Ian Malone

Tor said:
Roman Mashak skrev:
can't realize what's happening in this code snippet:

int main(int argc, char *argv[])
{
char buf[256];
strcpy(buf, argv[1]);
...
}

Debugger shows argv[1] as NULL and as a result I get 'segmentation fault' on
'strcpy' call.

Null pointer reference is undefined behavior, and here you even try to
modify it!

You can of course pass a null pointer to a function,
the problem (as you point out in the part I've snipped)
is that strcpy needs a valid object.
 
I

Ian Malone

Bill said:
Mark said:
CBFalconer wrote:
Of course argv[1] may not even exist, so you should also guard by:

if (argc > 1) ...

Shouldn't the argv[argc] be NULL and argc > 0?
No, some platforms provide no information on the commandline. ISTR
that earlier versions of MacOS did this, and you had to fetch the args
with a function called something intuitiive like GetCommandLineArgs().
(Not 100% sure, and regardless the general case
would require you to check)
Yup.
Well, actually the standard states that argv[argc] MUST be null. (I'd
always assumed that it wasn't even accessible).

And, on checking the C99 draft, argc can be zero, in which
case no argv[1]. I'd assume earlier standards would if
anything have been less strict rather than more, although
I don't have one I can check. The MacOS described could
have easily been compliant by always supplying
argc=0 argv[0]=0. ("But why?" I wonder.)
 
T

Tor Rustad

Ian Malone skrev:
Tor said:
Roman Mashak skrev:
Debugger shows argv[1] as NULL and as a result I get 'segmentation fault' on
'strcpy' call.

Null pointer reference is undefined behavior, and here you even try to
modify it!

You can of course pass a null pointer to a function,
the problem (as you point out in the part I've snipped)
is that strcpy needs a valid object.

When passing null pointer to a library function, you invoke undefined
behavior, unless the standard explicitly state that null pointer
argument is allowed.
 
S

SM Ryan

(e-mail address removed) (Richard Tobin) wrote:
# In article <[email protected]>,
#
# >Arbitrary restriction of C, the source [of strcpy()] cannot be null.
#
# Not entirely arbitrary. What would you want it to *do*? Do you want
# to treat NULL the same as an empty string?

My wrappers treat 0 as "" except compare(0,"")<0. It's arbitrary
in the same sense that O! = 1; a number of answers could be argued
correct, but one has to be chosen.
 
A

Arndt Jonasson

SM said:
(e-mail address removed) (Richard Tobin) wrote:
# In article <[email protected]>,
#
# >Arbitrary restriction of C, the source [of strcpy()] cannot be null.
#
# Not entirely arbitrary. What would you want it to *do*? Do you want
# to treat NULL the same as an empty string?

My wrappers treat 0 as "" except compare(0,"")<0. It's arbitrary
in the same sense that O! = 1; a number of answers could be argued
correct, but one has to be chosen.

Possibly "0^0 = 1" is a better example.
 
R

Richard Tobin

SM Ryan said:
# >Arbitrary restriction of C, the source [of strcpy()] cannot be null.
# Not entirely arbitrary. What would you want it to *do*? Do you want
# to treat NULL the same as an empty string?
My wrappers treat 0 as "" except compare(0,"")<0. It's arbitrary
in the same sense that O! = 1; a number of answers could be argued
correct, but one has to be chosen.

Treating NULL as "" is arbitrary in that sense, but making it
undefined is not.

-- Richard
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,225
Members
46,815
Latest member
treekmostly22

Latest Threads

Top