146
votes
\$\begingroup\$

As a programmer you certainly know the error of a stack overflow due to an obvious recursion. But there are certainly many weird and unusual ways to get your favourite language to spit that error out.

Objectives:

  1. Must cause a stack overflow which is clearly visible on the error output.
  2. Not allowed to use an obvious recursion.

Examples of invalid programs:

// Invalid, direct obvious recursion.
methodA(){ methodA(); }
// Invalid, indirect, but obvious recursion.
methodA(){ methodB(); }
methodB(){ methodA(); }

The most creative ways are the best as this a . I.e, avoid boring obvious answers like this:

throw new StackOverflowError(); // Valid, but very boring and downvote-deserving.

Even though I accepted an answer now, adding more answers is still okay :)

\$\endgroup\$

closed as too broad by Dennis Apr 18 '16 at 23:21

Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. Avoid asking multiple distinct questions at once. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

locked by Dennis Apr 18 '16 at 23:22

This question exists because it has historical significance, but it is not considered a good, on-topic question for this site so please do not use it as evidence that you can ask similar questions here. This question and its answers are frozen and cannot be changed. See the help center for guidance on writing a good question.

Read more about locked posts here.

  • 14
    \$\begingroup\$ I tend to produce by navigating to stackoverflow.com, though I have been known to query 'stack overflow' on my search engine of choice. \$\endgroup\$ – OJFord Feb 17 '14 at 13:19
  • 21
    \$\begingroup\$ Use Internet Explorer. A sure way to catch one :) \$\endgroup\$ – asgoth Feb 18 '14 at 17:48
  • 64
    \$\begingroup\$ The weirdest way to produce a stack overflow is to post a popularity-contest on codegolf.stackexchange.com asking for people to post the weirdest way to produce a stack overflow. The responders, in testing their solutions to the question, will produce a stack overflow. I haven't tested it though, so I can't be sure it works (which is why I didn't post it as an answer). \$\endgroup\$ – Tim Seguine Feb 18 '14 at 20:32
  • 3
    \$\begingroup\$ I'm partial to this method: joelonsoftware.com/items/2008/09/15.html \$\endgroup\$ – robert Feb 19 '14 at 13:10
  • 11
    \$\begingroup\$ Drive a Toyota (Hey, wait a minute, my car is a Toyota...) \$\endgroup\$ – squeamish ossifrage Feb 22 '14 at 1:08

116 Answers 116

1
vote
\$\begingroup\$

JAVA

"B" overrides "foo()", but invokes "super.foo()". Because the overridden "foo()" in "A" is invoked by an instance of "B", the "this" reference is pointing to "B", not "A". Therefore, when I create another instance of "this", another "B" object is created.

public class Main {  
  public static void main(String[] args) {
    new B();
  }

   static class A {       
        void foo() { 
            try {
                this.getClass().newInstance();
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    }


    static class B extends A {
        B() { foo(); }

        void foo() { super.foo(); }
    }
}
\$\endgroup\$
  • \$\begingroup\$ Don't forget to explain (in your answer) how your solution works. \$\endgroup\$ – Justin Feb 23 '14 at 6:20
1
vote
\$\begingroup\$

C#

public abstract class A
{
  public int X {get { return -1; }}      
  public virtual string Value(){ return "A"; }
}

public class B : A
{
  public new int X {get{ return 42; }}
  public override string Value() { return "B"; }
}

public class C : B
{
  // no recursion; returns -1      
  public int XFromA {get { return ((A)this).X; }}

  // no recursion; returns 42  
  public int XFromB {get { return ((B)this).X; }}

  // no recursion; returns "B"
  public override string Value() { return base.Value(); }

  // StackOverflowException
  public override string Value() { return ((A)this).Value(); }
}
\$\endgroup\$
  • \$\begingroup\$ Technically it's still quite obvious because it is technically calling itself, just with an added bit of anonymity. \$\endgroup\$ – Pharap Feb 23 '14 at 2:18
  • \$\begingroup\$ Just for clarification, the extra level of inheritance is the point of this example. Any class can "cast" itself to its base parent by using the base keyword. But what if it needs to cast itself to its grandparent? Its also possible to use the this keyword in a cast to an interface. So, perhaps I am not a sharp as others reading this, but the syntax seemed quite natural to me, and I had to write several experimental tests to pinpoint the source of the Stackoverflow that caught me by surprise. If it was that obvious, I would have expected the compiler to have caught it. \$\endgroup\$ – mdisibio Feb 24 '14 at 17:11
  • \$\begingroup\$ I've also added additional code to show that casting the this keyword to a parent or grandparent is not in and of itself the cause of the recursion...when I originally used this code, it was this fact that caused me to think: "that's wierd..." \$\endgroup\$ – mdisibio Feb 24 '14 at 17:42
1
vote
\$\begingroup\$

Scheme

((lambda (x) (x x)) (lambda (x) (+ 1 (x x))))

I claim this is not an obvious recursion.

\$\endgroup\$
  • \$\begingroup\$ after some university stuf that one is now obvious as hell for me \$\endgroup\$ – masterX244 May 1 '15 at 16:38
1
vote
\$\begingroup\$

Java again :) Serializing FTW :P

public class C {
    public static class Ci implements Serializable {
        public Object o;
    }

    public static void main(String[] a) throws IOException, InterruptedException {
        List l = new ArrayList<>();
        ObjectOutputStream o = new ObjectOutputStream(new OutputStream(){
            public void write(int b) {/*DEVNULL*/}
        });

        Ci c = new Ci();
        Ci c2 = null;
        int i = 0;
        for (;;) {
            i++;
            if (i % 100000 == 0) {
                System.out.println("Serializing...");
                o.writeObject(c);
                o = new ObjectOutputStream(new OutputStream(){
                    public void write(int b) {/*DEVNULL*/}
                });
                Thread.sleep(1000);
            }

            if (false) 
                break;

            c2 = c;
            c = new Ci();
            c.o = c2;
        }
    }
}

Googling a bit around should tell how this one works :P

The modulo operator is to reduce workload and speed the thing up.

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

A few months ago I ran into this stack overflow in C#, which took me a significant amount of time to track and figure out what was going on. Assuming you have a C# application with Aspose PDF installed:

Aspose.Pdf.Generator.Pdf pdf = new Pdf();
pdf.HtmlInfo.CharSet = "UTF-8";
pdf.BindHTML("<div><img src=\"myImage.jpg\" alt=\"broken!\" /></div>");
pdf.HtmlInfo.ImgUrl = @"C:\users\me\pictures";
pdf.Save(@"c:\output.pdf");

If "myImage.jpg" is more than about twice as tall as it is wide, the image will overflow the generated PDF page, and somewhere in obfuscated code this results in a stack overflow.

\$\endgroup\$
  • \$\begingroup\$ bugs outside the own code are the weirdest to locate :P; but nice find \$\endgroup\$ – masterX244 Feb 26 '14 at 20:12
1
vote
\$\begingroup\$

Java

This code causes StackOverflowError on Oracle's JRE/JDK and OpenJDK. Basically, any JVM that uses the reference implementation for the class library.

import java.util.regex.*;
import java.text.*;

class G21114 {
    public static void main(String args[]) {
        StringBuffer buf = new StringBuffer();
        int c = 0;

        for (int i = Character.MIN_CODE_POINT; i < Character.MAX_CODE_POINT; i++) {
            if (Character.isDefined(i) && Character.getType(i) != Character.SURROGATE) {
                int codePoint[] = {i};
                String s = new String(codePoint, 0, codePoint.length);

                if (!Normalizer.normalize(s, Normalizer.Form.NFD).equals(s)) {
                    buf.append(s); buf.append(s); buf.append(s);
                    buf.append('a');
                    buf.append(s); buf.append(s);
                    c++;

                    if (c >= 300) break; // Don't need too many
                }
            }
        }

        System.out.println(buf.length());

        // try-catch to clearly show what is thrown
        try {
            Pattern.compile(buf.toString(), Pattern.CANON_EQ);
        } catch (PatternSyntaxException e) {
            System.out.println(e.getClass());
        } catch (Error e) {
            System.out.println(e.getClass());
        }
    }
}

This is based on the fact that the reference implementation implements the Pattern.CANON_EQ (canonical equivalence) mode by modifying the input string to create alternation between all the possible decompositions. The string is then compiled as per normal.

The construction works well on a single character, but if there are multiple decomposable character in a row, the construction goes amok and doesn't close non-capturing groups (?:regex) properly. Look at this bug report for the test case.

However, to cause StackOverflowError, the parentheses don't need to be balanced. The combination of letters I chose above happen to produce a series of many opening parentheses, which cause the recursive descent parser in Pattern class to exhaust the stack. The underlying cause is similar to ɲeuroburɳ's answer. However, the code above is more discrete in causing the StackOverflowError and depends on internal implementation of Pattern class.

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

Java

public class Temp {
    public static void main(String[] args) throws Exception {
        Temp.class.getMethod("main", String[].class).invoke(null, new Object[]{null});
    }
}

Gives a bunch of weird stack traces and exceptions

  • InvocationTargetException once with a gazillion times 'caused by InvocationTargetException'
  • InvocationTargetException another gazillion times without stack trace, only ... 1024 more
  • finally ending in StackOverflowError

Also posted in Call a method without calling it

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

Lua:

setmetatable(_ENV, {__newindex = function(x, y) z = y; end});

test="Hello world!"
\$\endgroup\$
  • 2
    \$\begingroup\$ How does it work? \$\endgroup\$ – 23fc9a62-56de-47fb-97b4-737890 Mar 2 '14 at 2:52
  • \$\begingroup\$ @user2509848 it adds a metatable on the global environment. When test=... is executed, the __newindex method is called, since there's no test in the environment. Then the method does z=..., and since z isn't in the environment too, the recursion happens. Another thing to note, is that the __newindex is executed in a synthesized stack frame (unlike a usual frame which is created upon a regular funicton call), and when those are abused, a C stack overflow occurs. \$\endgroup\$ – mniip Mar 2 '14 at 17:27
1
vote
\$\begingroup\$

(C)Python

eval("f("*99+")"*99)

Produces:

s_push: parser stack overflow
Traceback (most recent call last):
  File "test.py", line 1, in <module>
    eval("f("*99+")"*99)
MemoryError
\$\endgroup\$
1
vote
\$\begingroup\$

Tcl

interp r {} 1
a

Uses the same trick that python uses (recursionlimit).
Calling a will result in a call to unknown which executes a lot of other stuff (which will fail)

And here an other one:

proc unknown {args} a
a
\$\endgroup\$
1
vote
\$\begingroup\$

Rant

[?[src]]

Allow me to explain.

[src] is a function that returns the source code of the current state object. Metapatterns ([?...]) generate their own source code, so the return value is different when [src] is called inside as opposed to outside. This is where things get rather weird...

When the code is executed, the metapattern generates a source. It calls [src], which returns the metapattern's source code, which is just [src]. It jumps back to the original scope with this new code on the stack, and runs it again. This calls [src], which returns [?[src]]. When this is executed, another metapattern is created. It generates the same code, until the entire allotted stack space is used up and all hell breaks loose.

Basically, the flow of the program looks like this:

  • [?[src]]
    • [src]
      • [?[src]]
        • [src]
          • [?[src]]
            • ...

... where indent depth represents stack size.

Try it online!

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

Shell and HQ9+

Assumes that there is an HQ9+ interpreter called hq9

crash_things.sh:

hq9 $1 | crash_things

runs recursively, exits when the output is not a valid HQ9+ program.

evil_code.sh:

hq9 QQ | crash_things

messes it up because the code doubles in length every time.

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

Frege

Type this in the REPL at try.frege-lang.org

> foldr (+) 0 [1..]
\$\endgroup\$
0
votes
\$\begingroup\$

Delphi / Object Pascal

Not exactly weird, but technically deprecated and certainly without recursion.

  raise EStackOverflow.Create('Without recursion'); // deprecated warning

This raises the same stack overflow exception that would be raised by an actual stack overflow. Compiling the code results in [dcc32 Warning]: W1000 Symbol 'EStackOverflow' is deprecated warning because the EStackOverflow class is defined in System.SysUtils as deprecated presumably with the intention that it never be actually raised, but it is defined to make it easier to trap and handle a Stack Overflow (despite the fact you really can't do much to recover from a stack overflow).

You could suppress the warning by wrapping it in a compiler directive.

\$\endgroup\$
  • \$\begingroup\$ "I.e, avoid boring obvious answers like this: throw new StackOverflowError(); // Valid, but very boring and downvote-deserving." \$\endgroup\$ – Pharap Feb 23 '14 at 2:10
0
votes
\$\begingroup\$

Python

class I:
    def __init__(self, kids=[]):
        self.kids=kids
    def allkids(self):
        for ii in self.kids:
            ii.allkids()
jj = I()
jj.kids.append(I())
jj.allkids()

It dumps when you run it because of a mutable default argument

  ... more here ...
  File "foo.py", line 6, in allkids
    ii.allkids()
  File "foo.py", line 6, in allkids
    ii.allkids()
RuntimeError: maximum recursion depth exceeded
[mpenning@tsunanmi]$
\$\endgroup\$
0
votes
\$\begingroup\$

Java again.

Using too many parameters this time

public class M
{

    public static final int maxmethods=1024;
    public static void main(String[]a) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
    {
        StringBuffer paramvals = new StringBuffer();
        StringBuffer paramdecls = new StringBuffer();
        StringBuffer paramusages = new StringBuffer();
        String[] methodnames = new String[maxmethods];
        String[] methods = new String[maxmethods];
        int i=0;
        for (; i < maxmethods-1; i++)
        {
            methodnames[i] = "method"+i+"(";
            System.out.println(i);
            if(i<253){
            paramvals.append(i+",");
            paramusages.append("param"+i+",");
            paramdecls.append("int param"+i+",");}
        }
        i=maxmethods-1;
        methodnames[i] = "method"+i+"(";
        paramvals.append(255+"");
        paramusages.append("param"+255);
        paramdecls.append("int param"+255);
        for (int j = 0; j < methodnames.length-1; j++)
        {
            methods[j] = "public static void "+methodnames[j]+paramdecls+")\n{\n"+methodnames[j+1]+paramusages+");\n}";
        }
        methods[maxmethods-1] = "public static void "+methodnames[maxmethods-1]+paramdecls+")\n{\nSystem.out.println(\"This shouldnt be reached\");\n}";
        //fuckyou java
        StringBuilder finaL = new StringBuilder();
        finaL.append("public class F{\npublic static void main(String[]a){System.out.println(\"NOPPE\");}\n\nstatic{helper();}\n"+
                "public static void helper(){method0("+paramvals+");\n}\n//#######################################################+\n");
        for (String method : methods)
        {
            finaL.append(method);
        }
        finaL.append("}");
        new FileWriter(new File("F.java")).write((finaL+"").toCharArray());//Dump of srcfile generated
        EU c2 = new EU("F", finaL+"");
        JavaCompiler c = ToolProvider.getSystemJavaCompiler();
        StandardJavaFileManager f = c.getStandardFileManager(null,null,null);
        c.getTask(null, f, null, null, null,Arrays.asList(new EU[]{c2})).call();
        //System.out.print(new File("").toURI().toURL());
        URLClassLoader u = new URLClassLoader(new URL[]{new File("").toURI().toURL()});
        Class fc = u.loadClass("F");
        fc.getMethod("helper", null).invoke(null, null);    
    }
        public static class EU extends SimpleJavaFileObject {
           final String code;

           EU(String name, String code) {
               super(URI.create("string:///" + name.replace('.','/') + JavaFileObject.Kind.SOURCE.extension),
                     JavaFileObject.Kind.SOURCE);
               this.code = code;
           }
           @Override
           public CharSequence getCharContent(boolean ignoreEncodingErrors) {
               return code;
           }
       }
}

generated file is dumped in workdirecotry used while running; no endless recursion inside :P runtime compilation ftw :)

Edit: moved the method count to a constant

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

Ruby

class Fixnum
  def +(arg)
    self-arg
  end
  def -(arg)
    self+arg
  end
end

reopens the Fixnum class, defines addition as substraction and substraction as addition, then simply do:

3+2

and voila :)

\$\endgroup\$
  • \$\begingroup\$ Obvious recursion but still funny. \$\endgroup\$ – Pierre Arlaud Feb 20 '14 at 12:58
  • \$\begingroup\$ Code that redefines numeric operators to return the wrong answer is always suspicious. Your recursive calls to Fixnum#+ and Fixnum#- look obvious to me. \$\endgroup\$ – kernigh May 13 '14 at 2:20
  • \$\begingroup\$ I did this to a friend, it didn't look obvious to him when he opened up a new feature branch and got stack overflow on an addition ^_^ \$\endgroup\$ – bbozo May 13 '14 at 5:02
0
votes
\$\begingroup\$

Python

>>> def foo( N ):
    root = list()
    nest = root
    for i in range(N):
        nest.append( list() )
        nest = nest[0]
    return root

>>> nested(999)

Traceback (most recent call last):
  File "<pyshell#184>", line 1, in <module>
    nested(999)
RuntimeError: maximum recursion depth exceeded while getting the repr of a list
\$\endgroup\$
0
votes
\$\begingroup\$

Batch

START http://stackoverflow.com
ECHO STACKOVERFLOW!
PAUSE > NUL

Sorry, I coudln't resist!

It fulfills rule 1 and 2 ;o

\$\endgroup\$
  • 1
    \$\begingroup\$ LOL :) nice bending of the rules :) \$\endgroup\$ – masterX244 Feb 26 '14 at 20:11
