PageRenderTime 56ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/Unittests/MethodObjectTest.cc

https://github.com/ianloic/unladen-swallow
C++ | 52 lines | 34 code | 6 blank | 12 comment | 4 complexity | 8ad2890f97d30035342ea0e789faf9b2 MD5 | raw file
Possible License(s): 0BSD, BSD-3-Clause
  1. #include "Python.h"
  2. #include "gtest/gtest.h"
  3. class PyCFunctionTest : public testing::Test {
  4. protected:
  5. PyCFunctionTest()
  6. {
  7. Py_NoSiteFlag = true;
  8. Py_Initialize();
  9. }
  10. ~PyCFunctionTest()
  11. {
  12. Py_Finalize();
  13. }
  14. };
  15. // Most PyMethodDef structs are allocated globally, and the compiler takes care
  16. // of zeroing out uninitialized fields. Not so with malloc(), which causes
  17. // problems for some embedding applications that don't memset() their memory.
  18. // This has been observed in applications that heap-allocate PyMethodDefs and
  19. // then set METH_NOARGS, which previously was #defined to METH_ARG_RANGE.
  20. // This is arguably a problem in the application, but if it works with Python
  21. // 2.6, it needs to work with Unladen Swallow.
  22. TEST_F(PyCFunctionTest, HeapAllocatedMethNoArgs)
  23. {
  24. PyMethodDef *method_def = PyMem_New(PyMethodDef, 1);
  25. ASSERT_TRUE(method_def != NULL);
  26. method_def->ml_min_arity = 55; // Dirty some memory.
  27. // From here on, pretend that method_def was free()d, then we did another
  28. // method_def = PyMem_New(PyMethodDef, 1); that returned the same memory,
  29. // but uninitialized. This is the behaviour observed in the wild.
  30. method_def->ml_flags = METH_NOARGS; // Important.
  31. method_def->ml_meth = (PyCFunction)PyList_Append; // Dummy.
  32. // Dummy objects; their type/contents are unimportant.
  33. PyObject *self = PyList_New(1);
  34. PyObject *module = PyList_New(1);
  35. ASSERT_TRUE(self != NULL);
  36. ASSERT_TRUE(module != NULL);
  37. // This PyCFunction_NewEx call used to trigger a PyErr_BadInternalCall.
  38. PyErr_Clear();
  39. PyObject *my_function = PyCFunction_NewEx(method_def, self, module);
  40. EXPECT_TRUE(my_function != NULL);
  41. EXPECT_FALSE(PyErr_Occurred());
  42. PyErr_Clear();
  43. PyMem_Free(method_def);
  44. Py_CLEAR(self);
  45. Py_CLEAR(module);
  46. }