Add a CI for increase_default_stack_size.sh

This runs whenever the script is modified, or weekly to ensure the CI doesn't
inadvertently decay (due to using the latest packages for a variety of shells).

This runs with `sh` (presumably `dash`), `ksh`, `bash`, `dash` (explicitly),
`zsh`, `ash` (Busybox), `hush` (Busybox), `mksh`, `yash`, and `brush`. While
none of these guarantee this script is POSIX-compliant, as a fully and
explicitly-only POSIX-compliant environment is not constructed, this does
reasonably test the script itself to be POSIX-compliant. The tools called have
been reviewed for being used to the POSIX standard (although not audited to
that degree).

The script itself is modified with the following changes for compliance with
POSIX:
1) `hexdump` is replaced with `od` (`od` suggested by @PlasmaPower)
2) `printf \xFF` replaced with octal escapes, as `\x` is not part of POSIX
3) `head -c` is replaced with `cut`, as the `-c` option is not standardized
   under POSIX (despite it being present for `tail`). This was identified by
   @PlasmaPower. As we used `head -c-2` to truncate the last two characters of
   a string, we now use `wc -c` for a `strlen` to enable the necessary
   arithmetic to calculate what two bytes in from the end of the string is.

This entire effort can be argued pointless, as we could simply run `monerod` on
Debian. This script is useful, the journey down the rabbithole of POSIX
compliance fascinating, and the methodology applicable to other potential
futures though (whether running binaries on Alpine or testing other `sh`
scripts for their portability). As part of this effort overall, our CI was
extended with `shellcheck` for all `sh` scripts in-tree, including all of our
existing `sh` scripts. That there is an actual, direct benefit past this
specific effort.
This commit is contained in:
Luke Parker
2025-12-09 00:57:26 -05:00
parent f70fee65b8
commit 6603100c7e
4 changed files with 110 additions and 8 deletions

View File

@@ -26,23 +26,28 @@ hex() {
read_bytes() {
dd bs=1 skip="$1" count="$2" if="$ELF" 2> /dev/null | hex
}
hex_to_octal() {
printf "ibase=16; obase=8; %s\n" "$1" | bc
}
write_bytes() {
POS=$1
BYTES=$2
while [ ! "$BYTES" = "" ]; do
NEXT=$(printf "%s" "$BYTES" | head -c2)
NEXT=$(printf "%s" "$BYTES" | cut -c-2)
# Advance to the third byte, as in, after the first two bytes
BYTES=$(printf "%s" "$BYTES" | tail -c+3)
NEXT=$(hex_to_octal "$NEXT")
# shellcheck disable=SC2059
printf "\x$NEXT" | dd conv=notrunc bs=1 seek="$POS" of="$ELF" 2> /dev/null
printf \\"$NEXT" | dd conv=notrunc bs=1 seek="$POS" of="$ELF" 2> /dev/null
POS=$((POS + 1))
done
}
# Magic
MAGIC=$(read_bytes 0 4)
EXPECTED_MAGIC=$(printf "\x7ELF" | hex)
# shellcheck disable=SC2059
EXPECTED_MAGIC=$(printf \\"$(hex_to_octal 7F)"ELF | hex)
if [ ! "$MAGIC" = "$EXPECTED_MAGIC" ]; then
echo "Not ELF"
exit 2
@@ -101,9 +106,13 @@ swap_native_endian() {
return
fi
while [ ! "$BYTES" = "" ]; do
while :; do
printf "%s" "$BYTES" | tail -c2
BYTES=$(printf "%s" "$BYTES" | head -c-2)
NEW_LENGTH=$(( $(printf "%s" "$BYTES" | wc -c) - 2 ))
if [ "$NEW_LENGTH" -eq 0 ]; then
break
fi
BYTES=$(printf "%s" "$BYTES" | cut -c-$NEW_LENGTH)
done
}
@@ -144,7 +153,7 @@ while [ "$NEXT_PROGRAM_HEADER" -ne -1 ]; do
NEXT_PROGRAM_HEADER=$(( NEXT_PROGRAM_HEADER - 1 ))
PROGRAM_HEADER=$(read_program_header "$THIS_PROGRAM_HEADER")
HEADER_TYPE=$(printf "%s" "$PROGRAM_HEADER" | head -c8)
HEADER_TYPE=$(printf "%s" "$PROGRAM_HEADER" | cut -c-8)
HEADER_TYPE=$(swap_native_endian "$HEADER_TYPE")
# `PT_GNU_STACK`
# https://github.com/torvalds/linux/blob/c2f2b01b74be8b40a2173372bcd770723f87e7b2/include/uapi/linux/elf.h#L41