What is the simplest standard conform way to produce a Segfault in C?

后端 未结 10 1629
迷失自我
迷失自我 2020-11-29 21:59

I think the question says it all. An example covering most standards from C89 to C11 would be helpful. I though of this one, but I guess it is just undefined behaviour:

10条回答
  •  执念已碎
    2020-11-29 22:27

     main;
    

    That's it.

    Really.

    Essentially, what this does is it defines main as a variable. In C, variables and functions are both symbols -- pointers in memory, so the compiler does not distinguish them, and this code does not throw an error.

    However, the problem rests in how the system runs executables. In a nutshell, the C standard requires that all C executables have an environment-preparing entrypoint built into them, which basically boils down to "call main".

    In this particular case, however, main is a variable, so it is placed in a non-executable section of memory called .bss, intended for variables (as opposed to .text for the code). Trying to execute code in .bss violates its specific segmentation, so the system throws a segmentation fault.

    To illustrate, here's (part of) an objdump of the resulting file:

    # (unimportant)
    
    Disassembly of section .text:
    
    0000000000001020 <_start>:
        1020:   f3 0f 1e fa             endbr64 
        1024:   31 ed                   xor    %ebp,%ebp
        1026:   49 89 d1                mov    %rdx,%r9
        1029:   5e                      pop    %rsi
        102a:   48 89 e2                mov    %rsp,%rdx
        102d:   48 83 e4 f0             and    $0xfffffffffffffff0,%rsp
        1031:   50                      push   %rax
        1032:   54                      push   %rsp
        1033:   4c 8d 05 56 01 00 00    lea    0x156(%rip),%r8        # 1190 <__libc_csu_fini>
        103a:   48 8d 0d df 00 00 00    lea    0xdf(%rip),%rcx        # 1120 <__libc_csu_init>
    
        # This is where the program should call main
        1041:   48 8d 3d e4 2f 00 00    lea    0x2fe4(%rip),%rdi      # 402c 
    1048: ff 15 92 2f 00 00 callq *0x2f92(%rip) # 3fe0 <__libc_start_main@GLIBC_2.2.5> 104e: f4 hlt 104f: 90 nop # (nice things we still don't care about) Disassembly of section .data: 0000000000004018 <__data_start>: ... 0000000000004020 <__dso_handle>: 4020: 20 40 00 and %al,0x0(%rax) 4023: 00 00 add %al,(%rax) 4025: 00 00 add %al,(%rax) ... Disassembly of section .bss: 0000000000004028 <__bss_start>: 4028: 00 00 add %al,(%rax) ... # main is in .bss (variables) instead of .text (code) 000000000000402c
    : 402c: 00 00 add %al,(%rax) ... # aaand that's it!

    PS: This won't work if you compile to a flat executable. Instead, you will cause undefined behaviour.

提交回复
热议问题