diff options
Diffstat (limited to 'python/tarfile.cc')
| -rw-r--r-- | python/tarfile.cc | 71 |
1 files changed, 52 insertions, 19 deletions
diff --git a/python/tarfile.cc b/python/tarfile.cc index 920f032e..0aeae662 100644 --- a/python/tarfile.cc +++ b/python/tarfile.cc @@ -43,7 +43,8 @@ public: PyObject *py_data; // The requested member or NULL. const char *member; - // Set to true if an error occured in the Python callback. + // Set to true if an error occured in the Python callback, or a file + // was too large to read in extractdata. bool error; // Place where the copy of the data is stored. char *copy; @@ -52,9 +53,13 @@ public: virtual bool DoItem(Item &Itm,int &Fd); virtual bool FinishedFile(Item &Itm,int Fd); +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 14) + virtual bool Process(Item &Itm,const unsigned char *Data, + unsigned long long Size,unsigned long long Pos); +#else virtual bool Process(Item &Itm,const unsigned char *Data, unsigned long Size,unsigned long Pos); - +#endif PyDirStream(PyObject *callback, const char *member=0) : callback(callback), py_data(0), member(member), error(false), copy(0), copy_size(0) { @@ -72,9 +77,13 @@ bool PyDirStream::DoItem(Item &Itm, int &Fd) { if (!member || strcmp(Itm.Name, member) == 0) { // Allocate a new buffer if the old one is too small. + if (Itm.Size > SIZE_MAX) + goto to_large; if (copy == NULL || copy_size < Itm.Size) { delete[] copy; - copy = new char[Itm.Size]; + copy = new (std::nothrow) char[Itm.Size]; + if (copy == NULL) + goto to_large; copy_size = Itm.Size; } Fd = -2; @@ -82,12 +91,31 @@ bool PyDirStream::DoItem(Item &Itm, int &Fd) Fd = -1; } return true; +to_large: + delete[] copy; + copy = NULL; + copy_size = 0; + /* If we are looking for a specific member, abort reading now */ + if (member) { + error = true; + PyErr_Format(PyExc_MemoryError, + "The member %s was too large to read into memory", + Itm.Name); + return false; + } + return true; } +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 14) +bool PyDirStream::Process(Item &Itm,const unsigned char *Data, + unsigned long long Size,unsigned long long Pos) +#else bool PyDirStream::Process(Item &Itm,const unsigned char *Data, unsigned long Size,unsigned long Pos) +#endif { - memcpy(copy + Pos, Data,Size); + if (copy != NULL) + memcpy(copy + Pos, Data,Size); return true; } @@ -98,7 +126,12 @@ bool PyDirStream::FinishedFile(Item &Itm,int Fd) return true; Py_XDECREF(py_data); - py_data = PyBytes_FromStringAndSize(copy, Itm.Size); + if (copy == NULL) { + Py_INCREF(Py_None); + py_data = Py_None; + } else { + py_data = PyBytes_FromStringAndSize(copy, Itm.Size); + } if (!callback) return true; @@ -309,7 +342,7 @@ static PyObject *tarfile_new(PyTypeObject *type,PyObject *args,PyObject *kwds) { PyObject *file; PyTarFileObject *self; - char *filename; + PyApt_Filename filename; int fileno; int min = 0; int max = 0xFFFFFFFF; @@ -323,8 +356,8 @@ static PyObject *tarfile_new(PyTypeObject *type,PyObject *args,PyObject *kwds) self = (PyTarFileObject*)CppPyObject_NEW<ExtractTar*>(file,type); // We receive a filename. - if ((filename = (char*)PyObject_AsString(file))) - new (&self->Fd) FileFd(filename,FileFd::ReadOnly); + if (filename.init(file)) + new (&self->Fd) FileFd((const char *) filename,FileFd::ReadOnly); else if ((fileno = PyObject_AsFileDescriptor(file)) != -1) { // clear the error set by PyObject_AsString(). PyErr_Clear(); @@ -349,8 +382,8 @@ static const char *tarfile_extractall_doc = static PyObject *tarfile_extractall(PyObject *self, PyObject *args) { std::string cwd = SafeGetCWD(); - char *rootdir = 0; - if (PyArg_ParseTuple(args,"|s:extractall",&rootdir) == 0) + PyApt_Filename rootdir; + if (PyArg_ParseTuple(args,"|O&:extractall", PyApt_Filename::Converter, &rootdir) == 0) return 0; if (rootdir) { @@ -384,8 +417,8 @@ static const char *tarfile_go_doc = static PyObject *tarfile_go(PyObject *self, PyObject *args) { PyObject *callback; - char *member = 0; - if (PyArg_ParseTuple(args,"O|s",&callback,&member) == 0) + PyApt_Filename member; + if (PyArg_ParseTuple(args,"O|O&",&callback, PyApt_Filename::Converter, &member) == 0) return 0; if (member && strcmp(member, "") == 0) member = 0; @@ -397,7 +430,7 @@ static PyObject *tarfile_go(PyObject *self, PyObject *args) return 0; if (member && !stream.py_data) return PyErr_Format(PyExc_LookupError, "There is no member named '%s'", - member); + member.path); return HandleErrors(PyBool_FromLong(res)); } @@ -407,20 +440,20 @@ static const char *tarfile_extractdata_doc = "LookupError if there is no member with the given name."; static PyObject *tarfile_extractdata(PyObject *self, PyObject *args) { - const char *member; - if (PyArg_ParseTuple(args,"s",&member) == 0) + PyApt_Filename member; + if (PyArg_ParseTuple(args,"O&", PyApt_Filename::Converter, &member) == 0) return 0; PyDirStream stream(NULL, member); ((PyTarFileObject*)self)->Fd.Seek(((PyTarFileObject*)self)->min); // Go through the stream. GetCpp<ExtractTar*>(self)->Go(stream); + if (stream.error) + return 0; + if (!stream.py_data) return PyErr_Format(PyExc_LookupError, "There is no member named '%s'", - member); - if (stream.error) { - return 0; - } + member.path); return Py_INCREF(stream.py_data), stream.py_data; } |
