gdb: fix nullptr dereference in block::ranges()
authorAndrew Burgess <aburgess@redhat.com>
Thu, 28 Apr 2022 10:37:51 +0000 (11:37 +0100)
committerAndrew Burgess <aburgess@redhat.com>
Thu, 28 Apr 2022 14:09:50 +0000 (15:09 +0100)
This commit:

  commit f5cb8afdd297dd68273d98a10fbfd350dff918d8
  Date:   Sun Feb 6 22:27:53 2022 -0500

      gdb: remove BLOCK_RANGES macro

introduces a potential nullptr dereference in block::ranges, this is
breaking most tests, e.g. gdb.base/break.exp is failing for me.

In the above patch BLOCK_CONTIGUOUS_P is changed from this:

  #define BLOCK_CONTIGUOUS_P(bl)  (BLOCK_RANGES (bl) == nullptr \
                                   || BLOCK_NRANGES (bl) <= 1)

to this:

  #define BLOCK_CONTIGUOUS_P(bl)  ((bl)->ranges ().size () == 0 \
                                   || (bl)->ranges ().size () == 1)

So, before the commit we checked for the block ranges being nullptr,
but afterwards we just call block::ranges() in all cases.

The problem is that block::ranges() looks like this:

  /* Return a view on this block's ranges.  */
  gdb::array_view<blockrange> ranges ()
  { return gdb::make_array_view (m_ranges->range, m_ranges->nranges); }

where m_ranges is:

  struct blockranges *m_ranges;

And so, we see that the nullptr check has been lost, and we might end
up dereferencing a nullptr.

My proposed fix is to move the nullptr check into block::ranges, and
return an explicit empty array_view if m_ranges is nullptr.

After this, everything seems fine again.

gdb/block.h

index b9f4e974c040a7993673268df13b89cc7213865e..038ce7bd2f3258b42a96e9379bdf788410d0468c 100644 (file)
@@ -157,11 +157,21 @@ struct block
 
   /* Return a view on this block's ranges.  */
   gdb::array_view<blockrange> ranges ()
-  { return gdb::make_array_view (m_ranges->range, m_ranges->nranges); }
+  {
+    if (m_ranges == nullptr)
+      return {};
+    else
+      return gdb::make_array_view (m_ranges->range, m_ranges->nranges);
+  }
 
   /* Const version of the above.  */
   gdb::array_view<const blockrange> ranges () const
-  { return gdb::make_array_view (m_ranges->range, m_ranges->nranges); }
+  {
+    if (m_ranges == nullptr)
+      return {};
+    else
+      return gdb::make_array_view (m_ranges->range, m_ranges->nranges);
+  }
 
   /* Set this block's ranges array.  */
   void set_ranges (blockranges *ranges)