Home | History | Annotate | Line # | Download | only in sh
      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 
     36 atf_test_case nul_elimination
     37 
     38 nul_elimination_head() {
     39 	atf_set "descr" "verifies that \0 chars in input are properly ignored"
     40 }
     41 
     42 nul_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 
    174 atf_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