A beta tester on my WIP discovered a stack overflow bug in adv3Lite. My WIP uses adv3Lite 1.5 (I know, I know, I’ll upgrade in my next project), but I’ve reproduced this on the latest GitHub master of adv3Lite (which reports as version 2.1).
Using this code as a test harness:
versionInfo: GameID
;
gameMain: GameMainDef
initialPlayerChar = me
;
startRoom: Room 'A room'
;
me: Thing
location = startRoom
isFixed = true
person = 2
contType = Carrier
;
and this as the test code:
Thing 'a penny' @startRoom
;
The transcript looks like this:
>l
A room
You can see a penny here.
>version
version
adv3Lite Library version 2.1
T3 VM (mjr-T3) version 3.1.3
>get penny. g.
Taken.
You’re already holding the penny.
You’re already holding the penny.
// ... repeated many times ...
You’re already holding the penny.
Runtime error: stack overflow
-->../adv3Lite/parser.t, line 3542
../adv3Lite/parser.t, line 3422
../adv3Lite/parser.t, line 4232
../adv3Lite/parser.t, line 3542
../adv3Lite/parser.t, line 3422
// ... stack loop repeated many times ...
../adv3Lite/parser.t, line 603
../adv3Lite/actions.t, line 3119
../adv3Lite/doer.t, line 414
../adv3Lite/doer.t, line 383
../adv3Lite/command.t, line 509
../adv3Lite/command.t, line 464
../adv3Lite/command.t, line 239
../adv3Lite/parser.t, line 603
../adv3Lite/actions.t, line 3119
../adv3Lite/doer.t, line 414
../adv3Lite/doer.t, line 383
../adv3Lite/command.t, line 509
../adv3Lite/command.t, line 464
../adv3Lite/command.t, line 239
../adv3Lite/parser.t, line 603
../adv3Lite/main.t, line 177
../adv3Lite/main.t, line 118
../adv3Lite/misc.t, line 124
../adv3Lite/main.t, line 70
../adv3Lite/main.t, line 24
/opt/homebrew/Cellar/frobtads/2.0/share/frobtads/tads3/lib/_main.t, line 217
/opt/homebrew/Cellar/frobtads/2.0/share/frobtads/tads3/lib/_main.t, line 122
/opt/homebrew/Cellar/frobtads/2.0/share/frobtads/tads3/lib/_main.t, line 31
I can provide a full stack trace, if needed, but it’s quite easy to reproduce. The key is to issue a command on the object, followed by a period, and then g
(i.e., AGAIN
) followed by a period. It doesn’t work for all commands (for example, MOVE PENNY. G.
doesn’t do it), but only some (DROP PENNY. G.
will reproduce, even if you’re not holding the penny to start with).
I did a little investigating down the stack. I believe the infinite regress only occurs when the action has againRepeatsParse = true
set, causing the last command to be parsed again. (Perhaps instead of re-parsing GET PENNY
it’s re-parsing GET PENNY. G.
?)
@Eric_Eve I would normally take this on to try and come up with a suitable patch, but these are in the guts of the Mercury parser, where I’m less familiar. I’ll keep looking, but I suspect you’ll come up with a proper fix faster than me.