diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2c346175..a584bd68 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: - name: Configure run: cmake -S . -B build-cmake -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DEQ_BUILD_TESTS=ON - name: Build - run: cmake --build build-cmake --config ${{ matrix.build_type }} --parallel + run: cmake --build build-cmake --config ${{ matrix.build_type }} --parallel 4 - name: Test run: ctest --test-dir build-cmake --build-config ${{ matrix.build_type }} --output-on-failure --no-tests=error - name: Setup tmate debug session diff --git a/base/strings/base_string.h b/base/strings/base_string.h index bbcd3f77..88dbf384 100644 --- a/base/strings/base_string.h +++ b/base/strings/base_string.h @@ -316,11 +316,13 @@ class BasicBaseString { } } + // data(), not c_str(): a view (StringRef) has c_str() too, but a slice of a + // longer string is not null-terminated and its c_str() refuses in debug. template requires(base::HasStringTraits) BasicBaseString(const TOther& other) { init_empty(); - assign(other.c_str(), static_cast(other.size())); + assign(other.data(), static_cast(other.size())); } // From any non-owning character range (std::string_view, base::StringRef). diff --git a/base/strings/base_string_test.cc b/base/strings/base_string_test.cc index 7463f037..d2616690 100644 --- a/base/strings/base_string_test.cc +++ b/base/strings/base_string_test.cc @@ -603,6 +603,15 @@ TEST(BaseStringSearch, ReverseFindHonoursThePosition) { EXPECT_EQ(s.rfind('.', 2), 1u); } +TEST(BaseStringAssign, ConstructsFromAnUnterminatedSlice) { + // A slice of a longer string ends before the terminator; copying it must + // take (data, size), never c_str(). + const base::StringRef whole("rxe://config/low.ini"); + const base::String mount(whole.substr(0, 3)); + EXPECT_EQ(mount, "rxe"); + EXPECT_EQ(mount.size(), 3u); +} + TEST(BaseStringAssign, AssignsFromAnotherStringLike) { base::StringRef ref("hello"); base::String s;