ctf-archive sanity checks

Alan Modra amodra@gmail.com
Mon Nov 3 23:16:01 GMT 2025


On Mon, Nov 03, 2025 at 05:04:06PM +0000, Nick Alcock wrote:
> On 3 Nov 2025, Alan Modra verbalised:
> > diff --git a/libctf/ctf-archive.c b/libctf/ctf-archive.c
> > index 6c4595fcc84..63184e66244 100644
> > --- a/libctf/ctf-archive.c
> > +++ b/libctf/ctf-archive.c
> > @@ -395,7 +395,7 @@ const ctf_preamble_t *
> >  ctf_arc_bufpreamble (const ctf_sect_t *ctfsect)
> >  {
> >    if (ctfsect->cts_data != NULL
> > -      && ctfsect->cts_size > sizeof (uint64_t)
> > +      && ctfsect->cts_size >= sizeof (struct ctf_archive)
> >        && (le64toh ((*(uint64_t *) ctfsect->cts_data)) == CTFA_MAGIC))
> >      {
> >        struct ctf_archive *arc = (struct ctf_archive *) ctfsect->cts_data;
> 
> I don't think that's quite enough.  Right below that, we do
> 
>       return (const ctf_preamble_t *) ((char *) arc + le64toh (arc->ctfa_ctfs)
>                                        + sizeof (uint64_t));
> 
> which is just off the end of struct ctf_archive.  So we should check
> 
> ctfsect->cts_size >= (sizeof (struct ctf_archive) + sizeof (uint64_t)).

OK, and then there is the fact that arc->ctfa_ctfs can hold anything
in a fuzzed object file so that needs checking too, as reported in the
PR.  Which BTW was an uncommonly good bug report.  The reporter didn't
just attach a fuzzed object file but reduced it to a testcase that
could easily be the basis for a testsuite addition, and provided
patches!

I did consider making ctf_arc_bufpreamble look like the following,
but decided to leave that to someone who knows what they are doing.

const ctf_preamble_t *
ctf_arc_bufpreamble (const ctf_sect_t *ctfsect)
{
  if (ctfsect->cts_size >= sizeof (struct ctf_archive)
      && (le64toh ((*(uint64_t *) ctfsect->cts_data)) == CTFA_MAGIC))
    {
      struct ctf_archive *arc = (struct ctf_archive *) ctfsect->cts_data;
      uint64_t preamble_off = le64toh (arc->ctfa_ctfs);
      if (ctfsect->cts_size >= preamble_off
	  && (ctfsect->cts_size - preamble_off
	      >= sizeof (uint64_t) + sizeof (ctf_preamble_t)))
	return (const ctf_preamble_t *) ((char *) arc + preamble_off
					 + sizeof (uint64_t));
    }
  return (const ctf_preamble_t *) ctfsect->cts_data;
}

-- 
Alan Modra


More information about the Binutils mailing list