Harden FIFA17 SBC dispatch repair
This commit is contained in:
@@ -92,6 +92,7 @@ enum Rejection {
|
|||||||
ReaderMissing,
|
ReaderMissing,
|
||||||
ParseFailed,
|
ParseFailed,
|
||||||
ResponseClassMismatch,
|
ResponseClassMismatch,
|
||||||
|
ModelChanged,
|
||||||
ModelEmpty,
|
ModelEmpty,
|
||||||
NotifierNotCurrent,
|
NotifierNotCurrent,
|
||||||
ControllerMismatch,
|
ControllerMismatch,
|
||||||
@@ -118,6 +119,7 @@ struct DecisionInput {
|
|||||||
deserializer_thread: usize,
|
deserializer_thread: usize,
|
||||||
response_class_matches: bool,
|
response_class_matches: bool,
|
||||||
model: usize,
|
model: usize,
|
||||||
|
live_category_count: usize,
|
||||||
category_count: usize,
|
category_count: usize,
|
||||||
notifier_entries: u64,
|
notifier_entries: u64,
|
||||||
notifier_exits: u64,
|
notifier_exits: u64,
|
||||||
@@ -175,6 +177,9 @@ fn decide(input: DecisionInput) -> Result<Decision, Rejection> {
|
|||||||
if input.model == 0 || input.category_count == 0 || input.category_count == usize::MAX {
|
if input.model == 0 || input.category_count == 0 || input.category_count == usize::MAX {
|
||||||
return Err(Rejection::ModelEmpty);
|
return Err(Rejection::ModelEmpty);
|
||||||
}
|
}
|
||||||
|
if input.live_category_count != input.category_count {
|
||||||
|
return Err(Rejection::ModelChanged);
|
||||||
|
}
|
||||||
if input.notifier_entries != generation
|
if input.notifier_entries != generation
|
||||||
|| input.notifier_entries == 0
|
|| input.notifier_entries == 0
|
||||||
|| input.notifier_exits.checked_add(1) != Some(input.notifier_entries)
|
|| input.notifier_exits.checked_add(1) != Some(input.notifier_entries)
|
||||||
@@ -265,6 +270,12 @@ unsafe extern "system" fn completion_wrapper(
|
|||||||
|
|
||||||
let response_vtable = crate::sbc_trace::guarded_usize(evidence.deserializer_this);
|
let response_vtable = crate::sbc_trace::guarded_usize(evidence.deserializer_this);
|
||||||
let captured_controller = SBC_CONTROLLER.load(Ordering::Acquire);
|
let captured_controller = SBC_CONTROLLER.load(Ordering::Acquire);
|
||||||
|
let live_category_count = evidence
|
||||||
|
.model
|
||||||
|
.checked_add(0x50)
|
||||||
|
.and_then(|address| crate::sbc_trace::guarded_u16(address))
|
||||||
|
.map(usize::from)
|
||||||
|
.unwrap_or(usize::MAX);
|
||||||
let (controller_matches, controller_model_matches) =
|
let (controller_matches, controller_model_matches) =
|
||||||
controller_identity(evidence.base, captured_controller, evidence.model);
|
controller_identity(evidence.base, captured_controller, evidence.model);
|
||||||
let input = DecisionInput {
|
let input = DecisionInput {
|
||||||
@@ -287,6 +298,7 @@ unsafe extern "system" fn completion_wrapper(
|
|||||||
response_class_matches: response_vtable
|
response_class_matches: response_vtable
|
||||||
== evidence.base.checked_add(CATEGORY_RESPONSE_VTABLE_RVA),
|
== evidence.base.checked_add(CATEGORY_RESPONSE_VTABLE_RVA),
|
||||||
model: evidence.model,
|
model: evidence.model,
|
||||||
|
live_category_count,
|
||||||
category_count: evidence.category_count,
|
category_count: evidence.category_count,
|
||||||
notifier_entries: evidence.notifier_entries,
|
notifier_entries: evidence.notifier_entries,
|
||||||
notifier_exits: evidence.notifier_exits,
|
notifier_exits: evidence.notifier_exits,
|
||||||
@@ -676,6 +688,7 @@ mod tests {
|
|||||||
deserializer_thread: 7,
|
deserializer_thread: 7,
|
||||||
response_class_matches: true,
|
response_class_matches: true,
|
||||||
model: 0x4000,
|
model: 0x4000,
|
||||||
|
live_category_count: 2,
|
||||||
category_count: 2,
|
category_count: 2,
|
||||||
notifier_entries: generation,
|
notifier_entries: generation,
|
||||||
notifier_exits: generation - 1,
|
notifier_exits: generation - 1,
|
||||||
@@ -731,6 +744,10 @@ mod tests {
|
|||||||
let mut input = valid_input(1);
|
let mut input = valid_input(1);
|
||||||
input.controller_model_matches = false;
|
input.controller_model_matches = false;
|
||||||
assert_eq!(decide(input), Err(Rejection::ControllerModelMismatch));
|
assert_eq!(decide(input), Err(Rejection::ControllerModelMismatch));
|
||||||
|
|
||||||
|
let mut input = valid_input(1);
|
||||||
|
input.live_category_count = 0;
|
||||||
|
assert_eq!(decide(input), Err(Rejection::ModelChanged));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Reference in New Issue
Block a user