]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
fixup! libctf: move string deduplication into ctf-archive
authorNick Alcock <nick.alcock@oracle.com>
Wed, 19 Nov 2025 12:32:23 +0000 (12:32 +0000)
committerNick Alcock <nick.alcock@oracle.com>
Tue, 9 Dec 2025 13:02:33 +0000 (13:02 +0000)
ctf_err_copy is an obscure function used during archive generation,
propagating the errwarning stream from archives beyond the first (the
child into the first one (the parent): this means that the rest of
libctf can ignore the possibility that archives are being generated when
emitting errors, and the archive writer will compensate.

This code has been emitting format string errors for as long as it was
written, and I've been ignoring them for just as long because of course
we know it must be a false positive because this is a ctf_err_warn()
call that is propagating something that is already stored in an
errwarning string and thus has already been passed through vasprintf().

It isn`t. If for some reason we ended up emitting a %% into the
errwarning stream, this second invocation would treat it as a conversion
specification and might do all the horrible things that can happen
then. Though we do no such thing in any ctf_err_warn() calls in libctf,
this is still a real risk because we print human-readable text derived
from CTF dicts on error paths.  These are all type names, so can't
usually contain % characters, but crafted CTF dict inputs might, and
then all bets are off.  We are mostly saved by the only real caller of
this code being the linker, but even then, one crafted object file in
the link triggering an error during archive preserialization and
suddenly we are printf()ing using an attacker-controlled format string.

Fix this by manually propagating the errors, avoiding a second
ctf_err_warn() call.

This function only exists on the ctfv4 branch: no released binutils are
impacted, nor is binutils trunk.

libctf/ctf-api.c

index 0c02a70e659f324b77347beb5452d058a55c2772..2c3afd04febeb6dda3f62c8bf71c156be748f7a0 100644 (file)
@@ -256,8 +256,23 @@ ctf_err_copy (ctf_dict_t *dest, ctf_dict_t *src)
   ctf_err_warning_t *cew;
   for (cew = ctf_list_next (&src->ctf_errs_warnings); cew != NULL;
        cew = ctf_list_next (cew))
-    ctf_err_warn (dest, cew->cew_is_warning, 0, cew->cew_text);
+    {
+      ctf_err_warning_t *new_cew;
+
+      if ((new_cew = malloc (sizeof (ctf_err_warning_t))) == NULL)
+       goto oom;
+      memcpy (new_cew, cew, sizeof (ctf_err_warning_t));
+      if ((new_cew->cew_text = strdup (new_cew->cew_text)) == NULL)
+       {
+         free (new_cew);
+         goto oom;
+       }
+      ctf_list_append (&dest->ctf_errs_warnings, new_cew);
+    }
   ctf_set_errno (dest, ctf_errno (src));
+  return;
+ oom:
+  ctf_set_errno (dest, ENOMEM);
 }
 
 /* Error-warning reporting: an 'iterator' that returns errors and warnings from