Avoid a crash in source_cache::extract_lines
authorTom Tromey <tromey@adacore.com>
Fri, 8 Mar 2019 20:59:27 +0000 (13:59 -0700)
committerTom Tromey <tromey@adacore.com>
Thu, 14 Mar 2019 11:47:11 +0000 (05:47 -0600)
If the first requested line is larger than the number of lines in the
source buffer, source_cache::extract_lines could crash, because it
would try to pass string::npos" to string::substr.

This patch avoids the crash by checking for this case.

This version of the patch changes get_source_lines to return
std::string.

gdb/ChangeLog
2019-03-14  Tom Tromey  <tromey@adacore.com>

* source-cache.h (class source_cache) <get_source_lines>: Return
std::string.
* source-cache.c (source_cache::extract_lines): Handle case where
first_pos==npos.  Return std::string.
(source_cache::get_source_lines): Update.

gdb/ChangeLog
gdb/source-cache.c
gdb/source-cache.h

index 787949c5d93fa07db176554f28f2c5c96dc37316..50cbd2ed70e4080cb38bbc958d81aaa78e4bb3c7 100644 (file)
@@ -1,3 +1,11 @@
+2019-03-14  Tom Tromey  <tromey@adacore.com>
+
+       * source-cache.h (class source_cache) <get_source_lines>: Return
+       std::string.
+       * source-cache.c (source_cache::extract_lines): Handle case where
+       first_pos==npos.  Return std::string.
+       (source_cache::get_source_lines): Update.
+
 2019-03-14  Tom Tromey  <tromey@adacore.com>
 
        * NEWS: Add item for "style sources" commands.
index 3b15b3f28895dcd86632ee59fa66fd0fd4efd8a5..1ed2601c61459a96e1500abf4302bb07437e49a0 100644 (file)
@@ -84,9 +84,9 @@ source_cache::get_plain_source_lines (struct symtab *s, int first_line,
 
 /* See source-cache.h.  */
 
-bool
+std::string
 source_cache::extract_lines (const struct source_text &text, int first_line,
-                            int last_line, std::string *lines)
+                            int last_line)
 {
   int lineno = 1;
   std::string::size_type pos = 0;
@@ -102,16 +102,17 @@ source_cache::extract_lines (const struct source_text &text, int first_line,
       pos = new_pos;
       if (lineno == last_line || pos == std::string::npos)
        {
+         if (first_pos == std::string::npos)
+           return {};
          if (pos == std::string::npos)
            pos = text.contents.size ();
-         *lines = text.contents.substr (first_pos, pos - first_pos);
-         return true;
+         return text.contents.substr (first_pos, pos - first_pos);
        }
       ++lineno;
       ++pos;
     }
 
-  return false;
+  return {};
 }
 
 #ifdef HAVE_SOURCE_HIGHLIGHT
@@ -187,7 +188,10 @@ source_cache::get_source_lines (struct symtab *s, int first_line,
       for (const auto &item : m_source_map)
        {
          if (item.fullname == fullname)
-           return extract_lines (item, first_line, last_line, lines);
+           {
+             *lines = extract_lines (item, first_line, last_line);
+             return true;
+           }
        }
 
       const char *lang_name = get_language_name (SYMTAB_LANGUAGE (s));
@@ -208,8 +212,9 @@ source_cache::get_source_lines (struct symtab *s, int first_line,
              if (m_source_map.size () > MAX_ENTRIES)
                m_source_map.erase (m_source_map.begin ());
 
-             return extract_lines (m_source_map.back (), first_line,
-                                   last_line, lines);
+             *lines = extract_lines (m_source_map.back (), first_line,
+                                     last_line);
+             return true;
            }
        }
     }
index dd23266e2530158b61ee263446cadfebb3fc2c61..e2e25a170fd2b30fb9d1b048c3791094de52a1db 100644 (file)
@@ -65,9 +65,10 @@ private:
                               int last_line, std::string *lines_out);
   /* A helper function for get_plain_source_lines that extracts the
      desired source lines from TEXT, putting them into LINES_OUT.  The
-     arguments and return value are as for get_source_lines.  */
-  bool extract_lines (const struct source_text &text, int first_line,
-                     int last_line, std::string *lines_out);
+     arguments are as for get_source_lines.  The return value is the
+     desired lines.  */
+  std::string extract_lines (const struct source_text &text, int first_line,
+                            int last_line);
 
   /* The contents of the cache.  */
   std::vector<source_text> m_source_map;