1313 *
1414 */
1515
16+ #ifdef WIN32
17+ #ifdef max
18+ #undef max
19+ #endif
20+ #ifdef min
21+ #undef min
22+ #endif
23+ #endif
1624
1725#ifdef __cplusplus
1826#include < ctime>
2230#include < list>
2331#include < set>
2432#include < cstring>
33+ #include < limits>
34+ #include < cstdint>
2535#endif
2636
2737
@@ -68,29 +78,127 @@ class Driver;
6878using modsecurity::debug_log::DebugLog;
6979using modsecurity::audit_log::AuditLog;
7080
71- /* * @ingroup ModSecurity_CPP_API */
72- class ConfigInt {
73- public:
74- ConfigInt () : m_set( false ), m_value( 0 ) { }
75- bool m_set;
76- int m_value;
81+ // template for different numeric int types
82+ template < typename T>
83+ class ConfigValue {
84+ public:
85+ bool m_set = false ;
86+ T m_value = 0 ;
7787
78- void merge ( const ConfigInt *from) {
79- if (m_set == true || from-> m_set == false ) {
80- return ;
81- }
88+ ConfigValue () = default ;
89+
90+ void merge ( const ConfigValue<T>* from) {
91+ if (m_set || !from-> m_set ) return ;
8292 m_set = true ;
8393 m_value = from->m_value ;
84- return ;
94+ }
95+
96+ // default parser
97+ bool parse (const std::string& a, std::string* errmsg = nullptr ) {
98+
99+ // use an alias type because the template can convert both signed and unsigned int
100+ using LimitSigned = std::conditional_t <std::is_signed_v<T>, std::int64_t , std::uint64_t >;
101+ LimitSigned val;
102+
103+ // clear errno variable, wee need that later
104+ errno = 0 ;
105+
106+ try {
107+ if constexpr (std::is_signed_v<T>) {
108+ val = static_cast <std::int64_t >(std::stoll (a));
109+ } else {
110+ val = static_cast <std::uint64_t >(std::stoull (a));
111+ }
112+ }
113+ catch (const std::invalid_argument&) {
114+ // probably can't occur, but we handle it anyway
115+ set_error (errmsg, " Invalid number format (not numeric)" );
116+ return false ;
117+ }
118+ catch (const std::out_of_range&) {
119+ // the value is out of range, we can not handle it
120+ set_error (errmsg, " Number out of range" );
121+ return false ;
122+ }
123+ catch (...) { // NOSONAR
124+ // we don't need to handle all exceptions, the engine's BISON parser
125+ // does not allow other symbols than numbers
126+ set_error (errmsg, " An unknown error occurred while parsed the value." );
127+ return false ;
128+ }
129+
130+ if (
131+ // first condition will be true if the value is bigger than int64/uint64 max value
132+ // the second condition checks if the value is fit as int64/uint64, but not fit for
133+ // designed type, eg. uint32; in that case the errno will be 0, but
134+ // we must check the value is not bigger than the given max() at the type class
135+ (errno == ERANGE && val == std::numeric_limits<LimitSigned>::max ())
136+ ||
137+ (val > static_cast <LimitSigned>(maxValue ()))
138+ ) {
139+ set_error (errmsg, " Value is too big." );
140+ return false ;
141+ }
142+
143+ if (
144+ // same as above
145+ (errno == ERANGE && val == std::numeric_limits<LimitSigned>::min ())
146+ ||
147+ (val < static_cast <LimitSigned>(minValue ()))
148+ ) {
149+ set_error (errmsg, " Value is too small." );
150+ return false ;
151+ }
152+
153+ m_value = static_cast <T>(val);
154+ m_set = true ;
155+ return true ;
156+
157+ }
158+
159+ protected:
160+ // derived classes must implement the maxValue
161+ virtual T maxValue () const = 0;
162+ // minValue is optional
163+ virtual T minValue () const { return 0 ; }
164+
165+ private:
166+ static inline void set_error (std::string* err, const char * msg) {
167+ if (err) *err = msg;
85168 }
86169};
87170
171+ /* * @ingroup ModSecurity_CPP_API */
172+
173+ class ConfigInt : public ConfigValue <int32_t > {
174+ protected:
175+ int32_t minValue () const override {
176+ return std::numeric_limits<int32_t >::min ();
177+ }
178+ int32_t maxValue () const override {
179+ return std::numeric_limits<int32_t >::max ();
180+ }
181+ };
182+
183+ class ConfigUnsignedInt : public ConfigValue <uint32_t > {
184+ protected:
185+ uint32_t maxValue () const override {
186+ return std::numeric_limits<uint32_t >::max ();
187+ }
188+ };
189+
190+ class ConfigUnsignedLong : public ConfigValue <uint64_t > {
191+ protected:
192+ uint64_t maxValue () const override {
193+ return std::numeric_limits<uint64_t >::max ();
194+ }
195+ };
88196
89197class ConfigDouble {
90198 public:
91- ConfigDouble () : m_set( false ), m_value( 0 ) { }
92- bool m_set ;
93- double m_value ;
199+ bool m_set = false ;
200+ double m_value = 0.0 ;
201+ ConfigDouble () = default ;
94202
95203 void merge (const ConfigDouble *from) {
96204 if (m_set == true || from->m_set == false ) {
@@ -105,9 +213,9 @@ class ConfigDouble {
105213
106214class ConfigString {
107215 public:
108- ConfigString () : m_set( false ), m_value( " " ) { }
109- bool m_set ;
110- std::string m_value ;
216+ bool m_set = false ;
217+ std::string m_value = " " ;
218+ ConfigString () = default ;
111219
112220 void merge (const ConfigString *from) {
113221 if (m_set == true || from->m_set == false ) {
@@ -122,10 +230,10 @@ class ConfigString {
122230
123231class ConfigSet {
124232 public:
125- ConfigSet () : m_set(false ), m_clear(false ) { }
126- bool m_set;
127- bool m_clear;
233+ bool m_set = false ;
234+ bool m_clear = false ;
128235 std::set<std::string> m_value;
236+ ConfigSet () = default ;
129237};
130238
131239
@@ -504,14 +612,14 @@ class RulesSetProperties {
504612 ConfigXMLParseXmlIntoArgs m_secXMLParseXmlIntoArgs;
505613 ConfigBoolean m_tmpSaveUploadedFiles;
506614 ConfigBoolean m_uploadKeepFiles;
507- ConfigDouble m_argumentsLimit;
508- ConfigDouble m_requestBodyJsonDepthLimit;
509- ConfigDouble m_requestBodyLimit;
510- ConfigDouble m_requestBodyNoFilesLimit;
511- ConfigDouble m_responseBodyLimit;
512- ConfigInt m_pcreMatchLimit;
513- ConfigInt m_uploadFileLimit;
514- ConfigInt m_uploadFileMode;
615+ ConfigUnsignedInt m_argumentsLimit;
616+ ConfigUnsignedInt m_requestBodyJsonDepthLimit;
617+ ConfigUnsignedLong m_requestBodyLimit;
618+ ConfigUnsignedLong m_requestBodyNoFilesLimit;
619+ ConfigUnsignedLong m_responseBodyLimit;
620+ ConfigUnsignedInt m_pcreMatchLimit;
621+ ConfigUnsignedInt m_uploadFileLimit;
622+ ConfigUnsignedInt m_uploadFileMode;
515623 DebugLog *m_debugLog;
516624 OnFailedRemoteRulesAction m_remoteRulesActionOnFailed;
517625 RuleEngine m_secRuleEngine;
0 commit comments