1825747 Members
2637 Online
109687 Solutions
New Discussion

Re: strange behaviour?

 
SOLVED
Go to solution
Luke_39
New Member

strange behaviour?

hello,

I am developing C on HP UX 11v2 with native c compiler. I cannot understand why below program do not produce core dump / segmentation fault.

void main(void)
{
char buf[10];

strcpy(buf, "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789");

printf("content of buf: %s\n", buf);
}


It is strange to me that instead of core dump, the program truncate the string and produce the following output:
$ ./test
content of buf: 0123456789012345678901234567890123456789012345678901234567890123

any idea about this strange behaviour?
14 REPLIES 14
Hein van den Heuvel
Honored Contributor

Re: strange behaviour?

Welcome to the hpux forum Luke!

[ be sure to check out:
http://forums1.itrc.hp.com/service/forums/helptips.do? ]

Your question is exactly why some folks hate the C language with a vengance. The language does not require array bound/buffer checking.
The strcpy merrily destroyed data cells outside the 'buf' storage, but due to the simplicity of the program it happened to have no effect. If you had other variables allocated, then some of those would have been overwritten.
You were just lucky (or unlucky according to some) then the overwrite in this case caused no serious damage. I consider it unlucky because coding bugs like this can cause bugs to go undetected for years and suddenly strike when you least suspect. If it had core dumped during development, then the problem woudl probably quickly spotted, but if this starts faulting years later when you perhaps modified a module 'next' to it, well then it becomes tricky to debug.

Hope this helps some,
Hein.

Luke_39
New Member

Re: strange behaviour?

I must thank you for sparing your time to ans. my question, but in fact I am asking why the program did not produce core dump, i.e. I expect core dump.

if u compile this program on other platforms: DOS, Solaris. It will produce core dump. It is natural because it over-write memory where it should not over-write.

but why core dump did not happen on HP UX?
Jdamian
Respected Contributor

Re: strange behaviour?

Luke wrote
"It will produce core dump. It is natural because it over-write memory where it should not over-write"

I don't agree that because local variables as buf[] are hold in the $BSS$ subspace (uninitialized data).
I guess this subspace has a minimum size that, in your example, is empty. Your process can WRITE on this area (the objects inside expect to be INITIALIZED after program starts running). It is not an READ-ONLY area.

I guess that, if another string buf2[] is placed AFTER string buf[], the strcpy() call WILL PROBABLY OVERWRITE the contents of buf2[]. Compile and run the following proposal:

void main()
{
char buf[10], buf2[10];

strcpy(buf2, "hello");
printf("content of buf2: %s\n", buf2);

strcpy(buf, "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789");

printf("content of buf: %s\n", buf);
printf("content of buf2: %s\n", buf2);
}

In my box this program prints:

content of buf2: hello
content of buf: 01234567890123456789012345678901
content of buf2: 6789012345678901
Stephen Keane
Honored Contributor

Re: strange behaviour?

If you WANT a core dump, try

void main()
{
char buf[10];
const char * buf2 = "Hello";

printf("content of buf2: %s\n", buf2);

strcpy(buf, "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789");

printf("content of buf: %s\n", buf);
printf("content of buf2: %s\n", buf2);
}
Volker Borowski
Honored Contributor

Re: strange behaviour?

Hi,
I think this is normal !
Variables inside the program are either put on a data segment or on a stack if they are local to functions.
The data segment usually is bigger than just the plain amount of bytes used by all variables.
I think this might be rounded to a at least 2 or 4 K boundary.
So addressing anything inbetween that segment will not be an addressviolation.

But you may destroy variables belonging to your own process located in that area as said already.

But just specualting....
Volker
Gregory Fruth
Esteemed Contributor

Re: strange behaviour?

I don't think there's any specification
that says that it MUST produce a core dump.
The HP-UX platform (particularly on PA-RISC)
is pretty lenient (some would say lax)
about memory errors.

P.S. Your example program has several other
problems as well. You need to #include
stdio.h and string.h. main() must be
of type int. Your main() also doesn't
have a return value.
Luke_39
New Member

Re: strange behaviour?

thank you so much,

I noticed the length of the memory piece is 64 bytes (in my example), so I suspected there is sth. about heap allocation.
In fact I've tried insert variables of different types and length, and found it can only over-run neighbouring variables but restricted in the 2^n memory.

What puzzled me : at run time, library routine (strcpy) seems know how to check for memory boundary (2^n) and stop where boundary reach (truncated). In other words, it 'check' 'boundary'. But just I don't know how it works and in what ways it determine the boundary.

Stephen, your core dump produced because of dereferencing of address which is not exists (or exists but illegal to access),
but we are talking about buffer overflow. Pls. don't get angry.
Hein van den Heuvel
Honored Contributor

Re: strange behaviour?


A couple of remarks


- your program only uses stack local variables and constants. No heap.

- Stephens example does shwo the problem with 'silent' corruption, but indeed does not show why a segmenation fault does nto happen there and then on the copy.

- I suspect that those DOS, Solaris and other examples would also not fault... if you allocate a little more local variables, making it 'your space' to overwrite. They woudl then also silent fail.

- computer / software vendors only document correct behaviour. Random erroroneous program errors can cause random subsequent effect which may or might not include segmentation faults.

- segmentation faults are triggered by hardware, based on protecting entire pages. Is that what you mean by "2^n" ? If not, what did you mean by that 2^n?

- your 'buf' starts somewhere on a page. if it is allocated toward the end of a mamroy chunk, a hardware error will occur. If the page next to it happens to be writeable (more stack), it will happily overwrite that, and a further error may mor might not happen depnding on what is overwritten.

- Admittedly I do not actually know how strcpy is implemented on hpux but I hope it does NOT check. If it did, it would be wasting cpu time all the time (IMHO).
Man strcpy explains: "strcpy() Copies string s2 to s1, stopping after the null byte has been copied." Nowhere does it say it will stop when the target space is too small or some such. How could it know in a language like C?

- whether it faults or not depends the exact memory layout the system chooses for you. You can get some insight in that from several web pages. I found some with google for "+"memory layout" +hpux +site:hp.com"
For example:
http://h21007.www2.hp.com/dspp/files/unprotected/Itanium/aas_white_paper.pdf
Other interesting search terms are "local variables" and grow and stack.

- A 'fun' document about overwriting stacks:
www.comms.scitech.susx.ac.uk/fft/security/ Stack_Smashing_Vulnerabilities_in_the_UNIX_Operating_System.pdf

Hope this helps some!
Regards,
Hein.
A. Clay Stephenson
Acclaimed Contributor

Re: strange behaviour?

It's really quite simple why you didn't trigger a core dump. You didn't actually trigger a segmentation violation. Because of the way the memomory is allocated, I'm pretty sure that strcpy(&(buf[-128),"012...789"); (which is perfectly legal C syntax) would have triggered a segmentation violation. There is no bounds checking in C so the only ways memory violations are detected are at a much lower level -- typically the hardware can detect an illegal access when it crosses a page boundary. You example did not cross a page boundary and thus no SIGSEGV was generated.
If it ain't broke, I can fix that.
Luke_39
New Member

Re: strange behaviour?

Clay, you are right, the main point is my example code did not triggered a segmentation fault, which imply there is no illegal memory access.
but as all of us know strcpy() do not check boundary, if I feed in a string with size larger than the page where the process located, it will generate segmentation fault, is that true?
R. Allan Hicks
Trusted Contributor

Re: strange behaviour?

Your statement "which imply there is no illegal memory access" might be better said as "no illegal memory access was detected."

Buffer overuns are nasty things and make for great security risks. Your DOS program may have detected your illegal access, but the PNG exploit under windows happens because of a undetected buffer overun.

The old HP1000 16 bit computer that you can probably find in a museum somewhere had a memory protect fence. The OS set the bounds of memory and if you crossed it, it was the end of your program.

I suspect that a modern OS like HP-UX probably allocates a heap area based on page boundaries and will allow you to write all over yourself as long as you stay in the heap.
"Only he who attempts the absurd is capable of achieving the impossible
A. Clay Stephenson
Acclaimed Contributor
Solution

Re: strange behaviour?

To get a good handle on this, I suggest the following test program (I haven't run it):

#define STOP 100000000L

int main()
{
long i = 0L;
char s[128];

while (i < STOP)
{
if ((i % 10000L) == 0L) (void) printf("%9ld\n",i);
s[i] = 'X';
++i;
} /* while */
return(0);
}

-------------------------------------------

You are probably only going to get a segmentation violation when maxssiz is exceeded -- if running this on HP-UX.
Writing C requires great discipline on the part of the programmer. Remember, in the good old days of C (before prototypes) , there was not even any checking of functions to make sure that formal and actual parameters agreed even in number and type.
If it ain't broke, I can fix that.
Gregory Fruth
Esteemed Contributor

Re: strange behaviour?

You seem to think that illegal memory access
always results in a core dump. Unfortunately
this is simply not true in this type of
environment. Perhaps it is true on a
mainframe-type machine or on a machine with
rigid memory management.

For example, HP-UX on PA-RISC lets you
dereference a null pointer without causing
an error. (You can use cc -z the disable
this "feature".)

As for your comments about 2^n, perhaps you
are referring to the memory alignment rules.
The compiler has to put variables in memory
in addresses which match the size of the
item. For example, a C double variable is
8 bytes long and must be placed at an
address which is a multiple of 8. A C char
is 1 bytes long and can be placed at any
address. So if you declare a char followed
by a double, there will typically be a
"hole" of unused space between the two
items in memory. You can see the effect
in the following program by changing
the double to a char.

#include

int main() {
char foo;
double bar;
printf("address of foo: 0x%x\n", &foo);
printf("address of bar: 0x%x\n", &bar);
return(0);
}
Luke_39
New Member

Re: strange behaviour?

Clay, with your hint (maxssiz) I found the header file param.h and other associate files, in which contains detail description of stack layout and how it is allocated.

Before closing the thread, I must thank you all of you, for patient, and getting through all those with me.
special thanks to Hein & Clay, guide me and get me back on the right track.