Hi Aaron,

On Mon, Jul 20, 2026 at 10:34:58PM -0400, Aaron Merey wrote:
> On Fri, Jul 10, 2026 at 6:35 PM Mark Wielaard <[email protected]> wrote:
> >  static Dwarf *
> >  check_section (Dwarf *result, size_t shstrndx, Elf_Scn *scn, bool inscngrp)
> > @@ -190,11 +193,11 @@ check_section (Dwarf *result, size_t shstrndx, 
> > Elf_Scn *scn, bool inscngrp)
> >      {
> >        /* .debug_cu_index and .debug_tu_index don't have a .dwo suffix,
> >          but they are for DWO.  */
> > -      if (result->type != TYPE_DWO
> > +      if (result->type != DWARF_T_DWO
> >           && (cnt == IDX_debug_cu_index || cnt == IDX_debug_tu_index))
> >         continue;
> >        bool need_dot_dwo =
> > -       (result->type == TYPE_DWO
> > +       (result->type == DWARF_T_DWO
> >          && cnt != IDX_debug_cu_index
> >          && cnt != IDX_debug_tu_index);
> 
> Should IDX_debug_dwp be included here since it also doesn't have a .dwo
> suffix?

Yes, well spotted. It can be part of either a dwp DWARF_T_DWO or
DWARF_T_PLAIN, but in both cases it won't have a .dwo extension.
debug_sup and gnu_debugaltlink however cannot be part of DWARF_T_DWO.

> > @@ -545,24 +576,58 @@ scngrp_read (Dwarf *result, Elf *elf, size_t 
> > shstrndx, Elf_Scn *scngrp)
> >    Elf32_Word *scnidx = (Elf32_Word *) data->d_buf;
> >    size_t cnt;
> >
> > -  /* First check the type (PLAIN, DWO, LTO) we are looking for.  We
> > -     prefer PLAIN if available over DWO, over LTO.  */
> > -  for (cnt = 1; cnt * sizeof (Elf32_Word) <= data->d_size; ++cnt)
> > +  if (requested_type == DWARF_T_AUTO)
> >      {
> > -      Elf_Scn *scn = elf_getscn (elf, scnidx[cnt]);
> > -      if (scn == NULL)
> > +      /* First check the type (PLAIN, DWO, LTO) we are looking for.  We
> > +        prefer PLAIN if available over DWO, over LTO.  */
> > +      for (cnt = 1; cnt * sizeof (Elf32_Word) <= data->d_size; ++cnt)
> >         {
> > -         /* A section group refers to a non-existing section.  Should
> > -            never happen.  */
> > +         Elf_Scn *scn = elf_getscn (elf, scnidx[cnt]);
> > +         if (scn == NULL)
> > +           {
> > +             /* A section group refers to a non-existing section.  Should
> > +                never happen.  */
> > +             Dwarf_Sig8_Hash_free (&result->sig8_hash);
> > +             __libdw_seterrno (DWARF_E_INVALID_ELF);
> > +             free (result);
> > +             return NULL;
> > +           }
> > +
> > +         Dwarf_Type type = scn_dwarf_type (result, shstrndx, scn);
> > +         if (type > result->type)
> > +           result->type = type;
> > +       }
> > +    }
> > +  else
> > +    {
> > +      /* Check there is at least one section of the requested type.  */
> > +      bool found = false;
> > +      for (cnt = 1; cnt * sizeof (Elf32_Word) <= data->d_size && !found; 
> > ++cnt)
> > +       {
> > +         Elf_Scn *scn = elf_getscn (elf, scnidx[cnt]);
> > +         if (scn == NULL)
> > +           {
> > +             Dwarf_Sig8_Hash_free (&result->sig8_hash);
> > +             __libdw_seterrno (DWARF_E_INVALID_ELF);
> > +             free (result);
> > +             return NULL;
> > +           }
> > +
> > +         Dwarf_Type type = scn_dwarf_type (result, shstrndx, scn);
> > +         if (type == requested_type)
> > +           found = true;
> 
> There is an assert around line 636 in dwarf_begin_elf.c that will fail
> if a malformed binary has scngrp containing non-existing sections.

Yes, at the end of scngrp_read.

> The loop in the `if (requested_type == DWARF_T_AUTO)` branch verifies
> every scngrp entry corresponds to a real section but the new else branch
> loop will stop early if found is set to true.  In this case not every
> entry is verified.
> 
> It might be worth addressing this to prevent another security bug report.
> We can still exit the loop early but replace the assert with an early
> return.

Yes, good idea. In general asserts are tricky in a library unless you
are really, really sure they can never trigger.

I'll sent a new version.

Thanks,

Mark

Reply via email to