Generates random Python functions using Markov chains
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

120 lignes
3.2 KiB

  1. import dis
  2. import opcode
  3. import random
  4. import types
  5. ############## CODE ###########################################################
  6. MARKOV_START = -1
  7. MARKOV_END = -2
  8. def make_chain(funcs):
  9. chain = {}
  10. for func in funcs:
  11. co = func.func_code
  12. code = co.co_code
  13. n = len(code)
  14. i = 0
  15. lastop = MARKOV_START
  16. while i < n:
  17. c = code[i]
  18. op = ord(c)
  19. i += 1
  20. if op >= opcode.HAVE_ARGUMENT:
  21. oparg = ord(code[i]) + ord(code[i + 1]) * 256
  22. i += 2
  23. if op in opcode.hasconst:
  24. arg = co.co_consts[oparg]
  25. elif op in opcode.haslocal:
  26. arg = co.co_varnames[oparg]
  27. else:
  28. raise NotImplementedError(op, opcode.opname[op])
  29. else:
  30. arg = None
  31. _chain_append(chain, lastop, (op, arg))
  32. lastop = op
  33. _chain_append(chain, op, MARKOV_END)
  34. return chain
  35. def make_function(chain, name, argcount=1):
  36. codes, constants, varnames = _make_codes(chain)
  37. nlocals = len(varnames) + argcount
  38. stacksize = 1024 # High limit?
  39. flags = 0 # Denotes funcs with *args and/or **kwargs; nothing for now
  40. codestring = "".join([chr(code) for code in codes])
  41. names = ()
  42. filename = "<smash>"
  43. firstlineno = 1
  44. lnotab = ""
  45. code = types.CodeType(argcount, nlocals, stacksize, flags, codestring,
  46. constants, names, varnames, filename, name,
  47. firstlineno, lnotab)
  48. func = types.FunctionType(code, globals(), name)
  49. return func
  50. def _chain_append(chain, first, second):
  51. try:
  52. chain[first].append(second)
  53. except KeyError:
  54. chain[first] = [second]
  55. def _make_codes(chain):
  56. codes = []
  57. code = random.choice(chain[MARKOV_START])
  58. constants, varnames = [], []
  59. while 1:
  60. if code == MARKOV_END:
  61. break
  62. op, arg = code
  63. codes.append(op)
  64. if op >= opcode.HAVE_ARGUMENT:
  65. if op in opcode.hasconst:
  66. args = constants
  67. elif op in opcode.haslocal:
  68. args = varnames
  69. else:
  70. raise NotImplementedError(op, opcode.opname[op])
  71. if arg not in args:
  72. args.append(arg)
  73. codes.append(args.index(arg))
  74. codes.append(0)
  75. code = random.choice(chain[op])
  76. return codes, tuple(constants), tuple(varnames)
  77. ############## FUNCTION CORPUS ################################################
  78. def f1(a):
  79. b = a + 7.0
  80. return b
  81. def f2(a):
  82. b = a - 5.0
  83. return b
  84. def f3(a):
  85. b = a * 3.0
  86. return b
  87. def f4(a):
  88. b = a / 2.0
  89. return b
  90. corpus = [f1, f2, f3, f4]
  91. ############## DEMO ###########################################################
  92. if __name__ == "__main__":
  93. print "USING FUNCTION CORPUS:", [func.__name__ for func in corpus]
  94. chain = make_chain(corpus)
  95. print "OPCODE MARKOV CHAIN:", chain
  96. print
  97. func = make_function(chain, "func")
  98. print "SMASHED FUNCTION CODE:", [ord(c) for c in func.func_code.co_code]
  99. print "FUNCTION DISASSEMBLY:"
  100. dis.dis(func)
  101. print
  102. n = 12.0
  103. print "func(%s) =" % n, func(n)