Skip to content

Commit 1020a1a

Browse files
committed
[Concurrency] Clear Slab's fake metadata pointer before freeing it.
This helps ensure that memory analysis tools don't get confused by leftover metadata pointers in reallocated memory that hasn't been initialized yet. rdar://88494373
1 parent 5a5f4b0 commit 1020a1a

File tree

2 files changed

+29
-0
lines changed

2 files changed

+29
-0
lines changed

stdlib/public/Concurrency/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ else()
6161
list(APPEND SWIFT_RUNTIME_CONCURRENCY_C_FLAGS "-fswift-async-fp=never")
6262
endif()
6363

64+
list(APPEND SWIFT_RUNTIME_CONCURRENCY_C_FLAGS
65+
"-D__STDC_WANT_LIB_EXT1__=1")
66+
6467
add_swift_target_library(swift_Concurrency ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} IS_STDLIB
6568
../CompatibilityOverride/CompatibilityOverride.cpp
6669
Actor.cpp

stdlib/public/runtime/StackAllocator.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@
1414
//
1515
//===----------------------------------------------------------------------===//
1616

17+
// Define __STDC_WANT_LIB_EXT1__ to get memset_s on platforms that have it.
18+
// Other files may have included string.h without it already, so we also set
19+
// this with a -D flag when building, but this allows tests to build without
20+
// additional trouble.
21+
#define __STDC_WANT_LIB_EXT1__ 1
22+
#include <string.h>
23+
1724
#include "swift/ABI/MetadataValues.h"
1825
#include "swift/Runtime/Debug.h"
1926
#include "llvm/Support/Alignment.h"
@@ -118,6 +125,22 @@ class StackAllocator {
118125
return headerSize() + size;
119126
}
120127

128+
/// Clear the fake metadata pointer. Call before freeing so that leftover
129+
/// heap garbage doesn't have slab metadata pointers in it.
130+
void clearMetadata() {
131+
// Use memset_s or explicit_bzero where available. Fall back to a plain
132+
// assignment on unknown platforms. This is not necessary for correctness,
133+
// just as an aid to analysis tools, so it's OK if the fallback gets
134+
// optimized out.
135+
#if defined(__APPLE__)
136+
memset_s(&metadata, sizeof(metadata), 0, sizeof(metadata));
137+
#elif defined(__linux__)
138+
explicit_bzero(&metadata, sizeof(metadata));
139+
#else
140+
metadata = 0;
141+
#endif
142+
}
143+
121144
/// Return the payload buffer address at \p atOffset.
122145
///
123146
/// Note: it's valid to call this function on a not-yet-constructed slab.
@@ -247,6 +270,7 @@ class StackAllocator {
247270
while (slab) {
248271
Slab *next = slab->next;
249272
freedCapacity += slab->capacity;
273+
slab->clearMetadata();
250274
free(slab);
251275
numAllocatedSlabs--;
252276
slab = next;
@@ -272,6 +296,8 @@ class StackAllocator {
272296
~StackAllocator() {
273297
if (lastAllocation)
274298
SWIFT_FATAL_ERROR(0, "not all allocations are deallocated");
299+
if (firstSlabIsPreallocated)
300+
firstSlab->clearMetadata();
275301
(void)freeAllSlabs(firstSlabIsPreallocated ? firstSlab->next : firstSlab);
276302
assert(getNumAllocatedSlabs() == 0);
277303
}

0 commit comments

Comments
 (0)