From 26b964b587007caace43f0dda8db1ac4a8c97e3d Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 02:21:53 +0200 Subject: [PATCH] psxbios : Several fixes to malloc. - Don't allow malloc to init memory if heap is invalid According to nocash documentation, malloc will not allocate if heap size is too small or invalid. - Also merge some fixes from PCSX4ALL fork by senquack in order to allow Burning Road to run. --- libpcsxcore/psxbios.c | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 399df9a4..e9a13f99 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -254,6 +254,7 @@ static EvCB *RcEV; // 0xf2 static EvCB *UeEV; // 0xf3 static EvCB *SwEV; // 0xf4 static EvCB *ThEV; // 0xff +static u32 heap_size = 0; static u32 *heap_addr = NULL; static u32 *heap_end = NULL; static u32 SysIntRP[8]; @@ -983,6 +984,11 @@ void psxBios_malloc() { // 0x33 #ifdef PSXBIOS_LOG PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x33]); #endif + if (!a0 || (!heap_size || !heap_addr)) { + v0 = 0; + pc0 = ra; + return; + } // scan through heap and combine free chunks of space chunk = heap_addr; @@ -992,6 +998,15 @@ void psxBios_malloc() { // 0x33 csize = ((u32)*chunk) & 0xfffffffc; cstat = ((u32)*chunk) & 1; + // most probably broken heap descriptor + // this fixes Burning Road + if (*chunk == 0) { + newchunk = chunk; + dsize = ((uptr)heap_end - (uptr)chunk) - 4; + colflag = 1; + break; + } + // it's a free chunk if(cstat == 1) { if(colflag == 0) { @@ -1023,28 +1038,36 @@ void psxBios_malloc() { // 0x33 // exit on uninitialized heap if (chunk == NULL) { - SysPrintf("malloc %x,%x: Uninitialized Heap!\n", v0, a0); + printf("malloc %x,%x: Uninitialized Heap!\n", v0, a0); v0 = 0; pc0 = ra; return; } // search an unused chunk that is big enough until the end of the heap - while ((dsize > csize || cstat == 0) && chunk < heap_end ) { + while ((dsize > csize || cstat==0) && chunk < heap_end ) { chunk = (u32*)((uptr)chunk + csize + 4); + + // catch out of memory + if(chunk >= heap_end) { + printf("malloc %x,%x: Out of memory error!\n", + v0, a0); + v0 = 0; pc0 = ra; + return; + } + csize = ((u32)*chunk) & 0xfffffffc; cstat = ((u32)*chunk) & 1; } - // catch out of memory - if(chunk >= heap_end) { SysPrintf("malloc %x,%x: Out of memory error!\n", v0, a0); v0 = 0; pc0 = ra; return; } - // allocate memory if(dsize == csize) { // chunk has same size *chunk &= 0xfffffffc; - } - else { + } else if (dsize > csize) { + v0 = 0; pc0 = ra; + return; + } else { // split free chunk *chunk = SWAP32(dsize); newchunk = (u32*)((uptr)chunk + dsize + 4); @@ -1052,9 +1075,9 @@ void psxBios_malloc() { // 0x33 } // return pointer to allocated memory - v0 = ((unsigned long)chunk - (unsigned long)psxM) + 4; + v0 = ((uptr)chunk - (uptr)psxM) + 4; v0|= 0x80000000; - SysPrintf ("malloc %x,%x\n", v0, a0); + //printf ("malloc %x,%x\n", v0, a0); pc0 = ra; } @@ -2885,6 +2908,7 @@ void psxBiosInit() { pad_buf1len = pad_buf2len = 0; heap_addr = NULL; heap_end = NULL; + heap_size = 0; CardState = -1; CurThread = 0; memset(FDesc, 0, sizeof(FDesc)); -- 2.39.2