Skip to content

Commit 3e8d5b7

Browse files
authored
Merge pull request #75 from MarcCote/fix_buffer_overflow
Truncate very long action to avoid buffer overflow.
2 parents 5bcf3a8 + 85dede9 commit 3e8d5b7

File tree

3 files changed

+35
-2
lines changed

3 files changed

+35
-2
lines changed

jericho/jericho.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@
3636
JERICHO_PATH = importlib.resources.files("jericho")
3737
FROTZ_LIB_PATH = os.path.join(JERICHO_PATH, 'libfrotz.so')
3838

39+
# The buffer size for actions in frotz. -2 to allow for newline and null terminator.
40+
INPUT_BUFFER_SIZE = 200 - 2
41+
3942
# Function to unload a shared library.
4043
dlclose_func = CDLL(None).dlclose # This WON'T work on Win
4144
dlclose_func.argtypes = [c_void_p]
@@ -361,6 +364,10 @@ class UnsupportedGameWarning(UserWarning):
361364
pass
362365

363366

367+
class TruncatedInputActionWarning(UserWarning):
368+
pass
369+
370+
364371
class FrotzEnv():
365372
"""
366373
The Frotz Environment is a fast interface to Z-Machine games.
@@ -465,9 +472,19 @@ def step(self, action):
465472
the immediate reward, a boolean indicating whether the game is over,\
466473
and a dictionary of info.
467474
:rtype: string, float, boolean, dictionary
475+
476+
Note:
477+
- The action is converted to bytes and truncated to 198 characters.
468478
'''
479+
action_bytes = action.encode('utf-8')
480+
if len(action_bytes) > INPUT_BUFFER_SIZE:
481+
action_bytes = action_bytes[:INPUT_BUFFER_SIZE]
482+
msg = ("Once converted to bytes, actions should have less than 198 characters."
483+
" Action '{}' was truncated to '{}'.".format(action, action_bytes.decode()))
484+
warnings.warn(msg, TruncatedInputActionWarning)
485+
469486
old_score = self.frotz_lib.get_score()
470-
next_state = self.frotz_lib.step((action+'\n').encode('utf-8')).decode('cp1252')
487+
next_state = self.frotz_lib.step(action_bytes + b'\n').decode('cp1252')
471488
score = self.frotz_lib.get_score()
472489
reward = score - old_score
473490
return next_state, reward, (self.game_over() or self.victory()),\

jericho/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = '3.2.0'
1+
__version__ = '3.3.0'

tests/test_jericho.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,3 +127,19 @@ def test_saving_opcode_in_state():
127127
else:
128128
obs, rew, done, info = env.step(cmd)
129129
assert not env._emulator_halted()
130+
131+
132+
def test_very_long_action():
133+
rom = pjoin(DATA_PATH, "905.z5")
134+
env = jericho.FrotzEnv(rom)
135+
env.reset()
136+
137+
long_command = "It's a " + "very " * 36 + "long action!"
138+
assert len(long_command) == 199
139+
env.step(long_command)
140+
env.step(long_command * 2)
141+
142+
long_command = "It's a " + "très " * 36 + "long action!"
143+
assert len(long_command) == 199
144+
env.step(long_command)
145+
env.step(long_command * 2)

0 commit comments

Comments
 (0)