Skip to content

Linux: preflight OpenSSL 3 vs PHP <8.1, surface build errors, fix zsh did-you-mean (v1.13.1)#28

Merged
devhardiyanto merged 5 commits into
mainfrom
linux-openssl-preflight
Jul 26, 2026
Merged

Linux: preflight OpenSSL 3 vs PHP <8.1, surface build errors, fix zsh did-you-mean (v1.13.1)#28
devhardiyanto merged 5 commits into
mainfrom
linux-openssl-preflight

Conversation

@devhardiyanto

Copy link
Copy Markdown
Owner

What

Patch Linux/macOS: hentikan build PHP < 8.1 di host OpenSSL 3 sebelum compile, munculkan baris error yang relevan saat build gagal, dan perbaiki tiga ketidakcocokan zsh yang membuat phpvm <typo> rusak total. Bump 1.13.0 → 1.13.1.

Why

Dilaporkan dari pemakaian nyata: phpvm install 7.3.33 gagal setelah ~10 menit compile. Log 1801 baris, dan satu baris yang menjelaskannya terkubur di tengah:

ext/openssl/openssl.c:1491:58: error: 'RSA_SSLV23_PADDING' undeclared

OpenSSL menghapus konstanta itu di 3.0, dan php-src baru berhenti memakainya di 8.1 — jadi semua PHP < 8.1 tak bisa dibuild di distro modern. Ini kondisi upstream, bukan bug phpvm. Yang jadi masalah: hasilnya sudah bisa dipastikan sebelum satu file pun dicompile, tapi phpvm tetap membiarkan user menunggu sepuluh menit lalu cuma bilang See log.

Temuan zsh datang dari audit terpisah di sesi yang sama, dipicu oleh kelas bug yang baru saja ditemukan di sisi Windows (asumsi tipe yang tak pernah tersentuh test).

How

Preflight OpenSSL. _phpvm_check_openssl_compat dipanggil tepat setelah _phpvm_check_deps, saat versi sudah diresolusi penuh (jadi phpvm install 7.37.3.33 dulu, baru dicek). Versi OpenSSL dibaca dari pkg-config — itu yang dikonsultasi ./configure — dengan CLI openssl sebagai fallback.

Dua keputusan desain yang sengaja:

  • Fail open. Kalau kedua probe tak menjawab, build tetap jalan. Guard yang menebak lalu memblokir lebih buruk daripada tak ada guard.
  • Bisa di-bypass lewat PHPVM_SKIP_OPENSSL_CHECK=1. Ada setup di mana pkg-config meresolusi OpenSSL 1.1 yang tak terlihat oleh probe ini; guard mutlak akan mengunci mereka tanpa jalan keluar.

Surface error. Saat build gagal apa pun sebabnya, ambil error pertama dari log — configure: error: diutamakan di atas noise compiler yang menyusul. Diuji terhadap log 1801 baris dari laporan asli: ia menarik persis baris RSA_SSLV23_PADDING.

zsh. Job CI zsh ditambahkan lebih dulu dan sengaja dibiarkan merah, baru fix menyusul — supaya masalahnya terbukti, bukan diasumsikan. Job itu menemukan tiga hal, masing-masing tersembunyi di balik yang sebelumnya:

  1. _phpvm_levenshtein menulis row[0]. Array zsh 1-based dan menolaknya: assignment to invalid subscript range.
  2. for c in $_PHPVM_COMMANDS mengandalkan word-splitting parameter tanpa kutip — zsh tidak melakukannya. Tiap typo dijawab Did you mean 'install use list ls current uninstall ...', seluruh daftar command sebagai satu saran.
  3. ${a:i-1:1} membuat zsh membaca :i sebagai history modifier. Menariknya phpvm.sh:335 sudah mendokumentasikan jebakan yang sama persis untuk spinner — loop levenshtein terlewat.

Efek gabungannya: di zsh, setiap command salah ketik memuntahkan error internal plus saran ngawur.

Changes

  • linux/phpvm.sh_phpvm_openssl_version + _phpvm_check_openssl_compat (dekat _phpvm_check_deps), dipanggil dari phpvm_install
  • linux/phpvm.sh_phpvm_show_build_error, dipanggil saat subshell build gagal
  • linux/phpvm.sh_phpvm_levenshtein indeks digeser ke basis 1 + offset substring dieksplisitkan; _PHPVM_COMMANDS jadi array
  • linux/phpvm.sh — hint older-patch: paste -sd ', ' menyiklus delimiter (8.3.1,8.3.2 8.3.5); Windows sudah benar sejak awal
  • tests/linux/build_preflight.bats (baru) — 12 test guard + surfacing
  • tests/linux/commands.bats — 1 test format hint older-patch
  • tests/linux/zsh-smoke.zsh (baru) + job CI zsh — jaring pengaman zsh pertama di repo ini
  • README.md — cara jalankan zsh smoke + tiga jebakan zsh yang perlu diingat
  • version.txt + 4 sumber versi → 1.13.1

Paritas OS

