From 699f140c9fd0c9d514f1081cd8b101ed9ee7f22d Mon Sep 17 00:00:00 2001 From: Mikel Olasagasti Uranga Date: Fri, 15 May 2026 11:23:15 +0200 Subject: [PATCH 01/23] Fix sign-compare warning in anchored set variable translation proxy Use vector::size_type for the loop index when iterating over resolved variable values, avoiding a signed/unsigned comparison with size(). Fixes GCC -Wsign-compare: ../headers/modsecurity/anchored_set_variable_translation_proxy.h:46:31: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector::size_type' {aka 'long unsigned int'} [-Wsign-compare] Signed-off-by: Mikel Olasagasti Uranga --- headers/modsecurity/anchored_set_variable_translation_proxy.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/headers/modsecurity/anchored_set_variable_translation_proxy.h b/headers/modsecurity/anchored_set_variable_translation_proxy.h index 37767b980c..e5b3ff9437 100644 --- a/headers/modsecurity/anchored_set_variable_translation_proxy.h +++ b/headers/modsecurity/anchored_set_variable_translation_proxy.h @@ -43,7 +43,8 @@ class AnchoredSetVariableTranslationProxy { m_fount(fount) { m_translate = [](const std::string *name, std::vector *l) { - for (int i = 0; i < l->size(); ++i) { + for (std::vector::size_type i = 0; + i < l->size(); ++i) { VariableValue *newVariableValue = new VariableValue(name, &l->at(i)->getKey(), &l->at(i)->getKey()); const VariableValue *oldVariableValue = l->at(i); l->at(i) = newVariableValue; From 067c1fc11ffef27a73eb7862a4c221fcd07a14bb Mon Sep 17 00:00:00 2001 From: Mikel Olasagasti Uranga Date: Fri, 15 May 2026 11:25:54 +0200 Subject: [PATCH 02/23] Fix unused-function warnings for intervention helpers in header Mark intervention::{reset,clean,freeUrl,freeLog,free} as inline so they are not emitted as unused static functions in every translation unit that includes intervention.h. Fixes GCC -Wunused-function: ../headers/modsecurity/intervention.h:39:17: warning: 'void modsecurity::intervention::clean(...)' defined but not used [-Wunused-function] ../headers/modsecurity/intervention.h:59:17: warning: 'void modsecurity::intervention::free(...)' defined but not used [-Wunused-function] Signed-off-by: Mikel Olasagasti Uranga --- headers/modsecurity/intervention.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/headers/modsecurity/intervention.h b/headers/modsecurity/intervention.h index af88e85813..f6280b4f1a 100644 --- a/headers/modsecurity/intervention.h +++ b/headers/modsecurity/intervention.h @@ -30,33 +30,33 @@ typedef struct ModSecurityIntervention_t { #ifdef __cplusplus namespace intervention { - static void reset(ModSecurityIntervention_t *i) { + inline void reset(ModSecurityIntervention_t *i) { i->status = 200; i->pause = 0; i->disruptive = 0; } - static void clean(ModSecurityIntervention_t *i) { + inline void clean(ModSecurityIntervention_t *i) { i->url = NULL; i->log = NULL; reset(i); } - static void freeUrl(ModSecurityIntervention_t *i) { + inline void freeUrl(ModSecurityIntervention_t *i) { if (i->url) { free(i->url); i->url = NULL; } } - static void freeLog(ModSecurityIntervention_t *i) { + inline void freeLog(ModSecurityIntervention_t *i) { if (i->log) { free(i->log); i->log = NULL; } } - static void free(ModSecurityIntervention_t *i) { + inline void free(ModSecurityIntervention_t *i) { freeUrl(i); freeLog(i); } From 0871489e6837c72ec083da47bda4656c1beeb119 Mon Sep 17 00:00:00 2001 From: Mikel Olasagasti Uranga Date: Fri, 15 May 2026 11:30:00 +0200 Subject: [PATCH 03/23] Fix sign-compare warning in utils::string::limitTo Use std::string::size_type for the length limit so it matches str.length() and assign()'s count parameter. Fixes GCC -Wsign-compare: ../src/utils/string.h:94:22: warning: comparison of integer expressions of different signedness: 'std::__cxx11::basic_string::size_type' and 'int' [-Wsign-compare] Signed-off-by: Mikel Olasagasti Uranga --- src/utils/string.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/string.h b/src/utils/string.h index ac3264aeab..5976e8b595 100644 --- a/src/utils/string.h +++ b/src/utils/string.h @@ -89,7 +89,7 @@ inline std::string dash_if_empty(const std::string *str) { } -inline std::string limitTo(int amount, const std::string &str) { +inline std::string limitTo(std::string::size_type amount, const std::string &str) { std::string ret; if (str.length() > amount) { From 57c86417578937bab1ca359a70a91c8702483ecf Mon Sep 17 00:00:00 2001 From: Mikel Olasagasti Uranga Date: Fri, 15 May 2026 11:32:16 +0200 Subject: [PATCH 04/23] Fix -Wreorder in VariableDictElement constructor Initialize the Variable base class before m_dictElement, matching member declaration order. Fixes GCC -Wreorder: ../src/variables/variable.h:635:17: warning: 'm_dictElement' will be initialized after base 'Variable' [-Wreorder] Signed-off-by: Mikel Olasagasti Uranga --- src/variables/variable.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/variables/variable.h b/src/variables/variable.h index 06f407f2c3..3388553c7f 100644 --- a/src/variables/variable.h +++ b/src/variables/variable.h @@ -634,7 +634,7 @@ class Variable : public VariableMonkeyResolution { class VariableDictElement : public Variable { public: VariableDictElement(const std::string &name, const std::string &dict_element) - : m_dictElement(dict_element), Variable(name + ":" + dict_element) { } + : Variable(name + ":" + dict_element), m_dictElement(dict_element) { } std::string m_dictElement; }; From 92653c844059baa70c4f3d4130c63da9ee75024e Mon Sep 17 00:00:00 2001 From: Mikel Olasagasti Uranga Date: Fri, 15 May 2026 11:33:03 +0200 Subject: [PATCH 05/23] Fix -Wreorder in VariableRegex constructor Initialize the Variable base class before m_r and m_regex, matching member declaration order. Fixes GCC -Wreorder: ../src/variables/variable.h:648:17: warning: 'm_regex' will be initialized after base 'Variable' [-Wreorder] Signed-off-by: Mikel Olasagasti Uranga --- src/variables/variable.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/variables/variable.h b/src/variables/variable.h index 3388553c7f..80d0d85be4 100644 --- a/src/variables/variable.h +++ b/src/variables/variable.h @@ -643,9 +643,9 @@ class VariableDictElement : public Variable { class VariableRegex : public Variable { public: VariableRegex(const std::string &name, const std::string ®ex) - : m_r(regex, true), - m_regex(regex), - Variable(name + ":" + "regex(" + regex + ")") { } + : Variable(name + ":" + "regex(" + regex + ")"), + m_r(regex, true), + m_regex(regex) { } Utils::Regex m_r; // FIXME: no need for that. From 1e56bda1010b72837f7ef79576ea484b23369a35 Mon Sep 17 00:00:00 2001 From: Mikel Olasagasti Uranga Date: Fri, 15 May 2026 11:38:31 +0200 Subject: [PATCH 06/23] Fix sign-compare warning in InitCol::init Use std::string::size_type for the position returned by find(), avoiding comparison with std::string::npos as a signed int. Fixes GCC -Wsign-compare: actions/init_col.cc:37:19: warning: comparison of integer expressions of different signedness [-Wsign-compare] Signed-off-by: Mikel Olasagasti Uranga --- src/actions/init_col.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/actions/init_col.cc b/src/actions/init_col.cc index 0c6fafe95f..d1ca8b3d37 100644 --- a/src/actions/init_col.cc +++ b/src/actions/init_col.cc @@ -28,7 +28,7 @@ namespace actions { bool InitCol::init(std::string *error) { - int posEquals = m_parser_payload.find("="); + const std::string::size_type posEquals = m_parser_payload.find("="); if (m_parser_payload.size() < 2) { error->assign("Something wrong with initcol format: too small"); From 6a62374867dfc1c55d3aeec061ffa017aef82c73 Mon Sep 17 00:00:00 2001 From: Mikel Olasagasti Uranga Date: Fri, 15 May 2026 11:39:34 +0200 Subject: [PATCH 07/23] Fix sign-compare warnings in ModSecurity::processContentOffset Cast parsed highlight offsets to size_t before comparing with content and variable lengths. Fixes GCC -Wsign-compare: modsecurity.cc:271:30: warning: comparison of integer expressions of different signedness [-Wsign-compare] modsecurity.cc:350:30: warning: comparison of integer expressions of different signedness [-Wsign-compare] Signed-off-by: Mikel Olasagasti Uranga --- src/modsecurity.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modsecurity.cc b/src/modsecurity.cc index 487efa4af5..e1f9d512a1 100644 --- a/src/modsecurity.cc +++ b/src/modsecurity.cc @@ -268,7 +268,7 @@ int ModSecurity::processContentOffset(const char *content, size_t len, size.size()); yajl_gen_map_close(g); - if (stoi(startingAt) >= len) { + if (static_cast(stoi(startingAt)) >= len) { *err = "Offset is out of the content limits."; return -1; } @@ -347,7 +347,7 @@ int ModSecurity::processContentOffset(const char *content, size_t len, size.size()); yajl_gen_map_close(g); - if (stoi(startingAt) >= varValue.size()) { + if (static_cast(stoi(startingAt)) >= varValue.size()) { *err = "Offset is out of the variable limits."; return -1; } From d52a2c4b0de79ecc4c9ec5384ce49ffc97c36077 Mon Sep 17 00:00:00 2001 From: Mikel Olasagasti Uranga Date: Fri, 15 May 2026 11:40:20 +0200 Subject: [PATCH 08/23] Fix -Wreorder in Rx and RxGlobal constructor Initialize the Operator base class before m_re, matching member declaration order. Fixes GCC -Wreorder: ../src/operators/rx.h:62:12: warning: 'm_re' will be initialized after base 'Operator' [-Wreorder] ../src/operators/rx_global.h:62:12: warning: 'm_re' will be initialized after base 'Operator' [-Wreorder] Signed-off-by: Mikel Olasagasti Uranga --- src/operators/rx.h | 5 ++--- src/operators/rx_global.h | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/operators/rx.h b/src/operators/rx.h index 03d33700cd..8973d746d0 100644 --- a/src/operators/rx.h +++ b/src/operators/rx.h @@ -37,8 +37,7 @@ class Rx : public Operator { public: /** @ingroup ModSecurity_Operator */ explicit Rx(std::unique_ptr param) - : m_re(nullptr), - Operator("Rx", std::move(param)) { + : Operator("Rx", std::move(param)) { m_couldContainsMacro = true; } @@ -59,7 +58,7 @@ class Rx : public Operator { bool init(const std::string &arg, std::string *error) override; private: - Regex *m_re; + Regex *m_re = nullptr; }; diff --git a/src/operators/rx_global.h b/src/operators/rx_global.h index e41ff2781d..e2b490ee6d 100644 --- a/src/operators/rx_global.h +++ b/src/operators/rx_global.h @@ -37,8 +37,7 @@ class RxGlobal : public Operator { public: /** @ingroup ModSecurity_Operator */ explicit RxGlobal(std::unique_ptr param) - : m_re(nullptr), - Operator("RxGlobal", std::move(param)) { + : Operator("RxGlobal", std::move(param)) { m_couldContainsMacro = true; } @@ -59,7 +58,7 @@ class RxGlobal : public Operator { bool init(const std::string &arg, std::string *error) override; private: - Regex *m_re; + Regex *m_re = nullptr; }; From fa25fbaa25d0795624e44c1421e447f975615ba1 Mon Sep 17 00:00:00 2001 From: Mikel Olasagasti Uranga Date: Fri, 15 May 2026 11:41:46 +0200 Subject: [PATCH 09/23] Fix sign-compare warning in RulesSet::evaluate Use size_t for the rule loop index when comparing against rules->size(). Fixes GCC -Wsign-compare: rules_set.cc:147:23: warning: comparison of integer expressions of different signedness [-Wsign-compare] Signed-off-by: Mikel Olasagasti Uranga --- src/rules_set.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rules_set.cc b/src/rules_set.cc index 96bfa689ad..f7545c6597 100644 --- a/src/rules_set.cc +++ b/src/rules_set.cc @@ -144,7 +144,7 @@ int RulesSet::evaluate(int phase, Transaction *t) { t->m_allowType = actions::disruptive::NoneAllowType; //} - for (int i = 0; i < rules->size(); i++) { + for (size_t i = 0; i < rules->size(); i++) { // FIXME: This is not meant to be here. At the end of this refactoring, // the shared pointer won't be used. auto rule = rules->at(i); From 666f2cec4ed9700f9f9d6e83ec40197804447ce1 Mon Sep 17 00:00:00 2001 From: Mikel Olasagasti Uranga Date: Fri, 15 May 2026 11:46:16 +0200 Subject: [PATCH 10/23] Remove unused variables in seclang parser runtime-var rules Drop dead `char z = name.at(0)` assignments from RUN_TIME_VAR_* grammar actions; the first character was never used. Fixes GCC -Wunused-variable: seclang-parser.yy:2591:14: warning: unused variable 'z' [-Wunused-variable] Signed-off-by: Mikel Olasagasti Uranga --- src/parser/seclang-parser.yy | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/parser/seclang-parser.yy b/src/parser/seclang-parser.yy index c3aa5bc4bc..7629339343 100644 --- a/src/parser/seclang-parser.yy +++ b/src/parser/seclang-parser.yy @@ -2588,7 +2588,6 @@ var: | RUN_TIME_VAR_DUR { std::string name($1); - char z = name.at(0); std::unique_ptr c(new Duration(name)); $$ = std::move(c); } @@ -2596,84 +2595,72 @@ var: | RUN_TIME_VAR_BLD { std::string name($1); - char z = name.at(0); std::unique_ptr c(new ModsecBuild(name)); $$ = std::move(c); } | RUN_TIME_VAR_HSV { std::string name($1); - char z = name.at(0); std::unique_ptr c(new HighestSeverity(name)); $$ = std::move(c); } | RUN_TIME_VAR_REMOTE_USER { std::string name($1); - char z = name.at(0); std::unique_ptr c(new RemoteUser(name)); $$ = std::move(c); } | RUN_TIME_VAR_TIME { std::string name($1); - char z = name.at(0); std::unique_ptr c(new Time(name)); $$ = std::move(c); } | RUN_TIME_VAR_TIME_DAY { std::string name($1); - char z = name.at(0); std::unique_ptr c(new TimeDay(name)); $$ = std::move(c); } | RUN_TIME_VAR_TIME_EPOCH { std::string name($1); - char z = name.at(0); std::unique_ptr c(new TimeEpoch(name)); $$ = std::move(c); } | RUN_TIME_VAR_TIME_HOUR { std::string name($1); - char z = name.at(0); std::unique_ptr c(new TimeHour(name)); $$ = std::move(c); } | RUN_TIME_VAR_TIME_MIN { std::string name($1); - char z = name.at(0); std::unique_ptr c(new TimeMin(name)); $$ = std::move(c); } | RUN_TIME_VAR_TIME_MON { std::string name($1); - char z = name.at(0); std::unique_ptr c(new TimeMon(name)); $$ = std::move(c); } | RUN_TIME_VAR_TIME_SEC { std::string name($1); - char z = name.at(0); std::unique_ptr c(new TimeSec(name)); $$ = std::move(c); } | RUN_TIME_VAR_TIME_WDAY { std::string name($1); - char z = name.at(0); std::unique_ptr c(new TimeWDay(name)); $$ = std::move(c); } | RUN_TIME_VAR_TIME_YEAR { std::string name($1); - char z = name.at(0); std::unique_ptr c(new TimeYear(name)); $$ = std::move(c); } From 74b802c50b9347f8635e73f3aa2226b5e43538ff Mon Sep 17 00:00:00 2001 From: Mikel Olasagasti Uranga Date: Fri, 15 May 2026 11:50:36 +0200 Subject: [PATCH 11/23] Fix compiler warnings in msc_tree.cc Align integer types for bit/count comparisons in CPTAddElement, remove an unused variable, and compute CIDR slash position safely in TreeAddIP. Fixes -Wsign-compare and -Wunused-variable in CPTAddElement and TreeAddIP. Signed-off-by: Mikel Olasagasti Uranga --- src/utils/msc_tree.cc | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/utils/msc_tree.cc b/src/utils/msc_tree.cc index ea6c1a4167..309d0cece0 100644 --- a/src/utils/msc_tree.cc +++ b/src/utils/msc_tree.cc @@ -298,7 +298,7 @@ int InsertNetmask(TreeNode *node, TreeNode *parent, TreeNode *new_node, TreeNode *CPTAddElement(unsigned char *ipdata, unsigned int ip_bitmask, CPTTree *tree, unsigned char netmask) { unsigned char *buffer = NULL; unsigned char bitlen = 0; - int bit_validation = 0, test_bit = 0; + unsigned int bit_validation = 0, test_bit = 0; size_t i = 0; unsigned int x, y; TreeNode *node = NULL, *new_node = NULL; @@ -357,7 +357,7 @@ TreeNode *CPTAddElement(unsigned char *ipdata, unsigned int ip_bitmask, CPTTree else bit_validation = bitlen; - for (i = 0; (i * NETMASK_8) < bit_validation; i++) { + for (i = 0; (i * NETMASK_8) < static_cast(bit_validation); i++) { int net = 0, div = 0; int cnt = 0; int temp; @@ -483,8 +483,8 @@ TreeNode *CPTAddElement(unsigned char *ipdata, unsigned int ip_bitmask, CPTTree if (node->netmasks != NULL) { i = 0; - int j; - while(i < node->count) { + size_t j; + while (i < static_cast(node->count)) { if (node->netmasks[i] < test_bit + 1) break; i++; @@ -501,7 +501,7 @@ TreeNode *CPTAddElement(unsigned char *ipdata, unsigned int ip_bitmask, CPTTree } j = 0; - while (j < (node->count - i)) { + while (j < static_cast(node->count) - i) { i_node->netmasks[j] = node->netmasks[i + j]; j++; } @@ -833,19 +833,22 @@ TreeNode *CPTIpMatch(unsigned char *ipdata, CPTTree *tree, int type) { } TreeNode *TreeAddIP(const char *buffer, CPTTree *tree, int type) { - unsigned long ip; int ret; unsigned char netmask_v4 = NETMASK_32, netmask_v6 = NETMASK_128; char ip_strv4[NETMASK_32], ip_strv6[NETMASK_128]; struct in_addr addr4; struct in6_addr addr6; - int pos = 0; + const char *slash = NULL; + size_t pos = 0; char *ptr = NULL; if(tree == NULL) return NULL; - pos = strchr(buffer, '/') - buffer; + slash = strchr(buffer, '/'); + if (slash != NULL) { + pos = static_cast(slash - buffer); + } switch(type) { @@ -871,7 +874,7 @@ TreeNode *TreeAddIP(const char *buffer, CPTTree *tree, int type) { if (netmask_v4 == 0) { return NULL; } - else if (pos < strlen(ip_strv4)) { + else if (slash != NULL && pos < strlen(ip_strv4)) { ip_strv4[pos] = '\0'; } @@ -908,7 +911,8 @@ TreeNode *TreeAddIP(const char *buffer, CPTTree *tree, int type) { if(netmask_v6 == 0) { return NULL; } - else if (netmask_v6 != NETMASK_128 && pos < strlen(ip_strv6)) { + else if (slash != NULL && netmask_v6 != NETMASK_128 && + pos < strlen(ip_strv6)) { ip_strv6[pos] = '\0'; } From 311e04aa809870a1e5b7719ea85ad4d0cb6f0c20 Mon Sep 17 00:00:00 2001 From: Mikel Olasagasti Uranga Date: Fri, 15 May 2026 11:54:24 +0200 Subject: [PATCH 12/23] Fix snprintf and sign-compare warnings in utf8_to_unicode Use sizeof(unicode) for the hex snprintf buffer size, strlen() for the formatted hex digit length, and size_t for the length and loop indices. Fixes -Wsizeof-pointer-memaccess and -Wsign-compare in actions/transformations/utf8_to_unicode.cc. Signed-off-by: Mikel Olasagasti Uranga --- .../transformations/utf8_to_unicode.cc | 38 ++++++++++++++----- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/src/actions/transformations/utf8_to_unicode.cc b/src/actions/transformations/utf8_to_unicode.cc index 813534a907..a4691833c3 100644 --- a/src/actions/transformations/utf8_to_unicode.cc +++ b/src/actions/transformations/utf8_to_unicode.cc @@ -15,7 +15,7 @@ #include "utf8_to_unicode.h" -#include +#include #include "src/utils/string.h" @@ -78,12 +78,18 @@ static inline bool encode(std::string &value) { unicode_len = 2; count += 6; if (count <= len) { - int length = 0; + size_t length = 0; /* compute character number */ d = ((c & 0x1F) << 6) | (*(utf + 1) & 0x3F); *data++ = '%'; *data++ = 'u'; - length = snprintf(unicode, sizeof(unicode), "%x", d); + const int written = std::snprintf(unicode, sizeof(unicode), + "%x", d); + if (written < 0 + || static_cast(written) >= sizeof(unicode)) { + return changed; + } + length = static_cast(written); switch (length) { case 1: @@ -103,7 +109,7 @@ static inline bool encode(std::string &value) { break; } - for (int j = 0; j < length; j++) { + for (size_t j = 0; j < length; j++) { *data++ = unicode[j]; } @@ -125,14 +131,20 @@ static inline bool encode(std::string &value) { unicode_len = 3; count+=6; if (count <= len) { - int length = 0; + size_t length = 0; /* compute character number */ d = ((c & 0x0F) << 12) | ((*(utf + 1) & 0x3F) << 6) | (*(utf + 2) & 0x3F); *data++ = '%'; *data++ = 'u'; - length = snprintf(unicode, sizeof(unicode), "%x", d); + const int written = std::snprintf(unicode, sizeof(unicode), + "%x", d); + if (written < 0 + || static_cast(written) >= sizeof(unicode)) { + return changed; + } + length = static_cast(written); switch (length) { case 1: @@ -152,7 +164,7 @@ static inline bool encode(std::string &value) { break; } - for (int j = 0; j < length; j++) { + for (size_t j = 0; j < length; j++) { *data++ = unicode[j]; } @@ -183,7 +195,7 @@ static inline bool encode(std::string &value) { unicode_len = 4; count+=7; if (count <= len) { - int length = 0; + size_t length = 0; /* compute character number */ d = ((c & 0x07) << 18) | ((*(utf + 1) & 0x3F) << 12) @@ -191,7 +203,13 @@ static inline bool encode(std::string &value) { | (*(utf + 3) & 0x3F); *data++ = '%'; *data++ = 'u'; - length = snprintf(unicode, sizeof(unicode), "%x", d); + const int written = std::snprintf(unicode, sizeof(unicode), + "%x", d); + if (written < 0 + || static_cast(written) >= sizeof(unicode)) { + return changed; + } + length = static_cast(written); switch (length) { case 1: @@ -211,7 +229,7 @@ static inline bool encode(std::string &value) { break; } - for (int j = 0; j < length; j++) { + for (size_t j = 0; j < length; j++) { *data++ = unicode[j]; } From a656bb8bf2fa514569810ed3f691ed3c9ddb471b Mon Sep 17 00:00:00 2001 From: Mikel Olasagasti Uranga Date: Fri, 15 May 2026 11:55:20 +0200 Subject: [PATCH 13/23] Fix sign-compare warning in html_entity_decode Use std::string::size_type for the copy loop index to match copy. Fixes GCC -Wsign-compare: actions/transformations/html_entity_decode.cc:157:28: warning: comparison of integer expressions of different signedness [-Wsign-compare] Signed-off-by: Mikel Olasagasti Uranga --- src/actions/transformations/html_entity_decode.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/actions/transformations/html_entity_decode.cc b/src/actions/transformations/html_entity_decode.cc index b537ba3563..5a01678812 100644 --- a/src/actions/transformations/html_entity_decode.cc +++ b/src/actions/transformations/html_entity_decode.cc @@ -154,7 +154,7 @@ static inline bool inplace(std::string &value) { HTML_ENT_OUT: - for (auto z = 0; z < copy; z++) { + for (std::string::size_type z = 0; z < copy; z++) { *d++ = input[i++]; } } From 866ef1d984c755f2f481fa5a1c4ef9a5d08f9ca3 Mon Sep 17 00:00:00 2001 From: Mikel Olasagasti Uranga Date: Fri, 15 May 2026 11:56:13 +0200 Subject: [PATCH 14/23] Fix sign-compare warning in CompressWhitespace::transform Cast the in-place compression length to std::string::size_type before comparing with value.length(). Fixes GCC -Wsign-compare: actions/transformations/compress_whitespace.cc:42:34: warning: comparison of integer expressions of different signedness [-Wsign-compare] Signed-off-by: Mikel Olasagasti Uranga --- src/actions/transformations/compress_whitespace.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/actions/transformations/compress_whitespace.cc b/src/actions/transformations/compress_whitespace.cc index a9b31c962b..e46dd583d3 100644 --- a/src/actions/transformations/compress_whitespace.cc +++ b/src/actions/transformations/compress_whitespace.cc @@ -38,8 +38,8 @@ bool CompressWhitespace::transform(std::string &value, const Transaction *trans) } } - const auto new_len = d - value.c_str(); - const auto changed = new_len != value.length(); + const auto new_len = static_cast(d - value.data()); + const bool changed = new_len != value.length(); value.resize(new_len); return changed; } From bb9466936da8439103532b2d8828ea435c8986ff Mon Sep 17 00:00:00 2001 From: Mikel Olasagasti Uranga Date: Fri, 15 May 2026 11:57:43 +0200 Subject: [PATCH 15/23] Fix sign-compare warning in Multipart::process_part_data Compare upload file count against SecUploadFileLimit using uint32_t on both sides. Fixes GCC -Wsign-compare: request_body_processor/multipart.cc:561:26: warning: comparison of integer expressions of different signedness [-Wsign-compare] Signed-off-by: Mikel Olasagasti Uranga --- src/request_body_processor/multipart.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/request_body_processor/multipart.cc b/src/request_body_processor/multipart.cc index c8d78c7e00..09254ce736 100644 --- a/src/request_body_processor/multipart.cc +++ b/src/request_body_processor/multipart.cc @@ -558,7 +558,7 @@ int Multipart::process_part_data(std::string *error, size_t offset) { /* check if the file limit has been reached */ if (extract && m_transaction->m_rules->m_uploadFileLimit.m_value - && (m_nfiles >= + && (static_cast(m_nfiles) >= m_transaction->m_rules->m_uploadFileLimit.m_value)) { if (m_flag_file_limit_exceeded == 0) { ms_dbg_a(m_transaction, 1, From 9b2fc605c04cf2801ede6dccc661f684bd077c6b Mon Sep 17 00:00:00 2001 From: Mikel Olasagasti Uranga Date: Fri, 15 May 2026 12:01:37 +0200 Subject: [PATCH 16/23] Fix sign-compare warnings in ValidateUrlEncoding Use uint64_t for the scan index to match input_length. Fixes -Wsign-compare in operators/validate_url_encoding.cc:36 and :38. Signed-off-by: Mikel Olasagasti Uranga --- src/operators/validate_url_encoding.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/operators/validate_url_encoding.cc b/src/operators/validate_url_encoding.cc index 65a3a328b8..362e9f3faa 100644 --- a/src/operators/validate_url_encoding.cc +++ b/src/operators/validate_url_encoding.cc @@ -25,14 +25,13 @@ namespace operators { int ValidateUrlEncoding::validate_url_encoding(const char *input, uint64_t input_length, size_t *offset) { - int i; + uint64_t i = 0; *offset = 0; if ((input == NULL) || (input_length == 0)) { return -1; } - i = 0; while (i < input_length) { if (input[i] == '%') { if (i + 2 >= input_length) { From dfac3f474ed2dbcb382572057202ae0a7f09582d Mon Sep 17 00:00:00 2001 From: Mikel Olasagasti Uranga Date: Fri, 15 May 2026 12:02:14 +0200 Subject: [PATCH 17/23] Fix sign-compare warning in PmFromFile::isComment Use size_t for the loop index when scanning characters before '#'. Fixes GCC -Wsign-compare: operators/pm_from_file.cc:36:27: warning: comparison of integer expressions of different signedness [-Wsign-compare] Signed-off-by: Mikel Olasagasti Uranga --- src/operators/pm_from_file.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/operators/pm_from_file.cc b/src/operators/pm_from_file.cc index 52651e95cc..6d0726d4bf 100644 --- a/src/operators/pm_from_file.cc +++ b/src/operators/pm_from_file.cc @@ -33,7 +33,7 @@ bool PmFromFile::isComment(const std::string &s) { } size_t pos = s.find("#"); if (pos != std::string::npos) { - for (int i = 0; i < pos; i++) { + for (size_t i = 0; i < pos; i++) { if (!std::isspace(s[i])) { return false; } From a73e3b1d45d5a16c37730bf34e3aa9144ae92c92 Mon Sep 17 00:00:00 2001 From: Mikel Olasagasti Uranga Date: Fri, 15 May 2026 12:03:13 +0200 Subject: [PATCH 18/23] Fix sign-compare warning in Driver::addSecRule Use size_t for the rule index when checking for duplicate rule IDs. Fixes GCC -Wsign-compare: parser/driver.cc:111:27: warning: comparison of integer expressions of different signedness [-Wsign-compare] Signed-off-by: Mikel Olasagasti Uranga --- src/parser/driver.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parser/driver.cc b/src/parser/driver.cc index a193e7bcdf..22c46b713a 100644 --- a/src/parser/driver.cc +++ b/src/parser/driver.cc @@ -108,7 +108,7 @@ int Driver::addSecRule(std::unique_ptr r) { for (int i = 0; i < modsecurity::Phases::NUMBER_OF_PHASES; i++) { const Rules *rules = m_rulesSetPhases[i]; - for (int j = 0; j < rules->size(); j++) { + for (size_t j = 0; j < rules->size(); j++) { const RuleWithOperator *lr = dynamic_cast(rules->at(j).get()); if (lr && lr->m_ruleId == rule->m_ruleId) { m_parserError << "Rule id: " << std::to_string(rule->m_ruleId) \ From 57e1b41fde676083434cef4c60edfc68368ab0aa Mon Sep 17 00:00:00 2001 From: Mikel Olasagasti Uranga Date: Fri, 15 May 2026 12:04:58 +0200 Subject: [PATCH 19/23] Fix -Wreorder in Transaction constructor Initialize TransactionAnchoredVariables before m_logCbData in the member initializer list. Signed-off-by: Mikel Olasagasti Uranga --- src/transaction.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/transaction.cc b/src/transaction.cc index 8a83e12f39..447029d04f 100644 --- a/src/transaction.cc +++ b/src/transaction.cc @@ -118,7 +118,8 @@ Transaction::Transaction(ModSecurity *ms, RulesSet *rules, const char *id, void Transaction::Transaction(ModSecurity *ms, RulesSet *rules, const char *id, void *logCbData, const time_t timestamp) - : m_creationTimeStamp(utils::cpu_seconds()), + : TransactionAnchoredVariables(this), + m_creationTimeStamp(utils::cpu_seconds()), m_ARGScombinedSizeDouble(0), m_clientPort(0), m_highestSeverityAction(255), @@ -149,8 +150,7 @@ Transaction::Transaction(ModSecurity *ms, RulesSet *rules, const char *id, #endif m_secRuleEngine(RulesSetProperties::PropertyNotSetRuleEngine), m_secXMLParseXmlIntoArgs(rules->m_secXMLParseXmlIntoArgs), - m_logCbData(logCbData), - TransactionAnchoredVariables(this) { + m_logCbData(logCbData) { m_variableUrlEncodedError.set("0", 0); m_variableMscPcreError.set("0", 0); m_variableMscPcreLimitsExceeded.set("0", 0); From 6b30ce095a3dfc929c12cc635bfab3603f0c05ca Mon Sep 17 00:00:00 2001 From: Mikel Olasagasti Uranga Date: Fri, 15 May 2026 12:05:17 +0200 Subject: [PATCH 20/23] Fix sign-compare in Transaction::processRequestBody Use uint64_t for reqbodyNoFilesLength when comparing against SecRequestBodyNoFilesLimit. Signed-off-by: Mikel Olasagasti Uranga --- src/transaction.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/transaction.cc b/src/transaction.cc index 447029d04f..4ae2141851 100644 --- a/src/transaction.cc +++ b/src/transaction.cc @@ -770,7 +770,7 @@ int Transaction::processRequestBody() { if (m_requestBodyType == MultiPartRequestBody) { #endif std::string error; - int reqbodyNoFilesLength = 0; + uint64_t reqbodyNoFilesLength = 0; if (a != NULL) { Multipart m(*a, this); if (m.init(&error) == true) { From b58cfd47d2548d80e2c7d56b3d34153f91e40090 Mon Sep 17 00:00:00 2001 From: Mikel Olasagasti Uranga Date: Tue, 30 Jun 2026 12:47:55 +0200 Subject: [PATCH 21/23] Avoid undefined behavior in PmFromFile::isComment Cast characters to unsigned char before passing them to std::isspace. The ctype functions require EOF or an unsigned char-representable value. Signed-off-by: Mikel Olasagasti Uranga --- src/operators/pm_from_file.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/operators/pm_from_file.cc b/src/operators/pm_from_file.cc index 6d0726d4bf..9ecbe1cfdb 100644 --- a/src/operators/pm_from_file.cc +++ b/src/operators/pm_from_file.cc @@ -34,7 +34,7 @@ bool PmFromFile::isComment(const std::string &s) { size_t pos = s.find("#"); if (pos != std::string::npos) { for (size_t i = 0; i < pos; i++) { - if (!std::isspace(s[i])) { + if (!std::isspace(static_cast(s[i]))) { return false; } } From a8136523520505a57e8af0dab648374e6d434218 Mon Sep 17 00:00:00 2001 From: Mikel Olasagasti Uranga Date: Tue, 30 Jun 2026 12:54:12 +0200 Subject: [PATCH 22/23] Free YAJL generator on processContentOffset errors Release the YAJL generator before returning from offset validation errors to avoid leaking it on malformed matchString input. Signed-off-by: Mikel Olasagasti Uranga --- src/modsecurity.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/modsecurity.cc b/src/modsecurity.cc index e1f9d512a1..5eabe6599e 100644 --- a/src/modsecurity.cc +++ b/src/modsecurity.cc @@ -270,6 +270,7 @@ int ModSecurity::processContentOffset(const char *content, size_t len, if (static_cast(stoi(startingAt)) >= len) { *err = "Offset is out of the content limits."; + yajl_gen_free(g); return -1; } @@ -349,6 +350,7 @@ int ModSecurity::processContentOffset(const char *content, size_t len, if (static_cast(stoi(startingAt)) >= varValue.size()) { *err = "Offset is out of the variable limits."; + yajl_gen_free(g); return -1; } yajl_gen_string(g, From 396c3271d84b1074406d21ecf978711d7f38b3ec Mon Sep 17 00:00:00 2001 From: Mikel Olasagasti Uranga Date: Wed, 1 Jul 2026 15:32:13 +0200 Subject: [PATCH 23/23] Refactor UTF-8 Unicode escape emission This should address the SonarQube duplication without mixing in unrelated cleanup. Signed-off-by: Mikel Olasagasti Uranga --- .../transformations/utf8_to_unicode.cc | 132 ++++++------------ 1 file changed, 42 insertions(+), 90 deletions(-) diff --git a/src/actions/transformations/utf8_to_unicode.cc b/src/actions/transformations/utf8_to_unicode.cc index a4691833c3..29eb48f363 100644 --- a/src/actions/transformations/utf8_to_unicode.cc +++ b/src/actions/transformations/utf8_to_unicode.cc @@ -27,6 +27,42 @@ constexpr int UNICODE_ERROR_INVALID_ENCODING = -2; namespace modsecurity::actions::transformations { +static inline bool writeUnicodeEscape(char *&data, char *unicode, + size_t unicode_size, unsigned int d) { + *data++ = '%'; + *data++ = 'u'; + const int written = std::snprintf(unicode, unicode_size, "%x", d); + if (written < 0 || static_cast(written) >= unicode_size) { + return false; + } + + const auto length = static_cast(written); + switch (length) { + case 1: + *data++ = '0'; + *data++ = '0'; + *data++ = '0'; + break; + case 2: + *data++ = '0'; + *data++ = '0'; + break; + case 3: + *data++ = '0'; + break; + case 4: + case 5: + break; + } + + for (size_t j = 0; j < length; j++) { + *data++ = unicode[j]; + } + + return true; +} + + static inline bool encode(std::string &value) { auto input = reinterpret_cast(value.data()); const auto input_len = value.length(); @@ -78,40 +114,12 @@ static inline bool encode(std::string &value) { unicode_len = 2; count += 6; if (count <= len) { - size_t length = 0; /* compute character number */ d = ((c & 0x1F) << 6) | (*(utf + 1) & 0x3F); - *data++ = '%'; - *data++ = 'u'; - const int written = std::snprintf(unicode, sizeof(unicode), - "%x", d); - if (written < 0 - || static_cast(written) >= sizeof(unicode)) { + if (writeUnicodeEscape(data, unicode, + sizeof(unicode), d) == false) { return changed; } - length = static_cast(written); - - switch (length) { - case 1: - *data++ = '0'; - *data++ = '0'; - *data++ = '0'; - break; - case 2: - *data++ = '0'; - *data++ = '0'; - break; - case 3: - *data++ = '0'; - break; - case 4: - case 5: - break; - } - - for (size_t j = 0; j < length; j++) { - *data++ = unicode[j]; - } changed = true; } @@ -131,42 +139,14 @@ static inline bool encode(std::string &value) { unicode_len = 3; count+=6; if (count <= len) { - size_t length = 0; /* compute character number */ d = ((c & 0x0F) << 12) | ((*(utf + 1) & 0x3F) << 6) | (*(utf + 2) & 0x3F); - *data++ = '%'; - *data++ = 'u'; - const int written = std::snprintf(unicode, sizeof(unicode), - "%x", d); - if (written < 0 - || static_cast(written) >= sizeof(unicode)) { + if (writeUnicodeEscape(data, unicode, + sizeof(unicode), d) == false) { return changed; } - length = static_cast(written); - - switch (length) { - case 1: - *data++ = '0'; - *data++ = '0'; - *data++ = '0'; - break; - case 2: - *data++ = '0'; - *data++ = '0'; - break; - case 3: - *data++ = '0'; - break; - case 4: - case 5: - break; - } - - for (size_t j = 0; j < length; j++) { - *data++ = unicode[j]; - } changed = true; } @@ -195,43 +175,15 @@ static inline bool encode(std::string &value) { unicode_len = 4; count+=7; if (count <= len) { - size_t length = 0; /* compute character number */ d = ((c & 0x07) << 18) | ((*(utf + 1) & 0x3F) << 12) | ((*(utf + 2) & 0x3F) << 6) | (*(utf + 3) & 0x3F); - *data++ = '%'; - *data++ = 'u'; - const int written = std::snprintf(unicode, sizeof(unicode), - "%x", d); - if (written < 0 - || static_cast(written) >= sizeof(unicode)) { + if (writeUnicodeEscape(data, unicode, + sizeof(unicode), d) == false) { return changed; } - length = static_cast(written); - - switch (length) { - case 1: - *data++ = '0'; - *data++ = '0'; - *data++ = '0'; - break; - case 2: - *data++ = '0'; - *data++ = '0'; - break; - case 3: - *data++ = '0'; - break; - case 4: - case 5: - break; - } - - for (size_t j = 0; j < length; j++) { - *data++ = unicode[j]; - } changed = true; }