diff options
author | Denys Vlasenko <dvlasenk@redhat.com> | 2019-11-21 15:51:47 +0100 |
---|---|---|
committer | Thierry Vignaud <thierry.vignaud@gmail.com> | 2019-12-23 16:02:47 +0100 |
commit | 8ecaeab1b79c20f83eda540e39f31e6a73018d7f (patch) | |
tree | d0be71a0a008f4aad7819822fc5f58292b0ec4e6 | |
parent | 7944a0608672698b96767550fa265fde01f29bf0 (diff) | |
download | rpm-setup-8ecaeab1b79c20f83eda540e39f31e6a73018d7f.tar rpm-setup-8ecaeab1b79c20f83eda540e39f31e6a73018d7f.tar.gz rpm-setup-8ecaeab1b79c20f83eda540e39f31e6a73018d7f.tar.bz2 rpm-setup-8ecaeab1b79c20f83eda540e39f31e6a73018d7f.tar.xz rpm-setup-8ecaeab1b79c20f83eda540e39f31e6a73018d7f.zip |
brp-mangle-shebangs: fix unsafe/incorrect command expansion
trim() {
printf '%s' "$*"
}
...
read shebang_line < "$f" || :
orig_shebang=$(trim $(echo "$shebang_line" | grep -Po "#!\K.*" || echo))
The "trimming", i.e. replacement of multiple spaces and removal of leading
and trailing spaces, is achieved because "trim $(cmd)" construct has an
unquoted $(), which is subject to word splitting.
This works, yes. BUT.
It is also subject to glob expansion - any ?s and *s will be attempted
to be expanded as well - definitely NOT what we want!
This change replaces this trick with code which avoids the expansion issue,
and which does not spawn any subprocesses for string manipulations -
this is ~3 times faster (fork+execs are expensive).
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
-rwxr-xr-x | brp-mangle-shebangs | 33 |
1 files changed, 19 insertions, 14 deletions
diff --git a/brp-mangle-shebangs b/brp-mangle-shebangs index d79af5a..11809b4 100755 --- a/brp-mangle-shebangs +++ b/brp-mangle-shebangs @@ -70,10 +70,6 @@ done cd "$RPM_BUILD_ROOT" -trim() { - printf '%s' "$*" -} - # Large packages such as kernel can have thousands of executable files. # We take care to not fork/exec thousands of "file"s and "grep"s, # but run just two of them. @@ -98,22 +94,31 @@ while IFS= read -r line; do ts=$(stat -c %y "$f") - read shebang_line < "$f" || : - orig_shebang=$(trim $(echo "$shebang_line" | grep -Po "#!\K.*" || echo)) - shebang="$orig_shebang" - if [ -n "$exclude_shebangs" ]; then - echo "$shebang" | grep -q -E "$exclude_shebangs" && continue - fi - if [ -n "$exclude_shebangs_from" ]; then - echo "$shebang" | grep -q -E -f "$exclude_shebangs_from" && continue + read shebang_line < "$f" + orig_shebang="${shebang_line#\#!}" + if [ "$orig_shebang" = "$shebang_line" ]; then + echo >&2 "*** WARNING: $f is executable but has no shebang, removing executable bit" + chmod -x "$f" + touch -d "$ts" "$f" + continue fi + # Trim spaces + while shebang="${orig_shebang// / }"; [ "$shebang" != "$orig_shebang" ]; do + orig_shebang="$shebang" + done + # Treat "#! /path/to " as "#!/path/to" + orig_shebang="${orig_shebang# }" + + shebang="$orig_shebang" + if [ -z "$shebang" ]; then - echo >&2 "*** WARNING: $f is executable but has empty or no shebang, removing executable bit" + echo >&2 "*** WARNING: $f is executable but has empty shebang, removing executable bit" chmod -x "$f" touch -d "$ts" "$f" continue - elif [ -n "${shebang##/*}" ]; then + fi + if [ -n "${shebang##/*}" ]; then echo >&2 "*** ERROR: $f has shebang which doesn't start with '/' ($shebang)" fail=1 continue |