Skip to content

Commit af8be01

Browse files
committed
Perform UrlDecodeUni & UrlDecode transformations in-place
- Use std::string in UrlEncode transformation, instead of manually memory management. This avoids an additional copy after completing encoding by just swapping the encoded value and the input. - Removed inplace helper function from the class, as it's only referenced by the implementation.
1 parent 119a722 commit af8be01

File tree

5 files changed

+43
-97
lines changed

5 files changed

+43
-97
lines changed

src/actions/transformations/url_decode.cc

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,25 +27,16 @@ UrlDecode::UrlDecode(const std::string &action)
2727
}
2828

2929
bool UrlDecode::transform(std::string &value, const Transaction *trans) const {
30-
unsigned char *val(NULL);
3130
int invalid_count = 0;
32-
int _changed;
33-
34-
val = (unsigned char *) malloc(sizeof(char) * value.size() + 1);
35-
memcpy(val, value.c_str(), value.size() + 1);
36-
val[value.size()] = '\0';
37-
38-
int size = utils::urldecode_nonstrict_inplace(val, value.size(),
39-
&invalid_count, &_changed);
40-
std::string out;
41-
42-
out.append((const char *)val, size);
43-
44-
free(val);
45-
46-
const auto changed = out != value;
47-
value = out;
48-
return changed;
31+
int changed;
32+
const auto new_len = utils::urldecode_nonstrict_inplace(
33+
(unsigned char*)value.data(),
34+
value.length(),
35+
&invalid_count,
36+
&changed);
37+
38+
value.resize(new_len);
39+
return changed != 0;
4940
}
5041

5142

src/actions/transformations/url_decode_uni.cc

Lines changed: 18 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -22,41 +22,19 @@
2222
namespace modsecurity::actions::transformations {
2323

2424

25-
bool UrlDecodeUni::transform(std::string &value, const Transaction *t) const {
26-
std::string ret;
27-
unsigned char *input;
28-
29-
input = reinterpret_cast<unsigned char *>
30-
(malloc(sizeof(char) * value.length()+1));
31-
32-
if (input == NULL) {
33-
return "";
34-
}
35-
36-
memcpy(input, value.c_str(), value.length()+1);
37-
38-
size_t i = inplace(input, value.length(), t);
39-
40-
ret.assign(reinterpret_cast<char *>(input), i);
41-
free(input);
42-
43-
const auto changed = ret != value;
44-
value = ret;
45-
return changed;
46-
}
47-
48-
4925
/**
5026
*
5127
* IMP1 Assumes NUL-terminated
5228
*/
53-
int UrlDecodeUni::inplace(unsigned char *input, uint64_t input_len,
29+
static inline bool inplace(std::string &value,
5430
const Transaction *t) {
55-
unsigned char *d = input;
56-
int64_t i, count, fact, j, xv;
57-
int Code, hmap = -1;
31+
bool changed = false;
32+
auto d = reinterpret_cast<unsigned char*>(value.data());
33+
const unsigned char *input = d;
34+
const auto input_len = value.length();
5835

59-
if (input == NULL) return -1;
36+
std::string::size_type i, count, fact, j, xv;
37+
int Code, hmap = -1;
6038

6139
i = count = 0;
6240
while (i < input_len) {
@@ -116,19 +94,17 @@ int UrlDecodeUni::inplace(unsigned char *input, uint64_t input_len,
11694
}
11795
}
11896
d++;
119-
count++;
12097
i += 6;
98+
changed = true;
12199
} else {
122100
/* Invalid data, skip %u. */
123101
*d++ = input[i++];
124102
*d++ = input[i++];
125-
count += 2;
126103
}
127104
} else {
128105
/* Not enough bytes (4 data bytes), skip %u. */
129106
*d++ = input[i++];
130107
*d++ = input[i++];
131-
count += 2;
132108
}
133109
} else {
134110
/* Standard URL encoding. */
@@ -143,8 +119,8 @@ int UrlDecodeUni::inplace(unsigned char *input, uint64_t input_len,
143119

144120
if (VALID_HEX(c1) && VALID_HEX(c2)) {
145121
*d++ = utils::string::x2c(&input[i + 1]);
146-
count++;
147122
i += 3;
123+
changed = true;
148124
} else {
149125
/* Not a valid encoding, skip this % */
150126
*d++ = input[i++];
@@ -153,25 +129,31 @@ int UrlDecodeUni::inplace(unsigned char *input, uint64_t input_len,
153129
} else {
154130
/* Not enough bytes available, skip this % */
155131
*d++ = input[i++];
156-
count++;
157132
}
158133
}
159134
} else {
160135
/* Character is not a percent sign. */
161136
if (input[i] == '+') {
162137
*d++ = ' ';
138+
changed = true;
163139
} else {
164140
*d++ = input[i];
165141
}
166142

167-
count++;
168143
i++;
169144
}
170145
}
171146

