1 /*-
2  * Copyright (c) 2003-2007 Tim Kientzle
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 #include "test.h"
26 __FBSDID("$FreeBSD$");
27 
28 /* Copy this function for each test file and adjust it accordingly. */
29 DEFINE_TEST(test_compat_zip_1)
30 {
31 	char name[] = "test_compat_zip_1.zip";
32 	struct archive_entry *ae;
33 	struct archive *a;
34 	int r;
35 
36 	assert((a = archive_read_new()) != NULL);
37 	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
38 	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a));
39 	extract_reference_file(name);
40 	assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240));
41 
42 	/* Read first entry. */
43 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
44 	assertEqualString("META-INF/MANIFEST.MF", archive_entry_pathname(ae));
45 
46 	/* Read second entry. */
47 	r = archive_read_next_header(a, &ae);
48 	if (r == ARCHIVE_FATAL && archive_zlib_version() == NULL) {
49 		skipping("Skipping ZIP compression check: %s",
50 			archive_error_string(a));
51 		goto finish;
52 	}
53 	assertEqualIntA(a, ARCHIVE_OK, r);
54 	assertEqualString("tmp.class", archive_entry_pathname(ae));
55 
56 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
57 
58 	assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE);
59 	assertEqualInt(archive_format(a), ARCHIVE_FORMAT_ZIP);
60 
61 finish:
62 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
63 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
64 }
65 
66 /*
67  * Verify that we skip junk between entries.  The compat_zip_2.zip file
68  * has several bytes of junk between 'file1' and 'file2'.  Such
69  * junk is routinely introduced by some Zip writers when they manipulate
70  * existing zip archives.
71  */
72 DEFINE_TEST(test_compat_zip_2)
73 {
74 	char name[] = "test_compat_zip_2.zip";
75 	struct archive_entry *ae;
76 	struct archive *a;
77 
78 	assert((a = archive_read_new()) != NULL);
79 	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
80 	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a));
81 	extract_reference_file(name);
82 	assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240));
83 
84 	/* Read first entry. */
85 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
86 	assertEqualString("file1", archive_entry_pathname(ae));
87 
88 	/* Read first entry. */
89 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
90 	assertEqualString("file2", archive_entry_pathname(ae));
91 
92 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
93 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
94 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
95 }
96 
97 /*
98  * Issue 185:  Test a regression that got in between 2.6 and 2.7 that
99  * broke extraction of Zip entries with length-at-end.
100  */
101 DEFINE_TEST(test_compat_zip_3)
102 {
103 	const char *refname = "test_compat_zip_3.zip";
104 	struct archive_entry *ae;
105 	struct archive *a;
106 
107 	extract_reference_file(refname);
108 	assert((a = archive_read_new()) != NULL);
109 	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
110 	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
111 	assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240));
112 
113 	/* First entry. */
114 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
115 	assertEqualString("soapui-4.0.0/", archive_entry_pathname(ae));
116 	assertEqualInt(0, archive_entry_size(ae));
117 	assert(archive_entry_size_is_set(ae));
118 	assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));
119 
120 	/* Second entry. */
121 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
122 	assertEqualString("soapui-4.0.0/soapui-settings.xml", archive_entry_pathname(ae));
123 	assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
124 	assertEqualInt(1030, archive_entry_size(ae));
125 	assert(archive_entry_size_is_set(ae));
126 
127 	/* Extract under a different name. */
128 	archive_entry_set_pathname(ae, "test_3.txt");
129 	if(archive_zlib_version() != NULL) {
130 		char *p;
131 		size_t s;
132 		assertEqualIntA(a, ARCHIVE_OK, archive_read_extract(a, ae, 0));
133 		/* Verify the first 12 bytes actually got written to disk correctly. */
134 		p = slurpfile(&s, "test_3.txt");
135 		assertEqualInt(s, 1030);
136 		assertEqualMem(p, "<?xml versio", 12);
137 		free(p);
138 	} else {
139 		skipping("Skipping ZIP compression check, no libz support");
140 	}
141 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
142 
143 	assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
144 	assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a));
145 }
146 
147 /**
148  * A file with leading garbage (similar to an SFX file).
149  */
150 DEFINE_TEST(test_compat_zip_4)
151 {
152 	const char *refname = "test_compat_zip_4.zip";
153 	struct archive_entry *ae;
154 	struct archive *a;
155 	void *p;
156 	size_t s;
157 
158 	extract_reference_file(refname);
159 	p = slurpfile(&s, refname);
160 
161 	/* SFX files require seek support. */
162 	assert((a = archive_read_new()) != NULL);
163 	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
164 	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
165 	assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, p, s, 18));
166 
167 	/* First entry. */
168 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
169 	assertEqualString("foo", archive_entry_pathname(ae));
170 	assertEqualInt(4, archive_entry_size(ae));
171 	assert(archive_entry_size_is_set(ae));
172 	assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
173 	assertEqualInt(0412, archive_entry_perm(ae));
174 
175 	/* Second entry. */
176 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
177 	assertEqualString("bar", archive_entry_pathname(ae));
178 	assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
179 	assertEqualInt(4, archive_entry_size(ae));
180 	assert(archive_entry_size_is_set(ae));
181 	assertEqualInt(0567, archive_entry_perm(ae));
182 
183 	/* Third entry. */
184 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
185 	assertEqualString("baz", archive_entry_pathname(ae));
186 	assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
187 	assertEqualInt(4, archive_entry_size(ae));
188 	assert(archive_entry_size_is_set(ae));
189 	assertEqualInt(0644, archive_entry_perm(ae));
190 
191 	assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
192 	assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a));
193 
194 	/* Try reading without seek support and watch it fail. */
195 	assert((a = archive_read_new()) != NULL);
196 	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
197 	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
198 	assertEqualIntA(a, ARCHIVE_FATAL, read_open_memory(a, p, s, 3));
199 	assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
200 	assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a));
201 	free(p);
202 }
203 /**
204  * Issue 152: A file generated by a tool that doesn't really
205  * believe in populating local file headers at all.  This
206  * is only readable with the seeking reader.
207  */
208 DEFINE_TEST(test_compat_zip_5)
209 {
210 	const char *refname = "test_compat_zip_5.zip";
211 	struct archive_entry *ae;
212 	struct archive *a;
213 	void *p;
214 	size_t s;
215 
216 	extract_reference_file(refname);
217 	p = slurpfile(&s, refname);
218 
219 	/* Verify with seek support.
220 	 * Everything works correctly here. */
221 	assert((a = archive_read_new()) != NULL);
222 	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
223 	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
224 	assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, p, s, 18));
225 
226 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
227 	assertEqualString("Metadata/Job_PT.xml", archive_entry_pathname(ae));
228 	assertEqualInt(3559, archive_entry_size(ae));
229 	assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
230 	assertEqualInt(0664, archive_entry_perm(ae));
231 
232 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
233 	assertEqualString("Metadata/MXDC_Empty_PT.xml", archive_entry_pathname(ae));
234 	assertEqualInt(456, archive_entry_size(ae));
235 	assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
236 	assertEqualInt(0664, archive_entry_perm(ae));
237 
238 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
239 	assertEqualString("Documents/1/Metadata/Page1_Thumbnail.JPG", archive_entry_pathname(ae));
240 	assertEqualInt(1495, archive_entry_size(ae));
241 	assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
242 	assertEqualInt(0664, archive_entry_perm(ae));
243 	/* TODO: Read some of the file data and verify it.
244 	   The code to read uncompressed Zip entries with "file at end" semantics
245 	   is tricky and should be verified more carefully. */
246 
247 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
248 	assertEqualString("Documents/1/Pages/_rels/1.fpage.rels", archive_entry_pathname(ae));
249 
250 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
251 	assertEqualString("Documents/1/Pages/1.fpage", archive_entry_pathname(ae));
252 
253 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
254 	assertEqualString("Documents/1/Resources/Fonts/3DFDBC8B-4514-41F1-A808-DEA1C79BAC2B.odttf", archive_entry_pathname(ae));
255 
256 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
257 	assertEqualString("Documents/1/_rels/FixedDocument.fdoc.rels", archive_entry_pathname(ae));
258 
259 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
260 	assertEqualString("Documents/1/FixedDocument.fdoc", archive_entry_pathname(ae));
261 
262 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
263 	assertEqualString("_rels/FixedDocumentSequence.fdseq.rels", archive_entry_pathname(ae));
264 
265 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
266 	assertEqualString("FixedDocumentSequence.fdseq", archive_entry_pathname(ae));
267 
268 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
269 	assertEqualString("_rels/.rels", archive_entry_pathname(ae));
270 
271 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
272 	assertEqualString("[Content_Types].xml", archive_entry_pathname(ae));
273 
274 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
275 
276 	assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
277 	assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a));
278 
279 	/* Try reading without seek support. */
280 	assert((a = archive_read_new()) != NULL);
281 	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
282 	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
283 	assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, p, s, 3));
284 
285 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
286 	assertEqualString("Metadata/Job_PT.xml", archive_entry_pathname(ae));
287 	assertEqualInt(0, archive_entry_size(ae));
288 	assert(!archive_entry_size_is_set(ae));
289 	assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
290 	assertEqualInt(0664, archive_entry_perm(ae));
291 
292 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
293 	assertEqualString("Metadata/MXDC_Empty_PT.xml", archive_entry_pathname(ae));
294 	assertEqualInt(0, archive_entry_size(ae));
295 	assert(!archive_entry_size_is_set(ae));
296 	assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
297 	assertEqualInt(0664, archive_entry_perm(ae));
298 
299 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
300 	assertEqualString("Documents/1/Metadata/Page1_Thumbnail.JPG", archive_entry_pathname(ae));
301 	assertEqualInt(0, archive_entry_size(ae));
302 	assert(!archive_entry_size_is_set(ae));
303 	assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
304 	assertEqualInt(0664, archive_entry_perm(ae));
305 
306 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
307 	assertEqualString("Documents/1/Pages/_rels/1.fpage.rels", archive_entry_pathname(ae));
308 
309 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
310 	assertEqualString("Documents/1/Pages/1.fpage", archive_entry_pathname(ae));
311 
312 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
313 	assertEqualString("Documents/1/Resources/Fonts/3DFDBC8B-4514-41F1-A808-DEA1C79BAC2B.odttf", archive_entry_pathname(ae));
314 
315 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
316 	assertEqualString("Documents/1/_rels/FixedDocument.fdoc.rels", archive_entry_pathname(ae));
317 
318 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
319 	assertEqualString("Documents/1/FixedDocument.fdoc", archive_entry_pathname(ae));
320 
321 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
322 	assertEqualString("_rels/FixedDocumentSequence.fdseq.rels", archive_entry_pathname(ae));
323 
324 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
325 	assertEqualString("FixedDocumentSequence.fdseq", archive_entry_pathname(ae));
326 
327 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
328 	assertEqualString("_rels/.rels", archive_entry_pathname(ae));
329 
330 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
331 	assertEqualString("[Content_Types].xml", archive_entry_pathname(ae));
332 
333 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
334 
335 	assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
336 	assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a));
337 	free(p);
338 }
339 
340 /*
341  * Issue 225: Errors extracting MSDOS Zip archives with directories.
342  */
343 static void
344 compat_zip_6_verify(struct archive *a)
345 {
346 	struct archive_entry *ae;
347 
348 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
349 	assertEqualString("New Folder/New Folder/", archive_entry_pathname(ae));
350 	assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));
351 	/* Zip timestamps are local time, so vary by time zone. */
352 	/* TODO: A more complex assert would work here; we could
353 	   verify that it's within +/- 24 hours of a particular value. */
354 	/* assertEqualInt(1327314468, archive_entry_mtime(ae)); */
355 	assertEqualInt(0, archive_entry_size(ae));
356 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
357 	assertEqualString("New Folder/New Folder/New Text Document.txt", archive_entry_pathname(ae));
358 	assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
359 	/* Zip timestamps are local time, so vary by time zone. */
360 	/* assertEqualInt(1327314476, archive_entry_mtime(ae)); */
361 	assertEqualInt(11, archive_entry_size(ae));
362 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
363 }
364 
365 DEFINE_TEST(test_compat_zip_6)
366 {
367 	const char *refname = "test_compat_zip_6.zip";
368 	struct archive *a;
369 	void *p;
370 	size_t s;
371 
372 	extract_reference_file(refname);
373 	p = slurpfile(&s, refname);
374 
375 	assert((a = archive_read_new()) != NULL);
376 	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
377 	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
378 	assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, p, s, 7));
379 	compat_zip_6_verify(a);
380 	assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a));
381 
382 	assert((a = archive_read_new()) != NULL);
383 	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
384 	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
385 	assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, p, s, 7));
386 	compat_zip_6_verify(a);
387 	assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a));
388 	free(p);
389 }
390 
391 /*
392  * Issue 226: Try to reproduce hang when reading archives where the
393  * length-at-end marker ends exactly on a block boundary.
394  */
395 DEFINE_TEST(test_compat_zip_7)
396 {
397 	const char *refname = "test_compat_zip_7.xps";
398 	struct archive *a;
399 	struct archive_entry *ae;
400 	void *p;
401 	size_t s;
402 	int i;
403 
404 	extract_reference_file(refname);
405 	p = slurpfile(&s, refname);
406 
407 	for (i = 1; i < 1000; ++i) {
408 		assert((a = archive_read_new()) != NULL);
409 		assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a));
410 		assertEqualIntA(a, ARCHIVE_OK, read_open_memory_minimal(a, p, s, i));
411 
412 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
413 		assertEqualIntA(a, ARCHIVE_OK, archive_read_data_skip(a));
414 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
415 		assertEqualIntA(a, ARCHIVE_OK, archive_read_data_skip(a));
416 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
417 		assertEqualIntA(a, ARCHIVE_OK, archive_read_data_skip(a));
418 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
419 		assertEqualIntA(a, ARCHIVE_OK, archive_read_data_skip(a));
420 
421 		assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a));
422 	}
423 	free(p);
424 }
425 
426 /**
427  * A file with backslash path separators instead of slashes.
428  * PowerShell's Compress-Archive cmdlet produces such archives.
429  */
430 DEFINE_TEST(test_compat_zip_8)
431 {
432 	const char *refname = "test_compat_zip_8.zip";
433 	struct archive *a;
434 	struct archive_entry *ae;
435 	void *p;
436 	size_t s;
437 
438 	extract_reference_file(refname);
439 	p = slurpfile(&s, refname);
440 
441 	assert((a = archive_read_new()) != NULL);
442 	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a));
443 	assertEqualIntA(a, ARCHIVE_OK, read_open_memory_minimal(a, p, s, 7));
444 
445 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
446 	/* This file is in the archive as arc\test */
447 	assertEqualString("arc/test", archive_entry_pathname(ae));
448 	assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a));
449 	free(p);
450 }
451