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