CTD using GetSpellNameByID

A forum for reporting bugs NOT related to custom plugins.

Moderator: MacroQuest Developers

Zoydburg
a lesser mummy
a lesser mummy
Posts: 34
Joined: Wed Jul 21, 2004 3:30 am

CTD using GetSpellNameByID

Post by Zoydburg » Fri Oct 01, 2004 3:53 am

This happens when you try to use GetSpellNameByID() with an epmty spell Gem

Output wrote: First-chance exception at 0x01717cb7 (MQ2Main.dll) in eqgame.exe: 0xC0000005: Access violation reading location 0x4152a7d4.
Call Stack wrote: > MQ2Main.dll!GetSpellNameByID(unsigned long dwSpellID=4294967295) Line 866 C++
Locals wrote: dwSpellID 4294967295 unsigned long
MQ2Utilities.cpp

Code: Select all

PCHAR GetSpellNameByID(DWORD dwSpellID)
{
    PSPELL pSpell = NULL;
    if (ppSpellMgr == NULL) return "Unknown Spell";
    pSpell =  &(*((PSPELLMGR)pSpellMgr)->Spells[dwSpellID]);
    if (pSpell != NULL) {
>>        if (pSpell->Name != NULL) {
            if (pSpell->Name[0]!='\0') {
                return pSpell->Name;
            }
        }
    }
    return "Unknown Spell";
}

Zoydburg
a lesser mummy
a lesser mummy
Posts: 34
Joined: Wed Jul 21, 2004 3:30 am

Post by Zoydburg » Fri Oct 01, 2004 4:19 am

Also get a CTD using GetSpellByID() and a blank spell slot
Output wrote: First-chance exception at 0x0340121c in eqgame.exe: 0xC0000005: Access violation reading location 0x00000210.
Call Stack wrote: > MQ2SpellSet.dll!0340121c()
Disasembaly wrote: 03401218 jmp 0340121C
0340121A xor eax,eax
>0340121C mov edx,dword ptr [eax+210h]
03401222 push esi
03401223 push edx
03401224 lea eax,[esp+1018h]
code that calls GetSpellByID()

Code: Select all

VOID MemSpellSet(PSPAWNINFO pChar, PCHAR szLine)
{
   for (i=1; i<=9; i++)
   {
	  PSPELL pSpell=GetSpellByID(GetCharInfo()->MemorizedSpells[i-1]);

		sprintf(szMsg,"Spell %s goes in Gem %d",pSpell->Name, i);
		WriteChatColor(szMsg,USERCOLOR_CHAT_CHANNEL);
   }
}

Amadeus
The Maestro
The Maestro
Posts: 2036
Joined: Sat Jun 29, 2002 3:51 pm

Post by Amadeus » Fri Oct 01, 2004 9:15 am

What's the syntax of the macro you're using to get this error? I'm not sure I'm following on how you're creating this bug.

Zoydburg
a lesser mummy
a lesser mummy
Posts: 34
Joined: Wed Jul 21, 2004 3:30 am

Post by Zoydburg » Fri Oct 01, 2004 4:38 pm

Not a macro its a plugin and anytime I use either the GetSpellByID() or GetSpellNameByID() and the spell slot I am searching is blank it CTD's

Code: Select all

GetCharInfo()->MemorizedSpells[i-1]
Returns a -1 if the spell slot it is searching is empty

I tried

Code: Select all

VOID MemSpellSet(PSPAWNINFO pChar, PCHAR szLine)
{
   for (i=1; i<=9; i++)
   {
     PSPELL pSpell=GetSpellByID(GetCharInfo()->MemorizedSpells[i-1]);

      sprintf(szMsg,"Spell %s goes in Gem %d",pSpell->Name, i);
      WriteChatColor(szMsg,USERCOLOR_CHAT_CHANNEL);
   }
}
and

Code: Select all

VOID MemSpellSet(PSPAWNINFO pChar, PCHAR szLine)
{
   CHAR szSpellName[MAX_STRING] = {0};
   for (i=1; i<=9; i++)
   {
     sprintf(szSpellname,"%s",GetSpellNameByID(GetCharInfo()->MemorizedSpells[i-1]));

      sprintf(szMsg,"Spell %s goes in Gem %d",szSpellName, i);
      WriteChatColor(szMsg,USERCOLOR_CHAT_CHANNEL);
   }
}


Posible fix for GetSpellNameByID, I have not tested it but looking at the code this looks like it will fix it

Code: Select all

PCHAR GetSpellNameByID(DWORD dwSpellID)
{
    if(dwSpellID == -1) return "Unknown Spell";
    PSPELL pSpell = NULL;
    if (ppSpellMgr == NULL) return "Unknown Spell";
    pSpell =  &(*((PSPELLMGR)pSpellMgr)->Spells[dwSpellID]);
    if (pSpell != NULL) {
        if (pSpell->Name != NULL) {
            if (pSpell->Name[0]!='\0') {
                return pSpell->Name;
            }
        }
    }
    return "Unknown Spell";
}
Last edited by Zoydburg on Fri Oct 01, 2004 4:45 pm, edited 1 time in total.

User avatar
dont_know_at_all
Developer
Developer
Posts: 5450
Joined: Sun Dec 01, 2002 4:15 am
Location: Florida, USA
Contact:

Post by dont_know_at_all » Fri Oct 01, 2004 4:40 pm

Zoydburg wrote:Not a macro its a plugin and anytime I use either the GetSpellByID() or GetSpellNameByID() and the spell slot I am searching is blank it CTD's
Well, duh. Check for a blank one.

Zoydburg
a lesser mummy
a lesser mummy
Posts: 34
Joined: Wed Jul 21, 2004 3:30 am

Post by Zoydburg » Fri Oct 01, 2004 4:49 pm

Yes DKAA I did that, but it still should not CTD if someone does not do that it should return Unknown Spell or NULL or something.

User avatar
dont_know_at_all
Developer
Developer
Posts: 5450
Joined: Sun Dec 01, 2002 4:15 am
Location: Florida, USA
Contact:

Post by dont_know_at_all » Fri Oct 01, 2004 4:58 pm

Please use macros and not plugins.

Zoydburg
a lesser mummy
a lesser mummy
Posts: 34
Joined: Wed Jul 21, 2004 3:30 am

Post by Zoydburg » Fri Oct 01, 2004 5:02 pm

I was trying to update Digitalxero's MQ2SpellSet when I found this BUG. Though it looks like he updated it lastnight at the same time I was playing with it.

User avatar
dont_know_at_all
Developer
Developer
Posts: 5450
Joined: Sun Dec 01, 2002 4:15 am
Location: Florida, USA
Contact:

Post by dont_know_at_all » Fri Oct 01, 2004 5:19 pm

Your crash is not a bug.

If you are going to call functions with the wrong data, you're going to get crashes. We have no way of determining if the spell id is valid or not. YOU have to check MemorizedSpells before you use it. It's not guarranteed to be a valid spell ID.

Amadeus
The Maestro
The Maestro
Posts: 2036
Joined: Sat Jun 29, 2002 3:51 pm

Post by Amadeus » Fri Oct 01, 2004 6:22 pm

Yes, a plugin has to be coded correctly and has to have the check in the plugin's code. The plugin should verify that the spell gem and/or the spell id is valid before it calls the function.