30
\$\begingroup\$

Inspired by this comment...

Thanks to users Step Hen, Wheat-Wizard, and Dennis for helping my solidify the specification of this challenge before posting it!

This is the Robber's thread! For the Cops' thread, go here


In this challenge, you are tasked with running some code that makes it so that your language no longer satisfies our criteria of being a programming language. In that challenge, that means making it so that the language can no longer...

  • Take numerical input and output

  • Add two numbers together

  • Test if a certain number is a prime or not.

This is a challenge, where there are two different challenges with two different objectives: The Cops will try to write some code that makes the language mostly unusable, and the robbers will try to find the hidden workaround that allows the cops to recover their language.

The cops will write two snippets of code:

  1. One that makes their language mostly unusable, e.g. by removing built in functions for taking input/output and numerical operations. This code is not allowed to crash or exit. It should be possible to add code to the end of this snippet, and that code will get evaluated. And

  2. A snippet of code that takes two numbers as input, adds them together, and outputs their sum. This snippet must still correctly function even after running the first snippet. When the two snippets are combined together, they must form a full program that adds two numbers, or define a function that adds two numbers. This snippet will probably rely upon obscure behavior, and be hard to find.

The cops will also choose any standard method of input and output. However, they must reveal exactly which format (input and output) they are using. For you to crack their answer, you must follow the same input/output format, or your crack does not count.

A cops answer will always reveal

  • The first snippet (obviously not the second).

  • Language (including minor version, since most submissions will probably rely on strange edge-cases)

  • IO format, including whether it's a function or full program. Robbers must use the same format to be a valid crack.

  • Any strange edge cases required for their answer to work. For example, only runs on linux, or requires an Internet connection.

As a robber, you must look at one of the cops submissions, and attempt to crack it. You may crack it by writing any valid snippet that could work as snippet 2 (adding two numbers together after the language is made mostly unusable). This does not have to be the same snippet that the cop originally wrote. Once you have an answer cracked, post your code as an answer on this thread, and post a link to your answer as a comment on the cop's answer. Then, that post will be edited to indicate is has been cracked.

Here's an example. For the first snippet, you might see the following python 3 program as a cops answer:

Python 3

print=None

Takes input from STDIN and output to STDOUT

A valid second snippet could be

import sys
a,b=int(input()),int(input())
sys.stdout.write(a+b)

This is valid because it will take two numbers as input, and output their sum even if you join the two snippets together, e.g.

print=None
import sys
a,b=int(input()),int(input())
sys.stdout.write(a+b)

This is a valid crack to their answer.

If a cop's answer remains uncracked for one whole week, they may edit in their second snippet, and indicate that their answer is now safe. Once it is edited to be safe, you may no longer attempt to crack it. If they do not edit it as safe, you may continue to try to crack it until they do.

The winner of the robber's thread is the user who has cracked the most answers, with the tie-breaker being the time they reached N cracks. (so if two different users each have 5 cracks for example, the user who posted their 5th crack first is the winner) After sufficient time has passed, I will accept the winner's answer with the most votes.

Have fun!

Rule clarifications

  • The first snippet must run correctly without taking any input. It may output whatever you like, and this output will be ignored. As long as after the snippet is done, the second snippet runs correctly.

  • The second snippet must actually be executed for your answer to be valid. This means an answer like

    import sys
    sys.exit()
    

    is not valid because it doesn't break the language. It simply quits.

  • After being safe, your score is the byte count of both snippets.

  • This goes back to Please reveal any strange edge cases required for your answer to work... Your submission must contain enough information before being revealed to be reproducible after being revealed. This means that if your answer becomes safe, and then you edit in: Here's my answer. Oh ya, BTW this only works if you run it on Solaris, jokes on you! your answer is invalid and will be deleted and not considered eligible for winning.

  • The second snippet is allowed to crash after outputting the sum. As long as the output is still correct (for example, if you choose to output to STDERR, and then you get a bunch of crash information, this is invalid)

Leaderboard

Here is a list of every user with at least one crack, ordered by score and then name (alphabetical). If you submit a crack, please update your score accordingly.

#User                       #Score
Ilmari Karonen              8

Dennis                      5

Olivier Grégoire            4

Sisyphus                    3
Veedrac                     3

Arnold Palmer               2
Bruce Forte                 2
DJMcMayhem                  2
Dom Hastings                2
ppperry                     2

1bluston                    1
2012rcampion                1
Ben                         1
BlackCap                    1
Christian Sievers           1
Cody Gray                   1
HyperNeutrino               1
Joshua                      1
Kaz                         1
Mark                        1
Mayube                      1
Xnor                        1
zbw                         1
\$\endgroup\$
0

