Skip to content

Commit f96a27f

Browse files
authored
Merge pull request #4370 from JohnAFernandez/Ensure-obj_team-is_called_safely
Do our best to avoid invalid types in obj_team
2 parents f935a4a + e9e7222 commit f96a27f

File tree

3 files changed

+125
-97
lines changed

3 files changed

+125
-97
lines changed

code/ai/aicode.cpp

Lines changed: 122 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -2400,6 +2400,7 @@ void ai_attack_object(object* attacker, object* attacked, int ship_info_index)
24002400

24012401
Assert(attacker != nullptr);
24022402
Assert(attacker->instance >= 0);
2403+
Assert(attacker->type == OBJ_SHIP);
24032404
Assert(Ships[attacker->instance].ai_index != -1);
24042405
// Bogus! Who tried to get me to attack myself!
24052406
if (attacker == attacked) {
@@ -10014,7 +10015,7 @@ void guard_object_was_hit(object *guard_objp, object *hitter_objp)
1001410015
aip->submode = SM_ATTACK;
1001510016
aip->submode_start_time = Missiontime;
1001610017
aip->active_goal = AI_ACTIVE_GOAL_DYNAMIC;
10017-
} else {
10018+
} else if (Objects[aip->target_objnum].type == OBJ_SHIP) {
1001810019
int num_attacking_cur, num_attacking_new;
1001910020

1002010021
num_attacking_cur = num_ships_attacking(aip->target_objnum);
@@ -10036,6 +10037,8 @@ void guard_object_was_hit(object *guard_objp, object *hitter_objp)
1003610037
aip->active_goal = AI_ACTIVE_GOAL_DYNAMIC;
1003710038
}
1003810039
}
10040+
} else {
10041+
UNREACHABLE("The AI previously had a guard goal to guard something besides a ship, specifically an object of type %d. As we understand it, this should not happen. Please report!", Objects[aip->target_objnum].type);
1003910042
}
1004010043
}
1004110044
}
@@ -14490,6 +14493,13 @@ void validate_mode_submode(ai_info *aip)
1449014493
*/
1449114494
void ai_frame(int objnum)
1449214495
{
14496+
// Cyborg - can you believe this was added in *2022*??
14497+
Assertion (Objects[objnum].type == OBJ_SHIP, "Ai_frame was called for a non-ship of type %d. Please report!", Objects[objnum].type);
14498+
14499+
if (Objects[objnum].type != OBJ_SHIP){
14500+
return;
14501+
}
14502+
1449314503
ship *shipp = &Ships[Objects[objnum].instance];
1449414504
ai_info *aip = &Ai_info[shipp->ai_index];
1449514505
int target_objnum;
@@ -14572,7 +14582,7 @@ void ai_frame(int objnum)
1457214582
} else if (aip->resume_goal_time == -1) {
1457314583
// AL 12-9-97: Don't allow cargo and navbuoys to set their aip->target_objnum
1457414584
if ( Ship_info[shipp->ship_info_index].class_type > -1 && (Ship_types[Ship_info[shipp->ship_info_index].class_type].flags[Ship::Type_Info_Flags::AI_auto_attacks]) ) {
14575-
target_objnum = find_enemy(objnum, MAX_ENEMY_DISTANCE, The_mission.ai_profile->max_attackers[Game_skill_level]); // Attack up to 25K units away.
14585+
target_objnum = find_enemy(objnum, MAX_ENEMY_DISTANCE, The_mission.ai_profile->max_attackers[Game_skill_level]); // Attack up to 2.5K units away.
1457614586
if (target_objnum != -1) {
1457714587
if (aip->target_objnum != target_objnum)
1457814588
aip->aspect_locked_time = 0.0f;
@@ -15109,9 +15119,9 @@ void init_aip_from_class_and_profile(ai_info *aip, ai_class *aicp, ai_profile_t
1510915119

1511015120
void ai_do_default_behavior(object *obj)
1511115121
{
15112-
Assert(obj != NULL);
15113-
Assert(obj->instance != -1);
15114-
Assert(Ships[obj->instance].ai_index != -1);
15122+
Assertion(obj != nullptr, "Ai_do_default_behavior() was given a bad information. Specifically obj is a nullptr. This is a coder error, please report!");
15123+
Assertion((obj->type == OBJ_SHIP) && (obj->instance > -1) && (obj->instance < MAX_SHIPS), "This function that requires an object to be a ship was passed an invalid ship. Please report\n\nObject type: %d\nInstance #: %d", obj->type, obj->instance);
15124+
Assertion(Ships[obj->instance].ai_index >= 0, "A ship has been found to have an invalid ai_index of %d. This should have been assigned and is coder mistake, please report!", Ships[obj->instance].ai_index);
1511515125

1511615126
ai_info *aip = &Ai_info[Ships[obj->instance].ai_index];
1511715127
ship_info* sip = &Ship_info[Ships[obj->instance].ship_info_index];
@@ -15209,118 +15219,125 @@ void maybe_process_friendly_hit(object *objp_hitter, object *objp_hit, object *o
1520915219
return;
1521015220
}
1521115221

15212-
if ((obj_team(objp_hitter) == obj_team(objp_hit)) && (objp_hitter == Player_obj)) {
15222+
// Cyborg -- I had to switch around the logic here because it was potentially
15223+
// sending non-ships to obj_team, which would trigger an assert
15224+
if (objp_hitter == Player_obj){
1521315225

15214-
// AL 12-4-97: It is possible the Player is a OBJ_GHOST at this point. If so, bail out.
15226+
// Cyborg - So check if this is a ship first. Probably true, but you never know, with FSO
15227+
// (especially in multi)
1521515228
if ( objp_hitter->type != OBJ_SHIP ) {
1521615229
return;
1521715230
}
1521815231

15219-
Assert(objp_hitter->type == OBJ_SHIP);
15232+
// And assert that obj_hit is a ship as well.
1522015233
Assert(objp_hit->type == OBJ_SHIP);
15221-
Assert((objp_weapon->type == OBJ_WEAPON) || (objp_weapon->type == OBJ_BEAM)); //beam added for traitor detection - FUBAR
15222-
15223-
ship *shipp_hitter = &Ships[objp_hitter->instance];
15224-
ship *shipp_hit = &Ships[objp_hit->instance];
15225-
15226-
if (shipp_hitter->team != shipp_hit->team) {
15227-
return;
15228-
}
1522915234

15230-
// get the player
15231-
player *pp = &Players[Player_num];
15235+
if (obj_team(objp_hitter) == obj_team(objp_hit)) {
1523215236

15233-
// wacky stuff here
15234-
if (pp->friendly_hits != 0) {
15235-
float time_since_last_hit = f2fl(Missiontime - pp->friendly_last_hit_time);
15236-
if ((time_since_last_hit >= 0.0f) && (time_since_last_hit < 10000.0f)) {
15237-
if (time_since_last_hit > 60.0f) {
15238-
pp->friendly_hits = 0;
15239-
pp->friendly_damage = 0.0f;
15240-
} else if (time_since_last_hit > 2.0f) {
15241-
pp->friendly_hits -= (int) time_since_last_hit/2;
15242-
pp->friendly_damage -= time_since_last_hit;
15243-
}
15237+
Assert((objp_weapon->type == OBJ_WEAPON) || (objp_weapon->type == OBJ_BEAM)); //beam added for traitor detection - FUBAR
1524415238

15245-
if (pp->friendly_damage < 0.0f) {
15246-
pp->friendly_damage = 0.0f;
15247-
}
15239+
ship *shipp_hitter = &Ships[objp_hitter->instance];
15240+
ship *shipp_hit = &Ships[objp_hit->instance];
1524815241

15249-
if (pp->friendly_hits < 0) {
15250-
pp->friendly_hits = 0;
15251-
}
15242+
if (shipp_hitter->team != shipp_hit->team) {
15243+
return;
1525215244
}
15253-
}
1525415245

15255-
float damage; // Damage done by weapon. Gets scaled down based on size of ship.
15246+
// get the player
15247+
player *pp = &Players[Player_num];
1525615248

15257-
if (objp_weapon->type == OBJ_BEAM) // added beam for traitor detection -FUBAR
15258-
damage = beam_get_ship_damage(&Beams[objp_weapon->instance], objp_hit);
15259-
else
15260-
damage = Weapon_info[Weapons[objp_weapon->instance].weapon_info_index].damage;
15261-
15262-
// wacky stuff here
15263-
ship_info *sip = &Ship_info[Ships[objp_hit->instance].ship_info_index];
15264-
if (shipp_hit->ship_max_hull_strength > 1000.0f) {
15265-
float factor = shipp_hit->ship_max_hull_strength / 1000.0f;
15266-
factor = MIN(100.0f, factor);
15267-
damage /= factor;
15268-
}
15269-
15270-
// Don't penalize much at all for hitting cargo
15271-
if (sip->class_type > -1) {
15272-
damage *= Ship_types[sip->class_type].ff_multiplier;
15273-
}
15249+
// wacky stuff here
15250+
if (pp->friendly_hits != 0) {
15251+
float time_since_last_hit = f2fl(Missiontime - pp->friendly_last_hit_time);
15252+
if ((time_since_last_hit >= 0.0f) && (time_since_last_hit < 10000.0f)) {
15253+
if (time_since_last_hit > 60.0f) {
15254+
pp->friendly_hits = 0;
15255+
pp->friendly_damage = 0.0f;
15256+
} else if (time_since_last_hit > 2.0f) {
15257+
pp->friendly_hits -= (int) time_since_last_hit/2;
15258+
pp->friendly_damage -= time_since_last_hit;
15259+
}
1527415260

15275-
// Hit ship, but not targeting it, so it's not so heinous, maybe an accident.
15276-
if (Ai_info[shipp_hitter->ai_index].target_objnum != OBJ_INDEX(objp_hit)) {
15277-
damage /= 5.0f;
15278-
}
15261+
if (pp->friendly_damage < 0.0f) {
15262+
pp->friendly_damage = 0.0f;
15263+
}
1527915264

15280-
pp->friendly_last_hit_time = Missiontime;
15281-
pp->friendly_hits++;
15265+
if (pp->friendly_hits < 0) {
15266+
pp->friendly_hits = 0;
15267+
}
15268+
}
15269+
}
1528215270

15283-
// cap damage and number of hits done this frame
15284-
float accredited_damage = MIN(MAX_BURST_DAMAGE, pp->damage_this_burst + damage) - pp->damage_this_burst;
15285-
pp->friendly_damage += accredited_damage;
15286-
pp->damage_this_burst += accredited_damage;
15271+
float damage; // Damage done by weapon. Gets scaled down based on size of ship.
1528715272

15288-
// Done with adjustments to damage. Evaluate based on current friendly_damage
15289-
nprintf(("AI", "Friendly damage: %.1f, threshold: %.1f, inc damage: %.1f, max burst: %d\n", pp->friendly_damage, FRIENDLY_DAMAGE_THRESHOLD * (1.0f + (float) (NUM_SKILL_LEVELS + 1 - Game_skill_level)/3.0f), pp->damage_this_burst, MAX_BURST_DAMAGE ));
15290-
15291-
if (is_instructor(objp_hit)) {
15292-
// it's not nice to hit your instructor
15293-
if (pp->friendly_damage > FRIENDLY_DAMAGE_THRESHOLD) {
15294-
message_send_builtin_to_player( MESSAGE_INSTRUCTOR_ATTACK, NULL, MESSAGE_PRIORITY_HIGH, MESSAGE_TIME_IMMEDIATE, 0, 0, -1, -1);
15295-
pp->last_warning_message_time = Missiontime;
15296-
ship_set_subsystem_strength( Player_ship, SUBSYSTEM_WEAPONS, 0.0f);
15273+
if (objp_weapon->type == OBJ_BEAM) // added beam for traitor detection -FUBAR
15274+
damage = beam_get_ship_damage(&Beams[objp_weapon->instance], objp_hit);
15275+
else
15276+
damage = Weapon_info[Weapons[objp_weapon->instance].weapon_info_index].damage;
15277+
15278+
// wacky stuff here
15279+
ship_info *sip = &Ship_info[Ships[objp_hit->instance].ship_info_index];
15280+
if (shipp_hit->ship_max_hull_strength > 1000.0f) {
15281+
float factor = shipp_hit->ship_max_hull_strength / 1000.0f;
15282+
factor = MIN(100.0f, factor);
15283+
damage /= factor;
15284+
}
1529715285

15298-
training_fail();
15286+
// Don't penalize much at all for hitting cargo
15287+
if (sip->class_type > -1) {
15288+
damage *= Ship_types[sip->class_type].ff_multiplier;
15289+
}
1529915290

15300-
// Instructor leaves.
15301-
mission_do_departure(objp_hit);
15302-
gameseq_post_event( GS_EVENT_PLAYER_WARPOUT_START_FORCED ); // Force player to warp out.
15303-
} else if (Missiontime - pp->last_warning_message_time > F1_0*4) {
15304-
// warning every 4 sec
15305-
// use NULL as the message sender here since it is the Terran Command persona
15306-
message_send_builtin_to_player( MESSAGE_INSTRUCTOR_HIT, NULL, MESSAGE_PRIORITY_HIGH, MESSAGE_TIME_IMMEDIATE, 0, 0, -1, -1);
15307-
pp->last_warning_message_time = Missiontime;
15291+
// Hit ship, but not targeting it, so it's not so heinous, maybe an accident.
15292+
if (Ai_info[shipp_hitter->ai_index].target_objnum != OBJ_INDEX(objp_hit)) {
15293+
damage /= 5.0f;
1530815294
}
1530915295

15310-
// not nice to hit your friends
15311-
} else if (pp->friendly_damage > FRIENDLY_DAMAGE_THRESHOLD * (1.0f + (float) (NUM_SKILL_LEVELS + 1 - Game_skill_level)/3.0f)) {
15312-
process_friendly_hit_message( MESSAGE_HAMMER_SWINE, objp_hit );
15313-
mission_goal_fail_all();
15314-
ai_abort_rearm_request( Player_obj );
15296+
pp->friendly_last_hit_time = Missiontime;
15297+
pp->friendly_hits++;
1531515298

15316-
Player_ship->team = Iff_traitor;
15299+
// cap damage and number of hits done this frame
15300+
float accredited_damage = MIN(MAX_BURST_DAMAGE, pp->damage_this_burst + damage) - pp->damage_this_burst;
15301+
pp->friendly_damage += accredited_damage;
15302+
pp->damage_this_burst += accredited_damage;
1531715303

15318-
} else if ((damage > frand()) && (Missiontime - pp->last_warning_message_time > F1_0*4) && (pp->friendly_damage > FRIENDLY_DAMAGE_THRESHOLD)) {
15319-
// no closer than 4 sec intervals
15320-
// Note: (damage > frand()) added on 12/9/97 by MK. Since damage is now scaled down for big ships, we could get too
15321-
// many warnings. Kind of tedious. frand() returns a value in 0..1, so this won't affect legit hits.
15322-
process_friendly_hit_message( MESSAGE_OOPS, objp_hit );
15323-
pp->last_warning_message_time = Missiontime;
15304+
// Done with adjustments to damage. Evaluate based on current friendly_damage
15305+
nprintf(("AI", "Friendly damage: %.1f, threshold: %.1f, inc damage: %.1f, max burst: %d\n", pp->friendly_damage, FRIENDLY_DAMAGE_THRESHOLD * (1.0f + (float) (NUM_SKILL_LEVELS + 1 - Game_skill_level)/3.0f), pp->damage_this_burst, MAX_BURST_DAMAGE ));
15306+
15307+
if (is_instructor(objp_hit)) {
15308+
// it's not nice to hit your instructor
15309+
if (pp->friendly_damage > FRIENDLY_DAMAGE_THRESHOLD) {
15310+
message_send_builtin_to_player( MESSAGE_INSTRUCTOR_ATTACK, NULL, MESSAGE_PRIORITY_HIGH, MESSAGE_TIME_IMMEDIATE, 0, 0, -1, -1);
15311+
pp->last_warning_message_time = Missiontime;
15312+
ship_set_subsystem_strength( Player_ship, SUBSYSTEM_WEAPONS, 0.0f);
15313+
15314+
training_fail();
15315+
15316+
// Instructor leaves.
15317+
mission_do_departure(objp_hit);
15318+
gameseq_post_event( GS_EVENT_PLAYER_WARPOUT_START_FORCED ); // Force player to warp out.
15319+
} else if (Missiontime - pp->last_warning_message_time > F1_0*4) {
15320+
// warning every 4 sec
15321+
// use NULL as the message sender here since it is the Terran Command persona
15322+
message_send_builtin_to_player( MESSAGE_INSTRUCTOR_HIT, NULL, MESSAGE_PRIORITY_HIGH, MESSAGE_TIME_IMMEDIATE, 0, 0, -1, -1);
15323+
pp->last_warning_message_time = Missiontime;
15324+
}
15325+
15326+
// not nice to hit your friends
15327+
} else if (pp->friendly_damage > FRIENDLY_DAMAGE_THRESHOLD * (1.0f + (float) (NUM_SKILL_LEVELS + 1 - Game_skill_level)/3.0f)) {
15328+
process_friendly_hit_message( MESSAGE_HAMMER_SWINE, objp_hit );
15329+
mission_goal_fail_all();
15330+
ai_abort_rearm_request( Player_obj );
15331+
15332+
Player_ship->team = Iff_traitor;
15333+
15334+
} else if ((damage > frand()) && (Missiontime - pp->last_warning_message_time > F1_0*4) && (pp->friendly_damage > FRIENDLY_DAMAGE_THRESHOLD)) {
15335+
// no closer than 4 sec intervals
15336+
// Note: (damage > frand()) added on 12/9/97 by MK. Since damage is now scaled down for big ships, we could get too
15337+
// many warnings. Kind of tedious. frand() returns a value in 0..1, so this won't affect legit hits.
15338+
process_friendly_hit_message( MESSAGE_OOPS, objp_hit );
15339+
pp->last_warning_message_time = Missiontime;
15340+
}
1532415341
}
1532515342
}
1532615343
}
@@ -15545,11 +15562,14 @@ void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hit_normal)
1554515562
return;
1554615563

1554715564
hitter_objnum = hit_objp->parent;
15548-
Assert((hitter_objnum >= 0) && (hitter_objnum < MAX_OBJECTS));
15565+
Assertion((hitter_objnum >= 0) && (hitter_objnum < MAX_OBJECTS), "hitter_objnum in this function is an invalid index of %d. This can cause random behavior, and is a coder mistake. Please report!", hitter_objnum);
1554915566
objp_hitter = &Objects[hitter_objnum];
1555015567

15568+
Assertion((objp_hitter->type == OBJ_SHIP) || (objp_hitter->type == OBJ_WEAPON) || (objp_hitter->type == OBJ_ASTEROID) || (objp_hitter->type == OBJ_BEAM) || (objp_hitter->type == OBJ_DEBRIS),
15569+
"The ai code is passing an invalid object type of %d to a function when trying to decide how to respond to something hitting it. This is a bug in the code, please report!", objp_hitter->type);
15570+
1555115571
// lets not check hits by ghosts any further either
15552-
if(objp_hitter->type == OBJ_GHOST)
15572+
if(objp_hitter->type != OBJ_SHIP && objp_hitter->type != OBJ_WEAPON && objp_hitter->type != OBJ_ASTEROID && objp_hitter->type != OBJ_BEAM && objp_hitter->type != OBJ_DEBRIS)
1555315573
return;
1555415574

1555515575
// Hit by a protected ship, don't attack it.
@@ -16147,6 +16167,12 @@ void maybe_cheat_fire_synaptic(object *objp)
1614716167
ship *shipp;
1614816168
int wing_index, time;
1614916169

16170+
Assertion(objp->type == OBJ_SHIP, "This ai function requires a ship, but was called with a non-ship object type of %d. Please report!", objp->type);
16171+
16172+
if (objp->type != OBJ_SHIP) {
16173+
return;
16174+
}
16175+
1615016176
shipp = &Ships[objp->instance];
1615116177

1615216178
if (!(strnicmp(shipp->ship_name, NOX("delta"), 5)))

code/hud/hudtarget.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1530,6 +1530,8 @@ void hud_target_missile(object *source_obj, int next_flag)
15301530
continue;
15311531
}
15321532

1533+
Assertion(Objects[so->objnum].type == OBJ_SHIP, "hud_target_missile was about to call obj_team with a non-ship obejct with type %d. Please report!", Objects[so->objnum].type);
1534+
15331535
// only allow targeting of hostile bombs
15341536
if (!iff_x_attacks_y(Player_ship->team, obj_team(A))) {
15351537
continue;

code/network/multi_ingame.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1785,7 +1785,7 @@ void multi_ingame_send_ship_update(net_player *p)
17851785
// go through the list and send all ships which are mark as OF_COULD_BE_PLAYER
17861786
while(moveup!=END_OF_LIST(&Ship_obj_list)){
17871787
//Make sure the object can be a player and is on the same team as this guy
1788-
if(Objects[moveup->objnum].flags[Object::Object_Flags::Could_be_player] && obj_team(&Objects[moveup->objnum]) == p->p_info.team){
1788+
if(Objects[moveup->objnum].flags[Object::Object_Flags::Could_be_player] && Objects[moveup->objnum].type == OBJ_SHIP && obj_team(&Objects[moveup->objnum]) == p->p_info.team){
17891789
// send the update
17901790
send_ingame_ship_update_packet(p,&Ships[Objects[moveup->objnum].instance]);
17911791
}

0 commit comments

Comments
 (0)