summaryrefslogtreecommitdiff
path: root/Source/Core/Common/FatFsUtil.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Core/Common/FatFsUtil.cpp')
-rw-r--r--Source/Core/Common/FatFsUtil.cpp18
1 files changed, 17 insertions, 1 deletions
diff --git a/Source/Core/Common/FatFsUtil.cpp b/Source/Core/Common/FatFsUtil.cpp
index 7e0c2e2a21..a3230f2cc6 100644
--- a/Source/Core/Common/FatFsUtil.cpp
+++ b/Source/Core/Common/FatFsUtil.cpp
@@ -8,8 +8,11 @@
#include <cstdlib>
#include <mutex>
#include <string>
+#include <string_view>
#include <vector>
+#include <fmt/format.h>
+
// Does not compile if diskio.h is included first.
// clang-format off
#include "ff.h"
@@ -439,8 +442,21 @@ static bool Unpack(const std::string path, bool is_directory, const char* name,
if (entry.fname[0] == '\0')
break;
- if (!Unpack(path + "/" + entry.fname, entry.fattrib & AM_DIR, entry.fname, tmp_buffer))
+ const std::string_view childname = entry.fname;
+
+ // Check for path traversal attacks.
+ if (childname.find("\\") != std::string_view::npos)
+ return false;
+ if (childname.find('/') != std::string_view::npos)
+ return false;
+ if (std::all_of(childname.begin(), childname.end(), [](char c) { return c == '.'; }))
+ return false;
+
+ if (!Unpack(fmt::format("{}/{}", path, childname), entry.fattrib & AM_DIR, entry.fname,
+ tmp_buffer))
+ {
return false;
+ }
}
if (f_closedir(&directory) != FR_OK)