Page 1 of 1

CTD on ${MacroQuest.LastCommand}

Posted: Fri Apr 23, 2004 5:53 pm
by tonio
I /echo'ed ${MacroQuest.LastCommand} and CTD'd. I hadn't entered any commands before that one (mebbe that's the problem).

Call Stack:

Code: Select all

>	MQ2Main.dll!memmove(unsigned char * dst=0x00130005, unsigned char * src=0x0012ffff, unsigned long count=1)  Line 333	Asm
 	MQ2Main.dll!ParseMacroData(char * szOriginal=0x00130005)  Line 707	C++
 	MQ2Main.dll!ParseMacroParameter(EQData::_SPAWNINFO * pChar=0x06b222c0, char * szOriginal=0x0012ae80)  Line 434	C++
 	MQ2Main.dll!CCommandHook::Detour(EQData::_SPAWNINFO * pChar=0x00130005, char * szFullLine=0x0012ffff)  Line 177 + 0xe	C++
 	652f206f()	
Pertinent debug spew:

Code: Select all

[MQ2]CCommandHook::Detour(/echo ${MacroQuest.LastCommand})
First-chance exception at 0x030382c6 (MQ2Main.dll) in eqgame.exe: 0xC0000005: Access violation writing location 0x00130005.
Disassembly:

Code: Select all

    TrailUp1:
            mov     al,[esi]        ;U - get byte from source
    030382C4  mov         al,byte ptr [esi] 
                                    ;V - spare
            mov     [edi],al        ;U - put byte in destination
[color=yellow]-->[/color] 030382C6  mov         byte ptr [edi],al 
            mov     eax,[dst]       ;V - return pointer to destination
    030382C8  mov         eax,dword ptr [dst] 
            pop     esi             ;U - restore esi
    030382CB  pop         esi  
            pop     edi             ;V - restore edi
    030382CC  pop         edi  
            M_EXIT
    030382CD  leave            
    030382CE  ret              
    030382CF  nop 
As far as I can tell, the source file seems to be "memcpy.asm", which doesn't sound right, but that's where the disassembly code was.

Posted: Fri Apr 23, 2004 5:58 pm
by dont_know_at_all
Congratulations. You are the first person to successfully follow the directions for posting all the data needed to fix a bug.

Uh, it looks like there was some data corruption somewhere unrelaed to this command. Is this problem reproducible? What was the last command?

Posted: Fri Apr 23, 2004 6:02 pm
by Imperfect
dont_know_at_all wrote:Congratulations. You are the first person to successfully follow the directions for posting all the data needed to fix a bug.

This will be fixed shortly.
Second person :)

Posted: Fri Apr 23, 2004 7:24 pm
by tonio
Ok, got more info (thanks Lax!)...

Source file: mq2dataapi.cpp
Line: 707
(Line in red)

Code: Select all

BOOL ParseMacroData(PCHAR szOriginal)
{
	// find each {}
	PCHAR pBrace=strstr(szOriginal,"${");
	if (!pBrace)
		return false;
	unsigned long NewLength;
	BOOL Changed=false;
//	PCHAR pPos;
//	PCHAR pStart;
//	PCHAR pIndex;
	CHAR szCurrent[MAX_STRING]={0};

	do
	{
		// find this brace's end
		PCHAR pEnd=&pBrace[1];
		BOOL Quote=false;

		int nBrace=1;
		while(nBrace)
		{
			++pEnd;
			if (*pEnd==0)
			{// unmatched brace or quote
				goto pmdbottom;
			}
			if (*pEnd=='}')
			{
				if (!Quote)
					nBrace--;
			}
			else if (*pEnd=='{')
			{
				if (!Quote)
					nBrace++;
			}
			else if (*pEnd=='\"')
			{
				Quote=!Quote;
			}
		}
		*pEnd=0;
		strcpy(szCurrent,&pBrace[2]);
		if (szCurrent[0]==0)
		{
			goto pmdbottom;
		}
		if (ParseMacroData(szCurrent))
		{
			unsigned long NewLength=strlen(szCurrent);
			memmove(&pBrace[NewLength+1],&pEnd[1],strlen(&pEnd[1])+1);
			strncpy(pBrace,szCurrent,NewLength);
			pEnd=&pBrace[NewLength];
			*pEnd=0;
		}

		MQ2TYPEVAR Result;
		if (ParseMQ2DataPortion(szCurrent,Result))
			Result.Type->ToString(Result.VarPtr,szCurrent);
		else
			strcpy(szCurrent,"NULL");

		NewLength=strlen(szCurrent);

		memmove(&pBrace[NewLength],&pEnd[1],strlen(&pEnd[1])+1);
		[color=red]strncpy(pBrace,szCurrent,NewLength);[/color]
		Changed=true;

pmdbottom:;
	} while (pBrace=strstr(&pBrace[1],"${"));
	return Changed;
}
Also re-tested, issuing commands before /echo'ing ${MacroQuest.LastCommand}, and still CTD'd at the same line.

Hope that helps!

Posted: Fri Apr 23, 2004 7:41 pm
by Lax
no worries, now that login is working again i'm testing it and getting the same output you are. i'll get it fixed ;)

Posted: Fri Apr 23, 2004 7:54 pm
by Lax
k heres the problem

In the current zip, the "last command" gets set before you actually execute your current one. In other words, the "last command" was:
/echo ${MacroQuest.LastCommand}

Now... put that through the MQ2Data parser, you get:
/echo /echo ${MacroQuest.LastCommand}
And it doesnt stop because it sees another ${
/echo /echo /echo ${MacroQuest.LastCommand}
/echo /echo /echo /echo ${MacroQuest.LastCommand}
... continue until the buffer overflows.

Unfortunately theres no good way to remove that, so next zip it'll work correctly, but you'll have to make sure your previous command did not involve ${MacroQuest.LastCommand} :lol: