[ASan] Due to data races, ASan malloc stats are inaccurate, which may cause certain ASan interface functions returning negative values (casted to unsigned). Return a reasonable value if such a case is detected.

git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@166548 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/asan/asan_thread_registry.cc b/lib/asan/asan_thread_registry.cc
index 877d32b..4bf63cd 100644
--- a/lib/asan/asan_thread_registry.cc
+++ b/lib/asan/asan_thread_registry.cc
@@ -113,7 +113,11 @@
 uptr AsanThreadRegistry::GetCurrentAllocatedBytes() {
   ScopedLock lock(&mu_);
   UpdateAccumulatedStatsUnlocked();
-  return accumulated_stats_.malloced - accumulated_stats_.freed;
+  uptr malloced = accumulated_stats_.malloced;
+  uptr freed = accumulated_stats_.freed;
+  // Return sane value if malloced < freed due to racy
+  // way we update accumulated stats.
+  return (malloced > freed) ? malloced - freed : 1;
 }
 
 uptr AsanThreadRegistry::GetHeapSize() {
@@ -125,11 +129,14 @@
 uptr AsanThreadRegistry::GetFreeBytes() {
   ScopedLock lock(&mu_);
   UpdateAccumulatedStatsUnlocked();
-  return accumulated_stats_.mmaped
-         - accumulated_stats_.malloced
-         - accumulated_stats_.malloced_redzones
-         + accumulated_stats_.really_freed
-         + accumulated_stats_.really_freed_redzones;
+  uptr total_free = accumulated_stats_.mmaped
+                  + accumulated_stats_.really_freed
+                  + accumulated_stats_.really_freed_redzones;
+  uptr total_used = accumulated_stats_.malloced
+                  + accumulated_stats_.malloced_redzones;
+  // Return sane value if total_free < total_used due to racy
+  // way we update accumulated stats.
+  return (total_free > total_used) ? total_free - total_used : 1;
 }
 
 // Return several stats counters with a single call to