From 67aa1f3c2881e607081d9e1b57be3e7544c2c45c Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Thu, 10 Jan 2019 17:52:39 +0000 Subject: Fix tracepoint.c:parse_tracepoint_definition leak (and one more) Coverity points out that gdb/tracepoint.c:parse_tracepoint_definition can leak 'cond' in this line: cond = (char *) xmalloc (2 * xlen + 1); That can leak because we're in a loop and 'cond' may have already been xmalloc'ed into in a previous iteration. That won't normally happen, because we don't expect to see a tracepoint definition with multiple conditions listed, but, it doesn't hurt to be pedantically correct, in case some stub manages to send something odd back to GDB. At first I thought I'd just replace the xmalloc call with: cond = (char *) xrealloc (cond, 2 * xlen + 1); and be done with it. However, my pedantic self realizes that warning() can throw as well (due to pagination + Ctrl-C), so I fixed it using gdb::unique_xmalloc_ptr instead. While doing this, I noticed that these vectors in struct uploaded_tp: std::vector actions; std::vector step_actions; hold heap-allocated strings, but nothing is freeing the strings, AFAICS. So I ended up switching all the heap-allocated strings in uploaded_tp to unique pointers. This patch is the result of that. I also wrote an alternative, but similar patch that uses std::string throughout instead of gdb::unique_xmalloc_ptr, but in the end reverted it because the code didn't look that much better, and I kind of dislike replacing pointers with fat std::string's (3 or 4 times the size of a pointer) in structures. gdb/ChangeLog: 2019-01-10 Pedro Alves * breakpoint.c (read_uploaded_action) (create_tracepoint_from_upload): Adjust to use gdb::unique_xmalloc_ptr. * ctf.c (ctf_write_uploaded_tp): (SET_ARRAY_FIELD): Use emplace_back. (SET_STRING_FIELD): Adjust to use gdb::unique_xmalloc_ptr. * tracefile-tfile.c (tfile_write_uploaded_tp): * tracepoint.c (parse_tracepoint_definition): Adjust to use gdb::unique_xmalloc_ptr. * tracepoint.h (struct uploaded_tp) : Replace char pointers with gdb::unique_xmalloc_ptr. --- gdb/tracepoint.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'gdb/tracepoint.c') diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index c74e750..bed35bd 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -3083,7 +3083,8 @@ find_matching_tracepoint_location (struct uploaded_tp *utp) if (b->type == utp->type && t->step_count == utp->step && t->pass_count == utp->pass - && cond_string_is_same (t->cond_string, utp->cond_string) + && cond_string_is_same (t->cond_string, + utp->cond_string.get ()) /* FIXME also test actions. */ ) { @@ -3462,7 +3463,7 @@ parse_tracepoint_definition (const char *line, struct uploaded_tp **utpp) int enabled, end; enum bptype type; const char *srctype; - char *cond, *buf; + char *buf; struct uploaded_tp *utp = NULL; p = line; @@ -3475,13 +3476,14 @@ parse_tracepoint_definition (const char *line, struct uploaded_tp **utpp) p++; /* skip a colon */ if (piece == 'T') { + gdb::unique_xmalloc_ptr cond; + enabled = (*p++ == 'E'); p++; /* skip a colon */ p = unpack_varlen_hex (p, &step); p++; /* skip a colon */ p = unpack_varlen_hex (p, &pass); type = bp_tracepoint; - cond = NULL; /* Thumb through optional fields. */ while (*p == ':') { @@ -3502,8 +3504,8 @@ parse_tracepoint_definition (const char *line, struct uploaded_tp **utpp) p++; p = unpack_varlen_hex (p, &xlen); p++; /* skip a comma */ - cond = (char *) xmalloc (2 * xlen + 1); - strncpy (cond, p, 2 * xlen); + cond.reset ((char *) xmalloc (2 * xlen + 1)); + strncpy (&cond[0], p, 2 * xlen); cond[2 * xlen] = '\0'; p += 2 * xlen; } @@ -3516,17 +3518,17 @@ parse_tracepoint_definition (const char *line, struct uploaded_tp **utpp) utp->enabled = enabled; utp->step = step; utp->pass = pass; - utp->cond = cond; + utp->cond = std::move (cond); } else if (piece == 'A') { utp = get_uploaded_tp (num, addr, utpp); - utp->actions.push_back (xstrdup (p)); + utp->actions.emplace_back (xstrdup (p)); } else if (piece == 'S') { utp = get_uploaded_tp (num, addr, utpp); - utp->step_actions.push_back (xstrdup (p)); + utp->step_actions.emplace_back (xstrdup (p)); } else if (piece == 'Z') { @@ -3546,11 +3548,11 @@ parse_tracepoint_definition (const char *line, struct uploaded_tp **utpp) buf[end] = '\0'; if (startswith (srctype, "at:")) - utp->at_string = xstrdup (buf); + utp->at_string.reset (xstrdup (buf)); else if (startswith (srctype, "cond:")) - utp->cond_string = xstrdup (buf); + utp->cond_string.reset (xstrdup (buf)); else if (startswith (srctype, "cmd:")) - utp->cmd_strings.push_back (xstrdup (buf)); + utp->cmd_strings.emplace_back (xstrdup (buf)); } else if (piece == 'V') { -- cgit v1.1