Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

Program won't crash when it should

Name: Anonymous 2012-01-16 3:24

(GCC C)
I ran a pointer over each member of an integer array, storing one character of input in each cell.

The program seems to consistently crash when I try to store X+3 or more characters, where X is the size of the array, but if I do not exceed X+2 it will not crash.

Why does it crashes exactly at the point it does, but not for X+1 or X+2?

Name: Anonymous 2012-01-16 3:27

Buffer overflow

Name: Anonymous 2012-01-16 3:30

Perhaps you have a variable that is two bytes on the stack after your array. Writing X+2 will overwrite the short variable while any more may overwrite the return address or saved EBP, causing an obvious crash.

Name: Anonymous 2012-01-16 5:44

You're invoking undefined behavior so there is no telling what it will do, it might crash but then again it might not crash.

Name: Anonymous 2012-01-16 7:53

Read SICP.

Name: Anonymous 2012-01-16 7:56

It's undefinedbehaviour.

Name: Anonymous 2012-01-16 8:38

I am aware that it is undefined. I was just wondering why this happened so consistently. >>3 is probably the answer.

Name: Anonymous 2012-01-16 9:37

>>1,7
Protip: Fucking word alignment, how does it work

Also
undefined behaviour

Name: Anonymous 2012-01-16 9:41

>>8
This. The reason is due to your compiler aligning the variables and padding to meet alignment.

Name: Anonymous 2012-01-16 14:03

>> 7
actually I think >>2 is the answer

Name: Anonymous 2012-01-16 16:09

>>2 is correct, assuming you're compiling on a x86.

And it is not the case that the program should crash in the first place.

If you overwrite your return address with a valid address, the program will continue to run, and may even run correctly depending on your input. That is actually the basis for several buffer overflow exploits.

If your routine never returns (for example, an infinite loop or an early call to exit()), your program won't crash, even if you overwrite the entire stack space before it.

Undefined behavior means undefined behavior standard-wise. It is only a catch-all situation: a wildcard in the sense that any behavior produced by an implementation is correct according to the standard.

In this particular case, the program behavior is well-defined and consistent, as you might have perceived, and this behavior is determined by the underlying environment. The compiler might insert some code to protect against stack smashing, but in the situation of the normal call-ret pair, with or without a frame pointer involved, overwriting stack addresses only affect your own local variables and any or all of your callers. You can, for example, make you or any caller return to another function or block of code instead of returning to their respective callers.

Walking forward in the stack, on the other hand, is a typical hack used to create variables with "discardable" semantics, that is: variables which are not preserved across function calls, which do not grow the stack and without the need to allocate or deallocate heap memory. Care must be taken to not overrun the stack size, that is, overflow the stack itself.

This, naturally, applies only to the x86 architecture. In other environments the behavior may differ completely.

Name: Anonymous 2012-01-16 16:18

Take a look at this.

#include <stdio.h>
#include <stdlib.h>

void g() {
    puts("Hello, World!");
    exit(0);
}

void f() {
    int stack[1];
    /* stack[0] is local data.
     * stack[1] contains ebp.
     * stack[2] contains the return address. */
    stack[2] = g;
}

int main(void) {
    f();
}

Name: Anonymous 2012-01-16 16:57

>>12
You're invoking undefined behavior, this isn't conforming C code.

Name: Anonymous 2012-01-16 16:58

>>13
This is intentional and most obvious.

Name: Anonymous 2012-01-16 16:58

>>14
So your program is worthless, why post it?

Name: Anonymous 2012-01-16 17:04

>>15
Just fuck off, troll.

Name: Anonymous 2012-01-16 17:06

>>16
How am I a troll? I'm not the one posting broken C programs.

Name: Anonymous 2012-01-16 17:21

