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 Cops' thread. For the Robbers' 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 cops-and-robbers 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.
As a cop, you must write two snippets of code:
One that makes your language mostly unusable, e.g. by removing built-in functions for taking input/output and numerical operations. The more features you remove, the better. 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...
...a snippet of code that takes two non-negative integers 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. Ideally, this snippet should rely upon very obscure behavior, so as to be more difficult to find.
You may choose any standard method of input and output. However, you must reveal exactly which format (input and output) you are using. A robber cannot crack your answer unless they use the same format as you.
After writing both of these snippets, you must post the first one as an answer, without revealing the second one. Your answer should contain all of the following information:
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 for their crack to be valid.
Any strange edge cases required for your answer to work. For example, only runs on linux, or requires an Internet connection. Obviously, this is slightly subjective, but if a cop has some extreme edge case that prevents it from being cracked, and then only reveals this after being safe, I consider this poor sportsmanship. A potential robber should have all information necessary to crack your answer before it is cracked.
You do not need to reveal your byte count until your answer is safe.
Here's an example. For the first snippet, you could submit the following Python 3 program:
Python 3
print=None
Takes input from STDIN and output to STDOUT
And then as your second snippet, you could write:
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)
However, this will be extremely easy for a robber to find a solution to. Since this would be very easy to crack, you could attempt to patch this particular approach like so:
import sys
sys.stdout=None
print=None
However, even this has a very easy workaround:
del print
a,b=int(input()),int(input())
print(a+b)
As a cop, your goal is to make the hidden workaround as obscure as possible, to prevent the robbers from finding it.
The robbers will look at one of your answers, and attempt to crack it. They 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 as you originally intended. If a robber cracks your answer, they will leave a comment on your answer, and then you should edit it to indicate that it has been cracked. If your post is cracked, you should edit your answer to show the solution (snippet 2) that you originally intended. This isn't a rule per se, just a friendly suggestion to keep the game fun. You do not have to.
If an answer remains uncracked for one whole week, you can edit in your second snippet, and indicate that your answer is now safe. If you do not edit it after the week is up, other users can still crack it until you do. If you do not reveal your second snippet, you cannot claim points for your answer, or call it safe.
The winner of the cops' thread is the shortest safe answer including both snippets, counted in bytes, and this answer will be accepted after sufficient time has passed. You do not need to reveal your byte count until your answer is safe, since byte count is irrelevant to your score until your answer is safe. In the event that sufficient time has passed and no answers remain uncracked, the winner will be the answer that remained uncracked for the longest period of time.
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. Similarly, entering an infinite loop is not valid, since the second snippet will never be executed.
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, joke's 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).
You may not edit your code after submitting an answer.
You may not rely on cryptographic functions like encryption, hash functions, CSPRNGs etc.
Snippet to find uncracked submissions:
<script>site='meta.codegolf';postID=5686;isAnswer=false;QUESTION_ID=133174;</script><script src='//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js'></script><script>jQuery(function(){var u='//api.stackexchange.com/2.2/';if(isAnswer)u+='answers/'+postID+'?order=asc&sort=creation&site='+site+'&filter=!GeEyUcJFJeRCD';else u+='questions/'+postID+'?order=asc&sort=creation&site='+site+'&filter=!GeEyUcJFJO6t)';jQuery.get(u,function(b){function d(s){return jQuery('<textarea>').html(s).text()};function r(l){return new RegExp('<pre class="snippet-code-'+l+'\\b[^>]*><code>([\\s\\S]*?)</code></pre>')};b=b.items[0].body;var j=r('js').exec(b),c=r('css').exec(b),h=r('html').exec(b);if(c!==null)jQuery('head').append(jQuery('<style>').text(d(c[1])));if (h!==null)jQuery('body').append(d(h[1]));if(j!==null)jQuery('body').append(jQuery('<script>').text(d(j[1])))})})</script>
46 Answers 46
Haskell, cracked by Christian Sievers
import Prelude(getLine,print)
a=a
Full program, reading two integers (including negative ones) from stdin and writing to stdout.
I've just disabled the Prelude so almost nothing is in scope, and then added a definition; further imports are syntactically invalid. I gave you getLine
and print
though.
Edited to add my original solution. Christian's crack was different, but exploits the same basic features (you can get a surprising amount of computation done by accessing functions that have syntactic sugar, even when you can't call anything builtin directly or even name the types involved).
import Prelude(getLine,print)
a=a
(x:l)!0=x
(x:l)!n=l!d[0..n]
d[x,y]=x
d(x:l)=d l
x^y=[x..]!y
x+y=f[0..y](x^y)(-((-x)^(-y)))
f[]x y=y
f _ x y=x
f.g= \x->f(g x)
f&0= \x->x
f&n=f.(f&d[0..n])
x*y=((+x)&y)0
x%[]=x
x%('-':s)= -(x%s)
x%(c:s)=x*10+i c%s
i c=l['1'..c]
l[]=0
l(x:s)=1+l s
main=do
x<-getLine
y<-getLine
print((0%x)+(0%y))
Which probably isn't super-golfed anyway, but here it is more readibly:
import Prelude(getLine,print)
a=a
-- List indexing
(x : _) !! 0 = x
(_ : xs) !! n = xs !! (sndLast [0..n])
-- sndLast [0..n] lets us decrement a positive integer
sndLast [x, _] = x
sndLast (_ : xs) = sndLast xs
-- Pseudo-addition: right-operator must be non-negative
x +~ y = [x..] !! y
-- Generalised addition by sign-flipping if y is negative
x + y = switch [0..y] (x +~ y) (-((-x) +~ (-y)))
where switch [] _ empty = empty -- [0..y] is null if y is negative
switch _ nonempty _ = nonempty
f . g = \x -> f (g x)
-- compose a function with itself N times
composeN f 0 = \x -> x
composeN f n = f . (composeN f (sndLast [0..n]))
-- multiplication is chained addition
x * y = composeN (+x) y 0
strToNat acc [] = acc
strToNat acc ('-' : cs) = -(strToNat acc cs)
strToNat acc (c : cs) = strToNat (acc * 10 + charToDigit c) cs
charToDigit c = length ['1'..c]
length [] = 0
length (_ : xs) = 1 + length xs
main = do
x <- getLine
y <- getLine
print (strToNat 0 x + strToNat 0 y)
-
2\$\begingroup\$ cracked \$\endgroup\$Christian Sievers– Christian Sievers2017年07月19日 12:36:26 +00:00Commented Jul 19, 2017 at 12:36
Python 2, Cracked
Implements addition as a named function
import sys
c="".join(open(__file__).read().split('\n')[4:])
if set(c)-set(' &)(,.:[]a`cdfijmonrt~')or"import"in c:sys.setrecursionlimit(1)
f=lambda\
What does this do?
For the purposes of helping you out a bit I'll explain what this does. This code opens the source file and checks if the remainder of the code fits the following criteria:
- Does not contain the string
import
- Is made solely of the characters
&)(,.:[]a`cdfijmonrt~
If it fails either criterion the recursion limit is set to 1
meaning that any code you write will hit the recursion limit.
There are no tricks here, I have written a solution that uses only these characters and no imports, I'm not doing anything subversive, but I will say that I think this will be pretty hard to crack.
To save you some time here is a short list of useful things you cannot do with this restriction
+
well duh,eval
/exec
Wasn't going to let you get away with thatNumbers, They might be more useful than you think
String literals
len
=
, No assigning variables>
,<
,==
. . . I have left you with no comparisons*
,-
,/
,%
,^
,|
,>>
,<<
The only operators available are~
and&
__foo__
, None of those fancy double underscore methods are allowed.
-
1\$\begingroup\$ Wow this is quite evil. Nice! \$\endgroup\$2017年07月19日 01:24:51 +00:00Commented Jul 19, 2017 at 1:24
-
\$\begingroup\$ Fantastic answer to kick things off :) \$\endgroup\$DJMcMayhem– DJMcMayhem2017年07月19日 01:33:15 +00:00Commented Jul 19, 2017 at 1:33
-
\$\begingroup\$ Hehe, this just might have been inspired by that dumb king-of-the-hill challenge I tried to spec out in chat that one time \$\endgroup\$Stephen– Stephen2017年07月19日 01:37:45 +00:00Commented Jul 19, 2017 at 1:37
-
4\$\begingroup\$ I think this is a valid crack: codegolf.stackexchange.com/a/133209/68942 \$\endgroup\$2017年07月19日 02:03:12 +00:00Commented Jul 19, 2017 at 2:03
-
\$\begingroup\$ RE the first snippet:
This code is not allowed to crash or exit.
(see chat for discussion on it) \$\endgroup\$Stephen– Stephen2017年07月19日 02:18:15 +00:00Commented Jul 19, 2017 at 2:18
Python 2, Cracked
This is the fourth iteration of this answer. Each of the last answers has was cracked via reseting the recursion depth.
Implements addition as a named function
import sys
if set("".join(open(__file__).read().split('\n')[4:]))-set(' &)(,.:[]a`cdfijmonrt~'):sys.setrecursionlimit(1)
for m in sys.modules:sys.modules[m]=None
del sys;f=lambda\
What does this do?
For the purposes of helping you out a bit I'll explain what this does. This code opens the source file and checks if the remainder of the code
is made solely of the characters &)(,.:[]a`cdfijmonrt~
If it fails the recursion limit is set to 1
meaning that any code you write will hit the recursion limit.
I've also disabled all of the modules, so you can't import anything.
There are no tricks here, I have written a solution that uses only these characters and no imports, I'm not doing anything subversive, but I will say that I think this will be pretty hard to crack.
To save you some time here is a short list of useful things you cannot do with this restriction
+
well duh,eval
/exec
Wasn't going to let you get away with thatNumbers, They might be more useful than you think
String literals
len
=
, No assigning variables>
,<
,==
. . . I have left you with no comparisons*
,-
,/
,%
,^
,|
,>>
,<<
The only operators available are~
and&
__foo__
, None of those fancy double underscore methods are allowed.
My solution
So now that xnor has cracked it in a way I am sufficiently satisfied with I am going to reveal my solution
r,o:(o and f(~(~r&~o)&~(r&o),int(`r`[:r&~r].join([`dict()`[r&~r],`r&~r`,`dict([(r&~r,r&~r)])`[int(`~([]in[[]])`[[]in[[]]:])],`min`[[]in[[]]],`dict()`[~(r&~r)],`r&~r`]).format(r&o),int(`~([]in[[]])`[[]in[[]]:]))))or r
Surprise, surprise its a hulking pile of gibberish. Rather than break this down I'm going to go through the process of how I made this.
I started with a pretty standard addition algorithm
r,o:(o and f(r^o,r&o<<1))or r
Then I used a bitwise trick for representing ^
with |
,&
,~
.
r,o:(o and f((r|o)&~(r&o),r&o<<1))or r
I used another bitwise trick to get rid of the |
r,o:(o and f(~(~r&~o)&~(r&o),r&o<<1))or r
Now all thats left is the <<
, shouldn't be too hard, right? Well get ready for a bumpy ride. To replace the bitshift I used strings to append a zero to the end of its binary representation
r,o:(o and f(~(~r&~o)&~(r&o),int(bin(r&o)[2:]+"0",2)))or r
This has a few problems but the primary one is using addition, so I worked around this by using a format instead
r,o:(o and f(~(~r&~o)&~(r&o),int("{}0".format(bin(r&o)[2:]),2)))or r
We are not allowed to use bin, so I used string formatting to convert to binary.
r,o:(o and f(~(~r&~o)&~(r&o),int("{0:b}0".format(r&o),2)))or r
Since string literals are forbidden I have to build the string {0:b}0
out of parts made with back ticks and join
them together.
r,o:(o and f(~(~r&~o)&~(r&o),int("".join(["{","0",":","b","}","0"]).format(r&o),2)))or r
The empty string is pretty easy, you can just do
`r`[:0]
The zeros were
`0`
and the {:}
were all grabbed from dictionaries.
r,o:(o and f(~(~r&~o)&~(r&o),int("".join([`dict()`[0],`0`,`dict([(0,0)])`[2],"b",`dict()`[-1],`0`]).format(r&o),2)))or r
b
seems pretty hard to get, its not in our character set, so how are we supposed to get an object that has a b
in its repr
? Well here's how: When you use repr
on a builtin function you get something that looks like
<built-in function name>
And thats from where we'll get our b
.
r,o:(o and f(~(~r&~o)&~(r&o),int("".join([`dict()`[0],`0`,`dict([(0,0)])`[2],`min`[1],`dict()`[-1],`0`]).format(r&o),2)))or r
Now all thats left are numbers, I only need -1, 0, 1, and 2 so here's how I represented them:
-1 = ~(r&~r)
0 = r&~r
1 = []in[[]]
2 = `~([]in[[]])`[[]in[[]]:]
2 could actually be a byte shorter as
```r&~r```.find(`r&~r`)
based on @Blender's suggestions in the comments, but I didn't think of this until after the fact.
So we substitute these numbers in
r,o:(o and f(~(~r&~o)&~(r&o),int(`r`[:r&~r].join([`dict()`[r&~r],`r&~r`,`dict([(r&~r,r&~r)])`[int(`~([]in[[]])`[[]in[[]]:])],`min`[[]in[[]]],`dict()`[~(r&~r)],`r&~r`]).format(r&o),int(`~([]in[[]])`[[]in[[]]:]))))or r
And thats the crack.
-
\$\begingroup\$ This snippet seems to error on its own. \$\endgroup\$ATaco– ATaco2017年07月19日 05:22:25 +00:00Commented Jul 19, 2017 at 5:22
-
\$\begingroup\$ @ATaco I believe this was discussed in chat and it was decided that this was ok. \$\endgroup\$2017年07月19日 05:23:18 +00:00Commented Jul 19, 2017 at 5:23
-
\$\begingroup\$ Rules explicitly state otherwise. "This code is not allowed to crash or exit." \$\endgroup\$ATaco– ATaco2017年07月19日 05:24:23 +00:00Commented Jul 19, 2017 at 5:24
-
\$\begingroup\$ @ATaco Here's the message he said he would update it when he got the chance. \$\endgroup\$2017年07月19日 05:26:38 +00:00Commented Jul 19, 2017 at 5:26
-
5
Haskell, cracked by Ben
main=main--
Try it online! This should be a full program reading two numbers from stdin and outputting the sum to stdout.
Each full program starts by running the main
function, but here main
calls itself and causes an infinite loop. To make matters worse, a line comment is started with --
directly behind the recursive call to prevent changing it to e.g. main2
and then defining that to do the summation.
Intended solution:
main=main--$()
_ --$ _ = do
x <- readLn
y <- readLn
print $ x+y
--
starts a line comment unless it can also be parsed as part of an operator. (The syntax highlighting seems to be unaware of this fact.) --$
is a valid infix operator which takes main
as first argument and some dummy second argument ()
. It is then defined to ignore both arguments and to perform the required task instead.
-
2\$\begingroup\$ Cracked it: codegolf.stackexchange.com/a/133244/17061 \$\endgroup\$Ben– Ben2017年07月19日 06:42:40 +00:00Commented Jul 19, 2017 at 6:42
-
5\$\begingroup\$ you can just add "where main = ..." \$\endgroup\$michi7x7– michi7x72017年07月19日 07:20:31 +00:00Commented Jul 19, 2017 at 7:20
-
\$\begingroup\$ +1 for a Haskell solution that only works because of Haskell's lazy evaluation. \$\endgroup\$Jules– Jules2017年07月20日 17:38:01 +00:00Commented Jul 20, 2017 at 17:38
C (gcc) Cracked!
#define D(f)void f(void);
D(printf)D(fprintf)D(putc)D(puts)D(getchar)D(putc)D(fputc)D(ferror)D(feof)D(read)D(fclose)D(fread)D(wr1te)D(fgets)D(fgetc)D(popem)D(gets)D(read)D(scanf)D(setbuf)D(execl)D(execlp)D(putchar)D(execle)D(execv)D(malloc)D(execvp)D(execvpe)D(exec)D(system)D(close)D(fwrite)D(open)D(free)
int stdin;
int main(){
//your code goes here...hehe
}
Input from STDIN and output to STDOUT.
This runs without error. Hahaha this is quite evil. I've only tested it on TIO's gcc. Per usual, you must append your code after this snippet in order for it to work :) The comment is a mean one, don't listen to it.
Tested on gcc (GCC) 6.3.1 20161221 (Red Hat 6.3.1-1)
. Should work on any linux system.
Original solution
#define D(f)void f(void);
D(printf)D(fprintf)D(putc)D(puts)D(getchar)D(putc)D(fputc)D(ferror)D(feof)D(read)D(fclose)D(fread)D(wr1te)D(fgets)D(fgetc)D(popem)D(gets)D(read)D(scanf)D(setbuf)D(execl)D(execlp)D(putchar)D(execle)D(execv)D(malloc)D(execvp)D(execvpe)D(exec)D(system)D(close)D(fwrite)D(open)D(free)
int stdin;
int main(){
//your code goes here...hehe
}
void __attribute__ ((destructor)) dtor() {
int a,b,c,d;a=b=c=0;
struct FILE* z = popen("cat", "r");
#define q(x)for(;(c=getc(z))^32&&c^-1;)x=10*x+c-48;
q(a);q(b);
char*y=calloc(c=a+b,1);
for(a=0;c;){y[a++]=(48+(c%10));c=c/10;}
for(b=0;b<a/2;b++){d=y[b];y[b]=y[a-b-1];y[a-b-1]=d;}
write(1,y,a);
}
-
\$\begingroup\$ @LegionMammal978 Ah yes \$\endgroup\$Conor O'Brien– Conor O'Brien2017年07月19日 02:38:22 +00:00Commented Jul 19, 2017 at 2:38
-
2\$\begingroup\$ Specify your platform! \$\endgroup\$Joshua– Joshua2017年07月19日 02:48:33 +00:00Commented Jul 19, 2017 at 2:48
-
\$\begingroup\$ @Joshua I have added some information \$\endgroup\$Conor O'Brien– Conor O'Brien2017年07月19日 03:02:45 +00:00Commented Jul 19, 2017 at 3:02
-
4
-
\$\begingroup\$ Well,
__asm__
and you have plenty of functions to choose from :) don't think C and C++ are good enemies here. \$\endgroup\$edmz– edmz2017年07月19日 13:07:34 +00:00Commented Jul 19, 2017 at 13:07
C (GCC on Linux) (cracked)
Instead of using silly file-reading sandboxing techniques, we do it the proper way - with SECCOMP whitelisting!
Your task: implement addition with input from STDIN and output to STDOUT.
#include <stdlib.h>
#include <unistd.h>
#include <sys/prctl.h>
#include <linux/seccomp.h>
#include <syscall.h>
#include <stdio.h>
void sandbox();
__attribute__ ((constructor(0))) int s() {
close(0);
close(1);
close(2);
prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT);
}
int main() {
sandbox();
syscall(SYS_exit, EXIT_SUCCESS);
}
void sandbox() {
// Your code here!
}
WTF is this!?
To help you in your insurmountable task I'll explain what this code does.
__attribute__ ((constructor(0)))
ensures the s
function is run first. The function closes all open file descriptors for STDIN, STDOUT and STDERR. Then the program restricts itself with a strict SECCOMP whitelist, which limits your system calls to the following:
read(2)
write(2)
_exit(2)
sigreturn(2)
Therefore you cannot open any new files (or basically do anything). We then come to main and call your code, nicely wrapped in the sandbox
function.
The syscall(SYS_exit, EXIT_SUCCESS);
at the end is just to ensure the program exits cleanly - by default GCC will exit with exit_group(2)
which is not allowed by the SECCOMP whitelist. This exiting function is called after your code is run.
So you have no open file descriptors, and you can't open anything new. Impossible, right? ;)
-
3\$\begingroup\$ cracked \$\endgroup\$2012rcampion– 2012rcampion2017年07月19日 15:40:21 +00:00Commented Jul 19, 2017 at 15:40
x86 16 bit real mode Assembly (Cracked)
_main:
call l
cli
hlt
l: pop si
xor ax, ax
mov bp, cs
mov es, ax
mov di, 12
mov [di], si
mov [di + 2], bp
pushf
mov bp, sp
or word [bp], 256
popf
Easy if you know the trick.
-
1\$\begingroup\$ How are you taking the input? On the stack, or in registers? (Also, it looks like this is supposed to be 16-bit assembly, but if so,
or [bp], 256
is invalid. Is that supposed to beor WORD PTR [bp], 256
?) \$\endgroup\$Cody Gray– Cody Gray2017年07月19日 08:10:58 +00:00Commented Jul 19, 2017 at 8:10 -
1\$\begingroup\$ Also, you should specify which processor you're using; there's lots of x86 versions and clones out there, and lots of undefined instructions. If I wrote code for an "obscure 80186 clone" that just so happened to have an undefined instruction that took a few arguments and blah blah blah... We also might need environment. 16 bit Windows gave an SS==DS guarantee that other systems might not, for example. \$\endgroup\$Orion– Orion2017年07月19日 09:06:00 +00:00Commented Jul 19, 2017 at 9:06
-
1\$\begingroup\$ You only need to specify which processor if you actually are using some trick that works only on one particular model (or one particular generation). This code isn't like that, so I think "x86-16" is sufficient. In my opinion, the more general the better. Agreed that real or protected mode should be specified, although the presence of the
hlt
instruction (ring 0) strongly implies that this is not protected mode. \$\endgroup\$Cody Gray– Cody Gray2017年07月19日 12:30:12 +00:00Commented Jul 19, 2017 at 12:30 -
3\$\begingroup\$ @Joshua if it doesn't work on every platform, you have to at least specify a platform it will work on, I believe.
Your submission must contain enough information before being revealed to be reproducible after being revealed
\$\endgroup\$Stephen– Stephen2017年07月19日 21:08:13 +00:00Commented Jul 19, 2017 at 21:08 -
1\$\begingroup\$ @StepHen: The solution to unbreak the language is platform agnostic once specified x86-16 real mode, but I/O is not platform agnostic. He who breaks out it may specify the OS for which he broke out. I added the _main label late so that someone could in theory make a nearly agnostic break by linking against libc. \$\endgroup\$Joshua– Joshua2017年07月19日 21:11:28 +00:00Commented Jul 19, 2017 at 21:11
cQuents, cracked by Mayube
#|1,1:A
This should be fairly easy, but you never know.
The "problem" was that without C
in your code, you got an error.
Mayube's solution:
#|1,1:A+BC
Each item in the sequence is the first input plus the second times the third (aka 1)
My solutions:
#1,1:A+B,C
The sequence cycles between the first input plus the second input, and the third input (1). The first item in the second is A+B
.
#1,1:A+B+C-C
Similar to Mayube's solution - instead of multiplying B*C
, just adds C
and then subtracts it.
Explanation
#|1,1 Append 1 and 1 to the end of the user's input
: Set mode to : (sequence 1: if given n, output nth term in sequence; if given no n, output whole sequence)
A Each item in the sequence equals the first input
Currently, this program outputs 1
, since with no user input, the first input is the first 1
in the default input (#
).
-
\$\begingroup\$ The docs seem really awkwardly worded, I can't for the life of me figure out what it means when it says
Default input is combined with user input to form the total input, which must align with the expected input (which is based on the highest input requested by the Sequence Definition)
\$\endgroup\$Mayube– Mayube2017年07月19日 14:49:33 +00:00Commented Jul 19, 2017 at 14:49 -
\$\begingroup\$ @Mayube it's weird, I need to find a way to say it correctly. Basically, your input to the program can be equal to the highest input queried by variables
A,B,C,D,E
in the code. For example, if at any point you have the variableD
in your program, the parser expects there to be 4 inputs, but if there is also anE
, the parser expects there to be 5 inputs. There cannot be less than the expected amount. However, there is always an optional last input,n
, which is used in different ways by different modes. \$\endgroup\$Stephen– Stephen2017年07月19日 14:55:42 +00:00Commented Jul 19, 2017 at 14:55 -
\$\begingroup\$ @Mayube the snippet I posted above contains an
A
, so it looks for one input. Since there are two, both coming from#
which specifies default input, it uses the first one asA
's value and the second one asn
. \$\endgroup\$Stephen– Stephen2017年07月19日 14:56:24 +00:00Commented Jul 19, 2017 at 14:56 -
\$\begingroup\$ So if I were to give 2 inputs, and append
BC
, A would be the first input, B would be the second, C would be 1, and n would be the second 1? \$\endgroup\$Mayube– Mayube2017年07月19日 15:12:44 +00:00Commented Jul 19, 2017 at 15:12 -
\$\begingroup\$ @Mayube exactly, sorry for my crappy docs. TMI: if the beginning looked like
#1,1
(no bar), it would be: A as the first 1, B as the second 1, C as the first input, and n as the second input. You can also do#1|1
, where A is the first 1, B is is the first input, C is the second input, and n is the second 1. \$\endgroup\$Stephen– Stephen2017年07月19日 15:15:05 +00:00Commented Jul 19, 2017 at 15:15
Javascript, Cracked
This challenge builds off of Grant Davis's, but fixes the solution he had in mind (which creates an iframe and uses the iframe's window
). The solution runs in the javascript console on chrome's about:blank page
, and takes two input()
s, adds them together, and console.log
s the result. Put your code after:
d=prompt=console=document;new MutationObserver(s=>s.forEach(e=>{t=e.target;t.parentNode.removeChild(t)})).observe(d,{"childList":d, "subtree":d})
First, we clobber prompt
and console
and set the shortcut d
. Then, we create a mutation observer with a callback which removes every target mutated. We set that mutation observer to observe the document, and notify on childList
and subtree
modifications. Instead of the literal true
, we use our shortcut to the truthy value document
(the spec doesn't allow this, but chrome does).
After I posted this, I realized a much more elegant clobber. My intended solution still works, but the crack posted does not:
h=document.querySelector("html");h.parentNode.removeChild(h);
-
\$\begingroup\$ Welcome to the site! I'm interested to see what the solution will be :) \$\endgroup\$DJMcMayhem– DJMcMayhem2017年07月19日 21:17:58 +00:00Commented Jul 19, 2017 at 21:17
-
\$\begingroup\$ I think this counts as a crack. \$\endgroup\$Ilmari Karonen– Ilmari Karonen2017年07月19日 22:31:34 +00:00Commented Jul 19, 2017 at 22:31
Perl 5, cracked by Ilmari Karonen
$_=<DATA>;
s/[+'{dPz|K.UD!_ iJ;o}e6tjWb7253k@%&Iq4l0AN:?\8ドルB`Yywn9^pfmZQTF"M#-]//g;
eval;
print@_,$!,pop,shift,<>,eval"@>",$,円@ARGV,eval"@$",$@,eval"@@",,,ドルeval"@,",$/
__DATA__
Input is received on separate lines of STDIN
and output is printed to STDOUT
.
All code goes after the __DATA__
marker. This uses a similar method to @WheatWizard's solution in that the code is parsed and unusable chars are removed.
This has been tested on versions 5.8, 5.10 and 5.16, and requires no command-line flags.
-
2\$\begingroup\$ Could you please specify the input/output method and format? \$\endgroup\$Ilmari Karonen– Ilmari Karonen2017年07月19日 21:44:18 +00:00Commented Jul 19, 2017 at 21:44
-
\$\begingroup\$ @IlmariKaronen Apologies, it's
STDIN
with chars on separate lines andSTDOUT
. I'll add this to the main body. \$\endgroup\$Dom Hastings– Dom Hastings2017年07月20日 04:37:24 +00:00Commented Jul 20, 2017 at 4:37 -
\$\begingroup\$ Cracked, I think. \$\endgroup\$Ilmari Karonen– Ilmari Karonen2017年07月20日 23:22:32 +00:00Commented Jul 20, 2017 at 23:22
Python 3, cracked by zbw
import sys
for mod in sys.modules.values():mod.__dict__.clear()
1+1
All modlues have been deleted, which means there are no builtins available and not much else can be done. Output to STDOUT, input from STDIN. This is the second iteration of this answer after the previous one was broken by a trivial crack by adding a break statement.
-
\$\begingroup\$ I'm really curious to see the snippet that works after this \$\endgroup\$user52452– user524522017年07月21日 01:50:10 +00:00Commented Jul 21, 2017 at 1:50
-
\$\begingroup\$ Well, you have to wait seven days or for a non-trivial crack, whichever comes first ... \$\endgroup\$The Fifth Marshal– The Fifth Marshal2017年07月21日 02:19:45 +00:00Commented Jul 21, 2017 at 2:19
-
-
\$\begingroup\$ Well, well, challenges like these are very difficult to do well \$\endgroup\$The Fifth Marshal– The Fifth Marshal2017年07月21日 19:23:41 +00:00Commented Jul 21, 2017 at 19:23
APL (ngn-apl), cracked by ngn
Made in cooperation with my colleague Marshall.
Input through left and right arguments to +
. I.e. your goal is to insert code after the the following, so that your last line reads ⎕←3+2
and outputs 5
to STDOUT.
+←-←−←⍴←≢←≡←⊥←⊤←⍟←○しろまる←⍳←⌹←~←∈←∊←⍷←<←≤←=←≥←>←≠←,←⍪←⌷←⌽←⍉←⊖←{}⋄⍣←∘
Works by setting all useful functions to {}
which takes one or two arguments and returns an empty numeric list. Also sets ⍣
to just compose functions.
Crack
+←{⌈/⍋⍺⍵1/0}
⍺⍵1/0
replicate 0 by the left argument and the right argument and 1
⍋
get the indices that would sort that (since all elements are zero, it gives 0 1 2...(a+b)
⌈/
the maximum value (a+b)
-
\$\begingroup\$ ngn/apl includes the ability to execute arbitrary JavaScript. I do not consider such a solution valid, as it would then be about disabling JavaScript rather than APL. There is indeed a valid (albeit obscure) way to reset
+
using only pure APL and no dirty tricks. \$\endgroup\$Adám– Adám2017年07月19日 20:51:23 +00:00Commented Jul 19, 2017 at 20:51
Python 2, Cracked
This is the second iteration of an answer that has been cracked once by @HyperNuetrino using a method I had not expected. I've now patched it so hopefully the only solutions left will have to abide by the restrictions I intended.
Implements addition as a named function
import sys
c="".join(open(__file__).read().split('\n')[4:])
if set(c)-set(' &)(,.:[]a`cdfijmonrt~')or"import"in c:sys.setrecursionlimit(1)
sys.modules['sys'],sys.modules['os']=None,None;del sys;f=lambda\
-
\$\begingroup\$ I think I could do this if I had a
u
, but I'm stuck without it. \$\endgroup\$izzyg– izzyg2017年07月19日 03:21:02 +00:00Commented Jul 19, 2017 at 3:21 -
\$\begingroup\$ @isaacg Just out of curiosity, what would you to with
u
? \$\endgroup\$2017年07月19日 03:21:52 +00:00Commented Jul 19, 2017 at 3:21 -
\$\begingroup\$
.count
. I can get a string as long as the desired output, but I have no way to take its length. \$\endgroup\$izzyg– izzyg2017年07月19日 03:22:56 +00:00Commented Jul 19, 2017 at 3:22 -
\$\begingroup\$
__import__('sys').setrecursionlimit(100)
... and nothing actually got patched. I don't really feel like posting it in the robber's thread though, feels like cheating. Try it online \$\endgroup\$Value Ink– Value Ink2017年07月19日 03:27:03 +00:00Commented Jul 19, 2017 at 3:27 -
2\$\begingroup\$ Cracked, I think? \$\endgroup\$Sisyphus– Sisyphus2017年07月19日 04:13:42 +00:00Commented Jul 19, 2017 at 4:13
Java 8, Cracked by @OlivierGrégoire
Here's my attempt. Pretty much, the idea is to just overload all the namespaces you can use to output (and reflect, I hope). Output is intended to sdout (System.out).
class java {
public static void main(String[]s){
//there is no executable code in snippet one.
//your code here.
}
class Class{}
class Method{}
class System{}
class FileDescriptor{}
class Logger{}
class Runtime{}
class Scanner{}
}
Blacklisting is typically a worse approach than whitelisting, so I'm sure it's just a matter of time before someone comes up with an approach I didn't consider.
-
1\$\begingroup\$ This is not an executable class... \$\endgroup\$Olivier Grégoire– Olivier Grégoire2017年07月19日 14:26:20 +00:00Commented Jul 19, 2017 at 14:26
-
1\$\begingroup\$ @OlivierGrégoire Sorry about that, I added
class String{}
after testing without realizing it would knock outmain(String[] ...)
. It should work now \$\endgroup\$Lord Farquaad– Lord Farquaad2017年07月19日 14:30:48 +00:00Commented Jul 19, 2017 at 14:30 -
1\$\begingroup\$ Yep, that'll do it, thank you! :) It doesn't change the crack I'm about to do, though :p \$\endgroup\$Olivier Grégoire– Olivier Grégoire2017年07月19日 14:33:58 +00:00Commented Jul 19, 2017 at 14:33
-
1\$\begingroup\$ Cracked! I really enjoyed this one :) \$\endgroup\$Olivier Grégoire– Olivier Grégoire2017年07月19日 14:57:11 +00:00Commented Jul 19, 2017 at 14:57
-
1\$\begingroup\$ I was looking at something like this (sorry it's hard to format code in comments), but I think your solution is much cleaner:
int sum = 0; new Exception("" + sum) { public void printStackTrace() { ClassLoader cl = ClassLoader.getSystemClassLoader(); try { printStackTrace(new PrintStream((PrintStream)cl.loadClass("java.lang.System").getDeclaredField("out").get(null))); } catch (Exception e){} } }.printStackTrace();
\$\endgroup\$Lord Farquaad– Lord Farquaad2017年07月19日 15:24:26 +00:00Commented Jul 19, 2017 at 15:24
Node.JS version 7.3.0 (Cracked by Dom Hastings)
var p=process,f;(_=>{var w=p.stdout.write,n='f'+(Math.random()*1e7|0),l=1
f=p.stdout.write=a=>eval(`(function ${n}(a){while(l&&((typeof a)[0]!='s'||'f'+a!=n));a=l?l="":a;w.apply(p.stdout,arguments);})`)(a)})();
Place the second code block after the first.
Disclaimer: the second code block will not function on its own (without being placed after the first). If this is not allowed however I can modify the second snippet.
This is a full program. Output is process.stdout
(STDOUT), input is process.argv
(command line arguments)
This is my first cops and robbers, hopefully this is a good challenge :)
The challenge explained
Generates a random variable n
from 0 to 1e7. If you call write with the correct n
, doesn't print anything but sets l
to 0 which "unlocks" the write function, allowing you to print anything. If you try to call write with a non-string, sends you into an infinite loop. If you try to call write with anything other than the correct n
while write is "locked", sends you into an infinite loop to prevent guessing.
The intended solution
Sneaks past the typeof that seemingly checks for strings only by using a Symbol, which also starts with s. This throws an error in the function resulting from the eval call because you can't add the string "f" to a Symbol. We catch the error and use regex to recover n
from the stack trace, where it is in the function's name. Then we try to write n
which doesn't print anything, but sets the "lock" variable l
to 0 to "unlock" the write function. Now that the write function is unlocked we just print the sum.
try{f(Symbol())}catch(e){f(e.stack.match(/f(\d+)/)[1])
f(+p.argv[2]+ +p.argv[3]+"")}
-
\$\begingroup\$ Cracked! \$\endgroup\$Dom Hastings– Dom Hastings2017年07月20日 17:00:20 +00:00Commented Jul 20, 2017 at 17:00
-
\$\begingroup\$ That's genius... I was on the right track originally then! Thanks for the brain training! \$\endgroup\$Dom Hastings– Dom Hastings2017年07月20日 18:06:23 +00:00Commented Jul 20, 2017 at 18:06
RProgN2, Cracked by Arnold Palmer
"+-/*÷^"{2[[\=};
Writes over all the math operators, with no way to restore them. In particular, it replaces them with a function that removes the top two items on the stack.
Original Solution
{S]‘[L}`d={0RL}`i=«x=y=x{xd`x=yi`y=x}:y»`+=
{S]‘[L}`d={0RL}`i=«x=y=x{xd`x=yi`y=x}:y»`+=
{ }`d= #Define a function, "d", which returns n-1
S #Convert the input to a stack, which, as a number, makes a stack of 1 - n.
]‘ #Duplicate the stack, and pop the top value off it.
[ #Discard the popped'd value.
L #Get the length of the stack, which now is n-1.
{ }`i= #Define a function, "i", which returns n+1
0R #Get the range of numbers between 0 and n.
L #Get the length of that stack, which is n+1
« »`+= #Define a function, "+", which takes two numbers, and outputs their sum. We use «» here, because it localises references, instead of globalising them.
x= #Set the first input to the value of "x", which by default, is x.
y= #Ditto for y.
x{ x}: #While x is truthy, which in this case, is non-zero.
xd #Get x - 1
`x= #Set x to it.
yi`y= #And set y to y + 1
y #Push y to the output. And we're done.
-
\$\begingroup\$ I'm going through your documentation and I can't seem to find what the
²
symbol does. Care to enlighten me? \$\endgroup\$Arnold Palmer– Arnold Palmer2017年07月19日 17:31:02 +00:00Commented Jul 19, 2017 at 17:31 -
\$\begingroup\$ That documentation is not incredibly relevant for RProgN2, and that symbol takes the next two concepts
[[
in this case, and wraps them in a function @ArnoldPalmer \$\endgroup\$ATaco– ATaco2017年07月19日 21:25:21 +00:00Commented Jul 19, 2017 at 21:25 -
\$\begingroup\$ Cracked \$\endgroup\$Arnold Palmer– Arnold Palmer2017年07月20日 13:03:42 +00:00Commented Jul 20, 2017 at 13:03
-
\$\begingroup\$ Dang, that's much better. I didn't know about the stack operators, which sure would've been handy. Also, knowing
«»
creates local variables as opposed to messing up global ones would've been super helpful. \$\endgroup\$Arnold Palmer– Arnold Palmer2017年07月21日 10:32:39 +00:00Commented Jul 21, 2017 at 10:32
Haskell, (削除) 161 (削除ここまで) 144 bytes, Cracked by BlackCap
{-#OPTIONS_GHC -fth -w#-}
module M where
Input to STDIN, output to STDERR. Add to the end of the program.
Edit: Intended to be compiled with no extra GHC arguments, just the normal ghc --make prog.hs
.
Edited again to lower the byte count.
Have fun!
-
\$\begingroup\$ So I cannot do this, because the main function won't be called?
main = do x <- readLn :: IO Integer; y <- readLn; print $ x + y
\$\endgroup\$BlackCap– BlackCap2017年07月22日 00:11:10 +00:00Commented Jul 22, 2017 at 0:11 -
\$\begingroup\$ @BlackCap No, because GHC expects the
main
function to be in the moduleMain
when no-main-is
flag is provided. \$\endgroup\$zbw– zbw2017年07月22日 17:18:23 +00:00Commented Jul 22, 2017 at 17:18 -
-
-
\$\begingroup\$ If you post your solution, I'll mark it cracked. \$\endgroup\$zbw– zbw2017年07月24日 01:55:20 +00:00Commented Jul 24, 2017 at 1:55
Mascarpone, cracked by Ilmari Karonen
[ Make 'i' and 'z' print 'q' ]$
v ['q.]v* 'i<^
v ['q.]v* 'z<^
[ Disable some standard commands ]$
v[]v* '1<^
v[]v* '$<^
v[]v* '@<^
v[]v* '{<^
v[]v* '}<^
v[<:]v* '<<^
v[]v* 'v<^$
Input is church numerals on stdio, using i
for increment and z
for zero. For instance, 2+3 would be:
iiziiiz
With a trailing newline
Output should be a number on stdout, in the same format as on stdio. For example, if the answer is five you should output:
iiiiiz
(mascarpone has no concept of numbers)
Intended solution:
: '[/''/'i/'./' /':/',/'>/'!/']/* 'i<^
: '[/':/',/'>/'!/']/* 'z<^
: ,>!
'z.
It is not immediately apparent from the documentation, but as @IlmariKaronen stated in his crack, string literals in Mascarpone are actually syntactic sugar for pushing a sequence of characters.
I deliberately wrote comments like [this]$
to make it look like I am pushing a string and popping it immediately afterwards. A naive cracker might have tried something like [:,>!]/*
to push a string, swap it with the interpreter, and interpret it.
I also pretend to pop the interpreter I left on the stack with $
, but $
has already been redefined to a NOP. You are left with this interpreter on the stack, and you have to carry it with you trough the entire program; trough each character of every string.
-
\$\begingroup\$ Cracked. And no, I'd never heard of Mascarpone before this challenge. \$\endgroup\$Ilmari Karonen– Ilmari Karonen2017年07月25日 22:14:10 +00:00Commented Jul 25, 2017 at 22:14
-
\$\begingroup\$ @IlmariKaronen New favorite language? Good job! \$\endgroup\$BlackCap– BlackCap2017年07月25日 23:16:23 +00:00Commented Jul 25, 2017 at 23:16
Gforth 0.7.3 (TIO), 231 bytes [SAFE]
This code redefines as useless some necessary output methods, as well as addition and something crucial for declaring functions. Good luck!
: . ;
: dec. ;
: u. ;
: .r ;
: u.r ;
: d. ;
: ud. ;
: d.r ;
: ud.r ;
: emit ;
: type ;
: + postpone 2drop ;
: ; + + + postpone exit reveal postpone [ ;
Input will be two signed integers taken from the top of the stack as function parameters. Output to STDOUT.
So you should fix the damage done, and define a function that takes the top two values from the stack and prints the result as an integer (not a float) to STDOUT without additional output (no trailing space).
Here's a template, if your goal function is named f
.
Solution:
79 bytes
I actually removed theimmediate
keyword from the end of the redefinition of;
, so it was necessary for an answer to include it at the start. The function I defined is mostly equivalent to the internal definition of.
, but it doesn't print the space at the end, and the addition is performed first, by moving the numbers to the floating point stack and back.
immediate : f s>f s>f f+ f>d swap over dabs <<# #s rot sign #> (type) #>> 0 0 ;
Try it online
-
1\$\begingroup\$ This is a very nice answer. At this rate, it looks like it might end up being the only uncracked answer! \$\endgroup\$DJMcMayhem– DJMcMayhem2017年07月25日 16:24:58 +00:00Commented Jul 25, 2017 at 16:24
-
\$\begingroup\$ :) I combined a couple of different obstacles. At this point, I'm wondering if I could've done just a single one to make my score better. But it's possible that having more than one is why it's uncracked yet. \$\endgroup\$mbomb007– mbomb0072017年07月25日 18:08:29 +00:00Commented Jul 25, 2017 at 18:08
C# (.NET Core) Cracked by Ilmari Karonen
namespace System
{
class Console
{
static void Main()
{
//Your code goes here
}
}
}
Reads the two values from stdin and writes the result to stdout. Tested on Windows with Framework Version 3, 4.6 and on TIO.
Here is the full program I had intended.
namespace System
{
class Console
{
static void Main()
{
var t = Reflection.Assembly.Load("mscorlib").GetType("System.Console");
var r = t.GetMethod("ReadLine");
int a = int.Parse((string)r.Invoke(null, null));
int b = int.Parse((string)r.Invoke(null, null));
var w = t.GetMethod("WriteLine", new[] { typeof(int) });
w.Invoke(null, new object[] { a + b });
}
}
}
-
\$\begingroup\$ Cracked. \$\endgroup\$Ilmari Karonen– Ilmari Karonen2017年07月19日 17:44:30 +00:00Commented Jul 19, 2017 at 17:44
-
\$\begingroup\$ codegolf.stackexchange.com/a/133412/14306 I assume this wasn't the intended solution. \$\endgroup\$Joshua– Joshua2017年07月19日 17:54:54 +00:00Commented Jul 19, 2017 at 17:54
-
\$\begingroup\$ @IlmariKaronen: +1. This was the intended solution. \$\endgroup\$raznagul– raznagul2017年07月20日 07:35:41 +00:00Commented Jul 20, 2017 at 7:35
-
\$\begingroup\$ @Joshua: +1 for finding a different solution than I had intended. \$\endgroup\$raznagul– raznagul2017年07月20日 07:38:08 +00:00Commented Jul 20, 2017 at 7:38
GolfScript, cracked by Dennis
{}' !$%&()*+,-./<=>?@[\]^`|~'':'*~;
This is a code-golf challenge, after all, so why not try GolfScript?
A valid solution should be a snippet that reads two integers off the stack, adds them together and returns the result on the stack. The catch is that it should still work even after the code above has redefined almost all of the built-in GolfScript operators to do abolutely nothing. At least I left ;
untouched, so you can still pop values off the stack. ;-) Your code should work on the standard GolfScript interpreter, as implemented e.g. on TIO (see link above).
Dennis' solution, like my own, relies on the rarely used feature of GolfScript that allows interpolated Ruby code in double quoted strings. We use this feature to define a new addition operator that works exactly like the built-in +
operator, and then call it.
(One reason why the Ruby interpolation feature in GolfScript is so rarely used is that, awkwardly, the interpolated Ruby code is executed during parsing, and its output is cached by the GolfScript interpreter. Thus, if you e.g. have a string with interpolated Ruby code in a loop, the code will run only once before the actual program starts and thereafter always return the same value on every iteration of the loop. You can work around that using string eval to defer parsing, but that makes the already awkward syntax even more ugly and verbose, and in any case, for this challenge I disabled the eval operator ~
, too. However, it turns out that defining new built-in GolfScript operators is one thing this feature actually does quite nicely and cleanly.)
-
\$\begingroup\$ Hint \$\endgroup\$CalculatorFeline– CalculatorFeline2017年07月19日 17:32:56 +00:00Commented Jul 19, 2017 at 17:32
-
-
\$\begingroup\$ @Dennis: Yeah, you nailed it this time. FWIW, my intended solution was
"#{var'_','gpush a+b'.cc2}";_
, which works exactly like yours except for being a few bytes shorter. \$\endgroup\$Ilmari Karonen– Ilmari Karonen2017年07月20日 10:37:54 +00:00Commented Jul 20, 2017 at 10:37
Node.js v8.2.0, Cracked by Dom Hastings
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 => /* Your code here */;
log . id . num ( logic (ap (dot) (x))
(f => z => (( y(flip (id) . id . flip (dot (id)) (f)) ) (Const (z))) (id) )
);
}
You are to implement the logic
function. Input is the arguments provided (from stdin), output is whatever your function returns (is printed to stdout).
My code church encodes the numbers from the input. The rest of the code is just there to intimidate you.
The mess function does some trickery to implement point-free notation (a . b == dot (a) (b)
), which I primarely use to add . id .
to random places, which doesn't do anything, but will confuse anyone unfamiliar with functional programming.
The transformation applied to the numbers before I pass them to the logic
function is x+1
and y-1
, which adds up to 0, so it's another NOP to add to the obscurity.
The intended solution was:
logic = x => y => f => z => x (f) (y (f) (z))
-
1\$\begingroup\$ Cracked! \$\endgroup\$Dom Hastings– Dom Hastings2017年07月20日 17:36:04 +00:00Commented Jul 20, 2017 at 17:36
-
\$\begingroup\$ @DomHastings That's not the intended solution, but I'm gonna say that you can, as long as the program halts without an exception, and doesn't print additional characters to the output \$\endgroup\$BlackCap– BlackCap2017年07月20日 17:37:06 +00:00Commented Jul 20, 2017 at 17:37
-
\$\begingroup\$ I've just posted an alternative! (You can see my previous solution in the history of that answer though!) \$\endgroup\$Dom Hastings– Dom Hastings2017年07月20日 17:37:56 +00:00Commented Jul 20, 2017 at 17:37
-
\$\begingroup\$ Oh wow, I was a way off... Still that's better than my first very cheaty attempt! Thanks for the puzzle! \$\endgroup\$Dom Hastings– Dom Hastings2017年07月20日 17:43:31 +00:00Commented Jul 20, 2017 at 17:43
Inform 7, cracked by ppperry
For reading a command: rule fails.
[Your code here.]
The input should be typed by the player as an interactive command, e.g. add 17 to 25
or sum 17 25
. You're free to choose the exact form of the command that should be entered, as long as it includes two numbers. The sum of the numbers (e.g. 42
) should be printed in response to the command.
The challenge, of course, is doing that while the entire "reading a command" activity is replaced by a no-op. There are probably several ways to solve this problem, but at least it should require some familiarity with the language. The one I came up with is actually quite simple, if a bit unexpected.
I've tested my solution in the GNOME Inform 7 IDE, version 6L38, on Ubuntu Linux. The intended solution works on both the Glulx and the Z-machine back-ends, and should work on other recent versions of Inform 7, too. Note that (without a suitable work-around) the code above will cause the interpreter to busy-loop when it tries to read a command; the Z-machine interpreter seems to become completely unresponsive when this happens, and can't be stopped from within the IDE, so I recommend using Glulx for testing.
-
\$\begingroup\$ cracked, and in case you were wondering, I had never heard of inform before this challenge \$\endgroup\$The Fifth Marshal– The Fifth Marshal2017年07月21日 22:30:35 +00:00Commented Jul 21, 2017 at 22:30
CPython 3 (again), cracked by Sisyphus
import sys,os,functools
def p(f,e,a,_=os._exit):
if e == "c_call":_(1)
sys.setprofile(p)
You can do anything you want -- as long as it isn't implemented in C. This means no print
, no input
-- all of those will hit the _(1)
line and terminate. Input from STDIN with the numbers on two seperate lines, output to STDOUT. I wonder how long this is going to last ... Took me quite a while to find the second working snippet after coming up with this disabling trick. Explicitly specifying Cpython to avoid being cracked based non some alternative implementation of sys.setprofile.
-
-
\$\begingroup\$ I guess I can ask now: why
functools
? \$\endgroup\$Dennis– Dennis2017年07月22日 06:29:26 +00:00Commented Jul 22, 2017 at 6:29 -
\$\begingroup\$ @Dennis Because sispyphus discovered a loophole, not the intended solution \$\endgroup\$The Fifth Marshal– The Fifth Marshal2017年07月22日 12:14:45 +00:00Commented Jul 22, 2017 at 12:14
-
\$\begingroup\$ @Sisyphus Your crack has been reported as a bug in python \$\endgroup\$The Fifth Marshal– The Fifth Marshal2017年07月22日 12:52:55 +00:00Commented Jul 22, 2017 at 12:52
Java 8 (Cracked)
Second attempt. This time I invested two minutes of testing.
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);
// Your code goes here.
} catch (Throwable t) {
}
}
Most things shouuuld be covered.
-
1\$\begingroup\$ Would you please enclose this in a class with appropriate imports? It's the kind of challenge where this small changes can make or break an entry. I got several solutions for this one as is, but that reduces drastically if you simply enclose this in a class / interface. Also, format to remove all those while lines would be pretty nice for us, readers. \$\endgroup\$Olivier Grégoire– Olivier Grégoire2017年07月19日 13:47:01 +00:00Commented Jul 19, 2017 at 13:47
-
\$\begingroup\$ There, a cracked answer using exactly your code. And a +1 because it seems I forgot it. Sorry. \$\endgroup\$Olivier Grégoire– Olivier Grégoire2017年07月19日 15:23:21 +00:00Commented Jul 19, 2017 at 15:23
-
\$\begingroup\$ The #setAccessible(false) calls do nothing. \$\endgroup\$Nevay– Nevay2017年07月19日 21:48:03 +00:00Commented Jul 19, 2017 at 21:48
Python 2 cracked
import sys,hashlib
c=open(__file__).read().split()[-1]
if c!='#'and hashlib.sha256(c).hexdigest()!='e6400dd63733d10ec042e3c28033cfa85e1d25fbef80020810c354d7c942e843':sys.exit() #
I'll preface this by saying this answer is a jerk move, intended as a lower-bound answer.
Inspired by Wheat Wizard's and HyperNeutrino's answers.
The snippet reads the source file and refuses to continue if the last whitespace-separated chunk of code does not sha256 into e6400dd63733d10ec042e3c28033cfa85e1d25fbef80020810c354d7c942e843
.
EDIT: Edited slightly in response to this comment. The core problem does not change, any crack attempt is not invalidated.
-
1\$\begingroup\$ RE the first snippet:
This code is not allowed to crash or exit.
\$\endgroup\$Stephen– Stephen2017年07月19日 02:19:22 +00:00Commented Jul 19, 2017 at 2:19 -
\$\begingroup\$ This is invalid because it exits, which is not allowed for the first snippet. \$\endgroup\$DJMcMayhem– DJMcMayhem2017年07月19日 02:40:05 +00:00Commented Jul 19, 2017 at 2:40
-
1
Java 8 Cracked by @OlivierGrégoire
I tried to make it as hard as possible! :) And, unlike the other Java answer so far, you'll have to follow the exact rules of the challenge, by placing it after this entire snippet (so no, you don't put your code in the public static void main(String[] args)
method, you put it after the entire class. :) Good luck!
I've added comments to show what is being restricted.
(Inspired by this post, which is less restrictive and beatiable with the same approach I could use for my answer.)
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileDescriptor;
import java.io.FilePermission;
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class Main {
// Put everything in a static block so it is run before the static main method
// and any trailing (static) initializer-blocks:
static {
try {
initializing();
} catch (final Exception e) {
}
}
static void initializing() throws Exception {
// Overwrite System.out, System.err and System.in:
System.setOut(new PrintStream(new ByteArrayOutputStream()));
System.setErr(new PrintStream(new ByteArrayOutputStream()));
System.setIn(new ByteArrayInputStream(new byte[0]));
// Enable reflection for System.out, System.err and System.in:
final Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
final Class<?> fdClass = java.io.FileDescriptor.class;
final Field outField = fdClass.getDeclaredField("out");
outField.setAccessible(true);
modifiersField.setInt(outField, outField.getModifiers() & ~Modifier.FINAL);
final Field errField = fdClass.getDeclaredField("err");
errField.setAccessible(true);
modifiersField.setInt(errField, errField.getModifiers() & ~Modifier.FINAL);
final Field inField = fdClass.getDeclaredField("in");
inField.setAccessible(true);
modifiersField.setInt(inField, inField.getModifiers() & ~Modifier.FINAL);
// Replace existing System.out FileDescriptor with a new (useless) one:
outField.set(null, new FileDescriptor());
// Replace existing System.err FileDescriptor with a new (useless) one:
errField.set(null, new FileDescriptor());
// Replace existing System.in FileDescriptor with a new (useless) one:
inField.set(null, new FileDescriptor());
// Disable reflection for System.out, System.err, System.in again:
modifiersField.setInt(outField, outField.getModifiers() & ~Modifier.FINAL);
modifiersField.setInt(errField, errField.getModifiers() & ~Modifier.FINAL);
modifiersField.setInt(inField, inField.getModifiers() & ~Modifier.FINAL);
inField.setAccessible(false);
errField.setAccessible(false);
outField.setAccessible(false);
modifiersField.setAccessible(false);
// Overwrite the SecurityManager:
System.setSecurityManager(new SecurityManager() {
private boolean exitAllowed = false;
@Override
public void checkExec(final String cmd) {
throw new SecurityException();
}
@Override
public void checkPermission(final java.security.Permission perm) {
final String name = perm.getName();
// You're not allowed to read/write files:
if (name.equals("setIO") || name.equals("writeFileDescriptor")
|| name.equals("readFileDescriptor")
|| ((perm instanceof FilePermission) && name.startsWith("/proc/self/fd/"))) {
throw new SecurityException();
}
// You're not allowed to overwrite the Security settings:
if (name.equals("setSecurityManager") || name.equals("suppressAccessChecks")) {
throw new SecurityException();
}
// You're not allowed to use reflection anymore:
if (name.equals("getModifiers") || name.equals("get") || name.equals("set")
|| name.equals("setBoolean") || name.equals("setByte")
|| name.equals("setChar") || name.equals("setShort") || name.equals("setInt")
|| name.equals("setLong") || name.equals("setFloat") || name.equals("setDouble")
|| name.equals("setFieldAccessor") || name.equals("setFieldAccessor")) {
throw new SecurityException();
}
// When you try to leave the current VM it will stop the program:
if (name.startsWith("exitVM") && !this.exitAllowed) {
this.exitAllowed = true;
System.exit(0);
}
// You know what, nothing is allowed!
throw new SecurityException("Mhuahahahaha!");
}
});
}
public static void main(String[] args) {
// Overwritting all given arguments:
args = new String[0];
// Exit the program before you can do anything!
System.exit(0);
}
}
// Your code goes below:
Try it here. (ideone.com instead of TIO, since it doesn't seem to work there.. Testing has been done in the Eclipse IDE, but my intended solution does work if you use ideone.com)
-
1\$\begingroup\$ Cracked! \$\endgroup\$Olivier Grégoire– Olivier Grégoire2017年07月19日 14:11:34 +00:00Commented Jul 19, 2017 at 14:11
Jelly: CRACKED
This will be insanely easy compared to Wheat Wizard's awesome Python answer, but here we go :P
"for c in code_page:
if c in atoms:atoms[c].call=None"ŒVø<insert code snippet here>
The sha256 hexdigest of my workaround solution, including the first snippet, is cfeb1e193ad77f66f039c0d6a792a3e4c311490f6412698e019ca1fae10c0e0a
.
Note
You may not have any newlines in the code except for strings otherwise this code will not even be run, which defeats the purpose of this challenge.
Cracked by DJMcMayhem
To be fair, this uses a newline, so I'd like to see a solution that doesn't use a newline.
Also a solution by Jonathan Allan
This doesn't use a newline, so it's been cracked. :P
My solution is this:
"for c in code_page:
if c in atoms:atoms[c].call=None"ŒVø"print(int(input())+int(input()))"ŒV
The first snippet only deletes single character atoms which means that Python eval still works :)))
-
\$\begingroup\$ The second snippet is always appended to the end of the first snippet. \$\endgroup\$Stephen– Stephen2017年07月19日 01:38:55 +00:00Commented Jul 19, 2017 at 1:38
-
\$\begingroup\$ @StepHen Just specifying :P But I forgot to add the note; that's really important. \$\endgroup\$2017年07月19日 01:42:20 +00:00Commented Jul 19, 2017 at 1:42
-
3\$\begingroup\$ I don't think you can restrict the robbers like that. If you can crack it with Newlines, that's a valid crack. Is there anyway to prevent Newlines from being added, or forcing the first line to be executed? \$\endgroup\$DJMcMayhem– DJMcMayhem2017年07月19日 01:49:13 +00:00Commented Jul 19, 2017 at 1:49
-
2\$\begingroup\$ codegolf.stackexchange.com/a/133213/31716 \$\endgroup\$DJMcMayhem– DJMcMayhem2017年07月19日 02:49:21 +00:00Commented Jul 19, 2017 at 2:49
-
1\$\begingroup\$ I like your intended crack. Very sneaky. \$\endgroup\$Dennis– Dennis2017年07月20日 03:21:29 +00:00Commented Jul 20, 2017 at 3:21
JavaScript, Cracked
Input: prompt()
twice
Output: console.log()
My solution does not work in jsfiddle. Works on the about:blank page with Google chrome's JS console.
prompt=console=0
My solution:
x=document.createElement("iframe")
x.src="data:text/html,<script>console.log(prompt()-0+(prompt()-0))</script>"
document.body.appendChild(x)
Explanation:
I removed prompt and console by setting them equal to 0.
In my solution I create an iframe, which creates a sandbox, and a new instance of window where prompt and console work properly.
-
1\$\begingroup\$ Cracked? \$\endgroup\$Ilmari Karonen– Ilmari Karonen2017年07月19日 15:49:14 +00:00Commented Jul 19, 2017 at 15:49
-
\$\begingroup\$ @CRDrost I don't believe there is primality testing in the spec, and you don't show both snippets. \$\endgroup\$Stephen– Stephen2017年07月19日 21:21:15 +00:00Commented Jul 19, 2017 at 21:21
-
\$\begingroup\$ Sorry, you're right, I misread. \$\endgroup\$CR Drost– CR Drost2017年07月19日 21:45:46 +00:00Commented Jul 19, 2017 at 21:45
Java, Cracked
import java.lang.reflect.*;
public class Main{
public static void main(String... args){
System.setOut(null);
System.setErr(null);
/*Your code here*/
}
}
This (削除) should be (削除ここまで) was very easy to crack.
Intended solution
import java.lang.reflect.*;
public class Main{
public static void main(String... args){
System.setOut(null);
System.setErr(null);
try{
Class<?> cistream = Class.forName("java.io.InputStream");
Class<?> cfostream = Class.forName("java.io.FileOutputStream");
Class<?> costream = Class.forName("java.io.OutputStream");
Class<?> cfdescriptor = Class.forName("java.io.FileDescriptor");
Object sout = cfostream.getConstructor(cfdescriptor).newInstance(cfdescriptor.getField("out").get(null));
Class<?> csys = Class.forName("java.lang.System");
Field mod = Field.class.getDeclaredField("modifiers");
mod.setAccessible(true);
Field stdout = csys.getField("out");
mod.set(stdout,Integer.class.cast(mod.get(stdout) )&~ Modifier.FINAL);
stdout.set(null,Class.forName("java.io.PrintStream").getConstructor(costream).newInstance(sout));
Class<?> cscanner = Class.forName("java.util.Scanner");
Object scanner = cscanner.getConstructor(cistream).newInstance(System.in);
Method nextInt = cscanner.getMethod("nextInt");
int f = Integer.class.cast(nextInt.invoke(scanner));
int s = Integer.class.cast(nextInt.invoke(scanner));
int sum = s + f;
System.out.println(sum);
}catch(Throwable t){t.printStackTrace();}
}
}
-
\$\begingroup\$ I think this is valid \$\endgroup\$Salem– Salem2017年07月19日 09:17:50 +00:00Commented Jul 19, 2017 at 9:17
-
\$\begingroup\$ I totally forgot about
java.io
.. But you got the intended solution anyways.. \$\endgroup\$Linnea Gräf– Linnea Gräf2017年07月19日 09:35:50 +00:00Commented Jul 19, 2017 at 9:35 -
\$\begingroup\$ I don't see any problem here. I actually wrote the second snipet just forgot to edit it on. According to TIO the first snipppet compiles without any warning. \$\endgroup\$Linnea Gräf– Linnea Gräf2017年07月19日 13:12:30 +00:00Commented Jul 19, 2017 at 13:12
-
\$\begingroup\$ @OlivierGrégoire Done. I think any IDE will yell at me for this but I at least the compiler accepts it... \$\endgroup\$Linnea Gräf– Linnea Gräf2017年07月19日 16:15:55 +00:00Commented Jul 19, 2017 at 16:15
Explore related questions
See similar questions with these tags.
int main(){ do_evil_stuff(); }
where should the users code go? In a function? After all the statements inmain
? \$\endgroup\$