13
13
*
14
14
*/
15
15
16
+ #ifdef WIN32
17
+ #ifdef max
18
+ #undef max
19
+ #endif
20
+ #ifdef min
21
+ #undef min
22
+ #endif
23
+ #endif
16
24
17
25
#ifdef __cplusplus
18
26
#include < ctime>
22
30
#include < list>
23
31
#include < set>
24
32
#include < cstring>
33
+ #include < limits>
34
+ #include < cstdint>
25
35
#endif
26
36
27
37
@@ -68,29 +78,127 @@ class Driver;
68
78
using modsecurity::debug_log::DebugLog;
69
79
using modsecurity::audit_log::AuditLog;
70
80
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 ;
77
87
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 ;
82
92
m_set = true ;
83
93
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;
85
168
}
86
169
};
87
170
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
+ };
88
196
89
197
class ConfigDouble {
90
198
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 ;
94
202
95
203
void merge (const ConfigDouble *from) {
96
204
if (m_set == true || from->m_set == false ) {
@@ -105,9 +213,9 @@ class ConfigDouble {
105
213
106
214
class ConfigString {
107
215
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 ;
111
219
112
220
void merge (const ConfigString *from) {
113
221
if (m_set == true || from->m_set == false ) {
@@ -122,10 +230,10 @@ class ConfigString {
122
230
123
231
class ConfigSet {
124
232
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 ;
128
235
std::set<std::string> m_value;
236
+ ConfigSet () = default ;
129
237
};
130
238
131
239
@@ -504,14 +612,14 @@ class RulesSetProperties {
504
612
ConfigXMLParseXmlIntoArgs m_secXMLParseXmlIntoArgs;
505
613
ConfigBoolean m_tmpSaveUploadedFiles;
506
614
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;
515
623
DebugLog *m_debugLog;
516
624
OnFailedRemoteRulesAction m_remoteRulesActionOnFailed;
517
625
RuleEngine m_secRuleEngine;
0 commit comments