(root)/
gcc-13.2.0/
libsanitizer/
asan/
asan_descriptions.h
       1  //===-- asan_descriptions.h -------------------------------------*- C++ -*-===//
       2  //
       3  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
       4  // See https://llvm.org/LICENSE.txt for license information.
       5  // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
       6  //
       7  //===----------------------------------------------------------------------===//
       8  //
       9  // This file is a part of AddressSanitizer, an address sanity checker.
      10  //
      11  // ASan-private header for asan_descriptions.cpp.
      12  // TODO(filcab): Most struct definitions should move to the interface headers.
      13  //===----------------------------------------------------------------------===//
      14  #ifndef ASAN_DESCRIPTIONS_H
      15  #define ASAN_DESCRIPTIONS_H
      16  
      17  #include "asan_allocator.h"
      18  #include "asan_thread.h"
      19  #include "sanitizer_common/sanitizer_common.h"
      20  #include "sanitizer_common/sanitizer_report_decorator.h"
      21  
      22  namespace __asan {
      23  
      24  void DescribeThread(AsanThreadContext *context);
      25  static inline void DescribeThread(AsanThread *t) {
      26    if (t) DescribeThread(t->context());
      27  }
      28  
      29  class AsanThreadIdAndName {
      30   public:
      31    explicit AsanThreadIdAndName(AsanThreadContext *t);
      32    explicit AsanThreadIdAndName(u32 tid);
      33  
      34    // Contains "T%tid (%name)" or "T%tid" if the name is empty.
      35    const char *c_str() const { return &name[0]; }
      36  
      37   private:
      38    void Init(u32 tid, const char *tname);
      39  
      40    char name[128];
      41  };
      42  
      43  class Decorator : public __sanitizer::SanitizerCommonDecorator {
      44   public:
      45    Decorator() : SanitizerCommonDecorator() {}
      46    const char *Access() { return Blue(); }
      47    const char *Location() { return Green(); }
      48    const char *Allocation() { return Magenta(); }
      49  
      50    const char *ShadowByte(u8 byte) {
      51      switch (byte) {
      52        case kAsanHeapLeftRedzoneMagic:
      53        case kAsanArrayCookieMagic:
      54          return Red();
      55        case kAsanHeapFreeMagic:
      56          return Magenta();
      57        case kAsanStackLeftRedzoneMagic:
      58        case kAsanStackMidRedzoneMagic:
      59        case kAsanStackRightRedzoneMagic:
      60          return Red();
      61        case kAsanStackAfterReturnMagic:
      62          return Magenta();
      63        case kAsanInitializationOrderMagic:
      64          return Cyan();
      65        case kAsanUserPoisonedMemoryMagic:
      66        case kAsanContiguousContainerOOBMagic:
      67        case kAsanAllocaLeftMagic:
      68        case kAsanAllocaRightMagic:
      69          return Blue();
      70        case kAsanStackUseAfterScopeMagic:
      71          return Magenta();
      72        case kAsanGlobalRedzoneMagic:
      73          return Red();
      74        case kAsanInternalHeapMagic:
      75          return Yellow();
      76        case kAsanIntraObjectRedzone:
      77          return Yellow();
      78        default:
      79          return Default();
      80      }
      81    }
      82  };
      83  
      84  enum ShadowKind : u8 {
      85    kShadowKindLow,
      86    kShadowKindGap,
      87    kShadowKindHigh,
      88  };
      89  static const char *const ShadowNames[] = {"low shadow", "shadow gap",
      90                                            "high shadow"};
      91  
      92  struct ShadowAddressDescription {
      93    uptr addr;
      94    ShadowKind kind;
      95    u8 shadow_byte;
      96  
      97    void Print() const;
      98  };
      99  
     100  bool GetShadowAddressInformation(uptr addr, ShadowAddressDescription *descr);
     101  bool DescribeAddressIfShadow(uptr addr);
     102  
     103  enum AccessType {
     104    kAccessTypeLeft,
     105    kAccessTypeRight,
     106    kAccessTypeInside,
     107    kAccessTypeUnknown,  // This means we have an AddressSanitizer bug!
     108  };
     109  
     110  struct ChunkAccess {
     111    uptr bad_addr;
     112    sptr offset;
     113    uptr chunk_begin;
     114    uptr chunk_size;
     115    u32 user_requested_alignment : 12;
     116    u32 access_type : 2;
     117    u32 alloc_type : 2;
     118  };
     119  
     120  struct HeapAddressDescription {
     121    uptr addr;
     122    uptr alloc_tid;
     123    uptr free_tid;
     124    u32 alloc_stack_id;
     125    u32 free_stack_id;
     126    ChunkAccess chunk_access;
     127  
     128    void Print() const;
     129  };
     130  
     131  bool GetHeapAddressInformation(uptr addr, uptr access_size,
     132                                 HeapAddressDescription *descr);
     133  bool DescribeAddressIfHeap(uptr addr, uptr access_size = 1);
     134  
     135  struct StackAddressDescription {
     136    uptr addr;
     137    uptr tid;
     138    uptr offset;
     139    uptr frame_pc;
     140    uptr access_size;
     141    const char *frame_descr;
     142  
     143    void Print() const;
     144  };
     145  
     146  bool GetStackAddressInformation(uptr addr, uptr access_size,
     147                                  StackAddressDescription *descr);
     148  
     149  struct WildAddressDescription {
     150    uptr addr;
     151    uptr access_size;
     152  
     153    void Print() const;
     154  };
     155  
     156  struct GlobalAddressDescription {
     157    uptr addr;
     158    // Assume address is close to at most four globals.
     159    static const int kMaxGlobals = 4;
     160    __asan_global globals[kMaxGlobals];
     161    u32 reg_sites[kMaxGlobals];
     162    uptr access_size;
     163    u8 size;
     164  
     165    void Print(const char *bug_type = "") const;
     166  
     167    // Returns true when this descriptions points inside the same global variable
     168    // as other. Descriptions can have different address within the variable
     169    bool PointsInsideTheSameVariable(const GlobalAddressDescription &other) const;
     170  };
     171  
     172  bool GetGlobalAddressInformation(uptr addr, uptr access_size,
     173                                   GlobalAddressDescription *descr);
     174  bool DescribeAddressIfGlobal(uptr addr, uptr access_size, const char *bug_type);
     175  
     176  // General function to describe an address. Will try to describe the address as
     177  // a shadow, global (variable), stack, or heap address.
     178  // bug_type is optional and is used for checking if we're reporting an
     179  // initialization-order-fiasco
     180  // The proper access_size should be passed for stack, global, and heap
     181  // addresses. Defaults to 1.
     182  // Each of the *AddressDescription functions has its own Print() member, which
     183  // may take access_size and bug_type parameters if needed.
     184  void PrintAddressDescription(uptr addr, uptr access_size = 1,
     185                               const char *bug_type = "");
     186  
     187  enum AddressKind {
     188    kAddressKindWild,
     189    kAddressKindShadow,
     190    kAddressKindHeap,
     191    kAddressKindStack,
     192    kAddressKindGlobal,
     193  };
     194  
     195  class AddressDescription {
     196    struct AddressDescriptionData {
     197      AddressKind kind;
     198      union {
     199        ShadowAddressDescription shadow;
     200        HeapAddressDescription heap;
     201        StackAddressDescription stack;
     202        GlobalAddressDescription global;
     203        WildAddressDescription wild;
     204      };
     205    };
     206  
     207    AddressDescriptionData data;
     208  
     209   public:
     210    AddressDescription() = default;
     211    // shouldLockThreadRegistry allows us to skip locking if we're sure we already
     212    // have done it.
     213    explicit AddressDescription(uptr addr, bool shouldLockThreadRegistry = true)
     214        : AddressDescription(addr, 1, shouldLockThreadRegistry) {}
     215    AddressDescription(uptr addr, uptr access_size,
     216                       bool shouldLockThreadRegistry = true);
     217  
     218    uptr Address() const {
     219      switch (data.kind) {
     220        case kAddressKindWild:
     221          return data.wild.addr;
     222        case kAddressKindShadow:
     223          return data.shadow.addr;
     224        case kAddressKindHeap:
     225          return data.heap.addr;
     226        case kAddressKindStack:
     227          return data.stack.addr;
     228        case kAddressKindGlobal:
     229          return data.global.addr;
     230      }
     231      UNREACHABLE("AddressInformation kind is invalid");
     232    }
     233    void Print(const char *bug_descr = nullptr) const {
     234      switch (data.kind) {
     235        case kAddressKindWild:
     236          data.wild.Print();
     237          return;
     238        case kAddressKindShadow:
     239          return data.shadow.Print();
     240        case kAddressKindHeap:
     241          return data.heap.Print();
     242        case kAddressKindStack:
     243          return data.stack.Print();
     244        case kAddressKindGlobal:
     245          // initialization-order-fiasco has a special Print()
     246          return data.global.Print(bug_descr);
     247      }
     248      UNREACHABLE("AddressInformation kind is invalid");
     249    }
     250  
     251    void StoreTo(AddressDescriptionData *dst) const { *dst = data; }
     252  
     253    const ShadowAddressDescription *AsShadow() const {
     254      return data.kind == kAddressKindShadow ? &data.shadow : nullptr;
     255    }
     256    const HeapAddressDescription *AsHeap() const {
     257      return data.kind == kAddressKindHeap ? &data.heap : nullptr;
     258    }
     259    const StackAddressDescription *AsStack() const {
     260      return data.kind == kAddressKindStack ? &data.stack : nullptr;
     261    }
     262    const GlobalAddressDescription *AsGlobal() const {
     263      return data.kind == kAddressKindGlobal ? &data.global : nullptr;
     264    }
     265  };
     266  
     267  }  // namespace __asan
     268  
     269  #endif  // ASAN_DESCRIPTIONS_H