|
23 | 23 | namespace modsecurity::actions::transformations {
|
24 | 24 |
|
25 | 25 |
|
26 |
| -#ifndef VALID_HEX |
27 |
| -#define VALID_HEX(X) (((X >= '0') && (X <= '9')) \ |
28 |
| - || ((X >= 'a') && (X <= 'f')) \ |
29 |
| - || ((X >= 'A') && (X <= 'F'))) |
30 |
| -#endif |
31 |
| -#ifndef ISODIGIT |
32 |
| -#define ISODIGIT(X) ((X >= '0') && (X <= '7')) |
33 |
| -#endif |
34 |
| - |
35 |
| -bool SqlHexDecode::transform(std::string &value, const Transaction *trans) const { |
36 |
| - std::string ret; |
37 |
| - unsigned char *input; |
38 |
| - int size = 0; |
39 |
| - |
40 |
| - input = reinterpret_cast<unsigned char *> |
41 |
| - (malloc(sizeof(char) * value.length()+1)); |
42 |
| - |
43 |
| - if (input == NULL) { |
44 |
| - return ""; |
45 |
| - } |
46 |
| - |
47 |
| - memcpy(input, value.c_str(), value.length()+1); |
48 |
| - |
49 |
| - size = inplace(input, value.length()); |
50 |
| - |
51 |
| - ret.assign(reinterpret_cast<char *>(input), size); |
52 |
| - free(input); |
53 |
| - |
54 |
| - const auto changed = ret != value; |
55 |
| - value = ret; |
56 |
| - return changed; |
| 26 | +static inline int mytolower(int ch) { |
| 27 | + if (ch >= 'A' && ch <= 'Z') |
| 28 | + return ('a' + ch - 'A'); |
| 29 | + else |
| 30 | + return ch; |
57 | 31 | }
|
58 | 32 |
|
59 |
| - |
60 |
| -int SqlHexDecode::inplace(unsigned char *data, int len) { |
61 |
| - unsigned char *d, *begin = data; |
62 |
| - int count = 0; |
63 |
| - |
64 |
| - if ((data == NULL) || (len == 0)) { |
65 |
| - return 0; |
| 33 | +static inline bool inplace(std::string &value) { |
| 34 | + if (value.empty()) { |
| 35 | + return false; |
66 | 36 | }
|
67 | 37 |
|
68 |
| - for (d = data; (++count < len) && *data; *d++ = *data++) { |
69 |
| - if (*data != '0') { |
70 |
| - continue; |
| 38 | + auto d = reinterpret_cast<unsigned char*>(value.data()); |
| 39 | + const unsigned char *data = d; |
| 40 | + const auto end = data + value.size(); |
| 41 | + |
| 42 | + bool changed = false; |
| 43 | + |
| 44 | + while (data < end) { |
| 45 | + if (data + 3 < end |
| 46 | + && *data == '0' |
| 47 | + && mytolower(*(data + 1)) == 'x' |
| 48 | + && VALID_HEX(*(data + 2)) && VALID_HEX(*(data + 3))) { |
| 49 | + data += 2; // skip '0x' |
| 50 | + do { |
| 51 | + *d++ = utils::string::x2c(data); |
| 52 | + data += 2; |
| 53 | + } while ((data + 1 < end) && VALID_HEX(*data) && VALID_HEX(*(data + 1))); |
| 54 | + changed = true; |
71 | 55 | }
|
72 |
| - ++data; |
73 |
| - ++count; |
74 |
| - if (mytolower(*data) != 'x') { |
75 |
| - data--; |
76 |
| - count--; |
77 |
| - continue; |
| 56 | + else { |
| 57 | + *d++ = *data++; |
78 | 58 | }
|
| 59 | + } |
79 | 60 |
|
80 |
| - data++; |
81 |
| - ++count; |
| 61 | + *d = '\0'; |
82 | 62 |
|
83 |
| - // Do we need to keep "0x" if no hexa after? |
84 |
| - if (!VALID_HEX(data[0]) || !VALID_HEX(data[1])) { |
85 |
| - data -= 2; |
86 |
| - count -= 2; |
87 |
| - continue; |
88 |
| - } |
| 63 | + value.resize(d - reinterpret_cast<const unsigned char*>(value.c_str())); |
| 64 | + return changed; |
| 65 | +} |
89 | 66 |
|
90 |
| - while (VALID_HEX(data[0]) && VALID_HEX(data[1])) { |
91 |
| - *d++ = utils::string::x2c(data); |
92 |
| - data += 2; |
93 |
| - count += 2; |
94 |
| - } |
95 |
| - } |
96 | 67 |
|
97 |
| - *d = '\0'; |
98 |
| - return strlen(reinterpret_cast<char *>(begin)); |
| 68 | +bool SqlHexDecode::transform(std::string &value, const Transaction *trans) const { |
| 69 | + return inplace(value); |
99 | 70 | }
|
100 | 71 |
|
101 | 72 |
|
|
0 commit comments