45 Answers 45

1
2
1
\$\begingroup\$

JavaScript (Node.js) by BlackCap, 1229 bytes

I'm not sure this is intended, there's probably a much shorter 'proper' solution, but this appears to work as expected!

let mess = ctx => f => new Proxy (f, {
  has: (t, p) => p in t || p in ctx
, get: (t, p) => {
    let k = p in t? t[p]: ctx[p];

    if (k instanceof Function) return (
      function fetch (_k) {
        return mess (ctx) ( x => ( q => q instanceof Function
                                      ? fetch (q)
                                      : t (q)
                                  ) ( _k(x) )
                          )
      })(k);

    return k;
  }
});

with (mess (global) (x => x)) {
  dot   = f => a => b => f(a(b))
  ap    = f => g => x => f (x) (g (x))
  flip  = f => x => y => f (y) (x)
  Const = a => b => a
  id    = x => x
  num   = n => n (x => x + 1) (0)
  log   = console.log

  let x = flip (Const . id . id)
    , y = flip (Const . id . id . id)
  for (let i = 0; i < process.argv[2]; i++) x = ap (dot) (x)
  for (let i = 0; i < process.argv[3]; i++) y = ap (dot) (y)
  process.argv = [];

  logic = x => y => {
    let j = flip (Const . id . id);
    for (var i = 0; i < num(x)+num(y); i++) {
      j = ap(dot)(j);
    }
    return j
  }

  log . id . num ( logic (ap (dot) (x))
                         (f => z => (( y(flip (id) . id . flip (dot (id)) (f)) ) (Const (z))) (id) )
                 );
}

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ I should have hid that num function. Nice solution ;) \$\endgroup\$
    – BlackCap
    Commented Jul 20, 2017 at 17:49
  • \$\begingroup\$ @BlackCap Honestly, without the num function, I'd have spent a lot longer in debug... \$\endgroup\$ Commented Jul 20, 2017 at 17:53
1
\$\begingroup\$

Python 3 by @ppperry

import sys
for mod in sys.modules.values():mod.__dict__.clear();break;
a=int(input());b=int(input());print(a+b)

Try it online!

Just broke out of the loop after the first module is deleted, which doesn't involve the printing/reading functions.

\$\endgroup\$
1
  • \$\begingroup\$ D'oh! Why didn't I think of that! \$\endgroup\$ Commented Jul 20, 2017 at 19:15
1
\$\begingroup\$

Python 3, ppperry

import sys
atexit.unregister(1..__truediv__)
print(int(input())+int(input()),file=sys.stderr)

Try it online!

This simply uses the atexit.unregister function to remove the registered function, clearing the dirtied STDERR output. I'm not sure if this was the intended solution.

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

Perl 5 by Dom Hastings

*>=[1*(()=((1)x<>,(1)x<>))]

Try it online!

This was actually surprisingly simple, once I figured out the right approach. I did waste quite a lot of time trying to use string manipulation or nested eval tricks before I realized that simple array repetition and counting would do it.

\$\endgroup\$
1
  • \$\begingroup\$ That's it exactly! I tried to leave enough red herrings to keep you busy but restricting the character set was tough. \$\endgroup\$ Commented Jul 21, 2017 at 4:36
1
\$\begingroup\$

Python 3 by ppperry

del sys.modules['ctypes']

import ctypes
ctypes.pythonapi.Py_AtExit(ctypes.pythonapi.Py_Exit)

sys.stderr.write(str(int(input()) + int(input())))

Strictly speaking, I only need the last line of code (the segfault is reported by the shell, not Python), but there are no bonus points for short robber answers, so here is is a clean crack.

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ This was similar to, but not quite, the intended solution. \$\endgroup\$ Commented Jul 21, 2017 at 12:36
1
\$\begingroup\$

x86 16 bit real mode Assembly by Joshua

    cli
    pop ax
    pop dx
    add ax, dx
    ret

Joshua's code acts to wedge the CPU rather thoroughly, by putting it into "trace" mode, where a debug exception is raised after each instruction is executed. Additionally, it stops code execution by arranging for the HLT instruction to be executed with interrupts disabled. In this situation, the only way for the CPU to start executing code again is for a non-maskable interrupt to come in, something that you can't trigger from software.

The key line from the Intel CPU documentation for getting out of this situation is

If an application program sets the TF flag using a POPF, POPFD, or IRET instruction, a debug exception is generated after the instruction that follows the POPF, POPFD, or IRET.

