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,46 +78,132 @@ 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 ) {
88
+ ConfigValue () = default ;
89
+
90
+ void merge (const ConfigValue<T>* from) {
91
+ if (m_set || !from->m_set ) {
80
92
return ;
81
93
}
82
94
m_set = true ;
83
95
m_value = from->m_value ;
84
- return ;
85
96
}
86
- };
87
97
98
+ // default parser
99
+ bool parse (const std::string& a, std::string* errmsg = nullptr ) {
88
100
89
- class ConfigDouble {
90
- public:
91
- ConfigDouble () : m_set(false ), m_value(0 ) { }
92
- bool m_set;
93
- double m_value;
101
+ // use an alias type because the template can convert both signed and unsigned int
102
+ using LimitSigned = std::conditional_t <std::is_signed_v<T>, std::int64_t , std::uint64_t >;
103
+ LimitSigned val;
94
104
95
- void merge (const ConfigDouble *from) {
96
- if (m_set == true || from->m_set == false ) {
97
- return ;
105
+ // clear errno variable, wee need that later
106
+ errno = 0 ;
107
+
108
+ try {
109
+ if constexpr (std::is_signed_v<T>) {
110
+ val = static_cast <std::int64_t >(std::stoll (a));
111
+ } else {
112
+ val = static_cast <std::uint64_t >(std::stoull (a));
113
+ }
114
+ }
115
+ catch (const std::invalid_argument&) {
116
+ // probably can't occur, but we handle it anyway
117
+ set_error (errmsg, " Invalid number format (not numeric)" );
118
+ return false ;
119
+ }
120
+ catch (const std::out_of_range&) {
121
+ // the value is out of range, we can not handle it
122
+ set_error (errmsg, " Number out of range" );
123
+ return false ;
124
+ }
125
+ catch (...) { // NOSONAR
126
+ // we don't need to handle all exceptions, the engine's BISON parser
127
+ // does not allow other symbols than numbers
128
+ set_error (errmsg, " An unknown error occurred while parsing number." );
129
+ return false ;
130
+ }
131
+
132
+ if (
133
+ // The first condition will be true when the value is bigger than int64/uint64 maximum value.
134
+ // The second condition checks whether the value fits into int64/uint64, but not
135
+ // into the designed type, e.g., uint32; in that case the errno will be 0, but
136
+ // we must check the value is not bigger than the defined maximum of the class.
137
+ (errno == ERANGE && val == std::numeric_limits<LimitSigned>::max ())
138
+ ||
139
+ (val > static_cast <LimitSigned>(maxValue ()))
140
+ ) {
141
+ set_error (errmsg, " Value is too big." );
142
+ return false ;
143
+ }
144
+
145
+ if (
146
+ // same as above
147
+ (errno == ERANGE && val == std::numeric_limits<LimitSigned>::min ())
148
+ ||
149
+ (val < static_cast <LimitSigned>(minValue ()))
150
+ ) {
151
+ set_error (errmsg, " Value is too small." );
152
+ return false ;
98
153
}
154
+
155
+ m_value = static_cast <T>(val);
99
156
m_set = true ;
100
- m_value = from->m_value ;
101
- return ;
157
+ return true ;
158
+
159
+ }
160
+
161
+ protected:
162
+ // derived classes must implement the maxValue
163
+ virtual T maxValue () const = 0;
164
+ // minValue is optional
165
+ virtual T minValue () const { return 0 ; }
166
+
167
+ private:
168
+ static inline void set_error (std::string* err, const char * msg) {
169
+ if (err) {
170
+ *err = msg;
171
+ }
172
+ }
173
+ };
174
+
175
+ /* * @ingroup ModSecurity_CPP_API */
176
+
177
+ class ConfigInt : public ConfigValue <int32_t > {
178
+ protected:
179
+ int32_t minValue () const override {
180
+ return std::numeric_limits<int32_t >::min ();
181
+ }
182
+ int32_t maxValue () const override {
183
+ return std::numeric_limits<int32_t >::max ();
184
+ }
185
+ };
186
+
187
+ class ConfigUnsignedInt : public ConfigValue <uint32_t > {
188
+ protected:
189
+ uint32_t maxValue () const override {
190
+ return std::numeric_limits<uint32_t >::max ();
191
+ }
192
+ };
193
+
194
+ class ConfigUnsignedLong : public ConfigValue <uint64_t > {
195
+ protected:
196
+ uint64_t maxValue () const override {
197
+ return std::numeric_limits<uint64_t >::max ();
102
198
}
103
199
};
104
200
105
201
106
202
class ConfigString {
107
203
public:
108
- ConfigString () : m_set( false ), m_value( " " ) { }
109
- bool m_set ;
110
- std::string m_value ;
204
+ bool m_set = false ;
205
+ std::string m_value = " " ;
206
+ ConfigString () = default ;
111
207
112
208
void merge (const ConfigString *from) {
113
209
if (m_set == true || from->m_set == false ) {
@@ -122,10 +218,10 @@ class ConfigString {
122
218
123
219
class ConfigSet {
124
220
public:
125
- ConfigSet () : m_set(false ), m_clear(false ) { }
126
- bool m_set;
127
- bool m_clear;
221
+ bool m_set = false ;
222
+ bool m_clear = false ;
128
223
std::set<std::string> m_value;
224
+ ConfigSet () = default ;
129
225
};
130
226
131
227
@@ -504,14 +600,14 @@ class RulesSetProperties {
504
600
ConfigXMLParseXmlIntoArgs m_secXMLParseXmlIntoArgs;
505
601
ConfigBoolean m_tmpSaveUploadedFiles;
506
602
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;
603
+ ConfigUnsignedInt m_argumentsLimit;
604
+ ConfigUnsignedInt m_requestBodyJsonDepthLimit;
605
+ ConfigUnsignedLong m_requestBodyLimit;
606
+ ConfigUnsignedLong m_requestBodyNoFilesLimit;
607
+ ConfigUnsignedLong m_responseBodyLimit;
608
+ ConfigUnsignedInt m_pcreMatchLimit;
609
+ ConfigUnsignedInt m_uploadFileLimit;
610
+ ConfigUnsignedInt m_uploadFileMode;
515
611
DebugLog *m_debugLog;
516
612
OnFailedRemoteRulesAction m_remoteRulesActionOnFailed;
517
613
RuleEngine m_secRuleEngine;
0 commit comments