Browse Source

ensure Cnf::FindFile doesn't return files below /dev/null

Very unlikely, but if the parent is /dev/null, the child empty and the
grandchild a value we returned /dev/null/value which doesn't exist, so
hardly a problem, but for best operability we should be consistent in
our work and return /dev/null always.
David Kalnischkies 7 years ago
parent
commit
bbd8308cc0

+ 1 - 9
apt-pkg/contrib/configuration.cc

@@ -225,15 +225,7 @@ string Configuration::FindFile(const char *Name,const char *Default) const
       }
       result.append(val);
    }
-
-   // do some normalisation by removing // and /./ from the path
-   size_t found = string::npos;
-   while ((found = result.find("/./")) != string::npos)
-      result.replace(found, 3, "/");
-   while ((found = result.find("//")) != string::npos)
-      result.replace(found, 2, "/");
-
-   return result;
+   return flNormalize(result);
 }
 									/*}}}*/
 // Configuration::FindDir - Find a directory name			/*{{{*/

+ 19 - 0
apt-pkg/contrib/fileutl.cc

@@ -694,6 +694,25 @@ string flAbsPath(string File)
    return AbsPath;
 }
 									/*}}}*/
+std::string flNormalize(std::string file)				/*{{{*/
+{
+   if (file.empty())
+      return file;
+   // do some normalisation by removing // and /./ from the path
+   size_t found = string::npos;
+   while ((found = file.find("/./")) != string::npos)
+      file.replace(found, 3, "/");
+   while ((found = file.find("//")) != string::npos)
+      file.replace(found, 2, "/");
+
+   if (APT::String::Startswith(file, "/dev/null"))
+   {
+      file.erase(strlen("/dev/null"));
+      return file;
+   }
+   return file;
+}
+									/*}}}*/
 // SetCloseExec - Set the close on exec flag				/*{{{*/
 // ---------------------------------------------------------------------
 /* */

+ 2 - 0
apt-pkg/contrib/fileutl.h

@@ -234,6 +234,8 @@ std::string flCombine(std::string Dir,std::string File);
 /** \brief Takes a file path and returns the absolute path
  */
 std::string flAbsPath(std::string File);
+/** \brief removes superfluous /./ and // from path */
+APT_HIDDEN std::string flNormalize(std::string file);
 
 // simple c++ glob
 std::vector<std::string> Glob(std::string const &pattern, int flags=0);

+ 28 - 0
test/libapt/configuration_test.cc

@@ -112,6 +112,34 @@ TEST(ConfigurationTest,DirsAndFiles)
 	EXPECT_EQ("/rootdir/dev/null", Cnf.FindDir("Dir::State"));
 	EXPECT_EQ("/rootdir/dev/null", Cnf.FindDir("Dir::State::lists"));
 }
+TEST(ConfigurationTest,DevNullInPaths)
+{
+	Configuration Cnf;
+	EXPECT_EQ("", Cnf.FindFile("Dir"));
+	EXPECT_EQ("", Cnf.FindFile("Dir::State"));
+	EXPECT_EQ("", Cnf.FindFile("Dir::State::status"));
+	Cnf.Set("Dir::State", "/dev/null");
+	EXPECT_EQ("/dev/null", Cnf.FindFile("Dir::State"));
+	Cnf.Set("Dir", "/");
+	Cnf.Set("Dir::State::status", "status");
+	EXPECT_EQ("/dev/null", Cnf.FindFile("Dir::State"));
+	EXPECT_EQ("/dev/null", Cnf.FindFile("Dir::State::status"));
+	Cnf.Set("Dir::State", "");
+	EXPECT_EQ("", Cnf.FindFile("Dir::State"));
+	EXPECT_EQ("/status", Cnf.FindFile("Dir::State::status"));
+	Cnf.Set("Dir", "/dev/null");
+	EXPECT_EQ("/dev/null", Cnf.FindFile("Dir"));
+	EXPECT_EQ("", Cnf.FindFile("Dir::State"));
+	EXPECT_EQ("/dev/null", Cnf.FindFile("Dir::State::status"));
+	Cnf.Set("Dir", "/rootdir");
+	EXPECT_EQ("/rootdir", Cnf.FindFile("Dir"));
+	EXPECT_EQ("", Cnf.FindFile("Dir::State"));
+	EXPECT_EQ("/rootdir/status", Cnf.FindFile("Dir::State::status"));
+	Cnf.Set("Dir::State::status", "/foo/status");
+	EXPECT_EQ("/rootdir", Cnf.FindFile("Dir"));
+	EXPECT_EQ("", Cnf.FindFile("Dir::State"));
+	EXPECT_EQ("/foo/status", Cnf.FindFile("Dir::State::status"));
+}
 TEST(ConfigurationTest,Vector)
 {
 	Configuration Cnf;