From 228ffa7bd1e190ae51fa2d31a46254e7734722f5 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Wed, 8 Jun 2022 19:22:12 -0700 Subject: [PATCH 1/3] Don't assume that _Hash_vec's size and capacity are always equal The prior implementation that used `vector` directly had bugs that sometimes result in differing size and capacity. Since old and new code have may link, we need to tolerate this condition. Fixes DevCom-1190124/VSO-1220461 --- stl/inc/xhash | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/stl/inc/xhash b/stl/inc/xhash index 80f983cc88..d259100f83 100644 --- a/stl/inc/xhash +++ b/stl/inc/xhash @@ -269,6 +269,12 @@ struct _Hash_vec { _Aliter_traits::max_size(_Mypair._Get_first())); } + _NODISCARD size_type capacity() const noexcept { + // This implementation never has capacity() differ from size(), but the previous implementation could. + // We need to handle that situation gracefully since we may link to old code. + return static_cast(_Mypair._Myval2._Myend - _Mypair._Myval2._Myfirst); + } + void _Assign_grow(const size_type _Cells, const value_type _Val) { // set the elements stored here to _Cells copies of _Val, leaving the value unchanged if an exception is thrown const auto _Oldsize = size(); @@ -279,7 +285,7 @@ struct _Hash_vec { // nothrow hereafter if (_Oldsize != 0) { _Destroy_range(_Mypair._Myval2._Myfirst, _Mypair._Myval2._Mylast); - _Alvec.deallocate(_Mypair._Myval2._Myfirst, _Oldsize); + _Alvec.deallocate(_Mypair._Myval2._Myfirst, capacity()); } _Mypair._Myval2._Myfirst = _Newvec; @@ -294,7 +300,7 @@ struct _Hash_vec { void _Tidy() noexcept { _Destroy_range(_Mypair._Myval2._Myfirst, _Mypair._Myval2._Mylast); - _Mypair._Get_first().deallocate(_Mypair._Myval2._Myfirst, size()); + _Mypair._Get_first().deallocate(_Mypair._Myval2._Myfirst, capacity()); _Mypair._Myval2._Myfirst = nullptr; _Mypair._Myval2._Mylast = nullptr; _Mypair._Myval2._Myend = nullptr; From 708a8c8258a97af3f675f83a7f94cc1a9013228a Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Wed, 8 Jun 2022 20:53:02 -0700 Subject: [PATCH 2/3] Review comments --- stl/inc/xhash | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/stl/inc/xhash b/stl/inc/xhash index d259100f83..ab19f23fa6 100644 --- a/stl/inc/xhash +++ b/stl/inc/xhash @@ -271,7 +271,7 @@ struct _Hash_vec { _NODISCARD size_type capacity() const noexcept { // This implementation never has capacity() differ from size(), but the previous implementation could. - // We need to handle that situation gracefully since we may link to old code. + // We need to handle that situation gracefully since we may link to old code (See GH-2774). return static_cast(_Mypair._Myval2._Myend - _Mypair._Myval2._Myfirst); } @@ -283,9 +283,10 @@ struct _Hash_vec { if (_Oldsize < _Cells) { const auto _Newvec = _Alvec.allocate(_Cells); // throws // nothrow hereafter - if (_Oldsize != 0) { + const auto _Oldcapacity = capacity(); + if (_Oldcapacity != 0) { _Destroy_range(_Mypair._Myval2._Myfirst, _Mypair._Myval2._Mylast); - _Alvec.deallocate(_Mypair._Myval2._Myfirst, capacity()); + _Alvec.deallocate(_Mypair._Myval2._Myfirst, _Old_capacity); } _Mypair._Myval2._Myfirst = _Newvec; From f6be1bf786879b8149aa7c10ef86759e28f91021 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Wed, 8 Jun 2022 21:47:22 -0700 Subject: [PATCH 3/3] Use a single spelling for `_Oldcapacity`, stifling my creativity --- stl/inc/xhash | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/xhash b/stl/inc/xhash index ab19f23fa6..0638994f43 100644 --- a/stl/inc/xhash +++ b/stl/inc/xhash @@ -286,7 +286,7 @@ struct _Hash_vec { const auto _Oldcapacity = capacity(); if (_Oldcapacity != 0) { _Destroy_range(_Mypair._Myval2._Myfirst, _Mypair._Myval2._Mylast); - _Alvec.deallocate(_Mypair._Myval2._Myfirst, _Old_capacity); + _Alvec.deallocate(_Mypair._Myval2._Myfirst, _Oldcapacity); } _Mypair._Myval2._Myfirst = _Newvec;