]> git.saurik.com Git - apt.git/commitdiff
Do not read stderr from proxy autodetection scripts
authorJulian Andres Klode <jak@debian.org>
Sun, 2 Oct 2016 15:20:33 +0000 (17:20 +0200)
committerJulian Andres Klode <jak@debian.org>
Tue, 4 Oct 2016 17:30:30 +0000 (19:30 +0200)
This fixes a regression introduced in
  commit 8f858d560e3b7b475c623c4e242d1edce246025a

  don't leak FD in AutoProxyDetect command return parsing

which accidentally made the proxy autodetection code also read
the scripts output on stderr, not only on stdout when it switched
the code from popen() to Popen().

Reported-By: Tim Small <tim@seoss.co.uk>
apt-pkg/contrib/fileutl.cc
apt-pkg/contrib/fileutl.h
apt-pkg/contrib/proxy.cc
test/libapt/apt-proxy-script [new file with mode: 0755]
test/libapt/uri_test.cc

index fd13b45dc61374f6534524becda29e7bce488b0a..6c43bed90a580224b8058d37088c1a727a88cfc5 100644 (file)
@@ -2860,6 +2860,11 @@ bool Rename(std::string From, std::string To)                            /*{{{*/
 }
                                                                        /*}}}*/
 bool Popen(const char* Args[], FileFd &Fd, pid_t &Child, FileFd::OpenMode Mode)/*{{{*/
+{
+   return Popen(Args, Fd, Child, Mode, true);
+}
+                                                                       /*}}}*/
+bool Popen(const char* Args[], FileFd &Fd, pid_t &Child, FileFd::OpenMode Mode, bool CaptureStderr)/*{{{*/
 {
    int fd;
    if (Mode != FileFd::ReadOnly && Mode != FileFd::WriteOnly)
@@ -2891,7 +2896,8 @@ bool Popen(const char* Args[], FileFd &Fd, pid_t &Child, FileFd::OpenMode Mode)/
       if(Mode == FileFd::ReadOnly)
       {
          dup2(fd, 1);
-         dup2(fd, 2);
+        if (CaptureStderr == true)
+           dup2(fd, 2);
       } else if(Mode == FileFd::WriteOnly)
          dup2(fd, 0);
 
index 15665f8b5ea8703d033f0f874b3a456379f360ed..dddeb70f59c71283aefa52fd0e25a23c95abcd3e 100644 (file)
@@ -248,8 +248,11 @@ std::vector<std::string> Glob(std::string const &pattern, int flags=0);
  * \param Child a reference to the integer that stores the child pid
  *        Note that you must call ExecWait() or similar to cleanup
  * \param Mode is either FileFd::ReadOnly or FileFd::WriteOnly
+ * \param CaptureStderr True if we should capture stderr in addition to stdout.
+ *                      (default: True).
  * \return true on success, false on failure with _error set
  */
+bool Popen(const char* Args[], FileFd &Fd, pid_t &Child, FileFd::OpenMode Mode, bool CaptureStderr);
 bool Popen(const char* Args[], FileFd &Fd, pid_t &Child, FileFd::OpenMode Mode);
 
 
index 4529cf230245747ebfe1966f68bf29b6c7e59ad1..62cfba032cf1741683534d7c862d64d71db0bc3f 100644 (file)
@@ -48,7 +48,7 @@ bool AutoDetectProxy(URI &URL)
    Args.push_back(nullptr);
    FileFd PipeFd;
    pid_t Child;
-   if(Popen(&Args[0], PipeFd, Child, FileFd::ReadOnly) == false)
+   if(Popen(&Args[0], PipeFd, Child, FileFd::ReadOnly, false) == false)
       return _error->Error("ProxyAutoDetect command '%s' failed!", AutoDetectProxyCmd.c_str());
    char buf[512];
    bool const goodread = PipeFd.ReadLine(buf, sizeof(buf)) != nullptr;
diff --git a/test/libapt/apt-proxy-script b/test/libapt/apt-proxy-script
new file mode 100755 (executable)
index 0000000..41cfdc3
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+if [ $1 = "http://www.debian.org:90/temp/test" ]; then
+    echo "http://example.com"
+fi
+if [ $1 = "http://www.debian.org:91/temp/test" ]; then
+    echo "This works" >&2
+    echo "http://example.com/foo"
+fi
index 8296ca6a0de032ff1adaacf5835be541f8ff391f..09d0180493429547548f1841d752c63b167b2ace 100644 (file)
@@ -1,4 +1,6 @@
 #include <config.h>
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/proxy.h>
 #include <apt-pkg/strutl.h>
 #include <string>
 #include <gtest/gtest.h>
@@ -188,3 +190,27 @@ TEST(URITest, RFC2732)
    EXPECT_EQ("ftp://example.org", URI::ArchiveOnly(U));
    EXPECT_EQ("ftp://example.org/", URI::NoUserPassword(U));
 }
+TEST(URITest, AutoProxyTest)
+{
+   URI u0("http://www.debian.org:90/temp/test");
+   URI u1("http://www.debian.org:91/temp/test");
+
+   _config->Set("Acquire::http::Proxy-Auto-Detect", "./apt-proxy-script");
+
+   // Scenario 0: Autodetecting a simple proxy
+   AutoDetectProxy(u0);
+   EXPECT_EQ(_config->Find("Acquire::http::proxy::www.debian.org", ""), "http://example.com");
+
+   // Scenario 1: Proxy stays the same if it is already set
+   AutoDetectProxy(u1);
+   EXPECT_EQ(_config->Find("Acquire::http::proxy::www.debian.org", ""), "http://example.com");
+
+   // Scenario 2: Reading with stderr output works fine
+   _config->Clear("Acquire::http::proxy::www.debian.org");
+   AutoDetectProxy(u1);
+   EXPECT_EQ(_config->Find("Acquire::http::proxy::www.debian.org", ""), "http://example.com/foo");
+
+   // Scenario 1 again: Proxy stays the same if it is already set
+   AutoDetectProxy(u0);
+   EXPECT_EQ(_config->Find("Acquire::http::proxy::www.debian.org", ""), "http://example.com/foo");
+}