Archive: To NSIS developers (bug)


To NSIS developers (bug)
Function
CEXEBuild::doCommand(...);//line 793
gets pointer to macros storage (m_macros)
char *t=(char *)m_macros.get(); //line 815
and use this pointer throw the function.
If you have a lot of macroses (such as in my case) realloc for m_macros occured (in my case in string: if (str[0]) m_macros.add(str,strlen(str)+1); file script.cpp, line 891), thus t pointed to invalid memory. And code such as
if (strcmp(t," "))
{
int ret=process_oneline(t,str,lp);
if (ret != PS_OK)
{
ERROR_MSG("Error in macro %s on macroline %d\n",line.gettoken_str(1),lp);
return ret;
}
}

t+=strlen(t)+1;
finaly kill nsis:-( Release NSIS compiler work very unstable because of this and debug crush always (because memory marked as 0xEEFE). I think you should check this and another places when such bug can occured.
Best regards,
Penetrat


Those are not the same variables, they are not in the same scope. The first `t' is in the TOK_P_MACRO block and the second one is in the TOK_P_INSERTMACRO block. The first one is not used after data is added to m_macros.

If you can reproduce the crash attach an example script and specify the exact version of NSIS you've used. If you've recompiled makensis.exe, specify which compiler you've used.


Call stack:

NTDLL! 77f82d4b()
NTDLL! 77fac7da()
NTDLL! 77f8cf62()
NTDLL! 77f5e449()
NTDLL! 77f57688()
NTDLL! 77fac47f()
NTDLL! 77f8ec53()
_realloc_base(void * 0x009f8050, unsigned int 98464) line 258 + 22 bytes
realloc_help(void * 0x009f8070, unsigned int 98422, int 1, const char * 0x00000000, int 0, int 1) line 649 + 16 bytes
_realloc_dbg(void * 0x009f8070, unsigned int 98422, int 1, const char * 0x00000000, int 0) line 824 + 27 bytes
realloc(void * 0x009f8070, unsigned int 98422) line 768 + 19 bytes
GrowBuf::resize(int 32827) line 63 + 19 bytes
GrowBuf::add(const void * 0x00101710, int 35) line 50
CEXEBuild::doCommand(int 75, LineParser & {...}) line 892
CEXEBuild::doParse(const char * 0x00b70108) line 436 + 16 bytes
CEXEBuild::parseScript() line 621 + 20 bytes
CEXEBuild::includeScript(char * 0x009e9848) line 663 + 8 bytes
CEXEBuild::doCommand(int 69, LineParser & {...}) line 2622 + 15 bytes
CEXEBuild::doParse(const char * 0x00a302a8) line 436 + 16 bytes
CEXEBuild::parseScript() line 621 + 20 bytes
CEXEBuild::includeScript(char * 0x009e95f8) line 663 + 8 bytes
CEXEBuild::doCommand(int 69, LineParser & {...}) line 2674 + 15 bytes
CEXEBuild::doParse(const char * 0x00a40029) line 436 + 16 bytes
CEXEBuild::process_oneline(char * 0x009f906f, char * 0x0011dde0, int 3) line 743 + 17 bytes
CEXEBuild::doCommand(int 77, LineParser & {...}) line 971 + 29 bytes
CEXEBuild::doParse(const char * 0x00a181d1) line 436 + 16 bytes
CEXEBuild::process_oneline(char * 0x009fc5c2, char * 0x00124c04, int 5) line 743 + 17 bytes
CEXEBuild::doCommand(int 77, LineParser & {...}) line 971 + 29 bytes
CEXEBuild::doParse(const char * 0x00a000c9) line 436 + 16 bytes
CEXEBuild::parseScript() line 621 + 20 bytes
CEXEBuild::process_script(_iobuf * 0x004f1328, char * 0x0012d754) line 196 + 8 bytes
main(int 2, char * * 0x00931700) line 377 + 25 bytes
mainCRTStartup() line 206 + 25 bytes
KERNEL32! BaseProcessStart@4 + 35 bytes


Source of stack bold string(CEXEBuild::process_oneline) is
while (*t)
{
lp++;
if (strcmp(t," "))
{
int ret=process_oneline(t,str,lp);
if (ret != PS_OK)
{
ERROR_MSG("Error in macro %s on macroline %d\n",line.gettoken_str(1),lp);
return ret;
}
}
t+=strlen(t)+1;
}


Local variable is:
eip = int ret=process_oneline(t,str,lp); //current instruction
m_macros.m_s = 0x009f8070 //ok
t = 0x009f906f //ok

After one debug step:
eip = if (ret != PS_OK) //current instruction
m_macros.m_s = 0x00b82ff8 //ok realloc
t = 0x009f906f //ERROR! Invalid memory

Next debug step is t+=strlen(t)+1;...I think you made guess whats going to happen...

P.S. Sorry, cannot attach script, because a lot of large files.


Thanks, fixed in latest CVS version.


Now I use simple workaround for GrowBuf::resize and all work fine but slowly:-)
void resize(int newlen)
{
m_used = newlen;
if (!m_s)
{
m_alloc = 0x000FFFFF; //1 Mb
m_s = calloc (m_alloc, 1);
}
}

There are still another bug in the CZlib::Compress
(Access violation)
Stack:

memcpy(unsigned char * 0x03187acb, unsigned char * 0x00adf0b0, unsigned long 48568) line 272
flush_pending(z_stream_s * 0x00a9d8f8) line 298 + 26 bytes
deflate_slow(internal_state * 0x00a94868, int 0) line 816 + 93 bytes
deflate(z_stream_s * 0x00a9d8f8, int 0) line 380 + 14 bytes
CZlib::Compress(int 0) line 22 + 23 bytes
CEXEBuild::add_db_data(IMMap * 0x000ea9a0) line 820 + 25 bytes
CEXEBuild::do_add_file(const char * 0x00a9d810, int 0, int 0, int 138, int * 0x000ec354, const char * 0x00a9d7df, int 1, int * 0x00000000, int 0) line 5577 + 15 bytes
CEXEBuild::doCommand(int 127, LineParser & {...}) line 3983 + 60 bytes
CEXEBuild::doParse(const char * 0x047f0044) line 436 + 16 bytes
CEXEBuild::process_oneline(char * 0x01ea1123, char * 0x000f4908, int 138) line 743 + 17 bytes
CEXEBuild::doCommand(int 77, LineParser & {...}) line 971 + 29 bytes
CEXEBuild::doParse(const char * 0x044c0042) line 436 + 16 bytes
CEXEBuild::process_oneline(char * 0x01ea149c, char * 0x000fb72c, int 4) line 743 + 17 bytes
CEXEBuild::doCommand(int 77, LineParser & {...}) line 971 + 29 bytes
CEXEBuild::doParse(const char * 0x04080041) line 436 + 16 bytes
CEXEBuild::process_oneline(char * 0x01ea17c0, char * 0x00102550, int 3) line 743 + 17 bytes
CEXEBuild::doCommand(int 77, LineParser & {...}) line 971 + 29 bytes
CEXEBuild::doParse(const char * 0x03c40041) line 436 + 16 bytes
CEXEBuild::process_oneline(char * 0x01ea1860, char * 0x00109374, int 2) line 743 + 17 bytes
CEXEBuild::doCommand(int 77, LineParser & {...}) line 971 + 29 bytes
CEXEBuild::doParse(const char * 0x03a20042) line 436 + 16 bytes
CEXEBuild::process_oneline(char * 0x01ea6bd1, char * 0x00110198, int 59) line 743 + 17 bytes
CEXEBuild::doCommand(int 77, LineParser & {...}) line 971 + 29 bytes
CEXEBuild::doParse(const char * 0x036f0043) line 436 + 16 bytes
CEXEBuild::process_oneline(char * 0x01e81645, char * 0x00116fbc, int 9) line 743 + 17 bytes
CEXEBuild::doCommand(int 77, LineParser & {...}) line 971 + 29 bytes
CEXEBuild::doParse(const char * 0x02700041) line 436 + 16 bytes
CEXEBuild::process_oneline(char * 0x01e8235e, char * 0x0011dde0, int 5) line 743 + 17 bytes
CEXEBuild::doCommand(int 77, LineParser & {...}) line 971 + 29 bytes
CEXEBuild::doParse(const char * 0x022c0042) line 436 + 16 bytes
CEXEBuild::process_oneline(char * 0x01e84612, char * 0x00124c04, int 6) line 743 + 17 bytes
CEXEBuild::doCommand(int 77, LineParser & {...}) line 971 + 29 bytes
CEXEBuild::doParse(const char * 0x01a40041) line 436 + 16 bytes
CEXEBuild::parseScript() line 621 + 20 bytes
CEXEBuild::process_script(_iobuf * 0x004f1328, char * 0x0012d754) line 196 + 8 bytes
main(int 2, char * * 0x00931390) line 377 + 25 bytes
mainCRTStartup() line 206 + 25 bytes
KERNEL32! BaseProcessStart@4 + 35 bytes


Maybe also memory allocation/reallocation problem.
Compiler environment MSVC 6.0 Sp 5, Platform SDK November 2001 (old, but good:-), because old version idl compiler).

P.S. If you want I can send memory dump (for WinDbg).


Why fix it that way? I've already fixed it in the latest CVS version. Grab script.cpp from CVS and compile.

Memory dump would help. Stack trace alone doesn't help much here.


Thanks! Fix work. Bug with CZlib::Compress didn't reproduce on latest sources but reproduce when I replace GrowBuf::resize as mentioned above. IMHO possible reasons uninitialize variable or memory somewhere used. I can't attach dump (0,5 mb. zip), because size restriction. Please, let me know how I can send this file to you (if you are still interested in).


If it's caused by your change to resize, I'm not intereseted in it. It probably went over your 1mb buffer.


Ok. Thanks a lot to kichik. Case is closed.