Commit 023a3fb4 by Jonathan Wakely Committed by Jonathan Wakely

libstdc++: fix buffer overflow in path::operator+= (PR92853)

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.

From-SVN: r279110
parent a65d584d
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.
2019-12-09 François Dumont <fdumont@gcc.gnu.org>
* testsuite/23_containers/array/tuple_interface/get_debug_neg.cc:
......
......@@ -975,16 +975,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)
{
......
// 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();
}
......@@ -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();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment