This makes us savestate the NAND using the same APIs the guest uses
instead of directly touching the host files. This solves several
problems:
* If the user loaded a malicious savestate, it could use path traversal
to overwrite arbitrary files on the host file system. (Reported by
MrSynAckster.)
* Metadata (UID, GID, attribute, modes) wasn't being savestated.
* NAND redirects weren't handled, except for NAND redirects at the root
of where the savestate was being done. (This only possibly matters if
TASing a Riivolution patch. The root of the savestate is at /tmp when
not TASing, and the only case where we do a NAND redirect is inside
/title if requested by a Riivolution patch.)
The conditions were in reverse order (maybe someone was reading the
PowerPC manual and forgot about IBM's bit numbering), and additionally
the two conditions for unsigned comparison were wrong.
Fixes https://bugs.dolphin-emu.org/issues/14054.
Reported by MrSynAckster. A specifically crafted NAND dump could use
path traversal to overwrite files on the host file system.
This is also an accuracy fix for importing NAND dumps that contain
file names that Dolphin is supposed to escape. Some games' save files
are affected.
GetPath has two special cases where it doesn't add a slash.
The first is for the root entry's special name "/". The next commit will
be neater if we can skip calling GetPath for the root entry, because '/'
is one of the characters that Common::EscapeFileName replaces with an
escape sequence. Let's check for entry number 0 instead.
The second is for parent paths that already end in a slash. There's no
actual need to check for this - double slashes are harmless, and for
comparison, NANDImporter::ExtractCertificates already appends slashes
without checking if there already is one. Let's remove this check.
Workaround for the following error on gradle sync:
java.nio.file.InvalidPathException: Illegal char <:> at index 68:
C:\Users\tompr\Development\dolphin\Externals\minizip-ng\minizip-ng\C:\Users\tompr\Development\dolphin\Source\Android\app\.cxx\RelWithDebInfo\3b681gem\arm64-v8a\Externals\zlib-ng\zlib-ng
If the last write to a register comes before the last read of it,
we can write the register to ppcState after the last write instead of
after the last read. This will hopefully help spread out m_ppc_state
writes across a code block, improving pipelining. Also, if there's a
conditional branch that's after the last write but before the last read,
instead of needing to emit one m_ppc_state write on each side of the
branch, we now only need to emit one m_ppc_state write.
A note about the changes made to stmw and mfcr: These instructions don't
write to any GPRs or CRs respectively – they only read from them.
With this commit, there are no longer any cases where registers get
written back to m_ppc_state after an instruction that just reads from
them, so we can get rid of all STP logic from these two instructions.
lmw still needs its STP logic, since that one does write to registers.
This jumps us up two releases, both of which only introduce bug fixes. Changes potentially relevant to us are:
[3.4.6](https://github.com/libsdl-org/SDL/tree/release-3.4.6):
- Fixed Xbox controllers being unresponsive on preview release of Windows 11
- Fixed the menu button state on controllers on Apple platforms
[3.4.8](https://github.com/libsdl-org/SDL/tree/release-3.4.8) (hotfix release):
- Fixed a controller related crash on Windows, introduced in 3.4.6
For some reason, NativeLibrary.kt calling Log for the alert message text
makes Dolphin die with a JNI error. Supposedly the jstring passed to the
logging function is invalid. I don't understand why, because the dialog
that we show right afterwards is able to read the string just fine. The
error happens even if I pass the string directly to Log without
prepending any extra text.
There's no real downside to having the logging in C++ instead of Kotlin,
so let's move it to C++ to avoid the JNI error.
When calling `ShowMessageAlert` with a given `MsgType`, log the alert
with a `LogLevel` matching the `MsgType` instead of always using
`LogLevel::LERROR`.