Opened 8 years ago

Closed 8 years ago

Last modified 8 years ago

#11150 closed Bugs (fixed)

string_ref::to_string is necessarily UB for a default-constructed string_ref, despite stating no preconditions

Reported by: Tomalak Geret'kal Owned by: No-Maintainer
Milestone: To Be Determined Component: utility
Version: Boost 1.57.0 Severity: Problem
Keywords: Cc:

Description

Consider:

boost::string_ref foo;
auto bar = foo.to_string();

As currently specified (to_string is not documented but in the code it seems to share the semantics of explicit string conversion, which is defined by the reference material, N3442), this invokes std::string::string(nullptr, 0), which has UB because one of the preconditions of that std::string constructor is that the pointer not be nullptr or NULL... and default-constructing boost::string_ref indeed sets the relevant pointer to NULL.

This has been fixed in newer versions of the proposal, e.g. by N3762 (seemingly accidentally):

Returns: basic_string<charT, traits, Allocator>(str.begin(), str.end(), a)

Boost.StringRef should be updated to make the same change, otherwise invoking .to_string() on a default-constructed boost::to_string has undefined behaviour, despite there being no preconditions specified on .to_string().

Alternatively it could be documented that .to_string()'s precondition is that the string_ref actually refers to a string.

(Thanks to Mgetz and Luc Danton on Stack Overflow for help identifying this bug.)

(I tried to link to references but Trac thought I was a spammer and the Captcha did not show up.)

Change History (4)

comment:1 by Marshall Clow, 8 years ago

Interestingly enough, this section of the standard [string.cons] has changed over time.

Specifically the bit about this constructor:

basic_string(const charT* s, size_type n, const Allocator& a = Allocator());

C++03 and C++11 have the following requirement: "Requires: s shall not be a null pointer and n < npos"

C++14 says instead: "Requires: s points to an array of at least n elements of charT."

{ NULL, 0 } is allowable in the second case, but not in the first.

comment:2 by Marshall Clow, 8 years ago

Resolution: fixed
Status: newclosed

Committed 13610caa36edcae896f59246a2933ef4772690f4 to fix this.

comment:3 by Tomalak Geret'kal, 8 years ago

I disagree. There is such a thing as an array of [at least] 0 elements of charT:

char* ptr = new char[0];
delete[] ptr;

and a NULL pointer cannot ever point to such an array. It doesn't point to anything.

comment:4 by Tomalak Geret'kal, 8 years ago

Thanks for fixing, anyway. :)

(Please note that, as you can see, I'm having real difficulty with Trac at the moment. Submissions take a good minute and one appeared to fail but then apparently succeeded. And led to two "comment 3"s?!)

Note: See TracTickets for help on using tickets.