diff --git a/linux/install.sh b/linux/install.sh index 23fc745..39a54f5 100644 --- a/linux/install.sh +++ b/linux/install.sh @@ -6,7 +6,7 @@ set -e -PHPVM_VERSION="1.13.1" +PHPVM_VERSION="1.13.2" PHPVM_DIR="${PHPVM_DIR:-$HOME/.phpvm}" PHPVM_REPO="https://raw.githubusercontent.com/devhardiyanto/phpvm/main" diff --git a/linux/phpvm.sh b/linux/phpvm.sh index b1c3631..3ddc03c 100644 --- a/linux/phpvm.sh +++ b/linux/phpvm.sh @@ -10,7 +10,7 @@ # phpvm use 8.3.0 # ============================================================================== -PHPVM_VERSION="1.13.1" +PHPVM_VERSION="1.13.2" PHPVM_DIR="${PHPVM_DIR:-$HOME/.phpvm}" PHPVM_VERSIONS="$PHPVM_DIR/versions" PHPVM_CURRENT="$PHPVM_DIR/current" @@ -238,9 +238,17 @@ _phpvm_detect_os() { # what configure consults, so ask it first; the `openssl` CLI is a fallback and # can disagree with the installed headers. Echoes "3.0.2"; non-zero if unknown. _phpvm_openssl_version() { + # LibreSSL and BoringSSL answer `openssl version` and ship an openssl.pc of + # their own, but their 3.x still defines RSA_SSLV23_PADDING — the premise of + # the guard below. Their numbering says nothing about it, so report the host + # as unknown rather than block a build that would have succeeded. + local banner="" + command -v openssl &>/dev/null && banner=$(openssl version 2>/dev/null) + [[ -n "$banner" && "$banner" != OpenSSL* ]] && return 1 + local v="" command -v pkg-config &>/dev/null && v=$(pkg-config --modversion openssl 2>/dev/null) - [[ -z "$v" ]] && command -v openssl &>/dev/null && v=$(openssl version 2>/dev/null | awk '{print $2}') + [[ -z "$v" && -n "$banner" ]] && v=$(echo "$banner" | awk '{print $2}') # Strip a letter suffix: OpenSSL 1.1.1w -> 1.1.1 v="${v%%[a-zA-Z]*}" [[ -n "$v" ]] || return 1 @@ -264,9 +272,13 @@ _phpvm_check_openssl_compat() { (( major > 8 )) && return 0 (( major == 8 && minor >= 1 )) && return 0 - local ssl + local ssl ssl_major ssl=$(_phpvm_openssl_version) || return 0 # can't tell -> don't block - [[ "${ssl%%.*}" -lt 3 ]] && return 0 + ssl_major="${ssl%%.*}" + # A non-numeric major is something this probe doesn't model; `-lt` would + # error and fall through to blocking, so fail open here too. + [[ "$ssl_major" =~ ^[0-9]+$ ]] || return 0 + (( ssl_major < 3 )) && return 0 _err "PHP $ver cannot be built against OpenSSL $ssl." _dim "OpenSSL 3.0 removed RSA_SSLV23_PADDING; PHP's openssl extension only" @@ -604,6 +616,12 @@ phpvm_install() { local cpus cpus=$(_phpvm_cpus) + # One install owns the log. Every step below appends, so without this the + # file accumulates across runs and _phpvm_show_build_error's `grep -m1` + # reports the first error of an *earlier* build — exactly the wrong line + # when someone is retrying the install they just watched fail. + : > "$PHPVM_LOG" + # The whole build runs in a subshell so the `cd` cannot escape: phpvm.sh is # sourced, so a bare cd here would strand the user's own shell in the build # directory — which is then deleted, leaving them in a dangling cwd. diff --git a/tests/linux/build_preflight.bats b/tests/linux/build_preflight.bats index 1be9df8..6ce1a39 100644 --- a/tests/linux/build_preflight.bats +++ b/tests/linux/build_preflight.bats @@ -22,6 +22,13 @@ _stub_openssl() { eval "_phpvm_openssl_version() { echo '$1'; }" } +# Pin what `openssl version` reports, to exercise the probe itself. A function +# satisfies `command -v openssl`, so the probe takes the same path it would on +# a host that really ships this binary. +_stub_openssl_cli() { + eval "openssl() { [ \"\$1\" = version ] && echo '$1'; }" +} + # ── OpenSSL compatibility guard ─────────────────────────────────────────────── @test "openssl 3 blocks PHP 7.3" { @@ -74,6 +81,34 @@ _stub_openssl() { [[ "$output" == *"PHPVM_SKIP_OPENSSL_CHECK=1"* ]] } +@test "a non-numeric openssl major does not block the build" { + _stub_openssl "unknown" + run _phpvm_check_openssl_compat 7.3.33 + [ "$status" -eq 0 ] +} + +@test "libressl reports as unknown rather than blocking" { + _stub_openssl_cli "LibreSSL 3.3.6" + run _phpvm_openssl_version + [ "$status" -eq 1 ] + # LibreSSL 3.x still defines RSA_SSLV23_PADDING, so PHP 7.3 must build. + run _phpvm_check_openssl_compat 7.3.33 + [ "$status" -eq 0 ] +} + +@test "boringssl reports as unknown rather than blocking" { + _stub_openssl_cli "BoringSSL 3.0.0" + run _phpvm_check_openssl_compat 7.3.33 + [ "$status" -eq 0 ] +} + +@test "a genuine OpenSSL banner still yields a version" { + _stub_openssl_cli "OpenSSL 3.0.13 30 Jan 2024" + run _phpvm_openssl_version + [ "$status" -eq 0 ] + [[ "$output" =~ ^[0-9]+(\.[0-9]+)*$ ]] +} + @test "openssl version probe strips a letter suffix" { # Only meaningful when the host actually has one of the probes. if ! command -v pkg-config &>/dev/null && ! command -v openssl &>/dev/null; then @@ -123,3 +158,20 @@ LOG [ "$status" -eq 0 ] [ -z "$output" ] } + +# Every build step appends, so one install must start the log from empty or +# `grep -m1` above surfaces the first error of a *previous* run. Driving a real +# install here would mean a compiler and ten minutes, so assert the ordering in +# phpvm_install's own body instead. +@test "install truncates the build log before anything appends to it" { + local src="$BATS_TEST_DIRNAME/../../linux/phpvm.sh" + local body trunc append + body=$(awk '/^phpvm_install\(\)/{f=1} f{print} f&&/^}$/{exit}' "$src") + + trunc=$(printf '%s\n' "$body" | grep -n ': > "\$PHPVM_LOG"' | head -1 | cut -d: -f1) + append=$(printf '%s\n' "$body" | grep -n '>>"\?\$PHPVM_LOG"\?' | head -1 | cut -d: -f1) + + [ -n "$trunc" ] + [ -n "$append" ] + [ "$trunc" -lt "$append" ] +} diff --git a/tests/linux/zsh-smoke.zsh b/tests/linux/zsh-smoke.zsh index ec50031..1a4e4d9 100644 --- a/tests/linux/zsh-smoke.zsh +++ b/tests/linux/zsh-smoke.zsh @@ -65,6 +65,24 @@ print "8.3" > "$tmp/proj/.phpvmrc" out=$(cd "$tmp/proj" && _phpvm_read_rc "$tmp/proj/.phpvmrc" 2>&1) check "reads a .phpvmrc version" "8.3" "$out" +print -r -- "-- openssl guard (pattern and regex matching) --" +# The guard leans on [[ != OpenSSL* ]] globbing and [[ =~ ]] regex, both of +# which zsh parses on its own terms. bats only ever sees the bash reading. +# Probe first, while the real _phpvm_openssl_version is still in place. +openssl() { [[ "$1" == version ]] && print "LibreSSL 3.3.6" } +_phpvm_openssl_version >/dev/null 2>&1 +check "libressl reports as unknown" "1" "$?" +unset -f openssl + +_phpvm_openssl_version() { print 3.0.2 } +out=$(_phpvm_check_openssl_compat 7.3.33 2>&1) +check "openssl 3 blocks PHP 7.3" "cannot be built against OpenSSL 3.0.2" "$out" +_phpvm_check_openssl_compat 8.1.0 >/dev/null 2>&1 +check "openssl 3 allows PHP 8.1" "0" "$?" +_phpvm_openssl_version() { print unknown } +_phpvm_check_openssl_compat 7.3.33 >/dev/null 2>&1 +check "non-numeric openssl major fails open" "0" "$?" + print -r -- "-- older-patch hint --" mkdir -p "$PHPVM_DIR/versions/8.5.1" "$PHPVM_DIR/versions/8.5.2" "$PHPVM_DIR/versions/8.5.8" out=$(_phpvm_older_patch_hint 8.5.8 2>&1) diff --git a/version.txt b/version.txt index da38e07..f0df1f7 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.13.1 \ No newline at end of file +1.13.2 \ No newline at end of file diff --git a/windows/install.ps1 b/windows/install.ps1 index 53c843f..8b5a454 100644 --- a/windows/install.ps1 +++ b/windows/install.ps1 @@ -8,7 +8,7 @@ Set-StrictMode -Version Latest $ErrorActionPreference = "Stop" -$PHPVM_VERSION = "1.13.1" +$PHPVM_VERSION = "1.13.2" $PHPVM_DIR = if ($env:PHPVM_DIR) { $env:PHPVM_DIR } else { "$env:USERPROFILE\.phpvm" } $PHPVM_BIN = "$PHPVM_DIR\bin" diff --git a/windows/phpvm.ps1 b/windows/phpvm.ps1 index 8d2c79b..b58a128 100644 --- a/windows/phpvm.ps1 +++ b/windows/phpvm.ps1 @@ -23,7 +23,7 @@ Set-StrictMode -Version Latest $ErrorActionPreference = "Stop" # -- Constants ----------------------------------------------------------------- -$PHPVM_VERSION = "1.13.1" +$PHPVM_VERSION = "1.13.2" $PHPVM_DIR = if ($env:PHPVM_DIR) { $env:PHPVM_DIR } else { "$env:USERPROFILE\.phpvm" } $VERSIONS_DIR = "$PHPVM_DIR\versions" $CURRENT_LINK = "$PHPVM_DIR\current" diff --git a/windows/src/00-header.ps1 b/windows/src/00-header.ps1 index f288432..f82eb8d 100644 --- a/windows/src/00-header.ps1 +++ b/windows/src/00-header.ps1 @@ -15,7 +15,7 @@ Set-StrictMode -Version Latest $ErrorActionPreference = "Stop" # -- Constants ----------------------------------------------------------------- -$PHPVM_VERSION = "1.13.1" +$PHPVM_VERSION = "1.13.2" $PHPVM_DIR = if ($env:PHPVM_DIR) { $env:PHPVM_DIR } else { "$env:USERPROFILE\.phpvm" } $VERSIONS_DIR = "$PHPVM_DIR\versions" $CURRENT_LINK = "$PHPVM_DIR\current"