From ad8f6cce43502be793855b2c594ac16b42aa4069 Mon Sep 17 00:00:00 2001 From: chairmanpow Date: Wed, 7 Oct 2026 00:20:23 +0100 Subject: [PATCH] ui: GetWhoInfo answers a 0 level on a miss, so GetDifficultyColor cannot raise A who-list miss pushed six nils, but the reference shape is (nil,nil,number,nil,nil,nil): the level of an empty who slot is 0. ShaguTweaks colors every WhoList_Update slot and calls GetDifficultyColor(level) unguarded, which does level - UnitLevel("player") and raised on the nil. --- crates/benilla-ui/src/script/social.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/crates/benilla-ui/src/script/social.rs b/crates/benilla-ui/src/script/social.rs index 0e80379c..d51b0abb 100644 --- a/crates/benilla-ui/src/script/social.rs +++ b/crates/benilla-ui/src/script/social.rs @@ -380,10 +380,13 @@ pub(super) fn install(lua: &Lua) -> mlua::Result<()> { .ok() .and_then(|i| model.social.who.get(i)); let Some(row) = row else { + // A miss still pushes six values with a NUMBER level (`1.12-shapes.tsv`: + // `(nil,nil,number,nil,nil,nil)`). An empty who slot reads level 0, and callers + // like `GetDifficultyColor(level)` do arithmetic on it unguarded. return Ok(( Value::Nil, Value::Nil, - Value::Nil, + Value::Integer(0), Value::Nil, Value::Nil, Value::Nil, @@ -483,6 +486,22 @@ mod tests { } } + /// A miss still answers six values with a NUMBER level (`1.12-shapes.tsv`: + /// `(nil,nil,number,nil,nil,nil)`), so an unguarded `GetDifficultyColor(level)` over the empty + /// slots of the who list does not raise. + #[test] + fn a_who_miss_answers_six_values_with_a_number_level() { + let mut s = UiScript::new().unwrap(); + s.set_social(SocialState::default()); + let got = s + .eval::<(bool, bool, i64, bool, bool, bool)>( + "local a,b,c,d,e,f = GetWhoInfo(1) \ + return a == nil, b == nil, c, d == nil, e == nil, f == nil", + ) + .unwrap(); + assert_eq!(got, (true, true, 0, true, true, true)); + } + /// Two `/who` hits and a `WHO_LIST_UPDATE` handler that records the order it sees. fn seated() -> UiScript { let mut s = UiScript::new().unwrap();