alan-if / alan

ALAN IF compilers and interpreters

Home Page:https://alanif.se

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

String Parameters: Infinite Recursion due to $1 Expansion

tajmone opened this issue · comments

String parameters accept special $ symbols, which can cause infinite recursion when the player types in a string literal the $1 symbol.

Possibly, string paramaters shouldn't be interpreted for special $ symbols at all. For example, escaping quotes in string parameters isn't possible (eg. write "hello ""world""!" is not parsed), so dollar symbols should be treated as raw text too — otherwise, if the player need to type a $ char he/she is likely to get into trouble (see last example).

Example code:

--==============================================================================
-- BUG: String parameters may contain Alan special $ symbols, which can lead to
--      infinite recursion when the player types "$1".
--==============================================================================

THE room IsA LOCATION
  Has text "".
  VERB write
    DOES
      "You write ""$1""."
      Set text of room to str.
  END VERB write.
END THE room.

-- Verb Write
SYNTAX write = write (str)
  WHERE str IsA string
    ELSE "You can only use strings with this verb."


-- Verb Read
SYNTAX read = read.

VERB read
  DOES
    Say text of room.
END VERB read.

Start at room.

test with:

read
write "Hello world."
read
write "Hello.$pWorld"
read
write "Hello.$1"
read
write "$1"

Dollar Symbols Are Expanded

The command write "Hello.$pWorld" clearly demonstrates that $ symbols are expanded in string parameters:


> write "Hello.$pWorld"
You write "Hello.

World".

> read
Hello.

World

$1 Infinite Recursion 1

when it gets to write "Hello.$1" the game session enters infinite recursion and the abruplty crashes:

> write "Hello.$1"
You write "Hello.Hello.Hello.Hello.Hello.Hello.Hello.Hello.Hello.Hello.
Hello.Hello.Hello.Hello.Hello.Hello.Hello.Hello.Hello.Hello.Hello.Hello.
Hello.Hello.Hello.Hello.Hello.Hello.Hello.Hello.Hello.Hello.Hello.Hello.
Hello.Hello.Hello.Hello.Hello.Hello.Hello.Hello.Hello.Hello.Hello.Hello.
Hello.Hello.Hello.Hello.Hello.Hello.Hello.Hello.Hello.Hello.Hello.Hello.
Hello.Hello.Hello.Hello.Hello.Hello.Hello.Hello.Hello.Hello.Hello.Hello.
Hello.Hello.Hello.Hello.Hello.Hello.Hello.Hello.Hello.Hello.Hello.Hello.
[... TERP CRASHES ...]

Whereas by typing write "$1" the terp just hangs until it crashes.

Problems With Literal $ (Currency) Symbol

Also, note that trying using the $ character crashes the terp:

> write "I have $5!"
You write "I have 

As you enter the twilight zone of Adventures, you stumble and fall to your knees. In front of you, you can vaguely see the outlines of an Adventure that never was.

APPLICATION ERROR: Nonexistent parameter referenced.

<If you are playing this piece of Interactive Fiction, please help the author to debug this programming error. Send an exact transcript of the commands that led to this error to the author. Thank you! If you *are* the author, then you have to figure this out before releasing the game.>

That's quite an amusing bug. I can't think of any reason why the expansion should be needed or allowed when printing the content of a string parameter or attribute. So I'll try to find a way to avoid this.

Obviously, this expansion is in the lower regions of the output, so it might require some restructuring to do it in a pretty fashion.

There are a few cases where the spacing around attributes and parameters of string type will be different. Of all the test cases I had only a few changed, and all diffed a single empty line. All other cases of embedded printing of string parameters or attributes spaced the same.

So, I think this is acceptable. If you find any alarming spacing problems, give me a shout and we'll analyze them.

build 2019: String Attributes Not Expanded

I've tried build 2019, the problem is that now it doesn't expand dollar symbols when SAYing string attributes either — the various libraries rely on such attributes to store shared verb reply messages, e.g.:

The my_game IsA location
  Has already_have_ogg1 "You already have $1."
End The

...

  Verb take
    ...
    Else Say my_game:already_have_ogg1.
    ...

etc., where these string attributes hold reusable snippets of text used by various verbs and rely on dollar symbols for parameter expansion, etc.

Now the Italian library test suite shows the actual $s in the output. Eg:

> take apple
You already have $1.

instead of:

> take apple
You already have the apple.

Possibly, the fix should only concern player types input — i.e. a sort of string sanitation. E.g. you might filter for $ in the user input and add an extra dollar to escape it: $ -> $$, so that any dollar symbol will be expanded as a litera dollar ($1 -> $$1).

Ok. So, since player input can, and probably often is, stored in attributes, we will need to do that in the input side rather than on the printing side, as was my initial attempt.

Have to add a test case for this then.

Ok. So, since player input can, and probably often is, stored in attributes ...

Interesting, are these internal attributes of the interpreter?

... we will need to do that in the input side rather than on the printing side, as was my initial attempt.

My guess is that doubling any dollar occurence in a player input string should do the work, so that they'll all expeand to $ characters via escaping.

The only reason a player should use a $ in a string input is to represent the actual Dollar currency — all other uses should be futile, for the player shouldn't even know about special dollar symbols in Alan, and I can see no reason for him/her to exploit them in the input.

Have to add a test case for this then.

The following variation on the previous test might suffice:

--==============================================================================
-- BUG: String parameters may contain Alan special $ symbols, which can lead to
--      infinite recursion when the player types "$1".
--==============================================================================

THE room IsA LOCATION
  Has text "".
  Has write_msg "You write ""$1"".".
  VERB write
    DOES
      Say room:write_msg.
      Set text of room to str.
  END VERB write.
END THE room.

-- Verb Write
SYNTAX write = write (str)
  WHERE str IsA string
    ELSE "You can only use strings with this verb."


-- Verb Read
SYNTAX read = read.

VERB read
  DOES
    Say text of room.
END VERB read.

Start at room.

for it exploits a string attribute in the room location as verb message.

Ok. So, since player input can, and probably often is, stored in attributes ...

Interesting, are these internal attributes of the interpreter?

No, I ment attributes of an Alan instance. If you implement a "write" verb and want to keep the text written you have to store it in an attribute. My point was that it is not a difference between syntax paramters and instance attributes, since player input can be stored in instance attributes from syntax parameters.

So the translation has to be made directly on input. And, since "$$p" will not be an escaped '$' with a 'p' after, the escaping will have to be done with '_'. See the manual. Yes, I had forgotten about that too...