IWebCore's Security Strategy¶
In C++, security issues are a major concern. The logic of C++ is to trust the user and have the user take responsibility for their actions. This includes, but is not limited to, the following common problems:
- Memory Management Prone to Errors: For example, using a dangling pointer (pointing to released memory) or array out-of-bounds, which can cause program crashes; in severe cases, it can be exploited by hackers (such as data theft).
- Type Conversion Too Flexible: For instance, assigning a negative value to an unsigned type or a large value into a small container, leading to numerical overflow and calculation errors.
- Lack of Safety Net: For example, accessing a null pointer, unlike Java which throws a null pointer exception, C++ directly crashes.
The C++ standards committee also has a series of security proposals, and Bjarne Stroustrup has repeatedly called for C++ security solutions and strategies in public forums.
“Security issues cannot be solved by mere patching; they must be considered at the design level. We need to build security into the system, like designing a car—we want it to be fast, but we also need seatbelts and airbags.”
Therefore, in IWebCore, based on common C++ practices, we propose our own security strategy.
Compile-Time Safety¶
Users should write strict code, and certain issues should be caught during compilation. For IWebCore, we provide stricter static checks to prevent illegal or invalid code from being compiled.
-
static_assert / if constexpr:
Using static assertions and compile-time checks to block illegal code during compilation. -
Extensive Use of const in Function Signatures:
Users can restrict code compilation through function signatures. -
Template Rules:
Using SFINAE mechanisms to select valid code and block invalid or illogical code.
Runtime Initialization Fast-Fail¶
During IWebCore development, user code is task-based and modular. The code written by developers represents individual functional points, encapsulated as tasks (Task). During project initialization, all tasks are initialized, and once completed, the program begins to provide services.
Therefore, for IWebCore, users can perform early checks on code logic, functionality, and content during task execution. If the code meets certain logical requirements, it continues to execute; otherwise, the task fails immediately, exposing issues early so they can be identified and resolved during development.
For more information on Fast-Fail, please refer to the Abort-FastFail documentation.
IWebCore implements the Fast-Fail mechanism during the initial runtime phase through our Abort mechanism. For specific details, please refer to the corresponding documentation.
Runtime Safety¶
Using IResult¶
IResult is a renamed version of std::optional, allowing it to integrate naturally and seamlessly with IWebCore's naming conventions, without appearing abrupt to users.
When calling a function, the outcome depends on input content and environment, making it uncertain whether the function can correctly return the desired data. Common approaches include:
- Passing an additional variable to indicate success or failure.
- Agreeing on a specific return value to denote an error (e.g., 0 for errors, other values for success).
- Returning a composite object that includes a success/failure indicator (e.g.,
std::optional,std::expectedin standard libraries). - Throwing exceptions for the user to handle.
The first method is the fastest, and the third is the most convenient. IResult uses the third approach. In IWebCore, we extensively use IResult for handling function return values, such as numerical conversions or configuration requests.
For more details, please refer to the IResult documentation.
Exceptions¶
In my view, C++ exceptions are something to avoid whenever possible. I care less about their speed (if a problem occurs, spending time to resolve it is acceptable) but their usability is a concern. Compared to Java exceptions, C++ exceptions are like a child—unreliable and difficult to handle—while Java exceptions are like a well-behaved but overly heavy adult.
Though not ideal, there are two scenarios where exceptions must be used, but with caution. These are situations where additional variables or IResult fall short:
-
Errors in Multi-layer Function Calls:
For instance, during nested HTML callback generation, you may not know where the error occurs, but you can throw exceptions at any point, as long as they are caught at the top level. -
Unpredictable Exceptions Due to Environmental Changes:
For example, database connection changes, which involve a series of issues related to networks, servers, etc. These are usually not a concern during development but must be addressed when they occur. My approach is to throw exceptions at the top level for handling.
Additionally, some exceptions require users to handle them proactively, such as division by zero or null pointer exceptions. In Java, these might crash a thread, but in C++, they crash the entire program. Users must manually handle these exceptions through preventive programming.
For more information on exceptions in IWebCore, please refer to IException.
Secure Coding Practices¶
RAII¶
In IWebCore, we strive to avoid initializing objects with new and deleting them with delete, unless absolutely necessary. In our practices, we rarely use new to create objects; instead, we rely on well-structured code to initialize objects systematically.
Additionally, we welcome the use of static const for static local constants.
Prefer Base Classes Provided by IWebCore¶
IWebCore offers a wide range of base classes. Users can inherit from these classes and override their functions to implement custom functionality.
For more extensive content, there are numerous books available for reference.