Last active
October 22, 2015 23:45
-
-
Save theY4Kman/e3a0a2b573cdb10a393b to your computer and use it in GitHub Desktop.
With a little bit o' CPython internals knowledge, you can fuck everything up.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ast | |
import pyximport; pyximport.install() | |
import fuckitallup | |
def print_eval(s): | |
print s + ':', eval(s) | |
def extract_evals(): | |
with open(__file__) as fp: | |
root = ast.parse(fp.read()) | |
evals = [] | |
for node in ast.walk(root): | |
if isinstance(node, ast.Call) and isinstance(node.func, ast.Name): | |
func_name = node.func.id | |
first_arg = node.args and node.args[0] | |
if func_name == 'print_eval' and isinstance(first_arg, ast.Str): | |
evals.append(first_arg.s) | |
return evals | |
print "I'm going to fuck everything up, but first, here's the state of the world" | |
for s in extract_evals(): | |
print_eval(s) | |
print "Now, let's fuck it up." | |
print "First, let's take a trip to Oceania by modifying int values" | |
fuckitallup.fuckup_int(5, 4) | |
print_eval('2 + 2 == 5') | |
print "Why not mess with the edges of Python's small int cache?" | |
fuckitallup.fuckup_int(255, 256) | |
print_eval('256 - 1 == 256') | |
print "Doesn't work with larger numbers, though." | |
print "For instance, if we set 256's value to 255, we can't get the same effect," | |
print "because every reference to 256 is another object in memory." | |
fuckitallup.fuckup_int(256, 255) | |
print_eval('255 + 1 == 255') | |
print "Hmmm, let's change the underlying value of True to 0" | |
fuckitallup.fuckup_boolean(1, 0) | |
print_eval('True') | |
print "Hey, it looks like we've left Oceania, though" | |
print_eval('2 + 2 == 5') | |
print "Now, the underlying value of False to 1" | |
fuckitallup.fuckup_boolean(0, 1) | |
print_eval('False') | |
print_eval('bool(0)') | |
print_eval('bool(1)') | |
print_eval('1 == 0') | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
cdef struct PyIntObject: | |
Py_ssize_t ob_refcnt | |
void *ob_type # actually PyTypeObject | |
long ob_ival | |
cdef extern from 'Python.h': | |
PyIntObject* PyBool_FromLong(long v) | |
PyIntObject* PyInt_FromLong(long ival) | |
cpdef fuckup_boolean(int boolean, long newvalue): | |
""" | |
YSK: in CPython, the boolean type is just an alias for an int. The names | |
True and False are simply pointers to the canonical bool instances for 0 | |
and 1. | |
You can set these instances' integer values, and get interesting results. | |
""" | |
cdef PyIntObject *b = PyBool_FromLong(boolean) | |
b.ob_ival = newvalue | |
cpdef fuckup_int(int int, long newvalue): | |
""" | |
YSK: in CPython, numbers 0-256 are pre-created and cached, so when you | |
reference them in Python, it simply does a lookup on a table and retrieves | |
the underlying PyObject. Larger values are allocated on the fly. | |
You can set these cached instances' integer values for interesting results. | |
""" | |
cdef PyIntObject *i = PyInt_FromLong(int) | |
i.ob_ival = newvalue |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Cython |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment