digitalmars.D - Obfuscated code challenge
- Phillip Meyer (4/4) Mar 13 2021 See if you can figure out what this code does without running it
See if you can figure out what this code does without running it
;)
import std;void main(){(*["clung/locks"].tee!(function(x){return
x;}).array.ptr).enumerate.map!(i=>mixin(cast(typeof({}))(6.8*13.3824)~"6r0d2a5
".array.chunks(2).map!(i=>[i[0].to!string~":"~39~(i[1].to!string)~'\''][0]).join(",")~"]").get(i[0],i[1])).writeln;}
Mar 13 2021
On Sunday, 14 March 2021 at 01:31:36 UTC, Phillip Meyer wrote:See if you can figure out what this code does without running it ;)Nope. I couldn't make sense of the mixin. (Also, this only works because of a compiler bug that I didn't know about.)import std;void main(){(*["clung/locks"].tee!(function(x){return x;}).array.ptr).enumerate.map!(i=>mixin(cast(typeof({}))(6.8*13.3824)~"6r0d2a5 ".array.chunks(2).map!(i=>[i[0].to!string~":"~39~(i[1].to!string)~'\''][0]).join(",")~"]").get(i[0],i[1])).writeln;}WAT?! Why is concatenating a function pointer with a char string not an error, even in system code? unittest { // This passes! assert(is(typeof(cast(typeof({})) 91) == void function() pure safe nothrow nogc)); assert((cast(typeof({})) 91) ~ "" == "["); } I filed a DMD issue: https://issues.dlang.org/show_bug.cgi?id=21711
Mar 13 2021
On 14.03.21 02:31, Phillip Meyer wrote:
See if you can figure out what this code does without running it ;)
import std;void main(){(*["clung/locks"].tee!(function(x){return
x;}).array.ptr).enumerate.map!(i=>mixin(cast(typeof({}))(6.8*13.3824)~"6r0d2a5
".array.chunks(2).map!(i=>[i[0].to!string~":"~39~(i[1].to!string)~'\''][0]).join(",")~"]").get(i
0],i[1])).writeln;}
First, format the code a bit:
----
import std;
void main()
{
(*["clung/locks"].tee!(function(x) { return x; }).array.ptr)
.enumerate
.map!(i =>
mixin(
cast(typeof({}))(6.8 * 13.3824) ~
"6r0d2a5 ".array.chunks(2)
.map!(i => i[0].to!string ~ ":" ~ 39 ~ i[1].to!string ~
'\'')
.join(",") ~
"]"
)
.get(i[0], i[1])
)
.writeln;
}
----
Now piece by piece:
(*["clung/locks"].tee!(function(x) { return x; }).array.ptr)
-> "clung/locks"
":" ~ 39
-> ":'"
"6r0d2a5 ".array.chunks(2)
-> ["6r", "0d", "2a", "5 "]
["6r", "0d", "2a", "5 "].map!(...).join(",")
-> "6:'r',0:'d',2:'a',5:' '"
From context, guess that `cast(typeof({}))(6.8 * 13.3824)` becomes
char(6.8 * 13.3824) = char(91) = '['.
The mixin is now trivial:
mixin('[' ~ "6:'r',0:'d',2:'a',5:' '" ~ "]")
-> [6: 'r', 0: 'd', 2: 'a', 5: ' ']
The outer `map` effectively replaces characters in "clung/locks" with
the values from the mixed in associative array. So:
"clung/locks"[6] = 'r' -> "clung/rocks"
"clung/rocks"[0] = 'd' -> "dlung/rocks"
"dlung/rocks"[2] = 'a' -> "dlang/rocks"
"dlang/rocks"[5] = ' ' -> "dlang rocks"
And there it is:
----
import std;
void main() { "dlang rocks".writeln; }
----
Mar 14 2021
On Sunday, 14 March 2021 at 01:31:36 UTC, Phillip Meyer wrote:
See if you can figure out what this code does without running
it ;)
import std;void
main(){(*["clung/locks"].tee!(function(x){return
x;}).array.ptr).enumerate.map!(i=>mixin(cast(typeof({}))(6.8*13.3824)~"6r0d2a5
".array.chunks(2).map!(i=>[i[0].to!string~":"~39~(i[1].to!string)~'\''][0]).join(",")~"]").get(i[0],i[1])).writeln;}
SPOILER ALERT: my result at bottom of the post.
Hmm, trying this blindly. No quarantees about right result. I'll
try to figure it out by refactoring in phases. First, some
reformatting:
```
import std;
void main()
{ (*["clung/locks"].tee!(function(x){return x;}).array.ptr)
.enumerate
.map!(
i=>
mixin(cast(typeof({}))(6.8*13.3824)~"6r0d2a5
".array.chunks(2).map!(i=>[i[0].to!string~":"~39~(i[1].to!string)~'\''][0]).join(",")~"]")
.get(i[0],i[1])
)
.writeln;
}
```
Let's sanitize the top of the function a bit:
```
import std;
void main()
{ "clung/locks".enumerate
.map!(
i=>
mixin(cast(typeof({}))(6.8*13.3824)~"6r0d2a5
".array.chunks(2).map!(i=>[i[0].to!string~":"~39~(i[1].to!string)~'\''][0]).join(",")~"]")
.get(i[0],i[1])
)
.writeln;
}
```
Next we move the ugliest bit to a different function:
```
import std;
void main()
{ "clung/locks".enumerate
.map!(i=>handleUglyDetails(i.index, i.value))
.writeln;
}
auto handleUglyDetails(size_t index, dchar value)
{ auto something = mixin(cast(typeof({}))(6.8*13.3824)~"6r0d2a5
".array.chunks(2).map!(i=>[i[0].to!string~":"~39~(i[1].to!string)~'\''][0]).join(",")~"]");
return something.get(index, value);
}
```
Omitting the top import and `main()` from rest of the examples as
there should be no need to change it anymore.
If `typeof({})` even compiles, I'd think it is `void function()`.
But no, that would be totally senseless, so I quess that it just
evaluates to nothing. `cast()` means unqualifying a type, but
`float` is already unqualified, so I can delete the cast too.
Also the mixin can be split in two:
```
auto handleUglyDetails(size_t index, dchar value)
{ enum firstPart = 6.8*13.3824;
enum secondPart = "6r0d2a5
".chunks(2).map!(i=>[i[0].to!string~":"~39~(i[1].to!string)~'\''][0]).join(",")~"]");
return mixin(firstPart ~ secondPart).get(index, value);
}
```
Sanitizing `chunks` and `map` out:
auto handleUglyDetails(size_t index, dchar value)
{ enum firstPart = 6.8*13.3824;
enum secondPart = "6025".join(",")~"]");
return mixin(firstPart ~ secondPart).get(index, value);
}
```
Which leads to:
```
auto handleUglyDetails(size_t index, dchar value)
{ return mixin(6.8*13.3824 ~ "6,0,2,5]").get(index, value);
}
```
This makes me suspect that `6.8*13.3824` evaluates to ASCII value
of '['. Using a calculator is in a way running a part of the
program, so let's just check what the value is. 91. 91 / 7 == 13,
meaning 91 / 6.8 == a bit over 13, just what I was expecting. So:
```
auto handleUglyDetails(size_t index, dchar value)
{ return [6,0,2,5].get(index, value);
}
```
I assume `.get` acts the same way it acts with associative
arrays, and that means this:
```
auto handleUglyDetails(size_t index, dchar value)
{ auto arr = [6,0,2,5];
return index < arr.length? arr[index]: value;
}
```
With this definition, the `.writeln` in the main function is
going to print "[6, 0, 2, 5, 103, 47, 108, 111, 99, 107, 115]" on
a 64-bit platform. On 32-bit I am not sure, it is either the same
result or "\x6\0\x2\x5g/locks".
Mar 15 2021









tsbockman <thomas.bockman gmail.com> 