forked from Ports/perfect_dark
Fix a few cases of UB incl. OoB
Behaviour should be mostly the same but there are some OoB accesses in the menu code where I've had to assume things. Tests for each OoB case: - Accessing of layer -1: Select a game file in the "Choose Your Reality" screen. - Accessing of menu for the 5th player: Die in a mission.
This commit is contained in:
1 parent
d2574c4b49
commit
889ae950fe
4 files changed
+36
-2
No files matched your search
@@ -1,4 +1,5 @@
|
||||
#include <ultra64.h>
|
||||
#include <string.h>
|
||||
#include "constants.h"
|
||||
#include "game/atan2f.h"
|
||||
#include "game/camera.h"
|
||||
@@ -600,6 +601,9 @@ bool camIsPosInFovAndVisibleRoom(RoomNum *rooms, struct coord *pos, f32 arg2)
|
||||
RoomNum room;
|
||||
bool hasdata = false;
|
||||
struct drawslot *thisthing;
|
||||
#ifdef AVOID_UB
|
||||
static struct drawslot dslot;
|
||||
#endif
|
||||
struct screenbox box;
|
||||
|
||||
for (i = 0, room = rooms[i]; room != -1; i++, room = rooms[i]) {
|
||||
@@ -637,5 +641,10 @@ bool camIsPosInFovAndVisibleRoom(RoomNum *rooms, struct coord *pos, f32 arg2)
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef AVOID_UB
|
||||
memcpy(&dslot.box, &box, sizeof(box));
|
||||
return camIsPosInScreenBox(pos, arg2, &dslot);
|
||||
#else
|
||||
return camIsPosInScreenBox(pos, arg2, (struct drawslot *) &(((u8 *) &box)[-((uintptr_t) &(((struct drawslot *)0)->box))]));
|
||||
#endif
|
||||
}
|
||||
@@ -329,7 +329,11 @@ void gfxReplaceGbiCommands(Gfx *startgdl, Gfx *endgdl, s32 type)
|
||||
|
||||
void gfxReplaceGbiCommandsRecursively(struct roomblock *block, s32 type)
|
||||
{
|
||||
#ifndef AVOID_UB
|
||||
// Sometimes block is NULL when this is called.
|
||||
// If UBSan is being used, this will crash in this instance.
|
||||
if (block->type == ROOMBLOCKTYPE_PARENT);
|
||||
#endif
|
||||
|
||||
while (true) {
|
||||
if (!block) {
|
||||
|
||||
@@ -3413,8 +3413,14 @@ void menuClose(void)
|
||||
|
||||
void func0f0f8120(void)
|
||||
{
|
||||
#ifdef AVOID_UB
|
||||
u32 mpindex = g_MpPlayerNum % MAX_PLAYERS;
|
||||
struct menudialog *prev = g_Menus[mpindex].curdialog;
|
||||
s32 i;
|
||||
#else
|
||||
struct menudialog *prev = g_Menus[g_MpPlayerNum].curdialog;
|
||||
s32 i;
|
||||
#endif
|
||||
|
||||
if (g_MenuData.unk66e > 0) {
|
||||
for (i = g_MenuData.unk66e; i >= 0; i--) {
|
||||
@@ -3422,11 +3428,22 @@ void func0f0f8120(void)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef AVOID_UB
|
||||
mpindex = g_MpPlayerNum;
|
||||
if (mpindex >= MAX_PLAYERS)
|
||||
mpindex -= MAX_PLAYERS;
|
||||
if (g_Menus[mpindex].curdialog == prev) {
|
||||
while (g_Menus[mpindex].depth > 0) {
|
||||
menuPopDialog();
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (g_Menus[g_MpPlayerNum].curdialog == prev) {
|
||||
while (g_Menus[g_MpPlayerNum].depth > 0) {
|
||||
menuPopDialog();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void func0f0f820c(struct menudialogdef *dialogdef, s32 root)
|
||||
@@ -4340,7 +4357,11 @@ void dialogTick(struct menudialog *dialog, struct menuinputs *inputs, u32 tickfl
|
||||
}
|
||||
|
||||
// Apply default navigational behaviour if requested
|
||||
#ifdef AVOID_UB
|
||||
if (usedefaultbehaviour && (tickflags & MENUTICKFLAG_DIALOGISCURRENT) && !dialog->dimmed && g_Menus[g_MpPlayerNum].depth >= 1) {
|
||||
#else
|
||||
if (usedefaultbehaviour && (tickflags & MENUTICKFLAG_DIALOGISCURRENT) && !dialog->dimmed) {
|
||||
#endif
|
||||
struct menulayer *layer = &g_Menus[g_MpPlayerNum].layers[g_Menus[g_MpPlayerNum].depth - 1];
|
||||
|
||||
if (layer->numsiblings <= 1) {
|
||||
|
||||
@@ -2736,8 +2736,8 @@ bool mp3dec000427d8(struct asistream *stream, u32 gr)
|
||||
f32 *sp0c = stream->unk4664[0][0].unk00;
|
||||
s32 i = 0;
|
||||
|
||||
if (stream->window_switching[gr][0] && stream->window_switching[gr][2] == 2) {
|
||||
if (stream->window_switching[gr][4]) {
|
||||
if (stream->window_switching[gr][0] && stream->block_type[gr][0] == 2) {
|
||||
if (stream->mixed_block_flag[gr][0]) {
|
||||
while (i++ < 36) {
|
||||
*(sp10++) = *(sp0c++);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user