<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/87969>87969</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
[libc++] `num_get::get` extracts too many characters when the input is invalid
</td>
</tr>
<tr>
<th>Labels</th>
<td>
libc++
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
frederick-vs-ja
</td>
</tr>
</table>
<pre>
Currently, the following program prints 2 when using libc++, which means that the call to `num_get::get` accumulates the whole "XX" when parsing a `double` value ([Godbolt link](https://godbolt.org/z/v9Web7f6G)).
```C++
#include <iostream>
#include <sstream>
#include <locale>
int main()
{
struct num_get_helper : std::num_get<char, char*> {};
num_get_helper ng;
char str[]{"XX"};
std::ios_base::iostate err{};
double x = -1.0;
std::istringstream is;
auto it = ng.get(str, str + sizeof(str) - 1, is, err, x);
std::cout << it - str << '\n';
}
```
Per [[facet.num.get.virtuals]](https://eel.is/c++draft/facet.num.get.virtuals#3):
> If it is not discarded, then a check is made to determine if `c` is allowed as the next character of an input field of the conversion specifier returned by Stage 1.
The leading 'X' is already a disallowed character for specifier `l` (for `double`), so it shouldn't be accumulated and thus the printed value should be 0.
Likewise, if `"XX"` is replaced with `"0XX"`, the printed value should be 2 ('0' and the first 'X' are accumulated), but libc++ currently reports 3 ([Godbolt link](https://godbolt.org/z/6d69dscha)).
It seems that some checking for being "allowed as the next character of an input field of the conversion specifier" is missing.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJysVU2P4zYM_TXKhUigyEkcH3KYcTaLBXoo0ALd20KW6Fg7shToIzOzv76g7WSS6UwPRYHAjk2LfHwkH2WM5ugQd2z9yNb7mcyp82HXBtQYjHqan-P8p5w1Xr_u6hwCumRfmaghdQitt9Y_G3eEU_DHIHs4BeNSBAHPHTrIkWzWNIqJx-FXw3NnVAc9ShchdTINjpS0FpIHtuEu9z-OmFjxwIoH-rPhIJXKfbYyYRw-f-68RWBCfP_OxBTrJMMQTZIT7XNjkY6epc306ZatH7963XibwBr3xNZ7JrZdSqdIocSBicNxtC98ODJx-MXE4Vz9hU3Zbr4yUTFRLRjfM_4wXTd8_NVTcuNbURinbNYIrKiNjymg7Fnx5SNz_Fer9UpafDMOV-MS9NI4ykhUk6WcggMAxBSySjDR-KNDe8IArHiAmPTI6pXiWnUyUFHG-wMrvgA5K_esuLh858gdr6a3mHScAo89RB6m0tx5usY3Pv5oZMTrU5IJAUN4HxsAxkrCC7BiD_Plgn_kL6Zg3HEkE0y8cyBz8mDScN4dF5S32BJWURNkYOIRovmFvr28r2AOSzKbSFfCJWp4Ibr_mfoVhPKZgtSsqCncfHQ-PjNRsnXt6Hb1UO7ftdGt59-pZETmYysVpoXLPSFfnE1IWdpILH_QwIh2QaAP07zpINvExOETJ6IohqQe7tq6-ALfWkrBRHA-gTZRyaBRT1PvQILqUD3RB73USIOrMWHojUMwLQ2gotkzESQJBGqQ4-A6fElDt0iVMIBvQTow7pQTtAatpjeDHnh3xhCNdxBPqExrMEDAlINDDc0r_JHkEWF5N5B_dggWpSYVYKL8zkQ5Qggo9StIyuSC5w1D68NNDLbhlqAzsSXDrZQMElBDHLopdj5bTRVN0OCNQGmQTkPq8pjwoIeoJxkaT9EBfof8N_OEzybi0HQDf9cBGmkMeLJSoYZnk7rJzi8fXNT4s1hikD9RciJkRIfQmhDTlSYZ7nKYUm1yuhFvUBf5Jzg-pAjFfxbWjd5UOqpOfiCs3xJExH5aD9H3OPYb1ZWK0uBYYfE_NhetEWpnE2mJLGZ6V-iqqOQMd8tyKdabQhTLWbfTmwKXZbtVQolmtVouV43ilRZCq6LhxXJmdoKLFV_xLd9yXvDFutQbvt3iuqn4VuslW3HspbELa889MTIzMWbcbctqU82sbNDGYRkLcbs4BS3nsKND8yYfI1txa2KKb26SSXZY4zfH1vvPViq-JOIpQvIeeule35iL40Ilqkb2TATjztIaPcvB7t7V1qQuNwvleyYOBGa6zU_B_0RF8jMkSLI05Ph3AAAA___mQ5bP">