Fix more possible crashes

This commit is contained in:
MysterD 2023-05-11 00:19:01 -07:00
parent af01a214ee
commit f785050ccb
19 changed files with 807 additions and 44 deletions

View file

@ -1,4 +1,4 @@
#!/usr/bin/bash
python3 ./autogen/convert_structs.py
python3 ./autogen/convert_functions.py
python3 ./autogen/convert_constants.py
python3 ./autogen/convert_structs.py $1
python3 ./autogen/convert_functions.py $1
python3 ./autogen/convert_constants.py $1

View file

@ -576,7 +576,7 @@ def build_call(function):
if ftype == 'void':
return ' %s;\n' % ccall
# We can't possibly know the type of a void pointer,
# We can't possibly know the type of a void pointer,
# So we just don't return anything from it
elif ftype == 'void *':
return ' %s;\n' % ccall
@ -605,7 +605,7 @@ def build_call(function):
def build_function(function, do_extern):
s = ''
fid = function['identifier']
if fid in override_function_version_excludes:
s += '#ifndef ' + override_function_version_excludes[fid] + '\n'
@ -614,6 +614,12 @@ def build_function(function, do_extern):
else:
s += 'int smlua_func_%s(lua_State* L) {\n' % function['identifier']
# make sure the bhv functions have a current object
fname = function['filename']
if fname == 'behavior_actions.h' or fname == 'obj_behaviors_2.h' or fname == 'obj_behaviors.h':
if 'bhv_' in fid:
s += ' if (!gCurrentObject) { return 0; }\n'
s += """ if (L == NULL) { return 0; }\n
int top = lua_gettop(L);
if (top != %d) {
@ -640,7 +646,7 @@ def build_function(function, do_extern):
s += '\n'
s += ' return 1;\n}\n'
if fid in override_function_version_excludes:
s += '#endif\n'
@ -659,6 +665,7 @@ def build_functions(processed_files):
s += gen_comment_header(processed_file['filename'])
for function in processed_file['functions']:
function['filename'] = processed_file['filename']
s += build_function(function, processed_file['extern'])
return s
@ -792,28 +799,51 @@ def process_files():
############################################################################
def output_nuke_function(fname, function):
fuzz_functions = ""
def output_fuzz_function(fname, function):
first = True
comment = ''
comment = ' -- '
fid = function['identifier']
print(fid + '(', end='')
line = ' ' + fid + '('
for param in function['params']:
if first:
first = False
else:
print(', ', end='')
line += ', '
comment += ', '
pid = param['identifier']
ptype = param['type']
ptype, plink = translate_type_to_lua(ptype)
if ptype == '`integer`' or ptype == '`number`' or 'enum' in ptype:
print('0', end='')
else:
print('nil', end='')
if 'enum ' in ptype:
ptype = 'integer'
line += 'rnd_' + ptype.strip().replace('`', '').replace(' ', '').split('<')[-1].split('>')[0].split('(')[0] + '()'
#if ptype == '`integer`' or ptype == '`number`' or 'enum' in ptype:
# print('0', end='')
#else:
# print('nil', end='')
comment += ptype
print(') -- ' + comment)
line += ')'
if len(line) >= 80:
line = line + '\n ' + comment + '\n'
else:
line = line.ljust(80) + comment + '\n'
global fuzz_functions
fuzz_functions += line
def output_fuzz_file():
global fuzz_functions
with open('./autogen/fuzz_template.lua') as f:
file_str = f.read()
with open('/home/djoslin/.local/share/sm64ex-coop/mods/test-fuzz.lua', 'w') as f:
f.write(file_str.replace('-- $[FUNCS]', fuzz_functions))
############################################################################
@ -877,7 +907,8 @@ def doc_function(fname, function):
return ''
# debug print out lua nuke functions
# output_nuke_function(fname, function)
if len(sys.argv) >= 2 and sys.argv[1] == 'fuzz':
output_fuzz_function(fname, function)
if not doc_should_document(fname, function['identifier']):
return ''
@ -1073,5 +1104,8 @@ def main():
global total_functions
print('Total functions: ' + str(total_functions))
if len(sys.argv) >= 2 and sys.argv[1] == 'fuzz':
output_fuzz_file()
if __name__ == '__main__':
main()

View file

@ -242,6 +242,27 @@ def parse_structs(extracted):
############################################################################
def output_fuzz_struct(struct):
sid = struct['identifier']
print('function Nuke' + sid + "(struct)")
for field in struct['fields']:
fid, ftype, fimmutable, lvt, lot = get_struct_field_info(struct, field)
if fimmutable == 'true':
continue
if sid in override_field_invisible:
if fid in override_field_invisible[sid]:
continue
if lvt == 'LVT_COBJECT':
print(' Fuzz' + ftype.replace('struct ', '') + '(struct.' + fid + ')')
elif lvt == 'LVT_COBJECT_P':
print(' struct.' + fid + ' = nil')
else:
print(' struct.' + fid + ' = 0')
print('end')
print('')
############################################################################
sLuaObjectTable = []
sLotAutoGenList = []
@ -272,28 +293,10 @@ def get_struct_field_info(struct, field):
return fid, ftype, fimmutable, lvt, lot
def output_nuke_struct(struct):
sid = struct['identifier']
print('function Nuke' + sid + "(struct)")
for field in struct['fields']:
fid, ftype, fimmutable, lvt, lot = get_struct_field_info(struct, field)
if fimmutable == 'true':
continue
if sid in override_field_invisible:
if fid in override_field_invisible[sid]:
continue
if lvt == 'LVT_COBJECT':
print(' Nuke' + ftype.replace('struct ', '') + '(struct.' + fid + ')')
elif lvt == 'LVT_COBJECT_P':
print(' struct.' + fid + ' = nil')
else:
print(' struct.' + fid + ' = 0')
print('end')
print('')
def build_struct(struct):
# debug print out lua nuke functions
# output_nuke_struct(struct)
# debug print out lua fuzz functions
if len(sys.argv) >= 2 and sys.argv[1] == 'fuzz':
output_fuzz_struct(struct)
sid = struct['identifier']

141
autogen/fuzz_template.lua Normal file
View file

@ -0,0 +1,141 @@
-- $[STRUCTS]
--------
function FuzzVec3s(struct)
struct.x = 0
struct.y = 0
struct.z = 0
end
function FuzzVec3f(struct)
struct.x = 0
struct.y = 0
struct.z = 0
end
function FuzzVec4s(struct)
struct.x = 0
struct.y = 0
struct.z = 0
struct.w = 0
end
function FuzzVec4f(struct)
struct.x = 0
struct.y = 0
struct.z = 0
struct.w = 0
end
function FuzzMat4(struct)
struct.a = 0
struct.b = 0
struct.c = 0
struct.d = 0
struct.e = 0
struct.f = 0
struct.g = 0
struct.h = 0
struct.i = 0
struct.j = 0
struct.k = 0
struct.l = 0
struct.m = 0
struct.n = 0
struct.o = 0
struct.p = 0
end
--------
function rnd_string()
t = { 0, "test", "this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string" }
return t[math.random(#t)]
end
function rnd_integer()
t = { 0, math.random(1, 10), math.random(-2147483648, 2147483647) }
return t[math.random(#t)]
end
function rnd_number()
t = { 0, math.random(), (math.random() - 0.5) * 2 * 4294967296 }
return t[math.random(#t)]
end
function rnd_Vec3s()
t = { nil, { x = rnd_integer(), y = rnd_integer(), z = rnd_integer() } }
return t[math.random(#t)]
end
function rnd_Vec3f()
t = { nil, { x = rnd_number(), y = rnd_number(), z = rnd_number() } }
return t[math.random(#t)]
end
function rnd_Vec4s()
t = { nil, { x = rnd_integer(), y = rnd_integer(), z = rnd_integer(), w = rnd_integer() } }
return t[math.random(#t)]
end
function rnd_Vec4f()
t = { nil, { x = rnd_number(), y = rnd_number(), z = rnd_number(), w = rnd_number() } }
return t[math.random(#t)]
end
function rnd_Mat4()
t = { nil, { a = rnd_integer(), b = rnd_integer(), c = rnd_integer(), d = rnd_integer(), e = rnd_integer(), f = rnd_integer(), g = rnd_integer(), h = rnd_integer(), i = rnd_integer(), j = rnd_integer(), k = rnd_integer(), l = rnd_integer(), m = rnd_integer(), n = rnd_integer(), o = rnd_integer(), p = rnd_integer() } }
return t[math.random(#t)]
end
function rnd_Object()
t = { nil, gMarioStates[0].marioObj, gMarioStates[1].marioObj }
return t[math.random(#t)]
end
function rnd_MarioState()
t = { nil, gMarioStates[math.random(0, MAX_PLAYERS)] }
return t[math.random(#t)]
end
function rnd_NetworkPlayer()
t = { nil, gNetworkPlayers[math.random(0, MAX_PLAYERS)] }
return t[math.random(#t)]
end
function rnd_SpawnParticlesInfo()
t = { nil, obj_get_temp_spawn_particles_info(math.random(0, E_MODEL_MAX)) }
return t[math.random(#t)]
end
function rnd_BehaviorScript()
t = { nil, get_behavior_from_id(math.random(0, id_bhv_max_count)) }
return t[math.random(#t)]
end
function rnd_Camera()
t = { nil, gMarioStates[0].area.camera }
return t[math.random(#t)]
end
function rnd_PlayerGeometry()
t = { nil, {} }
return t[math.random(#t)]
end
--------
function fuzz_functions()
-- $[FUNCS]
end
--------
function fuzz_structs()
end
hook_chat_command('fuzz-funcs', 'funcs', fuzz_functions)
hook_chat_command('fuzz-structs', 'structs', fuzz_structs)
fuzz_functions()
print('!')

View file

@ -52,7 +52,7 @@ u16 random_u16(void) {
if (gOverrideRngPosition != NULL) {
// override this function for rng positions
gRandomSeed16 = gOverrideRngPosition->seed;
} else if (gCurrentObject->oSyncID != 0) {
} else if (gCurrentObject && gCurrentObject->oSyncID != 0) {
// override this function for synchronized entities
so = sync_object_get(gCurrentObject->oSyncID);
if (so != NULL && so->o == gCurrentObject) {

View file

@ -1,6 +1,7 @@
// chuckya.c.inc
void common_anchor_mario_behavior(f32 sp28, f32 sp2C, s32 sp30) {
if (!o) { return; }
for (s32 i = 0; i < MAX_PLAYERS; i++) {
if (!is_player_active(&gMarioStates[i])) { continue; }
struct MarioState* marioState = &gMarioStates[i];
@ -38,6 +39,7 @@ void bhv_chuckya_anchor_mario_loop(void) {
}
s32 unknown_chuckya_function(s32 sp20, f32 sp24, f32 sp28, s32 sp2C) {
if (!o) { return 0; }
struct Object* player = nearest_player_to_object(o);
s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000;
s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0;
@ -82,6 +84,7 @@ s32 approach_forward_vel(f32 *arr, f32 spC, f32 sp10) {
}
void chuckya_act_0(void) {
if (!o) { return; }
struct Object* player = nearest_player_to_object(o);
s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0;
s32 sp3C = 0;
@ -137,6 +140,7 @@ void chuckya_act_0(void) {
}
void chuckya_act_1(void) {
if (!o) { return; }
if (o->oSubAction == 0) {
if (cur_obj_init_animation_and_check_if_near_end(0))
o->oSubAction++;
@ -174,6 +178,7 @@ void chuckya_act_1(void) {
}
void chuckya_act_3(void) {
if (!o) { return; }
o->oForwardVel = 0;
o->oVelY = 0;
cur_obj_init_animation_with_sound(4);
@ -182,6 +187,7 @@ void chuckya_act_3(void) {
}
void chuckya_act_2(void) {
if (!o) { return; }
if (o->oMoveFlags & (OBJ_MOVE_HIT_WALL | OBJ_MOVE_MASK_IN_WATER | OBJ_MOVE_LANDED)) {
obj_mark_for_deletion(o);
obj_spawn_loot_yellow_coins(o, 5, 20.0f);
@ -192,6 +198,7 @@ void chuckya_act_2(void) {
void (*sChuckyaActions[])(void) = { chuckya_act_0, chuckya_act_1, chuckya_act_2, chuckya_act_3 };
void chuckya_move(void) {
if (!o) { return; }
cur_obj_update_floor_and_walls();
CUR_OBJ_CALL_ACTION_FUNCTION(sChuckyaActions);
cur_obj_move_standard(-30);

View file

@ -1,6 +1,7 @@
// grand_star.c.inc
s32 arc_to_goal_pos(Vec3f empty, Vec3f pos, f32 yVel, f32 gravity) {
if (!o) { return 0; }
f32 dx = empty[0] - pos[0];
f32 dz = empty[2] - pos[2];
f32 planarDist = sqrtf(dx * dx + dz * dz);
@ -13,6 +14,7 @@ s32 arc_to_goal_pos(Vec3f empty, Vec3f pos, f32 yVel, f32 gravity) {
}
void grand_star_zero_velocity(void) {
if (!o) { return; }
o->oGravity = 0.0f;
o->oVelY = 0.0f;
o->oForwardVel = 0.0f;

View file

@ -25,7 +25,7 @@ void spawn_smoke_with_velocity(void) {
// TODO Fix name
void clear_particle_flags(u32 flags) {
if (o->parentObj) {
if (o && o->parentObj) {
o->parentObj->oActiveParticleFlags &= flags ^ -1; // Clear the flags given (could just be ~flags)
}
}

View file

@ -4,6 +4,7 @@ void spawn_child_obj_relative(struct Object *parent, s16 xOffset, s16 yOffset, s
s16 yawOffset, s16 rollOffset, s16 forwardVel,
s32 model, const BehaviorScript *behavior) {
struct Object *sp1C = spawn_object(parent, model, behavior);
if (!sp1C) { return; }
sp1C->header.gfx.animInfo.animFrame = random_float() * 6.f;
sp1C->oEndBirdUnk104 = sCutsceneVars[9].point[0];

View file

@ -13,6 +13,7 @@ struct ObjectHitbox sMetalBoxHitbox = {
};
s32 check_if_moving_over_floor(f32 a0, f32 a1) {
if (!o) { return 0; }
struct Surface *sp24;
f32 sp20 = o->oPosX + sins(o->oMoveAngleYaw) * a1;
f32 floorHeight;

View file

@ -27,17 +27,19 @@ void spawn_star_number(void) {
// Check if the star already has a number
struct Object *starNumber = obj_get_first_with_behavior_id(id_bhvStarNumber);
u32 sanityDepth = 0;
for (; starNumber; starNumber = obj_get_next_with_same_behavior_id(starNumber)) {
if (++sanityDepth >= 10000) { break; }
if (!starNumber || starNumber->parentObj == o) {
break;
}
}
// If not, spawn a number
if (!starNumber) {
if (!starNumber && o) {
starNumber = spawn_object(o, MODEL_NUMBER, bhvStarNumber);
}
if (starNumber) {
if (starNumber && o) {
starNumber->parentObj = o;
starNumber->activeFlags |= ACTIVE_FLAG_INITIATED_TIME_STOP; // to make sure it's updated even during time stop
starNumber->oStarBehavior = (const void *) smlua_override_behavior(o->behavior);
@ -208,6 +210,7 @@ struct Object *spawn_default_star(f32 x, f32 y, f32 z) {
}
struct Object *spawn_red_coin_cutscene_star(f32 x, f32 y, f32 z) {
if (!o) { return NULL; }
u32 behParams = o->oBehParams;
// de-duplication checking
@ -225,6 +228,7 @@ struct Object *spawn_red_coin_cutscene_star(f32 x, f32 y, f32 z) {
}
struct Object *spawn_no_exit_star(f32 x, f32 y, f32 z) {
if (!o) { return NULL; }
u32 behParams = o->oBehParams;
// de-duplication checking

View file

@ -9,12 +9,13 @@ s8 D_8032F948[] = { 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 2, 5, 1, 5, 1, 5, 1, 5,
s8 *D_8032F96C[] = { D_8032F8F0, D_8032F924, D_8032F948 };
void tox_box_shake_screen(void) {
if (o->oDistanceToMario < 3000.0f)
if (o && o->oDistanceToMario < 3000.0f)
cur_obj_shake_screen(SHAKE_POS_SMALL);
}
void tox_box_move(f32 forwardVel, f32 a1, s16 deltaPitch, s16 deltaRoll)
{
if (!o) { return; }
o->oPosY = 99.41124 * sins((f32)(o->oTimer + 1) / 8 * 0x8000) + o->oHomeY + 3.0f;
o->oForwardVel = forwardVel;
o->oUnkC0 = a1;
@ -47,6 +48,7 @@ void tox_box_act_7(void) {
}
void tox_box_act_1(void) {
if (!o) { return; }
o->oForwardVel = 0.0f;
if (o->oTimer == 0)
tox_box_shake_screen();
@ -56,16 +58,19 @@ void tox_box_act_1(void) {
}
void tox_box_act_2(void) {
if (!o) { return; }
if (o->oTimer == 20)
o->oAction = cur_obj_progress_direction_table();
}
void tox_box_act_3(void) {
if (!o) { return; }
if (o->oTimer == 20)
o->oAction = cur_obj_progress_direction_table();
}
void tox_box_act_0(void) {
if (!o) { return; }
if (!BHV_ARR_CHECK(D_8032F96C, o->oBehParams2ndByte, s8*)) { return; }
s8 *sp1C = D_8032F96C[o->oBehParams2ndByte];
o->oAction = cur_obj_set_direction_table(sp1C);

View file

@ -2,7 +2,7 @@
void play_penguin_walking_sound(s32 walk) {
s32 sound;
if (o->oSoundStateID == 0) {
if (o && o->oSoundStateID == 0) {
if (walk == PENGUIN_WALK_BABY)
sound = SOUND_OBJ_BABY_PENGUIN_WALK;
else // PENGUIN_WALK_BIG

View file

@ -5410,6 +5410,7 @@ void warp_camera(f32 displacementX, f32 displacementY, f32 displacementZ) {
* unless smooth movement is off, in which case the y coordinate is simply set to `goal`
*/
void approach_camera_height(struct Camera *c, f32 goal, f32 inc) {
if (!c) { return; }
if (sStatusFlags & CAM_FLAG_SMOOTH_MOVEMENT) {
if (c->pos[1] < goal) {
if ((c->pos[1] += inc) > goal) {

View file

@ -106,7 +106,7 @@ struct Object *gMarioObjects[MAX_PLAYERS];
* This object is used frequently in object behavior code, and so is often
* aliased as "o".
*/
struct Object *gCurrentObject;
struct Object *gCurrentObject = NULL;
/**
* The next object behavior command to be executed.
@ -350,6 +350,7 @@ s32 update_objects_starting_at(struct ObjectNode *objList, struct ObjectNode *fi
if (!firstObj) { return 0; }
s32 count = 0;
struct Object* prevObject = gCurrentObject;
while (objList != firstObj) {
gCurrentObject = (struct Object *) firstObj;
@ -362,6 +363,8 @@ s32 update_objects_starting_at(struct ObjectNode *objList, struct ObjectNode *fi
count += 1;
}
gCurrentObject = prevObject;
return count;
}
@ -378,6 +381,7 @@ s32 update_objects_during_time_stop(struct ObjectNode *objList, struct ObjectNod
if (!firstObj) { return 0; }
s32 count = 0;
s32 unfrozen;
struct Object* prevObject = gCurrentObject;
while (objList != firstObj) {
gCurrentObject = (struct Object *) firstObj;
@ -414,6 +418,8 @@ s32 update_objects_during_time_stop(struct ObjectNode *objList, struct ObjectNod
count++;
}
gCurrentObject = prevObject;
return count;
}
@ -440,6 +446,7 @@ s32 update_objects_in_list(struct ObjectNode *objList) {
s32 unload_deactivated_objects_in_list(struct ObjectNode *objList) {
if (!objList) { return 0; }
struct ObjectNode *obj = objList->next;
struct Object* prevObject = gCurrentObject;
while (objList != obj) {
gCurrentObject = (struct Object *) obj;
@ -458,6 +465,8 @@ s32 unload_deactivated_objects_in_list(struct ObjectNode *objList) {
}
}
gCurrentObject = prevObject;
return 0;
}

File diff suppressed because it is too large Load diff

View file

@ -123,10 +123,12 @@ struct Object *obj_get_first(enum ObjectList objList) {
struct Object *obj_get_first_with_behavior_id(enum BehaviorId behaviorId) {
const BehaviorScript* behavior = get_behavior_from_id(behaviorId);
u32 sanityDepth = 0;
behavior = smlua_override_behavior(behavior);
if (behavior) {
enum ObjectList objList = get_object_list_from_behavior(behavior);
for (struct Object *obj = obj_get_first(objList); obj != NULL; obj = obj_get_next(obj)) {
if (++sanityDepth > 10000) { break; }
if (obj->behavior == behavior && obj->activeFlags != ACTIVE_FLAG_DEACTIVATED) {
return obj;
}
@ -137,10 +139,12 @@ struct Object *obj_get_first_with_behavior_id(enum BehaviorId behaviorId) {
struct Object *obj_get_first_with_behavior_id_and_field_s32(enum BehaviorId behaviorId, s32 fieldIndex, s32 value) {
const BehaviorScript* behavior = get_behavior_from_id(behaviorId);
u32 sanityDepth = 0;
behavior = smlua_override_behavior(behavior);
if (behavior) {
enum ObjectList objList = get_object_list_from_behavior(behavior);
for (struct Object *obj = obj_get_first(objList); obj != NULL; obj = obj_get_next(obj)) {
if (++sanityDepth > 10000) { break; }
if (obj->behavior == behavior && obj->activeFlags != ACTIVE_FLAG_DEACTIVATED && obj->OBJECT_FIELD_S32(fieldIndex) == value) {
return obj;
}

View file

@ -216,9 +216,11 @@ void network_receive_level_macro(struct Packet* p) {
u8 mask = ((o2->oBehParams2ndByte & GOOMBA_BP_TRIPLET_FLAG_MASK) >> 2);
if (info & mask) {
extern void mark_goomba_as_dead(void);
struct Object* prevObject = gCurrentObject;
gCurrentObject = o2;
mark_goomba_as_dead();
obj_mark_for_deletion(o2);
gCurrentObject = prevObject;
}
}
LOG_INFO("rx macro special: goomba triplet");

View file

@ -68,6 +68,7 @@ void network_receive_spawn_star(struct Packet* p) {
}
void network_send_spawn_star_nle(struct Object* o, u32 params) {
if (!o) { return; }
u8 globalIndex = UNKNOWN_GLOBAL_INDEX;
if (o->behavior == smlua_override_behavior(bhvMario)) {
u8 localIndex = o->oBehParams - 1;