Semua perubahan Linux-only by design: Windows pakai zip PHP prebuilt (tak ada build-from-source, jadi tak ada padanan OpenSSL/build-log), dan paste/zsh tak punya counterpart di PowerShell. Bug hint older-patch versi Windows sendiri sudah diperbaiki di rilis sebelumnya.

Testing Done

  • bats 77/77 pass (bats di-clone ke scratchpad — tidak terpasang di mesin dev)
  • zsh smoke pass — dijalankan lokal dengan zsh 5.9 dari msys2, bukan hanya diserahkan ke CI
  • Test format older-patch dibuktikan merah di kode lama, hijau di kode baru — jadi ia benar-benar mengunci sesuatu
  • _phpvm_show_build_error diuji terhadap build.log asli dari laporan (1801 baris) — menarik baris yang benar
  • Matriks guard OpenSSL diverifikasi: 7.3/7.4/8.0 diblokir di ssl3; 8.1/8.3/9.0 lolos; ssl1.1 lolos semua; probe gagal = lolos; bypass = lolos
  • Windows tak tersentuh: Pester 168/168, drift check OK
  • shellcheck — dijalankan CI (tak terpasang lokal)

Catatan review

Commit test(ci): add a zsh compatibility job sengaja merah saat berdiri sendiri. Itu bukti gap-nya nyata; commit berikutnya yang menghijaukannya. Kalau mau memverifikasi ulang: checkout commit itu dan jalankan zsh tests/linux/zsh-smoke.zsh.

Tidak diambil (sengaja)

  • Auto-fallback ke OpenSSL 1.1 (--with-openssl=<prefix>) untuk PHP lama — openssl 1.1 sudah EOL dan tak ada di Ubuntu 24.04; deteksinya rumit dengan hasil yang makin jarang berguna. Bypass manual sudah cukup untuk yang benar-benar butuh.
  • phpvm doctor belum melaporkan kombinasi OpenSSL 3 + PHP lama. Kandidat wajar, tapi di luar scope patch ini.

paste -d takes a *list* of delimiters and cycles through it, so
`paste -sd ', '` alternated comma and space: three stale patches
printed as "8.3.1,8.3.2 8.3.5". Join on a comma and space it out
afterwards.

Windows was already correct - Show-OlderPatchHint uses -join ', '.

devhardiyanto
Building PHP 7.3 on a modern distro fails ~10 minutes in with a wall of
C errors, the useful one buried mid-log: RSA_SSLV23_PADDING undeclared.
OpenSSL removed that constant in 3.0 and php-src only stopped using it
in 8.1, so the outcome is knowable before a single file is compiled.

Add _phpvm_check_openssl_compat, called right after the dependency
check once the version is fully resolved. It reads the OpenSSL version
from pkg-config (what ./configure consults) and falls back to the
openssl CLI. It fails open: if neither probe answers the build still
runs, and PHPVM_SKIP_OPENSSL_CHECK=1 overrides it outright - a guard
that cannot be bypassed would strand anyone whose pkg-config resolves
an OpenSSL 1.1 this probe can't see.

Also surface the first hard error from the build log on any failure,
preferring a configure error over later compiler noise. "See log" alone
left the user paging through thousands of lines.

Ref: php/php-src#9503

devhardiyanto
phpvm.sh is documented as bash/zsh and registers a chpwd hook for zsh
users, but the bats suite runs under bash - so zsh has had zero
coverage. Add a smoke script exercising the paths most likely to
depend on bash semantics (array indexing in _phpvm_levenshtein, the
unquoted $_PHPVM_COMMANDS split in _phpvm_unknown) plus the read-only
commands, and wire it into CI.

Expected to fail on this commit: proving the gap is the point. The
fix follows.

devhardiyanto
The zsh job added in the previous commit went red, as intended. It
found three separate bash assumptions, each hidden behind the one
before it, all on the `phpvm <typo>` path:

1. _phpvm_levenshtein assigned row[0]. zsh arrays are 1-based and
   reject that outright - "assignment to invalid subscript range" -
   so the function printed an error instead of a distance. Shift the
   indices by one; bash just leaves index 0 unused.
2. `for c in $_PHPVM_COMMANDS` relied on word-splitting an unquoted
   parameter, which zsh does not do. Every typo was answered with
   "Did you mean 'install use list ls current ...'" - the entire
   command list as a single suggestion. Make it a real array.
3. ${a:i-1:1} makes zsh parse ":i" as a history modifier. Spell the
   offset out as $((i-1)). phpvm.sh:335 already documents this exact
   trap for the spinner; the levenshtein loop had missed it.

Net effect: under zsh, every mistyped command printed an internal
error and a nonsense suggestion. bash behaviour is unchanged - 77/77
bats still green.

Also fixes two bugs in the smoke script itself: `print "-- x --"` ate
the leading dashes as options, and a status check was reading $? from
the preceding print rather than from the source.

devhardiyanto
@devhardiyanto
devhardiyanto merged commit 0949dc2 into main Jul 26, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant