xref: /freebsd/contrib/sendmail/libsm/t-qic.c (revision 8d20be1e22095c27faf8fe8b2f0d089739cc742e)
1 /*
2  * Copyright (c) 2006 Sendmail, Inc. and its suppliers.
3  *	All rights reserved.
4  *
5  * By using this file, you agree to the terms and conditions set
6  * forth in the LICENSE file which can be found at the top level of
7  * the sendmail distribution.
8  */
9 
10 #include <sm/gen.h>
11 SM_IDSTR(id, "@(#)$Id: t-qic.c,v 1.9 2006/08/24 21:26:13 ca Exp $")
12 
13 #include <stdio.h>
14 #include <sm/sendmail.h>
15 #include <sm/assert.h>
16 #include <sm/heap.h>
17 #include <sm/string.h>
18 #include <sm/test.h>
19 
20 extern bool SmTestVerbose;
21 
22 
23 void
24 show_diff(s1, s2)
25 	const char *s1;
26 	const char *s2;
27 {
28 	int i;
29 
30 	for (i = 0; s1[i] != '\0' && s2[i] != '\0'; i++)
31 	{
32 		if (s1[i] != s2[i])
33 		{
34 			fprintf(stderr, "i=%d, s1[]=%u, s2[]=%u\n",
35 				i, (unsigned char) s1[i],
36 				(unsigned char) s2[i]);
37 			return;
38 		}
39 	}
40 	if (s1[i] != s2[i])
41 	{
42 		fprintf(stderr, "i=%d, s1[]=%u, s2[]=%u\n",
43 			i, (unsigned char) s1[i], (unsigned char) s2[i]);
44 	}
45 }
46 
47 char *quote_unquote __P((char *, char *, int, int));
48 
49 char *
50 quote_unquote(in, out, outlen, exp)
51 	char *in;
52 	char *out;
53 	int outlen;
54 	int exp;
55 {
56 	char *obp, *bp;
57 	char line_back[1024];
58 	char line_in[1024];
59 	int cmp;
60 
61 	sm_strlcpy(line_in, in, sizeof(line_in));
62 	obp = quote_internal_chars(in, out, &outlen);
63 	bp = str2prt(line_in);
64 	dequote_internal_chars(obp, line_back, sizeof(line_back));
65 	cmp = strcmp(line_in, line_back);
66 	SM_TEST(exp == cmp);
67 	if (cmp != exp && !SmTestVerbose)
68 	{
69 		fprintf(stderr, "in: %s\n", bp);
70 		bp = str2prt(line_back);
71 		fprintf(stderr, "out:%s\n", bp);
72 		fprintf(stderr, "cmp=%d\n", cmp);
73 		show_diff(in, line_back);
74 	}
75 	if (SmTestVerbose)
76 	{
77 		fprintf(stderr, "%s -> ", bp);
78 		bp = str2prt(obp);
79 		fprintf(stderr, "%s\n", bp);
80 		fprintf(stderr, "cmp=%d\n", cmp);
81 	}
82 	return obp;
83 }
84 
85 struct sm_qic_S
86 {
87 	char		*qic_in;
88 	char		*qic_out;
89 	int		 qic_exp;
90 };
91 
92 typedef struct sm_qic_S sm_qic_T;
93 
94 
95 int
96 main(argc, argv)
97 	int argc;
98 	char *argv[];
99 {
100 	char line_in[1024], line[256], line_out[32], *obp;
101 	int i, los, cmp;
102 	sm_qic_T inout[] = {
103 		  { "", "",	0 }
104 		, { "abcdef", "abcdef",	0 }
105 		, { "01234567890123456789", "01234567890123456789",	0 }
106 		, { "01234567890123456789\001", "01234567890123456789\001",
107 			0 }
108 		, { "012345\2067890123456789", "012345\377\2067890123456789",
109 			0 }
110 		, { "\377", "\377\377",	0 }
111 		, { "\240", "\240",	0 }
112 		, { "\220", "\377\220",	0 }
113 		, { "\240\220", "\240\377\220",	0 }
114 		, { "\377\377", "\377\377\377\377",	0 }
115 		, { "\377a\377b", "\377\377a\377\377b",	0 }
116 		, { "\376a\377b", "\376a\377\377b",	0 }
117 		, { "\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240",
118 		    "\377\200\377\201\377\202\377\203\377\204\377\205\377\206\377\207\377\210\377\211\377\212\377\213\377\214\377\215\377\216\377\217\377\220\377\221\377\222\377\223\377\224\377\225\377\226\377\227\377\230\377\231\377\232\377\233\377\234\377\235\377\236\377\237\240",
119 			0 }
120 		, { NULL, NULL,	0 }
121 	};
122 
123 	sm_test_begin(argc, argv, "test meta quoting");
124 	for (i = 0; i < sizeof(line_out); i++)
125 		line_out[i] = '\0';
126 	for (i = 0; i < sizeof(line_in); i++)
127 		line_in[i] = '\0';
128 	for (i = 0; i < sizeof(line_in) / 2; i++)
129 	{
130 		char ch;
131 
132 		ch = 0200 + i;
133 		if ('\0' == ch)
134 			ch = '0';
135 		line_in[i] = ch;
136 	}
137 	los = sizeof(line_out) / 2;
138 	obp = quote_unquote(line_in, line_out, los, 0);
139 	if (obp != line_out)
140 		SM_FREE(obp);
141 
142 	for (i = 0; i < sizeof(line_in); i++)
143 		line_in[i] = '\0';
144 	for (i = 0; i < sizeof(line_in) / 2; i++)
145 	{
146 		char ch;
147 
148 		ch = 0200 + i;
149 		if ('\0' == ch)
150 			ch = '0';
151 		line_in[i] = ch;
152 	}
153 	los = sizeof(line_in);
154 	obp = quote_unquote(line_in, line_in, los, 0);
155 	if (obp != line_in)
156 		SM_FREE(obp);
157 
158 	for (i = 0; inout[i].qic_in != NULL; i++)
159 	{
160 		los = sizeof(line_out) / 2;
161 		obp = quote_unquote(inout[i].qic_in, line_out, los,
162 				inout[i].qic_exp);
163 		cmp = strcmp(inout[i].qic_out, obp);
164 		SM_TEST(inout[i].qic_exp == cmp);
165 		if (inout[i].qic_exp != cmp && !SmTestVerbose)
166 		{
167 			char *bp;
168 
169 			bp = str2prt(obp);
170 			fprintf(stderr, "got: %s\n", bp);
171 			bp = str2prt(inout[i].qic_out);
172 			fprintf(stderr, "exp:%s\n", bp);
173 			fprintf(stderr, "cmp=%d\n", cmp);
174 			show_diff(inout[i].qic_in, inout[i].qic_out);
175 		}
176 		if (obp != line_out)
177 			SM_FREE(obp);
178 	}
179 
180 	/* use same buffer for in and out */
181 	for (i = 0; inout[i].qic_in != NULL; i++)
182 	{
183 		bool same;
184 
185 		same = strcmp(inout[i].qic_in, inout[i].qic_out) == 0;
186 		los = sm_strlcpy(line, inout[i].qic_in, sizeof(line));
187 		SM_TEST(los + 1 < sizeof(line));
188 		++los;
189 		obp = quote_unquote(line, line, los, inout[i].qic_exp);
190 		cmp = strcmp(inout[i].qic_out, obp);
191 		SM_TEST(inout[i].qic_exp == cmp);
192 		if (inout[i].qic_exp != cmp && !SmTestVerbose)
193 		{
194 			char *bp;
195 
196 			bp = str2prt(obp);
197 			fprintf(stderr, "got: %s\n", bp);
198 			bp = str2prt(inout[i].qic_out);
199 			fprintf(stderr, "exp:%s\n", bp);
200 			fprintf(stderr, "cmp=%d\n", cmp);
201 			show_diff(inout[i].qic_in, inout[i].qic_out);
202 		}
203 		if (obp != line)
204 		{
205 			SM_TEST(!same);
206 			if (same)
207 				show_diff(obp, inout[i].qic_out);
208 			SM_FREE(obp);
209 		}
210 	}
211 
212 	/* use NULL buffer for out */
213 	for (i = 0; inout[i].qic_in != NULL; i++)
214 	{
215 		los = 0;
216 		obp = quote_unquote(inout[i].qic_in, NULL, los,
217 				inout[i].qic_exp);
218 		SM_TEST(obp != NULL);
219 		cmp = strcmp(inout[i].qic_out, obp);
220 		SM_TEST(inout[i].qic_exp == cmp);
221 		if (inout[i].qic_exp != cmp && !SmTestVerbose)
222 		{
223 			char *bp;
224 
225 			bp = str2prt(obp);
226 			fprintf(stderr, "got: %s\n", bp);
227 			bp = str2prt(inout[i].qic_out);
228 			fprintf(stderr, "exp:%s\n", bp);
229 			fprintf(stderr, "cmp=%d\n", cmp);
230 			show_diff(inout[i].qic_in, inout[i].qic_out);
231 		}
232 	}
233 
234 	return sm_test_end();
235 }
236