0
votes
\$\begingroup\$

Groovy

def getProperty(String p){ p2 }; p

Due to an undefined property, Groovy calls getProperty again.

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

Python 2

Stack overflow caused by printing. Yes, the standard usual printing operation. It's SIGSEGV, not standard RuntimeError in CPython.

print reduce(lambda*s:s,range(100000))
\$\endgroup\$
0
votes
\$\begingroup\$

We can do it with the worlds most convoluted javascript! I think it's a cheat since it is really just "obvious" recursion.

(function(f){
    return new function () {
        for(var i= 1; i<3;i++) {
        (function(i){this[i] =  this[f(i)] || function (arg) {
            return !arg || (this[f(i)] || this[i + 1]).apply(this, [f(arg)]);
    }}.bind(this))(f(i));
        }       
}
})(function(i){return i === 1 ? i : i - 1;})[1](1);
\$\endgroup\$
0
votes
\$\begingroup\$

VB.NET

I found this when I did your basic merge sort when I came across a StackOverFlowError. I was so confuzzled I asked a SO question about it. Without going to the link, can you find the cause? The link. Obviously this sorting algorithm uses recursion, but that is not the cause of the error being thrown.

Runner Class:

Module Module1

    Sub Main()
        dim array = new integer(100){}
        dim random = new Random()
        for i=0 to 100
            array(i) = random.next()
        next
        dim sorter = new MergeSort()
        sorter.sort(array)
    End Sub
