Przeglądaj źródła

2010-10-02 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

	Rewritten util::escapePath(). Now it does not replace bad chars:it
	performs percent-encode against them.  util::fixTaintedBasename()
	now replaces "/" with "%2F".  Added 0x7f as bad chars in
	util::detectDirTraversal().
	* src/util.cc
	* test/UtilTest.cc
Tatsuhiro Tsujikawa 15 lat temu
rodzic
commit
d5e0046f29
3 zmienionych plików z 37 dodań i 32 usunięć
  1. 9 0
      ChangeLog
  2. 24 28
      src/util.cc
  3. 4 4
      test/UtilTest.cc

+ 9 - 0
ChangeLog

@@ -1,3 +1,12 @@
+2010-10-02  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
+
+	Rewritten util::escapePath(). Now it does not replace bad chars:it
+	performs percent-encode against them.  util::fixTaintedBasename()
+	now replaces "/" with "%2F".  Added 0x7f as bad chars in
+	util::detectDirTraversal().
+	* src/util.cc
+	* test/UtilTest.cc
+
 2010-10-02  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
 
 	Non-UTF8 filenames are now percent-encoded.  For example, filename

+ 24 - 28
src/util.cc

@@ -1289,7 +1289,8 @@ std::string applyDir(const std::string& dir, const std::string& relPath)
 
 std::string fixTaintedBasename(const std::string& src)
 {
-  return escapePath(replace(src, A2STR::SLASH_C, A2STR::UNDERSCORE_C));
+  static std::string SLASH_REP = "%2F";
+  return escapePath(replace(src, A2STR::SLASH_C, SLASH_REP));
 }
 
 void generateRandomKey(unsigned char* key)
@@ -1329,7 +1330,8 @@ bool inPrivateAddress(const std::string& ipv4addr)
 bool detectDirTraversal(const std::string& s)
 {
   for(std::string::const_iterator i = s.begin(), eoi = s.end(); i != eoi; ++i) {
-    if(0x00 <= (*i) && (*i) <= 0x1f) {
+    unsigned char c = *i;
+    if(in(c, 0x00, 0x1f) || c == 0x7f) {
       return true;
     }
   }
@@ -1345,35 +1347,29 @@ bool detectDirTraversal(const std::string& s)
     util::endsWith(s, "/..");
 }
 
-namespace {
-class EscapePath {
-private:
-  char repChar_;
-public:
-  EscapePath(const char& repChar):repChar_(repChar) {}
-
-  char operator()(const char& c) {
-    if(0x00 <= c && c <=0x1f) {
-      return repChar_;
-    }
+std::string escapePath(const std::string& s)
+{
+  // We don't escape '/' because we use it as a path separator.
 #ifdef __MINGW32__
-    // We don't escape '/' because we use it as a path separator.
-    static const char WIN_INVALID_PATH_CHARS[] =
-      { '"', '*', ':', '<', '>', '?', '\\', '|' };
-    if(std::find(vbegin(WIN_INVALID_PATH_CHARS), vend(WIN_INVALID_PATH_CHARS),
-                 c) != vend(WIN_INVALID_PATH_CHARS)) {
-      return repChar_;
-    }
+  static const char WIN_INVALID_PATH_CHARS[] =
+    { '"', '*', ':', '<', '>', '?', '\\', '|' };
 #endif // __MINGW32__
-    return c;
-  }
-};
-}
+  std::string d;
+  for(std::string::const_iterator i = s.begin(), eoi = s.end(); i != eoi; ++i) {
+    unsigned char c = *i;
+    if(in(c, 0x00, 0x1f) || c == 0x7f
+#ifdef __MINGW32__
+       || std::find(vbegin(WIN_INVALID_PATH_CHARS),
+                    vend(WIN_INVALID_PATH_CHARS),
+                    c) != vend(WIN_INVALID_PATH_CHARS)
 
-std::string escapePath(const std::string& s)
-{
-  std::string d = s;
-  std::transform(d.begin(), d.end(), d.begin(), EscapePath('_'));
+#endif // __MINGW32__
+       ){
+      d += StringFormat("%%%02X", c).str();
+    } else {
+      d += *i;
+    }
+  }
   return d;
 }
 

+ 4 - 4
test/UtilTest.cc

@@ -1024,9 +1024,9 @@ void UtilTest::testApplyDir()
 
 void UtilTest::testFixTaintedBasename()
 {
-  CPPUNIT_ASSERT_EQUAL(std::string("a_b"), util::fixTaintedBasename("a/b"));
+  CPPUNIT_ASSERT_EQUAL(std::string("a%2Fb"), util::fixTaintedBasename("a/b"));
 #ifdef __MINGW32__
-  CPPUNIT_ASSERT_EQUAL(std::string("a_b"), util::fixTaintedBasename("a\\b"));
+  CPPUNIT_ASSERT_EQUAL(std::string("a%5Cb"), util::fixTaintedBasename("a\\b"));
 #else // !__MINGW32__
   CPPUNIT_ASSERT_EQUAL(std::string("a\\b"), util::fixTaintedBasename("a\\b"));
 #endif // !__MINGW32__
@@ -1059,12 +1059,12 @@ void UtilTest::testDetectDirTraversal()
 
 void UtilTest::testEscapePath()
 {
-  CPPUNIT_ASSERT_EQUAL(std::string("foo_bar__"),
+  CPPUNIT_ASSERT_EQUAL(std::string("foo%00bar%00%01"),
                        util::escapePath(std::string("foo")+(char)0x00+
                                         std::string("bar")+(char)0x00+
                                         (char)0x01));
 #ifdef __MINGW32__
-  CPPUNIT_ASSERT_EQUAL(std::string("foo_bar"), util::escapePath("foo\\bar"));
+  CPPUNIT_ASSERT_EQUAL(std::string("foo%5Cbar"), util::escapePath("foo\\bar"));
 #else // !__MINGW32__
   CPPUNIT_ASSERT_EQUAL(std::string("foo\\bar"), util::escapePath("foo\\bar"));
 #endif // !__MINGW32__