Skip to main content
added 422 characters in body
Source Link
Wheat Wizard
  • 100k
  • 22
  • 282
  • 661

HaskellHaskell, 49 bytes

So we end up printing a random one character string.

A more normal solution, 44 bytes

import System.Random
main=randomIO>>=putChar

Try it online!

For completion sake this is the "normal" Haskell approach. It is slightly shorter but far more boring.

Haskell, 49 bytes

So we end up printing a random one character string.

Haskell, 49 bytes

So we end up printing a random one character string.

A more normal solution, 44 bytes

import System.Random
main=randomIO>>=putChar

Try it online!

For completion sake this is the "normal" Haskell approach. It is slightly shorter but far more boring.

Source Link
Wheat Wizard
  • 100k
  • 22
  • 282
  • 661

Haskell, 49 bytes

import Unsafe.Coerce
main=putStr[unsafeCoerce(+)]

Unfortunately this seems to always outputs the same thing on TIO (I don't quite know why, but I have some guesses), so if you want to try it you should run it locally.

I've only tested this on Linux and OSX. I make no guarentees about Windows. If you are having trouble getting it to work on Linux I would be interested to know.

Explanation

What is unsafeCoerce?

This answer relies on unsafeCoerce. This function is a bit of magic, so first we are going to have to do a quick intro to Haskell's type system.

Haskell has something called type erasure. This means that the compiler checks all the types to make sure that nothing in the program is called on the wrong type. Once it is done with that there is no need to actually store type information any more, so Haskell erases it. So at runtime all data is the same and just relies on the fact that we already checked all the types before hand so nothing goes horribly wrong.

unsafeCoerce is a function that lies to the type checker. It tells it that it can take any input and produce any output; it's type is

forall a. forall b. a -> b

But it does nothing, it gives back the input exactly as it got it. So if you take a string like "abcd" and coerce it to an int using unsafeCoerce the result will be whatever the representation of "abcd" in memory is when interpreted as an integer.

How are functions represented in memory?

In Haskell, all complex objects including functions are internally represented as a pointer. This is a number in binary that "points" to a specific location in memory. This is because we want to pass these values by reference, since copying the whole thing is expensive, and since Haskell disallows mutation we can with no problem.

However simple objects like ints are passed by value since they are so small that copying them is about as expensive as copying a pointer would be. So they are not represented as pointers but rather just whatever structure they are.

So if we use unsafeCoerce from a complex object, say a function, to a simple object, say an Int, what happens is that the pointer to the function gets converted to the simple object. And the value of that simple object is dependent only on where the complex object is located not anything about what it is.

Address Space Layout Randomization

More reading

Many software vulnerabilities rely in part on being able to find particular functions in computer memory to access them. For these techniques you create some malicious code somewhere in memory (this can be done a few ways) and then by hijacking the stack pointer convince a program to run your code. In order to combat these exploits many systems implement something called Address Space Layout Randomization or ASLR. With ASLR key components are placed randomly so that their locations cannot be predicted. This means even if you do get control of the stack pointer it is hard to find where your malicious code is placed. ALSR is not the only technique used against these attacks but it is one we care about.

For Linux systems you can check of ASLR is on using

cat /proc/sys/kernel/randomize_va_space

Or since this is :

sysctl -anr "e_v"

There are three levels of security here 0 for off, and 1 and 2 for varying levels of on. My computer has this set to 2 (and your computer probably does too).

You can also set this. However do not do this unless you know what you are doing. Please do not mess with your kernel (unless you know what you are doing). For this reason I'm not going to include the command to do this, but you can look it up online or figure it out from the commands I already gave.

What this means for us is that the locations for objects allocated by Haskell at runtime is random or at least non-deterministic. This means that when we take a complex object like a function and convert it to a simple object like an Int the value of that object is random too.

The program

So that's what our program does. We coerce a function, (+) because it is short. We wrap this in a list and print it using putStr. Since putStr expects a string the compiler infers that the output of unsafeCoerce(+) must be a Char, which is a simple type.

So we end up printing a random one character string.