Fix leak in linespec parser
authorSimon Marchi <simon.marchi@ericsson.com>
Fri, 30 Nov 2018 21:49:35 +0000 (16:49 -0500)
committerSimon Marchi <simon.marchi@ericsson.com>
Fri, 30 Nov 2018 21:51:28 +0000 (16:51 -0500)
Valgrind reports this leak:

  ==798== VALGRIND_GDB_ERROR_BEGIN
  ==798== 32 (24 direct, 8 indirect) bytes in 1 blocks are definitely lost in loss record 447 of 3,143
  ==798==    at 0x4C2C48C: operator new(unsigned long) (vg_replace_malloc.c:334)
  ==798==    by 0x51D401: linespec_parser_new(ls_parser*, int, language_defn const*, program_space*, symtab*, int, linespec_result*) (linespec.c:2756)
  ==798==    by 0x524BF7: decode_line_full(event_location const*, int, program_space*, symtab*, int, linespec_result*, char const*, char const*) (linespec.c:3271)
  ==798==    by 0x3E8893: parse_breakpoint_sals(event_location const*, linespec_result*) (breakpoint.c:9067)
  ==798==    by 0x3E4E7F: create_breakpoint(gdbarch*, event_location const*, char const*, int, char const*, int, int, bptype, int, auto_boolean, breakpoint_ops const*, int, int, int, unsigned int) (breakpoint.c:9248)
  ==798==    by 0x3E55F5: break_command_1(char const*, int, int) (breakpoint.c:9434)
  ==798==    by 0x40BA68: cmd_func(cmd_list_element*, char const*, int) (cli-decode.c:1888)
  ==798==    by 0x665300: execute_command(char const*, int) (top.c:630)
  ...

linespec_parser_new allocates a std::vector<symtab *> at line 2756, and stores
the pointer to this vector in PARSER_RESULT (parser)->file_symtabs.  At 3
different places in linespec.c, another std::vector is assigned to a
linespec->file_symtabs, without first deleting the current value.

The leak is fixed by assigning the vector itself instead of the pointer.
Everything should be moved, so there is no significant data copy
involved.

Tested on debian/amd64, + a bunch of tests re-run under valgrind
(including the test that throws an error).

gdb/ChangeLog:

* linespec.c (symtab_vector_up): Remove.
(symtabs_from_filename): Change return type to std::vector.
(collect_symtabs_from_filename): Likewise.
(create_sals_line_offset): Assign return value of
collect_symtabs_from_filename to *ls->file_symtabs.
(convert_explicit_location_to_linespec): Remove call to release.
(parse_linespec): Likewise.
(symtab_collector) <symtab_collector>: Remove initialization of
m_symtabs.
<release_symtabs>: Change return type to std::vector<symtab *>.
<operator ()>: Adjust.

gdb/ChangeLog
gdb/linespec.c

index 348eb65..778eebc 100644 (file)
@@ -1,3 +1,18 @@
+2018-11-30  Philippe Waroquiers  <philippe.waroquiers@skynet.be>
+            Simon Marchi  <simon.marchi@ericsson.com>
+
+       * linespec.c (symtab_vector_up): Remove.
+       (symtabs_from_filename): Change return type to std::vector.
+       (collect_symtabs_from_filename): Likewise.
+       (create_sals_line_offset): Assign return value of
+       collect_symtabs_from_filename to *ls->file_symtabs.
+       (convert_explicit_location_to_linespec): Remove call to release.
+       (parse_linespec): Likewise.
+       (symtab_collector) <symtab_collector>: Remove initialization of
+       m_symtabs.
+       <release_symtabs>: Change return type to std::vector<symtab *>.
+       <operator ()>: Adjust.
+
 2018-11-30  John Baldwin  <jhb@FreeBSD.org>
 
        * fbsd-nat.c [__FreeBSD_version >= 700009] (USE_SIGINFO): Macro
index 00f59f9..e534cf2 100644 (file)
@@ -77,10 +77,6 @@ enum class linespec_complete_what
   KEYWORD,
 };
 
-/* Typedef for unique_ptrs of vectors of symtabs.  */
-
-typedef std::unique_ptr<std::vector<symtab *>> symtab_vector_up;
-
 /* An address entry is used to ensure that any given location is only
    added to the result a single time.  It holds an address and the
    program space from which the address came.  */
@@ -357,7 +353,7 @@ static std::vector<symtab_and_line> decode_objc (struct linespec_state *self,
                                                 linespec_p ls,
                                                 const char *arg);
 
