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