Skip to content

Commit 1c89e0f

Browse files
committed
Simplify and improve readability
Added helper functions, removed unnecessary branches, simplified code.
1 parent 0ab9216 commit 1c89e0f

File tree

9 files changed

+108
-131
lines changed

9 files changed

+108
-131
lines changed

compiler-rt/include/sanitizer/common_interface_defs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ void SANITIZER_CDECL __sanitizer_annotate_double_ended_contiguous_container(
213213
/// \param old_storage_end End of the old container region.
214214
/// \param new_storage_beg Beginning of the new container region.
215215
/// \param new_storage_end End of the new container region.
216-
void SANITIZER_CDECL __sanitizer_move_contiguous_container_annotations(
216+
void SANITIZER_CDECL __sanitizer_copy_contiguous_container_annotations(
217217
const void *old_storage_beg, const void *old_storage_end,
218218
const void *new_storage_beg, const void *new_storage_end);
219219

compiler-rt/lib/asan/asan_errors.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -348,10 +348,10 @@ void ErrorBadParamsToAnnotateDoubleEndedContiguousContainer::Print() {
348348
ReportErrorSummary(scariness.GetDescription(), stack);
349349
}
350350

351-
void ErrorBadParamsToMoveContiguousContainerAnnotations::Print() {
351+
void ErrorBadParamsToCopyContiguousContainerAnnotations::Print() {
352352
Report(
353353
"ERROR: AddressSanitizer: bad parameters to "
354-
"__sanitizer_move_contiguous_container_annotations:\n"
354+
"__sanitizer_copy_contiguous_container_annotations:\n"
355355
" old_storage_beg : %p\n"
356356
" old_storage_end : %p\n"
357357
" new_storage_beg : %p\n"

compiler-rt/lib/asan/asan_errors.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -353,12 +353,12 @@ struct ErrorBadParamsToAnnotateDoubleEndedContiguousContainer : ErrorBase {
353353
void Print();
354354
};
355355

356-
struct ErrorBadParamsToMoveContiguousContainerAnnotations : ErrorBase {
356+
struct ErrorBadParamsToCopyContiguousContainerAnnotations : ErrorBase {
357357
const BufferedStackTrace *stack;
358358
uptr old_storage_beg, old_storage_end, new_storage_beg, new_storage_end;
359359

360-
ErrorBadParamsToMoveContiguousContainerAnnotations() = default; // (*)
361-
ErrorBadParamsToMoveContiguousContainerAnnotations(
360+
ErrorBadParamsToCopyContiguousContainerAnnotations() = default; // (*)
361+
ErrorBadParamsToCopyContiguousContainerAnnotations(
362362
u32 tid, BufferedStackTrace *stack_, uptr old_storage_beg_,
363363
uptr old_storage_end_, uptr new_storage_beg_, uptr new_storage_end_)
364364
: ErrorBase(tid, 10,
@@ -439,7 +439,7 @@ struct ErrorGeneric : ErrorBase {
439439
macro(StringFunctionSizeOverflow) \
440440
macro(BadParamsToAnnotateContiguousContainer) \
441441
macro(BadParamsToAnnotateDoubleEndedContiguousContainer) \
442-
macro(BadParamsToMoveContiguousContainerAnnotations) \
442+
macro(BadParamsToCopyContiguousContainerAnnotations) \
443443
macro(ODRViolation) \
444444
macro(InvalidPointerPair) \
445445
macro(Generic)

compiler-rt/lib/asan/asan_poisoning.cpp

Lines changed: 88 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -576,32 +576,66 @@ void __sanitizer_annotate_double_ended_contiguous_container(
576576
}
577577
}
578578

579+
// Checks if two pointers fall within the same memory granule.
579580
static bool WithinOneGranule(uptr p, uptr q) {
580581
if (p == q)
581582
return true;
582583
return RoundDownTo(p, ASAN_SHADOW_GRANULARITY) ==
583584
RoundDownTo(q - 1, ASAN_SHADOW_GRANULARITY);
584585
}
585586

586-
static void PoisonContainer(uptr storage_beg, uptr storage_end) {
587+
// Copies ASan memory annotation (a shadow memory value)
588+
// from one granule to another.
589+
static void CopyGranuleAnnotation(uptr dst, uptr src) {
590+
*(u8 *)MemToShadow(dst) = *(u8 *)MemToShadow(src);
591+
}
592+
593+
// Marks the specified number of bytes in a granule as accessible or
594+
// poisones the whole granule with kAsanContiguousContainerOOBMagic value.
595+
static void AnnotateContainerGranuleAccessibleBytes(uptr ptr, u8 n) {
587596
constexpr uptr granularity = ASAN_SHADOW_GRANULARITY;
588-
uptr internal_beg = RoundUpTo(storage_beg, granularity);
589-
uptr external_beg = RoundDownTo(storage_beg, granularity);
590-
uptr internal_end = RoundDownTo(storage_end, granularity);
591-
592-
if (internal_end > internal_beg)
593-
PoisonShadow(internal_beg, internal_end - internal_beg,
594-
kAsanContiguousContainerOOBMagic);
595-
// The new buffer may start in the middle of a granule.
596-
if (internal_beg != storage_beg && internal_beg < internal_end &&
597-
!AddressIsPoisoned(storage_beg)) {
598-
*(u8 *)MemToShadow(external_beg) =
599-
static_cast<u8>(storage_beg - external_beg);
597+
if (n == granularity) {
598+
*(u8 *)MemToShadow(ptr) = 0;
599+
} else if (n == 0) {
600+
*(u8 *)MemToShadow(ptr) = static_cast<u8>(kAsanContiguousContainerOOBMagic);
601+
} else {
602+
*(u8 *)MemToShadow(ptr) = n;
600603
}
601-
// The new buffer may end in the middle of a granule.
602-
if (internal_end != storage_end && AddressIsPoisoned(storage_end)) {
603-
*(u8 *)MemToShadow(internal_end) =
604-
static_cast<u8>(kAsanContiguousContainerOOBMagic);
604+
}
605+
606+
// Performs a byte-by-byte copy of ASan annotations (shadow memory values).
607+
// Result may be different due to ASan limitations, but result cannot lead
608+
// to false positives (more memory than requested may get unpoisoned).
609+
static void SlowCopyContainerAnnotations(uptr old_storage_beg,
610+
uptr old_storage_end,
611+
uptr new_storage_beg,
612+
uptr new_storage_end) {
613+
constexpr uptr granularity = ASAN_SHADOW_GRANULARITY;
614+
uptr new_internal_end = RoundDownTo(new_storage_end, granularity);
615+
uptr old_ptr = old_storage_beg;
616+
uptr new_ptr = new_storage_beg;
617+
618+
while (new_ptr < new_storage_end) {
619+
uptr next_new = RoundUpTo(new_ptr + 1, granularity);
620+
uptr granule_begin = next_new - granularity;
621+
uptr unpoisoned_bytes = 0;
622+
623+
for (; new_ptr != next_new && new_ptr != new_storage_end;
624+
++new_ptr, ++old_ptr) {
625+
if (!AddressIsPoisoned(old_ptr)) {
626+
unpoisoned_bytes = new_ptr - granule_begin + 1;
627+
}
628+
}
629+
if (new_ptr < new_storage_end || new_ptr == new_internal_end ||
630+
AddressIsPoisoned(new_storage_end)) {
631+
if (unpoisoned_bytes != 0 || granule_begin >= new_storage_beg) {
632+
AnnotateContainerGranuleAccessibleBytes(granule_begin,
633+
unpoisoned_bytes);
634+
} else if (!AddressIsPoisoned(new_storage_beg)) {
635+
AnnotateContainerGranuleAccessibleBytes(
636+
granule_begin, new_storage_beg - granule_begin);
637+
}
638+
}
605639
}
606640
}
607641

@@ -616,7 +650,7 @@ static void PoisonContainer(uptr storage_beg, uptr storage_end) {
616650
// the function handles this by going byte by byte, slowing down performance.
617651
// The old buffer annotations are not removed. If necessary,
618652
// user can unpoison old buffer with __asan_unpoison_memory_region.
619-
void __sanitizer_move_contiguous_container_annotations(
653+
void __sanitizer_copy_contiguous_container_annotations(
620654
const void *old_storage_beg_p, const void *old_storage_end_p,
621655
const void *new_storage_beg_p, const void *new_storage_end_p) {
622656
if (!flags()->detect_container_overflow)
@@ -639,109 +673,52 @@ void __sanitizer_move_contiguous_container_annotations(
639673
(old_storage_end - old_storage_beg) !=
640674
(new_storage_end - new_storage_beg)) {
641675
GET_STACK_TRACE_FATAL_HERE;
642-
ReportBadParamsToMoveContiguousContainerAnnotations(
676+
ReportBadParamsToCopyContiguousContainerAnnotations(
643677
old_storage_beg, old_storage_end, new_storage_beg, new_storage_end,
644678
&stack);
645679
}
646680

647681
if (old_storage_beg == old_storage_end)
648682
return;
649683

684+
if (old_storage_beg % granularity != new_storage_beg % granularity ||
685+
WithinOneGranule(new_storage_beg, new_storage_end)) {
686+
SlowCopyContainerAnnotations(old_storage_beg, old_storage_end,
687+
new_storage_beg, new_storage_end);
688+
return;
689+
}
690+
650691
uptr new_internal_beg = RoundUpTo(new_storage_beg, granularity);
651-
uptr old_internal_beg = RoundUpTo(old_storage_beg, granularity);
652-
uptr new_external_beg = RoundDownTo(new_storage_beg, granularity);
653-
uptr old_external_beg = RoundDownTo(old_storage_beg, granularity);
654692
uptr new_internal_end = RoundDownTo(new_storage_end, granularity);
655-
uptr old_internal_end = RoundDownTo(old_storage_end, granularity);
656-
657-
// At the very beginning we poison the whole buffer.
658-
// Later we unpoison what is necessary.
659-
PoisonContainer(new_storage_beg, new_storage_end);
660-
661-
// There are two cases.
662-
// 1) Distance between buffers is granule-aligned.
663-
// 2) It's not aligned, and therefore requires going byte by byte.
664-
if (old_storage_beg % granularity == new_storage_beg % granularity) {
665-
// When buffers are aligned in the same way, we can just copy shadow memory,
666-
// except the first and the last granule.
667-
if (new_internal_end > new_internal_beg)
668-
__builtin_memcpy((u8 *)MemToShadow(new_internal_beg),
669-
(u8 *)MemToShadow(old_internal_beg),
670-
(new_internal_end - new_internal_beg) / granularity);
671-
// If the beginning and the end of the storage are aligned, we are done.
672-
// Otherwise, we have to handle remaining granules.
673-
if (new_internal_beg != new_storage_beg ||
674-
new_internal_end != new_storage_end) {
675-
if (WithinOneGranule(new_storage_beg, new_storage_end)) {
676-
if (new_internal_end == new_storage_end) {
677-
if (!AddressIsPoisoned(old_storage_beg)) {
678-
*(u8 *)MemToShadow(new_external_beg) =
679-
*(u8 *)MemToShadow(old_external_beg);
680-
} else if (!AddressIsPoisoned(new_storage_beg)) {
681-
*(u8 *)MemToShadow(new_external_beg) =
682-
new_storage_beg - new_external_beg;
683-
}
684-
} else if (AddressIsPoisoned(new_storage_end)) {
685-
if (!AddressIsPoisoned(old_storage_beg)) {
686-
*(u8 *)MemToShadow(new_external_beg) =
687-
AddressIsPoisoned(old_storage_end)
688-
? *(u8 *)MemToShadow(old_internal_end)
689-
: new_storage_end - new_external_beg;
690-
} else if (!AddressIsPoisoned(new_storage_beg)) {
691-
*(u8 *)MemToShadow(new_external_beg) =
692-
(new_storage_beg == new_external_beg)
693-
? static_cast<u8>(kAsanContiguousContainerOOBMagic)
694-
: new_storage_beg - new_external_beg;
695-
}
696-
}
697-
} else {
698-
// Buffer is not within one granule!
699-
if (new_internal_beg != new_storage_beg) {
700-
if (!AddressIsPoisoned(old_storage_beg)) {
701-
*(u8 *)MemToShadow(new_external_beg) =
702-
*(u8 *)MemToShadow(old_external_beg);
703-
} else if (!AddressIsPoisoned(new_storage_beg)) {
704-
*(u8 *)MemToShadow(new_external_beg) =
705-
new_storage_beg - new_external_beg;
706-
}
707-
}
708-
if (new_internal_end != new_storage_end &&
709-
AddressIsPoisoned(new_storage_end)) {
710-
*(u8 *)MemToShadow(new_internal_end) =
711-
AddressIsPoisoned(old_storage_end)
712-
? *(u8 *)MemToShadow(old_internal_end)
713-
: old_storage_end - old_internal_end;
714-
}
715-
}
693+
if (new_internal_end > new_internal_beg) {
694+
uptr old_internal_beg = RoundUpTo(old_storage_beg, granularity);
695+
__builtin_memcpy((u8 *)MemToShadow(new_internal_beg),
696+
(u8 *)MemToShadow(old_internal_beg),
697+
(new_internal_end - new_internal_beg) / granularity);
698+
}
699+
// The only remaining cases involve edge granules when the container starts or
700+
// ends within a granule. We already know that the container's start and end
701+
// points lie in different granules.
702+
if (new_internal_beg != new_storage_beg) {
703+
// First granule
704+
uptr new_external_beg = RoundDownTo(new_storage_beg, granularity);
705+
uptr old_external_beg = RoundDownTo(old_storage_beg, granularity);
706+
if (!AddressIsPoisoned(old_storage_beg)) {
707+
CopyGranuleAnnotation(new_external_beg, old_external_beg);
708+
} else if (!AddressIsPoisoned(new_storage_beg)) {
709+
AnnotateContainerGranuleAccessibleBytes(
710+
new_external_beg, new_storage_beg - new_external_beg);
716711
}
717-
} else {
718-
// If buffers are not aligned, we have to go byte by byte.
719-
uptr old_ptr = old_storage_beg;
720-
uptr new_ptr = new_storage_beg;
721-
uptr next_new;
722-
for (; new_ptr < new_storage_end;) {
723-
next_new = RoundUpTo(new_ptr + 1, granularity);
724-
uptr unpoison_to = 0;
725-
for (; new_ptr != next_new && new_ptr != new_storage_end;
726-
++new_ptr, ++old_ptr) {
727-
if (!AddressIsPoisoned(old_ptr)) {
728-
unpoison_to = new_ptr + 1;
729-
}
730-
}
731-
if (new_ptr < new_storage_end || new_ptr == new_internal_end ||
732-
AddressIsPoisoned(new_storage_end)) {
733-
uptr granule_beg = RoundDownTo(new_ptr - 1, granularity);
734-
if (unpoison_to != 0) {
735-
uptr value =
736-
(unpoison_to == next_new) ? 0 : unpoison_to - granule_beg;
737-
*(u8 *)MemToShadow(granule_beg) = static_cast<u8>(value);
738-
} else {
739-
*(u8 *)MemToShadow(granule_beg) =
740-
(granule_beg >= new_storage_beg)
741-
? static_cast<u8>(kAsanContiguousContainerOOBMagic)
742-
: new_storage_beg - granule_beg;
743-
}
744-
}
712+
}
713+
if (new_internal_end != new_storage_end &&
714+
AddressIsPoisoned(new_storage_end)) {
715+
// Last granule
716+
uptr old_internal_end = RoundDownTo(old_storage_end, granularity);
717+
if (AddressIsPoisoned(old_storage_end)) {
718+
CopyGranuleAnnotation(new_internal_end, old_internal_end);
719+
} else {
720+
AnnotateContainerGranuleAccessibleBytes(
721+
new_internal_end, old_storage_end - old_internal_end);
745722
}
746723
}
747724
}

compiler-rt/lib/asan/asan_report.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -367,11 +367,11 @@ void ReportBadParamsToAnnotateDoubleEndedContiguousContainer(
367367
in_report.ReportError(error);
368368
}
369369

370-
void ReportBadParamsToMoveContiguousContainerAnnotations(
370+
void ReportBadParamsToCopyContiguousContainerAnnotations(
371371
uptr old_storage_beg, uptr old_storage_end, uptr new_storage_beg,
372372
uptr new_storage_end, BufferedStackTrace *stack) {
373373
ScopedInErrorReport in_report;
374-
ErrorBadParamsToMoveContiguousContainerAnnotations error(
374+
ErrorBadParamsToCopyContiguousContainerAnnotations error(
375375
GetCurrentTidOrInvalid(), stack, old_storage_beg, old_storage_end,
376376
new_storage_beg, new_storage_end);
377377
in_report.ReportError(error);

compiler-rt/lib/asan/asan_report.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ void ReportBadParamsToAnnotateDoubleEndedContiguousContainer(
8888
uptr storage_beg, uptr storage_end, uptr old_container_beg,
8989
uptr old_container_end, uptr new_container_beg, uptr new_container_end,
9090
BufferedStackTrace *stack);
91-
void ReportBadParamsToMoveContiguousContainerAnnotations(
91+
void ReportBadParamsToCopyContiguousContainerAnnotations(
9292
uptr old_storage_beg, uptr old_storage_end, uptr new_storage_beg,
9393
uptr new_storage_end, BufferedStackTrace *stack);
9494

compiler-rt/lib/sanitizer_common/sanitizer_common_interface.inc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
INTERFACE_FUNCTION(__sanitizer_acquire_crash_state)
1111
INTERFACE_FUNCTION(__sanitizer_annotate_contiguous_container)
1212
INTERFACE_FUNCTION(__sanitizer_annotate_double_ended_contiguous_container)
13-
INTERFACE_FUNCTION(__sanitizer_move_contiguous_container_annotations)
13+
INTERFACE_FUNCTION(__sanitizer_copy_contiguous_container_annotations)
1414
INTERFACE_FUNCTION(__sanitizer_contiguous_container_find_bad_address)
1515
INTERFACE_FUNCTION(
1616
__sanitizer_double_ended_contiguous_container_find_bad_address)

compiler-rt/lib/sanitizer_common/sanitizer_interface_internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ void __sanitizer_annotate_double_ended_contiguous_container(
7171
const void *old_container_beg, const void *old_container_end,
7272
const void *new_container_beg, const void *new_container_end);
7373
SANITIZER_INTERFACE_ATTRIBUTE
74-
void __sanitizer_move_contiguous_container_annotations(
74+
void __sanitizer_copy_contiguous_container_annotations(
7575
const void *old_storage_beg, const void *old_storage_end,
7676
const void *new_storage_beg, const void *new_storage_end);
7777
SANITIZER_INTERFACE_ATTRIBUTE

compiler-rt/test/asan/TestCases/move_container_annotations.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// RUN: %clangxx_asan -fexceptions -O %s -o %t && %env_asan_opts=detect_stack_use_after_return=0 %run %t
22
//
3-
// Test __sanitizer_move_contiguous_container_annotations.
3+
// Test __sanitizer_copy_contiguous_container_annotations.
44

55
#include <algorithm>
66
#include <deque>
@@ -61,8 +61,8 @@ static size_t count_unpoisoned(std::deque<int> &poison_states, size_t n) {
6161
return result;
6262
}
6363

64-
void TestMove(size_t capacity, size_t off_old, size_t off_new,
65-
int poison_buffers) {
64+
void TestNonOverlappingContainers(size_t capacity, size_t off_old,
65+
size_t off_new, int poison_buffers) {
6666
size_t old_buffer_size = capacity + off_old + kGranularity * 2;
6767
size_t new_buffer_size = capacity + off_new + kGranularity * 2;
6868
char *old_buffer = new char[old_buffer_size];
@@ -76,15 +76,15 @@ void TestMove(size_t capacity, size_t off_old, size_t off_new,
7676
char *old_end = old_beg + capacity;
7777
char *new_end = new_beg + capacity;
7878

79-
for (int i = 0; i < 75; i++) {
79+
for (int i = 0; i < 35; i++) {
8080
if (poison_old)
8181
__asan_poison_memory_region(old_buffer, old_buffer_size);
8282
if (poison_new)
8383
__asan_poison_memory_region(new_buffer, new_buffer_size);
8484

8585
RandomPoison(old_beg, old_end);
8686
std::deque<int> poison_states = GetPoisonedState(old_beg, old_end);
87-
__sanitizer_move_contiguous_container_annotations(old_beg, old_end, new_beg,
87+
__sanitizer_copy_contiguous_container_annotations(old_beg, old_end, new_beg,
8888
new_end);
8989

9090
// If old_buffer were poisoned, expected state of memory before old_beg
@@ -150,11 +150,11 @@ void TestMove(size_t capacity, size_t off_old, size_t off_new,
150150

151151
int main(int argc, char **argv) {
152152
int n = argc == 1 ? 64 : atoi(argv[1]);
153-
for (size_t j = 0; j < kGranularity * 2; j++) {
154-
for (size_t k = 0; k < kGranularity * 2; k++) {
153+
for (size_t j = 0; j < kGranularity + 2; j++) {
154+
for (size_t k = 0; k < kGranularity + 2; k++) {
155155
for (int i = 0; i <= n; i++) {
156156
for (int poison = 0; poison < 4; ++poison) {
157-
TestMove(i, j, k, poison);
157+
TestNonOverlappingContainers(i, j, k, poison);
158158
}
159159
}
160160
}

0 commit comments

Comments
 (0)