Page 1 of 1

Limited number of CALLs per line?

Posted: 21 Nov 2020 14:18
by aschipfl
Hello,
I just encountered a very strange behaviour of the CALL command (on my Windows 7 x64 machine) when it tries to call a non-existent label and appears quite a number of times in a line: :o

Code: Select all

@echo off
::The following contains 85 times `call :SUB` and complaints about a missing label as expected.
::Strangely, appending one more ` & call :SUB` prevents it from raising an error message.
::If you copy this line multiple times, nothing changes, the expected exception occurs.
::However, when appending ` & call :SUB` even to the last of the lines, nothing is returned.
::Even when you copy the augmented `call :SUB` line below the last `goto :EOF`, nothing is output.
call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB
::If there is `call` more than 128 times it complains about exceedance of the recursion stack limit:
goto :EOF
:FAKESUB
goto :EOF
As expected, the above code returns several time the same error message: "The system cannot find the batch label specified - SUB".

As mentioned in the comments, as soon as I add more CALLs, the error message no longer appears, and when I add enough CALLs, the fatal CALL stack overflow error occurs, although there should actually not occur a single call.

I am quite sure that the numbers mentioned in the script may vary depending on a lot of (yet unknown) things.

Does anyone have an explanation of what happens here? :?:

Thanks 'n' cheers,
aschipfl

Re: Limited number of CALLs per line?

Posted: 22 Nov 2020 06:12
by sst
Adding the one more CALL :SUB to the line causes the last :SUB on the line to be recognized as a valid batch label so the next line will executed in the context of the :SUB function.

Code: Select all

@echo off

call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & CALL :SUB
echo %0
exit /b

Re: Limited number of CALLs per line?

Posted: 22 Nov 2020 07:24
by T3RRY
sst wrote:
22 Nov 2020 06:12
Adding the one more CALL :SUB to the line causes the last :SUB on the line to be recognized as a valid batch label so the next line will executed in the context of the :SUB function.

Code: Select all

@echo off

call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & call :SUB & CALL :SUB
echo %0
exit /b
My test of the above resulted in the line length being exceeded for notepad pushing the last :Sub onto the next line.

Re: Limited number of CALLs per line?

Posted: 22 Nov 2020 08:16
by dbenham
All can be explained once you understand how CALL/GOTO scan for labels. The label scanner reads until \r\n is found, or 512 bytes, whichever comes first. The code that has no error has the following at line position 1024:

<space>:SUB

So the label is found, and the routine starts on the next line (a label comment), and then GOTO :EOF is executed, so no error.

But if you keep on appending & CALL :SUB, then you eventually run into the situation where the buffer containing the found :SUB label is full at 512 bytes, so the called target is the very next position on the same line. This happens to be the following at line position 1536:

<space>CALL :SUB & ...

And there you have your infinite recursion that is interrupted by the batch recursion limit.

All the discovery and rules are within the thread at viewtopic.php?f=3&t=8988


Dave Benham

Re: Limited number of CALLs per line?

Posted: 22 Nov 2020 09:02
by aschipfl
dbenham wrote:
22 Nov 2020 08:16
All can be explained once you understand how CALL/GOTO scan for labels. The label scanner reads until \r\n is found, or 512 bytes, whichever comes first. The code that has no error has the following at line position 1024:

<space>:SUB

So the label is found, and the routine starts on the next line (a label comment), and then GOTO :EOF is executed, so no error.

But if you keep on appending & CALL :SUB, then you eventually run into the situation where the buffer containing the found :SUB label is full at 512 bytes, so the called target is the very next position on the same line. This happens to be the following at line position 1536:

<space>CALL :SUB & ...

And there you have your infinite recursion that is interrupted by the batch recursion limit.

All the discovery and rules are within the thread at viewtopic.php?f=3&t=8988


Dave Benham
Wow, thank you! I'm impressed and shocked at the same time! :o

This also explains why the number of CALLs to provoke said exceptions changes when the label name changes in length…