End Module

MergeSort Class:

public class MergeSort

    private numbers() as integer
    private helper() as integer

    private number as integer

    public sub sort(values as integer())
        me.numbers = values
        number = values.length
        me.helper = new integer(number) {}
        mergesort(0, number - 1)
    end sub

    private sub mergesort(low as integer, high as integer)
' check if low is smaller then high, if not then the array is sorted
        if (low < high)
  ' Get the index of the element which is in the middle
          dim middle as integer = low + (high - low) / 2
  ' Sort the left side of the array
          mergesort(low, middle)
  ' Sort the right side of the array
          mergesort(middle + 1, high)
  ' Combine them both
          merge(low, middle, high)
        end if
    end sub

    private sub merge(low as integer,middle as integer,high as integer)
    ' Copy both parts into the helper array
        for l = low to high 
          helper(l) = numbers(l)
        next

        dim i as integer = low
        dim j as integer = middle + 1
        dim k as integer = low
    ' Copy the smallest values from either the left or the right side back
    ' to the original array
        while (i <= middle andalso j <= high) 
          if (helper(i) <= helper(j)) 
            numbers(k) = helper(i)
            i+=1
          else 
            numbers(k) = helper(j)
            j+=1
          end if
          k+=1
        end while

    ' Copy the rest of the left side of the array integero the target array
        while (i <= middle) 
          numbers(k) = helper(i)
          k+=1
          i+=1
        end while
    end sub
