1
1
#include < iostream>
2
- #include < string>
3
- #include < vector>
4
- #include < algorithm>
5
- #include < sstream>
2
+ #include < string_view>
3
+ #include < cstdlib>
4
+ #include < stdexcept>
6
5
7
- /* *
8
- * Example "allowlist" of shell commands permitted by this program.
9
- * In real-world usage, you'd carefully design or omit this approach
10
- * to avoid potential command injection altogether.
11
- */
12
- static const std::vector<std::string> ALLOWED_COMMANDS = {
13
- " ls" , // List directory
14
- " pwd" , // Print working directory
15
- " whoami" , // Show current user
16
- // Add others only if absolutely necessary
17
- };
18
-
19
- /* *
20
- * Splits a string into tokens, e.g. "ls -l /home" -> ["ls", "-l", "/home"].
21
- * Helps us separate the base command from its arguments.
22
- */
23
- std::vector<std::string> tokenize (const std::string &input) {
24
- std::vector<std::string> tokens;
25
- std::istringstream iss (input);
26
- std::string token;
27
- while (iss >> token) {
28
- tokens.push_back (token);
29
- }
30
- return tokens;
31
- }
32
-
33
- /* *
34
- * Checks if a given command (the first token) is in the ALLOWED_COMMANDS.
35
- */
36
- bool is_base_command_allowed (const std::string &cmd) {
37
- return std::find (ALLOWED_COMMANDS.begin (), ALLOWED_COMMANDS.end (), cmd)
38
- != ALLOWED_COMMANDS.end ();
39
- }
6
+ namespace app {
40
7
41
- int main () {
42
- std::cout << " Enter a shell command to run (allowed: ls, pwd, whoami): " ;
8
+ class Greeter {
9
+ public:
10
+ // Use string_view for efficient string passing
11
+ explicit Greeter (std::string_view message) noexcept
12
+ : m_message(message) {}
43
13
44
- // Safely read user input into a std::string
45
- std::string userInput;
46
- if (!std::getline (std::cin, userInput)) {
47
- std::cerr << " Error reading input or EOF reached.\n " ;
48
- return 1 ;
14
+ // Mark member functions that don't modify state as const
15
+ [[nodiscard]] auto getMessage () const noexcept -> std::string_view {
16
+ return m_message;
49
17
}
50
18
51
- // Tokenize the input: first token is the base command; subsequent tokens are arguments
52
- std::vector<std::string> tokens = tokenize (userInput);
53
- if (tokens.empty ()) {
54
- std::cerr << " No command entered.\n " ;
55
- return 1 ;
19
+ // Use auto return type for better maintainability
20
+ auto greet () const -> void {
21
+ std::cout << getMessage () << ' \n ' ;
56
22
}
57
23
58
- // The first token (base command) must match our allowlist
59
- const std::string &baseCmd = tokens[0 ];
60
- if (!is_base_command_allowed (baseCmd)) {
61
- std::cerr << " [SECURITY] Denied: Command \" " << baseCmd << " \" is not in the allowed list.\n " ;
62
- return 1 ;
63
- }
64
-
65
- // Optional: further checks on arguments if you want to allow only certain flags, etc.
66
- // For example:
67
- // for (size_t i = 1; i < tokens.size(); i++) {
68
- // // Validate each token carefully
69
- // }
24
+ private:
25
+ std::string_view m_message;
26
+ };
70
27
71
- // Construct a sanitized command string for system()
72
- // Minimal version: rejoin tokens with spaces
73
- std::ostringstream oss;
74
- for (size_t i = 0 ; i < tokens.size (); ++i) {
75
- if (i > 0 ) {
76
- oss << " " ; // separate tokens by space
77
- }
78
- oss << tokens[i];
28
+ // Use [[nodiscard]] to ensure return values are handled
29
+ [[nodiscard]] auto createGreeter (std::string_view message) -> Greeter {
30
+ if (message.empty ()) {
31
+ throw std::invalid_argument (" Message cannot be empty" );
79
32
}
80
- std::string safeCommand = oss.str ();
33
+ return Greeter{message};
34
+ }
81
35
82
- // For demonstration purposes, using system() is still risky.
83
- // A truly secure design might replicate or wrap the needed functionality without calling the shell.
84
- int result = std::system (safeCommand.c_str ());
85
- if (result == -1 ) {
86
- std::cerr << " [ERROR] Failed to execute command.\n " ;
87
- return 1 ;
36
+ } // namespace app
37
+
38
+ auto main () -> int {
39
+ try {
40
+ constexpr std::string_view message = " Hello, World!" ;
41
+ auto greeter = app::createGreeter (message);
42
+ greeter.greet ();
43
+ return EXIT_SUCCESS;
44
+ } catch (const std::exception & e) {
45
+ std::cerr << " Error: " << e.what () << ' \n ' ;
46
+ return EXIT_FAILURE;
88
47
}
89
-
90
- std::cout << " [INFO] Command completed with exit code: " << WEXITSTATUS (result) << " \n " ;
91
- return 0 ;
92
- }
48
+ }
0 commit comments