mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 13:33:27 -04:00
2c356f28ea
The rest of the Gen 3 review fixes, each with a gated suite in tests/engine/.
ROM semantics were checked against pret/pokefirered.
Scripts
- givemon carried the wrong operand layout, found earlier; four more layout
desyncs came out of pret asm/macros/event.inc: comparestat is {byte,word},
and setptr / loadbytefromptr / setptrbyte each carry a leading byte plus a
word. A wrong size mis-decodes every instruction after the bad one, so
Versions.CACHE_VERSION moves to 113 and existing caches re-import.
- handlers for previously handler-less verbs: comparestat,
bufferitemnameplural, setmonmove, setmonmetlocation, the modern
fateful-encounter pair, the script-locals family (copylocal, setptr,
loadbytefromptr, setptrbyte, copybyte, compare_local_to_* and
compare_ptr_to_*), the RAM-script family (setvaddress, vgoto, vcall,
vgoto_if, vcall_if, vmessage, vbuffermessage, vbufferstring, endram,
returnram) and the same-map forms of the *at verbs.
- setdooropen / setdoorclosed read their coordinates through VarGet.
Battles
- Knock Off and Thief / Trick persist the item change instead of only
touching the in-battle copy.
- knocked-off party slots are tracked in a bitmask, so a slot reused later
does not inherit the flag.
Field and UI
- Player.reset restores facing and clears the surf flags.
- a definition-less Map.load no longer leaves collision unbound.
- an unresolved region-map section no longer reports PALLET TOWN.
- the naming screen splits input from the timer, so update(dt) stops
indexing a number.
- the hall of fame commits through the engine save path and serializes its
fields.
Persistence
- gameStats, the link-battle records and the trainer card are serialized.
- the PC deposit refuses at the 999 cap instead of destroying the overflow.
Robustness
- Data.load runs cached modules sandboxed.
- the file browser quotes shell arguments.
- .meta dimensions are bounds-checked and mids.idx validates its header.
51 lines
2.1 KiB
Lua
51 lines
2.1 KiB
Lua
-- The launcher file browser must not interpolate a path into a shell unescaped.
|
|
--
|
|
-- L3 regression: scanDirectory built
|
|
-- 'ls -1ap "' .. dir:gsub('"', '\\"') .. '" 2>/dev/null'
|
|
-- so only a double quote was escaped. A directory name containing $(...) or a
|
|
-- backtick executed as the user the moment it was entered in the ROM/mod picker.
|
|
-- HostShell.quote already escapes for the POSIX shell.
|
|
-- luajit tests/engine/game3_file_browser_quote_test.lua
|
|
|
|
package.path = "./?.lua;./?/init.lua;" .. package.path
|
|
|
|
local T = require("tests.harness")
|
|
local check, eq = T.check, T.eq
|
|
love = love or require("tests.love_stub")
|
|
|
|
local FileBrowser = require("src.ui.kit.FileBrowser")
|
|
local HostShell = require("src.core.HostShell")
|
|
|
|
-- 1. Injection: a directory named with a command substitution must not run.
|
|
-- The marker must not pre-exist (os.tmpname creates its file, so name it here).
|
|
local marker = "/tmp/gen1recomp-inject-" .. tostring(os.time())
|
|
.. "-" .. tostring(math.random(1000000))
|
|
check(io.open(marker, "r") == nil, "the injection marker does not exist before the call")
|
|
local hostile = "/tmp/gen1recomp-inject-$(touch " .. marker .. ")-x"
|
|
FileBrowser.setDirectory(hostile)
|
|
local created = io.open(marker, "r")
|
|
if created then created:close(); os.remove(marker) end
|
|
check(created == nil,
|
|
"a command substitution in a directory name is not executed by the file browser")
|
|
|
|
-- 2. Shape: the listing command single-quotes the path (HostShell's POSIX form).
|
|
local captured
|
|
local realPopen = io.popen
|
|
io.popen = function(cmd)
|
|
captured = cmd
|
|
return { read = function() return "" end, close = function() end }
|
|
end
|
|
FileBrowser.setDirectory("/tmp/it's $(here)")
|
|
io.popen = realPopen
|
|
|
|
check(type(captured) == "string", "the browser still lists through the shell")
|
|
if type(captured) == "string" then
|
|
local quoted = HostShell.quote("/tmp/it's $(here)")
|
|
check(captured:find(quoted, 1, true) ~= nil,
|
|
"the directory is passed through HostShell.quote (" .. tostring(captured) .. ")")
|
|
check(captured:find("$(here)", 1, true) == nil or captured:find(quoted, 1, true) ~= nil,
|
|
"the raw path is not left unquoted")
|
|
end
|
|
|
|
T.finish("game3_file_browser_quote_test")
|