xref: /freebsd/contrib/sendmail/libsm/t-qic.c (revision 95ee2897e98f5d444f26ed2334cc7c439f9c16c6)
1 /*
2  * Copyright (c) 2006 Proofpoint, 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.10 2013-11-22 20:51:43 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, int));
48 
49 char *
50 quote_unquote(in, out, outlen, exp, mode)
51 	char *in;
52 	char *out;
53 	int outlen;
54 	int exp;
55 	int mode;
56 {
57 	char *obp, *bp;
58 	char line_back[1024];
59 	char line_in[1024];
60 	int cmp;
61 
62 	sm_strlcpy(line_in, in, sizeof(line_in));
63 	obp = quote_internal_chars(in, out, &outlen, NULL);
64 	bp = str2prt(line_in);
65 	if (0 == mode)
66 		dequote_internal_chars(obp, line_back, sizeof(line_back));
67 	else if (1 == mode)
68 		dequote_internal_chars(obp, line_back, strlen(obp));
69 	else if (2 == mode)
70 		dequote_internal_chars(obp, line_back, strlen(obp) + 1);
71 	cmp = strcmp(line_in, line_back);
72 	SM_TEST(exp == cmp);
73 	if (cmp != exp && !SmTestVerbose)
74 	{
75 		fprintf(stderr, "in: %s\n", bp);
76 		bp = str2prt(line_back);
77 		fprintf(stderr, "out:%s\n", bp);
78 		fprintf(stderr, "cmp=%d\n", cmp);
79 		show_diff(in, line_back);
80 	}
81 	if (SmTestVerbose)
82 	{
83 		fprintf(stderr, "%s -> ", bp);
84 		bp = str2prt(obp);
85 		fprintf(stderr, "%s\n", bp);
86 		fprintf(stderr, "cmp=%d\n", cmp);
87 	}
88 	return obp;
89 }
90 
91 struct sm_qic_S
92 {
93 	char		*qic_in;
94 	char		*qic_out;
95 	int		 qic_exp;
96 };
97 
98 typedef struct sm_qic_S sm_qic_T;
99 
100 
101 int
102 main(argc, argv)
103 	int argc;
104 	char *argv[];
105 {
106 	char line_in[1024], line[256], line_out[32], *obp;
107 	int i, los, cmp, mode;
108 	sm_qic_T inout[] = {
109 		  { "", "",	0 }
110 		, { "abcdef", "abcdef",	0 }
111 		, { "01234567890123456789", "01234567890123456789",	0 }
112 		, { "\\", "\\",	0 }
113 		, { "\\A", "\\A",	0 }
114 		, { "01234567890123456789\001", "01234567890123456789\001",
115 			0 }
116 		, { "012345\2067890123456789", "012345\377\2067890123456789",
117 			0 }
118 		, { "\377", "\377\377",	0 }
119 		, { "\240", "\240",	0 }
120 		, { "\220", "\377\220",	0 }
121 		, { "\240\220", "\240\377\220",	0 }
122 		, { "\377\377", "\377\377\377\377",	0 }
123 		, { "\377a\377b", "\377\377a\377\377b",	0 }
124 		, { "\376a\377b", "\376a\377\377b",	0 }
125 		, { "\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",
126 		    "\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",
127 			0 }
128 		, { NULL, NULL,	0 }
129 	};
130 
131 	sm_test_begin(argc, argv, "test meta quoting");
132 	mode = 0;
133 	if (argc > 1)
134 		mode = atoi(argv[1]);
135 	for (i = 0; i < sizeof(line_out); i++)
136 		line_out[i] = '\0';
137 	for (i = 0; i < sizeof(line_in); i++)
138 		line_in[i] = '\0';
139 	for (i = 0; i < sizeof(line_in) / 2; i++)
140 	{
141 		char ch;
142 
143 		ch = 0200 + i;
144 		if ('\0' == ch)
145 			ch = '0';
146 		line_in[i] = ch;
147 	}
148 	los = sizeof(line_out) / 2;
149 	obp = quote_unquote(line_in, line_out, los, 0, mode);
150 	if (obp != line_out)
151 		SM_FREE(obp);
152 
153 	for (i = 0; i < sizeof(line_in); i++)
154 		line_in[i] = '\0';
155 	for (i = 0; i < sizeof(line_in) / 2; i++)
156 	{
157 		char ch;
158 
159 		ch = 0200 + i;
160 		if ('\0' == ch)
161 			ch = '0';
162 		line_in[i] = ch;
163 	}
164 	los = sizeof(line_in);
165 	obp = quote_unquote(line_in, line_in, los, 0, mode);
166 	if (obp != line_in)
167 		SM_FREE(obp);
168 
169 	for (i = 0; inout[i].qic_in != NULL; i++)
170 	{
171 		los = sizeof(line_out) / 2;
172 		obp = quote_unquote(inout[i].qic_in, line_out, los,
173 				inout[i].qic_exp, mode);
174 		cmp = strcmp(inout[i].qic_out, obp);
175 		SM_TEST(inout[i].qic_exp == cmp);
176 		if (inout[i].qic_exp != cmp && !SmTestVerbose)
177 		{
178 			char *bp;
179 
180 			bp = str2prt(obp);
181 			fprintf(stderr, "got: %s\n", bp);
182 			bp = str2prt(inout[i].qic_out);
183 			fprintf(stderr, "exp:%s\n", bp);
184 			fprintf(stderr, "cmp=%d\n", cmp);
185 			show_diff(inout[i].qic_in, inout[i].qic_out);
186 		}
187 		if (obp != line_out)
188 			SM_FREE(obp);
189 	}
190 
191 	/* use same buffer for in and out */
192 	for (i = 0; inout[i].qic_in != NULL; i++)
193 	{
194 		bool same;
195 
196 		same = strcmp(inout[i].qic_in, inout[i].qic_out) == 0;
197 		los = sm_strlcpy(line, inout[i].qic_in, sizeof(line));
198 		SM_TEST(los + 1 < sizeof(line));
199 		++los;
200 		obp = quote_unquote(line, line, los, inout[i].qic_exp, mode);
201 		cmp = strcmp(inout[i].qic_out, obp);
202 		SM_TEST(inout[i].qic_exp == cmp);
203 		if (inout[i].qic_exp != cmp && !SmTestVerbose)
204 		{
205 			char *bp;
206 
207 			bp = str2prt(obp);
208 			fprintf(stderr, "got: %s\n", bp);
209 			bp = str2prt(inout[i].qic_out);
210 			fprintf(stderr, "exp:%s\n", bp);
211 			fprintf(stderr, "cmp=%d\n", cmp);
212 			show_diff(inout[i].qic_in, inout[i].qic_out);
213 		}
214 		if (obp != line)
215 		{
216 			SM_TEST(!same);
217 			if (same)
218 				show_diff(obp, inout[i].qic_out);
219 			SM_FREE(obp);
220 		}
221 	}
222 
223 	/* use NULL buffer for out */
224 	for (i = 0; inout[i].qic_in != NULL; i++)
225 	{
226 		los = 0;
227 		obp = quote_unquote(inout[i].qic_in, NULL, los,
228 				inout[i].qic_exp, mode);
229 		SM_TEST(obp != NULL);
230 		cmp = strcmp(inout[i].qic_out, obp);
231 		SM_TEST(inout[i].qic_exp == cmp);
232 		if (inout[i].qic_exp != cmp && !SmTestVerbose)
233 		{
234 			char *bp;
235 
236 			bp = str2prt(obp);
237 			fprintf(stderr, "got: %s\n", bp);
238 			bp = str2prt(inout[i].qic_out);
239 			fprintf(stderr, "exp:%s\n", bp);
240 			fprintf(stderr, "cmp=%d\n", cmp);
241 			show_diff(inout[i].qic_in, inout[i].qic_out);
242 		}
243 	}
244 
245 	return sm_test_end();
246 }
247