Fix and guard against out-of-bounds writes in splev code
I traced a memory corruption bug in xNetHack to a themed room that
looked something like this:
function()
des.room({ type="themed", contents = function()
des.feature({ type='sink' })
...
end })
end
Placing a feature at a random spot within a room or region is a
reasonable thing for the parser to handle, but the code was not equipped
to handle it, and so the unspecified x and y set as -1 got passed
directly to SP_COORD_PACK, ending up as coordinates way off the map.
Since sel_set_feature does not do an isok() check, this ended up writing
data to unrelated memory.
This commit does the following things:
- Enables des.feature() with no coordinates specified, both via a table
with 'type' set, and as the single string argument. When no
coordinates are specified, it will pick a random normal-floor spot
within the enclosing room or region if there is one, or anywhere
on the level if there isn't.
- Prevents sel_set_feature from corrupting memory outside
g.level.locations. Additionally, if EXTRA_SANITY_CHECKS is defined and
this gets attempted, it causes an impossible.
- Guards the existing "door coord not ok" Lua error with an immediate
return from lspo_door.
- Adds similar "coord not ok" errors to all the other locations in
sp_lev.c which did not already check for a unspecified/invalid
coordinate and for which a random coordinate is nonsensical:
des.terrain(), des.drawbridge(), and des.mazewalk().
This commit is contained in:
@@ -534,6 +534,9 @@ Create a feature, and set flags for it.
|
||||
Valid features are a fountain, a sink, a pool, a throne, or a tree.
|
||||
Throne has `looted` flag, tree has `looted` and `swarm`, fountain has `looted` and `warned`,
|
||||
sink has `pudding`, `dishwasher`, and `ring`.
|
||||
If passed with no coordinates, it will be placed in a random normal-floor spot
|
||||
in the enclosing room or region if one exists, or a random normal-floor spot
|
||||
anywhere on the level if one does not exist.
|
||||
|
||||
Example:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user