summaryrefslogtreecommitdiff
path: root/Source/Core/Common/FatFsUtil.cpp
diff options
context:
space:
mode:
authorAdmiral H. Curtiss <pikachu025@gmail.com>2022-06-16 04:15:28 +0200
committerAdmiral H. Curtiss <pikachu025@gmail.com>2022-07-11 23:11:42 +0200
commitf40eeebcf0d768a2f6400186b25b3e51e9531610 (patch)
treedf34d5fe0f9f9b2b3a62427bc12f3f3e3c3a3a50 /Source/Core/Common/FatFsUtil.cpp
parenta621fdf857460d0cb4cb493fd5dc4f3b69d37295 (diff)
FatFsUtil: Add some path traversal attack protection when unpacking.
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)