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

Code explanation

Name: Anonymous 2012-01-11 12:49

Can somebody explain why this code outputs what it does?

// tested with Core 2 Duo, Core 2 Quad and Xeon
// tested with gcc4.1.2 gcc4.4.3 and gcc4.6.1
// compile with: gcc -O0 -m32
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <setjmp.h>

jmp_buf p;
void (*q)();

const char *data =
    "\x8b\x44\x24\x04\x8b\x5c\x24\x08"
    "\x8b\x00\x8b\x1b\x31\xc3\x31\xd8"
    "\x31\xc3\x8b\x4c\x24\x04\x89\x01"
    "\x8b\x4c\x24\x08\x89\x19\xc3\x90"
    "\x55\x89\xe5\x8b\x45\x04\xc9\xc3"
    "\x55\x90\x90\x89\xe5\x90\x90\x90"
    "\x8b\x45\x08\x89\x45\x04\xc9\xc3"
    "\x60\x09\x0e\x13\x14\x01\x0c\x0c"
    "\xc0\x07\x05\x0e\x14\x0f\x0f\x60"
    "\x00\x67\x6f\x74\x6f\x20\x63\x6f"
    "\x6e\x73\x69\x64\x65\x72\x65\x64"
    "\x20\x68\x61\x72\x6d\x66\x75\x6c"
    "\x6c\x00\x90\x90\x1c\x1b\x0a\x20";

int f(int x)
{
    static int b = 0; static int s = 0;
    int a = 0, t;
    if (!s) {
        a = b; b = x;
    } else {
        a = x; t = b;
        do {
            a ^= b;
            b = (a^b) & b;
            b <<= 1;
        } while (b);
        b = t;
    }
    s = (s+1) % 2;
    return a;
}

int g(int i, int *j)
{
    *j = i;
    i = (int) putchar;
    if (*j == (48 << 1)) 
        __asm volatile (
                "movl 8(%ebp),%eax;"
                "leave;"
                "ret"
                );
    return (int) puts;
}

void h(int i)
{
    int b;
    q = (void(*)()) g(i++[data],&b);
    for (f(b);*(data+i)!=b;++i,f(b))
        q(f(i[data])%0xff);
}

void sh(int s)
{
    if (s == 010)
        ((void(*)())g(s,&s))("F");
    longjmp(p,s);
}

int main(void)
{
    int base, addr = 0xffffffff, offs = 16;
    int a = 11, b = 32, i = 25;
    int s = 8, t = 1, u = 4;
    ((void(*)()) data)(&a,&b);
    ((void(*)()) data)(&b,&t);
    ((void(*)()) data)(&t,&s);
    addr ^= a;
       a ^= addr;
    addr ^= a;
    base = ((int(*)())data+addr)();
    if (a == -1)
        goto over;
    puts("A");

    base = (1<<3) | ((f(addr) + f(offs)) & ~0xff);
    h(base+addr+offs);
    exit(0);

over:
    signal(t,sh);signal(s,sh);signal(u,sh);

    if (!(s = setjmp(p))) {
        q = (void(*)()) g(0x30, &a);
        q(data + a + i);
        s = a / (b-1);
        puts("B");
    } else if (s == 0xb) {
        puts("C");
        ((int(*)(int)) data+addr+(offs/2))(base);
    } else {
        puts("D");
        *((int*) base+s) = 0xffffffff;
    }
   
    puts("E");
    return 1;
}

Name: Anonymous 2012-01-12 9:37

>>239
[quote]I stated that the use of __asm to alter the stack causes undefined behavior, I also stated that usage of longjmp in a manner defined by the C standard does not yield undefined behavior.[/quote]

That is contradicting since the implementation of longjmp on my machine most certainly uses __asm__ to alter the stack.

Name: Anonymous 2012-01-12 9:38

>>240
BUT SO DOES LONGJMP

Name: Anonymous 2012-01-12 9:42

>>242
longjmp has no concept of the stack, read the standard.

Name: Anonymous 2012-01-12 9:45

>>243
standard schmandard

The implementation of setjmp and longjmp clearly does.

Name: Anonymous 2012-01-12 9:46

>>241
Under the assumptions that longjmp on your machine is implemented using __asm__ in GCC I will agree that logic dictates that the __asm__ that is used to implement longjmp is well defined on your machine as long as it is only used exactly like longjmp is defined to work in the standard, any other usage is still undefined.

