From 1e5bc723669138e097e45c0a68e18699959273ec Mon Sep 17 00:00:00 2001 From: Vorspire Date: Tue, 21 Jul 2015 00:45:43 +0100 Subject: [PATCH] Infinite Loop Breakout There is a very rare potential, mostly in custom situations, for the 'BaseRunicTool' 'ApplySkillBonus' method to cause the server to become unresponsive. The reason for this is that, if you call the method on a 'Spellbook' which already has all 4 of the skills listed by default in 'm_PossibleSpellbookSkills', then 'found' is always true. This issue has been reproduced on a shard that calls 'ApplySkillBonus' more than once when crafting 'Spellbooks'; the rarity is that the 'ApplyAttributesTo' method may call the 'ApplySkillBonus' more than once; the off-chance of 5 consecutive calls, where each preceding call applies one unique skill of the 'possibleSkills', would result in the 5th call entering the deadlock state. The fix is quite simple, evaluate the 'count' in the while statement and decrement it for each skill that is checked; removing each skill from the 'possibleSkills' list as they are checked, to prevent them being checked multiple times due to the random indices selection. --- Scripts/Items/Skill Items/Tools/BaseRunicTool.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Scripts/Items/Skill Items/Tools/BaseRunicTool.cs b/Scripts/Items/Skill Items/Tools/BaseRunicTool.cs index ba258ffa5..53815a788 100644 --- a/Scripts/Items/Skill Items/Tools/BaseRunicTool.cs +++ b/Scripts/Items/Skill Items/Tools/BaseRunicTool.cs @@ -1,5 +1,6 @@ using System; using System.Collections; +using System.Collections.Generic; namespace Server.Items { @@ -180,7 +181,7 @@ namespace Server.Items private static void ApplySkillBonus( AosSkillBonuses attrs, int min, int max, int index, int low, int high ) { - SkillName[] possibleSkills = ( attrs.Owner is Spellbook ? m_PossibleSpellbookSkills : m_PossibleBonusSkills ); + List possibleSkills = new List( attrs.Owner is Spellbook ? m_PossibleSpellbookSkills : m_PossibleBonusSkills ); int count = ( Core.SE ? possibleSkills.Length : possibleSkills.Length - 2 ); SkillName sk, check; @@ -190,11 +191,12 @@ namespace Server.Items do { found = false; - sk = possibleSkills[Utility.Random( count )]; + sk = possibleSkills[Utility.Random( count-- )]; + possibleSkills.Remove(sk); for ( int i = 0; !found && i < 5; ++i ) found = ( attrs.GetValues( i, out check, out bonus ) && check == sk ); - } while ( found ); + } while ( found && count > 0 ); attrs.SetValues( index, sk, Scale( min, max, low, high ) ); } @@ -685,4 +687,4 @@ namespace Server.Items } } } -} \ No newline at end of file +}