Skip to content

Instantly share code, notes, and snippets.

@mkmik
Created July 13, 2012 17:00
Show Gist options
  • Save mkmik/3105991 to your computer and use it in GitHub Desktop.
Save mkmik/3105991 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
import dis
import inspect
def lineno():
"""Returns the current line number in our program."""
return inspect.currentframe().f_back.f_lineno
def test():
print "hello, from line", lineno()
print "hello, again from line", lineno()
def clone_code(c, firstlineno, lnotab):
return (type(c)(c.co_argcount,c.co_nlocals,c.co_stacksize,c.co_flags,c.co_code,c.co_consts,c.co_names,c.co_varnames,c.co_filename,c.co_name,firstlineno,lnotab,c.co_freevars,c.co_cellvars))
def patch(f, line_mapping=dict()):
tab = [i for i in f.func_code.co_lnotab]
print "Line number table"
print repr(''.join(tab))
for op_pos, line_delta in zip((ord(tab[i]) for i in xrange(0, len(tab)-1, 2)), (ord(tab[i]) for i in xrange(1, len(tab), 2))):
print op_pos, line_delta + f.func_code.co_firstlineno
print "----"
for i, line_delta in ((i, ord(tab[i])) for i in xrange(1, len(tab), 2)):
print 'IDX', line_delta
tab[i] = chr(line_delta + 1)
print repr(''.join(tab))
print "Before patching"
dis.disassemble(f.func_code)
f.func_code = clone_code(f.func_code, f.func_code.co_firstlineno, ''.join(tab))
print "After patching"
dis.disassemble(f.func_code)
if __name__ == '__main__':
test()
patch(test)
test()
hello, from line 11
hello, again from line 13
Line number table
'\x00\x01\x0c\x02'
0 11
12 12
----
IDX 1
IDX 2
'\x00\x02\x0c\x03'
Before patching
11 0 LOAD_CONST 1 ('hello, from line')
3 PRINT_ITEM
4 LOAD_GLOBAL 0 (lineno)
7 CALL_FUNCTION 0
10 PRINT_ITEM
11 PRINT_NEWLINE
13 12 LOAD_CONST 2 ('hello, again from line')
15 PRINT_ITEM
16 LOAD_GLOBAL 0 (lineno)
19 CALL_FUNCTION 0
22 PRINT_ITEM
23 PRINT_NEWLINE
24 LOAD_CONST 0 (None)
27 RETURN_VALUE
After patching
12 0 LOAD_CONST 1 ('hello, from line')
3 PRINT_ITEM
4 LOAD_GLOBAL 0 (lineno)
7 CALL_FUNCTION 0
10 PRINT_ITEM
11 PRINT_NEWLINE
15 12 LOAD_CONST 2 ('hello, again from line')
15 PRINT_ITEM
16 LOAD_GLOBAL 0 (lineno)
19 CALL_FUNCTION 0
22 PRINT_ITEM
23 PRINT_NEWLINE
24 LOAD_CONST 0 (None)
27 RETURN_VALUE
hello, from line 12
hello, again from line 15
@livenson
Copy link

Shell codes for a new virus?

@mkmik
Copy link
Author

mkmik commented Jul 14, 2012

There is a trick to add new statements to python, but it breaks line positions in debugger and exception stack traces.
This was the first attempt to play with that. I have a complete solution at:

https://github.com/mmikulicic/python-match-statement

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment