mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-20 20:49:12 +12:00
[FS] Add app data folder, add path safety checks
This commit is contained in:
parent
c16bf5c8aa
commit
b1f2be98fa
6 changed files with 77 additions and 12 deletions
|
@ -1,6 +1,8 @@
|
|||
#pragma once
|
||||
#include <cassert>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
#include "helpers.hpp"
|
||||
#include "memory.hpp"
|
||||
|
@ -93,6 +95,51 @@ protected:
|
|||
using Handle = u32;
|
||||
Memory& mem;
|
||||
|
||||
// Returns if a specified 3DS path in UTF16 or ASCII format is safe or not
|
||||
// A 3DS path is considered safe if its first character is '/' which means we're not trying to access anything outside the root of the fs
|
||||
// And if it doesn't contain enough instances of ".." (Indicating "climb up a folder" in filesystems) to let the software climb up the directory tree
|
||||
// And access files outside of the emulator's app data folder
|
||||
template <u32 format>
|
||||
bool isPathSafe(const FSPath& path) {
|
||||
static_assert(format == PathType::ASCII || format == PathType::UTF16);
|
||||
using String = std::conditional<format == PathType::UTF16, std::u16string, std::string>::type; // String type for the path
|
||||
using Char = String::value_type; // Char type for the path
|
||||
|
||||
String pathString, dots;
|
||||
if constexpr (std::is_same<String, std::u16string>()) {
|
||||
pathString = path.utf16_string;
|
||||
dots = u"..";
|
||||
} else {
|
||||
pathString = path.string;
|
||||
dots = "..";
|
||||
}
|
||||
|
||||
// If the path string doesn't begin with / then that means it's accessing outside the FS root, which is invalid & unsafe
|
||||
if (pathString[0] != Char('/')) return false;
|
||||
|
||||
// Counts how many folders sans the root our file is nested under.
|
||||
// If it's < 0 at any point of parsing, then the path is unsafe and tries to crawl outside our file sandbox.
|
||||
// If it's 0 then this is the FS root.
|
||||
// If it's > 0 then we're in a subdirectory of the root.
|
||||
int level = 0;
|
||||
|
||||
// Split the string on / characters and see how many of the substrings are ".."
|
||||
size_t pos = 0;
|
||||
while ((pos = pathString.find(Char('/'))) != String::npos) {
|
||||
String token = pathString.substr(0, pos);
|
||||
pathString.erase(0, pos + 1);
|
||||
|
||||
if (token == dots) {
|
||||
level--;
|
||||
if (level < 0) return false;
|
||||
} else {
|
||||
level++;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
virtual std::string name() = 0;
|
||||
virtual u64 getFreeBytes() = 0;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue