style: format code with ClangFormat and Prettier#99
style: format code with ClangFormat and Prettier#99deepsource-autofix[bot] wants to merge 3 commits into
Conversation
This commit fixes the style issues introduced in 000fa7f according to the output from ClangFormat and Prettier. Details: None
|
Here's the code health analysis summary for commits Analysis Summary
|
| void symlink(const std::filesystem::path &source, const std::filesystem::path &target); | ||
|
|
||
| void symlink_at(const std::filesystem::path &target, | ||
| const file_descriptor &dirfd, | ||
| const std::filesystem::path &link_path); | ||
| const file_descriptor &dirfd, | ||
| const std::filesystem::path &link_path); |
There was a problem hiding this comment.
Potential Naming Conflict with POSIX Functions
The function names symlink and symlink_at are identical to POSIX functions, which could lead to naming conflicts and confusion, especially in environments where POSIX functions are commonly used. This overlap might cause issues during compilation or runtime due to ambiguous references.
Recommendation: Consider renaming these functions to avoid conflicts and improve code clarity, perhaps to something like create_symlink and create_symlink_at.
| void symlink(const std::filesystem::path &source, const std::filesystem::path &target); | ||
|
|
||
| void symlink_at(const std::filesystem::path &target, | ||
| const file_descriptor &dirfd, | ||
| const std::filesystem::path &link_path); | ||
| const file_descriptor &dirfd, | ||
| const std::filesystem::path &link_path); |
There was a problem hiding this comment.
Lack of Error Handling in Function Prototypes
The prototypes for symlink and symlink_at do not provide any mechanism for error handling. File system operations can fail for various reasons (e.g., permissions, non-existent directories), and it's essential to communicate these failures back to the caller to handle them appropriately.
Recommendation: Modify the function signatures to include error handling, such as returning a status code or throwing exceptions to indicate failure conditions.
| TEST(LINYAPS_BOX, Placeholder1) | ||
| { | ||
| EXPECT_EQ(1, 1); | ||
| } |
There was a problem hiding this comment.
The test case LINYAPS_BOX, Placeholder1 contains a test that always passes (EXPECT_EQ(1, 1);). This is likely a placeholder and does not test any actual functionality. Recommendation: Implement a meaningful test that verifies specific functionality of the LINYAPS_BOX or remove this placeholder if it serves no purpose.
This PR refactors the mounting and device-configuration code to improve maintainability and comply with coding and security guidelines. We break up a large monolithic class into smaller functions, consolidate duplicated branching logic, enforce const correctness on globals, and make all implicit conversions explicit. - Function with cyclomatic complexity higher than threshold: We extracted the core mounting logic from the original `mounter` class into six focused helper functions (`processCgroupMount`, `setupMountDestination`, `needsRemount`, `computeRemountFlags`, `finalizeRemount`, and `do_mount`). Each helper now handles a single responsibility, drastically reducing the cyclomatic complexity of any individual function and making the control flow easier to follow. - Audit required: found a non-const global variable: All previously mutable globals were either declared inside anonymous namespaces or marked `static const`. For example, the return value of `getenv` is now `static const char* const`, and flag lookup tables (`mount_flags`, `flagInfos`) are defined as `static constexpr` arrays to prevent unintended modifications at runtime. - Empty exception handler block: Several catch blocks that previously had empty bodies are now explicitly rethrowing exceptions with `throw;`. This ensures that errors are not silently swallowed, improving observability and error reporting. - Found redundant cloned branches: We replaced dozens of nearly identical `if` statements that tested and appended flag names with data-driven loops over `mount_flags` and `flagInfos`. This removes redundant code clones and centralizes flag metadata. - Avoid array-to-pointer decay: Instead of manual pointer arithmetic and array decay, we use range-based for loops over `static constexpr` arrays. This preserves compile-time size information, avoids pointer decay, and makes iterations safer and clearer. - Found an implicit conversion across boolean and other primitive type: Conditions such as `if (*c)` have been changed to `if (*c != '\0')`, stream checks use explicit methods (`!ofs.is_open()`) or `static_cast<bool>`, and boolean contexts are now unambiguous, preventing hidden type conversions. - Implicit deletion of copy and move assignment constructors due to non-static const data member: The original `mounter` class contained non-static const members which disabled default assignment operators. By removing the class and using free functions instead, we avoid the implicit deletion issue and simplify object semantics. > This Autofix was generated by AI. Please review the change before merging.
| std::stringstream result; | ||
| for (int i = 0; i < argc; ++i) { | ||
| result << " \""; | ||
| for (char *c = argv[i]; *c; ++c) { | ||
| for (char *c = argv[i]; *c != '\0'; ++c) { | ||
| if (*c == '\\') { | ||
| result << "\\\\"; | ||
| } else if (*c == '"') { |
There was a problem hiding this comment.
The use of std::stringstream inside a loop that processes each character of command line arguments can lead to performance inefficiencies due to potential frequent memory reallocations. Consider using a more efficient string concatenation strategy, such as reserving an estimated amount of space in the std::stringstream object before the loop starts.
Suggested Change:
std::stringstream result;
result.reserve(estimated_size); // estimate based on typical argv content sizeThis pre-allocation can help in reducing the number of memory allocations during string construction.
| std::stringstream result; | ||
| for (int i = 0; i < argc; ++i) { | ||
| result << " \""; | ||
| for (char *c = argv[i]; *c; ++c) { | ||
| for (char *c = argv[i]; *c != '\0'; ++c) { | ||
| if (*c == '\\') { | ||
| result << "\\\\"; | ||
| } else if (*c == '"') { |
There was a problem hiding this comment.
The nested loop structure for escaping special characters in command line arguments makes the code hard to read and maintain. Consider abstracting this functionality into a separate utility function that handles the escaping of strings. This would not only improve readability but also enhance reusability of the escaping logic across different parts of your application.
Suggested Change:
std::string escape_string(const char* input) {
std::string result;
for (; *input != '\0'; ++input) {
switch (*input) {
case '\\': result += "\\\\"; break;
case '"': result += "\\\""; break;
default: result += *input;
}
}
return result;
}Then replace the inner loop with a call to escape_string(argv[i]).
| private: | ||
| std::string id; | ||
| const status_directory &status_dir_; | ||
| const status_directory *status_dir_; |
There was a problem hiding this comment.
The use of a raw pointer status_dir_ for referencing status_directory instances can lead to potential memory management issues, such as dangling pointers if the status_directory object is deleted elsewhere. Consider using smart pointers like std::shared_ptr or std::unique_ptr to automatically manage the lifetime of the object and prevent such issues.
Recommended Change:
std::shared_ptr<const status_directory> status_dir_;| @@ -26,7 +26,7 @@ class container_ref | |||
|
|
|||
| private: | |||
| std::string id; | |||
There was a problem hiding this comment.
The id member variable is mutable, which might not be desirable if the identifier should remain constant after the object's construction. To enforce immutability and prevent accidental modification, consider declaring id as const std::string.
Recommended Change:
const std::string id;|
|
||
| std::stringstream ss; | ||
| std::string key; | ||
| while (fdinfo >> key) { | ||
| while (static_cast<bool>(fdinfo >> key)) { | ||
| ss << " " << key << " "; | ||
| if (key != "flags:") { | ||
| std::string value; |
There was a problem hiding this comment.
The function inspect_fdinfo lacks proper error handling for file operations. Using assert to check if the file is open is not sufficient for production code as it only works in debug mode and does not provide a way to handle the error gracefully in release builds.
Recommendation:
Replace assert(fdinfo.is_open()); with proper error checking and handling. If the file cannot be opened, log an error and return an appropriate error message or code. This will make the function more robust and prevent potential crashes or undefined behavior in scenarios where the file cannot be accessed.
|
|
||
| std::string inspect_fcntl_or_open_flags(size_t flags) | ||
| { | ||
| std::stringstream ss; | ||
| struct FlagInfo { size_t mask; const char* name; }; | ||
| static constexpr FlagInfo flagInfos[] = { | ||
| { O_RDONLY, "O_RDONLY" }, | ||
| { O_WRONLY, "O_WRONLY" }, | ||
| { O_RDWR, "O_RDWR" }, | ||
| { O_CREAT, "O_CREAT" }, | ||
| { O_EXCL, "O_EXCL" }, | ||
| { O_NOCTTY, "O_NOCTTY" }, | ||
| { O_TRUNC, "O_TRUNC" }, | ||
| { O_APPEND, "O_APPEND" }, | ||
| { O_NONBLOCK, "O_NONBLOCK" }, | ||
| { O_NDELAY, "O_NDELAY" }, | ||
| { O_SYNC, "O_SYNC" }, | ||
| { O_ASYNC, "O_ASYNC" }, | ||
| { O_LARGEFILE, "O_LARGEFILE" }, | ||
| { O_DIRECTORY, "O_DIRECTORY" }, | ||
| { O_NOFOLLOW, "O_NOFOLLOW" }, | ||
| { O_CLOEXEC, "O_CLOEXEC" }, | ||
| { O_DIRECT, "O_DIRECT" }, | ||
| { O_NOATIME, "O_NOATIME" }, | ||
| { O_PATH, "O_PATH" }, | ||
| { O_DSYNC, "O_DSYNC" }, | ||
| { O_TMPFILE, "O_TMPFILE" } | ||
| }; | ||
|
|
||
| std::stringstream ss; | ||
| ss << "["; | ||
| if ((flags & O_RDONLY) != 0) { | ||
| ss << " O_RDONLY"; | ||
| } | ||
| if ((flags & O_WRONLY) != 0) { | ||
| ss << " O_WRONLY"; | ||
| } | ||
| if ((flags & O_RDWR) != 0) { | ||
| ss << " O_RDWR"; | ||
| } | ||
| if ((flags & O_CREAT) != 0) { | ||
| ss << " O_CREAT"; | ||
| } | ||
| if ((flags & O_EXCL) != 0) { | ||
| ss << " O_EXCL"; | ||
| } | ||
| if ((flags & O_NOCTTY) != 0) { | ||
| ss << " O_NOCTTY"; | ||
| } | ||
| if ((flags & O_TRUNC) != 0) { | ||
| ss << " O_TRUNC"; | ||
| } | ||
| if ((flags & O_APPEND) != 0) { | ||
| ss << " O_APPEND"; | ||
| } | ||
| if ((flags & O_NONBLOCK) != 0) { | ||
| ss << " O_NONBLOCK"; | ||
| } | ||
| if ((flags & O_NDELAY) != 0) { | ||
| ss << " O_NDELAY"; | ||
| } | ||
| if ((flags & O_SYNC) != 0) { | ||
| ss << " O_SYNC"; | ||
| } | ||
| if ((flags & O_ASYNC) != 0) { | ||
| ss << " O_ASYNC"; | ||
| } | ||
| if ((flags & O_LARGEFILE) != 0) { | ||
| ss << " O_LARGEFILE"; | ||
| } | ||
| if ((flags & O_DIRECTORY) != 0) { | ||
| ss << " O_DIRECTORY"; | ||
| } | ||
| if ((flags & O_NOFOLLOW) != 0) { | ||
| ss << " O_NOFOLLOW"; | ||
| } | ||
| if ((flags & O_CLOEXEC) != 0) { | ||
| ss << " O_CLOEXEC"; | ||
| } | ||
| if ((flags & O_DIRECT) != 0) { | ||
| ss << " O_DIRECT"; | ||
| } | ||
| if ((flags & O_NOATIME) != 0) { | ||
| ss << " O_NOATIME"; | ||
| } | ||
| if ((flags & O_PATH) != 0) { | ||
| ss << " O_PATH"; | ||
| } | ||
| if ((flags & O_DSYNC) != 0) { | ||
| ss << " O_DSYNC"; | ||
| } | ||
| if ((flags & O_TMPFILE) == O_TMPFILE) { | ||
| ss << " O_TMPFILE"; | ||
| for (const auto& info : flagInfos) { | ||
| if ((flags & info.mask) == info.mask) { | ||
| ss << " " << info.name; | ||
| } | ||
| } | ||
| ss << " ]"; | ||
| return ss.str(); |
There was a problem hiding this comment.
The function inspect_fcntl_or_open_flags iterates over all possible flags even after all flags have been matched. This results in unnecessary processing and can affect performance, especially with a large number of flags.
Recommendation:
Implement a mechanism to break out of the loop once all flags have been matched. This could involve keeping a count of matched flags and comparing it against the number of flags set in the input. This optimization will reduce the number of iterations and improve the function's performance.
| static const char *const result = getenv("LINYAPS_BOX_LOG_FORCE_STDERR"); | ||
| return result != nullptr; |
There was a problem hiding this comment.
The use of getenv in a potentially multi-threaded environment can lead to race conditions, as getenv is not thread-safe. This could result in undefined behavior if environment variables are modified concurrently.
Recommendation:
Consider using a thread-safe alternative or ensure that environment variables are not modified after the program starts. Additionally, caching the result of getenv after the first call can prevent repeated environment lookups, improving performance.
| static linyaps_box::config::process_t parse_process(const nlohmann::json &j, | ||
| const nlohmann::json::json_pointer &ptr) | ||
| { | ||
| linyaps_box::config::process_t proc; | ||
| if (j.contains(ptr / "process" / "terminal")) { | ||
| proc.terminal = j[ptr / "process" / "terminal"].get<bool>(); | ||
| } | ||
| if (proc.terminal && j.contains(ptr / "process" / "consoleSize")) { | ||
| proc.console.height = j[ptr / "process" / "consoleSize" / "height"].get<uint>(); | ||
| proc.console.width = j[ptr / "process" / "consoleSize" / "width"].get<uint>(); | ||
| } | ||
| proc.cwd = j[ptr / "process" / "cwd"].get<std::string>(); | ||
| if (j.contains(ptr / "process" / "env")) { | ||
| auto env = j[ptr / "process" / "env"].get<std::vector<std::string>>(); | ||
| for (const auto &e : env) { | ||
| auto pos = e.find('='); | ||
| if (pos == std::string::npos) { | ||
| throw std::runtime_error("invalid env entry: " + e); | ||
| } | ||
| } | ||
| proc.env = std::move(env); | ||
| } | ||
| proc.args = j[ptr / "process" / "args"].get<std::vector<std::string>>(); | ||
| if (auto rlimits = ptr / "process" / "rlimits"; j.contains(rlimits)) { | ||
| proc.rlimits = parse_rlimits(j, rlimits); | ||
| } | ||
| #ifdef LINYAPS_BOX_ENABLE_CAP | ||
| if (auto cap = ptr / "process" / "capabilities"; j.contains(cap)) { | ||
| proc.capabilities = parse_capability(j, cap); | ||
| } | ||
| #endif | ||
| if (j.contains(ptr / "process" / "noNewPrivileges")) { | ||
| proc.no_new_privileges = j[ptr / "process" / "noNewPrivileges"].get<bool>(); | ||
| } | ||
| return proc; | ||
| } |
There was a problem hiding this comment.
Error Handling and Security Concern
The function parse_process lacks robust error handling for malformed environment variables. If an environment variable string does not contain an '=' character, it throws a runtime error (line 285), which could be exploited to cause a denial of service if the input is not controlled.
Recommendation:
- Implement more comprehensive validation of the input JSON structure before processing. Consider using a schema validation library to ensure all inputs meet expected formats and contain necessary characters like '=' in environment variables. This would prevent the application from throwing runtime errors unexpectedly and improve the overall security and stability of the configuration parsing.
| @@ -265,6 +265,43 @@ linyaps_box::config::linux_t parse_linux(const nlohmann::json &obj, | |||
| return linux; | |||
| } | |||
There was a problem hiding this comment.
Maintainability and Modularity Issue
The parse_linux function handles multiple aspects of the Linux configuration parsing, making it lengthy and complex. This decreases maintainability and readability.
Recommendation:
- Refactor
parse_linuxinto smaller, more focused functions. Each function should handle a specific part of the Linux configuration, such as parsing user IDs, group IDs, or namespaces. This modular approach would make the code easier to manage, test, and debug.
This commit fixes the style issues introduced in 000fa7f according to the output
from ClangFormat and Prettier.
Details: None