-static symtab_vector_up symtabs_from_filename
+static std::vector<symtab *> symtabs_from_filename
   (const char *, struct program_space *pspace);
 
 static std::vector<block_symbol> *find_label_symbols
@@ -389,7 +385,7 @@ static void add_all_symbol_names_from_pspace
     (struct collect_info *info, struct program_space *pspace,
      const std::vector<const char *> &names, enum search_domain search_domain);
 
-static symtab_vector_up
+static std::vector<symtab *>
   collect_symtabs_from_filename (const char *file,
                                 struct program_space *pspace);
 
@@ -2117,9 +2113,8 @@ create_sals_line_offset (struct linespec_state *self,
       set_default_source_symtab_and_line ();
       initialize_defaults (&self->default_symtab, &self->default_line);
       fullname = symtab_to_fullname (self->default_symtab);
-      symtab_vector_up r =
-       collect_symtabs_from_filename (fullname, self->search_pspace);
-      ls->file_symtabs = r.release ();
+      *ls->file_symtabs
+       = collect_symtabs_from_filename (fullname, self->search_pspace);
       use_default = 1;
     }
 
@@ -2401,9 +2396,8 @@ convert_explicit_location_to_linespec (struct linespec_state *self,
     {
       TRY
        {
-         result->file_symtabs
-           = symtabs_from_filename (source_filename,
-                                    self->search_pspace).release ();
+         *result->file_symtabs
+           = symtabs_from_filename (source_filename, self->search_pspace);
        }
       CATCH (except, RETURN_MASK_ERROR)
        {
@@ -2627,10 +2621,9 @@ parse_linespec (linespec_parser *parser, const char *arg,
       /* Check if the input is a filename.  */
       TRY
        {
-         symtab_vector_up r
+         *PARSER_RESULT (parser)->file_symtabs
            = symtabs_from_filename (user_filename.get (),
                                     PARSER_STATE (parser)->search_pspace);
-         PARSER_RESULT (parser)->file_symtabs = r.release ();
        }
       CATCH (ex, RETURN_MASK_ERROR)
        {
@@ -3790,7 +3783,6 @@ class symtab_collector
 {
 public:
   symtab_collector ()
-    : m_symtabs (new std::vector<symtab *> ())
   {
     m_symtab_table = htab_create (1, htab_hash_pointer, htab_eq_pointer,
                                  NULL);
@@ -3805,15 +3797,15 @@ public:
   /* Callable as a symbol_found_callback_ftype callback.  */
   bool operator () (symtab *sym);
 
-  /* Releases ownership of the collected symtabs and returns them.  */
-  symtab_vector_up release_symtabs ()
+  /* Return an rvalue reference to the collected symtabs.  */
+  std::vector<symtab *> &&release_symtabs ()
   {
     return std::move (m_symtabs);
   }
 
 private:
   /* The result vector of symtabs.  */
-  symtab_vector_up m_symtabs;
+  std::vector<symtab *> m_symtabs;
 
   /* This is used to ensure the symtabs are unique.  */
   htab_t m_symtab_table;
@@ -3828,7 +3820,7 @@ symtab_collector::operator () (struct symtab *symtab)
   if (!*slot)
     {
       *slot = symtab;
-      m_symtabs->push_back (symtab);
+      m_symtabs.push_back (symtab);
     }
 
   return false;
@@ -3840,7 +3832,7 @@ symtab_collector::operator () (struct symtab *symtab)
    SEARCH_PSPACE is not NULL, the search is restricted to just that
    program space.  */
 
-static symtab_vector_up
+static std::vector<symtab *>
 collect_symtabs_from_filename (const char *file,
                               struct program_space *search_pspace)
 {
@@ -3872,14 +3864,14 @@ collect_symtabs_from_filename (const char *file,
 /* Return all the symtabs associated to the FILENAME.  If SEARCH_PSPACE is
    not NULL, the search is restricted to just that program space.  */
 
-static symtab_vector_up
+static std::vector<symtab *>
 symtabs_from_filename (const char *filename,
                       struct program_space *search_pspace)
 {
-  symtab_vector_up result
+  std::vector<symtab *> result
     = collect_symtabs_from_filename (filename, search_pspace);
 
-  if (result->empty ())
+  if (result.empty ())
     {
       if (!have_full_symbols () && !have_partial_symbols ())
        throw_error (NOT_FOUND_ERROR,