Fix for mysterious crash in podofo module

This commit is contained in:
Kovid Goyal 2015-12-08 15:10:18 +05:30
parent 5e07f19848
commit 957126c11a
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C

View File

@ -9,13 +9,19 @@
using namespace PoDoFo; using namespace PoDoFo;
#define NUKE(x) { Py_XDECREF(x); x = NULL; }
class pyerr : public std::exception { class pyerr : public std::exception {
}; };
class OutputDevice : public PdfOutputDevice { class OutputDevice : public PdfOutputDevice {
private: private:
PyObject *file; PyObject *tell_func;
PyObject *seek_func;
PyObject *read_func;
PyObject *write_func;
PyObject *flush_func;
size_t written; size_t written;
void update_written() { void update_written() {
@ -25,8 +31,17 @@ class OutputDevice : public PdfOutputDevice {
} }
public: public:
OutputDevice(PyObject *f) : file(f), written(0) { Py_XINCREF(file); } OutputDevice(PyObject *file) : tell_func(0), seek_func(0), read_func(0), write_func(0), flush_func(0), written(0) {
~OutputDevice() { Py_XDECREF(file); file = NULL; } #define GA(f, a) { if((f = PyObject_GetAttrString(file, a)) == NULL) throw pyerr(); }
GA(tell_func, "tell");
GA(seek_func, "seek");
GA(read_func, "read");
GA(write_func, "write");
GA(flush_func, "flush");
}
~OutputDevice() {
NUKE(tell_func); NUKE(seek_func); NUKE(read_func); NUKE(write_func); NUKE(flush_func);
}
size_t GetLength() const { return written; } size_t GetLength() const { return written; }
@ -87,11 +102,13 @@ class OutputDevice : public PdfOutputDevice {
} }
size_t Read( char* pBuffer, size_t lLen ) { size_t Read( char* pBuffer, size_t lLen ) {
PyObject *ret; PyObject *ret, *temp;
char *buf = NULL; char *buf = NULL;
Py_ssize_t len = 0; Py_ssize_t len = 0;
ret = PyObject_CallMethod(file, (char*)"read", (char*)"n", static_cast<Py_ssize_t>(lLen)); if ((temp = PyInt_FromSize_t(lLen)) == NULL) throw pyerr();
ret = PyObject_CallFunctionObjArgs(read_func, temp, NULL);
NUKE(temp);
if (ret != NULL) { if (ret != NULL) {
if (PyBytes_AsStringAndSize(ret, &buf, &len) != -1) { if (PyBytes_AsStringAndSize(ret, &buf, &len) != -1) {
memcpy(pBuffer, buf, len); memcpy(pBuffer, buf, len);
@ -109,8 +126,10 @@ class OutputDevice : public PdfOutputDevice {
} }
void Seek(size_t offset) { void Seek(size_t offset) {
PyObject *ret; PyObject *ret, *temp;
ret = PyObject_CallMethod(file, (char*)"seek", (char*)"n", static_cast<Py_ssize_t>(offset)); if ((temp = PyInt_FromSize_t(offset)) == NULL) throw pyerr();
ret = PyObject_CallFunctionObjArgs(seek_func, temp, NULL);
NUKE(temp);
if (ret == NULL) { if (ret == NULL) {
if (PyErr_Occurred() == NULL) if (PyErr_Occurred() == NULL)
PyErr_SetString(PyExc_Exception, "Failed to seek in python file object"); PyErr_SetString(PyExc_Exception, "Failed to seek in python file object");
@ -123,7 +142,7 @@ class OutputDevice : public PdfOutputDevice {
PyObject *ret; PyObject *ret;
unsigned long ans; unsigned long ans;
ret = PyObject_CallMethod(file, (char*)"tell", NULL); ret = PyObject_CallFunctionObjArgs(tell_func, NULL);
if (ret == NULL) { if (ret == NULL) {
if (PyErr_Occurred() == NULL) if (PyErr_Occurred() == NULL)
PyErr_SetString(PyExc_Exception, "Failed to call tell() on python file object"); PyErr_SetString(PyExc_Exception, "Failed to call tell() on python file object");
@ -142,9 +161,14 @@ class OutputDevice : public PdfOutputDevice {
} }
void Write(const char* pBuffer, size_t lLen) { void Write(const char* pBuffer, size_t lLen) {
PyObject *ret; PyObject *ret, *temp = NULL;
temp = PyBytes_FromStringAndSize(pBuffer, static_cast<Py_ssize_t>(lLen));
if (temp == NULL) throw pyerr();
ret = PyObject_CallFunctionObjArgs(write_func, temp, NULL);
NUKE(temp);
ret = PyObject_CallMethod(file, (char*)"write", (char*)"s#", pBuffer, (int)lLen);
if (ret == NULL) { if (ret == NULL) {
if (PyErr_Occurred() == NULL) if (PyErr_Occurred() == NULL)
PyErr_SetString(PyExc_Exception, "Failed to call write() on python file object"); PyErr_SetString(PyExc_Exception, "Failed to call write() on python file object");
@ -155,7 +179,7 @@ class OutputDevice : public PdfOutputDevice {
} }
void Flush() { void Flush() {
Py_XDECREF(PyObject_CallMethod(file, (char*)"flush", NULL)); Py_XDECREF(PyObject_CallFunctionObjArgs(flush_func, NULL));
} }
}; };