Generates random Python functions using Markov chains
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

179 lines
4.7 KiB

  1. import opcode
  2. import random
  3. import types
  4. ############## CODE ###########################################################
  5. MARKOV_START = -1
  6. MARKOV_END = -2
  7. def make_chain(funcs):
  8. chain = {}
  9. for func in funcs:
  10. _parse_func(func, chain)
  11. return chain
  12. def make_function(chain, name, argcount=1):
  13. codes, constants, varnames = _make_codes(chain)
  14. nlocals = len(varnames) + argcount
  15. stacksize = 1024 # High limit?
  16. flags = 0 # Denotes funcs with *args and/or **kwargs; nothing for now
  17. codestring = "".join([chr(code) for code in codes])
  18. names = ()
  19. filename = "<smash>"
  20. firstlineno = 1
  21. lnotab = ""
  22. code = types.CodeType(argcount, nlocals, stacksize, flags, codestring,
  23. constants, names, varnames, filename, name,
  24. firstlineno, lnotab)
  25. func = types.FunctionType(code, globals(), name)
  26. return func
  27. def print_chain(chain):
  28. print "{"
  29. for key in sorted(chain.keys()):
  30. op = _int_to_opname(key)
  31. targets = {}
  32. for op2 in chain[key]:
  33. target = _int_to_opname(op2[0])
  34. if op2[0] >= opcode.HAVE_ARGUMENT:
  35. target = "{0}({1})".format(target, op2[1])
  36. try:
  37. targets[target] += 1
  38. except KeyError:
  39. targets[target] = 1
  40. targs = []
  41. for optarget, count in targets.iteritems():
  42. if count == 1:
  43. targs.append(optarget)
  44. else:
  45. targs.append("{0}x {1}".format(count, optarget))
  46. targs.sort()
  47. print op.rjust(20), "=> [{0}]".format(", ".join(targs))
  48. print "}"
  49. def print_function(func):
  50. co = func.__code__
  51. code = co.co_code
  52. n = len(code)
  53. i = 0
  54. while i < n:
  55. op = ord(code[i])
  56. i += 1
  57. print opcode.opname[op].rjust(20),
  58. if op >= opcode.HAVE_ARGUMENT:
  59. arg = _get_argument(co, code, i, op)
  60. i += 2
  61. print " ({0})".format(arg)
  62. else:
  63. print
  64. def _parse_func(func, chain):
  65. co = func.__code__
  66. code = co.co_code
  67. n = len(code)
  68. i = 0
  69. lastop = MARKOV_START
  70. while i < n:
  71. op = ord(code[i])
  72. i += 1
  73. if op >= opcode.HAVE_ARGUMENT:
  74. arg = _get_argument(co, code, i, op)
  75. i += 2
  76. else:
  77. arg = None
  78. _chain_append(chain, lastop, (op, arg))
  79. lastop = op
  80. _chain_append(chain, op, (MARKOV_END, None))
  81. def _get_argument(co, code, i, op):
  82. oparg = ord(code[i]) + ord(code[i + 1]) * 256
  83. if op in opcode.hasconst:
  84. return co.co_consts[oparg]
  85. elif op in opcode.haslocal:
  86. return co.co_varnames[oparg]
  87. elif op in opcode.hascompare:
  88. return opcode.cmp_op[oparg]
  89. raise NotImplementedError(op, opcode.opname[op])
  90. def _chain_append(chain, first, second):
  91. try:
  92. chain[first].append(second)
  93. except KeyError:
  94. chain[first] = [second]
  95. def _make_codes(chain):
  96. codes = []
  97. code = random.choice(chain[MARKOV_START])
  98. constants, varnames = [], []
  99. while 1:
  100. op, arg = code
  101. if op == MARKOV_END:
  102. break
  103. codes.append(op)
  104. if op >= opcode.HAVE_ARGUMENT:
  105. if op in opcode.hasconst:
  106. if arg not in constants:
  107. constants.append(arg)
  108. args = constants
  109. elif op in opcode.haslocal:
  110. if arg not in varnames:
  111. varnames.append(arg)
  112. args = varnames
  113. elif op in opcode.hascompare:
  114. args = opcode.cmp_op
  115. else:
  116. raise NotImplementedError(op, opcode.opname[op])
  117. codes.append(args.index(arg) % 256)
  118. codes.append(args.index(arg) // 256)
  119. code = random.choice(chain[op])
  120. return codes, tuple(constants), tuple(varnames)
  121. def _int_to_opname(op):
  122. if op == MARKOV_START:
  123. return "START"
  124. elif op == MARKOV_END:
  125. return "END"
  126. return opcode.opname[op]
  127. ############## FUNCTION CORPUS ################################################
  128. def f1(a):
  129. b = a + 9.0
  130. return b
  131. def f2(a):
  132. b = a - 7.0
  133. return b
  134. def f3(a):
  135. b = a * 5.0
  136. return b
  137. def f4(a):
  138. b = a / 3.0
  139. return b
  140. def f5(a):
  141. b = a ** 2.0
  142. return b
  143. def f6(a):
  144. b = a % 10.0
  145. return b
  146. corpus = [f1, f2, f3, f4, f5, f6]
  147. ############## DEMO ###########################################################
  148. if __name__ == "__main__":
  149. chain = make_chain(corpus)
  150. func = make_function(chain, "func")
  151. print "Using {0}-function corpus.".format(len(corpus))
  152. print "Smashed function disassembly:"
  153. print_function(func)
  154. print
  155. n = 12.0
  156. print "func(%s) =" % n, func(n)