xref: /netbsd-src/tests/bin/sh/t_input.sh (revision 00937795f5cdeb348dc6bf60942524ee1cf29cef)
1*00937795Skre# $NetBSD: t_input.sh,v 1.2 2024/10/14 12:26:28 kre Exp $
26974a2b2Skre#
36974a2b2Skre# Copyright (c) 2021 The NetBSD Foundation, Inc.
46974a2b2Skre# All rights reserved.
56974a2b2Skre#
66974a2b2Skre# Redistribution and use in source and binary forms, with or without
76974a2b2Skre# modification, are permitted provided that the following conditions
86974a2b2Skre# are met:
96974a2b2Skre# 1. Redistributions of source code must retain the above copyright
106974a2b2Skre#    notice, this list of conditions and the following disclaimer.
116974a2b2Skre# 2. Redistributions in binary form must reproduce the above copyright
126974a2b2Skre#    notice, this list of conditions and the following disclaimer in the
136974a2b2Skre#    documentation and/or other materials provided with the distribution.
146974a2b2Skre#
156974a2b2Skre# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
166974a2b2Skre# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
176974a2b2Skre# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
186974a2b2Skre# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
196974a2b2Skre# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
206974a2b2Skre# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
216974a2b2Skre# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
226974a2b2Skre# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
236974a2b2Skre# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
246974a2b2Skre# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
256974a2b2Skre# POSSIBILITY OF SUCH DAMAGE.
266974a2b2Skre#
276974a2b2Skre# the implementation of "sh" to test
286974a2b2Skre: ${TEST_SH:="/bin/sh"}
296974a2b2Skre
306974a2b2Skre# This set of tests checks the low level shell (script) input
316974a2b2Skre# systrem (reading script files, nested files, fines read while
326974a2b2Skre# reading strings, ..) and correctly dropping nul bytes from file data
336974a2b2Skre
346974a2b2Skre# other shell input (the read builtin for example) is not covered here.
356974a2b2Skre
366974a2b2Skreatf_test_case nul_elimination
376974a2b2Skre
386974a2b2Skrenul_elimination_head() {
396974a2b2Skre	atf_set "descr" "verifies that \0 chars in input are properly ignored"
406974a2b2Skre}
416974a2b2Skre
426974a2b2Skrenul_elimination_body() {
436974a2b2Skre	atf_require_prog printf
446974a2b2Skre	atf_require_prog stat
456974a2b2Skre
466974a2b2Skre	# these really should always be present, but...
476974a2b2Skre	atf_require_prog dd
486974a2b2Skre	atf_require_prog cat
496974a2b2Skre	atf_require_prog rm
506974a2b2Skre
51*00937795Skre	atf_expect_fail "nuls are now errors, not ignored, revisit later"
52*00937795Skre
536974a2b2Skre	# please do not make even trivial changes (like correcting spelling)
546974a2b2Skre	# to the following script without taking care to fix the following
556974a2b2Skre	# tests, even minor changes can defeat the purpose of the test
566974a2b2Skre	cat > helper.sh <<- EOF
576974a2b2Skre		# a line of commentary that does nothing
586974a2b2Skre		# another line of comments (these just make the script bigger)
596974a2b2Skre		printf A
606974a2b2Skre		eval "printf B"
616974a2b2Skre		if printf C
626974a2b2Skre		then
636974a2b2Skre			printf D
646974a2b2Skre		fi
656974a2b2Skre		for x in E F G H
666974a2b2Skre		do
676974a2b2Skre			printf "\$x"
686974a2b2Skre		done
696974a2b2Skre		printf \\
706974a2b2Skre			I
716974a2b2Skre		printf '\n'
726974a2b2Skre		exit 0
736974a2b2Skre	EOF
746974a2b2Skre
756974a2b2Skre	# this first test simply verifies that the script works as
766974a2b2Skre	# expected, should it fail, it is not a problem with \0 chars
776974a2b2Skre	atf_check -s exit:0 -o 'inline:ABCDEFGHI\n' -e empty \
786974a2b2Skre		${TEST_SH} helper.sh
796974a2b2Skre
806974a2b2Skre	size=$(stat -f %z helper.sh)
816974a2b2Skre
826974a2b2Skre	# Now insert \0 chars at specifically chosen spots in script
836974a2b2Skre	for loc in 0 10 40 41 42 104 105 106 110 111 112 113 119 127 128 \
846974a2b2Skre		144 150 162 165 168 187 202 203 204 205 214 215 216 224 225
856974a2b2Skre	do
866974a2b2Skre		# at each location try varying the number of \0's inserted
876974a2b2Skre		for N in 1 2 4 7
886974a2b2Skre		do
896974a2b2Skre			OF="helper-${N}@${loc}.sh"
906974a2b2Skre
916974a2b2Skre			test "${loc}" -gt 0 &&
926974a2b2Skre				dd if=helper.sh bs=1 count="${loc}" \
936974a2b2Skre				   of="${OF}" >/dev/null 2>&1
946974a2b2Skre			dd if=helper.sh bs=1 skip="${loc}" \
956974a2b2Skre				oseek="$(( loc + N ))" \
966974a2b2Skre				of="${OF}" >/dev/null 2>&1
976974a2b2Skre
986974a2b2Skre			test "$(stat -f %z "${OF}")" -eq  "$(( size + N ))" ||
996974a2b2Skre					atf_fail "${N}@${loc}: build failure"
1006974a2b2Skre
1016974a2b2Skre			atf_check -s exit:0 -o 'inline:ABCDEFGHI\n' -e empty \
1026974a2b2Skre				${TEST_SH} "${OF}"
1036974a2b2Skre
1046974a2b2Skre			rm -f "${OF}"
1056974a2b2Skre		done
1066974a2b2Skre
1076974a2b2Skre	done
1086974a2b2Skre
1096974a2b2Skre	# Next insert \0 chars at multiple chosen locations
1106974a2b2Skre	# nb: offsets in each arg must be non-decreasing
1116974a2b2Skre	for locs in '0 225' '0 224' '0 127 223' '0 10 15' '0 48 55' \
1126974a2b2Skre		'0 0 0 225 225 225' '0 0 127 128 224 224 225' \
1136974a2b2Skre		'104 106' '105 110' '113 119' '113 119 122' '113 127' \
1146974a2b2Skre		'129 130 131 132 133 136 139 140'  '184 185 186 187' \
1156974a2b2Skre		'202 203 203 204 204 205 205 206 207'
1166974a2b2Skre	do
1176974a2b2Skre		set -- $locs
1186974a2b2Skre		gaps=$#
1196974a2b2Skre
1206974a2b2Skre		IFS=-
1216974a2b2Skre		OF="helper-${*}.sh"
1226974a2b2Skre		unset IFS
1236974a2b2Skre
1246974a2b2Skre		loc=$1; shift
1256974a2b2Skre		test "${loc}" -gt 0 &&
1266974a2b2Skre			dd if=helper.sh bs=1 count="${loc}" \
1276974a2b2Skre			   of="${OF}" >/dev/null 2>&1
1286974a2b2Skre		G=1
1296974a2b2Skre		for N
1306974a2b2Skre		do
1316974a2b2Skre			count=$(( N - loc ))
1326974a2b2Skre			if [ "${count}" -eq 0 ]
1336974a2b2Skre			then
1346974a2b2Skre				printf '\0' >> "${OF}"
1356974a2b2Skre			else
1366974a2b2Skre				dd if=helper.sh bs=1 skip="${loc}" \
1376974a2b2Skre				    oseek="$(( loc + G ))" count="${count}" \
1386974a2b2Skre				    of="${OF}" >/dev/null 2>&1
1396974a2b2Skre			fi
1406974a2b2Skre			loc=$N
1416974a2b2Skre			G=$(( G + 1 ))
1426974a2b2Skre		done
1436974a2b2Skre
1446974a2b2Skre		if [ "${loc}" -lt "${size}" ]
1456974a2b2Skre		then
1466974a2b2Skre			dd if=helper.sh bs=1 skip="${loc}" \
1476974a2b2Skre			    oseek="$(( loc + G ))" of="${OF}" >/dev/null 2>&1
1486974a2b2Skre		else
1496974a2b2Skre			printf '\0' >> "${OF}"
1506974a2b2Skre		fi
1516974a2b2Skre
1526974a2b2Skre		test "$(stat -f %z "${OF}")" -eq  "$(( size + gaps ))" ||
1536974a2b2Skre				atf_fail "${locs}: build failure"
1546974a2b2Skre
1556974a2b2Skre		atf_check -s exit:0 -o 'inline:ABCDEFGHI\n' -e empty \
1566974a2b2Skre			${TEST_SH} "${OF}"
1576974a2b2Skre
1586974a2b2Skre		rm -f "${OF}"
1596974a2b2Skre	done
1606974a2b2Skre
1616974a2b2Skre	# Now just insert \0's in random locations in the script,
1626974a2b2Skre	# hoping that if the somewhat carefully selected insertions
1636974a2b2Skre	# above fail to trigger a bug, then if any (bugs) remain,
1646974a2b2Skre	# eventually Murphy will prevail, and one of these tests will catch it.
1656974a2b2Skre
1666974a2b2Skre	test "${RANDOM}" = "${RANDOM}" &&
1676974a2b2Skre		atf_skip 'ATF shell does not support $RANDOM'
1686974a2b2Skre
1696974a2b2Skre	# To be added later...
1706974a2b2Skre
1716974a2b2Skre	return 0
1726974a2b2Skre}
1736974a2b2Skre
1746974a2b2Skreatf_init_test_cases() {
1756974a2b2Skre	atf_add_test_case nul_elimination
1766974a2b2Skre	# atf_add_test_case file_recursion
1776974a2b2Skre	# atf_add_test_case file_string_recursion
1786974a2b2Skre	# atf_add_test_case file_recursion_nul
1796974a2b2Skre	# atf_add_test_case file_string_recursion_nul
1806974a2b2Skre}
181