Name: Anonymous 2012-01-12 9:47

>>244
The implementation of setjmp and longjmp clearly does.
That is nonsensical, what if I have an architecture without a stack?

>>241,245
By the way I would very much like to see the implementation of longjmp on your machine.

Name: 246 2012-01-12 9:50

I am going to go away now as I have obligations, I will probably be back in a couple of hours and I'd be happy to continue our debate.

Name: Anonymous 2012-01-12 9:52

>>246
| That is nonsensical, what if I have an architecture without a stack?
On the architectures proposed by OP, silly.

The definition itself is: longjmp, siglongjmp - nonlocal jump to a saved stack context

Name: Anonymous 2012-01-12 9:56

>>248
Your edition of the standard seems to be erroneous, on mine it says setjmp - saves the calling environment, longjmp - restores calling environment while siglongjmp is not defined and I can't find it in C89, C99 or C11.

Name: not >>246 2012-01-12 9:58

>>248
The definition itself is: longjmp, siglongjmp - nonlocal jump to a saved stack context
    setjmp - set jump point for a non-local goto
    longjmp - non-local goto
I don't see any ``stack'' here.

Name: Anonymous 2012-01-12 10:04


$ man longjmp > bla.txt
$ cat bla.txt
LONGJMP(3)                                               Linux Programmer's Manual                                              LONGJMP(3)



NAME
       longjmp, siglongjmp - nonlocal jump to a saved stack context

SYNOPSIS
       #include <setjmp.h>

       void longjmp(jmp_buf env, int val);

       void siglongjmp(sigjmp_buf env, int val);

   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

       siglongjmp(): _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_C_SOURCE

DESCRIPTION
       longjmp()  and  setjmp(3)  are  useful  for  dealing with errors and interrupts encountered in a low-level subroutine of a program.
       longjmp() restores the environment saved by the last call of setjmp(3) with the corresponding env  argument.   After  longjmp()  is
       completed, program execution continues as if the corresponding call of setjmp(3) had just returned the value val.  longjmp() cannot
       cause 0 to be returned.  If longjmp() is invoked with a second argument of 0, 1 will be returned instead.

       siglongjmp() is similar to longjmp() except for the type of its env argument.  If, and only if, the sigsetjmp(3) call that set this
       env used a nonzero savesigs flag, siglongjmp() also restores the signal mask that was saved by sigsetjmp(3).

RETURN VALUE
       These functions never return.

CONFORMING TO
       C89, C99, and POSIX.1-2001 specify longjmp().  POSIX.1-2001 specifies siglongjmp().

NOTES
       POSIX  does  not  specify  whether longjmp() will restore the signal context (see setjmp(3) for some more details).  If you want to
       portably save and restore signal masks, use sigsetjmp() and siglongjmp().

       The values of automatic variables are unspecified after a call to longjmp() if they meet all the following criteria:

       ·  they are local to the function that made the corresponding setjmp(3) call;

       ·  their values are changed between the calls to setjmp(3) and longjmp(); and

       ·  they are not declared as volatile.

       Analogous remarks apply for siglongjmp().

       longjmp() and siglongjmp() make programs hard to understand and maintain.  If possible an alternative should be used.

SEE ALSO
       setjmp(3), sigsetjmp(3)

COLOPHON
       This page is part of release 3.27 of the Linux man-pages project.  A description of the project, and  information  about  reporting
       bugs, can be found at http://www.kernel.org/doc/man-pages/.



                                                                2009-01-13                                                      LONGJMP(3)

Name: Anonymous 2012-01-12 10:06

>>251
Of course, it's not "the standard".

Name: Anonymous 2012-01-12 10:10

>>251
Linux Programmer's Manual

[b][i][o]
LINUX IS NOT THE STANDARD
[/b][/i][/o]

Name: Anonymous 2012-01-12 10:10

>>251-252
the man pages are implementation details

Name: Anonymous 2012-01-12 10:15

>>254
Yes, but wasn't that the point? If the implementation of longjmp alters the stack than that would inherently be considered undefined.

Name: Anonymous 2012-01-12 10:16

>>254
FOR LINUX

Name: Anonymous 2012-01-12 10:17

>>256
Which doesn't contradict OP

Name: Anonymous 2012-01-12 10:20

>>254
That was my point.

