[libc-commits] [libc] [libc][stdlib] Fix UB in freelist (PR #95330)

via libc-commits libc-commits at lists.llvm.org
Thu Jun 13 13:48:11 PDT 2024


================
@@ -92,19 +93,14 @@ bool FreeList<NUM_BUCKETS>::add_chunk(span<cpp::byte> chunk) {
   if (chunk.size() < sizeof(FreeListNode))
     return false;
 
-  union {
-    FreeListNode *node;
-    cpp::byte *bytes;
-  } aliased;
-
-  aliased.bytes = chunk.data();
-
+  // Add it to the correct list.
   size_t chunk_ptr = find_chunk_ptr_for_size(chunk.size(), false);
 
-  // Add it to the correct list.
-  aliased.node->size = chunk.size();
-  aliased.node->next = chunks_[chunk_ptr];
-  chunks_[chunk_ptr] = aliased.node;
+  FreeListNode node;
+  node.next = chunks_[chunk_ptr];
+  node.size = chunk.size();
+  LIBC_NAMESPACE::memcpy(chunk.data(), &node, sizeof(node));
----------------
PiJoules wrote:

Actually, since this is the only place a FreeListNode is created, I think a better way to do this would be placement new via

```
FreeListNode *node = new (chunk.data()) FreeListNode(chunks_[chunk_ptr], chunk.size());
```

This way we start the object lifetime of a FreeListNode at `chunk.data()`. This only requires `chunk.data()` being properly aligned but I think this should always be the case because a FreeListNode should always be stored after a Block which will have alignment large enough to hold a pointer.

https://github.com/llvm/llvm-project/pull/95330


More information about the libc-commits mailing list