forked from OSchip/llvm-project
[NFC][asan] Handle non-intersecting case early
Differential Revision: https://reviews.llvm.org/D138772
This commit is contained in:
parent
e1657e3229
commit
2b026fedca
|
@ -512,97 +512,94 @@ void __sanitizer_annotate_double_ended_contiguous_container(
|
|||
FixUnalignedStorage(storage_beg, storage_end, old_beg, old_end, new_beg,
|
||||
new_end);
|
||||
|
||||
if (old_beg == old_end) {
|
||||
old_beg = old_end = new_beg;
|
||||
} else if (new_end <= old_beg || old_end <= new_beg || new_beg == new_end) {
|
||||
// Poisoining whole memory.
|
||||
uptr a = RoundDownTo(old_beg, granularity);
|
||||
uptr b = RoundUpTo(old_end, granularity);
|
||||
PoisonShadow(a, b - a, kAsanContiguousContainerOOBMagic);
|
||||
|
||||
old_beg = old_end = new_beg;
|
||||
}
|
||||
|
||||
if (old_beg != new_beg) {
|
||||
// There are two situations: we are poisoning or unpoisoning.
|
||||
// WARNING: at the moment we do not poison prefixes of blocks described by
|
||||
// one byte in shadow memory, so we have to unpoison prefixes of blocks with
|
||||
// content. Up to (granularity - 1) bytes not-in-use may not be poisoned.
|
||||
|
||||
if (new_beg < old_beg) { // We are unpoisoning
|
||||
uptr a = RoundDownTo(new_beg, granularity);
|
||||
uptr c = RoundDownTo(old_beg, granularity);
|
||||
// State at the moment is:
|
||||
// [storage_beg, a] is poisoned and should remain like that.
|
||||
// [a, c] is poisoned as well (interval may be empty if new_beg
|
||||
// and old_beg are in the same block). If the container is not
|
||||
// empty, first element starts somewhere in [c, c+granularity]. Because we
|
||||
// do not poison prefixes, memory [c, container_end] is not poisoned and
|
||||
// we won't change it. If container is empty, we have to unpoison memory
|
||||
// for elements after c, so [c, container_end]
|
||||
PoisonShadow(a, c - a, 0);
|
||||
if (old_beg == old_end &&
|
||||
!AddrIsAlignedByGranularity(old_beg)) { // was empty && ends in the
|
||||
// middle of a block
|
||||
*(u8 *)MemToShadow(c) = static_cast<u8>(old_end - c);
|
||||
}
|
||||
// else: we cannot poison prefix of a block with elements or there is
|
||||
// nothing to poison.
|
||||
} else { // we are poisoning as beginning moved further in memory
|
||||
// Handle non-intersecting new/old containers separately have simpler
|
||||
// intersecting case.
|
||||
if (old_beg == old_end || new_beg == new_end || new_end <= old_beg ||
|
||||
old_end <= new_beg) {
|
||||
if (old_beg != old_end) {
|
||||
// Poisoning the old container.
|
||||
uptr a = RoundDownTo(old_beg, granularity);
|
||||
uptr c = RoundDownTo(new_beg, granularity);
|
||||
// State at the moment is:
|
||||
// [storage_beg, a] is poisoned and should remain like that.
|
||||
// [a, c] is not poisoned (interval may be empty if new_beg and
|
||||
// old_beg are in the same block) [c, container_end] is not
|
||||
// poisoned. If there are remaining elements in the container:
|
||||
// We have to poison [a, c], but because we do not poison prefixes, we
|
||||
// cannot poison memory after c (even that there are not elements of the
|
||||
// container). Up to granularity-1 unused bytes will not be poisoned.
|
||||
// Otherwise:
|
||||
// We have to poison the last byte as well.
|
||||
PoisonShadow(a, c - a, kAsanContiguousContainerOOBMagic);
|
||||
if (new_beg == old_end &&
|
||||
!AddrIsAlignedByGranularity(new_beg)) { // is empty && ends in the
|
||||
// middle of a block
|
||||
*(u8 *)MemToShadow(c) =
|
||||
static_cast<u8>(kAsanContiguousContainerOOBMagic);
|
||||
}
|
||||
uptr b = RoundUpTo(old_end, granularity);
|
||||
PoisonShadow(a, b - a, kAsanContiguousContainerOOBMagic);
|
||||
}
|
||||
|
||||
old_beg = new_beg;
|
||||
if (new_beg != new_end) {
|
||||
// Unpoisoning the new container.
|
||||
uptr a = RoundDownTo(new_beg, granularity);
|
||||
uptr b = RoundDownTo(new_end, granularity);
|
||||
PoisonShadow(a, b - a, 0);
|
||||
if (!AddrIsAlignedByGranularity(new_end))
|
||||
*(u8 *)MemToShadow(b) = static_cast<u8>(new_end - b);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (old_end != new_end) {
|
||||
if (old_end < new_end) { // We are unpoisoning memory
|
||||
uptr a = RoundDownTo(old_end, granularity);
|
||||
uptr c = RoundDownTo(new_end, granularity);
|
||||
// State at the moment is:
|
||||
// if container_beg < a : [container_beg, a] is correct and we will not be
|
||||
// changing it. else [a, container_beg] cannot be poisoned, so we do not
|
||||
// have to think about it. we have to makr as unpoisoned [a, c]. [c, end]
|
||||
// is correctly poisoned.
|
||||
PoisonShadow(a, c - a, 0);
|
||||
if (!AddrIsAlignedByGranularity(
|
||||
new_end)) // ends in the middle of a block
|
||||
*(u8 *)MemToShadow(c) = static_cast<u8>(new_end - c);
|
||||
} else { // We are poisoning memory
|
||||
// Intersection of old and new containers is not empty.
|
||||
CHECK_LT(new_beg, old_end);
|
||||
CHECK_GT(new_end, old_beg);
|
||||
|
||||
// There are two situations: we are poisoning or unpoisoning.
|
||||
// WARNING: at the moment we do not poison prefixes of blocks described by
|
||||
// one byte in shadow memory, so we have to unpoison prefixes of blocks with
|
||||
// content. Up to (granularity - 1) bytes not-in-use may not be poisoned.
|
||||
|
||||
if (new_beg < old_beg) {
|
||||
// We are unpoisoning.
|
||||
uptr a = RoundDownTo(new_beg, granularity);
|
||||
uptr c = RoundDownTo(old_beg, granularity);
|
||||
// State at the moment is:
|
||||
// [storage_beg, a] is poisoned and should remain like that.
|
||||
// [a, c] is poisoned as well (interval may be empty if new_beg
|
||||
// and old_beg are in the same block). If the container is not
|
||||
// empty, first element starts somewhere in [c, c+granularity]. Because we
|
||||
// do not poison prefixes, memory [c, container_end] is not poisoned and
|
||||
// we won't change it. If container is empty, we have to unpoison memory
|
||||
// for elements after c, so [c, container_end]
|
||||
PoisonShadow(a, c - a, 0);
|
||||
} else if (new_beg > old_beg) {
|
||||
// We are poisoning as beginning moved further in memory.
|
||||
uptr a = RoundDownTo(old_beg, granularity);
|
||||
uptr c = RoundDownTo(new_beg, granularity);
|
||||
// State at the moment is:
|
||||
// [storage_beg, a] is poisoned and should remain like that.
|
||||
// [a, c] is not poisoned (interval may be empty if new_beg and
|
||||
// old_beg are in the same block) [c, container_end] is not
|
||||
// poisoned. If there are remaining elements in the container:
|
||||
// We have to poison [a, c], but because we do not poison prefixes, we
|
||||
// cannot poison memory after c (even that there are not elements of the
|
||||
// container). Up to granularity-1 unused bytes will not be poisoned.
|
||||
// Otherwise:
|
||||
// We have to poison the last byte as well.
|
||||
PoisonShadow(a, c - a, kAsanContiguousContainerOOBMagic);
|
||||
}
|
||||
|
||||
if (new_end > old_end) {
|
||||
// We are unpoisoning memory.
|
||||
uptr a = RoundDownTo(old_end, granularity);
|
||||
uptr c = RoundDownTo(new_end, granularity);
|
||||
// State at the moment is:
|
||||
// if container_beg < a : [container_beg, a] is correct and we will not be
|
||||
// changing it. else [a, container_beg] cannot be poisoned, so we do not
|
||||
// have to think about it. we have to makr as unpoisoned [a, c]. [c, end]
|
||||
// is correctly poisoned.
|
||||
PoisonShadow(a, c - a, 0);
|
||||
if (!AddrIsAlignedByGranularity(new_end)) // ends in the middle of a block
|
||||
*(u8 *)MemToShadow(c) = static_cast<u8>(new_end - c);
|
||||
} else if (new_end < old_end) {
|
||||
// We are poisoning memory.
|
||||
// State at the moment is:
|
||||
// [storage_beg, a] is correctly annotated
|
||||
// if container is empty after the removal, then a < container_beg and we
|
||||
// will have to poison memory which is adressable only because we are not
|
||||
// poisoning prefixes.
|
||||
uptr a2 = RoundUpTo(new_end, granularity);
|
||||
uptr c2 = RoundUpTo(old_end, granularity);
|
||||
PoisonShadow(a2, c2 - a2, kAsanContiguousContainerOOBMagic);
|
||||
if (!AddrIsAlignedByGranularity(new_end)) {
|
||||
// Starts in the middle of the block
|
||||
uptr a = RoundDownTo(new_end, granularity);
|
||||
// State at the moment is:
|
||||
// [storage_beg, a] is correctly annotated
|
||||
// if container is empty after the removal, then a < container_beg and we
|
||||
// will have to poison memory which is adressable only because we are not
|
||||
// poisoning prefixes.
|
||||
uptr a2 = RoundUpTo(new_end, granularity);
|
||||
uptr c2 = RoundUpTo(old_end, granularity);
|
||||
PoisonShadow(a2, c2 - a2, kAsanContiguousContainerOOBMagic);
|
||||
if (!AddrIsAlignedByGranularity(
|
||||
new_end)) { // Starts in the middle of the block
|
||||
if (new_end == old_beg) // empty
|
||||
*(u8 *)MemToShadow(a) = kAsanContiguousContainerOOBMagic;
|
||||
else // not empty
|
||||
*(u8 *)MemToShadow(a) = static_cast<u8>(new_end - a);
|
||||
}
|
||||
*(u8 *)MemToShadow(a) = static_cast<u8>(new_end - a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue