summaryrefslogtreecommitdiff
path: root/python/tarfile.cc
diff options
context:
space:
mode:
Diffstat (limited to 'python/tarfile.cc')
-rw-r--r--python/tarfile.cc71
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;
}