From ef21dd3bcffd350f0bf27386f1eafe8095d8feec Mon Sep 17 00:00:00 2001 From: Nick Alcock Date: Fri, 20 Nov 2020 13:34:04 +0000 Subject: [PATCH] libctf: do not crash when CTF symbol or variable linking fails When linking fails, we delete all the generated outputs, but we fail to remove them from the ctf_link_outputs hash we stuck them in before doing symbol and variable section linking (which we had to do because that's where ctf_create_per_cu, used by both, looks for them). This leaves stale pointers to freed memory behind, and crashes soon follow. Fix obvious. libctf/ChangeLog 2020-11-20 Nick Alcock * ctf-link.c (ctf_link_deduplicating): Clean up the ctf_link_outputs hash on error. --- libctf/ChangeLog | 5 +++++ libctf/ctf-link.c | 16 ++++++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/libctf/ChangeLog b/libctf/ChangeLog index 0a8da127616..7fdb3558f3d 100644 --- a/libctf/ChangeLog +++ b/libctf/ChangeLog @@ -1,3 +1,8 @@ +2020-11-20 Nick Alcock + + * ctf-link.c (ctf_link_deduplicating): Clean up the ctf_link_outputs + hash on error. + 2020-11-20 Nick Alcock * ctf-create.c (ctf_dtd_insert): Set ENOMEM on the dict if out of memory. diff --git a/libctf/ctf-link.c b/libctf/ctf-link.c index 4b86ca98095..cdf3db3a7c3 100644 --- a/libctf/ctf-link.c +++ b/libctf/ctf-link.c @@ -1616,18 +1616,14 @@ ctf_link_deduplicating (ctf_dict_t *fp) { ctf_err_warn (fp, 0, 0, _("deduplicating link variable emission failed for " "%s"), ctf_link_input_name (fp)); - for (i = 1; i < noutputs; i++) - ctf_dict_close (outputs[i]); - goto err; + goto err_clean_outputs; } if (ctf_link_deduplicating_syms (fp, inputs, ninputs, 0) < 0) { ctf_err_warn (fp, 0, 0, _("deduplicating link symbol emission failed for " "%s"), ctf_link_input_name (fp)); - for (i = 1; i < noutputs; i++) - ctf_dict_close (outputs[i]); - goto err; + goto err_clean_outputs; } /* Now close all the inputs, including per-CU intermediates. */ @@ -1647,6 +1643,14 @@ ctf_link_deduplicating (ctf_dict_t *fp) free (parents); free (outputs); return; + + err_clean_outputs: + for (i = 1; i < noutputs; i++) + { + ctf_dynhash_remove (fp->ctf_link_outputs, ctf_cuname (outputs[i])); + ctf_dict_close (outputs[i]); + } + goto err; } /* Merge types and variable sections in all files added to the link -- 2.30.2