diff --git a/src/CommandFormats.hh b/src/CommandFormats.hh index 83708a11..90df6435 100644 --- a/src/CommandFormats.hh +++ b/src/CommandFormats.hh @@ -4425,22 +4425,18 @@ struct G_CastTechniqueComplete_6x48 { le_uint16_t level = 0; } __packed_ws__(G_CastTechniqueComplete_6x48, 8); -// 6x49: Subtract photon blast energy (protected on V3/V4) +// 6x49: Execute Photon Blast (protected on V3/V4) -struct G_SubtractPBEnergy_6x49 { +struct G_ExecutePhotonBlast_6x49 { G_ClientIDHeader header; uint8_t unknown_a1 = 0; uint8_t unknown_a2 = 0; - le_uint16_t entry_count = 0; + le_uint16_t target_count = 0; le_uint16_t unknown_a3 = 0; le_uint16_t unknown_a4 = 0; - struct Entry { - le_uint16_t unknown_a1 = 0; - le_uint16_t unknown_a2 = 0; - } __packed_ws__(Entry, 4); // The client may send a shorter command if not all of these are used. - parray entries; -} __packed_ws__(G_SubtractPBEnergy_6x49, 0x34); + parray targets; +} __packed_ws__(G_ExecutePhotonBlast_6x49, 0x34); // 6x4A: Fully shield attack (protected on V3/V4) diff --git a/src/ProxyCommands.cc b/src/ProxyCommands.cc index c6bad4bb..5b487898 100644 --- a/src/ProxyCommands.cc +++ b/src/ProxyCommands.cc @@ -1122,8 +1122,7 @@ static HandlerResult S_6x(shared_ptr ses, uint16_t, const auto& cmd = check_size_t(data, offsetof(G_AttackFinished_6x46, targets), sizeof(G_AttackFinished_6x46)); - size_t allowed_count = min(cmd.header.size - 2, 11); - if (cmd.count > allowed_count) { + if (cmd.count > min(cmd.header.size - 2, cmd.targets.size())) { ses->log.warning("Blocking subcommand 6x46 with invalid count"); return HandlerResult::Type::SUPPRESS; } @@ -1131,17 +1130,15 @@ static HandlerResult S_6x(shared_ptr ses, uint16_t, const auto& cmd = check_size_t(data, offsetof(G_CastTechnique_6x47, targets), sizeof(G_CastTechnique_6x47)); - size_t allowed_count = min(cmd.header.size - 2, 10); - if (cmd.target_count > allowed_count) { + if (cmd.target_count > min(cmd.header.size - 2, cmd.targets.size())) { ses->log.warning("Blocking subcommand 6x47 with invalid count"); return HandlerResult::Type::SUPPRESS; } } else if (data[0] == 0x49) { - const auto& cmd = check_size_t(data, - offsetof(G_SubtractPBEnergy_6x49, entries), - sizeof(G_SubtractPBEnergy_6x49)); - size_t allowed_count = min(cmd.header.size - 3, 14); - if (cmd.entry_count > allowed_count) { + const auto& cmd = check_size_t(data, + offsetof(G_ExecutePhotonBlast_6x49, targets), + sizeof(G_ExecutePhotonBlast_6x49)); + if (cmd.target_count > min(cmd.header.size - 3, cmd.targets.size())) { ses->log.warning("Blocking subcommand 6x49 with invalid count"); return HandlerResult::Type::SUPPRESS; } diff --git a/src/ReceiveSubcommands.cc b/src/ReceiveSubcommands.cc index d4e489a9..0f55a4f2 100644 --- a/src/ReceiveSubcommands.cc +++ b/src/ReceiveSubcommands.cc @@ -1497,8 +1497,7 @@ static void on_cast_technique_finished(shared_ptr c, uint8_t command, ui static void on_attack_finished(shared_ptr c, uint8_t command, uint8_t flag, void* data, size_t size) { const auto& cmd = check_size_t(data, size, offsetof(G_AttackFinished_6x46, targets), sizeof(G_AttackFinished_6x46)); - size_t allowed_count = min(cmd.header.size - 2, 11); - if (cmd.count > allowed_count) { + if (cmd.count > min(cmd.header.size - 2, cmd.targets.size())) { throw runtime_error("invalid attack finished command"); } on_forward_check_game_client(c, command, flag, data, size); @@ -1507,18 +1506,16 @@ static void on_attack_finished(shared_ptr c, uint8_t command, uint8_t fl static void on_cast_technique(shared_ptr c, uint8_t command, uint8_t flag, void* data, size_t size) { const auto& cmd = check_size_t(data, size, offsetof(G_CastTechnique_6x47, targets), sizeof(G_CastTechnique_6x47)); - size_t allowed_count = min(cmd.header.size - 2, 10); - if (cmd.target_count > allowed_count) { + if (cmd.target_count > min(cmd.header.size - 2, cmd.targets.size())) { throw runtime_error("invalid cast technique command"); } on_forward_check_game_client(c, command, flag, data, size); } -static void on_subtract_pb_energy(shared_ptr c, uint8_t command, uint8_t flag, void* data, size_t size) { - const auto& cmd = check_size_t(data, size, - offsetof(G_SubtractPBEnergy_6x49, entries), sizeof(G_SubtractPBEnergy_6x49)); - size_t allowed_count = min(cmd.header.size - 3, 14); - if (cmd.entry_count > allowed_count) { +static void on_execute_photon_blast(shared_ptr c, uint8_t command, uint8_t flag, void* data, size_t size) { + const auto& cmd = check_size_t(data, size, + offsetof(G_ExecutePhotonBlast_6x49, targets), sizeof(G_ExecutePhotonBlast_6x49)); + if (cmd.target_count > min(cmd.header.size - 3, cmd.targets.size())) { throw runtime_error("invalid subtract PB energy command"); } on_forward_check_game_client(c, command, flag, data, size); @@ -4479,7 +4476,7 @@ const SubcommandDefinition subcommand_definitions[0x100] = { /* 6x46 */ {0x00, 0x42, 0x46, on_attack_finished}, /* 6x47 */ {0x3D, 0x43, 0x47, on_cast_technique}, /* 6x48 */ {0x00, 0x00, 0x48, on_cast_technique_finished}, - /* 6x49 */ {0x3E, 0x44, 0x49, on_subtract_pb_energy}, + /* 6x49 */ {0x3E, 0x44, 0x49, on_execute_photon_blast}, /* 6x4A */ {0x3F, 0x45, 0x4A, on_forward_check_game_client}, /* 6x4B */ {0x40, 0x46, 0x4B, on_change_hp}, /* 6x4C */ {0x41, 0x47, 0x4C, on_change_hp},