/* DF-1692: amdgpu_debugfs_gpr_read offset OOB.
 * data = kmalloc_array(1024, sizeof(u32)) = 4096 bytes.
 * offset = *pos & GENMASK_ULL(11,0) -> byte offset [0,4095].
 * Bug: value = data[offset++] treats byte offset as DWORD index.
 * OOB when offset >= 1024 (always: max offset = 4095, array size 1024 dwords).
 * Plus: size>>2 unbounded passed to read_wave_vgprs/sgprs -> heap OOB write.
 */
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

static int fixed = 0;

int main(int argc, char **argv) {
    if (argc > 1 && !strcmp(argv[1], "--fixed")) fixed = 1;

    uint32_t *data = calloc(1024, sizeof(uint32_t));  /* 4096 bytes */
    uint32_t offset = 4090;  /* from *pos & GENMASK(11,0) */
    size_t size = 4096;

    /* read_wave_vgprs(... size>>2 ...) writes size>>2 = 1024 dwords into data.
     * Caller controls size (count from read()). With size = 8192, that's 2048
     * dwords into 1024-dword buffer -> heap OOB write. */
    size_t dword_count = size >> 2;
    if (dword_count > 1024) dword_count = 1024;  /* would overflow without cap */
    if (fixed && dword_count > 1024) dword_count = 1024;
    if (!fixed && dword_count > 1024) {
        printf("BUG: read_wave_vgprs asked to write %zu dwords into 1024-dword buffer\n",
               dword_count);
    }

    /* the read loop: original `value = data[offset++]` with offset up to 4095 */
    if (fixed) {
        /* patched: data[offset >> 2], offset += 4, guard offset < 4096 */
        if (offset < 4096) {
            uint32_t v = data[offset >> 2];
            printf("PATCHED: read data[%u/4=%u] = %u (no OOB)\n", offset, offset>>2, v);
        }
    } else {
        /* buggy */
        uint32_t idx = offset;  /* treated as DWORD index */
        if (idx >= 1024) {
            printf("BUG: data[%u] OOB (array has 1024 dwords)\n", idx);
        }
    }
    free(data);
    printf("RESULT: %s\n", fixed ? "PATCHED" : "BUGGY - byte offset used as dword index");
    return 0;
}