Name: Anonymous 2012-01-12 10:38

>>117
You didn't really use -m32 there, did you

Name: Anonymous 2012-01-12 10:46

>>259
It was a troll obviously.

Name: Anonymous 2012-01-12 10:47

Aaand thread of the year award goes to this thread.

Guys, you can stop posting now. All of you. It's ok.

Name: Anonymous 2012-01-12 11:02

>>255
He explicitly stated that wasn't what he said and that it's untrue if you read >>239,245. You're being willfully ignorant about it, I'm not going bother to argue with you like he does, I would never have the patience to it, but I'm going to tell you that you're acting like a child.

Name: Anonymous 2012-01-12 11:04

By the way the program is undefined so the output is undefined.

Name: Anonymous 2012-01-12 11:14

>>263
You just keep on telling yourself that.

Name: Anonymous 2012-01-12 11:15

>>238
The preprocessor doesn't do anything to __asm, __asm__ or asm, do you even know what the preprocessor is?
And you have yet to show where __asm is defined as the doc linked to in >>100 doesn't even mention it.

Name: Anonymous 2012-01-12 11:17

>>264
Where is __asm defined then you fucking retard? What happens when you convert between data pointers and function pointers then you fucking retard? What happens when you do arithmetic with function pointers then you fucking retard?

Name: Anonymous 2012-01-12 11:20

>>262
You're missing the point. The point is that setjmp does in fact alter the stack by pushing registers, flags and calling environment and longjmp pushes that data from the stack, alters the return address and jumps.

Name: Anonymous 2012-01-12 11:22

>>266
What happens when you do arithmetic with function pointers then you fucking retard?

hurr durr pointer arithmetics are undefined behaviour

Name: /prog/ police !1fOeGamQwA!PrM413+Y2UUOlKE 2012-01-12 11:24

/g/ quality thread.

Name: Anonymous 2012-01-12 11:26

>>268
This is true in the case of void pointers and function pointers you dumb Jew. Fuck off back to /g/ until you have at least read one of the fucking standards you dumb piece of shit.

Name: Anonymous 2012-01-12 11:28

ITT
| Can somebody explain why this code outputs what it does?
| hurf durf show your ePenis somewhere else, it's undefined go fuck yourself nerf

Name: Anonymous 2012-01-12 11:28

>>267
There are safe constructs that alter the stack you dumb piece of shit, have you ever of "return" you god damned retard? longjmp is another way of safely altering the stack. Altering it from asm is unsafe and it says so at the fucking GCC page, what kind of mental disability do you have because you must have negative IQ or something.

Name: Anonymous 2012-01-12 11:31

>>271
The original question was answered in the first couple of posts, it either outputs Segmentation fault, the output >>142 or doesn't compile at all. Why you ask? Because it's undefined.

Name: Anonymous 2012-01-12 11:31

>>270
| This is true in the case of void pointers and function pointers
Can't into array of function pointers.

Name: Anonymous 2012-01-12 11:32

>>272
HOW DO YOU THINK LONGJMP IS IMPLEMENTED, fucking moron...

Name: Anonymous 2012-01-12 11:33

>>274
Read the standard you dumb piece of shit.

Name: Anonymous 2012-01-12 11:36

>>275
I think it's implemented safely unlike the fucking retarded shit that's posted in >>1, are you seriously this fucking dense? Why would the GCC manuals explicitly state that it's bad and dangerous to alter the stack through asm? Because your monkey ass is so fucking dumb that you might do something retarded like what was posted in >>1. And please you fucking retard, show us the source code of longjmp and setjmp on your system you dumb piece of shit, come up with some fucking evidence before you talk again.

Name: Anonymous 2012-01-12 11:41

>>277
Bad and dangerous != undefined behaviour

Name: Anonymous 2012-01-12 11:43

>>276
Not that guy, but an array of function pointers aren't non-standard...

Name: /V\3|\|T4|_ /V\1|)G3T 2012-01-12 11:48

>>277
LMAO U GAY AND JELY RUN THIS PICE OF CODE U ASSMASETR DIS CODE IS 100% SAFE BUT MUST COMPILE WITH -m32 KAY???+

#include <stdio.h>

int main (void) {
  int a = 2;
  int b = 3;
  int c = 5;

  asm("add 8(%ebp), %esp");

  printf("%d\n", b);

  return 0;
}

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