In short, you can execute exactly one instruction before trace mode kicks in and halts the CPU. The instruction I execute is cli: disable interrupts. Since trace mode works by repeatedly triggering an interrupt, this keeps things working, at least until some other poor sucker re-enables them.

Since the original snippet doesn't specify the I/O mode beyond a simple "language-agnostic", I chose to treat the snippet as a "cdecl function": a function taking two integers on the stack, with the return value in AX.

\$\endgroup\$
3
  • 2
    \$\begingroup\$ You have correctly reasoned the problem, and the solution is to unbooby the trap with one CPU instruction. If the CPU crashes you can't read its registers so just writing the result to register is not a solution. Also, the prelude cleared ax so it can't be fastcall. \$\endgroup\$
    – Joshua
    Commented Jul 21, 2017 at 3:54
  • \$\begingroup\$ @Joshua, new version that appears to work as a cdecl function, at least under MS-DOS. \$\endgroup\$
    – Mark
    Commented Jul 21, 2017 at 8:40
  • \$\begingroup\$ Since there's no length penalty on cracks, you could probably tidy up the remaining loose ends by unsetting the trap flag and then re-enabling interrupts. But at least to me this looks good enough. \$\endgroup\$ Commented Jul 21, 2017 at 11:08
1
\$\begingroup\$

CPython 3, by ppperry

I have no idea why the __call__ method is not traced properly.

p = lambda a,b,c:1
sys.setprofile.__call__(p)
print(int(input())+int(input()))

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ Interesting. Btw sys.setprofile.__call__(None) would work as well. \$\endgroup\$
    – Dennis
    Commented Jul 22, 2017 at 6:28
  • \$\begingroup\$ There are always so many loopholes you don't think of ... \$\endgroup\$ Commented Jul 22, 2017 at 12:14
1
\$\begingroup\$

S.I.L.O.S by Rohan Jhunjhunwala

Since the poster explicitoly clarified that there isn't a trailing newline at the end, I think this should count as a crack:

def print z p print
readIO
a=i
readIO
a+i
pInt a

My code starts with p print.

\$\endgroup\$
2
  • \$\begingroup\$ Good job, you even went the extra mile of golfing it. My intended crack, just defined z back to print! I might take an extra shot at posted a substantially more interesting version with a linefeed that will be harder to crack, although I might have to clarify what constitutes input and output. \$\endgroup\$ Commented Jul 23, 2017 at 3:36
  • \$\begingroup\$ slight nitpick, your code starts with a leading space as well. \$\endgroup\$ Commented Jul 23, 2017 at 3:44
1
\$\begingroup\$

Mascarpone by BlackCap

:'[/''/'i/'./':/',/'>/'!/']/*'i<
:'[/':/''/'[/'//''/''/'//''/'z/'//''/'./'//''/']/'//'*/''/'z/'</':/',/'>/'!/']/*'z<
:,>!

What this code does is three things:

  1. It defines a command i that, when executed, prints a literal i, reads a character and executes that character as a command.
  2. It defines a command z that, when executed, print nothing, redefines itself, reads a character and executes that character as a command. The redefined z command, when executed, prints a literal z and does nothing else.
  3. Finally, after these definitions, it reads a character from the input and executes it as a command.

In the code above, I've inserted newlines to split each of these three parts of the code onto its own line. The net effect of all this is that, given input of the form iiziiiz, the program echoes the i's, skips the first z and stops at the second z (and also echoes it).

Conveniently (and almost certainly deliberately), BlackCap's code leaves a copy of the most recently deified interpreter lying on the stack. Since I cannot reify the current interpreter anymore after v has been redefined, I instead make use of that interpreter to parse the input, making sure to always leave a copy of it on the stack after every operation.

