• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2    american fuzzy lop++ - python extension routines
3    ------------------------------------------------
4 
5    Originally written by Michal Zalewski
6 
7    Now maintained by Marc Heuse <mh@mh-sec.de>,
8                         Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
9                         Andrea Fioraldi <andreafioraldi@gmail.com>
10 
11    Copyright 2016, 2017 Google Inc. All rights reserved.
12    Copyright 2019-2022 AFLplusplus Project. All rights reserved.
13 
14    Licensed under the Apache License, Version 2.0 (the "License");
15    you may not use this file except in compliance with the License.
16    You may obtain a copy of the License at:
17 
18      https://www.apache.org/licenses/LICENSE-2.0
19 
20    This is the real deal: the program takes an instrumented binary and
21    attempts a variety of basic fuzzing tricks, paying close attention to
22    how they affect the execution path.
23 
24  */
25 
26 #include "afl-fuzz.h"
27 
28 /* Python stuff */
29 #ifdef USE_PYTHON
30 
unsupported(afl_state_t * afl,unsigned int seed)31 static void *unsupported(afl_state_t *afl, unsigned int seed) {
32 
33   (void)afl;
34   (void)seed;
35 
36   FATAL("Python Mutator cannot be called twice yet");
37   return NULL;
38 
39 }
40 
41   /* sorry for this makro...
42   it just fills in `&py_mutator->something_buf, &py_mutator->something_size`. */
43   #define BUF_PARAMS(name) (void **)&((py_mutator_t *)py_mutator)->name##_buf
44 
fuzz_py(void * py_mutator,u8 * buf,size_t buf_size,u8 ** out_buf,u8 * add_buf,size_t add_buf_size,size_t max_size)45 static size_t fuzz_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf,
46                       u8 *add_buf, size_t add_buf_size, size_t max_size) {
47 
48   size_t    mutated_size;
49   PyObject *py_args, *py_value;
50   py_args = PyTuple_New(3);
51   py_mutator_t *py = (py_mutator_t *)py_mutator;
52 
53   /* buf */
54   py_value = PyByteArray_FromStringAndSize(buf, buf_size);
55   if (!py_value) {
56 
57     Py_DECREF(py_args);
58     FATAL("Failed to convert arguments");
59 
60   }
61 
62   PyTuple_SetItem(py_args, 0, py_value);
63 
64   /* add_buf */
65   py_value = PyByteArray_FromStringAndSize(add_buf, add_buf_size);
66   if (!py_value) {
67 
68     Py_DECREF(py_args);
69     FATAL("Failed to convert arguments");
70 
71   }
72 
73   PyTuple_SetItem(py_args, 1, py_value);
74 
75   /* max_size */
76   #if PY_MAJOR_VERSION >= 3
77   py_value = PyLong_FromLong(max_size);
78   #else
79   py_value = PyInt_FromLong(max_size);
80   #endif
81   if (!py_value) {
82 
83     Py_DECREF(py_args);
84     FATAL("Failed to convert arguments");
85 
86   }
87 
88   PyTuple_SetItem(py_args, 2, py_value);
89 
90   py_value = PyObject_CallObject(py->py_functions[PY_FUNC_FUZZ], py_args);
91 
92   Py_DECREF(py_args);
93 
94   if (py_value != NULL) {
95 
96     mutated_size = PyByteArray_Size(py_value);
97 
98     *out_buf = afl_realloc(BUF_PARAMS(fuzz), mutated_size);
99     if (unlikely(!*out_buf)) { PFATAL("alloc"); }
100 
101     memcpy(*out_buf, PyByteArray_AsString(py_value), mutated_size);
102     Py_DECREF(py_value);
103     return mutated_size;
104 
105   } else {
106 
107     PyErr_Print();
108     FATAL("python custom fuzz: call failed");
109 
110   }
111 
112 }
113 
custom_describe_py(void * py_mutator,size_t max_description_len)114 static const char *custom_describe_py(void * py_mutator,
115                                       size_t max_description_len) {
116 
117   PyObject *py_args, *py_value;
118 
119   py_args = PyTuple_New(1);
120 
121   PyLong_FromSize_t(max_description_len);
122 
123   /* add_buf */
124   py_value = PyLong_FromSize_t(max_description_len);
125   if (!py_value) {
126 
127     Py_DECREF(py_args);
128     FATAL("Failed to convert arguments");
129 
130   }
131 
132   PyTuple_SetItem(py_args, 0, py_value);
133 
134   py_value = PyObject_CallObject(
135       ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_DESCRIBE], py_args);
136 
137   Py_DECREF(py_args);
138 
139   if (py_value != NULL) { return PyBytes_AsString(py_value); }
140 
141   return NULL;
142 
143 }
144 
init_py_module(afl_state_t * afl,u8 * module_name)145 static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
146 
147   (void)afl;
148 
149   if (!module_name) { return NULL; }
150 
151   py_mutator_t *py = calloc(1, sizeof(py_mutator_t));
152   if (!py) { PFATAL("Could not allocate memory for python mutator!"); }
153 
154   Py_Initialize();
155 
156   #if PY_MAJOR_VERSION >= 3
157   PyObject *py_name = PyUnicode_FromString(module_name);
158   #else
159   PyObject *py_name = PyString_FromString(module_name);
160   #endif
161 
162   py->py_module = PyImport_Import(py_name);
163   Py_DECREF(py_name);
164 
165   PyObject * py_module = py->py_module;
166   PyObject **py_functions = py->py_functions;
167 
168   // initialize the post process buffer; ensures it's always valid
169   PyObject *unused_bytes = PyByteArray_FromStringAndSize("OHAI", 4);
170   if (!unused_bytes) { FATAL("allocation failed!"); }
171   if (PyObject_GetBuffer(unused_bytes, &py->post_process_buf, PyBUF_SIMPLE) ==
172       -1) {
173 
174     FATAL("buffer initialization failed");
175 
176   }
177 
178   Py_DECREF(unused_bytes);
179 
180   if (py_module != NULL) {
181 
182     u8 py_notrim = 0, py_idx;
183     /* init, required */
184     py_functions[PY_FUNC_INIT] = PyObject_GetAttrString(py_module, "init");
185     if (!py_functions[PY_FUNC_INIT])
186       FATAL("init function not found in python module");
187     py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "fuzz");
188     if (!py_functions[PY_FUNC_FUZZ])
189       py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "mutate");
190     py_functions[PY_FUNC_DESCRIBE] =
191         PyObject_GetAttrString(py_module, "describe");
192     py_functions[PY_FUNC_FUZZ_COUNT] =
193         PyObject_GetAttrString(py_module, "fuzz_count");
194     if (!py_functions[PY_FUNC_FUZZ])
195       WARNF("fuzz function not found in python module");
196     py_functions[PY_FUNC_POST_PROCESS] =
197         PyObject_GetAttrString(py_module, "post_process");
198     py_functions[PY_FUNC_INIT_TRIM] =
199         PyObject_GetAttrString(py_module, "init_trim");
200     py_functions[PY_FUNC_POST_TRIM] =
201         PyObject_GetAttrString(py_module, "post_trim");
202     py_functions[PY_FUNC_TRIM] = PyObject_GetAttrString(py_module, "trim");
203     py_functions[PY_FUNC_HAVOC_MUTATION] =
204         PyObject_GetAttrString(py_module, "havoc_mutation");
205     py_functions[PY_FUNC_HAVOC_MUTATION_PROBABILITY] =
206         PyObject_GetAttrString(py_module, "havoc_mutation_probability");
207     py_functions[PY_FUNC_QUEUE_GET] =
208         PyObject_GetAttrString(py_module, "queue_get");
209     py_functions[PY_FUNC_QUEUE_NEW_ENTRY] =
210         PyObject_GetAttrString(py_module, "queue_new_entry");
211     py_functions[PY_FUNC_INTROSPECTION] =
212         PyObject_GetAttrString(py_module, "introspection");
213     py_functions[PY_FUNC_DEINIT] = PyObject_GetAttrString(py_module, "deinit");
214     if (!py_functions[PY_FUNC_DEINIT])
215       WARNF("deinit function not found in python module");
216 
217     for (py_idx = 0; py_idx < PY_FUNC_COUNT; ++py_idx) {
218 
219       if (!py_functions[py_idx] || !PyCallable_Check(py_functions[py_idx])) {
220 
221         if (py_idx >= PY_FUNC_INIT_TRIM && py_idx <= PY_FUNC_TRIM) {
222 
223           // Implementing the trim API is optional for now
224           if (PyErr_Occurred()) { PyErr_Print(); }
225           py_notrim = 1;
226 
227         } else if (py_idx >= PY_OPTIONAL) {
228 
229           // Only _init and _deinit are not optional currently
230 
231           if (PyErr_Occurred()) { PyErr_Print(); }
232 
233         } else {
234 
235           fprintf(stderr,
236                   "Cannot find/call function with index %d in external "
237                   "Python module.\n",
238                   py_idx);
239           return NULL;
240 
241         }
242 
243       }
244 
245     }
246 
247     if (py_notrim) {
248 
249       py_functions[PY_FUNC_INIT_TRIM] = NULL;
250       py_functions[PY_FUNC_POST_TRIM] = NULL;
251       py_functions[PY_FUNC_TRIM] = NULL;
252       WARNF(
253           "Python module does not implement trim API, standard trimming will "
254           "be used.");
255 
256     }
257 
258   } else {
259 
260     PyErr_Print();
261     fprintf(stderr, "Failed to load \"%s\"\n", module_name);
262     free(py);
263     return NULL;
264 
265   }
266 
267   return py;
268 
269 }
270 
finalize_py_module(void * py_mutator)271 void finalize_py_module(void *py_mutator) {
272 
273   py_mutator_t *py = (py_mutator_t *)py_mutator;
274 
275   if (py->py_module != NULL) {
276 
277     deinit_py(py_mutator);
278 
279     u32 i;
280     for (i = 0; i < PY_FUNC_COUNT; ++i) {
281 
282       Py_XDECREF(py->py_functions[i]);
283 
284     }
285 
286     Py_DECREF(py->py_module);
287 
288   }
289 
290   Py_Finalize();
291 
292 }
293 
init_py(afl_state_t * afl,py_mutator_t * py_mutator,unsigned int seed)294 static void init_py(afl_state_t *afl, py_mutator_t *py_mutator,
295                     unsigned int seed) {
296 
297   (void)afl;
298 
299   PyObject *py_args, *py_value;
300 
301   /* Provide the init function a seed for the Python RNG */
302   py_args = PyTuple_New(1);
303   #if PY_MAJOR_VERSION >= 3
304   py_value = PyLong_FromLong(seed);
305   #else
306   py_value = PyInt_FromLong(seed);
307   #endif
308 
309   if (!py_value) {
310 
311     Py_DECREF(py_args);
312     FATAL("Cannot convert argument in python init.");
313 
314   }
315 
316   PyTuple_SetItem(py_args, 0, py_value);
317 
318   py_value =
319       PyObject_CallObject(py_mutator->py_functions[PY_FUNC_INIT], py_args);
320 
321   Py_DECREF(py_args);
322 
323   if (py_value == NULL) {
324 
325     PyErr_Print();
326     fprintf(stderr, "Call failed\n");
327     FATAL("Custom py mutator INIT failed.");
328 
329   }
330 
331 }
332 
deinit_py(void * py_mutator)333 void deinit_py(void *py_mutator) {
334 
335   PyObject *py_args, *py_value;
336 
337   py_args = PyTuple_New(0);
338   py_value = PyObject_CallObject(
339       ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_DEINIT], py_args);
340   Py_DECREF(py_args);
341 
342   if (py_value != NULL) {
343 
344     Py_DECREF(py_value);
345 
346   } else {
347 
348     PyErr_Print();
349     FATAL("Call failed");
350 
351   }
352 
353 }
354 
load_custom_mutator_py(afl_state_t * afl,char * module_name)355 struct custom_mutator *load_custom_mutator_py(afl_state_t *afl,
356                                               char *       module_name) {
357 
358   struct custom_mutator *mutator;
359 
360   mutator = ck_alloc(sizeof(struct custom_mutator));
361 
362   mutator->name = module_name;
363   ACTF("Loading Python mutator library from '%s'...", module_name);
364 
365   py_mutator_t *py_mutator;
366   py_mutator = init_py_module(afl, module_name);
367   mutator->data = py_mutator;
368   if (!py_mutator) { FATAL("Failed to load python mutator."); }
369 
370   PyObject **py_functions = py_mutator->py_functions;
371 
372   if (py_functions[PY_FUNC_INIT]) { mutator->afl_custom_init = unsupported; }
373 
374   if (py_functions[PY_FUNC_DEINIT]) { mutator->afl_custom_deinit = deinit_py; }
375 
376   if (py_functions[PY_FUNC_FUZZ]) { mutator->afl_custom_fuzz = fuzz_py; }
377 
378   if (py_functions[PY_FUNC_DESCRIBE]) {
379 
380     mutator->afl_custom_describe = custom_describe_py;
381 
382   }
383 
384   if (py_functions[PY_FUNC_POST_PROCESS]) {
385 
386     mutator->afl_custom_post_process = post_process_py;
387 
388   }
389 
390   if (py_functions[PY_FUNC_INIT_TRIM]) {
391 
392     mutator->afl_custom_init_trim = init_trim_py;
393 
394   }
395 
396   if (py_functions[PY_FUNC_FUZZ_COUNT]) {
397 
398     mutator->afl_custom_fuzz_count = fuzz_count_py;
399 
400   }
401 
402   if (py_functions[PY_FUNC_POST_TRIM]) {
403 
404     mutator->afl_custom_post_trim = post_trim_py;
405 
406   }
407 
408   if (py_functions[PY_FUNC_TRIM]) { mutator->afl_custom_trim = trim_py; }
409 
410   if (py_functions[PY_FUNC_HAVOC_MUTATION]) {
411 
412     mutator->afl_custom_havoc_mutation = havoc_mutation_py;
413 
414   }
415 
416   if (py_functions[PY_FUNC_HAVOC_MUTATION_PROBABILITY]) {
417 
418     mutator->afl_custom_havoc_mutation_probability =
419         havoc_mutation_probability_py;
420 
421   }
422 
423   if (py_functions[PY_FUNC_QUEUE_GET]) {
424 
425     mutator->afl_custom_queue_get = queue_get_py;
426 
427   }
428 
429   if (py_functions[PY_FUNC_QUEUE_NEW_ENTRY]) {
430 
431     mutator->afl_custom_queue_new_entry = queue_new_entry_py;
432 
433   }
434 
435   #ifdef INTROSPECTION
436   if (py_functions[PY_FUNC_INTROSPECTION]) {
437 
438     mutator->afl_custom_introspection = introspection_py;
439 
440   }
441 
442   #endif
443 
444   OKF("Python mutator '%s' installed successfully.", module_name);
445 
446   /* Initialize the custom mutator */
447   init_py(afl, py_mutator, rand_below(afl, 0xFFFFFFFF));
448 
449   mutator->stacked_custom = (mutator && mutator->afl_custom_havoc_mutation);
450   mutator->stacked_custom_prob =
451       6;  // like one of the default mutations in havoc
452 
453   return mutator;
454 
455 }
456 
post_process_py(void * py_mutator,u8 * buf,size_t buf_size,u8 ** out_buf)457 size_t post_process_py(void *py_mutator, u8 *buf, size_t buf_size,
458                        u8 **out_buf) {
459 
460   PyObject *    py_args, *py_value;
461   py_mutator_t *py = (py_mutator_t *)py_mutator;
462 
463   // buffer returned previously must be released; initialized during init
464   // so we don't need to do comparisons
465   PyBuffer_Release(&py->post_process_buf);
466 
467   py_args = PyTuple_New(1);
468   py_value = PyByteArray_FromStringAndSize(buf, buf_size);
469   if (!py_value) {
470 
471     Py_DECREF(py_args);
472     FATAL("Failed to convert arguments in custom post_process");
473 
474   }
475 
476   PyTuple_SetItem(py_args, 0, py_value);
477 
478   py_value = PyObject_CallObject(
479       ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_POST_PROCESS],
480       py_args);
481 
482   Py_DECREF(py_args);
483 
484   if (py_value != NULL) {
485 
486     if (PyObject_GetBuffer(py_value, &py->post_process_buf, PyBUF_SIMPLE) ==
487         -1) {
488 
489       PyErr_Print();
490       FATAL(
491           "Python custom mutator: post_process call return value not a "
492           "bytes-like object");
493 
494     }
495 
496     Py_DECREF(py_value);
497 
498     *out_buf = (u8 *)py->post_process_buf.buf;
499     return py->post_process_buf.len;
500 
501   } else {
502 
503     PyErr_Print();
504     FATAL("Python custom mutator: post_process call failed.");
505 
506   }
507 
508 }
509 
init_trim_py(void * py_mutator,u8 * buf,size_t buf_size)510 s32 init_trim_py(void *py_mutator, u8 *buf, size_t buf_size) {
511 
512   PyObject *py_args, *py_value;
513 
514   py_args = PyTuple_New(1);
515   py_value = PyByteArray_FromStringAndSize(buf, buf_size);
516   if (!py_value) {
517 
518     Py_DECREF(py_args);
519     FATAL("Failed to convert arguments");
520 
521   }
522 
523   PyTuple_SetItem(py_args, 0, py_value);
524 
525   py_value = PyObject_CallObject(
526       ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_INIT_TRIM], py_args);
527   Py_DECREF(py_args);
528 
529   if (py_value != NULL) {
530 
531   #if PY_MAJOR_VERSION >= 3
532     u32 retcnt = (u32)PyLong_AsLong(py_value);
533   #else
534     u32 retcnt = PyInt_AsLong(py_value);
535   #endif
536     Py_DECREF(py_value);
537     return retcnt;
538 
539   } else {
540 
541     PyErr_Print();
542     FATAL("Call failed");
543 
544   }
545 
546 }
547 
fuzz_count_py(void * py_mutator,const u8 * buf,size_t buf_size)548 u32 fuzz_count_py(void *py_mutator, const u8 *buf, size_t buf_size) {
549 
550   PyObject *py_args, *py_value;
551 
552   py_args = PyTuple_New(1);
553   py_value = PyByteArray_FromStringAndSize(buf, buf_size);
554   if (!py_value) {
555 
556     Py_DECREF(py_args);
557     FATAL("Failed to convert arguments");
558 
559   }
560 
561   PyTuple_SetItem(py_args, 0, py_value);
562 
563   py_value = PyObject_CallObject(
564       ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_FUZZ_COUNT], py_args);
565   Py_DECREF(py_args);
566 
567   if (py_value != NULL) {
568 
569   #if PY_MAJOR_VERSION >= 3
570     u32 retcnt = (u32)PyLong_AsLong(py_value);
571   #else
572     u32 retcnt = PyInt_AsLong(py_value);
573   #endif
574     Py_DECREF(py_value);
575     return retcnt;
576 
577   } else {
578 
579     PyErr_Print();
580     FATAL("Call failed");
581 
582   }
583 
584 }
585 
post_trim_py(void * py_mutator,u8 success)586 s32 post_trim_py(void *py_mutator, u8 success) {
587 
588   PyObject *py_args, *py_value;
589 
590   py_args = PyTuple_New(1);
591 
592   py_value = PyBool_FromLong(success);
593   if (!py_value) {
594 
595     Py_DECREF(py_args);
596     FATAL("Failed to convert arguments");
597 
598   }
599 
600   PyTuple_SetItem(py_args, 0, py_value);
601 
602   py_value = PyObject_CallObject(
603       ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_POST_TRIM], py_args);
604   Py_DECREF(py_args);
605 
606   if (py_value != NULL) {
607 
608   #if PY_MAJOR_VERSION >= 3
609     u32 retcnt = (u32)PyLong_AsLong(py_value);
610   #else
611     u32 retcnt = PyInt_AsLong(py_value);
612   #endif
613     Py_DECREF(py_value);
614     return retcnt;
615 
616   } else {
617 
618     PyErr_Print();
619     FATAL("Call failed");
620 
621   }
622 
623 }
624 
trim_py(void * py_mutator,u8 ** out_buf)625 size_t trim_py(void *py_mutator, u8 **out_buf) {
626 
627   PyObject *py_args, *py_value;
628   size_t    ret;
629 
630   py_args = PyTuple_New(0);
631   py_value = PyObject_CallObject(
632       ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_TRIM], py_args);
633   Py_DECREF(py_args);
634 
635   if (py_value != NULL) {
636 
637     ret = PyByteArray_Size(py_value);
638     *out_buf = afl_realloc(BUF_PARAMS(trim), ret);
639     if (unlikely(!*out_buf)) { PFATAL("alloc"); }
640     memcpy(*out_buf, PyByteArray_AsString(py_value), ret);
641     Py_DECREF(py_value);
642 
643   } else {
644 
645     PyErr_Print();
646     FATAL("Call failed");
647 
648   }
649 
650   return ret;
651 
652 }
653 
havoc_mutation_py(void * py_mutator,u8 * buf,size_t buf_size,u8 ** out_buf,size_t max_size)654 size_t havoc_mutation_py(void *py_mutator, u8 *buf, size_t buf_size,
655                          u8 **out_buf, size_t max_size) {
656 
657   size_t    mutated_size;
658   PyObject *py_args, *py_value;
659   py_args = PyTuple_New(2);
660 
661   /* buf */
662   py_value = PyByteArray_FromStringAndSize(buf, buf_size);
663   if (!py_value) {
664 
665     Py_DECREF(py_args);
666     FATAL("Failed to convert arguments");
667 
668   }
669 
670   PyTuple_SetItem(py_args, 0, py_value);
671 
672   /* max_size */
673   #if PY_MAJOR_VERSION >= 3
674   py_value = PyLong_FromLong(max_size);
675   #else
676   py_value = PyInt_FromLong(max_size);
677   #endif
678   if (!py_value) {
679 
680     Py_DECREF(py_args);
681     FATAL("Failed to convert arguments");
682 
683   }
684 
685   PyTuple_SetItem(py_args, 1, py_value);
686 
687   py_value = PyObject_CallObject(
688       ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_HAVOC_MUTATION],
689       py_args);
690 
691   Py_DECREF(py_args);
692 
693   if (py_value != NULL) {
694 
695     mutated_size = PyByteArray_Size(py_value);
696     if (mutated_size <= buf_size) {
697 
698       /* We reuse the input buf here. */
699       *out_buf = buf;
700 
701     } else {
702 
703       /* A new buf is needed... */
704       *out_buf = afl_realloc(BUF_PARAMS(havoc), mutated_size);
705       if (unlikely(!*out_buf)) { PFATAL("alloc"); }
706 
707     }
708 
709     memcpy(*out_buf, PyByteArray_AsString(py_value), mutated_size);
710 
711     Py_DECREF(py_value);
712     return mutated_size;
713 
714   } else {
715 
716     PyErr_Print();
717     FATAL("Call failed");
718 
719   }
720 
721 }
722 
havoc_mutation_probability_py(void * py_mutator)723 u8 havoc_mutation_probability_py(void *py_mutator) {
724 
725   PyObject *py_args, *py_value;
726 
727   py_args = PyTuple_New(0);
728   py_value = PyObject_CallObject(
729       ((py_mutator_t *)py_mutator)
730           ->py_functions[PY_FUNC_HAVOC_MUTATION_PROBABILITY],
731       py_args);
732   Py_DECREF(py_args);
733 
734   if (py_value != NULL) {
735 
736     long prob = PyLong_AsLong(py_value);
737     Py_DECREF(py_value);
738     return (u8)prob;
739 
740   } else {
741 
742     PyErr_Print();
743     FATAL("Call failed");
744 
745   }
746 
747 }
748 
introspection_py(void * py_mutator)749 const char *introspection_py(void *py_mutator) {
750 
751   PyObject *py_args, *py_value;
752 
753   py_args = PyTuple_New(0);
754   py_value = PyObject_CallObject(
755       ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_INTROSPECTION],
756       py_args);
757   Py_DECREF(py_args);
758 
759   if (py_value == NULL) {
760 
761     return NULL;
762 
763   } else {
764 
765     return PyByteArray_AsString(py_value);
766 
767   }
768 
769 }
770 
queue_get_py(void * py_mutator,const u8 * filename)771 u8 queue_get_py(void *py_mutator, const u8 *filename) {
772 
773   PyObject *py_args, *py_value;
774 
775   py_args = PyTuple_New(1);
776 
777   // File name
778   #if PY_MAJOR_VERSION >= 3
779   py_value = PyUnicode_FromString(filename);
780   #else
781   py_value = PyString_FromString(filename);
782   #endif
783   if (!py_value) {
784 
785     Py_DECREF(py_args);
786     FATAL("Failed to convert arguments");
787 
788   }
789 
790   PyTuple_SetItem(py_args, 0, py_value);
791 
792   // Call Python function
793   py_value = PyObject_CallObject(
794       ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_QUEUE_GET], py_args);
795   Py_DECREF(py_args);
796 
797   if (py_value != NULL) {
798 
799     int ret = PyObject_IsTrue(py_value);
800     Py_DECREF(py_value);
801 
802     if (ret == -1) {
803 
804       PyErr_Print();
805       FATAL("Failed to convert return value");
806 
807     }
808 
809     return (u8)ret & 0xFF;
810 
811   } else {
812 
813     PyErr_Print();
814     FATAL("Call failed");
815 
816   }
817 
818 }
819 
queue_new_entry_py(void * py_mutator,const u8 * filename_new_queue,const u8 * filename_orig_queue)820 u8 queue_new_entry_py(void *py_mutator, const u8 *filename_new_queue,
821                       const u8 *filename_orig_queue) {
822 
823   PyObject *py_args, *py_value;
824 
825   py_args = PyTuple_New(2);
826 
827   // New queue
828   #if PY_MAJOR_VERSION >= 3
829   py_value = PyUnicode_FromString(filename_new_queue);
830   #else
831   py_value = PyString_FromString(filename_new_queue);
832   #endif
833   if (!py_value) {
834 
835     Py_DECREF(py_args);
836     FATAL("Failed to convert arguments");
837 
838   }
839 
840   PyTuple_SetItem(py_args, 0, py_value);
841 
842   // Orig queue
843   py_value = Py_None;
844   if (filename_orig_queue) {
845 
846   #if PY_MAJOR_VERSION >= 3
847     py_value = PyUnicode_FromString(filename_orig_queue);
848   #else
849     py_value = PyString_FromString(filename_orig_queue);
850   #endif
851     if (!py_value) {
852 
853       Py_DECREF(py_args);
854       FATAL("Failed to convert arguments");
855 
856     }
857 
858   }
859 
860   PyTuple_SetItem(py_args, 1, py_value);
861 
862   // Call
863   py_value = PyObject_CallObject(
864       ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_QUEUE_NEW_ENTRY],
865       py_args);
866   Py_DECREF(py_args);
867 
868   if (py_value != NULL) {
869 
870     int ret = PyObject_IsTrue(py_value);
871     Py_DECREF(py_value);
872 
873     if (ret == -1) {
874 
875       PyErr_Print();
876       FATAL("Failed to convert return value");
877 
878     }
879 
880     return (u8)ret & 0xFF;
881 
882   } else {
883 
884     PyErr_Print();
885     FATAL("Call failed");
886 
887   }
888 
889 }
890 
891   #undef BUF_PARAMS
892 
893 #endif                                                        /* USE_PYTHON */
894 
895