This is an archive of the discontinued LLVM Phabricator instance.

[libc++] Improve the tests for std::basic_stringbuf's constructors and assignment operators
ClosedPublic

Authored by ldionne on Jul 5 2023, 5:13 AM.

Diff Detail

Event Timeline

pfusik created this revision.Jul 5 2023, 5:13 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 5 2023, 5:13 AM
pfusik requested review of this revision.Jul 5 2023, 5:13 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 5 2023, 5:13 AM
Herald added a reviewer: Restricted Project. · View Herald Transcript
pfusik added a subscriber: Mordante.Jul 5 2023, 5:17 AM

This fixes use-after-moves spotted by @Mordante in https://reviews.llvm.org/D151896#inline-1482124
The pointers are now set to null, same as in the default constructor of stringbuf.

philnik requested changes to this revision.Jul 5 2023, 8:15 AM
philnik added a subscriber: philnik.

This change requires a test.

This revision now requires changes to proceed.Jul 5 2023, 8:15 AM
pfusik updated this revision to Diff 537461.Jul 5 2023, 12:12 PM

Test source pointers set to null.

philnik requested changes to this revision.Jul 5 2023, 12:19 PM

I am quite certain that basic_stringbuf has to be in a valid but unspecified state, meaning that you can't just check that the pointer are null. You have to find a way to exploit the issue without directly testing the values. For example, would the moved-to buffer get touched when writing to the moved-from stringbuf (or some other operation)?

This revision now requires changes to proceed.Jul 5 2023, 12:19 PM
philnik added inline comments.Jul 5 2023, 12:20 PM
libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.assign/move.pass.cpp
110–114

Thanks for improving the coverage here BTW.

pfusik marked an inline comment as done.Jul 5 2023, 12:36 PM

@philnik Are the tests for libc++ or the C++ standard? The former does specify the state.

Before this change, the pointers were pointing to the string *after* the move, i.e. an empty string. I don't understand what would you like to test here?

I am quite certain that basic_stringbuf has to be in a valid but unspecified state

https://timsong-cpp.github.io/cppwp/n4868/stringbuf#cons-11.13

@philnik Are the tests for libc++ or the C++ standard? The former does specify the state.

Before this change, the pointers were pointing to the string *after* the move, i.e. an empty string. I don't understand what would you like to test here?

Thanks for working on this!

tests in the directory test/std are for the C++ standard. You can use LIBCPP_ASSERT for libc++ specific asserts.
tests in the directory test/libcxx are always libc++ specific tests.

pfusik updated this revision to Diff 537817.Jul 6 2023, 11:37 AM

s/assert/LIBCPP_ASSERT/

I am quite certain that basic_stringbuf has to be in a valid but unspecified state

https://timsong-cpp.github.io/cppwp/n4868/stringbuf#cons-11.13

Interesting. IIUC the buffer has to be empty after a move. We can test for that, but it looks to me like that's already the case with the old code. Since you claim that this is a bug fix, this has to be observable in some way by the user without checking for unspecified behavior. Otherwise this is basically an NFC without any reasoning for why the new code is better. It actually looks to me like the old code is correct.

pfusik updated this revision to Diff 539397.Jul 11 2023, 11:22 PM

Mark move assignment/constructor tests as unsupported in C++03.

@Mordante You pointed this as a problem in https://reviews.llvm.org/D151896#inline-1482124 Could you please explain? Now I'm confused myself.

BTW. Was stringbuf copy-assignable in C++03 ? See https://en.cppreference.com/w/cpp/io/basic_stringbuf/operator%3D

ldionne commandeered this revision.Oct 13 2023, 4:55 PM
ldionne added a reviewer: pfusik.
ldionne added a subscriber: ldionne.

Commandeering to finish for the GH PR transition.

After consideration, I think our current tests are lacking a bit but there is no risk of use-after-move. Indeed, when we set __p = const_cast<char_type*>(__rhs.__str_.data());, __p is:

  • nullptr if the string was not using SSO, because it was moved-out-from above in __str_ = _VSTD::move(__rhs.__str_);
  • a pointer to the start of the SSO inside __rhs.__str_ if the string was using SSO

Either way, we are not reusing the storage incorrectly. I will commandeer and fix the tests, but I think our current implementation is fine.

ldionne updated this revision to Diff 557703.Oct 13 2023, 5:06 PM
ldionne retitled this revision from [libc++] Do not use stringbuf's string after move to [libc++] Improve the tests for std::basic_stringbuf's constructors and assignment operators.

Updating.

ldionne updated this revision to Diff 557741.Oct 17 2023, 5:10 PM

Fix C++11 CI issues.

ldionne accepted this revision as: Restricted Project.Oct 18 2023, 8:25 PM
This revision was not accepted when it landed; it landed in state Needs Review.Oct 18 2023, 8:26 PM
This revision was automatically updated to reflect the committed changes.