Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion androidtest/memtag/memtag_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ void tag_distinctness() {
p[j]++;
}

allocations[i] = addr;
allocations[i] = (uptr) p;
}

// free some of allocations to allow their slots to be reused
Expand Down
36 changes: 25 additions & 11 deletions h_malloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -801,7 +801,13 @@ static void enqueue_free_slab(struct size_class *c, struct slab_metadata *metada
}

// preserves errno
static inline void deallocate_small(void *p, const size_t *expected_size) {
static inline void deallocate_small(void *tagged_p, const size_t *expected_size) {
#ifdef HAS_ARM_MTE
u8 supplied_tag = get_pointer_tag(tagged_p);
#endif

void *p = untag_pointer(tagged_p);

struct slab_size_class_info size_class_info = slab_size_class(p);
size_t class = size_class_info.class;

Expand Down Expand Up @@ -830,6 +836,14 @@ static inline void deallocate_small(void *p, const size_t *expected_size) {
fatal_error("double free");
}

#ifdef HAS_ARM_MTE
if (likely51(is_memtag_enabled())) {
if (unlikely(supplied_tag != get_pointer_tag(__arm_mte_get_tag(p)))) {
fatal_error("invalid free (memory tag)");
}
}
#endif

if (likely(!is_zero_size)) {
check_canary(metadata, p, size);

Expand Down Expand Up @@ -1684,7 +1698,7 @@ EXPORT void *h_realloc(void *old, size_t size) {
}
memcpy(new, old_orig, copy_size);
if (old_in_slab_region) {
deallocate_small(old, NULL);
deallocate_small(old_orig, NULL);
} else {
deallocate_large(old, NULL);
}
Expand Down Expand Up @@ -1735,17 +1749,17 @@ EXPORT void h_free(void *p) {
return;
}

p = untag_pointer(p);
void *untagged_p = untag_pointer(p);

if (p < get_slab_region_end() && p >= ro.slab_region_start) {
if (untagged_p < get_slab_region_end() && untagged_p >= ro.slab_region_start) {
thread_unseal_metadata();
deallocate_small(p, NULL);
thread_seal_metadata();
return;
}

int saved_errno = errno;
deallocate_large(p, NULL);
deallocate_large(untagged_p, NULL);
errno = saved_errno;

thread_seal_metadata();
Expand All @@ -1760,11 +1774,11 @@ EXPORT void h_free_sized(void *p, size_t expected_size) {
return;
}

p = untag_pointer(p);
void *untagged_p = untag_pointer(p);

expected_size = adjust_size_for_canary(expected_size);

if (p < get_slab_region_end() && p >= ro.slab_region_start) {
if (untagged_p < get_slab_region_end() && untagged_p >= ro.slab_region_start) {
if (unlikely(expected_size > max_slab_size_class)) {
fatal_error("sized deallocation mismatch (small)");
}
Expand All @@ -1777,7 +1791,7 @@ EXPORT void h_free_sized(void *p, size_t expected_size) {
}

int saved_errno = errno;
deallocate_large(p, &expected_size);
deallocate_large(untagged_p, &expected_size);
errno = saved_errno;

thread_seal_metadata();
Expand All @@ -1788,11 +1802,11 @@ EXPORT void h_free_aligned_sized(void *p, size_t alignment, size_t expected_size
return;
}

p = untag_pointer(p);
void *untagged_p = untag_pointer(p);

expected_size = adjust_size_for_canary(expected_size);

if (p < get_slab_region_end() && p >= ro.slab_region_start) {
if (untagged_p < get_slab_region_end() && untagged_p >= ro.slab_region_start) {
if (unlikely((alignment - 1) & alignment || alignment > PAGE_SIZE)) {
fatal_error("invalid sized deallocation alignment (small)");
}
Expand All @@ -1814,7 +1828,7 @@ EXPORT void h_free_aligned_sized(void *p, size_t alignment, size_t expected_size
}

int saved_errno = errno;
deallocate_large(p, &expected_size);
deallocate_large(untagged_p, &expected_size);
errno = saved_errno;

thread_seal_metadata();
Expand Down