carpenter
carpenter

Reputation: 33

Why Linux does not crash but output an random string?

char* getChar()
{
    //char* pStr = "TEST!!!";
    char str[10] = "TEST!!!";
    return str;
}
int main(int argc, char *argv[])
{
    double *XX[2];

    printf("STR is %s.\n", getChar());
    return (0);
}

I know a temporary variable in a stack SHOULD not be returned.

Actually it will output a undecided string.

When does Linux crash except NULL-Pointer-Reference?

Upvotes: 1

Views: 111

Answers (2)

You've got some undefined behavior. Read also this answer to have an idea of what that could mean.

If you wish an explanation, you need to dive into implementation specific details. Here it goes....

This carp.c file (very similar to yours, I renamed getChar to carp and included <stdio.h>)

 #include <stdio.h>
 char *carp() {
   char str[10] = "TEST!!!";
   return str;
 }
 int main(int argc, char**argv)
 {
   printf("STR is %s.\n", carp());
   return 0;
 }    

is compiled by gcc -O -fverbose-asm -S carp.c into a good warning

carp.c: In function 'carp':
carp.c:4:8: warning: function returns address of local variable [-Wreturn-local-addr]
      return str;
      ^

and into this assembler code (GCC 4.9.1 on Debian/Sid/x86-64)

    .text
.Ltext0:
        .globl  carp
        .type   carp, @function
carp:
.LFB11:
        .file 1 "carp.c"
        .loc 1 2 0
        .cfi_startproc
        .loc 1 5 0
        leaq    -16(%rsp), %rax #, tmp85
        ret
        .cfi_endproc
.LFE11:
        .size   carp, .-carp
        .section        .rodata.str1.1,"aMS",@progbits,1
.LC0:
        .string "STR is %s.\n"
        .text
        .globl  main
        .type   main, @function
main:
.LFB12:
        .loc 1 7 0
        .cfi_startproc
.LVL0:
        subq    $24, %rsp       #,
        .cfi_def_cfa_offset 32
        .loc 1 8 0
        movq    %rsp, %rsi      #,
.LVL1:
        movl    $.LC0, %edi     #,
.LVL2:
        movl    $0, %eax        #,
        call    printf  #
.LVL3:
        .loc 1 10 0
        movl    $0, %eax        #,
        addq    $24, %rsp       #,
        .cfi_def_cfa_offset 8
        ret
        .cfi_endproc
.LFE12:
        .size   main, .-main

As you notice, the bad carp function is returning the stack pointer minus 16 bytes. And main would print what happens to be there. And what happens to be at that location probably depends upon a lot of factors (your environment environ(7), the ASLR used for the stack, etc....). If you are interested in understanding what exactly is the memory (and address space) at entry into main, dive into execve(2), ld.so(8), your compiler's crt0, your kernel's source code, your dynamic linker source code, your libc source code, the x86-64 ABI, etc.... My life is too short to take many hours to explain all of this.

BTW, notice that the initialization of local str to "TEST!!!" has been rightly optimized out by my compiler.

Read also signal(7): your process can be terminated in many cases (I won't call that "Linux crashing" like you do), e.g. when dereferencing a pointer out of its address space in virtual memory (see also this), executing a bad machine code, etc...

Upvotes: 5

Scott Hunter
Scott Hunter

Reputation: 49803

It didn't crash because you got lucky; since you have no way of knowing just how long this string that gets printed is, you have no idea what parts of memory it will venture into.

Upvotes: 2

Related Questions