The pure Lua version of `mw.ustring.gsub` handles replacement strings containing invalid '%' sequences differently than the PHP version.
There are two issues:
**Issue 1:** If a replacement string has '%' followed by an unrecognized character, the pure Lua implementation removes the '%', but PHP keeps it as-is:
```lua
mw.ustring.gsub("test", "test", "x%yz")
```
PHP: `x%yz`
Lua: `xyz`
**Issue 2:** A '%' at the end of a replacement string causes Lua to insert a null byte:
```lua
mmw.ustring.gsub("test", "test", "bar%")
```
PHP: `bar%`
Lua: `bar\000`
Both implementations should handle '%' characters the same way.
https://gerrit.wikimedia.org/r/c/mediawiki/extensions/Scribunto/+/1232409 (not for submission) demonstrates the bug: if you update the expected value to match the actual value cited in the test failure, the test will fail again, this time due to a mismatch with the PHP implementation.
You can run the test by installing the Scribunto extension and running `composer phpunit -- extensions/Scribunto/tests/phpunit` from the MediaWiki installation root.
Here is where the Lua implementation of `gsub` is located: [[ https://github.com/wikimedia/mediawiki-extensions-Scribunto/blob/7203ae4331b6169d242928b99aabda30b8ee07c0/includes/Engines/LuaCommon/lualib/ustring/ustring.lua#L945-L1055|includes/Engines/LuaCommon/lualib/ustring/ustring.lua, lines 945-1055]]