end class
\$\endgroup\$
-1
votes
\$\begingroup\$

Ruby

puts Time.now

Presumably, someday many millions of years into the future, the current time will become so large that the computer will run out of memory.

\$\endgroup\$
  • 3
    \$\begingroup\$ Surely time grows linearly while memory grows exponentially according to More's law...? \$\endgroup\$ – MathematicalOrchid Feb 22 '14 at 8:50
  • 3
    \$\begingroup\$ Won't the time just wrap round since technically most time structures are actually integers internally anyway? \$\endgroup\$ – Pharap Feb 23 '14 at 2:25
-3
votes
\$\begingroup\$

The Ackermann function!

Java

public class Ackermann {

   public static long ackermann(long m, long n) {
      if (m == 0) return n + 1;
      if (n == 0) return ackermann(m - 1, 1);
      return ackermann(m - 1, ackermann(m, n - 1));
   }

   public static void main(String[] args) {
      long M = Long.parseLong(args[0]);
      long N = Long.parseLong(args[1]);
      System.out.println(ackermann(M, N));
   }
}

(Shamelessly copied from http://introcs.cs.princeton.edu/java/75universality/Ackermann.java.html)

 % java Ackermann 3 8
 2045
 % java Ackermann 3 9
 StackOverflowError
\$\endgroup\$
  • 2
    \$\begingroup\$ This is obvious recursion, so I think this is not acceptable according to the rules. \$\endgroup\$ – svick Feb 18 '14 at 17:18
-3
votes
\$\begingroup\$

C

#include <stdio.h>

int main()
{
   main();
   return 0;
}
\$\endgroup\$
  • \$\begingroup\$ This question is about "weird". Your answer doesn't seem very interesting and is not likely to give you upvotes. \$\endgroup\$ – ace Feb 24 '14 at 13:14
  • \$\begingroup\$ please add title of the programming language (in this case c) \$\endgroup\$ – Elisha Feb 24 '14 at 13:52
  • \$\begingroup\$ You can optimize by return main(); \$\endgroup\$ – Fabricio May 12 '14 at 15:10

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