stream_dvdnav: clamp number of buttons to array size

libdvdread doesn't sanitize this value, so we do for corrupted discs.
This commit is contained in:
Kacper Michajłow committed 2026-08-26 01:47:41 +02:00
1 parent 93451ef64f
commit e1cf77c0e9
1 file changed
+11 -6
+11 -6
View File
@@ -248,10 +248,15 @@ static bool in_menu_domain(dvdnav_t *dvdnav)
dvdnav_is_domain_fp(dvdnav) == 1; dvdnav_is_domain_fp(dvdnav) == 1;
} }
static int pci_num_buttons(const pci_t *pci)
{
return MPMIN(pci->hli.hl_gi.btn_ns, MP_ARRAY_SIZE(pci->hli.btnit));
}
static void compute_button_rect(struct priv *priv, pci_t *pci, int btn) static void compute_button_rect(struct priv *priv, pci_t *pci, int btn)
{ {
priv->hl.rect = (struct mp_rect){0}; priv->hl.rect = (struct mp_rect){0};
if (btn <= 0 || btn > pci->hli.hl_gi.btn_ns) if (btn <= 0 || btn > pci_num_buttons(pci))
return; return;
// btni_t is packed and full of bitfields, memcpy to ensure correct alignment. // btni_t is packed and full of bitfields, memcpy to ensure correct alignment.
btni_t b; btni_t b;
@@ -272,7 +277,7 @@ static void compute_button_rect(struct priv *priv, pci_t *pci, int btn)
static void compute_highlight_palette(struct priv *priv, pci_t *pci, int btn) static void compute_highlight_palette(struct priv *priv, pci_t *pci, int btn)
{ {
memset(priv->hl.palette, 0, sizeof(priv->hl.palette)); memset(priv->hl.palette, 0, sizeof(priv->hl.palette));
if (!priv->spu_clut_valid || btn <= 0 || btn > pci->hli.hl_gi.btn_ns) if (!priv->spu_clut_valid || btn <= 0 || btn > pci_num_buttons(pci))
return; return;
btni_t b; btni_t b;
memcpy(&b, &pci->hli.btnit[btn - 1], sizeof(b)); memcpy(&b, &pci->hli.btnit[btn - 1], sizeof(b));
@@ -380,7 +385,7 @@ static void update_highlight(struct priv *priv)
if (highlight_live) if (highlight_live)
dvdnav_get_current_highlight(priv->dvdnav, &btn); dvdnav_get_current_highlight(priv->dvdnav, &btn);
if (!highlight_live || btn <= 0 || btn > pci->hli.hl_gi.btn_ns) { if (!highlight_live || btn <= 0 || btn > pci_num_buttons(pci)) {
priv->current_button = 0; priv->current_button = 0;
priv->hl = (struct mp_dvdnav_highlight){0}; priv->hl = (struct mp_dvdnav_highlight){0};
} else { } else {
@@ -422,7 +427,7 @@ static void select_neighbour_button(struct priv *priv, pci_t *pci,
{ {
int32_t cur = 0; int32_t cur = 0;
dvdnav_get_current_highlight(priv->dvdnav, &cur); dvdnav_get_current_highlight(priv->dvdnav, &cur);
if (cur <= 0 || cur > pci->hli.hl_gi.btn_ns) if (cur <= 0 || cur > pci_num_buttons(pci))
return; return;
btni_t b; btni_t b;
memcpy(&b, &pci->hli.btnit[cur - 1], sizeof(b)); memcpy(&b, &pci->hli.btnit[cur - 1], sizeof(b));
@@ -617,10 +622,10 @@ static int process_event(stream_t *s, int event, void *buf, int len)
{ {
int32_t btn = 0; int32_t btn = 0;
dvdnav_get_current_highlight(dvdnav, &btn); dvdnav_get_current_highlight(dvdnav, &btn);
if (btn <= 0 || btn > pnavpci->hli.hl_gi.btn_ns) { if (btn <= 0 || btn > pci_num_buttons(pnavpci)) {
MP_VERBOSE(s, "stale button %d for a %d-button menu, " MP_VERBOSE(s, "stale button %d for a %d-button menu, "
"selecting button 1\n", btn, "selecting button 1\n", btn,
pnavpci->hli.hl_gi.btn_ns); pci_num_buttons(pnavpci));
dvdnav_button_select(dvdnav, pnavpci, 1); dvdnav_button_select(dvdnav, pnavpci, 1);
} }
} }