>>17
He is obviously posting a program which only behaves in a specific way when compiled and run on a specific compiler and architecture. I actually suspect the behavior will differ greatly even within the same compiler if different settings were used when compiling. You have the C standard and within that, the behavior his program will have is undefined, however while that wouldn't be conforming C, it doesn't mean it doesn't have very precise semantics when using a specific compiler with specific settings on a specific architecture - you can almost always determine them when you have fully specified the environment, and when you can determine them, undefined behavior will be fully defined. If your program accidentally uses some undefined behavior (such as a stack overflow), you can blame the author for having made that error, but in practice, if you want to know if your error is exploitable by others, or how to exploit it, you must understand exactly what your program does - this can be done by examining the machine code the compiler generated, and that also has very precise semantics.

>>1
Most small overflows won't cause crashes as a typical ``crash'' is an unhandled exception or signal such as an "memory access violation" or "segmentation fault" which means you've tried to access a page of memory which is not allocated, and usually the stack's memory is allocated in bulk, so an overflow isn't typically fatal, and in some OSes, stacks are growable (this tends to be done by allocating a page where the stack is supposed to grow and setting the memory's protection flags in such a way as to cause an exception or segfault to be generated, which a handler installed by the OS or compiler (depends on implementation again) will then unprotect, allocate some some more memory and set new flags, then seamlessly continue your program like nothing happened at all), which means you would have to keep growing the stack for quite some time until a stack overflow would actually occur (until one reaches a limit imposed by the OS or compiler, usually such a limit is changable).

Name: Anonymous 2012-01-16 17:42

>>18

Exactly. Thank you for your kind and precise observation, even if it was directed to a troll.

And yes, the behavior can change if different compiler settings are used.

To illustrate that using GCC, just compile the program with -O3 and you'll see that the control flow analysis has decided that f() does nothing, thus removing the call to it. The result is simply an empty program.

Name: Anonymous 2012-01-16 17:45

>>19
Again, how am I a troll, or is that just a label you give everyone who says something that you don't understand?

Name: Anonymous 2012-01-16 17:46

>>11
>>18

thank you

Name: Anonymous 2012-01-16 17:57

>>18
You have the C standard and within that, the behavior his program will have is undefined, however while that wouldn't be conforming C, it doesn't mean it doesn't have very precise semantics when using a specific compiler with specific settings on a specific architecture - you can almost always determine them when you have fully specified the environment, and when you can determine them, undefined behavior will be fully defined.
What if the compiler has non-deterministic behavior? What if the compiler has a setting like "optimize for 30 seconds" which depends not only on the compiler but also the speed of the machine, the total amount of load on the system, disk swapping and other non-controllable factors?

Name: kodak_gallery_programmer !!kCq+A64Losi56ze 2012-01-16 18:15

>>22
"Undefined Behavior" in ANSI/ISO terms is what is known as a "Semantic Error". What that means is that the implementation is free to do anything it wants. In other words, undefined behavior is defined by the implementor and not the standard itself.

Name: kodak_gallery_programmer !!kCq+A64Losi56ze 2012-01-16 18:18

>>23
Also, before I forget, undefined behavior isn't the same as non-deterministic behavior. The latter can be (kind of) solved by the C preprocessor itself.

Name: Anonymous 2012-01-16 18:20

>>22
What if the compiler has non-deterministic behavior? What if the compiler has a setting like "optimize for 30 seconds" which depends not only on the compiler but also the speed of the machine, the total amount of load on the system, disk swapping and other non-controllable factors?See:
you can almost always determine them when you have fully specified the environmentHowever, to be fair, determining them by fully understanding the compiler is a bit of a pain, and in some cases it would be literally impossible(let's say you decide to defeat my argument by using a "true random" quantum RNG), the typical way one determines what the behavior is, is by examining the assembly listing generated by the compiler or just disassembling the compiled program - it would be a lot less work than mentally following the same steps a compiler would have to.

Name: Anonymous 2012-01-16 18:21

However, to be fair, determining them by fully understanding the compiler is a bit of a pain, and in some cases it would be literally impossible(let's say you decide to defeat my argument by using a "true random" quantum RNG), the typical way one determines what the behavior is, is by examining the assembly listing generated by the compiler or just disassembling the compiled program - it would be a lot less work than mentally following the same steps a compiler would have to.
How do you know the compiler produces the same program every time? Remember that the implementation is free to do whatever it wants with undefined behavior.

Name: Anonymous 2012-01-16 18:24

>>25
You have zero clue as to what your talking about. Let me quote the previous responses you idiot...

>>23
"Undefined Behavior" in ANSI/ISO terms is what is known as a "Semantic Error". What that means is that the implementation is free to do anything it wants. In other words, undefined behavior is defined by the implementor and not the standard itself. "

And

>>24
"Also, before I forget, undefined behavior isn't the same as non-deterministic behavior. The latter can be (kind of) solved by the C preprocessor itself. "

Name: Anonymous 2012-01-16 18:26

>>26
How do you know the compiler produces the same program every time? Remember that the implementation is free to do whatever it wants with undefined behavior.

The C compiler might generate a different program everytime. However, if the program is conforming, then the C standard itself guarantess that the program will produce the same output everytime.

Name: Anonymous 2012-01-16 18:30

>>28
Yes but I believe the person I quoted believed that specifying an environment would help defining an undefined program as he could look at the assembly output, I was arguing against that.

Name: Anonymous 2012-01-16 18:33

>>29
It won't. With that, I think you need to learn the fundamental difference between the implementation and the C Abstract Machine before you start answering any questions related to the standard.

Name: Anonymous 2012-01-16 18:34

>>30
Again, I never said it did, I specifically argued against it.

Name: Anonymous 2012-01-16 18:34

>>30
And the only reason I say that is because your responses are misleading.

Name: Anonymous 2012-01-16 18:38

>>32
What's unclear exactly?

He stated that you might look at the assembly output of a compiler to tell what a program as defined by the C code is doing, especially that you were able to do so in the face of undefined behavior in the C code so that undefined behavior might become "defined" by the implementation.

I said that isn't possible since the compiler might not produce the same assembly output every time.

Name: Anonymous 2012-01-16 18:41

>>33
No, the guy that works at Kodak said the compiler might produce not produce the same output assembly everytime.

Name: Anonymous 2012-01-16 18:42

>>34
I said it as well in >>26.

Name: Anonymous 2012-01-16 18:43

Look at response >>28. He clearly said that before you clued in. Now stop projecting you fucking douche

Name: Anonymous 2012-01-16 18:52

>>28
In that case, you can only judge the generated binary.
People don't actually compile the same program each time they run it.
You've won this argument, and I will say that your argument can extended like this: Just have the compiler terminate on any undefined behavior, thus it will generate no output.

This of course has little importance to the real world question that >>1 was asking about, since compilers are rarely that fickle things. As for >>12's example, it would still be defined ``in practice'' for most compilers/implementations when specified - it's true that you could make a compiler which might generate random binaries at runtime, or not generate anything, or generate different things depending on the environment, but in practice this is rare - most of the time, when someone is writing some piece of code which is undefined by the standard, but defined by the implementation (with some specific settings), in some cases it's possible to rely on what it can do. The example of accessing the stack's boundries randomly by indexing into some stack-allocated array (for a compiler which uses a stack) is actually not that unusual: it's behavior that even compiler/implementation developers depend in their own implementations of variable argument accessing code, among a few other uses. (Obviously the semantics of this would be completly different in an implementation that doesn't use a stack or an interpreter or ...)

Name: Anonymous 2012-01-16 18:58

I would rather specify GNU-C and use __builtin_frame_address.

Name: Anonymous 2012-01-16 19:00

In that case, you can only judge the generated binary.

That's incorrect. You'd judge the assembly.

Name: kodak_gallery_programmer !!HfslGqyCdtdPesq 2012-01-16 19:05

have the compiler terminate on any undefined behavior, thus it will generate no output.

Let's say I have something like the following..

#include <stdio.h>

int main(void)
{
  (void)printf("Hello");
  return 0;
}

This program has undefined behavior. How do you propose that I have the program terminate in this case?

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List