]> git.ipfire.org Git - thirdparty/squid.git/blob - lib/tests/testRFC1738.cc
Merged from trunk
[thirdparty/squid.git] / lib / tests / testRFC1738.cc
1 #define SQUID_UNIT_TEST 1
2 #include "squid.h"
3
4 #if HAVE_ASSERT_H
5 #include <assert.h>
6 #endif
7
8 #include "testRFC1738.h"
9
10 /* Being a C library code it is best bodily included and tested with C++ type-safe techniques. */
11 #include "lib/rfc1738.c"
12
13 CPPUNIT_TEST_SUITE_REGISTRATION( testRFC1738 );
14
15 /* Regular Format de-coding tests */
16 void testRFC1738::testUrlDecode()
17 {
18 char *unescaped_str;
19
20 /* regular URL-path */
21 unescaped_str = xstrdup("%2Fdata%2Fsource%2Fpath");
22 rfc1738_unescape(unescaped_str);
23 CPPUNIT_ASSERT(memcmp(unescaped_str, "/data/source/path",18)==0);
24 xfree(unescaped_str);
25
26 /* path in full URL */
27 unescaped_str = xstrdup("http://foo.invalid%2Fdata%2Fsource%2Fpath");
28 rfc1738_unescape(unescaped_str);
29 CPPUNIT_ASSERT(memcmp(unescaped_str, "http://foo.invalid/data/source/path",36)==0);
30 xfree(unescaped_str);
31
32 // TODO query string...
33
34 /* Newline %0A encoded */
35 unescaped_str = xstrdup("w%0Ard");
36 rfc1738_unescape(unescaped_str);
37 CPPUNIT_ASSERT(memcmp(unescaped_str, "w\nrd",5)==0);
38 xfree(unescaped_str);
39
40 /* Handle Un-encoded % */
41 unescaped_str = xstrdup("w%rd");
42 rfc1738_unescape(unescaped_str);
43 CPPUNIT_ASSERT(memcmp(unescaped_str, "w%rd",5)==0);
44 xfree(unescaped_str);
45
46 /* Handle encoded % */
47 unescaped_str = xstrdup("w%%rd");
48 rfc1738_unescape(unescaped_str);
49 CPPUNIT_ASSERT(memcmp(unescaped_str, "w%rd",5)==0);
50 xfree(unescaped_str);
51
52 /* Handle mixed-encoded % */
53 unescaped_str = xstrdup("w%%%rd");
54 rfc1738_unescape(unescaped_str);
55 CPPUNIT_ASSERT(memcmp(unescaped_str, "w%%rd",6)==0);
56 xfree(unescaped_str);
57
58 /* A corrupt string */
59 unescaped_str = xstrdup("Bad String %1");
60 rfc1738_unescape(unescaped_str);
61 CPPUNIT_ASSERT(memcmp(unescaped_str, "Bad String %1",14)==0);
62 xfree(unescaped_str);
63
64 /* A partly corrupt string */
65 unescaped_str = xstrdup("Bad String %1A%3");
66 rfc1738_unescape(unescaped_str);
67 CPPUNIT_ASSERT(memcmp(unescaped_str, "Bad String \032%3",15)==0);
68 xfree(unescaped_str);
69
70 /* A non corrupt string */
71 unescaped_str = xstrdup("Good String %1A");
72 rfc1738_unescape(unescaped_str);
73 CPPUNIT_ASSERT(memcmp(unescaped_str, "Good String \032",14)==0);
74 xfree(unescaped_str);
75 }
76
77 /**
78 * Public API is formed of a triplet of encode functions mapping to the rfc1738_do_encode() engine.
79 *
80 * Flags:
81 * rfc1738_escape == 0
82 * rfc1738_escape_unescaped == -1
83 * rfc1738_escape_part == 1
84 */
85 void testRFC1738::testUrlEncode()
86 {
87 char *result;
88
89 /* TEST: Escaping only unsafe characters */
90
91 /* regular URL (no encoding needed) */
92 result = rfc1738_do_escape("http://foo.invalid/data/source/path", RFC1738_ESCAPE_UNSAFE);
93 CPPUNIT_ASSERT(memcmp(result, "http://foo.invalid/data/source/path",36)==0);
94
95 /* long string of unsafe # characters */
96 result = rfc1738_do_escape("################ ################ ################ ################ ################ ################ ################ ################", RFC1738_ESCAPE_UNSAFE);
97 CPPUNIT_ASSERT(memcmp(result, "%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%20%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%20%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%20%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%20%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%20%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%20%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%20%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23",406)==0);
98
99 /* TEST: escaping only reserved characters */
100
101 /* regular URL (full encoding requested) */
102 result = rfc1738_do_escape("http://foo.invalid/data/source/path", RFC1738_ESCAPE_RESERVED);
103 CPPUNIT_ASSERT(memcmp(result, "http%3A%2F%2Ffoo.invalid%2Fdata%2Fsource%2Fpath",48)==0);
104
105 /* regular path (encoding wanted for ALL special chars) */
106 result = rfc1738_do_escape("/data/source/path", RFC1738_ESCAPE_RESERVED);
107 CPPUNIT_ASSERT(memcmp(result, "%2Fdata%2Fsource%2Fpath",24)==0);
108
109 /* TEST: safety-escaping a string already partially escaped */
110
111 /* escaping of dangerous characters in a partially escaped string */
112 result = rfc1738_do_escape("http://foo.invalid/data%2Fsource[]", RFC1738_ESCAPE_UNESCAPED);
113 CPPUNIT_ASSERT(memcmp(result, "http://foo.invalid/data%2Fsource%5B%5D",39)==0);
114
115 /* escaping of hexadecimal 0xFF characters in a partially escaped string */
116 result = rfc1738_do_escape("http://foo.invalid/data%2Fsource\xFF\xFF", RFC1738_ESCAPE_UNESCAPED);
117 CPPUNIT_ASSERT(memcmp(result, "http://foo.invalid/data%2Fsource%FF%FF",39)==0);
118
119 }
120
121 /** SECURITY BUG TESTS: avoid null truncation attacks by skipping %00 bytes */
122 void testRFC1738::PercentZeroNullDecoding()
123 {
124 char *unescaped_str;
125
126 /* Attack with %00 encoded NULL */
127 unescaped_str = xstrdup("w%00rd");
128 rfc1738_unescape(unescaped_str);
129 CPPUNIT_ASSERT(memcmp(unescaped_str, "w%00rd",7)==0);
130 xfree(unescaped_str);
131
132 /* Attack with %0 encoded NULL */
133 unescaped_str = xstrdup("w%0rd");
134 rfc1738_unescape(unescaped_str);
135 CPPUNIT_ASSERT(memcmp(unescaped_str, "w%0rd",6)==0);
136 xfree(unescaped_str);
137
138 /* Handle '0' bytes embeded in encoded % */
139 unescaped_str = xstrdup("w%%00%rd");
140 rfc1738_unescape(unescaped_str);
141 CPPUNIT_ASSERT(memcmp(unescaped_str, "w%00%rd",8)==0);
142 xfree(unescaped_str);
143
144 /* Handle NULL bytes with encoded % */
145 unescaped_str = xstrdup("w%%%00%rd");
146 rfc1738_unescape(unescaped_str);
147 CPPUNIT_ASSERT(memcmp(unescaped_str, "w%%00%rd",9)==0);
148 xfree(unescaped_str);
149 }