- Avoids copying std::shared_ptr when lifetime of the RuleMessage
is controlled by the caller.
- The RuleMessage instance is created in RuleWithActions::evaluate and
then used to call the overloaded version of this method that is
specialized by subclasses.
- Once the call to the overloaded method returns, the std::shared_ptr
is destroyed as it's not stored by any of the callers, so it can
be replaced with a stack variable and avoid paying the cost of
copying the std::shared_ptr (and its control block that is
guaranteed to be thread-safe and thus is not a straightforward
pointer copy)
- Introduced RuleMessage::reset because this is required by
RuleWithActions::performLogging when it's not the 'last log', the rule
has multimatch and it's to be logged.
- The current version is creating allocating another instance of
RuleMessage on the heap to copy the Rule & Transaction related state
while all the other members in the RuleMessage are set to their
default values.
- The new version leverages the existent, unused and incomplete
function 'clean' (renamed as 'reset') to do this on the current
instance.
- Notice that the current code preserves the value of m_saveMessage,
so 'reset' provides an argument for the caller to control whether
this member should be reinitialized.
- Leverage delegating constructor to avoid code duplication between the
two available Transaction constructors.
- The constructor without 'id' argument delegates to the one that
receives it by providing `nullptr` as a value, which is used to
flag that an id needs to be generated.
- Simplified constructor by removing member initialization where the
default constructor will be invoked.
- Because the lifetime of the RuleMessage instances do not extend beyond
the lifetime of the enclosing RuleWithActions & Transaction,
RuleMessage can just reference it and simplify its definition.
- Additionally, make the references const to show that it doesn't modify it.
- Replace RuleMessage copy constructor with default implementations.
- Removed unused RuleMessage assignment operator (which cannot be implemented
now that it has reference members).
- Removed constructor from RuleMessage pointer.
- Addressed Sonarcloud suggestions: Do not use the constructor's
initializer list for data member "xxx". Use the in-class initializer
instead.
- Some of the Transformation classes would initialize their Action's
action_kind using the default (using Transformation constructor
without an action_kind parameter).
- Others, however, would use that constructor and initialize action_kind
manually in their constructor, but setting the default value
(RunTimeBeforeMatchAttemptKind = 1), which was redundant.
- Removed unused Transformation constructor to specify action_kind.
- Converted Action::Kind into an 'enum class' to require using the enum
constants (instead of integer values, which are difficult to track in
the codebase and change)
- This function already expects these arguments not to be null pointers,
doesn't validate them and just dereference them.
- In order to make this explicit and enforced by the compiler, they're
now passed as references.
- Renamed Transformation::evaluate to Transformation::transform to avoid
confusion with Action's overload methods.
- Updated Transformation::transform signature to receive the value by
reference and perform the transformation inline, if possible.
- Some transformations still need to use a temporary std::string to
perform their work, and then copy the result back.
- Made Transformation::transform methods const and updated Transaction
parameter to be const.
- Transaction parameter could not be removed because it's used by just
a single transformation, UrlDecodeUni.
- Removed std::string Action::evaluate(const std::string &exp,
Transaction *transaction); which was only implemented by
Transformation but was not used from the base class, but only after
downcasting to Transformation, so it can just be declared there (and
not pollute other actions with a default member implementation -that
does nothing- which is never called).
- cppreference mentions this about the constructor that receives a
const char *:
- Constructs the string with the contents initialized with a copy of
the null-terminated character string pointed to by s. The length of
the string is determined by the first null character. The behavior
is undefined if [s, s + Traits::length(s)) is not a valid range
(for example, if s is a null pointer).
- C++23 introduces a deleted constructor to prevent this in static
scenarios, which is how this issue was detected.
- The following methods are introduced to allow clients of
libModSecurity that are not able to link and call the C/C++ standard
library to be able to free the buffers allocated by libModSecurity.
- msc_intervention_cleanup: Frees the buffers in a
ModSecurityIntervention structure that have been allocated by calls to
msc_intervention.
- msc_rules_error_cleanup: Frees an error message buffer allocated by
the msc_rules_xxx functions to detail the condition that triggered
the error.
- SonarCloud analysis identified standalone `throw;` calls without accompanying `try-catch` blocks, used inconsistently as placeholders or for premature termination under specific conditions.
- Removed these `throw;` instances to prevent potential runtime issues in future development phases, where such configurations might inadvertently be created.
- Introduced `assert` statements as a more appropriate mechanism for asserting preconditions in the affected class member functions, ensuring clearer intent and safer code behavior during development.
- Refactor action_kind processing to use switch() instead of if-else chains; add assertion in default case.
- Fix SonarCloud issue: Make this variable a const reference.
https://sonarcloud.io/project/issues?resolved=false&pullRequest=3104&id=owasp-modsecurity_ModSecurity&open=AY8Vpgy4f6U6E7VKL4Cn
- The previous approach would create a std::unique_ptr and store it in
a std::list in VariableValue (Origins)
- The new approach now stores Origins in a std::vector and constructs
VariableOrigin elements in-place on insertion.
- Instead of having two heap-allocations for every added VariableOrigin
instance, this performs only one.
- If multiple origins are added, std::vector's growth strategy may even
prevent a heap-allocation. There's a cost on growing the size of the
vector, because a copy of current elements will be necessary.
- Introduced reserveOrigin method to notify that multiple insertions
will be made, so that we can use std::vector's reserve and do a
single allocation (and copy of previous elements), and then just
initialize the new elements in-place.
If the rx or rxGlobal operator encounters a regex error,
the RX_ERROR and RX_ERROR_RULE_ID variables are set.
RX_ERROR contains a simple error code which can be either
OTHER or MATCH_LIMIT. RX_ERROR_RULE_ID unsurprisingly
contains the ID of the rule associated with the error.
More than one rule may encounter regex errors,
but only the first error is reflected in these variables.