View previous topic :: View next topic |
Author |
Message |
zzqzzq_zzq
Joined: 23 Feb 2008 Posts: 11
|
Posted: Mon Feb 25, 2008 21:57 Post subject: NWNX2 2.7b3 free(): invalid pointer |
|
|
So,
I've been poking around in the NWNX code for some fellows who've been trying to build themselves a persistent world.
And the server's been dying upon module entry by any characters with:
*** glibc detected *** ./nwserver: free(): invalid pointer: 0xb7fb91a0 ***
Poking through the code, on line 219, in nwnx2lib.c, there's this line:
if(strncmp(library,"LETO",4)!=0) free(pRes); //an exception for Leto
Umm, is that really what you want to do? (I notice the 2.5.3rc1 code does NOT do this)
pRes is the return value from the various plugin's OnRequest() routine, and doesn't necessarily look like its a dynamically allocated return value. In some cases (Profiler) its even NULL, now I know free(NULL)'ing is bad ju-ju.....
Anyone got any thoughts, or shall I just go back to 2.5.3rc1?
Thx,
David |
|
Back to top |
|
|
virusman
Joined: 30 Jan 2005 Posts: 1020 Location: Russia
|
Posted: Mon Feb 25, 2008 23:47 Post subject: |
|
|
Generally, if a plugin doesn't allocate memory, it returns NULL.
I had to add exceptions for some plugins that don't do that and return pointers to static memory. That's why it's still beta.
What plugins do you use? |
|
Back to top |
|
|
zzqzzq_zzq
Joined: 23 Feb 2008 Posts: 11
|
Posted: Tue Feb 26, 2008 1:00 Post subject: |
|
|
Ah, yeah, I see the NULL check above..(Yeah, I have to admit to being a little blind on occasion.)
I haven't gone through and figured out which plugin's the developers are wanting to use, I'm just trying to build all I can.
I'll run through and audit everything I'm building and report back any others I find, but:
nwnx_chat-0.3.2-linux.rar
Is returning the address of listIDs, which is statically allocated.
I'll probably also recommend the folks I'm helping go back to 2.5.3rc1 for the persistent world they're developing.
David |
|
Back to top |
|
|
virusman
Joined: 30 Jan 2005 Posts: 1020 Location: Russia
|
|
Back to top |
|
|
zzqzzq_zzq
Joined: 23 Feb 2008 Posts: 11
|
Posted: Tue Feb 26, 2008 13:52 Post subject: |
|
|
Source?
|
|
Back to top |
|
|
zzqzzq_zzq
Joined: 23 Feb 2008 Posts: 11
|
Posted: Thu Feb 28, 2008 14:02 Post subject: |
|
|
FWIW,
That version didn't work either. It'd crash as soon as anyone said anything, down inside of RunScript(). (Looked like stack corruption.)
We finally gave up, and got the binary NWNX modules distributed with SimTools 3.1 to (apparently) work. |
|
Back to top |
|
|
virusman
Joined: 30 Jan 2005 Posts: 1020 Location: Russia
|
Posted: Thu Feb 28, 2008 15:57 Post subject: |
|
|
Do you use Hashset plugin? |
|
Back to top |
|
|
zzqzzq_zzq
Joined: 23 Feb 2008 Posts: 11
|
Posted: Thu Feb 28, 2008 16:31 Post subject: |
|
|
I'm not certain if the module developers were actually "using" the module, but it certainly was in the bunch I was trying to load....
Is there a conflict?
David |
|
Back to top |
|
|
virusman
Joined: 30 Jan 2005 Posts: 1020 Location: Russia
|
Posted: Thu Feb 28, 2008 22:07 Post subject: |
|
|
zzqzzq_zzq wrote: | I'm not certain if the module developers were actually "using" the module, but it certainly was in the bunch I was trying to load....
Is there a conflict?
David | Yes, Hashset is one of the plugins that return static memory pointers, so it may cause crashes with 2.7-b3. |
|
Back to top |
|
|
zzqzzq_zzq
Joined: 23 Feb 2008 Posts: 11
|
Posted: Thu Mar 06, 2008 3:53 Post subject: |
|
|
I found the source of some of my problems.
It appears both nwnx_chat (nwnx_chat-0.3.2-linux.rar), and nwn_events (nwnx_events-1.1.7-linux.rar) don't clean up the stack when executing the RunScript() routine.
In both copies of the routine, I moved the 'scriptRun = 1;' to before the asm() statements, and then immediately after the pRunScript() call, and before the 'scriptRun = 0;' statement, I added a 'asm("add $0x10, %esp");' line. (I'm not entirely certain I needed to move the 'scriptRun=1' line, but eh, I'm like that.)
The code pushes 4 4byte objects onto the stack for pRunScript() call, it appears from all the other disaseemblies I looked that I looked at, it needs to add 16 bytes to the stack afterwards to clean up things..
Maybe its a GCC-4 ism, I dunno.. but that's what I needed to do.
<shrug>
hope this helps someone....
David
PS: ChatHookProc() appears to be having similar issues .. I'm definitely suspecting something compiler related at this point, since I didn't run into the problem on Ubuntu 6.10, but am on a CentOS5 box. (sigh) |
|
Back to top |
|
|
virusman
Joined: 30 Jan 2005 Posts: 1020 Location: Russia
|
Posted: Thu Mar 06, 2008 10:33 Post subject: |
|
|
Thanks. It seems that you're right. I copied that function without checking it. Actually, assembly isn't necessary there.
And it's very odd that it didn't leak or crash before. |
|
Back to top |
|
|
zzqzzq_zzq
Joined: 23 Feb 2008 Posts: 11
|
Posted: Fri Mar 07, 2008 4:37 Post subject: |
|
|
ChatHookProc() is also pretty good at messing up the stack..
This is my current version of it, w/ comments, and why/whatnot..
I've also only tried this for about 10 minutes to see if it works... Which it does in my limited testing.
(I also admit I've not spent the time to disassemble it, and see what's different. So, I guess I'm lazy.. )
FWIW, GCC/G++ is: (CentOS5's basically)
[uholld1@questron src]$ g++ --version
g++ (GCC) 4.1.2 20070626 (Red Hat 4.1.2-14)
HTH,
David
Code: |
void ChatHookProc(char * pthis, const int mode, const int id, const char **msg, const int to, const char * xz)
{
// You don't see it, but its here,
// asm ("push %ebp");
// asm ("mov %esp,%ebp");
// asm ("sub $0x18,%esp");
//
// Its stdcall() prefix...
// Which means, when we jump to d_ret_code, we can skip the first three bytes.
// Which will explain the add 3 to $eax below. (right?)
// We also must clean up the 0x18 bytes of stack space allocated.
// 0x18 == (# of args * 4) -- 6 arguments.
//
// asm ("pusha");
if(!pChatThis) pChatThis = pthis;
if(!scriptRun) lastRet = chat.Chat(mode, id, msg, to);
// asm ("popa");
// asm ("leave");
if (!scriptRun && lastRet) {
// Clean up the stack, since it appears we're returning to the caller, and not actually
// letting the chat go through.
asm("add $0x18, %esp");
asm("pop %ebp");
asm("ret");
} // else let the chat go through.
asm("mov $d_ret_code, %eax");
asm("add $0x3,%eax"); // Skip stdcall assembly intro code.
asm("add $0x18, %esp"); // Fix stack
asm("jmp %eax");
}
|
|
|
Back to top |
|
|
virusman
Joined: 30 Jan 2005 Posts: 1020 Location: Russia
|
Posted: Fri Mar 07, 2008 7:06 Post subject: |
|
|
There is no need for this, 'leave' returns esp to its original value. |
|
Back to top |
|
|
zzqzzq_zzq
Joined: 23 Feb 2008 Posts: 11
|
Posted: Sat Mar 08, 2008 0:41 Post subject: |
|
|
Except that it didn't work.....
Code: |
Breakpoint 2 at 0x16ca22: file HookChat.cpp, line 89.
Pending breakpoint "ChatHookProc" resolved
[New Thread 24284048 (LWP 22842)]
[New Thread 45763472 (LWP 22843)]
[New Thread 87784336 (LWP 22844)]
[Switching to Thread 1119536 (LWP 22833)]
Breakpoint 2, ChatHookProc (pthis=0xfbbdab8 "�\003\017\020\207", mode=5, id=2130706432, msg=0xbfef2950, to=0, xz=0xbfef2940 "") at HookChat.cpp:89
89 asm ("pusha");
Current language: auto; currently c++
(gdb) cont
Continuing.
Program received signal SIGSEGV, Segmentation fault.
ChatHookProc (pthis=Cannot access memory at address 0x7f000008
) at HookChat.cpp:93
93 asm ("leave");
|
I had whacked the leave instruction since I wasn't terribly familiar w/ them.
I did some more digging (and put the leave back in place), and its the popa that's causing the problem. Just commenting it (and the corresponding pusha above, out seems to be sufficient.
David |
|
Back to top |
|
|
virusman
Joined: 30 Jan 2005 Posts: 1020 Location: Russia
|
Posted: Sat Mar 08, 2008 1:37 Post subject: |
|
|
I think it's something with the compiler.
My g++ version is:
g++ (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
Works fine. |
|
Back to top |
|
|
|