Browse Source

don't leak an FD in lz4 (de)compression

Seen first in #826783, but as this buglog also shows leaked uncompressed
files as well we don't close it just yet.
David Kalnischkies 8 years ago
parent
commit
6f35be91c9

+ 6 - 1
apt-pkg/contrib/fileutl.cc

@@ -1535,7 +1535,7 @@ public:
 	 return false;
 
       unsigned int flags = (Mode & (FileFd::WriteOnly|FileFd::ReadOnly));
-      if (backend.OpenDescriptor(iFd, flags) == false)
+      if (backend.OpenDescriptor(iFd, flags, FileFd::None, true) == false)
 	 return false;
 
       // Write the file header
@@ -1646,6 +1646,11 @@ public:
 	 res = LZ4F_freeDecompressionContext(dctx);
 	 dctx = nullptr;
       }
+      if (backend.IsOpen())
+      {
+	 backend.Close();
+	 filefd->iFd = -1;
+      }
 
       return LZ4F_isError(res) == false;
    }

+ 16 - 0
test/integration/test-apt-helper-cat-file

@@ -5,6 +5,15 @@ TESTDIR="$(readlink -f "$(dirname "$0")")"
 . "$TESTDIR/framework"
 setupenvironment
 
+TESTTOOL="${BUILDDIRECTORY}/test_fileutl"
+msgtest 'Check if we have build the test tool' "$TESTTOOL"
+if [ -x "$TESTTOOL" ]; then
+	msgpass
+else
+	msgskip 'not available'
+	exit 0
+fi
+
 cat >rootdir/etc/apt/apt.conf.d/rev-as-compressor <<EOF
 APT::Compressor::rev {
 	Name "rev";
@@ -26,5 +35,12 @@ while read compressor extension command; do
 	else
 		FILE="./test.txt.${extension}"
 	fi
+	if [ -d /proc/self/fd ]; then
+		testsuccess runapt "${TESTTOOL}" "$FILE"
+		testequal '3' grep -c '/test.txt' rootdir/tmp/testsuccess.output
+	else
+		msgtest 'Test if /proc interface is available'
+		msgskip 'seems not'
+	fi
 	testsuccessequal "$(cat ./test.txt)" apthelper cat-file "$FILE"
 done < "${TMPWORKINGDIRECTORY}/rootdir/etc/testcase-compressor.conf"

+ 6 - 0
test/interactive-helper/makefile

@@ -33,6 +33,12 @@ LIB_MAKES = apt-pkg/makefile
 SOURCE = test_udevcdrom.cc
 include $(PROGRAM_H)
 
+PROGRAM=test_fileutl
+SLIBS = -lapt-pkg
+LIB_MAKES = apt-pkg/makefile
+SOURCE = test_fileutl.cc
+include $(PROGRAM_H)
+
 # Program for checking rpm versions
 #PROGRAM=rpmver
 #SLIBS = -lapt-pkg -lrpm

+ 43 - 0
test/interactive-helper/test_fileutl.cc

@@ -0,0 +1,43 @@
+#include <apt-pkg/fileutl.h>
+#include <apt-pkg/strutl.h>
+#include <apt-pkg/error.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+
+#include <iostream>
+#include <string>
+
+static void callsystem(std::string const &call)
+{
+   auto ret = system(call.c_str());
+   if (WIFEXITED(ret) == false || WEXITSTATUS(ret) != 0)
+      _error->Error("Calling %s failed!", call.c_str());
+}
+
+int main(int, char ** argv)
+{
+	auto const pid = getpid();
+	std::string ls;
+	strprintf(ls, "ls -l /proc/%d/fd", pid);
+	callsystem(ls);
+	FileFd t;
+	t.Open(argv[1], FileFd::ReadOnly, FileFd::Extension);
+	callsystem(ls);
+	char buf[1024];
+	unsigned long long act;
+	while (t.Read(buf, sizeof(buf), &act))
+		if (act == 0)
+			break;
+	callsystem(ls);
+	t.Seek(5);
+	callsystem(ls);
+	t.Close();
+	callsystem(ls);
+	auto const ret = _error->PendingError();
+	_error->DumpErrors();
+	return ret;
+}

+ 1 - 1
test/libapt/file-helpers.cc

@@ -74,7 +74,7 @@ void helperCreateTemporaryFile(std::string const &id, FileFd &fd, std::string *
       unlink(tempfile);
    free(tempfile);
 
-   EXPECT_TRUE(fd.OpenDescriptor(tempfile_fd, FileFd::ReadWrite));
+   EXPECT_TRUE(fd.OpenDescriptor(tempfile_fd, FileFd::ReadWrite, true));
    if (content != NULL)
    {
       ASSERT_TRUE(fd.Write(content, strlen(content)));