118
\$\begingroup\$

Write the shortest code that raises a Segmentation Fault (SIGSEGV) in any programming language.

\$\endgroup\$
2
  • 52
    \$\begingroup\$ Wow. Possibly the shortest successful question. \$\endgroup\$ Commented Feb 9, 2017 at 11:42
  • 6
    \$\begingroup\$ @MatthewRoh Out of interest, I made this SEDE query. It looks like there are a few with +10 or higher, but this is the first above +40 \$\endgroup\$
    – rydwolf
    Commented Nov 21, 2020 at 20:38

85 Answers 85

1 2
3
2
\$\begingroup\$

AArch64, 4 bytes

Raw machine code:

d65f03e0

Disassembly

        .globl f
f:
        ret     xzr

Branches to the xzr register, which is always null. We can't do something like str x0, [xzr] because it would be treated as sp.

\$\endgroup\$
2
\$\begingroup\$

F95, 27 bytes

program a;pointer p;p=0;end

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ Could you provide a link to the language, and preferably a link to someone other users can run your code, such as TryItOnline!? \$\endgroup\$ Commented Dec 25, 2020 at 21:18
  • \$\begingroup\$ It works with GFortran, here’s 17 bytes \$\endgroup\$
    – roblogic
    Commented Dec 26, 2020 at 22:00
2
\$\begingroup\$

pbrain, 1 byte

