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>
This commit is contained in:
Denys Vlasenko 2019-11-21 15:51:47 +01:00 committed by Igor Gnatenko
parent 63d7e4dc11
commit 618362d6fb
No known key found for this signature in database
GPG Key ID: 695714BD1BBC5F4C

View File

@ -70,10 +70,6 @@ done
cd "$RPM_BUILD_ROOT" cd "$RPM_BUILD_ROOT"
trim() {
printf '%s' "$*"
}
# Large packages such as kernel can have thousands of executable files. # 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, # We take care to not fork/exec thousands of "file"s and "grep"s,
# but run just two of them. # but run just two of them.
@ -98,22 +94,31 @@ while IFS= read -r line; do
ts=$(stat -c %y "$f") ts=$(stat -c %y "$f")
read shebang_line < "$f" || : read shebang_line < "$f"
orig_shebang=$(trim $(echo "$shebang_line" | grep -Po "#!\K.*" || echo)) orig_shebang="${shebang_line#\#!}"
shebang="$orig_shebang" if [ "$orig_shebang" = "$shebang_line" ]; then
if [ -n "$exclude_shebangs" ]; then echo >&2 "*** WARNING: $f is executable but has no shebang, removing executable bit"
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
fi
if [ -z "$shebang" ]; then
echo >&2 "*** WARNING: $f is executable but has empty or no shebang, removing executable bit"
chmod -x "$f" chmod -x "$f"
touch -d "$ts" "$f" touch -d "$ts" "$f"
continue continue
elif [ -n "${shebang##/*}" ]; then 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 shebang, removing executable bit"
chmod -x "$f"
touch -d "$ts" "$f"
continue
fi
if [ -n "${shebang##/*}" ]; then
echo >&2 "*** ERROR: $f has shebang which doesn't start with '/' ($shebang)" echo >&2 "*** ERROR: $f has shebang which doesn't start with '/' ($shebang)"
fail=1 fail=1
continue continue