Re: [PATCH] libsframe: validate FDE/FRE subsection bounds in sframe_decode

Indu Bhagat <[email protected]> Wed, 22 Jul 2026 14:35:02 -0700
Newsgroups gmane.comp.gnu.binutils
Message-ID <[email protected]>
On 2026-06-21 14:12, Naveed Khan wrote:
> sframe_decode only calls sframe_header_sanity_check_p, which verifies
> that sfh_fdeoff <= sfh_freoff but never checks the header-supplied
> offsets, lengths and counts against the size of the SFrame buffer.  On
> the native-endian decode path -- the foreign-endian path is bounds
> checked inside flip_sframe -- a crafted SFrame section therefore drives
> two out-of-bounds heap reads:
> 
>    - sframe_fde_tbl_init reads sfh_num_fdes function descriptor entries
>      starting at frame_buf + sfh_fdeoff, and
> 
>    - memcpy (dctx->sfd_fres, frame_buf + sfh_freoff, sfh_fre_len) copies
>      sfh_fre_len bytes starting at frame_buf + sfh_freoff.
> 
> Both read past the end of the buffer.  The defect is reachable from
> objdump --sframe and readelf on an object file carrying a crafted
> .sframe section; for example a 28-byte section whose header claims
> sfh_fre_len = 0x10000 makes objdump --sframe read 64KB past the
> section contents.
> 
> Validate in sframe_decode that the FDE and FRE sub-sections described
> by the header are fully contained in the buffer before they are read.
> The checks use subtraction and division so the arithmetic cannot
> overflow.
> 
> Signed-off-by: Naveed Khan <[email protected]>
> ---
> diff --git a/libsframe/sframe.c b/libsframe/sframe.c
> index cd6bb302..24d07ae3 100644
> --- a/libsframe/sframe.c
> +++ b/libsframe/sframe.c
> @@ -1480,6 +1480,25 @@ sframe_decode (const char *sf_buf, size_t sf_size, int *errp)
>         goto decode_fail_free;
>       }
>     hdrsz = sframe_get_hdr_size (dhp);
> +
> +  /* Validate that the FDE and FRE sub-sections described by the SFrame
> +     header lie entirely within the SFrame buffer.  The earlier call to
> +     sframe_header_sanity_check_p has checked that sfh_fdeoff <= sfh_freoff.
> +     The FDE sub-section holds sfh_num_fdes entries and precedes the FRE
> +     sub-section, which is sfh_fre_len bytes long.  The arithmetic below uses
> +     subtraction and division so that it cannot itself overflow.  */
> +  size_t fde_size = sizeof (sframe_func_desc_entry_v2);
> +  if (sfp->sfp_version == SFRAME_VERSION_3)
> +    fde_size = sizeof (sframe_func_desc_idx_v3);
> +  if (hdrsz > sf_size
> +      || dhp->sfh_freoff > sf_size - hdrsz
> +      || dhp->sfh_fre_len > sf_size - hdrsz - dhp->sfh_freoff
> +      || dhp->sfh_num_fdes > (dhp->sfh_freoff - dhp->sfh_fdeoff) / fde_size)
> +    {
> +      sframe_ret_set_errno (errp, SFRAME_ERR_BUF_INVAL);
> +      goto decode_fail_free;
> +    }
> +
>     frame_buf += hdrsz;
>   
>     /* Handle the SFrame Function Descriptor Entry section.  */

Thanks Naveed. Looks like this may need to be pushed on your behalf. 
Please confirm.

Indu