(The : commands at the beginning of lines 2 and 3 (and after the < in the quoted code on line 2) are actually unnecessary, since BlackCap's code redefines < as <:. I've left them in anyway so that the code works even without BlackCap's prefix, as long as a copy of any sufficiently functional Mascarpone interpreter (obtainable e.g. with a single initial v) is initially present on the stack.)

The annoying part here is Mascarpone's silly string handling, where strings are not stored on the stack as single elements, but as one element per symbol (i.e. character). That is, the string [foo] is actually stored on the stack as the sequence of five elements '[ 'f 'o 'o '] (yes, including the delimiters!). Since the / command only swaps the two topmost elements on the stack, and since a literal / inside a [] delimited string is just parsed as the literal symbol '/, the only way (that I know of) to move an existing element on the stack (such as the copy of the current interpreter that I need) on top of a literal string is to actually write that string out as individual '-quoted symbols (which doubles its length) and then insert a / command after each of these quoted symbols (effectively tripling the length of the string).

And, of course, in the solution I actually have a string that contains code that contains a string (that contains code). And since both of those strings are used as arguments to the * command, and since * wants its interpreter argument on top of its string argument, that means both the inner and the outer string need to be expanded in the manner described above, effectively bloating the inner string to nine times its original length.

Still, this is a completely trivial mechanical process to do, even if it does render the code effectively unreadable.

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

CPython 3, ppperry

p.__defaults__ = (lambda _:0),
print(int(input()) + int(input()))
\$\endgroup\$
1
  • \$\begingroup\$ Why do people keep finding loopholes? \$\endgroup\$ Commented Jul 31, 2017 at 1:35
1
\$\begingroup\$

CPython 3, ppperry

p.__code__ = (lambda *_:0).__code__
print(int(input()) + int(input()))

Try it online.

\$\endgroup\$
2
  • \$\begingroup\$ Why is __code__ even writable? \$\endgroup\$ Commented Jul 31, 2017 at 1:58
  • 1
    \$\begingroup\$ @ppperry Clearly you forgot to return Guido's favourite coffee mug. He made __code__ writable just to spite you. \$\endgroup\$
    – Veedrac
    Commented Jul 31, 2017 at 1:59
1
\$\begingroup\$

CPython 3, ppperry

import functools
input = functools.partial(sys.stdin.buffer.readline)
print = functools.partial(print)
print(int(input()) + int(input()))

Try it online.

\$\endgroup\$
1
  • \$\begingroup\$ This was similar to the intended solution (although I did not expect it to be so easy) \$\endgroup\$ Commented Jul 31, 2017 at 2:55
0
\$\begingroup\$

Second Java challenge by racer290

The challenge was only a static block. Which alone means nothing. So I took the liberty to wrap it in a class and to add the two required imports.

// I had to add the imports 
import java.lang.reflect.Method;
import java.security.Permission;

public class Racer2 {

static {

    try {

        System.setIn(null);
        System.setOut(null);
        System.setErr(null);

        for (Method m : System.class.getMethods()) {

            m.setAccessible(false);

        }

        System.class.getMethod("getSecurityManager", new Class[0]).setAccessible(false);

        for (Method m : Class.class.getMethods()) {

            m.setAccessible(false);

        }

        SecurityManager mngr = new SecurityManager() {

            @Override
            public void checkPermission(Permission p) {

                if (p.getName().equals("createSecurityManager")) throw new SecurityException();
                if (p.getActions().startsWith("read")) throw new SecurityException();

            }

        };

        System.setSecurityManager(mngr);

        // MY CODE

    } catch (Throwable t) {

    }
}

static class System {
  static void setIn(Object o) {}
  static void setOut(Object o) {}
  static void setErr(Object o) {}
  static void getSecurityManager() {}
  static void setSecurityManager(SecurityManager sm) {}
}

    static {
      java.util.Scanner scanner = new java.util.Scanner(java.lang.System.in);
      java.lang.System.out.println(scanner.nextInt() + scanner.nextInt());
        try {

        // END OF MY CODE

    } catch (Throwable t) {

    }

}

}

The solution is roughly the same as the one I used for Kevin Cruijssen's challenge.

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

Vim challenge (follow-up) by @DJMcMayhem

This is the follow up of this where I was allowed to use external commands. Here's a solution with pure vim:

Js--<Esc>0v$di<C-r>=<C-r>"⏎

Try it online!

Explanation

This works by using the expression register:

J                            - join the lines together
 s--                         - replace the current character with --
    <Esc>                    - back to NORMAL mode
         0v$                 - move cursor to beginning, select and then move it to the end
            d                - delete selected and place in paste register
             i               - change to INSERT mode
              <C-r>=         - change to expression register
                    <C-r>"   - place content of paste register
                          ⏎  - evaluate and insert at current position
\$\endgroup\$
0
\$\begingroup\$

Python 3.4 by Mega Man

__builtins__ = [t for t in ().__class__.__base__.__subclasses__() if t.__name__ == 'Sized'][0].__len__.__globals__['__builtins__']
import io
stdin =  io.FileIO(0, 'r')
stdout = io.FileIO(1, 'w')
ans = int(stdin.read(10))+int(stdin.read(10))
ans = str(ans).encode('latin1')
stdout.write(ans)

Try it online!

TIO is actually Python 3.6, but it seems to work as well. Since I can't (I don't think?) send multiple EOF markers to STDIN on TIO, I've resorted to something hacky, but you'll have to trust be that 1^D2^D works as well.

\$\endgroup\$
1
2

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.