Archive: makensis / logiclib crash


makensis / logiclib crash
The compiler (standard build) is crashing for me when it reaches a For loop:

${Explode} $R0 "," `$R4`
${For} $R1 1 $R0
Pop $R5

I set LOGICLIB_VERBOSITY to 4 and the compiler output is:
!insertmacro: end of Explode
!insertmacro: _For
!insertmacro: _ForEach
StrCpy $R1 "1" () ()
Goto: +2
!define: "_DoLoopExpression"="IntOp "$R1" "$R1" "+" "1""
!define: "_o=+"=""
!define: "__o"=">"
!undef: "_o=+"
!insertmacro: _Do
!insertmacro: _PushLogic
!insertmacro: _PushScope
at this point MAKENSIS.EXE stops responding and gives the standard Windows dialog.

I tried adding an echo to _PushScope and found that we don't even compile the first line of that macro.
The values passed from _PushLogic to _PushScope are:
Logic
_LogicLib_Label_311

The for loop I've added is the same as many others that I already had in my script that are working fine.
I cannot see any reason for the compiler to crash...

Does anyone have any insight? My first thought is why doesn't the compiler report an error if there is one, so looks like compiler can't handle something, but the values passed to the macro look just fine...


It appears to have something to do with the amount of code / number of defines / number of includes I am using. I have 1 section included three times and that gives me the problem, but if I only include the section twice then the problem goes away.

I have searched for NSIS limits but found nothing...

Found that removing all the runtime code from the section caused the problem to move to an If statement in another macro. So there is definitely something up with a limit somewhere - maximum number of macro arg defines possibly? Can anyone shed any light on this?


Is there perhaps a debug version of makensis that I can use to find out what is causing the error?


I've tried attaching a debugger to this but can't really see what's going on.

Call stack of main thread
Address Stack Procedure / arguments Called from Frame
000409FC 00423B83 ? makensis.0044F8C0 makensis.00423B7E
00040A14 00422CE9 ? makensis.00423B60 makensis.00422CE4
00040A88 004239E0 ? makensis.00422650 makensis.004239DB
00040A8C 017B4501 Arg1 = 017B4501
00040AEC 00424236 ? makensis.004238D0 makensis.00424231
00040AF0 01675DD9 Arg1 = 01675DD9 ASCII " !define _${Type} ${label}
00040AF4 00000000 Arg2 = 00000000
00040AF8 00000000 Arg3 = 00000000

!define _${Type} ${label} looks suspicious, as that line is inside the macro but we haven't compiled the first line of the macro yet - otherwise my !echo should have been displayed. So I'm guessing the script is buffered (?)

My colleague tells me the failing instruction is
0044F8D7 |. 8501 |TEST DWORD PTR DS:[ECX],EAX
because ECX is not pointing to accessible memory (ECX=00032A00, EAX=00001630). So definitely something going wrong in makensis.

If I add an ${If} immediately before the ${For} , the error still occurs in the ${For}, but if I add a ${For} then the error occurs in that ${For} instead.

I am at a loss as to how to proceed with this, please someone help!


I've been trying to get a hold of kichik for you, but he hasn't been online yet. Please stand by, one of the devs will reply soon enough.


Thanks MSG, in the meantime.... I have replicated the problem using a tiny script!

====MAIN SCRIPT====
!include LogicLib.nsh
OutFile "NESTTEST.EXE"
InstallDir $DESKTOP\Example1
RequestExecutionLevel user
ShowInstDetails show
Page components
Page instfiles
Section "nested includes test" NESTTEST
!define FILENUM "0"
!include "file1.nsh"
SectionEnd

====FILE1.NSH====
!ifdef _FILENUM
!undef _FILENUM
!endif
!define /math _FILENUM ${FILENUM} + 1
!echo `I am include number ${_FILENUM}`
!undef FILENUM
!define FILENUM ${_FILENUM}
${For} $R0 1 5
${Next}
!include "file1.nsh"


Last 4 lines of compiler output (before the crash) are:
I am include number 8 (file1.nsh:5)
!undef: "FILENUM"
!define: "FILENUM"="8"
!insertmacro: _For

So there appears to be a problem with the number of nested includes combined with LogicLib!
Now, !include doesn't appear to have a problem going beyond 8 nested levels normally, so I suspect something in the LogicLib magic is causing trouble...


You've got infinite recursion going on here. How can you expect it not to crash? You haven't put in a condition to stop it infinitely including file1.nsh...

Stu


That was just to show the example. Using this instead:

====FILE1.NSH====
!ifdef _FILENUM
!undef _FILENUM
!endif
!define /math _FILENUM ${FILENUM} + 1
!echo `I am include number ${_FILENUM}`
!undef FILENUM
!define FILENUM ${_FILENUM}
${For} $R0 1 5
${Next}

!if ${FILENUM} < 16
!include "file1.nsh"
!endif

...still crashes when filenum is 8.


I guess NSIS is limited to that many recursive includes. Have you tried using a recursive insertmacro rather than a recursive file include?

Edit: Actually I doubt that will work.

Stu


If I comment out the ${For} and ${Next} lines, the compiler tells me this:

I am include number 10 (file1.nsh:5)
!undef: "FILENUM"
!define: "FILENUM"="10"
!include: "file1.nsh"
parseScript: too many levels of includes (10 max).

So even though the limit is 10 there is a bug with LogicLib at 8 levels.

Recursive insertmacro doesn't work either:
!insertmacro: macro "recurse" already being inserted!

This means there is no way to do any kind of compile-time looping which is very restrictive.

1. Bug with include/LogicLib definitely needs fixing because that could be down to something more serious.
2. Pretty pretty please remove the 10-level nested include limit. Unlimited if possible, increased to at least 32 if there has to be a limit... That or allow recursive macro-inserts.


the main issue with increasing the recursion limit is that makensis is more likely to run out of stack space and crash (is probably why the limit was introduced in the first place) unless you take the source code and modify it as a custom version for your own usage.

-daz


LogicLib crashing the installer before the recursion limit is reached should definitely be fixed, though. Has someone filed a bug report yet?


i don't disagree that it shouldn't be crashing, just any high level of recursion needs to be considered for stack overflows / heap exhaustion. i doubt anyone has logged it so well volunteered :)

-daz


question is whether it's actually LogicLib crashing things, though. I peeked at this earlier and added Echos for every step in the _For macro. It got all the way up to `!echo "!verbose LOGICLIB_VERBOSITY"`, but crashed at that point. Commenting out that !verbose line just shifted the crash to the next command line, the ${ForEach}.

LogicLib doesn't do anything funny there as far as I can tell - just looks like the given example exposes the underlying issue.


I have logged a bug report for the crash and a feature request for extending the recursive options.