Chromium als Standardbrowser in Emacs
(setq browse-url-browser-function 'browse-url-generic
browse-url-generic-program "chromium")
(setq browse-url-browser-function 'browse-url-generic
browse-url-generic-program "chromium")
The file that would normally be displayed here (THE-GNU-PROJECT) has been moved to the emacs23-common-non-dfsg package because its license does not appear to be compatible with the Debian Free Software Guidelines (DFSG). Please see /usr/share/doc/emacs23-common/copyright for more information.
Please install THE-GNU-PROJECT from Debian's non-free distribution if you would like for Emacs to display the original file.
...and you wait long enough...
nothing will happen.
Aus: Garfield, Comic vom 23.03.2004
#include <iostream>
int main(int argc, char **argv)
{
int x = 10;
// x goes to 0
while (x --> 0)
std::cout << x << std::endl;
}
class Spam(object):
def __init__(self, value):
self.value = value
@property
def spam(self):
return self.value
@spam.setter
def spam(self, value):
self.value = value
spam = Spam(42)
print spam.spam
spam.spam = 23
print spam.spam
>>> import marshal
>>> marshal.loads('l\x02\x00\x00\x00\x00\x00\x00\x00')
00000L
>>> bool(_)
True
>>>
Dazu benutzt man einfach sys.displayhook. bpython und Python führen beim Starten die Datei aus, auf die die Umgebungsvariable PYTHONSTARTUP zeigt. Man kann sich also einfach eine Datei mit folgendem Inhalt anlegen:
import __builtin__
import sys
def displayhook(value):
if value is not None:
__builtin__._ = value
out = repr(value)
if len(out) > 42:
out = out[:42] + '... (truncated)'
print out
sys.displayhook = displayhook
Dann wird die Ausgabe automatisch abgeschnitten. Mag man dann die eigentliche Ausgabe, kann man print _ bzw. print repr(_) benutzen.
Häufig findet man Leute, die gerne mathematische Ausdrücke in Python evaluieren wollen. Dabei kommen sie auf die Idee, dass man dazu ja eval() benutzen könnte. Und damit das ganze auch noch sicher ist, übergibt man eigene globals und locals, in den man optimalerweise __builtins__ auf None setzt, da dann CPythons restricted mode aktiviert wird, ein Überbleibsel aus vergangenen Zeiten. Im restricted mode darf man auf besstimme Attribute von Funktionsobjekten und Klassen nicht zugreifen, wie etwa __defaults__, womit ein trügerisches Gefühl von Sicherheit gegeben wird.
Warum ist das nicht sicher? Zunächst einmal hat man irgendwann gemerkt, dass man in CPython einfach keine sichere Sandbox hinbekommt, weshalb man diesen Mode nicht mehr so wirklich pflegt. Seit Python 2.6 haben Generatoren ein gi_code-Attribut, wodurch man letztlich auch eigene Code-Objekte und damit beliebige Funktionen erstellen kann. Das führt uns also zu folgendem Code:
ns = dict(__builtins__=None)
print eval("""(lambda d={}, t=(1).__class__.__class__:
(t(lambda: 23)(
t((_ for _ in []).gi_code)(
0, 1, 4, 67,"""
# SETUP_EXCEPT
r"""'y\x0c\x00'"""
# LOAD_CONST 1
r"""'d\x01\x00'"""
# LOAD_CONST 0
r"""'d\x02\x00'"""
# BINARY_DIVIDE
r"""'\x15'"""
# POP_TOP
r"""'\x01'"""
# POP_BLOCK
r"""'W'"""
# JUMP FORWARD 9
r"""'n\x09\x00'"""
# POP_TOP
r"""'\x01'"""
# POP_TOP
r"""'\x01'"""
# Now the traceback object is on TOS
# STORE_GLOBAL tb
r"""'a\x00\x00'"""
# JUMP_FORWARD 1
r"""'n\x01\x00'"""
# END_FINALLY
r"""'X'"""
# LOAD_CONST None
r"""'d\x00\x00'"""
# RETURN_VALUE
"""'S',
(None, 1, 0), ('tb', ), (),
'evil.py', 'evil', 1, ''
), d, None, ()
)(),d['tb'].tb_frame.f_back.f_back.f_back.f_globals)[1])()""",
ns, ns)
Führt man das aus, fällt einem auf, dass man damit an das richtige __builtins__-Objekt kommt, und damit dann auch beispielsweise __import__ aufrufen kann. Wie funktioniert das aber? Zunächst einmal holt man sich das Builtin type mit (1).__class__.__class__ und speichert es sich in t (indem man es als Default-Argument eines lambdas benutzt und den eigentlichen Code im Körper des lambdas schreibt und das lambda dann aufruft). Damit erstellt man dann ein neues Code-Objekt, das man durch t((_ for _ in []).gi_code) bekommt und damit dann ein neues Funktionsobjekt, das man mit t(lambda: 23) bekommt. Dieses Funktionsobjekt wird dann ausgeführt.
Was macht das konstruierte Funktionsobjekt beim Ausführen? Dazu schaut man sich die folgende Funktion an:
def throws():
try:
1 / 0
except:
pass
Der Bytecode der Funktion sieht dabei wie folgt aus:
3 0 SETUP_EXCEPT 12 (to 15) 4 3 LOAD_CONST 1 (1) 6 LOAD_CONST 2 (0) 9 BINARY_DIVIDE 10 POP_TOP 11 POP_BLOCK 12 JUMP_FORWARD 7 (to 22) 5 >> 15 POP_TOP 16 POP_TOP 17 POP_TOP 6 18 JUMP_FORWARD 1 (to 22) 21 END_FINALLY >> 22 LOAD_CONST 0 (None) 25 RETURN_VALUE
Man beachte die drei POP_TOPs im Mittelteil (der den except-Block darstellt): CPython speichert bei einer Ausnahme den Typ der Ausnahme, die Ausnahme selbst und ein Traceback-Objekt auf dem Stack (das, was sys.exc_info() zurückliefert). Und bekanntlich kommt man mit Traceback-Objekten an ein Frame-Objekt, und mit Frame-Objekten kann man sich den Stack hochhangeln und kommt somit an die globals des Aufrufers, in der man die richtigen __builtins__ findet. Ergo konstruiert man sich einfach eine Funktion, die das Traceback-Objekt eben in einem globalen Namen speichert anstatt es einfach vom Stack verschwinden zu lassen.
Manche Syntaxfehler können in CPython wegoptimiert werden:
>>> if 0:
... yield
...
>>> if 1:
... yield
File "<input>", line 2
SyntaxError: 'yield' outside function (<input>, line 2)
Wenn man sich wundert, wie man mit gdb lustig Hardwarebreakpoints setzen kann, obwohl x86 eigentlich nur vier unterstützt: Die Manual klärt auf.
Since they depend on hardware resources, hardware breakpoints may be limited in number; when the user asks for more, GDB will start trying to set software breakpoints. (On some architectures, notably the 32-bit x86 platforms, GDB cannot always know whether there's enough hardware resources to insert all the hardware breakpoints and watchpoints. On those platforms, GDB prints an error message only when the program being debugged is continued.)
Gnarf.