33#include < cstdint>
44#include < cstdio>
55#include < cstring>
6- #include < memory>
7- #include < vector>
86#include < filesystem>
7+ #include < memory>
98#include < random>
10- #include < string>
119#include < sstream>
10+ #include < string>
11+ #include < vector>
1212
1313namespace bb {
1414
@@ -35,31 +35,25 @@ inline std::vector<uint8_t> exec_pipe_unsafe([[maybe_unused]] const std::string&
3535}
3636
3737// Tag type to mark string literals as safe
38- template <size_t N>
39- struct literal_string {
40- constexpr literal_string (const char (&str)[N]) {
41- std::copy_n (str, N, value);
42- }
38+ template <size_t N> struct literal_string {
39+ constexpr literal_string (const char (&str)[N]) { std::copy_n (str, N, value); }
4340 char value[N];
4441};
4542
4643// Helper to check if a type is a literal_string
47- template <typename T>
48- struct is_literal_string : std::false_type {};
44+ template <typename T> struct is_literal_string : std::false_type {};
4945
50- template <size_t N>
51- struct is_literal_string <literal_string<N>> : std::true_type {};
46+ template <size_t N> struct is_literal_string <literal_string<N>> : std::true_type {};
5247
53- template <typename T>
54- inline constexpr bool is_literal_string_v = is_literal_string<T>::value;
48+ template <typename T> inline constexpr bool is_literal_string_v = is_literal_string<T>::value;
5549
5650// Concept to ensure arguments are safe for command construction
57- template <typename T>
51+ template <typename T>
5852concept SafeCommandArg = std::is_arithmetic_v<std::decay_t <T>> || is_literal_string_v<std::decay_t <T>>;
5953
6054// Safe exec_pipe_safe that builds command from literal strings and numbers
61- template <SafeCommandArg... Args>
62- inline std::vector< uint8_t > exec_pipe_safe (Args... args) {
55+ template <SafeCommandArg... Args> inline std::vector< uint8_t > exec_pipe_safe (Args... args)
56+ {
6357 std::ostringstream command;
6458 auto append = [&command](auto && arg) {
6559 using T = std::decay_t <decltype (arg)>;
@@ -78,21 +72,23 @@ class SafePathSymlink {
7872 std::filesystem::path symlink_path;
7973 bool created = false ;
8074
81- static uint64_t get_random_suffix () {
75+ static uint64_t get_random_suffix ()
76+ {
8277 // Thread-local RNG for performance
8378 static thread_local std::random_device rd;
8479 static thread_local std::mt19937_64 gen (rd ());
8580 static thread_local std::uniform_int_distribution<uint64_t > dis (100000 , 99999999 );
8681 return dis (gen);
8782 }
8883
89- public:
90- explicit SafePathSymlink (const std::string& target_path) {
84+ public:
85+ explicit SafePathSymlink (const std::string& target_path)
86+ {
9187 // Generate random temporary symlink name
9288 std::filesystem::path temp_dir = std::filesystem::temp_directory_path ();
9389 std::string random_name = " bb_safe_" + std::to_string (get_random_suffix ());
9490 symlink_path = temp_dir / random_name;
95-
91+
9692 // Create symlink
9793 std::error_code ec;
9894 std::filesystem::create_symlink (target_path, symlink_path, ec);
@@ -101,30 +97,30 @@ class SafePathSymlink {
10197 }
10298 created = true ;
10399 }
104-
105- ~SafePathSymlink () {
100+
101+ ~SafePathSymlink ()
102+ {
106103 if (created) {
107104 std::error_code ec;
108105 std::filesystem::remove (symlink_path, ec);
109106 }
110107 }
111-
108+
112109 // Delete copy and move operations - only needed as stack variable in exec_pipe_with_path
113110 SafePathSymlink (const SafePathSymlink&) = delete ;
114111 SafePathSymlink& operator =(const SafePathSymlink&) = delete ;
115112 SafePathSymlink (SafePathSymlink&&) = delete ;
116113 SafePathSymlink& operator =(SafePathSymlink&&) = delete ;
117-
118- std::string path () const {
119- return symlink_path.string ();
120- }
114+
115+ std::string path () const { return symlink_path.string (); }
121116};
122117
123118// Helper function to execute a command with a safe file path (requires literal string prefixes)
124- template <size_t N1, size_t N2 = 1 >
125- inline std::vector<uint8_t > exec_pipe_with_path (const char (&command_prefix)[N1],
126- const std::string& file_path,
127- const char (&command_suffix)[N2] = "") {
119+ template <size_t N1, size_t N2 = 1 >
120+ inline std::vector<uint8_t > exec_pipe_with_path (const char (&command_prefix)[N1],
121+ const std::string& file_path,
122+ const char (&command_suffix)[N2] = "")
123+ {
128124 SafePathSymlink safe_path (file_path);
129125 std::string command = std::string (command_prefix) + safe_path.path () + std::string (command_suffix);
130126 return exec_pipe_unsafe (command);
0 commit comments