1 #!/bin/sh 2 3 echo T.misc: miscellaneous buglets now watched for 4 5 awk=${awk-../a.out} 6 7 rm -f core 8 9 echo 'The big brown over the lazy doe 10 The big brown over the lazy dog 11 x 12 The big brown over the lazy dog' >foo 13 echo 'failed 14 succeeded 15 failed 16 succeeded' >foo1 17 $awk '{ if (match($0, /^The big brown over the lazy dog/) == 0) { 18 printf("failed\n") 19 } else { 20 printf("succeeded\n") 21 } 22 } ' foo >foo2 23 cmp -s foo1 foo2 || echo 'BAD: T.misc ghosh RE bug' 24 25 echo '123 26 1234567890 27 12345678901' >foo 28 echo '12345678901' >foo1 29 $awk 'length($0) > 10' foo >foo2 30 cmp -s foo1 foo2 || echo 'BAD: T.misc last number bug' 31 32 # check some \ sequences in strings (ascii) 33 echo HIJKL >foo1 34 echo foo | $awk '{ print "H\x49\x4a\x4BL" }' >foo2 35 cmp -s foo1 foo2 || echo 'BAD: T.misc hex string cvt' 36 37 echo 012x45 >foo1 38 $awk 'BEGIN { print "0\061\62x\0645" }' >foo2 39 cmp -s foo1 foo2 || echo 'BAD: T.misc oct string cvt' 40 41 # $i++ means ($i)++ 42 echo 3 5 | $awk '{ i = 1; print $i++ ; print $1, i }' >foo1 43 echo '3 44 4 1' >foo2 45 cmp -s foo1 foo2 || echo 'BAD: T.misc bad field increment' 46 47 # makes sure that fields are recomputed even if self-assignment 48 # take into account that subtracting from NF now rebuilds the record 49 echo 'a b c 50 s p q r 51 x y z' >foo 52 echo 'a 53 s p 54 x' >foo1 55 $awk '{ NF -= 2; $1 = $1; print }' <foo >foo2 56 diff foo1 foo2 || echo 1>&2 "BAD: T.misc bad field self-assignment" 57 58 echo '1 59 1' >foo1 60 $awk 'BEGIN {x = 1; print x; x = x; print x}' >foo2 61 diff foo1 foo2 || echo 1>&2 "BAD: T.misc bad self-assignment" 62 63 echo 573109312 | $awk '{print $1*4}' >foo1 64 echo 2292437248 >foo2 65 diff foo1 foo2 || echo 1>&2 "BAD: T.misc bad overflow" 66 67 # note that there are 8-bit characters in the echo 68 # some shells will probably screw this up. 69 echo '# 70 code 1 71 code 2' | 72 $awk '/^#/' >foo1 73 echo '#' >foo2 74 diff foo1 foo2 || echo 1>&2 "BAD: T.misc bad match of 8-bit char" 75 76 echo hello | 77 $awk 'BEGIN { FILENAME = "/etc/passwd" } 78 { print $0 }' >/dev/null 79 if test -r core; then echo 1>&2 "BAD: T.misc /etc/passwd dropped core"; fi 80 81 echo hello | 82 $awk ' function foo(foo) { 83 foo = 1 84 foo() 85 } 86 { foo(bar) } 87 ' >/dev/null 2>&1 88 if test -r core; then 89 echo 1>&2 "BAD: T.misc function foo(foo) dropped core" 90 rm -f core 91 fi 92 93 echo '2 94 10' | 95 $awk '{ x[NR] = $0 } # test whether $0 is NUM as well as STR 96 END { if (x[1] > x[2]) print "BAD: T.misc: $0 is not NUM" }' 97 98 99 $awk 'BEGIN { 100 npad = substr("alexander" " ",1,15) 101 print npad 102 }' >foo 103 grep '\\' foo && echo 1>&2 "BAD: T.misc alexander fails" 104 105 # This should give an error about function arguments 106 $awk ' 107 function foo(x) { print "x is" x } 108 BEGIN { foo(foo) } 109 ' 2>foo 110 grep "can't use function foo" foo >/dev/null || echo 1>&2 "BAD: T.misc fcn args" 111 112 113 # gawk defref test; should give error about undefined function 114 $awk 'BEGIN { foo() }' 2>foo 115 grep "calling undefined function foo" foo >/dev/null || echo 1>&2 "BAD: T.misc undefined function" 116 117 118 # gawk arrayparm test; should give error about function 119 $awk ' 120 BEGIN { 121 foo[1]=1; 122 foo[2]=2; 123 bug1(foo); 124 } 125 function bug1(i) { 126 for (i in foo) { 127 bug2(i); 128 delete foo[i]; 129 print i,1,bot[1]; 130 } 131 } 132 function bug2(arg) { 133 bot[arg]=arg; 134 } 135 ' 2>foo 136 grep "can.t assign to foo" foo >/dev/null || echo 1>&2 "BAD: T.misc foo bug" 137 138 139 # This should be a syntax error 140 $awk ' 141 !x = y 142 ' 2>foo 143 grep "syntax error" foo >/dev/null || echo 1>&2 "BAD: T.misc syntax error !x=y fails" 144 145 # This should print bbb 146 $awk ' 147 BEGIN { up[1] = "a" 148 for (i in up) gsub("a", "A", x) 149 print x x "bbb" 150 exit 151 } 152 ' >foo 153 grep bbb foo >/dev/null || echo 1>&2 "BAD: T.misc gsub failed" 154 155 echo yes | 156 $awk ' 157 BEGIN { 158 printf "push return" >"/dev/null" 159 getline ans <"/dev/null" 160 } ' 161 if test -r core; then echo 1>&2 "BAD: T.misc getline ans dropped core"; fi 162 163 $awk 'BEGIN { unireghf() } 164 function unireghf(hfeed) { hfeed[1] = 0 }' 165 if test -r core; then echo 1>&2 "BAD: T.misc unireghf dropped core"; fi 166 167 echo x | $awk '/[/]/' 2>foo 168 grep 'nonterminated character class' foo >/dev/null || error 'BAD: T.misc nonterminated fails' 169 if test -r core; then echo 1>&2 "BAD: T.misc nonterminated dropped core"; fi 170 171 $awk ' 172 function f() { return 12345 } 173 BEGIN { printf "<%s>\n", f() } 174 ' >foo 175 grep '<12345>' foo >/dev/null || echo 'BAD: T.misc <12345> fails' 176 177 echo 'abc 178 def 179 180 ghi 181 jkl' >foo 182 $awk ' 183 BEGIN { RS = "" 184 while (getline <"foo") 185 print 186 }' >foo1 187 $awk 'END {print NR}' foo1 | grep 4 >/dev/null || echo 'BAD: T.misc abcdef fails' 188 189 # Test for RS regex matching an empty record at EOF 190 echo a | $awk 1 RS='a\n' > foo1 191 cat << \EOF > foo2 192 193 EOF 194 diff foo1 foo2 || echo 'BAD: T.misc RS regex matching an empty record at EOF fails' 195 196 # Test for RS regex being reapplied 197 echo aaa1a2a | $awk 1 RS='^a' >foo1 198 cat << \EOF > foo2 199 200 aa1a2a 201 202 EOF 203 diff foo1 foo2 || echo 'BAD: T.misc ^regex reapplied fails' 204 205 # ^-anchored RS matching should be active at the start of each input file 206 tee foo1 foo2 >foo3 << \EOF 207 aaa 208 EOF 209 $awk 1 RS='^a' foo1 foo2 foo3 >foo4 210 cat << \EOF > foo5 211 212 aa 213 214 215 aa 216 217 218 aa 219 220 EOF 221 diff foo4 foo5 || echo 'BAD: T.misc ^RS matches the start of every input file fails' 222 223 # The following should not produce a warning about changing a constant 224 # nor about a curdled tempcell list 225 $awk 'function f(x) { x = 2 } 226 BEGIN { f(1) }' >foo 227 grep '^' foo && echo 'BAD: test constant change fails' 228 229 # The following should not produce a warning about a curdled tempcell list 230 $awk 'function f(x) { x } 231 BEGIN { f(1) }' >foo 232 grep '^' foo && echo 'BAD: test tempcell list fails' 233 234 $awk 'BEGIN { print 9, a=10, 11; print a; exit }' >foo1 235 echo '9 10 11 236 10' >foo2 237 diff foo1 foo2 || echo 'BAD: T.misc (embedded expression)' 238 239 echo "abc defgh ijkl" | $awk ' 240 { $1 = ""; line = $0; print line; print $0; $0 = line; print $0 }' >foo1 241 echo " defgh ijkl 242 defgh ijkl 243 defgh ijkl" >foo2 244 diff foo1 foo2 || echo 'BAD: T.misc (assignment to $0)' 245 246 $awk ' 247 function min(a, b) 248 { 249 if (a < b) 250 return a 251 else 252 return b 253 } 254 BEGIN { exit } 255 ' 256 if test -r core; then echo 1>&2 "BAD: T.misc function min dropped core"; fi 257 258 # The following should not give a syntax error message: 259 $awk ' 260 function expand(chart) { 261 getline chart < "CHAR.ticks" 262 } 263 ' >foo 264 grep '^' foo >/dev/null && echo 'BAD: T.misc expand error' 265 266 $awk 'BEGIN { print 1e40 }' >/dev/null 267 if test -r core; then echo 1>&2 "BAD: T.misc 1E40 dropped core"; fi 268 269 # The following syntax error should not dump core: 270 $awk ' 271 $NF==3 {first=1} 272 $NF==2 && first==0 && (abs($1-o1)>120||abs($2-o2)>120) {print $0} 273 $NF==2 {o1=%1; o2=$2; first=0} 274 ' 2>/dev/null 275 if test -r core; then echo 1>&2 "BAD: T.misc first/abs dropped core"; fi 276 277 # The following syntax error should not dump core: 278 $awk '{ n = split($1, address, !); print address[1] }' 2>foo 279 grep 'illegal statement' foo >/dev/null || echo 'BAD: T.misc split error' 280 if test -r core; then echo 1>&2 "BAD: T.misc split! dropped core"; fi 281 282 # The following should cause a syntax error message 283 $awk 'BEGIN {"hello"}' 2>foo 284 grep 'illegal statement' foo >/dev/null || echo 'BAD: T.misc hello error' 285 286 # The following should give a syntax error message: 287 $awk ' 288 function pile(c, r) { 289 r = ++pile[c] 290 } 291 292 { pile($1) } 293 ' 2>foo 294 grep 'context is' foo >/dev/null || echo 'BAD: T.misc pile error' 295 296 # This should complain about missing atan2 argument: 297 $awk 'BEGIN { atan2(1) }' 2>foo 298 grep 'requires two arg' foo >/dev/null || echo 'BAD: T.misc atan2 error' 299 300 # This should not core dump: 301 $awk 'BEGIN { f() } 302 function f(A) { delete A[1] } 303 ' 304 if test -r core; then echo 1>&2 "BAD: T.misc delete dropped core"; fi 305 306 # nasty one: should not be able to overwrite constants 307 $awk 'BEGIN { gsub(/ana/,"anda","banana") 308 printf "the monkey ate a %s\n", "banana" } 309 ' >/dev/null 2>foo 310 grep 'syntax error' foo >/dev/null || echo 'BAD: T.misc gsub banana error' 311 312 # nasty one: should not be able to overwrite constants 313 $awk 'BEGIN { sub(/ana/,"anda","banana") 314 printf "the monkey ate a %s\n", "banana" } 315 ' >/dev/null 2>foo 316 grep 'syntax error' foo >/dev/null || echo 'BAD: T.misc sub banana error' 317 318 # line numbers used to double-count comments 319 $awk '# 320 # 321 # 322 /x 323 ' >/dev/null 2>foo 324 grep 'line [45]' foo >/dev/null || echo 'BAD: T.misc lineno' 325 326 echo 'x \y' >foo1 330 $awk 'BEGIN { print "x\f\r\b\v\a\\y" }' >foo2 331 cmp -s foo1 foo2 || echo 'BAD: T.misc weird chars' 332 333 echo 0 >foo1 334 $awk ' BEGIN { exit } 335 { print } 336 END { print NR }' >foo2 337 cmp -s foo1 foo2 || echo 'BAD: T.misc BEGIN exit' 338 339 echo 1 >foo1 340 $awk ' { exit } 341 END { print NR }' /etc/passwd >foo2 342 cmp -s foo1 foo2 || echo 'BAD: T.misc immmediate exit' 343 344 echo 1 >foo1 345 $awk ' {i = 1; while (i <= NF) {if (i == NF) exit; i++ } } 346 END { print NR }' /etc/passwd >foo2 347 cmp -s foo1 foo2 || echo 'BAD: T.misc immmediate exit 2' 348 349 echo 1 >foo1 350 $awk ' function f() { 351 i = 1; while (i <= NF) {if (i == NF) return NR; i++ } 352 } 353 { if (f() == 1) exit } 354 END { print NR }' /etc/passwd >foo2 355 cmp -s foo1 foo2 || echo 'BAD: T.misc while return' 356 357 echo 1 >foo1 358 $awk ' function f() { 359 split("a b c", arr) 360 for (i in arr) {if (i == 3) return NR; i++ } 361 } 362 { if (f() == 1) exit } 363 END { print NR }' /etc/passwd >foo2 364 cmp -s foo1 foo2 || echo 'BAD: T.misc while return' 365 366 echo 1 >foo1 367 $awk ' {i = 1; do { if (i == NF) exit; i++ } while (i <= NF) } 368 END { print NR }' /etc/passwd >foo2 369 cmp -s foo1 foo2 || echo 'BAD: T.misc immmediate exit 3' 370 371 echo 1 >foo1 372 $awk ' function f() { 373 i = 1; do { if (i == NF) return NR; i++ } while (i <= NF) 374 } 375 { if (f() == 1) exit } 376 END { print NR }' /etc/passwd >foo2 377 cmp -s foo1 foo2 || echo 'BAD: T.misc do return' 378 379 echo 1 >foo1 380 $awk ' {i = 1; do { if (i == NF) break; i++ } while (i <= NF); exit } 381 END { print NR }' /etc/passwd >foo2 382 cmp -s foo1 foo2 || echo 'BAD: T.misc immmediate exit 4' 383 384 echo 1 >foo1 385 $awk ' { n = split($0, x) 386 for (i in x) { 387 if (i == 1) 388 exit } } 389 END { print NR }' /etc/passwd >foo2 390 cmp -s foo1 foo2 || echo 'BAD: T.misc immmediate exit 5' 391 392 echo XXXXXXXX >foo1 393 $awk 'BEGIN { s = "ab\fc\rd\be" 394 t = s; gsub("[" s "]", "X", t); print t }' >foo2 395 cmp -s foo1 foo2 || echo 'BAD: T.misc weird escapes in char class' 396 397 $awk '{}' /etc/passwd glop/glop >foo 2>foo2 398 grep "can't open.*glop" foo2 >/dev/null || echo "BAD: T.misc can't open" 399 400 echo ' 401 402 403 a 404 aa 405 406 b 407 408 409 c 410 411 ' >foo 412 echo 3 >foo1 413 $awk 'BEGIN { RS = "" }; END { print NR }' foo >foo2 414 cmp -s foo1 foo2 || echo 'BAD: T.misc RS botch' 415 416 $awk 'BEGIN \ 417 { 418 print "hello, world" 419 } 420 }}}' >foo1 2>foo2 421 grep 'source line 5' foo2 >/dev/null 2>&1 || echo 'BAD: T.misc continuation line number' 422 423 $awk 'BEGIN { 424 if () { 425 print "foo" 426 } 427 }' >foo1 2>foo2 428 grep 'syntax error at source line 2' foo2 >/dev/null 2>&1 || echo 'BAD: T.misc syntax error line number' 429 430 echo 111 222 333 >foo 431 $awk '{ f[1]=1; f[2]=2; print $f[1], $f[1]++, $f[2], f[1], f[2] }' foo >foo2 432 echo 111 111 222 2 2 >foo1 433 cmp -s foo1 foo2 || echo 'BAD: T.misc $f[1]++' 434 435 436 # These should be syntax errors 437 $awk . 2>foo 438 grep "syntax error" foo >/dev/null || echo 1>&2 "BAD: T.misc syntax error . fails" 439 440 $awk .. 2>foo 441 grep "syntax error" foo >/dev/null || echo 1>&2 "BAD: T.misc syntax error .. fails" 442 443 $awk .E. 2>foo 444 grep "syntax error" foo >/dev/null || echo 1>&2 "BAD: T.misc syntax error .E. fails" 445 446 $awk .++. 2>foo 447 grep "syntax error" foo >/dev/null || echo 1>&2 "BAD: T.misc syntax error .++. fails" 448 449 450 451 # These should be syntax errors 452 $awk '$' 2>foo 453 grep "unexpected" foo >/dev/null || echo 1>&2 "BAD: T.misc syntax error $ fails" 454 455 $awk '{print $' 2>foo 456 grep "unexpected" foo >/dev/null || echo 1>&2 "BAD: T.misc syntax error $2 fails" 457 458 $awk '"' 2>foo 459 grep "non-terminated" foo >/dev/null || echo 1>&2 "BAD: T.misc bare quote fails" 460 461 462 # %c of 0 is explicit null byte 463 464 ./echo '3' >foo1 465 $awk 'BEGIN {printf("%c%c\n", 0, 0) }' | wc | $awk '{print $3}' >foo2 466 cmp -s foo1 foo2 || echo 'BAD: T.misc null byte' 467 468 # non-terminated RE 469 470 $awk /xyz >foo 2>&1 471 grep "non-terminated" foo >/dev/null || echo 1>&2 "BAD: T.misc non-terminated RE" 472 473 # next several were infinite loops, found by brian tsang. 474 # this is his example: 475 476 $awk 'BEGIN { 477 switch (substr("x",1,1)) { 478 case /ask.com/: 479 break 480 case "google": 481 break 482 } 483 }' >foo 2>&1 484 grep "illegal statement" foo >/dev/null || echo 1>&2 "BAD: T.misc looping syntax error 1" 485 486 $awk 'BEGIN { s { c /./ } }' >foo 2>&1 487 grep "illegal statement" foo >/dev/null || echo 1>&2 "BAD: T.misc looping syntax error 2" 488 489 $awk 'BEGIN { s { c /../ } }' >foo 2>&1 490 grep "illegal statement" foo >/dev/null || echo 1>&2 "BAD: T.misc looping syntax error 3" 491 492 $awk 'BEGIN {printf "%2$s %1$s\n", "a", "b"}' >foo 2>&1 493 grep "'$' not permitted in awk formats" foo >/dev/null || echo 1>&2 "BAD: T.misc '$' not permitted in formats" 494 495 echo 'a 496 b c 497 de fg hi' >foo0 498 $awk 'END { print NF, $0 }' foo0 >foo1 499 awk '{ print NF, $0 }' foo0| tail -1 >foo2 500 cmp -s foo1 foo2 || echo 'BAD: T.misc END must preserve $0' 501 502 echo 'fg hi' >foo0 503 $awk 'END { print NF, $0 }' foo0 >foo1 504 awk '{ print NF, $0 }' foo0| tail -1 >foo2 505 cmp -s foo1 foo2 || echo 'BAD: T.misc END must preserve $0' 506 507 echo '' >foo0 508 $awk 'END { print NF, $0 }' foo0 >foo1 509 awk '{ print NF, $0 }' foo0| tail -1 >foo2 510 cmp -s foo1 foo2 || echo 'BAD: T.misc END must preserve $0' 511 512 # Check for nonzero exit status on I/O error. 513 echo 'E 2' >foo1 514 (trap '' PIPE; "$awk" 'BEGIN { print "hi"; }' 2>/dev/null; echo "E $?" >foo2) | : 515 cmp -s foo1 foo2 || echo 'BAD: T.misc exit status on I/O error' 516 517 # Check for clobbering of the lexer's regular expression buffer. 518 # If the output is "a1" instead of "1b", /b/ clobbered /a/. 519 echo 1b >foo1 520 echo ab | $awk '{ sub(/a/, "b" ~ /b/); print }' >foo2 521 cmp -s foo1 foo2 || echo 'BAD: T.misc lexer regex buffer clobbered' 522 523 # Check handling of octal \OOO and hex \xHH esc. seqs. in strings. 524 echo 'hello888 525 hello 526 hello 527 helloxGOO 528 hello 529 0A' > foo1 530 $awk 'BEGIN { print "hello\888" }' > foo2 531 $awk 'BEGIN { print "hello\x000A" }' >> foo2 532 $awk 'BEGIN { printf "hello\x0A" }' >> foo2 533 $awk 'BEGIN { print "hello\xGOO" }' >> foo2 534 $awk 'BEGIN { print "hello\x0A0A" }' >> foo2 535 cmp -s foo1 foo2 || echo 'BAD: T.misc escape sequences in strings mishandled' 536