j-mie6 / parsley

A fast and modern parser combinator library for Scala
https://j-mie6.github.io/parsley/
BSD 3-Clause "New" or "Revised" License
173 stars 15 forks source link

[BUG] Recursive Let Found parsers in flat-map causes CalleeSave re-entry #241

Open DanKirwan opened 3 months ago

DanKirwan commented 3 months ago

Description

CalleeSave is designed to either be entered or exited, however as this parser can be let found (meaning we don't regenerate the instructions for it), if you recursively call a flatMap from within a flatMap and access the same CalleeSave instance, CalleeSave thinks we're leaving this scope so restores the outside registers which leads to undefined behaviour

Reproduction Steps

Write this code:


var x: Parsley[Unit] = pure(())
var death: Parsley[Unit] = 'x'.flatMap(_ => x)
x = death *> 1.makeRef(_=> pure('a'))

death.parse("xxx")

Expected behavior

This parser should return a failure with unexpected end of input but the scopes of the registers inside should still be consistent (it's possible to write a recursive state like this that uses the state to end the infinite recursion but this is the simplest example I could find that shows the bug)

Additional context

Parsley Version: 5.0 staging Scala Version: Both 2.13 and 3