172147
*d = '\0';
173148

174-
return count;
149+
value.resize(d - input);
150+
return changed;
151+
}
152+
153+
154+
155+
bool UrlDecodeUni::transform(std::string &value, const Transaction *trans) const {
156+
return inplace(value, trans);
175157
}
176158

177159

src/actions/transformations/url_decode_uni.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ class UrlDecodeUni : public Transformation {
2626
: Transformation(action) { }
2727

2828
bool transform(std::string &value, const Transaction *trans) const override;
29-
static int inplace(unsigned char *input, uint64_t input_len,
30-
const Transaction *transaction);
3129
};
3230

3331
} // namespace modsecurity::actions::transformations

src/actions/transformations/url_encode.cc

Lines changed: 16 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -26,64 +26,42 @@ UrlEncode::UrlEncode(const std::string &action)
2626
}
2727

2828

29-
std::string UrlEncode::url_enc(const char *input,
30-
unsigned int input_len, int *changed) {
31-
char *rval, *d;
32-
unsigned int i, len;
33-
int count = 0;
29+
static inline bool url_enc(std::string &value) {
30+
const auto len = value.size() * 3 + 1;
31+
std::string ret(len, {});
3432

35-
*changed = 0;
36-
37-
len = input_len * 3 + 1;
38-
d = rval = reinterpret_cast<char *>(malloc(len));
39-
if (rval == NULL) {
40-
return {};
41-
}
33+
bool changed = false;
4234

4335
/* ENH Only encode the characters that really need to be encoded. */
4436

45-
for (i = 0; i < input_len; i++) {
46-
unsigned char c = input[i];
47-
37+
char *d = ret.data();
38+
for (const auto c : value) {
4839
if (c == ' ') {
4940
*d++ = '+';
50-
*changed = 1;
51-
count++;
41+
changed = true;
5242
} else {
5343
if ( (c == 42) || ((c >= 48) && (c <= 57))
5444
|| ((c >= 65) && (c <= 90))
5545
|| ((c >= 97) && (c <= 122))) {
5646
*d++ = c;
57-
count++;
58-
} else {
47+
}
48+
else
49+
{
5950
*d++ = '%';
60-
count++;
61-
utils::string::c2x(c, (unsigned char *)d);
62-
d += 2;
63-
count++;
64-
count++;
65-
*changed = 1;
51+
d = (char *)utils::string::c2x(c, (unsigned char *)d);
52+
changed = true;
6653
}
6754
}
6855
}
6956

70-
*d = '\0';
71-
72-
std::string ret("");
73-
ret.append(rval, count);
74-
free(rval);
75-
return ret;
57+
ret.resize(d - ret.c_str());
58+
std::swap(value, ret);
59+
return changed;
7660
}
7761

7862

7963
bool UrlEncode::transform(std::string &value, const Transaction *trans) const {
80-
int _changed;
81-
82-
std::string ret = url_enc(value.c_str(), value.size(), &_changed);
83-
84-
const auto changed = ret != value;
85-
value = ret;
86-
return changed;
64+
return url_enc(value);
8765
}
8866

8967

src/actions/transformations/url_encode.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,6 @@ class UrlEncode : public Transformation {
2525
explicit UrlEncode(const std::string &action);
2626

2727
bool transform(std::string &value, const Transaction *trans) const override;
28-
29-
static std::string url_enc(const char *input,
30-
unsigned int input_len, int *changed);
3128
};
3229

3330
} // namespace modsecurity::actions::transformations

0 commit comments

Comments
 (0)