Title
char_traits::copy precondition too weak
Status
c++23
Section
[char.traits.require]
Submitter
Jonathan Wakely

Created on 2018-03-16.00:00:00 last changed 4 months ago

Messages

Date: 2023-02-13.10:17:57

Proposed resolution:

  1. Edit [char.traits.require], Table 75 — "Character traits requirements" [tab:char.traits.req], as indicated:

    Table 75 — Character traits requirements [tab:char.traits.req]
    Expression Return type Assertion/note
    pre/post-condition
    Complexity
    […]
    X::copy(s,p,n) X::char_type* Preconditions: p not in [s,s+n)The ranges [p,p+n)
    and [s,s+n) do not overlap
    .
    Returns: s.
    for each i in [0,n), performs
    X::assign(s[i],p[i]).
    linear
    […]
Date: 2023-02-13.00:00:00

[ 2023-02-13 Approved at February 2023 meeting in Issaquah. Status changed: Voting → WP. ]

Date: 2022-11-11.19:53:45

[ Kona 2022-11-11; Move to Ready ]

LWG voted for Option A (6 for, 0 against, 1 netural)

Date: 2022-04-15.00:00:00

[ 2022-04-25; Daniel rebases wording on N4910 ]

Previous resolution [SUPERSEDED]:

This wording is relative to N4910.

Option A:

  1. Edit [char.traits.require], Table 75 — "Character traits requirements" [tab:char.traits.req], as indicated:

    Table 75 — Character traits requirements [tab:char.traits.req]
    Expression Return type Assertion/note
    pre/post-condition
    Complexity
    […]
    X::copy(s,p,n) X::char_type* Preconditions: p not in [s,s+n)The ranges [p,p+n)
    and [s,s+n) do not overlap
    .
    Returns: s.
    for each i in [0,n), performs
    X::assign(s[i],p[i]).
    linear
    […]

Option B:

NAD (i.e. implementations need to be fixed, in practice char_traits::copy and char_traits::move might be equivalent).

Date: 2018-08-23.00:00:00

[ 2018-08-23 Batavia Issues processing ]

No consensus for direction; revisit in San Diego. Status to Open.

Date: 2018-04-03.00:00:00

[ 2018-04-03 Priority set to 2 after discussion on the reflector. ]

Date: 2018-03-16.00:00:00

Table 54, Character traits requirements, says that char_traits::move allows the ranges to overlap, but char_traits::copy requires that p is not in the range [s, s + n). This appears to be an attempt to map to the requirements of memmove and memcpy respectively, allowing those to be used to implement the functions, however the requirements for copy are weaker than those for memcpy. The C standard says for memcpy "If copying takes place between objects that overlap, the behavior is undefined" which is a stronger requirement than the start of the source range not being in the destination range.

All of libstdc++, libc++ and VC++ simply use memcpy for char_traits<char>::copy, resulting in undefined behaviour in this example:

char p[] = "abc";
char* s = p + 1;
std::char_traits<char>::copy(s, p, 2);
assert(std::char_traits<char>::compare(p, "aab", 3) == 0);

If the intention is to allow memcpy as a valid implementation then the precondition is wrong (unfortunately nobody realized this when fixing char_traits::move in LWG DR 7). If the intention is to require memmove then it is strange to have separate copy and move functions that both use memmove.

N.B. std::copy and std::copy_backward are not valid implementations of char_traits::copy either, due to different preconditions.

Changing the precondition implicitly applies to basic_string::copy ([string.copy]), and basic_string_view::copy ([string.view.ops]), which are currently required to support partially overlapping ranges:

std::string s = "abc";
s.copy(s.data() + 1, s.length() - 1);
assert(s == "aab");
History
Date User Action Args
2023-11-22 15:47:43adminsetstatus: wp -> c++23
2023-02-13 10:17:57adminsetmessages: + msg13349
2023-02-13 10:17:57adminsetstatus: voting -> wp
2023-02-06 15:33:48adminsetstatus: ready -> voting
2022-11-11 19:53:45adminsetmessages: + msg13022
2022-11-11 19:53:45adminsetstatus: open -> ready
2022-04-25 12:35:37adminsetmessages: + msg12434
2018-08-24 13:31:33adminsetmessages: + msg10130
2018-08-24 13:31:33adminsetstatus: new -> open
2018-04-03 19:00:32adminsetmessages: + msg9799
2018-03-25 12:00:21adminsetmessages: + msg9778
2018-03-16 00:00:00admincreate