19
\$\begingroup\$

This is limited to Java and C# by the syntax I guess.

In this programming puzzle, you are to produce Exceptions that can be caught but are thrown again at the end of the catch block.

try
{
    while(true)
        try
        {
            // you are only allowed to modify code between this try { } brackets
        }
        catch(Exception ex2) {  }
}
catch(Exception ex1)
{
    // your goal is to reach this catch block by modifying the code ...
    // in the inner try block above
    // You win if you reach this part and execute on of the following code lines
    Console.WriteLine("You won!"); // for C#
    // Or
    System.out.println("You won!"); // for Java
}

You can freely put code before and after this snippet.

The shortest code to reach the outer catch block wins.

\$\endgroup\$
  • 1
    \$\begingroup\$ I think Python may also be able to compete. \$\endgroup\$ – user12205 May 26 '14 at 14:19
  • 1
    \$\begingroup\$ You can freely put code before and after my snippet. \$\endgroup\$ – user21634 May 26 '14 at 14:46
  • 2
    \$\begingroup\$ Too bad it's closed. I've got a solution. To @algorithmshark, Michael and Jan Dvorak: This is NOT a general programming question. It is a programming puzzle, similar to When is a giraffe not a giraffe?. I'm nominating this for reopening. \$\endgroup\$ – user12205 May 26 '14 at 14:54
  • 1
    \$\begingroup\$ Uhhhhhh, Whaaat??? \$\endgroup\$ – TheDoctor May 26 '14 at 15:14
  • 1
    \$\begingroup\$ @algorithmshark I'd go with the sum of the lengths of the insertions \$\endgroup\$ – user12205 May 26 '14 at 15:27
24
\$\begingroup\$

C#, 46 (88 including boilerplate)

using System;class P{static void Main(){
        try
        {
            while(true)
                try
                {
                    System.Threading.Thread.CurrentThread.Abort();
                }
                catch(Exception ex2) {  }
        }
        catch(Exception ex1)
        {
            // your goal is to reach this catch block by modifying the code ...
            // in the inner try block above
            // You win if you reach this part and execute on of the following code lines
            Console.WriteLine("You won!"); // for C#
        }
}}

The Abort() method raises a ThreadAbortException, which is a special exception that is automatically rethrown at the end of each catch block (unless Thread.ResetAbort() is called).

\$\endgroup\$
20
\$\begingroup\$

C# 24 Characters

