xref: /netbsd-src/tests/bin/sh/t_input.sh (revision 00937795f5cdeb348dc6bf60942524ee1cf29cef)
1# $NetBSD: t_input.sh,v 1.2 2024/10/14 12:26:28 kre Exp $
2#
3# Copyright (c) 2021 The NetBSD Foundation, Inc.
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9# 1. Redistributions of source code must retain the above copyright
10#    notice, this list of conditions and the following disclaimer.
11# 2. Redistributions in binary form must reproduce the above copyright
12#    notice, this list of conditions and the following disclaimer in the
13#    documentation and/or other materials provided with the distribution.
14#
15# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
16# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25# POSSIBILITY OF SUCH DAMAGE.
26#
27# the implementation of "sh" to test
28: ${TEST_SH:="/bin/sh"}
29
30# This set of tests checks the low level shell (script) input
31# systrem (reading script files, nested files, fines read while
32# reading strings, ..) and correctly dropping nul bytes from file data
33
34# other shell input (the read builtin for example) is not covered here.
35
36atf_test_case nul_elimination
37
38nul_elimination_head() {
39	atf_set "descr" "verifies that \0 chars in input are properly ignored"
40}
41
42nul_elimination_body() {
43	atf_require_prog printf
44	atf_require_prog stat
45
46	# these really should always be present, but...
47	atf_require_prog dd
48	atf_require_prog cat
49	atf_require_prog rm
50
51	atf_expect_fail "nuls are now errors, not ignored, revisit later"
52
53	# please do not make even trivial changes (like correcting spelling)
54	# to the following script without taking care to fix the following
55	# tests, even minor changes can defeat the purpose of the test
56	cat > helper.sh <<- EOF
57		# a line of commentary that does nothing
58		# another line of comments (these just make the script bigger)
59		printf A
60		eval "printf B"
61		if printf C
62		then
63			printf D
64		fi
65		for x in E F G H
66		do
67			printf "\$x"
68		done
69		printf \\
70			I
71		printf '\n'
72		exit 0
73	EOF
74
75	# this first test simply verifies that the script works as
76	# expected, should it fail, it is not a problem with \0 chars
77	atf_check -s exit:0 -o 'inline:ABCDEFGHI\n' -e empty \
78		${TEST_SH} helper.sh
79
80	size=$(stat -f %z helper.sh)
81
82	# Now insert \0 chars at specifically chosen spots in script
83	for loc in 0 10 40 41 42 104 105 106 110 111 112 113 119 127 128 \
84		144 150 162 165 168 187 202 203 204 205 214 215 216 224 225
85	do
86		# at each location try varying the number of \0's inserted
87		for N in 1 2 4 7
88		do
89			OF="helper-${N}@${loc}.sh"
90
91			test "${loc}" -gt 0 &&
92				dd if=helper.sh bs=1 count="${loc}" \
93				   of="${OF}" >/dev/null 2>&1
94			dd if=helper.sh bs=1 skip="${loc}" \
95				oseek="$(( loc + N ))" \
96				of="${OF}" >/dev/null 2>&1
97
98			test "$(stat -f %z "${OF}")" -eq  "$(( size + N ))" ||
99					atf_fail "${N}@${loc}: build failure"
100
101			atf_check -s exit:0 -o 'inline:ABCDEFGHI\n' -e empty \
102				${TEST_SH} "${OF}"
103
104			rm -f "${OF}"
105		done
106
107	done
108
109	# Next insert \0 chars at multiple chosen locations
110	# nb: offsets in each arg must be non-decreasing
111	for locs in '0 225' '0 224' '0 127 223' '0 10 15' '0 48 55' \
112		'0 0 0 225 225 225' '0 0 127 128 224 224 225' \
113		'104 106' '105 110' '113 119' '113 119 122' '113 127' \
114		'129 130 131 132 133 136 139 140'  '184 185 186 187' \
115		'202 203 203 204 204 205 205 206 207'
116	do
117		set -- $locs
118		gaps=$#
119
120		IFS=-
121		OF="helper-${*}.sh"
122		unset IFS
123
124		loc=$1; shift
125		test "${loc}" -gt 0 &&
126			dd if=helper.sh bs=1 count="${loc}" \
127			   of="${OF}" >/dev/null 2>&1
128		G=1
129		for N
130		do
131			count=$(( N - loc ))
132			if [ "${count}" -eq 0 ]
133			then
134				printf '\0' >> "${OF}"
135			else
136				dd if=helper.sh bs=1 skip="${loc}" \
137				    oseek="$(( loc + G ))" count="${count}" \
138				    of="${OF}" >/dev/null 2>&1
139			fi
140			loc=$N
141			G=$(( G + 1 ))
142		done
143
144		if [ "${loc}" -lt "${size}" ]
145		then
146			dd if=helper.sh bs=1 skip="${loc}" \
147			    oseek="$(( loc + G ))" of="${OF}" >/dev/null 2>&1
148		else
149			printf '\0' >> "${OF}"
150		fi
151
152		test "$(stat -f %z "${OF}")" -eq  "$(( size + gaps ))" ||
153				atf_fail "${locs}: build failure"
154
155		atf_check -s exit:0 -o 'inline:ABCDEFGHI\n' -e empty \
156			${TEST_SH} "${OF}"
157
158		rm -f "${OF}"
159	done
160
161	# Now just insert \0's in random locations in the script,
162	# hoping that if the somewhat carefully selected insertions
163	# above fail to trigger a bug, then if any (bugs) remain,
164	# eventually Murphy will prevail, and one of these tests will catch it.
165
166	test "${RANDOM}" = "${RANDOM}" &&
167		atf_skip 'ATF shell does not support $RANDOM'
168
169	# To be added later...
170
171	return 0
172}
173
174atf_init_test_cases() {
175	atf_add_test_case nul_elimination
176	# atf_add_test_case file_recursion
177	# atf_add_test_case file_string_recursion
178	# atf_add_test_case file_recursion_nul
179	# atf_add_test_case file_string_recursion_nul
180}
181