xref: /freebsd/contrib/libarchive/libarchive/test/test_acl_from_text_overread.c (revision 185becb1e1bd2657c156f78aeb52edac05ba5fb5)
1 /*-
2  * Copyright (c) 2026 Kaif Khan
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 
27 #define __LIBARCHIVE_TEST
28 #include "archive_acl_private.h"
29 
30 /*
31  * archive_acl_from_text_nl() takes a pointer and a length and does not
32  * require the buffer to be NUL terminated.  An entry that is only
33  * whitespace, or trailing whitespace after a valid entry, must not make
34  * the parser read past the end of the buffer.
35  *
36  * Each input is copied into a buffer sized to exactly its length so that
37  * a read past the end is out of bounds.
38  */
39 static void
parse_nl(const char * text,int type)40 parse_nl(const char *text, int type)
41 {
42 	size_t len = strlen(text);
43 	char *buf = malloc(len);
44 	struct archive_acl acl;
45 
46 	assert(buf != NULL);
47 	memcpy(buf, text, len);
48 	memset(&acl, 0, sizeof(acl));
49 	/* Must not read buf[len]. */
50 	archive_acl_from_text_nl(&acl, buf, len, type, NULL);
51 	archive_acl_clear(&acl);
52 	free(buf);
53 }
54 
DEFINE_TEST(test_acl_from_text_overread)55 DEFINE_TEST(test_acl_from_text_overread)
56 {
57 	static const char *whitespace[] = {
58 		" ", "   ", "\t", "\n\n", "user::rwx,   "
59 	};
60 	size_t i;
61 
62 	for (i = 0; i < sizeof(whitespace) / sizeof(whitespace[0]); i++) {
63 		parse_nl(whitespace[i], ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
64 		parse_nl(whitespace[i], ARCHIVE_ENTRY_ACL_TYPE_NFS4);
65 	}
66 
67 	/*
68 	 * Trailing whitespace after a valid entry must not change the parse:
69 	 * the count matches the same text without the trailing spaces.
70 	 */
71 	{
72 		static const char clean[] = "user:100:rwx";
73 		static const char padded[] = "user:100:rwx   ";
74 		struct archive_acl acl1, acl2;
75 		char *b1 = malloc(sizeof(clean) - 1);
76 		char *b2 = malloc(sizeof(padded) - 1);
77 
78 		assert(b1 != NULL);
79 		assert(b2 != NULL);
80 		memcpy(b1, clean, sizeof(clean) - 1);
81 		memcpy(b2, padded, sizeof(padded) - 1);
82 		memset(&acl1, 0, sizeof(acl1));
83 		memset(&acl2, 0, sizeof(acl2));
84 		archive_acl_from_text_nl(&acl1, b1, sizeof(clean) - 1,
85 		    ARCHIVE_ENTRY_ACL_TYPE_ACCESS, NULL);
86 		archive_acl_from_text_nl(&acl2, b2, sizeof(padded) - 1,
87 		    ARCHIVE_ENTRY_ACL_TYPE_ACCESS, NULL);
88 		assertEqualInt(
89 		    archive_acl_count(&acl1, ARCHIVE_ENTRY_ACL_TYPE_ACCESS),
90 		    archive_acl_count(&acl2, ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
91 		assert(archive_acl_count(&acl2,
92 		    ARCHIVE_ENTRY_ACL_TYPE_ACCESS) > 0);
93 		archive_acl_clear(&acl1);
94 		archive_acl_clear(&acl2);
95 		free(b1);
96 		free(b2);
97 	}
98 }
99