(

Try it online!

This is due to an unchecked error in the interpreter:

// Interpret a container of instructions
template<typename It> void interpret(It ii, It eos)
{
   while (ii != eos) {
      switch (*ii) {
         // Snip
         case '(':
            ++ii;

            {
               SourceBlock sourceBlock;

               while (ii != eos && *ii != ')') {
                  sourceBlock.push_back(*ii);
                  ++ii;
               }

               // BUG: eos is not handled here, and when ii is incremented below,
               // it is GREATER than eos, not triggering the loop condition,
               // which is if ii is EQUAL to eos, and causing an out of bounds read.
               //
               // It should be this:
               //   if (ii == eos) {
               //       throw 5; // raise error in the interpreter
               //   }

               procedures.insert(std::make_pair(mem[mp], sourceBlock));
            }

            break;
     }
     // Snip
     ++ii;
   }
}

For a version which doesn't rely on an implementation bug, behold, the world's least interesting segfault: the stack overflow from recursing too much.

(:):

It does exactly as you might expect, it defines a function and then calls itself recursively.

\$\endgroup\$
2
\$\begingroup\$

Python, 53 characters

class A:__lt__=lambda s,o:o.clear()or s
vars(A)>A()<0

This is a bit longer than some other solutions, but unlike some other solutions it

  1. works in modern python versions (tested in 3.7.17, 3.8.17, 3.9.17, 3.10.12, 3.11.8 and 3.12.2)
  2. doesn't look like it does anything dangerous/suspicious/illegal at first glance
  3. showcases an actual interpreter crash rather than just explicitly dereferencing null/execing invalid code/etc

Btw, don't report this upstream, this issue is already known and closed as "wontfix" in CPython: https://github.com/python/cpython/issues/88004

Explanation:

The important part is essentially

class A:
    def __lt__(self, other):
        other.clear()

AnyClass.__dict__ > A()

AnyClass can be any class (A in the short version) and vars(A) is a shorthand for A.__dict__.

The issue here is that the class __dict__ property is supposed to be of type mappingproxy that is implemented as thin wrapper around regular dicts. This special type is supposed to make this dictionary immutable/read-only:

AnyClass.__dict__["foo"] = 0 # TypeError: 'mappingproxy' object does not support item assignment
del AnyClass.__dict__["foo"] # TypeError: 'mappingproxy' object does not support item deletion
AnyClass.__dict__.clear()    # AttributeError: 'mappingproxy' object has no attribute 'clear'

However, it's possible to circumvent this protection using python's data model. Specifically, mappingproxy doesn't reimplement all of the required methods itself, but instead just delegates to the underlying dict implementation.

So, when we do AnyClass.__dict__ > A() the following happens:

  1. m = AnyClass.__dict__ is of type mappingproxy

    a = A() is of type A

  2. we try to execute m > a or m.__gt__(a)

    mappingproxy doesn't implement __gt__, so it delegates this call to dict

    this essentially does something similar to

    # except this isn't a real property so it isn't accessible from pure python
    d = m.__internal_reference_to_underlying_dict
    return d.__gt__(a)
    

    where d is the actual underlying storage of type dict, not the safe/immutable/read-only mappingproxy wrapper

  3. we try to execute d.__gt__(a)

    dict does implement __gt__, but it doesn't know what to do with our custom type A, so it returns the special NotImplemented value

    python's data model says that when x.__gt__(y) (x > y) returns NotImplemented, you should try the swapped version y.__lt__(x) (y < x) before failing

  4. we try to execute a.__lt__(d)

    our custom class A does have an implementation for __lt__ that calls clear() on the "other" object, in this case - d

So with this, we were able to call clear() on the underlying storage for the class __dict__ that was supposed to be made immutable by exposing it through a mappingproxy. This breaks some core assumptions that python heavily relies on. After that, it's pretty easy to cause a SEGFAULT by attempting to interact with an instance of AnyClass (or A in the minified version).

The use of __lt__ and > here is not mandatory, this also works with any other paired binary operator (eq/ne, add/radd, sub/rsub, mul/rmul, etc).

\$\endgroup\$
1
\$\begingroup\$

Battlestar, 3 characters

ret

Test

 $ echo ret > main.bts
 $ bts main.bts
 (segfaults)
\$\endgroup\$
1
\$\begingroup\$

TI-BASIC, 5 bytes

Archive A:A

Archives the variable A and then tries to get the value of A.
Throws the ERR:ARCHIVED error when used.

This is the closest thing you'd get to a segmentation fault in TI-BASIC, since archived data cannot be accessed directly.

In other words, the software has attempted to access a restricted area of memory.


Note: TI-BASIC is a tokenized language. Character count does not equal byte count.

\$\endgroup\$
4
  • \$\begingroup\$ It's not a segmentation fault. \$\endgroup\$ Commented Jun 11, 2020 at 14:45
  • \$\begingroup\$ @Sapphire_Brick It most definitely is. "A segmentation fault occurs when a program attempts to access a memory location that it is not allowed to access, or attempts to access a memory location in a way that is not allowed (for example, attempting to write to a read-only location, or to overwrite part of the operating system)." (source) Archived data can't be accessed in TI-BASIC, simple as that. Do your research before commenting next time. \$\endgroup\$ Commented Jun 17, 2020 at 0:53
  • \$\begingroup\$ You seem to be saying "Fish can swim; I can swim, so I am a fish.". A segmentation fault is more specific than the definition you gave. It has to be the signal SIGSEGV, not just any memory permission error. Suppose you try to use a bash command that you don't have permission to use. Is that a segmentation fault? Of course not. \$\endgroup\$ Commented Jun 17, 2020 at 1:06
  • \$\begingroup\$ Fair enough. Though, you could've explained that in a way without trying to use a strawman like "Fish can swim; I can swim, so I am a fish." \$\endgroup\$ Commented Jun 17, 2020 at 3:13
1
\$\begingroup\$

Io, 25 bytes

Recursively executing the current file raises a segmentation fault. (You know, the system running Io obviously doesn't implement tail-call optimization.)

doFile(System args at(0))

Try it online!

\$\endgroup\$
1
\$\begingroup\$

C++, 19 bytes.

int main(){main();}

Not very interesting, just stack overflow. (pun not intended)

\$\endgroup\$
1
\$\begingroup\$

Swift 5, 29 characters:

func x(){y()}
let y={x()}
x()
\$\endgroup\$
1
  • \$\begingroup\$ 25 bytes \$\endgroup\$
    – Bbrk24
    Commented Jul 18, 2023 at 18:31
1
\$\begingroup\$

Go, 29 characters

package x;func x(y*int){*y=4}
\$\endgroup\$
1
\$\begingroup\$

x86 assembly (intel syntax), 12 chars

lgdt [0x123]

How it works

You force the cpu to load a GDT table at a random address(0x123 in this case) , and of course it'll segfault. And if that location is actually a valid gdt, you should still trigger a GPF. Also, this might triple fault if you use it on msdos.

\$\endgroup\$
1
\$\begingroup\$

Nim, 20 bytes

cast[ptr int](4)[]=2

Try it online!

Nim, 20 bytes

proc x()=x();x()
x()

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Braille (reference interpreter bug), 9 bytes (3 UTF-8 chars)

⢽⢽⢹

Try it online!

⢽ data_pointer += 32768
⢽ data_pointer += 32768
⢹ data_pointer[15] += shared_storage

The Braille interpreter does not correctly handle memory allocation.

Specifically, it will only allocate the power of two larger than the program size in Braille opcodes. This supposed data pointer does not have much to work with.

Specifically, this program would allocate 4 bytes of memory. Technically, just one opcode () is enough to write out of bounds (since it is writing 15 bytes past a buffer that is 2 bytes large), but that sadly isn't enough to create a segfault. At least not on TIO.

This code will advance the data pointer 65536 bytes forward, then write to 15 bytes past that.

Since this is outside a 64 KB page boundary, it segfaults.

\$\endgroup\$
1
\$\begingroup\$

Bitwise, interpreter bug, 2 bytes

SL

Try it online!

Hooray for input validation.

SL expects 3 arguments, but I give it zero.

    for (line = 0; line < lines; line++) {
        char *t = strdup(s[line]);
        char *cmd = strtok(t," ");
        char *arg1 = strtok(NULL," ");
        char *arg2 = strtok(NULL," ");
        char *arg3 = strtok(NULL," ");

        //printf("%s %s %s %s\n",cmd,arg1,arg2,arg3);

        exec_cmd(cmd,arg1,arg2,arg3);

        free(t);
    }

strtok returns a null pointer since I don't supply the expected arguments, and when it dereferences it, it segfaults.

A rough fix:

int _register(char *index)
{
    if (index == NULL) {
        fprintf(stderr, "missing argument\n");
        exit(1);
    }
    // ...

Note: this also allows you to go past the tape bounds, but the state is a global variable so it isn't very useful for my ACE challenge.

\$\endgroup\$
1
\$\begingroup\$

Erlang 33

os:cmd("kill -11 "++os:getpid()).

You can invoke like

erl -eval 'os:cmd("kill -11 "++os:getpid()).'
\$\endgroup\$
1
\$\begingroup\$

Pascal (FPC), 54 bytes

function _(x:int8):int8;begin _(0);end;begin _(0);end.

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ Free Pascal will not do any tail call optimize. So you may use procedure without parameter instead of a function: procedure _;begin _ end;begin _ end. would work the same. \$\endgroup\$
    – tsh
    Commented Sep 28, 2021 at 9:14
1
\$\begingroup\$

MMIX, 8 bytes (2 instrs)

00000000: e0fffef5 a5a4ff00                    ṭ”“ṫʠƥ”¡
sflt    SETH $255,#FEF5
        STW  $164,$255

Attempting to do anything with any data at a negative address causes a segfault unless you're the OS. I picked trying to store two bytes to a mem-mapped IO device so it'd look cool with jxd.

\$\endgroup\$
1
\$\begingroup\$

Knight (C/golf), 0 bytes

Not that I would call this interpreter golfed...

A program that is empty (or all whitespace) segfaults.

If it is read from an empty file, getdelim() stores NULL into stream... (line 236)

    else getdelim(&stream,&size,'\0',fopen(argv[2],"r"));

And when the program does an initial scan for non-whitespace... (line 33)

    while(strspn(stream, "\t\n\f\r {}[]():#")) {

...it dereferences a NULL pointer.

Otherwise, it will increment the stream pointer (line 54)...

    ++stream;

...recurse into parse() ((line 68)

    func[1] = parse();

and give that same strspn() an out of bounds pointer (it might take a few recursions to hit a page fault).

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ Ok but that's kinda the point. It's only well defined for valid inputs and everything else is irrelevent ;p \$\endgroup\$
    – Sampersand
    Commented Jun 17, 2021 at 2:25
  • \$\begingroup\$ Never said it wasn't. There are actually a lot of interpreters like this. \$\endgroup\$
    – EasyasPi
    Commented Jun 17, 2021 at 2:28
1
\$\begingroup\$

Java 17 (OpenJDK), 180 177 172 bytes

import sun.misc.*;interface A{static void main(String[]a)throws Throwable{var f=Unsafe.class.getDeclaredFields()[0];f.setAccessible(true);((Unsafe)f.get(null)).getInt(0);}}

This may be JVM dependent, but I think this is the most compact way to do it.

Some strategies used:

  • An interface is used to get rid of the public modifier on the main function
  • A space isn't necessary between the array brackets and the variable name a
  • Throwable is more compact than the full name of the exception that could be thrown
  • var is used (Java 10 and up) instead of Field, also gets rid of an import
  • A direct array access to the declared fields is used (JVM dependent), for hotspot the main Unsafe instance is the first field in the class
  • getInt(0) is used because I'm pretty sure it has the lowest profile of any method that could cause a segfault in Unsafe
  • A wildcard import can be used rather than the explicit type name to cut down on text
\$\endgroup\$
1
\$\begingroup\$

Assembly (MIPS, SPIM), interpreter bug, 15 14 bytes

main:sb$0 f
f:

Try it online!

Here's a cute one I found by accident.

This attempts to store a byte to the address at label f. This is in the .text section.

SPIM is pretty clever in that writing out of bounds of a section will just grow the section. However, writing to .text is tricky.

SPIM stores instructions in a struct for easier parsing it and debugging, instead of just storing data directly.

CPU/inst.h:57:

/* Representation of an instruction. Store the instruction fields in an
   overlapping manner similar to the real encoding (but not identical, to
   speed decoding in C code, as opposed to hardware).. */

typedef struct inst_s
{
  short opcode;

  union
    {
      // Snip
    } r_t;

  int32 encoding;
  imm_expr *expr;
  char *source_line;
} instruction;

Therefore, to store to .text, SPIM will give it a special treatment in bad_mem_write().

CPU/mem.cpp:395:

void
set_mem_byte(mem_addr addr, reg_word value)
{
  data_modified = true;
  // .data
  if ((addr >= DATA_BOT) && (addr < data_top))
    data_seg_b [addr - DATA_BOT] = (BYTE_TYPE) value;
  // .stack
  else if ((addr >= stack_bot) && (addr < STACK_TOP))
    stack_seg_b [addr - stack_bot] = (BYTE_TYPE) value;
  // .data
  else if ((addr >= K_DATA_BOT) && (addr < k_data_top))
    k_data_seg_b [addr - K_DATA_BOT] = (BYTE_TYPE) value;
  // .text or section out of bounds
  else
    bad_mem_write (addr, value, 0); // <--
}

In bad_mem_write(), SPIM will attempt to splice and recompile the instruction as if you modified the memory directly. CPU/mem.cpp:506:

static void
bad_mem_write (mem_addr addr, mem_word value, int mask)
{
  mem_word tmp;

  if ((addr & mask) != 0)
    /* Unaligned address fault */
    RAISE_EXCEPTION (ExcCode_AdES, CP0_BadVAddr = addr)
    else if (addr >= TEXT_BOT && addr < text_top)
  {
    // For halfword and byte writes, attempt to overwrite part of the instruction.
    switch (mask)
    {
    case 0x0:
      tmp = ENCODING (text_seg [(addr - TEXT_BOT) >> 2]);

#ifdef SPIM_BIGENDIAN
      tmp = ((tmp & ~(0xff << (8 * (3 - (addr & 0x3)))))
               | (value & 0xff) << (8 * (3 - (addr & 0x3))));
#else
      tmp = ((tmp & ~(0xff << (8 * (addr & 0x3))))
               | (value & 0xff) << (8 * (addr & 0x3)));
#endif
      break;
      // ...
    }

    // Free instruction if it isn't NULL
    if (text_seg [(addr - TEXT_BOT) >> 2] != NULL)
    {
      free_inst (text_seg[(addr - TEXT_BOT) >> 2]);
    }
    // create a new instruction with the encoding
    text_seg [(addr - TEXT_BOT) >> 2] = inst_decode (tmp);

But wait a second....

SPIM checks for NULL... CPU/mem.cpp:549:

if (text_seg [(addr - TEXT_BOT) >> 2] != NULL)

...after it already dereferenced it!

CPU/mem.cpp:519 (after macro expansion)

tmp = text_seg [(addr - TEXT_BOT) >> 2]->encoding;

And what would cause this instruction to be NULL? If it is not an instruction. And what is at the label f? Nothing, so SPIM dereferences a NULL pointer.

  • -1 byte: Parser abuse

I have submitted a patch fixing this but, but this works on at least 9.1.23 and earlier.

\$\endgroup\$
1
\$\begingroup\$

Trilangle, UB, 1 byte

If you allow undefined behavior that happens to segfault on my machine (Windows 10 on x64), all of the following programs work:

  • +
  • -
  • *
  • :
  • %
  • 7
  • >
  • v
  • L
  • <
  • ^
  • e
  • (
  • )
  • j
  • !
  • o
  • &
  • r
  • x
  • ~
  • 2

All of these attempt to perform some operation on an empty stack. Interestingly, , (pop from stack) runs just fine (though it loops forever).

\$\endgroup\$
1
\$\begingroup\$

Python 3.8, 14 bytes

This only works on Python 3.8 :P. I found this while scavenging bug reports.

*reversed({}),

Try it online!

\$\endgroup\$
0
\$\begingroup\$

.mmo (MMIX executable), 28 bytes (7 tetras)

Doesn't cause emulator segfault, but the program itself does segfault.

Negative addresses are reserved for the OS, and a fault occurs if the protection bit in rK is the same as the high bit of the instruction pointer, which it will be when the OS tries to start this program at the address given to start.

00000000: 98090100 980a00ff 8fe6a7d6 9b16daee  Ƭµ¢¡Ƭ½¡”Ɓȧʂẹɓæḷŀ
00000010: 980b0000 00000000 980c0001           Ƭ¿¡¡¡¡¡¡Ƭ€¡¢
98090100 lop_pre 1,0                // version 1, 0 tetras
980A00FF lop_post 255               // and immediately jump to postamble
8FE6A7D6                            // almost arbitrary address to start at
9B16DAEE                            // must have high bit set
980B0000 lop_stab
00000000                            // no tetras in symtab
980C0001 lop_end
\$\endgroup\$
0
\$\begingroup\$

C (gcc), 15 bytes

main(){main();}

So this is why Python has a recursion limit…

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ main(){*""=0;} is one character shorter and is more likely to segfault. The infinite recursion will not segfault if, for example, the compiler optimizes it into a flat loop (tail call optimization). GCC does exactly this if you pass -O2 or higher. The result is an infinite loop rather than a crash. \$\endgroup\$ Commented May 30 at 23:00
0
\$\begingroup\$

GFortran, compiler crash, 6 bytes

#if'a'

Try it online!

This answer is more appropriate for Crash your favorite compiler, but that one is closed unfortunately.

\$\endgroup\$
1 2
3

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.