GDB: Fix the overflow in addr/line_is_displayed()
authorShahab Vahedi <shahab@synopsys.com>
Mon, 6 Jan 2020 14:27:32 +0000 (15:27 +0100)
committerPedro Alves <palves@redhat.com>
Mon, 6 Jan 2020 19:47:20 +0000 (19:47 +0000)
In tui_disasm_window::addr_is_displayed(), there can be situations
where "content" is empty. For instance, it can happen when the
"content" was not filled in tui_disasm_window::set_contents(),
because tui_disassemble() threw an exception. Usually this exception
is the result of fetching invalid PC addresses like the ones beyond
the end of the program.

Having "content.size ()" zero leads to an overflow in this condition
check inside tui_disasm_window::addr_is_displayed():

  int i = 0;
  while (i < content.size () - threshold ...) {
    ... content[i] ...
  }

"threshold" is 2 and there are times that "content.size ()" is 0.
This results into an overflow and the loop is entered whereas it
should have been skipped. Finally, "content[i]" access leads to
a segmentation fault.

Same problem applies to tui_source_window::line_is_displayed().

The issue has been discussed at length in bug 25345:
  https://sourceware.org/bugzilla/show_bug.cgi?id=25345

This commit avoids the segmentation faults with an early check:

  if (content.size () < SCROLL_THRESHOLD)
    return false;

Moreover, those functions have been overhauled to a leaner code.

gdb/ChangeLog:
2020-01-06  Shahab Vahedi  <shahab@synopsys.com>

* tui/tui-disasm.c (tui_disasm_window::addr_is_displayed): Avoid
overflow by an early check of content vs threshold.
        * tui/tui-source.c (tui_source_window::line_is_displayed):
Likewise.

gdb/ChangeLog
gdb/tui/tui-disasm.c
gdb/tui/tui-source.c

index 69e426e0e6256d5b75859d35a39433f84a8f9b45..476712e6cba33a169c174809d08b2f07f5bd667f 100644 (file)
@@ -1,3 +1,10 @@
+2020-01-06  Shahab Vahedi  <shahab@synopsys.com>
+
+       * tui/tui-disasm.c (tui_disasm_window::addr_is_displayed): Avoid
+       overflow by an early check of content vs threshold.
+        * tui/tui-source.c (tui_source_window::line_is_displayed):
+       Likewise.
+
 2020-01-06  Eli Zaretskii  <eliz@gnu.org>
 
        * NEWS: Mention the recent fix of $_exitsignal on MS-Windows.
index ebd0ba317f5204c7ce80105f43c498a0197724a2..98c691f3387766610d17e7d8ce99c89d450e05c2 100644 (file)
@@ -348,19 +348,17 @@ tui_disasm_window::location_matches_p (struct bp_location *loc, int line_no)
 bool
 tui_disasm_window::addr_is_displayed (CORE_ADDR addr) const
 {
-  bool is_displayed = false;
-  int threshold = SCROLL_THRESHOLD;
+  if (content.size () < SCROLL_THRESHOLD)
+    return false;
 
-  int i = 0;
-  while (i < content.size () - threshold && !is_displayed)
+  for (size_t i = 0; i < content.size () - SCROLL_THRESHOLD; ++i)
     {
-      is_displayed
-       = (content[i].line_or_addr.loa == LOA_ADDRESS
-          && content[i].line_or_addr.u.addr == addr);
-      i++;
+      if (content[i].line_or_addr.loa == LOA_ADDRESS
+         && content[i].line_or_addr.u.addr == addr)
+       return true;
     }
 
-  return is_displayed;
+  return false;
 }
 
 void
index e028b724d23c5a18d1353d6f0023f3a5536545b7..1503cd4c63608f3db23965e36488280e5a4762da 100644 (file)
@@ -174,18 +174,17 @@ tui_source_window::location_matches_p (struct bp_location *loc, int line_no)
 bool
 tui_source_window::line_is_displayed (int line) const
 {
-  bool is_displayed = false;
-  int threshold = SCROLL_THRESHOLD;
-  int i = 0;
-  while (i < content.size () - threshold && !is_displayed)
+  if (content.size () < SCROLL_THRESHOLD)
+    return false;
+
+  for (size_t i = 0; i < content.size () - SCROLL_THRESHOLD; ++i)
     {
-      is_displayed
-       = (content[i].line_or_addr.loa == LOA_LINE
-          && content[i].line_or_addr.u.line_no == line);
-      i++;
+      if (content[i].line_or_addr.loa == LOA_LINE
+         && content[i].line_or_addr.u.line_no == line)
+       return true;
     }
 
-  return is_displayed;
+  return false;
 }
 
 void