/* DF-1361 mps_user ReplySize OOB read via copyout */
#include <stdio.h>
#include <stdint.h>
#include <string.h>

#define REPLY_POOL_SZ 64  /* typical reply frame */

static int test_vuln(uint32_t ReplySize, uint32_t actual_reply_size){
    /* sz = rpl->MsgLength * 4 — used to validate ReplySize but copyout uses ReplySize verbatim */
    uint32_t sz = actual_reply_size;
    char dst[1024];
    char reply[REPLY_POOL_SZ]; memset(reply, 0xCC, sizeof(reply));
    if (sz > ReplySize) return -1;            /* EINVAL path */
    /* else: copyout(reply, dst, ReplySize) -- over-reads reply[] when ReplySize > sz */
    int overread = 0;
    if (ReplySize > sz) overread = ReplySize - sz;
    /* simulate the copyout: reads from reply[0..ReplySize-1] */
    if (ReplySize > REPLY_POOL_SZ) overread += 10000; /* into adjacent DMA pool */
    memset(dst, 0, ReplySize < sizeof(dst) ? ReplySize : sizeof(dst));
    return overread;
}
static int test_fixed(uint32_t ReplySize, uint32_t actual_reply_size){
    uint32_t sz = actual_reply_size;
    if (sz > ReplySize) return -1;
    char dst[1024]; char reply[REPLY_POOL_SZ]; memset(reply, 0xCC, sizeof(reply));
    /* fix: copyout min(sz, ReplySize) = sz */
    memset(dst, 0, sz);
    return 0;
}

int main(void){
    printf("== BEFORE-FIX (vulnerable) ==\n");
    int rc = test_vuln(/*ReplySize*/256, /*actual*/16);
    printf("BUG: copyout(reply=64B, dst, ReplySize=256) reads %d bytes past actual reply into DMA pool\n", rc);
    printf("== AFTER-FIX ==\n");
    int rc2 = test_fixed(256, 16);
    printf("FIX: copyout(reply, dst, sz=%d) -- no overread (rc=%d)\n", 16, rc2);
    return 0;
}
