Skip to content

Commit

Permalink
Patches out the latest BRPED remote bombing exploit. (tgstation#62447)
Browse files Browse the repository at this point in the history
Reagent containers in BRPEDs can no longer have reagents inserted into them.

Does this by adding a signal for pre-reagent adding that accepts a cancel flag, which will stop the reagents being added.

Transferring reagents to things now actually checks the return value of add_reagent to stop people pouring chems that weren't added into the ether.
  • Loading branch information
Timberpoes authored Oct 31, 2021
1 parent f54ef74 commit d020e9e
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 6 deletions.
4 changes: 4 additions & 0 deletions code/__DEFINES/dcs/signals.dm
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,10 @@
///from base of [/datum/controller/subsystem/materials/proc/InitializeMaterial]: (/datum/material)
#define COMSIG_MATERIALS_INIT_MAT "SSmaterials_init_mat"

///from base of [/datum/reagents/proc/add_reagent] - Sent before the reagent is added: (reagenttype, amount, reagtemp, data, no_react)
#define COMSIG_REAGENTS_PRE_ADD_REAGENT "reagents_pre_add_reagent"
/// Prevents the reagent from being added.
#define COMPONENT_CANCEL_REAGENT_ADD (1<<0)
///from base of [/datum/reagents/proc/add_reagent]: (/datum/reagent, amount, reagtemp, data, no_react)
#define COMSIG_REAGENTS_NEW_REAGENT "reagents_new_reagent"
///from base of [/datum/reagents/proc/add_reagent]: (/datum/reagent, amount, reagtemp, data, no_react)
Expand Down
9 changes: 7 additions & 2 deletions code/modules/reagents/chemistry/holder.dm
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,9 @@
if(amount <= CHEMICAL_QUANTISATION_LEVEL)//To prevent small amount problems.
return FALSE

if(SEND_SIGNAL(src, COMSIG_REAGENTS_PRE_ADD_REAGENT, reagent, amount, reagtemp, data, no_react) & COMPONENT_CANCEL_REAGENT_ADD)
return FALSE

var/datum/reagent/glob_reagent = GLOB.chemical_reagents_list[reagent]
if(!glob_reagent)
stack_trace("[my_atom] attempted to add a reagent called '[reagent]' which doesn't exist. ([usr])")
Expand Down Expand Up @@ -481,7 +484,8 @@
trans_data = copy_data(reagent)
if(reagent.intercept_reagents_transfer(R, cached_amount))//Use input amount instead.
continue
R.add_reagent(reagent.type, transfer_amount * multiplier, trans_data, chem_temp, reagent.purity, reagent.ph, no_react = TRUE, ignore_splitting = reagent.chemical_flags & REAGENT_DONOTSPLIT) //we only handle reaction after every reagent has been transfered.
if(!R.add_reagent(reagent.type, transfer_amount * multiplier, trans_data, chem_temp, reagent.purity, reagent.ph, no_react = TRUE, ignore_splitting = reagent.chemical_flags & REAGENT_DONOTSPLIT)) //we only handle reaction after every reagent has been transfered.
continue
if(methods)
if(istype(target_atom, /obj/item/organ))
R.expose_single(reagent, target, methods, part, show_message)
Expand All @@ -506,7 +510,8 @@
transfer_amount = reagent.volume
if(reagent.intercept_reagents_transfer(R, cached_amount))//Use input amount instead.
continue
R.add_reagent(reagent.type, transfer_amount * multiplier, trans_data, chem_temp, reagent.purity, reagent.ph, no_react = TRUE, ignore_splitting = reagent.chemical_flags & REAGENT_DONOTSPLIT) //we only handle reaction after every reagent has been transfered.
if(!R.add_reagent(reagent.type, transfer_amount * multiplier, trans_data, chem_temp, reagent.purity, reagent.ph, no_react = TRUE, ignore_splitting = reagent.chemical_flags & REAGENT_DONOTSPLIT)) //we only handle reaction after every reagent has been transfered.
continue
to_transfer = max(to_transfer - transfer_amount , 0)
if(methods)
if(istype(target_atom, /obj/item/organ))
Expand Down
47 changes: 43 additions & 4 deletions code/modules/research/stock_parts.dm
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,25 @@ If you create T5+ please take a pass at mech_fabricator.dm. The parts being good
. = ..()

RegisterSignal(src, COMSIG_ATOM_ENTERED, .proc/on_part_entered)

RegisterSignal(src, COMSIG_ATOM_EXITED, .proc/on_part_exited)

/**
* Signal handler for when a part has been inserted into the BRPED.
*
* If the inserted item is a rigged or corrupted cell, does some logging.
*
* If it has a reagent holder, clears the reagents and registers signals to prevent new
* reagents being added and registers clean up signals on inserted item's removal from
* the BRPED.
*/
/obj/item/storage/part_replacer/bluespace/proc/on_part_entered(datum/source, obj/item/inserted_component)
SIGNAL_HANDLER
if(inserted_component.reagents && length(inserted_component.reagents.reagent_list))
inserted_component.reagents.clear_reagents()
to_chat(usr, span_notice("[src] churns as [inserted_component] has its reagents emptied into bluespace."))
if(inserted_component.reagents)
if(length(inserted_component.reagents.reagent_list))
inserted_component.reagents.clear_reagents()
to_chat(usr, span_notice("[src] churns as [inserted_component] has its reagents emptied into bluespace."))
RegisterSignal(inserted_component.reagents, COMSIG_REAGENTS_PRE_ADD_REAGENT, .proc/on_insered_component_reagent_pre_add)


if(!istype(inserted_component, /obj/item/stock_parts/cell))
return
Expand All @@ -72,6 +85,32 @@ If you create T5+ please take a pass at mech_fabricator.dm. The parts being good
log_game("[key_name(usr)] has inserted rigged/corrupted [inserted_cell] into [src].")
usr.log_message("inserted rigged/corrupted [inserted_cell] into [src]", LOG_ATTACK)

/**
* Signal handler for when the reagents datum of an inserted part has reagents added to it.
*
* Registers the PRE_ADD variant which allows the signal handler to stop reagents being
* added.
*
* Simply returns COMPONENT_CANCEL_REAGENT_ADD. We never want to allow people to add
* reagents to beakers in BRPEDs as they can then be used for spammable remote bombing.
*/
/obj/item/storage/part_replacer/bluespace/proc/on_insered_component_reagent_pre_add(datum/source, reagent, amount, reagtemp, data, no_react)
SIGNAL_HANDLER

return COMPONENT_CANCEL_REAGENT_ADD

/**
* Signal handler for a part is removed from the BRPED.
*
* Does signal registration cleanup on its reagents, if it has any.
*/
/obj/item/storage/part_replacer/bluespace/proc/on_part_exited(datum/source, obj/item/removed_component)
SIGNAL_HANDLER

if(removed_component.reagents)
UnregisterSignal(removed_component.reagents, COMSIG_REAGENTS_PRE_ADD_REAGENT)


/obj/item/storage/part_replacer/bluespace/tier1

/obj/item/storage/part_replacer/bluespace/tier1/PopulateContents()
Expand Down

0 comments on commit d020e9e

Please sign in to comment.