From bugzilla at busybox.net Wed Jun 1 21:06:49 2022
From: bugzilla at busybox.net (bugzilla at busybox.net)
Date: Wed, 01 Jun 2022 21:06:49 +0000
Subject: [Bug 14831] New: Segfault by recursively source-ing the same file
Message-ID:
https://bugs.busybox.net/show_bug.cgi?id=14831
Bug ID: 14831
Summary: Segfault by recursively source-ing the same file
Product: Busybox
Version: 1.30.x
Hardware: All
OS: Linux
Status: NEW
Severity: normal
Priority: P5
Component: Other
Assignee: unassigned at busybox.net
Reporter: g at gergelykalman.com
CC: busybox-cvs at busybox.net
Target Milestone: ---
Exact version: v1.30.1 (Debian 1:1.30.1-7+b3)
To reproduce:
$ cat c
source ./c
$ busybox sh c
Segmentation fault
--
You are receiving this mail because:
You are on the CC list for the bug.
From bugzilla at busybox.net Tue Jun 7 18:32:17 2022
From: bugzilla at busybox.net (bugzilla at busybox.net)
Date: Tue, 07 Jun 2022 18:32:17 +0000
Subject: [Bug 14781] A use-after-free in Busybox's awk applet leads to denial
of service and possibly code execution when processing a crafted awk
pattern in the copyvar function
In-Reply-To:
References:
Message-ID:
https://bugs.busybox.net/show_bug.cgi?id=14781
--- Comment #2 from Natanael Copa ---
I'm trying to reproduce this here. What is the content of `1.txt`?
--
You are receiving this mail because:
You are on the CC list for the bug.
From bugzilla at busybox.net Tue Jun 7 18:40:38 2022
From: bugzilla at busybox.net (bugzilla at busybox.net)
Date: Tue, 07 Jun 2022 18:40:38 +0000
Subject: [Bug 14781] A use-after-free in Busybox's awk applet leads to denial
of service and possibly code execution when processing a crafted awk
pattern in the copyvar function
In-Reply-To:
References:
Message-ID:
https://bugs.busybox.net/show_bug.cgi?id=14781
--- Comment #3 from Natanael Copa ---
It does not crash here but valgrind detects it and various other use after
free:
$ echo foo | valgrind ./busybox_unstripped awk '$3i$3in$9=$r||$9=i6/6-9f'
==3430== Memcheck, a memory error detector
==3430== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==3430== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
==3430== Command: ./busybox_unstripped awk $3i$3in$9=$r||$9=i6/6-9f
==3430==
==3430== Invalid read of size 4
==3430== at 0x195B74: copyvar (awk.c:1064)
==3430== by 0x196ED1: evaluate (awk.c:3141)
==3430== by 0x1983EB: ptest (awk.c:2227)
==3430== by 0x196A25: evaluate (awk.c:2951)
==3430== by 0x19885A: awk_main (awk.c:3713)
==3430== by 0x11600D: run_applet_no_and_exit (appletlib.c:967)
==3430== by 0x116331: run_applet_and_exit (appletlib.c:986)
==3430== by 0x116314: busybox_main (appletlib.c:917)
==3430== by 0x116314: run_applet_and_exit (appletlib.c:979)
==3430== by 0x1163AA: main (appletlib.c:1126)
==3430== Address 0x48b7510 is 0 bytes inside a block of size 64 free'd
==3430== at 0x48A4B0D: free (in
/usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==3430== by 0x1974EA: evaluate (awk.c:3537)
==3430== by 0x19698C: evaluate (awk.c:2923)
==3430== by 0x1983EB: ptest (awk.c:2227)
==3430== by 0x196A25: evaluate (awk.c:2951)
==3430== by 0x19885A: awk_main (awk.c:3713)
==3430== by 0x11600D: run_applet_no_and_exit (appletlib.c:967)
==3430== by 0x116331: run_applet_and_exit (appletlib.c:986)
==3430== by 0x116314: busybox_main (appletlib.c:917)
==3430== by 0x116314: run_applet_and_exit (appletlib.c:979)
==3430== by 0x1163AA: main (appletlib.c:1126)
==3430== Block was alloc'd at
==3430== at 0x48A26D5: malloc (in
/usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==3430== by 0x117287: xmalloc (xfuncs_printf.c:50)
==3430== by 0x1172BC: xzalloc (xfuncs_printf.c:71)
==3430== by 0x1968F6: nvalloc (awk.c:1825)
==3430== by 0x1968F6: evaluate (awk.c:2877)
==3430== by 0x19698C: evaluate (awk.c:2923)
==3430== by 0x1983EB: ptest (awk.c:2227)
==3430== by 0x196A25: evaluate (awk.c:2951)
==3430== by 0x19885A: awk_main (awk.c:3713)
==3430== by 0x11600D: run_applet_no_and_exit (appletlib.c:967)
==3430== by 0x116331: run_applet_and_exit (appletlib.c:986)
==3430== by 0x116314: busybox_main (appletlib.c:917)
==3430== by 0x116314: run_applet_and_exit (appletlib.c:979)
==3430== by 0x1163AA: main (appletlib.c:1126)
==3430==
==3430== Invalid read of size 8
==3430== at 0x195B76: copyvar (awk.c:1066)
==3430== by 0x196ED1: evaluate (awk.c:3141)
==3430== by 0x1983EB: ptest (awk.c:2227)
==3430== by 0x196A25: evaluate (awk.c:2951)
==3430== by 0x19885A: awk_main (awk.c:3713)
==3430== by 0x11600D: run_applet_no_and_exit (appletlib.c:967)
==3430== by 0x116331: run_applet_and_exit (appletlib.c:986)
==3430== by 0x116314: busybox_main (appletlib.c:917)
==3430== by 0x116314: run_applet_and_exit (appletlib.c:979)
==3430== by 0x1163AA: main (appletlib.c:1126)
==3430== Address 0x48b7520 is 16 bytes inside a block of size 64 free'd
==3430== at 0x48A4B0D: free (in
/usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==3430== by 0x1974EA: evaluate (awk.c:3537)
==3430== by 0x19698C: evaluate (awk.c:2923)
==3430== by 0x1983EB: ptest (awk.c:2227)
==3430== by 0x196A25: evaluate (awk.c:2951)
==3430== by 0x19885A: awk_main (awk.c:3713)
==3430== by 0x11600D: run_applet_no_and_exit (appletlib.c:967)
==3430== by 0x116331: run_applet_and_exit (appletlib.c:986)
==3430== by 0x116314: busybox_main (appletlib.c:917)
==3430== by 0x116314: run_applet_and_exit (appletlib.c:979)
==3430== by 0x1163AA: main (appletlib.c:1126)
==3430== Block was alloc'd at
==3430== at 0x48A26D5: malloc (in
/usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==3430== by 0x117287: xmalloc (xfuncs_printf.c:50)
==3430== by 0x1172BC: xzalloc (xfuncs_printf.c:71)
==3430== by 0x1968F6: nvalloc (awk.c:1825)
==3430== by 0x1968F6: evaluate (awk.c:2877)
==3430== by 0x19698C: evaluate (awk.c:2923)
==3430== by 0x1983EB: ptest (awk.c:2227)
==3430== by 0x196A25: evaluate (awk.c:2951)
==3430== by 0x19885A: awk_main (awk.c:3713)
==3430== by 0x11600D: run_applet_no_and_exit (appletlib.c:967)
==3430== by 0x116331: run_applet_and_exit (appletlib.c:986)
==3430== by 0x116314: busybox_main (appletlib.c:917)
==3430== by 0x116314: run_applet_and_exit (appletlib.c:979)
==3430== by 0x1163AA: main (appletlib.c:1126)
==3430==
==3430== Invalid read of size 8
==3430== at 0x195B7B: copyvar (awk.c:1067)
==3430== by 0x196ED1: evaluate (awk.c:3141)
==3430== by 0x1983EB: ptest (awk.c:2227)
==3430== by 0x196A25: evaluate (awk.c:2951)
==3430== by 0x19885A: awk_main (awk.c:3713)
==3430== by 0x11600D: run_applet_no_and_exit (appletlib.c:967)
==3430== by 0x116331: run_applet_and_exit (appletlib.c:986)
==3430== by 0x116314: busybox_main (appletlib.c:917)
==3430== by 0x116314: run_applet_and_exit (appletlib.c:979)
==3430== by 0x1163AA: main (appletlib.c:1126)
==3430== Address 0x48b7518 is 8 bytes inside a block of size 64 free'd
==3430== at 0x48A4B0D: free (in
/usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==3430== by 0x1974EA: evaluate (awk.c:3537)
==3430== by 0x19698C: evaluate (awk.c:2923)
==3430== by 0x1983EB: ptest (awk.c:2227)
==3430== by 0x196A25: evaluate (awk.c:2951)
==3430== by 0x19885A: awk_main (awk.c:3713)
==3430== by 0x11600D: run_applet_no_and_exit (appletlib.c:967)
==3430== by 0x116331: run_applet_and_exit (appletlib.c:986)
==3430== by 0x116314: busybox_main (appletlib.c:917)
==3430== by 0x116314: run_applet_and_exit (appletlib.c:979)
==3430== by 0x1163AA: main (appletlib.c:1126)
==3430== Block was alloc'd at
==3430== at 0x48A26D5: malloc (in
/usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==3430== by 0x117287: xmalloc (xfuncs_printf.c:50)
==3430== by 0x1172BC: xzalloc (xfuncs_printf.c:71)
==3430== by 0x1968F6: nvalloc (awk.c:1825)
==3430== by 0x1968F6: evaluate (awk.c:2877)
==3430== by 0x19698C: evaluate (awk.c:2923)
==3430== by 0x1983EB: ptest (awk.c:2227)
==3430== by 0x196A25: evaluate (awk.c:2951)
==3430== by 0x19885A: awk_main (awk.c:3713)
==3430== by 0x11600D: run_applet_no_and_exit (appletlib.c:967)
==3430== by 0x116331: run_applet_and_exit (appletlib.c:986)
==3430== by 0x116314: busybox_main (appletlib.c:917)
==3430== by 0x116314: run_applet_and_exit (appletlib.c:979)
==3430== by 0x1163AA: main (appletlib.c:1126)
==3430==
==3430== Invalid read of size 4
==3430== at 0x1947E6: getvar_i (awk.c:1023)
==3430== by 0x194869: is_numeric (awk.c:1082)
==3430== by 0x194869: istrue (awk.c:1089)
==3430== by 0x196A25: evaluate (awk.c:2951)
==3430== by 0x19885A: awk_main (awk.c:3713)
==3430== by 0x11600D: run_applet_no_and_exit (appletlib.c:967)
==3430== by 0x116331: run_applet_and_exit (appletlib.c:986)
==3430== by 0x116314: busybox_main (appletlib.c:917)
==3430== by 0x116314: run_applet_and_exit (appletlib.c:979)
==3430== by 0x1163AA: main (appletlib.c:1126)
==3430== Address 0x48b6c10 is 0 bytes inside a block of size 64 free'd
==3430== at 0x48A4B0D: free (in
/usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==3430== by 0x1974EA: evaluate (awk.c:3537)
==3430== by 0x1983EB: ptest (awk.c:2227)
==3430== by 0x196A25: evaluate (awk.c:2951)
==3430== by 0x19885A: awk_main (awk.c:3713)
==3430== by 0x11600D: run_applet_no_and_exit (appletlib.c:967)
==3430== by 0x116331: run_applet_and_exit (appletlib.c:986)
==3430== by 0x116314: busybox_main (appletlib.c:917)
==3430== by 0x116314: run_applet_and_exit (appletlib.c:979)
==3430== by 0x1163AA: main (appletlib.c:1126)
==3430== Block was alloc'd at
==3430== at 0x48A26D5: malloc (in
/usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==3430== by 0x117287: xmalloc (xfuncs_printf.c:50)
==3430== by 0x1172BC: xzalloc (xfuncs_printf.c:71)
==3430== by 0x1968F6: nvalloc (awk.c:1825)
==3430== by 0x1968F6: evaluate (awk.c:2877)
==3430== by 0x1983EB: ptest (awk.c:2227)
==3430== by 0x196A25: evaluate (awk.c:2951)
==3430== by 0x19885A: awk_main (awk.c:3713)
==3430== by 0x11600D: run_applet_no_and_exit (appletlib.c:967)
==3430== by 0x116331: run_applet_and_exit (appletlib.c:986)
==3430== by 0x116314: busybox_main (appletlib.c:917)
==3430== by 0x116314: run_applet_and_exit (appletlib.c:979)
==3430== by 0x1163AA: main (appletlib.c:1126)
==3430==
==3430== Invalid write of size 8
==3430== at 0x1947EF: getvar_i (awk.c:1024)
==3430== by 0x194869: is_numeric (awk.c:1082)
==3430== by 0x194869: istrue (awk.c:1089)
==3430== by 0x196A25: evaluate (awk.c:2951)
==3430== by 0x19885A: awk_main (awk.c:3713)
==3430== by 0x11600D: run_applet_no_and_exit (appletlib.c:967)
==3430== by 0x116331: run_applet_and_exit (appletlib.c:986)
==3430== by 0x116314: busybox_main (appletlib.c:917)
==3430== by 0x116314: run_applet_and_exit (appletlib.c:979)
==3430== by 0x1163AA: main (appletlib.c:1126)
==3430== Address 0x48b6c20 is 16 bytes inside a block of size 64 free'd
==3430== at 0x48A4B0D: free (in
/usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==3430== by 0x1974EA: evaluate (awk.c:3537)
==3430== by 0x1983EB: ptest (awk.c:2227)
==3430== by 0x196A25: evaluate (awk.c:2951)
==3430== by 0x19885A: awk_main (awk.c:3713)
==3430== by 0x11600D: run_applet_no_and_exit (appletlib.c:967)
==3430== by 0x116331: run_applet_and_exit (appletlib.c:986)
==3430== by 0x116314: busybox_main (appletlib.c:917)
==3430== by 0x116314: run_applet_and_exit (appletlib.c:979)
==3430== by 0x1163AA: main (appletlib.c:1126)
==3430== Block was alloc'd at
==3430== at 0x48A26D5: malloc (in
/usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==3430== by 0x117287: xmalloc (xfuncs_printf.c:50)
==3430== by 0x1172BC: xzalloc (xfuncs_printf.c:71)
==3430== by 0x1968F6: nvalloc (awk.c:1825)
==3430== by 0x1968F6: evaluate (awk.c:2877)
==3430== by 0x1983EB: ptest (awk.c:2227)
==3430== by 0x196A25: evaluate (awk.c:2951)
==3430== by 0x19885A: awk_main (awk.c:3713)
==3430== by 0x11600D: run_applet_no_and_exit (appletlib.c:967)
==3430== by 0x116331: run_applet_and_exit (appletlib.c:986)
==3430== by 0x116314: busybox_main (appletlib.c:917)
==3430== by 0x116314: run_applet_and_exit (appletlib.c:979)
==3430== by 0x1163AA: main (appletlib.c:1126)
==3430==
==3430== Invalid read of size 8
==3430== at 0x1947F7: getvar_i (awk.c:1025)
==3430== by 0x194869: is_numeric (awk.c:1082)
==3430== by 0x194869: istrue (awk.c:1089)
==3430== by 0x196A25: evaluate (awk.c:2951)
==3430== by 0x19885A: awk_main (awk.c:3713)
==3430== by 0x11600D: run_applet_no_and_exit (appletlib.c:967)
==3430== by 0x116331: run_applet_and_exit (appletlib.c:986)
==3430== by 0x116314: busybox_main (appletlib.c:917)
==3430== by 0x116314: run_applet_and_exit (appletlib.c:979)
==3430== by 0x1163AA: main (appletlib.c:1126)
==3430== Address 0x48b6c18 is 8 bytes inside a block of size 64 free'd
==3430== at 0x48A4B0D: free (in
/usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==3430== by 0x1974EA: evaluate (awk.c:3537)
==3430== by 0x1983EB: ptest (awk.c:2227)
==3430== by 0x196A25: evaluate (awk.c:2951)
==3430== by 0x19885A: awk_main (awk.c:3713)
==3430== by 0x11600D: run_applet_no_and_exit (appletlib.c:967)
==3430== by 0x116331: run_applet_and_exit (appletlib.c:986)
==3430== by 0x116314: busybox_main (appletlib.c:917)
==3430== by 0x116314: run_applet_and_exit (appletlib.c:979)
==3430== by 0x1163AA: main (appletlib.c:1126)
==3430== Block was alloc'd at
==3430== at 0x48A26D5: malloc (in
/usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==3430== by 0x117287: xmalloc (xfuncs_printf.c:50)
==3430== by 0x1172BC: xzalloc (xfuncs_printf.c:71)
==3430== by 0x1968F6: nvalloc (awk.c:1825)
==3430== by 0x1968F6: evaluate (awk.c:2877)
==3430== by 0x1983EB: ptest (awk.c:2227)
==3430== by 0x196A25: evaluate (awk.c:2951)
==3430== by 0x19885A: awk_main (awk.c:3713)
==3430== by 0x11600D: run_applet_no_and_exit (appletlib.c:967)
==3430== by 0x116331: run_applet_and_exit (appletlib.c:986)
==3430== by 0x116314: busybox_main (appletlib.c:917)
==3430== by 0x116314: run_applet_and_exit (appletlib.c:979)
==3430== by 0x1163AA: main (appletlib.c:1126)
==3430==
==3430== Invalid write of size 4
==3430== at 0x194839: getvar_i (awk.c:1039)
==3430== by 0x194869: is_numeric (awk.c:1082)
==3430== by 0x194869: istrue (awk.c:1089)
==3430== by 0x196A25: evaluate (awk.c:2951)
==3430== by 0x19885A: awk_main (awk.c:3713)
==3430== by 0x11600D: run_applet_no_and_exit (appletlib.c:967)
==3430== by 0x116331: run_applet_and_exit (appletlib.c:986)
==3430== by 0x116314: busybox_main (appletlib.c:917)
==3430== by 0x116314: run_applet_and_exit (appletlib.c:979)
==3430== by 0x1163AA: main (appletlib.c:1126)
==3430== Address 0x48b6c10 is 0 bytes inside a block of size 64 free'd
==3430== at 0x48A4B0D: free (in
/usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==3430== by 0x1974EA: evaluate (awk.c:3537)
==3430== by 0x1983EB: ptest (awk.c:2227)
==3430== by 0x196A25: evaluate (awk.c:2951)
==3430== by 0x19885A: awk_main (awk.c:3713)
==3430== by 0x11600D: run_applet_no_and_exit (appletlib.c:967)
==3430== by 0x116331: run_applet_and_exit (appletlib.c:986)
==3430== by 0x116314: busybox_main (appletlib.c:917)
==3430== by 0x116314: run_applet_and_exit (appletlib.c:979)
==3430== by 0x1163AA: main (appletlib.c:1126)
==3430== Block was alloc'd at
==3430== at 0x48A26D5: malloc (in
/usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==3430== by 0x117287: xmalloc (xfuncs_printf.c:50)
==3430== by 0x1172BC: xzalloc (xfuncs_printf.c:71)
==3430== by 0x1968F6: nvalloc (awk.c:1825)
==3430== by 0x1968F6: evaluate (awk.c:2877)
==3430== by 0x1983EB: ptest (awk.c:2227)
==3430== by 0x196A25: evaluate (awk.c:2951)
==3430== by 0x19885A: awk_main (awk.c:3713)
==3430== by 0x11600D: run_applet_no_and_exit (appletlib.c:967)
==3430== by 0x116331: run_applet_and_exit (appletlib.c:986)
==3430== by 0x116314: busybox_main (appletlib.c:917)
==3430== by 0x116314: run_applet_and_exit (appletlib.c:979)
==3430== by 0x1163AA: main (appletlib.c:1126)
==3430==
==3430== Invalid read of size 4
==3430== at 0x19483B: getvar_i (awk.c:1041)
==3430== by 0x194869: is_numeric (awk.c:1082)
==3430== by 0x194869: istrue (awk.c:1089)
==3430== by 0x196A25: evaluate (awk.c:2951)
==3430== by 0x19885A: awk_main (awk.c:3713)
==3430== by 0x11600D: run_applet_no_and_exit (appletlib.c:967)
==3430== by 0x116331: run_applet_and_exit (appletlib.c:986)
==3430== by 0x116314: busybox_main (appletlib.c:917)
==3430== by 0x116314: run_applet_and_exit (appletlib.c:979)
==3430== by 0x1163AA: main (appletlib.c:1126)
==3430== Address 0x48b6c10 is 0 bytes inside a block of size 64 free'd
==3430== at 0x48A4B0D: free (in
/usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==3430== by 0x1974EA: evaluate (awk.c:3537)
==3430== by 0x1983EB: ptest (awk.c:2227)
==3430== by 0x196A25: evaluate (awk.c:2951)
==3430== by 0x19885A: awk_main (awk.c:3713)
==3430== by 0x11600D: run_applet_no_and_exit (appletlib.c:967)
==3430== by 0x116331: run_applet_and_exit (appletlib.c:986)
==3430== by 0x116314: busybox_main (appletlib.c:917)
==3430== by 0x116314: run_applet_and_exit (appletlib.c:979)
==3430== by 0x1163AA: main (appletlib.c:1126)
==3430== Block was alloc'd at
==3430== at 0x48A26D5: malloc (in
/usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==3430== by 0x117287: xmalloc (xfuncs_printf.c:50)
==3430== by 0x1172BC: xzalloc (xfuncs_printf.c:71)
==3430== by 0x1968F6: nvalloc (awk.c:1825)
==3430== by 0x1968F6: evaluate (awk.c:2877)
==3430== by 0x1983EB: ptest (awk.c:2227)
==3430== by 0x196A25: evaluate (awk.c:2951)
==3430== by 0x19885A: awk_main (awk.c:3713)
==3430== by 0x11600D: run_applet_no_and_exit (appletlib.c:967)
==3430== by 0x116331: run_applet_and_exit (appletlib.c:986)
==3430== by 0x116314: busybox_main (appletlib.c:917)
==3430== by 0x116314: run_applet_and_exit (appletlib.c:979)
==3430== by 0x1163AA: main (appletlib.c:1126)
==3430==
==3430== Invalid read of size 8
==3430== at 0x194841: getvar_i (awk.c:1044)
==3430== by 0x194869: is_numeric (awk.c:1082)
==3430== by 0x194869: istrue (awk.c:1089)
==3430== by 0x196A25: evaluate (awk.c:2951)
==3430== by 0x19885A: awk_main (awk.c:3713)
==3430== by 0x11600D: run_applet_no_and_exit (appletlib.c:967)
==3430== by 0x116331: run_applet_and_exit (appletlib.c:986)
==3430== by 0x116314: busybox_main (appletlib.c:917)
==3430== by 0x116314: run_applet_and_exit (appletlib.c:979)
==3430== by 0x1163AA: main (appletlib.c:1126)
==3430== Address 0x48b6c20 is 16 bytes inside a block of size 64 free'd
==3430== at 0x48A4B0D: free (in
/usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==3430== by 0x1974EA: evaluate (awk.c:3537)
==3430== by 0x1983EB: ptest (awk.c:2227)
==3430== by 0x196A25: evaluate (awk.c:2951)
==3430== by 0x19885A: awk_main (awk.c:3713)
==3430== by 0x11600D: run_applet_no_and_exit (appletlib.c:967)
==3430== by 0x116331: run_applet_and_exit (appletlib.c:986)
==3430== by 0x116314: busybox_main (appletlib.c:917)
==3430== by 0x116314: run_applet_and_exit (appletlib.c:979)
==3430== by 0x1163AA: main (appletlib.c:1126)
==3430== Block was alloc'd at
==3430== at 0x48A26D5: malloc (in
/usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==3430== by 0x117287: xmalloc (xfuncs_printf.c:50)
==3430== by 0x1172BC: xzalloc (xfuncs_printf.c:71)
==3430== by 0x1968F6: nvalloc (awk.c:1825)
==3430== by 0x1968F6: evaluate (awk.c:2877)
==3430== by 0x1983EB: ptest (awk.c:2227)
==3430== by 0x196A25: evaluate (awk.c:2951)
==3430== by 0x19885A: awk_main (awk.c:3713)
==3430== by 0x11600D: run_applet_no_and_exit (appletlib.c:967)
==3430== by 0x116331: run_applet_and_exit (appletlib.c:986)
==3430== by 0x116314: busybox_main (appletlib.c:917)
==3430== by 0x116314: run_applet_and_exit (appletlib.c:979)
==3430== by 0x1163AA: main (appletlib.c:1126)
==3430==
==3430== Invalid read of size 4
==3430== at 0x19486A: is_numeric (awk.c:1083)
==3430== by 0x19486A: istrue (awk.c:1089)
==3430== by 0x196A25: evaluate (awk.c:2951)
==3430== by 0x19885A: awk_main (awk.c:3713)
==3430== by 0x11600D: run_applet_no_and_exit (appletlib.c:967)
==3430== by 0x116331: run_applet_and_exit (appletlib.c:986)
==3430== by 0x116314: busybox_main (appletlib.c:917)
==3430== by 0x116314: run_applet_and_exit (appletlib.c:979)
==3430== by 0x1163AA: main (appletlib.c:1126)
==3430== Address 0x48b6c10 is 0 bytes inside a block of size 64 free'd
==3430== at 0x48A4B0D: free (in
/usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==3430== by 0x1974EA: evaluate (awk.c:3537)
==3430== by 0x1983EB: ptest (awk.c:2227)
==3430== by 0x196A25: evaluate (awk.c:2951)
==3430== by 0x19885A: awk_main (awk.c:3713)
==3430== by 0x11600D: run_applet_no_and_exit (appletlib.c:967)
==3430== by 0x116331: run_applet_and_exit (appletlib.c:986)
==3430== by 0x116314: busybox_main (appletlib.c:917)
==3430== by 0x116314: run_applet_and_exit (appletlib.c:979)
==3430== by 0x1163AA: main (appletlib.c:1126)
==3430== Block was alloc'd at
==3430== at 0x48A26D5: malloc (in
/usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==3430== by 0x117287: xmalloc (xfuncs_printf.c:50)
==3430== by 0x1172BC: xzalloc (xfuncs_printf.c:71)
==3430== by 0x1968F6: nvalloc (awk.c:1825)
==3430== by 0x1968F6: evaluate (awk.c:2877)
==3430== by 0x1983EB: ptest (awk.c:2227)
==3430== by 0x196A25: evaluate (awk.c:2951)
==3430== by 0x19885A: awk_main (awk.c:3713)
==3430== by 0x11600D: run_applet_no_and_exit (appletlib.c:967)
==3430== by 0x116331: run_applet_and_exit (appletlib.c:986)
==3430== by 0x116314: busybox_main (appletlib.c:917)
==3430== by 0x116314: run_applet_and_exit (appletlib.c:979)
==3430== by 0x1163AA: main (appletlib.c:1126)
==3430==
==3430== Invalid read of size 8
==3430== at 0x19488D: istrue (awk.c:1091)
==3430== by 0x196A25: evaluate (awk.c:2951)
==3430== by 0x19885A: awk_main (awk.c:3713)
==3430== by 0x11600D: run_applet_no_and_exit (appletlib.c:967)
==3430== by 0x116331: run_applet_and_exit (appletlib.c:986)
==3430== by 0x116314: busybox_main (appletlib.c:917)
==3430== by 0x116314: run_applet_and_exit (appletlib.c:979)
==3430== by 0x1163AA: main (appletlib.c:1126)
==3430== Address 0x48b6c18 is 8 bytes inside a block of size 64 free'd
==3430== at 0x48A4B0D: free (in
/usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==3430== by 0x1974EA: evaluate (awk.c:3537)
==3430== by 0x1983EB: ptest (awk.c:2227)
==3430== by 0x196A25: evaluate (awk.c:2951)
==3430== by 0x19885A: awk_main (awk.c:3713)
==3430== by 0x11600D: run_applet_no_and_exit (appletlib.c:967)
==3430== by 0x116331: run_applet_and_exit (appletlib.c:986)
==3430== by 0x116314: busybox_main (appletlib.c:917)
==3430== by 0x116314: run_applet_and_exit (appletlib.c:979)
==3430== by 0x1163AA: main (appletlib.c:1126)
==3430== Block was alloc'd at
==3430== at 0x48A26D5: malloc (in
/usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==3430== by 0x117287: xmalloc (xfuncs_printf.c:50)
==3430== by 0x1172BC: xzalloc (xfuncs_printf.c:71)
==3430== by 0x1968F6: nvalloc (awk.c:1825)
==3430== by 0x1968F6: evaluate (awk.c:2877)
==3430== by 0x1983EB: ptest (awk.c:2227)
==3430== by 0x196A25: evaluate (awk.c:2951)
==3430== by 0x19885A: awk_main (awk.c:3713)
==3430== by 0x11600D: run_applet_no_and_exit (appletlib.c:967)
==3430== by 0x116331: run_applet_and_exit (appletlib.c:986)
==3430== by 0x116314: busybox_main (appletlib.c:917)
==3430== by 0x116314: run_applet_and_exit (appletlib.c:979)
==3430== by 0x1163AA: main (appletlib.c:1126)
==3430==
==3430==
==3430== HEAP SUMMARY:
==3430== in use at exit: 11,033 bytes in 174 blocks
==3430== total heap usage: 204 allocs, 30 frees, 13,028 bytes allocated
==3430==
==3430== LEAK SUMMARY:
==3430== definitely lost: 0 bytes in 0 blocks
==3430== indirectly lost: 0 bytes in 0 blocks
==3430== possibly lost: 11,033 bytes in 174 blocks
==3430== still reachable: 0 bytes in 0 blocks
==3430== suppressed: 0 bytes in 0 blocks
==3430== Rerun with --leak-check=full to see details of leaked memory
==3430==
==3430== For lists of detected and suppressed errors, rerun with: -s
==3430== ERROR SUMMARY: 12 errors from 11 contexts (suppressed: 0 from 0)
--
You are receiving this mail because:
You are on the CC list for the bug.
From bugzilla at busybox.net Tue Jun 7 18:49:18 2022
From: bugzilla at busybox.net (bugzilla at busybox.net)
Date: Tue, 07 Jun 2022 18:49:18 +0000
Subject: [Bug 14781] A use-after-free in Busybox's awk applet leads to denial
of service and possibly code execution when processing a crafted awk
pattern in the copyvar function
In-Reply-To:
References:
Message-ID:
https://bugs.busybox.net/show_bug.cgi?id=14781
--- Comment #4 from Natanael Copa ---
simpler way to reproduce it:
echo "foo" | valgrind ./busybox_unstripped awk '$1$1=0'
--
You are receiving this mail because:
You are on the CC list for the bug.
From bugzilla at busybox.net Tue Jun 7 19:14:25 2022
From: bugzilla at busybox.net (bugzilla at busybox.net)
Date: Tue, 07 Jun 2022 19:14:25 +0000
Subject: [Bug 14781] A use-after-free in Busybox's awk applet leads to denial
of service and possibly code execution when processing a crafted awk
pattern in the copyvar function
In-Reply-To:
References:
Message-ID:
https://bugs.busybox.net/show_bug.cgi?id=14781
--- Comment #5 from Natanael Copa ---
This change makes it segfault early:
$ git diff
diff --git a/editors/awk.c b/editors/awk.c
index 079d0bde5..840f2595f 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -55,7 +55,7 @@
/* If you comment out one of these below, it will be #defined later
* to perform debug printfs to stderr: */
#define debug_printf_walker(...) do {} while (0)
-#define debug_printf_eval(...) do {} while (0)
+//#define debug_printf_eval(...) do {} while (0)
#define debug_printf_parse(...) do {} while (0)
#ifndef debug_printf_walker
@@ -2922,7 +2922,7 @@ static var *evaluate(node *op, var *res)
if (opinfo & OF_RES2) {
R.v = evaluate(op->r.n, TMPVAR1);
//TODO: L.v may be invalid now, set L.v to NULL to
catch bugs?
- //L.v = NULL;
+ L.v = NULL;
if (opinfo & OF_STR2) {
R.s = getvar_s(R.v);
debug_printf_eval("R.s:'%s'\n", R.s);
$ echo "foo" | ./busybox_unstripped awk '$1$1=0'
fsrealloc: xrealloc(0, 512)
fsrealloc: Fields=0x7f6dbda05030..0x7f6dbda0522f
getvar_i: 0.000000
getvar_i: 1.000000
entered awk_getline()
returning from awk_getline(): 1
getvar_i: 0.000000
getvar_i: 0.000000
entered evaluate()
opinfo:00000300 opn:00000000
switch(0x3)
NEWSOURCE
opinfo:00000d00 opn:00000000
switch(0xd)
TEST
entered evaluate()
opinfo:4a031f00 opn:00000000
entered evaluate()
opinfo:230f1500 opn:00000000
entered evaluate()
opinfo:05021700 opn:00000000
entered evaluate()
opinfo:00002700 opn:00000000
switch(0x27)
VAR
returning from evaluate(): 0x7f6dbda03410
switch(0x17)
FIELD
getvar_i: 1.000000
returning from evaluate(): 0x7f6dbda05030
L.s:'foo'
entered evaluate()
opinfo:05021700 opn:00000000
entered evaluate()
opinfo:00002700 opn:00000000
switch(0x27)
VAR
returning from evaluate(): 0x7f6dbda034d0
switch(0x17)
FIELD
getvar_i: 1.000000
returning from evaluate(): 0x7f6dbda05030
R.s:'foo'
switch(0x15)
CONCAT /
COMMA
returning from evaluate(): 0x7f6dbda04bb0
entered evaluate()
opinfo:00002700 opn:00000000
switch(0x27)
VAR
returning from evaluate(): 0x7f6dbda03560
switch(0x1f)
MOVE
Segmentation fault
--
You are receiving this mail because:
You are on the CC list for the bug.
From bugzilla at busybox.net Tue Jun 7 19:31:09 2022
From: bugzilla at busybox.net (bugzilla at busybox.net)
Date: Tue, 07 Jun 2022 19:31:09 +0000
Subject: [Bug 14781] A use-after-free in Busybox's awk applet leads to denial
of service and possibly code execution when processing a crafted awk
pattern in the copyvar function
In-Reply-To:
References:
Message-ID:
https://bugs.busybox.net/show_bug.cgi?id=14781
--- Comment #6 from Natanael Copa ---
Possible fix:
diff --git a/editors/awk.c b/editors/awk.c
index 079d0bde5..d68b8d4bc 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -2922,7 +2922,7 @@ static var *evaluate(node *op, var *res)
if (opinfo & OF_RES2) {
R.v = evaluate(op->r.n, TMPVAR1);
//TODO: L.v may be invalid now, set L.v to NULL to
catch bugs?
- //L.v = NULL;
+ L.v = NULL;
if (opinfo & OF_STR2) {
R.s = getvar_s(R.v);
debug_printf_eval("R.s:'%s'\n", R.s);
@@ -3128,6 +3128,8 @@ static var *evaluate(node *op, var *res)
case XC( OC_MOVE ):
debug_printf_eval("MOVE\n");
+ if (L.v == NULL)
+ syntax_error(EMSG_POSSIBLE_ERROR);
/* if source is a temporary string, jusk relink it to
dest */
if (R.v == TMPVAR1
&& !(R.v->type & VF_NUMBER)
--
You are receiving this mail because:
You are on the CC list for the bug.
From bugzilla at busybox.net Fri Jun 10 02:05:26 2022
From: bugzilla at busybox.net (bugzilla at busybox.net)
Date: Fri, 10 Jun 2022 02:05:26 +0000
Subject: [Bug 11506] Out of bounds read in udhcp_get_option()
In-Reply-To:
References:
Message-ID:
https://bugs.busybox.net/show_bug.cgi?id=11506
--- Comment #6 from ??? <982326510 at qq.com> ---
Comment on attachment 7881
--> https://bugs.busybox.net/attachment.cgi?id=7881
Corrupt dhcpdiscover message which triggers the out of bounds read
?
--
You are receiving this mail because:
You are on the CC list for the bug.
From bugzilla at busybox.net Wed Jun 15 08:19:49 2022
From: bugzilla at busybox.net (bugzilla at busybox.net)
Date: Wed, 15 Jun 2022 08:19:49 +0000
Subject: [Bug 14846] New: quoting causes only first lib in
CONFIG_EXTRA_LDLIBS to be taken
Message-ID:
https://bugs.busybox.net/show_bug.cgi?id=14846
Bug ID: 14846
Summary: quoting causes only first lib in CONFIG_EXTRA_LDLIBS
to be taken
Product: Busybox
Version: 1.35.x
Hardware: All
OS: Linux
Status: NEW
Severity: normal
Priority: P5
Component: Other
Assignee: unassigned at busybox.net
Reporter: arekm at maven.pl
CC: busybox-cvs at busybox.net
Target Milestone: ---
Commit
commit 1f9ed02caffb269e5fc6fbdf19fc9ba05a79e628
Author: Denys Vlasenko
Date: Tue Feb 23 23:09:49 2021 +0100
trylink: do not drop libs from CONFIG_EXTRA_LDLIBS
removed (by not putting it in new place)
-ifneq ($(CONFIG_EXTRA_LDLIBS),)
-LDLIBS += $(strip $(subst ",,$(CONFIG_EXTRA_LDLIBS)))
-#"))
-endif
which was stripping "" from CONFIG_EXTRA_LDLIBS and now we get this:
.../busybox-1.35.0/scripts/trylink "busybox_unstripped"
"x86_64-pld-linux-gnux32-gcc" "-malign-data=abi ..." " applets/built-in.o" "
archival/lib.a ar ...id/built-in.o" "m crypt rt" ""tirpc pthread gssapi"" &&
/home/users/arekm/rpm/BUILD-x32/busybox-1.35.0/scripts/generate_BUFSIZ.sh
--post include/common_bufsiz.h
note the double quoting of ""tirpc pthread gssapi"". Then script/trylink does:
CONFIG_EXTRA_LDLIBS="$8"
which will be only
+ CONFIG_EXTRA_LDLIBS=tirpc
missing pthread and gssapi.
--
You are receiving this mail because:
You are on the CC list for the bug.
From bugzilla at busybox.net Wed Jun 15 08:21:39 2022
From: bugzilla at busybox.net (bugzilla at busybox.net)
Date: Wed, 15 Jun 2022 08:21:39 +0000
Subject: [Bug 14846] quoting causes only first lib in CONFIG_EXTRA_LDLIBS to
be taken
In-Reply-To:
References:
Message-ID:
https://bugs.busybox.net/show_bug.cgi?id=14846
--- Comment #1 from Arkadiusz Miskiewicz ---
Created attachment 9321
--> https://bugs.busybox.net/attachment.cgi?id=9321&action=edit
fix
--
You are receiving this mail because:
You are on the CC list for the bug.
From bugzilla at busybox.net Fri Jun 17 01:12:49 2022
From: bugzilla at busybox.net (bugzilla at busybox.net)
Date: Fri, 17 Jun 2022 01:12:49 +0000
Subject: [Bug 14851] New: Support pipefail in `sh`
Message-ID:
https://bugs.busybox.net/show_bug.cgi?id=14851
Bug ID: 14851
Summary: Support pipefail in `sh`
Product: Busybox
Version: unspecified
Hardware: All
OS: Linux
Status: NEW
Severity: normal
Priority: P5
Component: Other
Assignee: unassigned at busybox.net
Reporter: tmgross at umich.edu
CC: busybox-cvs at busybox.net
Target Milestone: ---
Hello all,
As I understand, POSIX:2022 will include the option to set -o pipefail. Would
busybox consider adding this to their flavor of `sh`?
The POSIX standard is expected to be released in 2023 I believe. The
in-progress standard is quite difficult to access for those not involved, but
this discussion makes it clear that it should be coming:
https://www.austingroupbugs.net/view.php?id=789. Additionally, St?phane in this
comment states that the resolution was accepted in 2019:
https://unix.stackexchange.com/a/654932/150903
Even outside of the scope of this standard, pipefail is a very useful option
and could be added at any time.
Note: I opened this request at the suggestion of Natanael Copa, based on the
Alpine git issue here: https://github.com/alpinelinux/docker-alpine/issues/258.
Most of the aboce is paraphrased from what I wrote in the comments there.
--
You are receiving this mail because:
You are on the CC list for the bug.
From bugzilla at busybox.net Fri Jun 17 09:49:42 2022
From: bugzilla at busybox.net (bugzilla at busybox.net)
Date: Fri, 17 Jun 2022 09:49:42 +0000
Subject: [Bug 14781] A use-after-free in Busybox's awk applet leads to denial
of service and possibly code execution when processing a crafted awk
pattern in the copyvar function
In-Reply-To:
References:
Message-ID:
https://bugs.busybox.net/show_bug.cgi?id=14781
--- Comment #7 from Natanael Copa ---
(In reply to Natanael Copa from comment #6)
Setting L.v to null does not work. it breaks other stuff.
This might work and ./runtests awk passes:
diff --git a/editors/awk.c b/editors/awk.c
index 079d0bde5..acdc50e32 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -3128,6 +3128,9 @@ static var *evaluate(node *op, var *res)
case XC( OC_MOVE ):
debug_printf_eval("MOVE\n");
+ /* make sure that we never return a temp var */
+ if (L.v == TMPVAR0)
+ L.v = res;
/* if source is a temporary string, jusk relink it to
dest */
if (R.v == TMPVAR1
&& !(R.v->type & VF_NUMBER)
--
You are receiving this mail because:
You are on the CC list for the bug.
From bugzilla at busybox.net Wed Jun 22 11:05:23 2022
From: bugzilla at busybox.net (bugzilla at busybox.net)
Date: Wed, 22 Jun 2022 11:05:23 +0000
Subject: [Bug 14861] New: ln: unrecognized option: t
Message-ID:
https://bugs.busybox.net/show_bug.cgi?id=14861
Bug ID: 14861
Summary: ln: unrecognized option: t
Product: Busybox
Version: 1.35.x
Hardware: All
OS: Linux
Status: NEW
Severity: normal
Priority: P5
Component: Other
Assignee: unassigned at busybox.net
Reporter: spam at ipik.org
CC: busybox-cvs at busybox.net
Target Milestone: ---
There are a few discrepancies between documented usages of -t and -T options
Trivial usage message [1] implies -t exists and says:
//usage: "[-sfnbtv] [-S SUF] TARGET... LINK|DIR"
but opt does not handle it [2]:
opts = getopt32(argv, "^" "sfnbS:vT" "\0" "-1", &suffix);
and web site command help does not list -T (nor -t)[3]:
ln
ln [OPTIONS] TARGET... LINK|DIRECTORY
Create a link LINK or DIRECTORY/TARGET to the specified TARGET(s)
Options:
-s Make symlinks instead of hardlinks
-f Remove existing destination files
-n Don't dereference symlinks - treat like normal file
-b Make a backup of the target (if exists) before link
operation
-S suf Use suffix instead of ~ when making backup files
[1] https://git.busybox.net/busybox/tree/coreutils/ln.c#n24
[2] https://git.busybox.net/busybox/tree/coreutils/ln.c#n64
[3] https://busybox.net/downloads/BusyBox.html
--
You are receiving this mail because:
You are on the CC list for the bug.
From bugzilla at busybox.net Fri Jun 24 20:29:59 2022
From: bugzilla at busybox.net (bugzilla at busybox.net)
Date: Fri, 24 Jun 2022 20:29:59 +0000
Subject: [Bug 14866] New: sha256sum reports false mismatch if input not
delimited by two spaces
Message-ID:
https://bugs.busybox.net/show_bug.cgi?id=14866
Bug ID: 14866
Summary: sha256sum reports false mismatch if input not
delimited by two spaces
Product: Busybox
Version: unspecified
Hardware: All
OS: Linux
Status: NEW
Severity: normal
Priority: P5
Component: Other
Assignee: unassigned at busybox.net
Reporter: rittneje+bugzilla at gmail.com
CC: busybox-cvs at busybox.net
Target Milestone: ---
For some reason, the Alpine version of sha256sum requires two spaces between
the hash and file path. No other version of sha256sum has this requirement.
See https://github.com/alpinelinux/docker-alpine/issues/246 for further
details.
--
You are receiving this mail because:
You are on the CC list for the bug.
From bugzilla at busybox.net Sat Jun 25 14:13:03 2022
From: bugzilla at busybox.net (bugzilla at busybox.net)
Date: Sat, 25 Jun 2022 14:13:03 +0000
Subject: [Bug 14871] New: `sort -s -u -k 2' didn't remove duplicate lines
Message-ID:
https://bugs.busybox.net/show_bug.cgi?id=14871
Bug ID: 14871
Summary: `sort -s -u -k 2' didn't remove duplicate lines
Product: Busybox
Version: unspecified
Hardware: All
OS: Linux
Status: NEW
Severity: normal
Priority: P5
Component: Standard Compliance
Assignee: unassigned at busybox.net
Reporter: zhangboyang.id at gmail.com
CC: busybox-cvs at busybox.net
Target Milestone: ---
Hi,
Please run `LANG=C sort -s -u -k 2' with following input data:
z b
a b
z a
a a
The output of busybox's sort is:
z a
a a
z b
a b
The expected output (from GNU sort) is:
z a
z b
--
You are receiving this mail because:
You are on the CC list for the bug.
From bugzilla at busybox.net Sat Jun 25 14:30:31 2022
From: bugzilla at busybox.net (bugzilla at busybox.net)
Date: Sat, 25 Jun 2022 14:30:31 +0000
Subject: [Bug 14871] sort: `sort -s -u -k 2' didn't remove duplicate lines
In-Reply-To:
References:
Message-ID:
https://bugs.busybox.net/show_bug.cgi?id=14871
Zhang Boyang changed:
What |Removed |Added
----------------------------------------------------------------------------
Summary|`sort -s -u -k 2' didn't |sort: `sort -s -u -k 2'
|remove duplicate lines |didn't remove duplicate
| |lines
--- Comment #1 from Zhang Boyang ---
(In reply to Zhang Boyang from comment #0)
--
You are receiving this mail because:
You are on the CC list for the bug.
From vda.linux at googlemail.com Sun Jun 26 15:17:02 2022
From: vda.linux at googlemail.com (Denys Vlasenko)
Date: Sun, 26 Jun 2022 17:17:02 +0200
Subject: [git commit] libbb: restore special handling of nomsg errors
Message-ID: <20220626150657.BD1FD87527@busybox.osuosl.org>
commit: https://git.busybox.net/busybox/commit/?id=95fec31be601bfdced6bed7007a33b26e968e0db
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master
The functions bb_perror_nomsg() and bb_perror_nomsg_and_die() are
used to print error messages where no specific information is
available. For example:
$ busybox mktemp -p /
mktemp: (null): Permission denied
mktemp(3) doesn't tell us the name of the file it tried to create.
However, printing '(null)' is a regression introduced by commit
6937487be (libbb: reduce the overhead of single parameter bb_error_msg()
calls). Restore the previous behaviour by reverting the changes to
the two functions mentioned:
$ busybox mktemp -p /
mktemp: Permission denied
function old new delta
bb_perror_nomsg_and_die 7 14 +7
bb_perror_nomsg 7 14 +7
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 14/0) Total: 14 bytes
Signed-off-by: Ron Yorston
Signed-off-by: Denys Vlasenko
---
libbb/perror_nomsg.c | 4 ++--
libbb/perror_nomsg_and_die.c | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/libbb/perror_nomsg.c b/libbb/perror_nomsg.c
index d7d53de44..a2a11cc8e 100644
--- a/libbb/perror_nomsg.c
+++ b/libbb/perror_nomsg.c
@@ -12,11 +12,11 @@
* instead of including libbb.h */
//#include "libbb.h"
#include "platform.h"
-extern void bb_simple_perror_msg(const char *s) FAST_FUNC;
+extern void bb_perror_msg(const char *s, ...) FAST_FUNC;
/* suppress gcc "no previous prototype" warning */
void FAST_FUNC bb_perror_nomsg(void);
void FAST_FUNC bb_perror_nomsg(void)
{
- bb_simple_perror_msg(0);
+ bb_perror_msg(0);
}
diff --git a/libbb/perror_nomsg_and_die.c b/libbb/perror_nomsg_and_die.c
index bea5f25a5..543ff5178 100644
--- a/libbb/perror_nomsg_and_die.c
+++ b/libbb/perror_nomsg_and_die.c
@@ -12,11 +12,11 @@
* instead of including libbb.h */
//#include "libbb.h"
#include "platform.h"
-extern void bb_simple_perror_msg_and_die(const char *s) FAST_FUNC;
+extern void bb_perror_msg_and_die(const char *s, ...) FAST_FUNC;
/* suppress gcc "no previous prototype" warning */
void FAST_FUNC bb_perror_nomsg_and_die(void);
void FAST_FUNC bb_perror_nomsg_and_die(void)
{
- bb_simple_perror_msg_and_die(0);
+ bb_perror_msg_and_die(0);
}
From vda.linux at googlemail.com Sun Jun 26 16:05:50 2022
From: vda.linux at googlemail.com (Denys Vlasenko)
Date: Sun, 26 Jun 2022 18:05:50 +0200
Subject: [git commit] ash,hush: use HOME for tab completion and prompts
Message-ID: <20220626155814.B6F768755A@busybox.osuosl.org>
commit: https://git.busybox.net/busybox/commit/?id=7d1c7d8337853ca99e6ec1150ac4b834cfed5cd3
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master
ash and hush correctly use the value of HOME for tilde expansion.
However the line editing code in libbb obtains the user's home
directory by calling getpwuid(). Thus tildes in tab completion
and prompts may be interpreted differently than in tilde expansion.
When the line editing code is invoked from a shell make it use the
shell's interpretation of tilde. This is similar to how GNU readline
and bash collaborate.
function old new delta
get_homedir_or_NULL 29 72 +43
optschanged 119 126 +7
hush_main 1204 1211 +7
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 3/0 up/down: 57/0) Total: 57 bytes
v2: Always check for HOME before trying the password database: this
is what GNU readline does.
Signed-off-by: Ron Yorston
Signed-off-by: Denys Vlasenko
---
include/libbb.h | 11 +++--------
libbb/lineedit.c | 12 +++++++++++-
shell/ash.c | 7 +++----
shell/hush.c | 5 ++---
4 files changed, 19 insertions(+), 16 deletions(-)
diff --git a/include/libbb.h b/include/libbb.h
index 6aeec249d..abbc9ac59 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -1924,6 +1924,7 @@ unsigned size_from_HISTFILESIZE(const char *hp) FAST_FUNC;
# define MAX_HISTORY 0
# endif
typedef const char *get_exe_name_t(int i) FAST_FUNC;
+typedef const char *sh_get_var_t(const char *name) FAST_FUNC;
typedef struct line_input_t {
int flags;
int timeout;
@@ -1937,9 +1938,8 @@ typedef struct line_input_t {
# if ENABLE_SHELL_ASH || ENABLE_SHELL_HUSH
/* function to fetch additional application-specific names to match */
get_exe_name_t *get_exe_name;
-# define EDITING_HAS_get_exe_name 1
-# else
-# define EDITING_HAS_get_exe_name 0
+ /* function to fetch value of shell variable */
+ sh_get_var_t *sh_get_var;
# endif
# endif
# if MAX_HISTORY
@@ -1993,11 +1993,6 @@ int read_line_input(const char* prompt, char* command, int maxsize) FAST_FUNC;
read_line_input(prompt, command, maxsize)
#endif
-#ifndef EDITING_HAS_get_exe_name
-# define EDITING_HAS_get_exe_name 0
-#endif
-
-
#ifndef COMM_LEN
# ifdef TASK_COMM_LEN
enum { COMM_LEN = TASK_COMM_LEN };
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 82624757e..b685399f9 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -259,6 +259,16 @@ static const char *get_username_str(void)
static NOINLINE const char *get_homedir_or_NULL(void)
{
+ const char *home;
+
+# if ENABLE_SHELL_ASH || ENABLE_SHELL_HUSH
+ home = state->sh_get_var ? state->sh_get_var("HOME") : getenv("HOME");
+# else
+ home = getenv("HOME");
+# endif
+ if (home != NULL && home[0] != '\0')
+ return home;
+
if (!got_user_strings)
get_user_strings();
return home_pwd_buf;
@@ -861,7 +871,7 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type)
continue;
}
# endif
-# if EDITING_HAS_get_exe_name
+# if ENABLE_SHELL_ASH || ENABLE_SHELL_HUSH
if (state->get_exe_name) {
i = 0;
for (;;) {
diff --git a/shell/ash.c b/shell/ash.c
index ef4a47afe..d29de37b7 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -9720,7 +9720,7 @@ evalpipe(union node *n, int flags)
}
/* setinteractive needs this forward reference */
-#if EDITING_HAS_get_exe_name
+#if ENABLE_FEATURE_EDITING
static const char *get_builtin_name(int i) FAST_FUNC;
#endif
@@ -9757,9 +9757,8 @@ setinteractive(int on)
#if ENABLE_FEATURE_EDITING
if (!line_input_state) {
line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
-# if EDITING_HAS_get_exe_name
line_input_state->get_exe_name = get_builtin_name;
-# endif
+ line_input_state->sh_get_var = lookupvar;
}
#endif
}
@@ -10262,7 +10261,7 @@ find_builtin(const char *name)
return bp;
}
-#if EDITING_HAS_get_exe_name
+#if ENABLE_FEATURE_EDITING
static const char * FAST_FUNC
get_builtin_name(int i)
{
diff --git a/shell/hush.c b/shell/hush.c
index ae81f0da5..051b123e7 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -8188,7 +8188,7 @@ static const struct built_in_command *find_builtin(const char *name)
return find_builtin_helper(name, bltins2, &bltins2[ARRAY_SIZE(bltins2)]);
}
-#if ENABLE_HUSH_JOB && EDITING_HAS_get_exe_name
+#if ENABLE_HUSH_JOB && ENABLE_FEATURE_EDITING
static const char * FAST_FUNC get_builtin_name(int i)
{
if (/*i >= 0 && */ i < ARRAY_SIZE(bltins1)) {
@@ -10668,9 +10668,8 @@ int hush_main(int argc, char **argv)
# if ENABLE_FEATURE_EDITING
G.line_input_state = new_line_input_t(FOR_SHELL);
-# if EDITING_HAS_get_exe_name
G.line_input_state->get_exe_name = get_builtin_name;
-# endif
+ G.line_input_state->sh_get_var = get_local_var_value;
# endif
# if ENABLE_HUSH_SAVEHISTORY && MAX_HISTORY > 0
{
From bugzilla at busybox.net Sun Jun 26 17:23:31 2022
From: bugzilla at busybox.net (bugzilla at busybox.net)
Date: Sun, 26 Jun 2022 17:23:31 +0000
Subject: [Bug 14866] sha256sum reports false mismatch if input not delimited
by two spaces
In-Reply-To:
References:
Message-ID:
https://bugs.busybox.net/show_bug.cgi?id=14866
--- Comment #1 from wolf+busybox at wolfsden.cz ---
As far as I know all versions of sha256sum do generate the output with two
spaces (or rather, one space and one character for mode indicator). Why do you
feed it something else?
--
You are receiving this mail because:
You are on the CC list for the bug.
From vda.linux at googlemail.com Sun Jun 26 17:38:28 2022
From: vda.linux at googlemail.com (Denys Vlasenko)
Date: Sun, 26 Jun 2022 19:38:28 +0200
Subject: [git commit] vi: fix regression in autoindent handling
Message-ID: <20220626174327.DA61E87570@busybox.osuosl.org>
commit: https://git.busybox.net/busybox/commit/?id=af3b585815de5af367995d6064d994394b46c928
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master
Suppose autoindent is enabled and we have a line with an initial
tab where we want to split the words onto separate lines:
split the words
One way to do this is with the sequence 'f r;r', but in
BusyBox vi the result is:
split
he
words
This is a regression introduced by commit 9659a8db1 (vi: remove
autoindent from otherwise empty lines). The amount of indentation
is being recorded when the 'r' command inserts a newline but
isn't subsequently reset. A fix is to only record the indent
when in insert or replace mode. Proper handling of the 'o' and
'O' commands then requires them to switch to insert mode before
calling char_insert() to insert a newline.
function old new delta
char_insert 884 891 +7
do_cmd 4243 4247 +4
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 11/0) Total: 11 bytes
Signed-off-by: Ron Yorston
Signed-off-by: Denys Vlasenko
---
editors/vi.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/editors/vi.c b/editors/vi.c
index 6fa0a4e18..5b86b0516 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -2227,7 +2227,10 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p'
p--; // open above, indent before newly inserted NL
if (len) {
- indentcol = col;
+ // only record indent if in insert/replace mode or for
+ // the 'o'/'O' commands, which are switched to insert
+ // mode early.
+ indentcol = cmd_mode != 0 ? col : 0;
if (expandtab) {
ntab = 0;
nspc = col;
@@ -4265,6 +4268,9 @@ static void do_cmd(int c)
case 'o': // o- open an empty line below
dot_end();
dc3:
+#if ENABLE_FEATURE_VI_SETOPTS
+ cmd_mode = 1; // switch to insert mode early
+#endif
dot = char_insert(dot, '\n', ALLOW_UNDO);
if (c == 'O' && !autoindent) {
// done in char_insert() for 'O'+autoindent
From vda.linux at googlemail.com Sun Jun 26 17:38:31 2022
From: vda.linux at googlemail.com (Denys Vlasenko)
Date: Sun, 26 Jun 2022 19:38:31 +0200
Subject: [git commit] vi: handle autoindent in 'cc' command
Message-ID: <20220626174327.EAD5087571@busybox.osuosl.org>
commit: https://git.busybox.net/busybox/commit/?id=2617a5e4c600b4577b2c18f794701276e55da43b
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master
When the 'cc' command is invoked with autoindent enabled it
should use the indent of the first line being changed.
The size of the indent has to be established before char_insert()
is called as the lines being changed are deleted. Introduce a
new global variable, newindent, to handle this. The indentcol
global is now effectively a static variable in char_insert().
function old new delta
do_cmd 4247 4308 +61
vi_main 416 422 +6
char_insert 891 875 -16
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/1 up/down: 67/-16) Total: 51 bytes
Signed-off-by: Ron Yorston
Signed-off-by: Denys Vlasenko
---
editors/vi.c | 71 ++++++++++++++++++++++++++++++++++++++++--------------------
1 file changed, 47 insertions(+), 24 deletions(-)
diff --git a/editors/vi.c b/editors/vi.c
index 5b86b0516..d799a8170 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -380,7 +380,9 @@ struct globals {
char *last_search_pattern; // last pattern from a '/' or '?' search
#endif
#if ENABLE_FEATURE_VI_SETOPTS
- int indentcol; // column of recently autoindent, 0 or -1
+ int char_insert__indentcol; // column of recent autoindent or 0
+ int newindent; // autoindent value for 'O'/'cc' commands
+ // or -1 to use indent from previous line
#endif
smallint cmd_error;
@@ -507,7 +509,8 @@ struct globals {
#define ioq_start (G.ioq_start )
#define dotcnt (G.dotcnt )
#define last_search_pattern (G.last_search_pattern)
-#define indentcol (G.indentcol )
+#define char_insert__indentcol (G.char_insert__indentcol)
+#define newindent (G.newindent )
#define cmd_error (G.cmd_error )
#define edit_file__cur_line (G.edit_file__cur_line)
@@ -540,10 +543,11 @@ struct globals {
#define INIT_G() do { \
SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
- last_modified_count = -1; \
+ last_modified_count--; \
/* "" but has space for 2 chars: */ \
IF_FEATURE_VI_SEARCH(last_search_pattern = xzalloc(2);) \
tabstop = 8; \
+ IF_FEATURE_VI_SETOPTS(newindent--;) \
} while (0)
#if ENABLE_FEATURE_VI_CRASHME
@@ -2113,6 +2117,7 @@ static size_t indent_len(char *p)
static char *char_insert(char *p, char c, int undo) // insert the char c at 'p'
{
#if ENABLE_FEATURE_VI_SETOPTS
+# define indentcol char_insert__indentcol
size_t len;
int col, ntab, nspc;
#endif
@@ -2141,7 +2146,8 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p'
#if ENABLE_FEATURE_VI_SETOPTS
if (autoindent) {
len = indent_len(bol);
- if (len && get_column(bol + len) == indentcol && bol[len] == '\n') {
+ col = get_column(bol + len);
+ if (len && col == indentcol && bol[len] == '\n') {
// remove autoindent from otherwise empty line
text_hole_delete(bol, bol + len - 1, undo);
p = bol;
@@ -2210,26 +2216,30 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p'
showmatching(p - 1);
}
if (autoindent && c == '\n') { // auto indent the new line
- // use indent of current/previous line
- bol = indentcol < 0 ? p : prev_line(p);
- len = indent_len(bol);
- col = get_column(bol + len);
-
- if (len && col == indentcol) {
- // previous line was empty except for autoindent
- // move the indent to the current line
- memmove(bol + 1, bol, len);
- *bol = '\n';
- return p;
+ if (newindent < 0) {
+ // use indent of previous line
+ bol = prev_line(p);
+ len = indent_len(bol);
+ col = get_column(bol + len);
+
+ if (len && col == indentcol) {
+ // previous line was empty except for autoindent
+ // move the indent to the current line
+ memmove(bol + 1, bol, len);
+ *bol = '\n';
+ return p;
+ }
+ } else {
+ // for 'O'/'cc' commands add indent before newly inserted NL
+ if (p != end - 1) // but not for 'cc' at EOF
+ p--;
+ col = newindent;
}
- if (indentcol < 0)
- p--; // open above, indent before newly inserted NL
-
- if (len) {
+ if (col) {
// only record indent if in insert/replace mode or for
- // the 'o'/'O' commands, which are switched to insert
- // mode early.
+ // the 'o'/'O'/'cc' commands, which are switched to
+ // insert mode early.
indentcol = cmd_mode != 0 ? col : 0;
if (expandtab) {
ntab = 0;
@@ -2252,6 +2262,7 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p'
}
#if ENABLE_FEATURE_VI_SETOPTS
indentcol = 0;
+# undef indentcol
#endif
return p;
}
@@ -4220,6 +4231,9 @@ static void do_cmd(int c)
case 'i': // i- insert before current char
case KEYCODE_INSERT: // Cursor Key Insert
dc_i:
+#if ENABLE_FEATURE_VI_SETOPTS
+ newindent = -1;
+#endif
cmd_mode = 1; // start inserting
undo_queue_commit(); // commit queue when cmd_mode changes
break;
@@ -4262,7 +4276,8 @@ static void do_cmd(int c)
case 'O': // O- open an empty line above
dot_begin();
#if ENABLE_FEATURE_VI_SETOPTS
- indentcol = -1;
+ // special case: use indent of current line
+ newindent = get_column(dot + indent_len(dot));
#endif
goto dc3;
case 'o': // o- open an empty line below
@@ -4385,14 +4400,22 @@ static void do_cmd(int c)
if (buftype == WHOLE) {
save_dot = p; // final cursor position is start of range
p = begin_line(p);
+#if ENABLE_FEATURE_VI_SETOPTS
+ if (c == 'c') // special case: use indent of current line
+ newindent = get_column(p + indent_len(p));
+#endif
q = end_line(q);
}
dot = yank_delete(p, q, buftype, yf, ALLOW_UNDO); // delete word
if (buftype == WHOLE) {
if (c == 'c') {
+#if ENABLE_FEATURE_VI_SETOPTS
+ cmd_mode = 1; // switch to insert mode early
+#endif
dot = char_insert(dot, '\n', ALLOW_UNDO_CHAIN);
- // on the last line of file don't move to prev line
- if (dot != (end-1)) {
+ // on the last line of file don't move to prev line,
+ // handled in char_insert() if autoindent is enabled
+ if (dot != (end-1) && !autoindent) {
dot_prev();
}
} else if (c == 'd') {
From bugzilla at busybox.net Sun Jun 26 18:21:14 2022
From: bugzilla at busybox.net (bugzilla at busybox.net)
Date: Sun, 26 Jun 2022 18:21:14 +0000
Subject: [Bug 14866] sha256sum reports false mismatch if input not delimited
by two spaces
In-Reply-To:
References:
Message-ID:
https://bugs.busybox.net/show_bug.cgi?id=14866
--- Comment #2 from rittneje+bugzilla at gmail.com ---
Particularly with a Dockerfile, people are not always literally feeding the
output of sha256sum to itself. It's pretty common to hand-write the echo
instead. And the double space is very easy to overlook.
As I mentioned, this is particularly confusing because (1) no other
implementation of sha256sum cares, and (2) this implementation never clearly
states what the problem is. Consequently people come to the conclusion that it
is broken.
--
You are receiving this mail because:
You are on the CC list for the bug.
From vda.linux at googlemail.com Thu Jun 30 15:18:12 2022
From: vda.linux at googlemail.com (Denys Vlasenko)
Date: Thu, 30 Jun 2022 17:18:12 +0200
Subject: [git commit] tree: new applet
Message-ID: <20220630150608.5EF55877E2@busybox.osuosl.org>
commit: https://git.busybox.net/busybox/commit/?id=20a4f70ecaad79bb932af09b7317a058872cd867
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master
Adds the tree program to list directories and files in a tree structure.
function old new delta
tree_print - 343 +343
scandir64 - 330 +330
scandir - 330 +330
tree_main - 86 +86
.rodata 105150 105228 +78
packed_usage 34511 34557 +46
alphasort64 - 31 +31
alphasort - 31 +31
strcoll - 5 +5
applet_names 2801 2806 +5
applet_main 1616 1620 +4
applet_suid 101 102 +1
applet_install_loc 202 203 +1
------------------------------------------------------------------------------
(add/remove: 11/0 grow/shrink: 6/0 up/down: 1291/0) Total: 1291 bytes
Signed-off-by: Roger Knecht
Signed-off-by: Denys Vlasenko
---
AUTHORS | 3 ++
miscutils/tree.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++
testsuite/tree.tests | 100 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 221 insertions(+)
diff --git a/AUTHORS b/AUTHORS
index 5c9a634c9..9ec0e2ee4 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -181,3 +181,6 @@ Jie Zhang
Maxime Coste
paste implementation
+
+Roger Knecht
+ tree
diff --git a/miscutils/tree.c b/miscutils/tree.c
new file mode 100644
index 000000000..8b16c5383
--- /dev/null
+++ b/miscutils/tree.c
@@ -0,0 +1,118 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Copyright (C) 2022 Roger Knecht
+ *
+ * Licensed under GPLv2, see file LICENSE in this source tree.
+ */
+//config:config TREE
+//config: bool "tree (0.6 kb)"
+//config: default y
+//config: help
+//config: List files and directories in a tree structure.
+
+//applet:IF_TREE(APPLET(tree, BB_DIR_USR_BIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_TREE) += tree.o
+
+//usage:#define tree_trivial_usage NOUSAGE_STR
+//usage:#define tree_full_usage ""
+
+#include "libbb.h"
+#include "common_bufsiz.h"
+
+#define prefix_buf bb_common_bufsiz1
+
+static void tree_print(unsigned count[2], const char* directory_name, char* prefix_pos)
+{
+ struct dirent **entries;
+ int index, size;
+
+ // read directory entries
+ size = scandir(directory_name, &entries, NULL, alphasort);
+
+ if (size < 0) {
+ fputs_stdout(directory_name);
+ puts(" [error opening dir]");
+ return;
+ }
+
+ // print directory name
+ puts(directory_name);
+
+ // switch to sub directory
+ xchdir(directory_name);
+
+ // print all directory entries
+ for (index = 0; index < size;) {
+ struct dirent *dirent = entries[index++];
+
+ // filter hidden files and directories
+ if (dirent->d_name[0] != '.') {
+ int status;
+ struct stat statBuf;
+
+//TODO: when -l is implemented, use stat, not lstat, if -l
+ status = lstat(dirent->d_name, &statBuf);
+
+ if (index == size) {
+ strcpy(prefix_pos, "????????? ");
+ } else {
+ strcpy(prefix_pos, "????????? ");
+ }
+ fputs_stdout(prefix_buf);
+
+ if (status == 0 && S_ISLNK(statBuf.st_mode)) {
+ // handle symlink
+ char* symlink_path = xmalloc_readlink(dirent->d_name);
+ printf("%s -> %s\n", dirent->d_name, symlink_path);
+ free(symlink_path);
+ count[1]++;
+ } else if (status == 0 && S_ISDIR(statBuf.st_mode)
+ && (prefix_pos - prefix_buf) < (COMMON_BUFSIZE - 16)
+ ) {
+ // handle directory
+ char* pos;
+ if (index == size) {
+ pos = stpcpy(prefix_pos, " ");
+ } else {
+ pos = stpcpy(prefix_pos, "??????? ");
+ }
+ tree_print(count, dirent->d_name, pos);
+ count[0]++;
+ } else {
+ // handle file
+ puts(dirent->d_name);
+ count[1]++;
+ }
+ }
+
+ // release directory entry
+ free(dirent);
+ }
+
+ // release directory array
+ free(entries);
+
+ // switch to parent directory
+ xchdir("..");
+}
+
+int tree_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int tree_main(int argc UNUSED_PARAM, char **argv)
+{
+ unsigned count[2] = { 0, 0 };
+
+ setup_common_bufsiz();
+
+ if (!argv[1])
+ *argv-- = (char*)".";
+
+ // list directories given as command line arguments
+ while (*(++argv))
+ tree_print(count, *argv, prefix_buf);
+
+ // print statistic
+ printf("\n%u directories, %u files\n", count[0], count[1]);
+
+ return EXIT_SUCCESS;
+}
diff --git a/testsuite/tree.tests b/testsuite/tree.tests
new file mode 100755
index 000000000..4f4a9e30b
--- /dev/null
+++ b/testsuite/tree.tests
@@ -0,0 +1,100 @@
+#!/bin/sh
+
+# Copyright 2022 by Roger Knecht
+# Licensed under GPLv2, see file LICENSE in this source tree.
+
+. ./testing.sh -v
+
+# testing "description" "command" "result" "infile" "stdin"
+
+testing "tree error opening dir" \
+ "tree tree.tempdir" \
+ "\
+tree.tempdir [error opening dir]\n\
+\n\
+0 directories, 0 files\n" \
+ "" ""
+
+mkdir -p tree2.tempdir
+touch tree2.tempdir/testfile
+
+testing "tree single file" \
+ "cd tree2.tempdir && tree" \
+ "\
+.\n\
+????????? testfile\n\
+\n\
+0 directories, 1 files\n" \
+ "" ""
+
+mkdir -p tree3.tempdir/test1 \
+ tree3.tempdir/test2/a \
+ tree3.tempdir/test2/b \
+ tree3.tempdir/test3/c \
+ tree3.tempdir/test3/d
+
+touch tree3.tempdir/test2/a/testfile1 \
+ tree3.tempdir/test2/a/testfile2 \
+ tree3.tempdir/test2/a/testfile3 \
+ tree3.tempdir/test2/b/testfile4 \
+ tree3.tempdir/test3/c/testfile5 \
+ tree3.tempdir/test3/d/testfile6 \
+ tree3.tempdir/test3/d/.testfile7
+
+(cd tree3.tempdir/test2/a && ln -s ../b/testfile4 .)
+(cd tree3.tempdir/test2/b && ln -s ../../test3 .)
+
+testing "tree nested directories and files" \
+ "cd tree3.tempdir && tree" \
+ "\
+.\n\
+????????? test1\n\
+????????? test2\n\
+??????? ????????? a\n\
+??????? ??????? ????????? testfile1\n\
+??????? ??????? ????????? testfile2\n\
+??????? ??????? ????????? testfile3\n\
+??????? ??????? ????????? testfile4 -> ../b/testfile4\n\
+??????? ????????? b\n\
+??????? ????????? test3 -> ../../test3\n\
+??????? ????????? testfile4\n\
+????????? test3\n\
+ ????????? c\n\
+ ??????? ????????? testfile5\n\
+ ????????? d\n\
+ ????????? testfile6\n\
+\n\
+7 directories, 8 files\n" \
+ "" ""
+#note: tree v2.0.1 says "8 directories, 7 files":
+#it counts "test3 -> ../../test3" as a directory, even though it does not follow this symlink
+
+testing "tree multiple directories" \
+ "tree tree2.tempdir tree3.tempdir" \
+ "\
+tree2.tempdir\n\
+????????? testfile\n\
+tree3.tempdir\n\
+????????? test1\n\
+????????? test2\n\
+??????? ????????? a\n\
+??????? ??????? ????????? testfile1\n\
+??????? ??????? ????????? testfile2\n\
+??????? ??????? ????????? testfile3\n\
+??????? ??????? ????????? testfile4 -> ../b/testfile4\n\
+??????? ????????? b\n\
+??????? ????????? test3 -> ../../test3\n\
+??????? ????????? testfile4\n\
+????????? test3\n\
+ ????????? c\n\
+ ??????? ????????? testfile5\n\
+ ????????? d\n\
+ ????????? testfile6\n\
+\n\
+7 directories, 9 files\n" \
+ "" ""
+#note: tree v2.0.1 says "8 directories, 7 files" (not "8 files", probably a/testfile4 -> ../b/testfile4 and b/testfile4 are counted as one file, not 2?)
+
+rm -rf tree.tempdir tree2.tempdir tree3.tempdir
+
+exit $FAILCOUNT