StringRef no longer repoints m_start to m_data after c_str() on a substring.

This fixes an issue where a self-assignment of a StringRef copy would point into internally (and now dangling) data.
(now self-assignment check is no longer needed)
This commit is contained in:
Phil Nash 2019-05-21 00:04:19 +01:00
parent 71fce429af
commit 96355da34e
3 changed files with 10 additions and 11 deletions

View File

@ -39,9 +39,11 @@ namespace Catch {
} }
auto StringRef::c_str() const -> char const* { auto StringRef::c_str() const -> char const* {
if( isSubstring() ) if( !isSubstring() )
const_cast<StringRef*>( this )->takeOwnership(); return m_start;
return m_start;
const_cast<StringRef *>( this )->takeOwnership();
return m_data;
} }
auto StringRef::currentData() const noexcept -> char const* { auto StringRef::currentData() const noexcept -> char const* {
return m_start; return m_start;
@ -59,7 +61,6 @@ namespace Catch {
m_data = new char[m_size+1]; m_data = new char[m_size+1];
memcpy( m_data, m_start, m_size ); memcpy( m_data, m_start, m_size );
m_data[m_size] = '\0'; m_data[m_size] = '\0';
m_start = m_data;
} }
} }
auto StringRef::substr( size_type start, size_type size ) const noexcept -> StringRef { auto StringRef::substr( size_type start, size_type size ) const noexcept -> StringRef {

View File

@ -71,12 +71,12 @@ namespace Catch {
} }
auto operator = ( StringRef const &other ) noexcept -> StringRef& { auto operator = ( StringRef const &other ) noexcept -> StringRef& {
if( this != &other ) { // if( this != &other ) {
delete[] m_data; delete[] m_data;
m_data = nullptr; m_data = nullptr;
m_start = other.m_start; m_start = other.m_start;
m_size = other.m_size; m_size = other.m_size;
} // }
return *this; return *this;
} }

View File

@ -65,7 +65,6 @@ TEST_CASE( "StringRef", "[Strings][StringRef]" ) {
original.c_str(); // Forces it to take ownership original.c_str(); // Forces it to take ownership
REQUIRE( isSubstring( original ) == false );
REQUIRE( isOwned( original ) ); REQUIRE( isOwned( original ) );
} }
@ -88,14 +87,13 @@ TEST_CASE( "StringRef", "[Strings][StringRef]" ) {
REQUIRE( rawChars == s.currentData() ); // same pointer value REQUIRE( rawChars == s.currentData() ); // same pointer value
REQUIRE( ss.c_str() != rawChars ); REQUIRE( ss.c_str() != rawChars );
REQUIRE( isSubstring( ss ) == false );
REQUIRE( isOwned( ss ) ); REQUIRE( isOwned( ss ) );
REQUIRE( ss.currentData() != s.currentData() ); // different pointer value
SECTION( "Self-assignment after substring" ) { SECTION( "Self-assignment after substring" ) {
ss = *&ss; // the *& are there to suppress warnings (see: "Improvements to Clang's diagnostics" in https://rev.ng/gitlab/revng-bar-2019/clang/raw/master/docs/ReleaseNotes.rst) ss = *&ss; // the *& are there to suppress warnings (see: "Improvements to Clang's diagnostics" in https://rev.ng/gitlab/revng-bar-2019/clang/raw/master/docs/ReleaseNotes.rst)
REQUIRE(isOwned(ss) == true); REQUIRE( isOwned(ss) == false );
REQUIRE( ss == "hello" );
REQUIRE( rawChars == ss.currentData() ); // same pointer value
} }
} }