6 #include "lib/replace/replace.h"
13 #include "lib/util/samba_util.h"
15 /* These flags say what can be asserted about a relationship between a string
16 and its supposedly escaped equivalent.
18 The first part of the flag name indicates the direction of transformation;
19 the second part is the expected result. For example, ESCAPE_EQ means the
20 escape is expected to succeed and result is expected to be equal to the
21 given answer. ESCAPE_EQ_CASECMP is only equal when compared
22 case-insensitively. UNESCAPE_ERR means unescaping the escaped string should
25 #define UNESCAPE_ERR 1
30 #define UNESCAPE_NE 32
31 #define ESCAPE_EQ_CASECMP 64
34 const char *escaped
; /* original for unescape; result for escape */
35 const char *unescaped
; /* result in unescape; original for escape */
36 uint32_t flags
; /* see above */
37 int unesc_len
; /* end - start will be this */
38 int unesc_strlen
; /* strlen() will say this */
39 int esc_len
; /* escaped string length */
42 /* unreserved = ALPHA DIGIT - . _ ~ */
44 char spectrum
[255 + 1];
45 char spectrum_escaped
[255 * 3 + 1];
47 struct rfc1738_test examples
[] = {
49 #define SIMPLE1 "this_is_a_simple-string._With_no_escapes~" /* maps to self */
53 ESCAPE_EQ
| UNESCAPE_EQ
, /* round trip should work */
58 #define SIMPLE2 "no escapes, but\n non-printables \xc5\x8d\x99"
59 #define SIMPLE2_ESC "no%20escapes%2C%20but%0A%20non-printables%20%C5%8D%99"
63 ESCAPE_EQ
| UNESCAPE_EQ
,
66 sizeof(SIMPLE2_ESC
) - 1,
68 #define SIMPLE3 "this @#$^&*()_+{}:;"
69 #define SIMPLE3_ESC "this%20%40%23%24%5E%26%2A%28%29_%2B%7B%7D%3A%3B"
73 ESCAPE_EQ
| UNESCAPE_EQ
,
76 sizeof(SIMPLE3_ESC
) - 1,
79 #define ESCAPE1 "%/\x06this string has expected escapes"
80 #define ESCAPE1_ESC "%25%2F%06this%20string%20has%20expected%20escapes"
81 #define ESCAPE1_ESC_ESC "%2525%252F%2506this%2520string%2520has%2520expected"\
86 ESCAPE_EQ
| UNESCAPE_EQ
,
89 sizeof(ESCAPE1_ESC
) - 1,
92 ESCAPE1_ESC_ESC
, /*re-escaping */
94 ESCAPE_EQ
| UNESCAPE_EQ
,
95 sizeof(ESCAPE1_ESC
) - 1,
96 sizeof(ESCAPE1_ESC
) - 1,
97 sizeof(ESCAPE1_ESC_ESC
) - 1,
99 #define ESCAPE2 "%25%2f%06-this-string-has-expected-lowercase-escapes-%ab"
100 #define ESCAPE2_UNESC "%/\x06-this-string-has-expected-lowercase-escapes-\xab"
104 ESCAPE_EQ_CASECMP
| UNESCAPE_EQ
, /* escape won't match case */
105 sizeof(ESCAPE2_UNESC
) - 1,
106 sizeof(ESCAPE2_UNESC
) - 1,
109 #define ESCAPE3 "%25%2f%06 %32 %44 %6a%AA THIS string h%61s random escapes %ab"
110 #define ESCAPE3_UNESC "%/\x06 2 D j\xAA THIS string has random escapes \xab"
114 ESCAPE_NE
| UNESCAPE_EQ
, /* escape will have escaped spaces */
115 sizeof(ESCAPE3_UNESC
) - 1,
116 sizeof(ESCAPE3_UNESC
) - 1,
119 #define ESCAPE4 "%25%25%25" /* */
120 #define ESCAPE4_UNESC "%%%" /* */
121 #define ESCAPE4_ESC "%2525%2525%2525"
125 ESCAPE_EQ
| UNESCAPE_EQ
,
126 sizeof(ESCAPE4_UNESC
) - 1,
127 sizeof(ESCAPE4_UNESC
) - 1,
133 ESCAPE_EQ
| UNESCAPE_EQ
,
136 sizeof(ESCAPE4_ESC
) - 1,
138 #define BAD1 "trailing percent is bad %"
139 #define BAD1_ESC "trailing%20percent%20is%20bad%20%25"
143 UNESCAPE_EQ
|ESCAPE_EQ
,
146 sizeof(BAD1_ESC
) - 1,
156 #define BAD2 "trailing percent is bad %1"
157 #define BAD3 "bad characters %1 "
174 #define BAD4 "bad characters %1 "
183 #define BAD5 "bad characters %1- "
192 #define BAD6 "bad characters %1G "
201 #define BAD7 "bad characters %%1 "
210 #define BAD8 "bad characters %sb "
219 #define BAD_SSCANF "sscanf would be happy with this\n"
220 #define BAD_SSCANF_ESC "sscanf would be happy with this% a"
224 ESCAPE_NE
| UNESCAPE_ERR
,
225 sizeof(BAD_SSCANF
) - 1,
226 sizeof(BAD_SSCANF
) - 1,
227 sizeof(BAD_SSCANF_ESC
) - 1,
229 /* now try some with zeros in. escaping can't see past zeros, and the result is truncated */
231 #define ZERO_UNESC "\0"
233 ESCAPE4 ZERO ESCAPE4
,
234 ESCAPE4_UNESC ZERO_UNESC ESCAPE4_UNESC
,
235 ESCAPE_NE
| UNESCAPE_EQ
,
236 sizeof(ESCAPE4_UNESC ZERO_UNESC ESCAPE4_UNESC
) - 1,
237 sizeof(ESCAPE4_UNESC
) - 1,
238 sizeof(ESCAPE4 ZERO ESCAPE4
) - 1,
242 ZERO_UNESC ESCAPE4_UNESC
,
243 ESCAPE_NE
| UNESCAPE_EQ
,
244 sizeof(ZERO_UNESC ESCAPE4_UNESC
) - 1,
246 sizeof(ZERO ESCAPE4
) - 1,
251 ESCAPE_NE
| UNESCAPE_EQ
,
252 sizeof(ZERO_UNESC
) - 1,
259 ESCAPE_EQ
| UNESCAPE_EQ
,
266 static struct rfc1738_test
* dup_test(struct rfc1738_test
*src
)
268 struct rfc1738_test
*dest
= malloc(sizeof(*dest
));
269 char *esc
= NULL
, *unesc
= NULL
;
275 esc
= malloc(src
->esc_len
+ 1);
280 memcpy(esc
, src
->escaped
, src
->esc_len
+ 1);
284 if (src
->unesc_len
) {
285 unesc
= malloc(src
->unesc_len
+ 1);
291 memcpy(unesc
, src
->unescaped
, src
->unesc_len
+ 1);
292 dest
->unescaped
= unesc
;
298 static void free_test(struct rfc1738_test
*t
)
300 free(discard_const_p(char, t
->escaped
));
301 free(discard_const_p(char, t
->unescaped
));
306 static void test_unescape(void **state
)
310 struct rfc1738_test
*test
, *orig
;
311 for (i
= 0; i
< ARRAY_SIZE(examples
); i
++) {
313 if ((orig
->flags
& (UNESCAPE_ERR
|
315 UNESCAPE_NE
)) == 0) {
318 test
= dup_test(&examples
[i
]);
319 s
= discard_const_p(char, test
->escaped
);
320 e
= rfc1738_unescape(s
);
321 if (test
->flags
& UNESCAPE_ERR
) {
327 assert_int_equal(e
- s
, test
->unesc_len
);
329 if (test
->flags
& UNESCAPE_EQ
) {
330 assert_memory_equal(s
,
333 assert_int_equal(strlen(s
),
336 assert_memory_not_equal(s
,
339 assert_int_equal(strlen(s
),
346 static void test_escape(void **state
)
350 struct rfc1738_test
*test
, *orig
;
351 for (i
= 0; i
< ARRAY_SIZE(examples
); i
++) {
353 if ((orig
->flags
& (ESCAPE_EQ
|
358 test
= dup_test(&examples
[i
]);
359 s
= discard_const_p(char, test
->unescaped
);
360 e
= rfc1738_escape_part(NULL
, s
);
361 if (test
->flags
& ESCAPE_EQ
) {
362 assert_memory_equal(e
, test
->escaped
,
364 } else if (test
->flags
& ESCAPE_EQ_CASECMP
) {
365 int cmp
= strcasecmp(e
, test
->escaped
);
366 assert_int_equal(cmp
, 0);
367 assert_string_not_equal(e
, test
->escaped
);
369 assert_string_not_equal(e
, test
->escaped
);
376 static void gen_spectrum(void)
379 const char *lut
= "0123456789ABCDEF";
380 for (i
= 1; i
< 256; i
++) {
388 spectrum_escaped
[j
] = i
;
391 spectrum_escaped
[j
] = '%';
392 spectrum_escaped
[j
+ 1] = lut
[i
>> 4];
393 spectrum_escaped
[j
+ 2] = lut
[i
& 15];
397 spectrum
[i
- 1] = '\0';
398 spectrum_escaped
[j
] = '\0';
401 int main(int argc
, const char **argv
)
403 const struct CMUnitTest tests
[] = {
404 cmocka_unit_test(test_escape
),
405 cmocka_unit_test(test_unescape
),
409 cmocka_set_message_output(CM_OUTPUT_SUBUNIT
);
410 return cmocka_run_group_tests(tests
, NULL
, NULL
);