aboutsummaryrefslogtreecommitdiff
path: root/src/fs.h
diff options
context:
space:
mode:
authorRussell Yanofsky <russ@yanofsky.org>2021-09-10 00:17:20 -0400
committerRussell Yanofsky <russ@yanofsky.org>2021-10-05 11:10:47 -0400
commit6544ea5035268025207d2402db2f7d90fde947a6 (patch)
treec3f6600cfd84c8cb1c57e00bce5a83e4d44dde75 /src/fs.h
parentb39a477ec69a51b2016d3a8c70c0c77670f87f2b (diff)
downloadbitcoin-6544ea5035268025207d2402db2f7d90fde947a6.tar.xz
refactor: Block unsafe fs::path std::string conversion calls
There is no change in behavior. This just helps prepare for the transition from boost::filesystem to std::filesystem by avoiding calls to methods which will be unsafe after the transaction to std::filesystem to due lack of a boost::filesystem::path::imbue equivalent and inability to set a predictable locale. Co-authored-by: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Co-authored-by: Kiminuo <kiminuo@protonmail.com> Co-authored-by: MarcoFalke <falke.marco@gmail.com>
Diffstat (limited to 'src/fs.h')
-rw-r--r--src/fs.h58
1 files changed, 56 insertions, 2 deletions
diff --git a/src/fs.h b/src/fs.h
index 2dcd9c9860..4a0bf39e95 100644
--- a/src/fs.h
+++ b/src/fs.h
@@ -13,6 +13,7 @@
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
+#include <tinyformat.h>
/** Filesystem operations and types */
namespace fs {
@@ -23,8 +24,8 @@ using namespace boost::filesystem;
* Path class wrapper to prepare application code for transition from
* boost::filesystem library to std::filesystem implementation. The main
* purpose of the class is to define fs::path::u8string() and fs::u8path()
- * functions not present in boost. In the next git commit, it also blocks calls
- * to the fs::path(std::string) implicit constructor and the fs::path::string()
+ * functions not present in boost. It also blocks calls to the
+ * fs::path(std::string) implicit constructor and the fs::path::string()
* method, which worked well in the boost::filesystem implementation, but have
* unsafe and unpredictable behavior on Windows in the std::filesystem
* implementation (see implementation note in \ref PathToString for details).
@@ -33,7 +34,26 @@ class path : public boost::filesystem::path
{
public:
using boost::filesystem::path::path;
+
+ // Allow path objects arguments for compatibility.
path(boost::filesystem::path path) : boost::filesystem::path::path(std::move(path)) {}
+ path& operator=(boost::filesystem::path path) { boost::filesystem::path::operator=(std::move(path)); return *this; }
+ path& operator/=(boost::filesystem::path path) { boost::filesystem::path::operator/=(std::move(path)); return *this; }
+
+ // Allow literal string arguments, which are safe as long as the literals are ASCII.
+ path(const char* c) : boost::filesystem::path(c) {}
+ path& operator=(const char* c) { boost::filesystem::path::operator=(c); return *this; }
+ path& operator/=(const char* c) { boost::filesystem::path::operator/=(c); return *this; }
+ path& append(const char* c) { boost::filesystem::path::append(c); return *this; }
+
+ // Disallow std::string arguments to avoid locale-dependent decoding on windows.
+ path(std::string) = delete;
+ path& operator=(std::string) = delete;
+ path& operator/=(std::string) = delete;
+ path& append(std::string) = delete;
+
+ // Disallow std::string conversion method to avoid locale-dependent encoding on windows.
+ std::string string() const = delete;
// Define UTF-8 string conversion method not present in boost::filesystem but present in std::filesystem.
std::string u8string() const { return boost::filesystem::path::string(); }
@@ -45,6 +65,33 @@ static inline path u8path(const std::string& string)
return boost::filesystem::path(string);
}
+// Disallow implicit std::string conversion for system_complete to avoid
+// locale-dependent encoding on windows.
+static inline path system_complete(const path& p)
+{
+ return boost::filesystem::system_complete(p);
+}
+
+// Disallow implicit std::string conversion for exists to avoid
+// locale-dependent encoding on windows.
+static inline bool exists(const path& p)
+{
+ return boost::filesystem::exists(p);
+}
+
+// Allow explicit quoted stream I/O.
+static inline auto quoted(const std::string& s)
+{
+ return boost::io::quoted(s, '&');
+}
+
+// Allow safe path append operations.
+static inline path operator+(path p1, path p2)
+{
+ p1 += std::move(p2);
+ return p1;
+}
+
/**
* Convert path object to byte string. On POSIX, paths natively are byte
* strings so this is trivial. On Windows, paths natively are Unicode, so an
@@ -179,4 +226,11 @@ namespace fsbridge {
#endif // WIN32 && __GLIBCXX__
};
+// Disallow path operator<< formatting in tinyformat to avoid locale-dependent
+// encoding on windows.
+namespace tinyformat {
+template<> inline void formatValue(std::ostream&, const char*, const char*, int, const boost::filesystem::path&) = delete;
+template<> inline void formatValue(std::ostream&, const char*, const char*, int, const fs::path&) = delete;
+} // namespace tinyformat
+
#endif // BITCOIN_FS_H