terminates the inner try block before intended, allowing me to cause an exception outside of the try block.

}finally{int a=1/0;}try{
\$\endgroup\$
  • 1
    \$\begingroup\$ Man this is genius! Why didn't I think of that? (Btw can you shorten it by actually causing an exception instead of throwing an exception? e.g. int a=1/0;?) \$\endgroup\$ – user12205 May 29 '14 at 19:32
  • \$\begingroup\$ Do you need int a= there? Some languages let you just write the expression 1/0 \$\endgroup\$ – gnibbler Nov 13 '14 at 10:38
  • \$\begingroup\$ This isn't a complete working example, is it? So the 24 characters don't count... \$\endgroup\$ – Matt Oct 2 '18 at 14:24
13
\$\begingroup\$

Java, 76 or 31

Counting only the insertions made to the code, ignoring new lines. 76 if you count everything I've added, 31 if you exclude the first line and the last line, i.e. only counting int a=1/0;try{}catch(Error e){}.

class P{public static void main(String[]A){
try
{
    while(true)
        try
        {
            int a=1/0;try{
        }
        catch(Exception ex2) {  }
}
catch(Exception ex1)
{
    // your goal is to reach this catch block by modifying the code ...
    // in the inner try block above
    // You win if you reach this part and execute on of the following code lines
    //Console.WriteLine("You won!"); // for C#
    // Or
    System.out.println("You won!"); // for Java
}
}catch(Error e){}
}}
\$\endgroup\$
  • \$\begingroup\$ Oops, sorry, I didn't pay attention to how you counted. I'll update my answer to add the other counting method. I reckon just counting the characters in the try block is better, since otherwise we'd basically be comparing C# vs Java boilerplate. But that could become complicated if someone submits an answer with important code outside the try block (as is allowed by the rules). \$\endgroup\$ – BenM May 27 '14 at 1:27
  • \$\begingroup\$ @BenM No worries, and I understand why you counted it that way. It's just that the OP did not specify which way to count, so I figured I'd include both. \$\endgroup\$ – user12205 May 27 '14 at 1:32
  • \$\begingroup\$ Very clever solution. \$\endgroup\$ – Nicolas Barbulesco May 30 '14 at 13:07
  • \$\begingroup\$ @NicolasBarbulesco To be honest I think the answer by Ryan is more clever than mine. After all, I added a catch block after the snippet, he didn't. \$\endgroup\$ – user12205 May 30 '14 at 14:12
3
\$\begingroup\$

Warning: These programs are clone bombs (a sort of less-dangerous but still-dangerous form of a fork bomb); as such, do not run them on a production system without sandboxing or resource limits. Clone bombs create threads in a loop (as opposed to fork bombs, which create processes in a loop), thus you can stop them simply by killing the process in question (making them much less dangerous than fork bombs, which can be very hard to clear up); but they will likely tie up most of your CPU until you manage to do so (or until the program wins and exits naturally by itself). Asking your OS to place limits on the amount of memory and CPU time these programs are allowed to use should create a safe environment in which to test them.

Java (OpenJDK 8), 65 60 bytes (with a slight modification to the wrapper)

Thread x=Thread.currentThread();new Thread(x::stop).start();

Try it online!

Requires both instances of catch (Exception …) in the question to be changed to catch (Throwable …). This should in theory be more secure, not less, but it enables this solution to be possible.

I saved 5 bytes over the first version of this answer via using a method reference rather than a lambda.

Java 4, 104 bytes (untested, should work with the original wrapper)

final Thread x=Thread.currentThread();new Thread(){public void run(){x.stop(new Exception());}}.start();

Try it online! (link goes to a Java 8 implementation, thus won't work)

Using features that have been removed from modern versions of Java, it's possible to solve even the version of the puzzle which requires an Exception. Probably, at least. (Java 4 is very old by now and I can't remember which features it did and didn't contain. As can be seen, there were many fewer features in Java back then and it was therefore more verbose; we didn't have lambdas, so I had to create an inner class.)

Explanations

Most of the solutions to this question are in C# (together with a Java solution that cheats via using unbalanced brackets as a form of code injection, and a Perl solution which also isn't in Java). So I thought it would be worth trying to show how this puzzle can be solved "properly" in Java too.

Both programs are effectively identical (thus the fact that the first program works gives me high confidence that the second program would work too, unless I've accidentally used a non-Java-4 feature; Thread#stop was deprecated in Java 5).

Java's Thread#stop method works, behind the scenes, via causing a throwable to be thrown into the thread in question. The throwable intended for the purpose is ThreadDeath (an Error, specifically because people often try to blanket-catch exceptions and Java's designers didn't want that happening), although it allows you to throw anything (or used to; at some point after the API was designed, Java's designers realised that this was an incredibly bad idea and removed the version of the method that takes arguments outright). Of course, even the version which throws ThreadDeath is a fairly risky operation about which you can make few guarantees (for example, it allows you to solve this puzzle, something which "shouldn't" be possible), so you're not supposed to use it, but as of Java 8, it still works.

This program works by spawning a new thread, and asking it to forcibly throw an exception back into the main thread. If we're lucky, it'll do that at a point in time when we're outside the inner catch block (we can't escape the outer catch block until the program ends, because there's a loop around it). Because we have the loop conveniently added already, it's byte-saving to simply use that loop to allow us to keep creating threads, in the hope that one of them will eventually hit the correct timing. This normally seems to happen within a couple of seconds.

(TIO note: the current version of TIO is quite inclined to kill this program early in its execution, presumably due to all the threads being created. It can work on TIO, but does not work reliably, so often a few attempts are required to get the "You won!" output.)

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

C#

    try
    {
        int i = 0, j = 1, k;

        int flag = 0;
        lbl:
        if (flag == 1)
        {
            k = j / i;
        }

        while (true)
            try
            {
                k = j / i;

            }
            catch (Exception e)
            {
                flag = 1;
                goto lbl;
                //Console.WriteLine("loose");

            }
    }
    catch (Exception e)
    {
        Console.WriteLine("Won");

    }
\$\endgroup\$
  • 1
    \$\begingroup\$ Welcome to Programming Puzzles & Code Golf! As this question is a code-golf challenge, please try to make your code as short as possible and include the character count at the top of your answer. Thanks! \$\endgroup\$ – ProgramFOX Dec 24 '14 at 14:20
1
\$\begingroup\$

Perl 5, 37 or 36 bytes

eval {
    while (1) {
        eval {

 

use overload'""',sub{die};die bless[]

 

        };
        $@ eq "" or 0;
    }
};
$@ eq "" or print "You won!\n";

Try it online!

Turns out that this question translates into Perl well enough to make an interesting puzzle there, too. Perl's try equivalent is called (a little confusingly) eval, and specifies an exception by setting @_ to an exception if it occurred, and the null string otherwise. As such, a catch block is implemented via comparing @_ to the null string.

This solution works by creating an object (whose class is the program as a whole; you can use arbitrary Perl files like classes, sort of like the reverse of Java (where you can use arbitrary classes like files)). That's the bless[] part (bless normally only appears deep inside constructors, as the primitive that makes things into objects in the first place, but you can use it directly if you really want to; [] is the memory allocator for the object – a list constructor, in this case – and the class isn't given so it's assumed to be the currently executing one). Meanwhile, we give our "class" (i.e. the main file) a custom compare-to-string method via use overload, and make that method throw an exception (thus breaking out of the loop and solving the puzzle); we can actually put the use overload anywhere, and although it would traditionally go in with the other method definitions and nearish the top of the file, we can put it into the gap we've been given instead and it still works. (If we put it at the end of the file, we could omit the semicolon after it, leading to a 36-byte solution, but this is arguably cheating as it depends on the program having a trailing semicolon in the first place, which is not guaranteed.) It's actually shorter to overload the stringify operation and let Perl autogenerate a string compare from that, than it would be to overload string compare directly (because overloading some operators forces you to overload other operators too).

Now, all we have to do is throw our object using die. The eval terminates, then when we attempt to compare $@ to the null string (to see if there was an exception), the comparison throws another exception and we escape the outside eval.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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