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.

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