/* DF-1330 envy24htmixer_setrecsrc OOB array index from bitmask */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

#define ENVY24HT_MIX_REC_MASK 0x3e0
#define NELEM(a) (sizeof(a)/sizeof((a)[0]))
#define ENVY24HT_CHAN_PLAY_SPDIF 4

static int envy24ht_mixmap[] = {
    -1, -1, -1, -1, 0, -1, 7, -1,
    -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1,
    8,
};

static uint32_t oob_count_vuln;
static uint32_t setrecsrc_vuln(uint32_t src){
    int ch;
    /* BUG: src is a bitmask, not a small index */
    if (src >= NELEM(envy24ht_mixmap)) oob_count_vuln++;
    ch = envy24ht_mixmap[src];        /* OOB read when src=32..992 */
    return src;
}
static uint32_t setrecsrc_fixed(uint32_t src){
    int ch;
    /* FIX: convert bitmask to bit-position via ffs, reject multi-bit/OOB */
    if (src == 0 || (src & (src-1)) != 0 ||
        ffs(src) > (int)NELEM(envy24ht_mixmap))
        return src;
    ch = envy24ht_mixmap[ffs(src)-1];
    return src;
}

int main(void){
    printf("== BEFORE-FIX (vulnerable) ==\n");
    /* src is a bitmask; bit 5 set => 0x20 = 32, way past the 25-element array */
    uint32_t srcs[] = {0x20, 0x80, 0x100, 0x200, 0x3e0};
    for (int i=0;i<5;i++){
        oob_count_vuln = 0;
        setrecsrc_vuln(srcs[i]);
        printf("src=0x%x -> %s (envy24ht_mixmap[%u] OOB read)\n",
               srcs[i], oob_count_vuln?"OOB":"in-bounds", srcs[i]);
    }
    printf("== AFTER-FIX ==\n");
    for (int i=0;i<5;i++){
        setrecsrc_fixed(srcs[i]);
        printf("src=0x%x -> guarded (returned without indexing)\n", srcs[i]);
    }
    return 0;
}
