]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: fix buffer overflow in path::operator+= (PR92853)
authorJonathan Wakely <jwakely@redhat.com>
Mon, 9 Dec 2019 11:16:29 +0000 (11:16 +0000)
committerJonathan Wakely <redi@gcc.gnu.org>
Mon, 9 Dec 2019 11:16:29 +0000 (11:16 +0000)
When concatenating a path ending in a root-directory onto another path,
we added an empty filename to the end of the path twice, but only
reserved space for one. That meant the second write went past the end of
the allocated buffer.

PR libstdc++/92853
* src/c++17/fs_path.cc (filesystem::path::operator+=(const path&)):
Do not process a trailing directory separator twice.
* testsuite/27_io/filesystem/path/concat/92853.cc: New test.
* testsuite/27_io/filesystem/path/concat/path.cc: Test more cases.
* testsuite/27_io/filesystem/path/concat/strings.cc: Test more cases.

From-SVN: r279115

libstdc++-v3/ChangeLog
libstdc++-v3/src/c++17/fs_path.cc
libstdc++-v3/testsuite/27_io/filesystem/path/concat/92853.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/filesystem/path/concat/path.cc
libstdc++-v3/testsuite/27_io/filesystem/path/concat/strings.cc

index c793fe97722cde671d365b3f1897b21ba36c46d5..4a092e835fa6d7798d9f282afc11aa845d8e98e7 100644 (file)
@@ -1,3 +1,15 @@
+2019-12-09  Jonathan Wakely  <jwakely@redhat.com>
+
+       Backport from mainline
+       2019-12-09  Jonathan Wakely  <jwakely@redhat.com>
+
+       PR libstdc++/92853
+       * src/c++17/fs_path.cc (filesystem::path::operator+=(const path&)):
+       Do not process a trailing directory separator twice.
+       * testsuite/27_io/filesystem/path/concat/92853.cc: New test.
+       * testsuite/27_io/filesystem/path/concat/path.cc: Test more cases.
+       * testsuite/27_io/filesystem/path/concat/strings.cc: Test more cases.
+
 2019-11-22  Jonathan Wakely  <jwakely@redhat.com>
 
        Backport from mainline
index 14842452354e089febbe699e34badfaacb333fdb..54bef75efd87579c022159e644214038f418d565 100644 (file)
@@ -968,16 +968,7 @@ path::operator+=(const path& p)
        }
 
       if (it != last && it->_M_type() == _Type::_Root_dir)
-       {
-         ++it;
-         if (it == last)
-           {
-             // This root-dir becomes a trailing slash
-             auto pos = _M_pathname.length() + p._M_pathname.length();
-             ::new(output++) _Cmpt({}, _Type::_Filename, pos);
-             ++_M_cmpts._M_impl->_M_size;
-           }
-       }
+       ++it;
 
       while (it != last)
        {
diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/concat/92853.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/concat/92853.cc
new file mode 100644 (file)
index 0000000..62bde05
--- /dev/null
@@ -0,0 +1,61 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do run { target c++17 } }
+
+#include <filesystem>
+#include <testsuite_fs.h>
+
+void
+test01()
+{
+  // PR libstdc++/92853
+  using std::filesystem::path;
+  path p1{ "." }, p2{ "/" };
+  p1 += p2;    // corrupts heap
+  path p3{ p1 };       // CRASH!
+  __gnu_test::compare_paths( p3, "./" );
+}
+
+void
+test02()
+{
+  using std::filesystem::path;
+  path p1{ "." }, p2{ "////" };
+  p1 += p2;
+  path p3{ p1 };
+  __gnu_test::compare_paths( p3, ".////" );
+}
+
+void
+test03()
+{
+  using std::filesystem::path;
+  path p1{ "./" }, p2{ "/" };
+  p1 += p2;
+  path p3{ p1 };
+  __gnu_test::compare_paths( p3, ".//" );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+  test03();
+}
index 9f534e64cb7ccde35eee2c753e1f22ca8217a3a9..16e668c01633f5221eebb2bc230bfe9ea744efaf 100644 (file)
@@ -55,6 +55,8 @@ test02()
     path x("//blah/di/blah");
     p += x;
     VERIFY( p.native() == prior_native + x.native() );
+    path copy(p);
+    compare_paths( copy, p );
   }
 }
 
@@ -66,10 +68,28 @@ test03()
   compare_paths(p, "a//b");
 }
 
+void
+test04()
+{
+  // Concat every test path onto every test path.
+  for (path p : __gnu_test::test_paths)
+  {
+    for (path x : __gnu_test::test_paths)
+    {
+      auto prior_native = p.native();
+      p += x;
+      VERIFY( p.native() == prior_native + x.native() );
+      path copy(p); // PR libstdc++/98523
+      compare_paths( copy, p );
+    }
+  }
+}
+
 int
 main()
 {
   test01();
   test02();
   test03();
+  test04();
 }
index 80ce25ef119a26cf03530b0bee438d83d556803d..f51707b171cb938ae48166bc9f99d3bffb55216b 100644 (file)
@@ -113,10 +113,29 @@ test03()
   p4 += s;
   compare_paths(p4, path(s0+'/'+s));
 }
+
+void
+test04()
+{
+  // Concat every test path onto every test path.
+  for (path p : __gnu_test::test_paths)
+  {
+    for (path x : __gnu_test::test_paths)
+    {
+      auto prior_native = p.native();
+      p += x.native();
+      VERIFY( p.native() == prior_native + x.native() );
+      path copy(p);
+      compare_paths( copy, p );
+    }
+  }
+}
+
 int
 main()
 {
   test01();
   test02();
   test03();
+  test04();
 }