Skip to content

Commit 776202b

Browse files
committed
SharedFreeList - Fix nodes count desync and use after free on deallocateAll
1 parent 5caa66e commit 776202b

File tree

1 file changed

+21
-1
lines changed

1 file changed

+21
-1
lines changed

std/experimental/allocator/building_blocks/free_list.d

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -855,6 +855,10 @@ struct SharedFreeList(ParentAllocator,
855855
assert(nodes);
856856
atomicOp!("-=")(nodes, 1);
857857
}
858+
private void resetNodes() shared
859+
{
860+
nodes = 0;
861+
}
858862
private bool nodesFull() shared
859863
{
860864
return nodes >= approxMaxLength;
@@ -864,6 +868,7 @@ struct SharedFreeList(ParentAllocator,
864868
{
865869
private static void incNodes() { }
866870
private static void decNodes() { }
871+
private static void resetNodes() { }
867872
private enum bool nodesFull = false;
868873
}
869874

@@ -1017,13 +1022,16 @@ struct SharedFreeList(ParentAllocator,
10171022
else static if (hasMember!(ParentAllocator, "deallocate"))
10181023
{
10191024
result = true;
1020-
for (auto n = _root; n; n = n.next)
1025+
for (auto n = _root; n;)
10211026
{
1027+
auto tmp = n.next;
10221028
if (!parent.deallocate((cast(ubyte*)n)[0 .. max]))
10231029
result = false;
1030+
n = tmp;
10241031
}
10251032
}
10261033
_root = null;
1034+
resetNodes();
10271035
return result;
10281036
}
10291037
}
@@ -1064,6 +1072,18 @@ unittest
10641072
}
10651073
}
10661074

1075+
unittest
1076+
{
1077+
import std.experimental.allocator.mallocator : Mallocator;
1078+
static shared SharedFreeList!(Mallocator, 64, 128, 10) a;
1079+
auto b = a.allocate(100);
1080+
a.deallocate(b);
1081+
assert(a.nodes == 1);
1082+
b = [];
1083+
a.deallocateAll();
1084+
assert(a.nodes == 0);
1085+
}
1086+
10671087
unittest
10681088
{
10691089
import std.experimental.allocator.mallocator : Mallocator;

0 commit comments

Comments
 (0)