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 jobsengaja 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 mainJul 26, 2026
5 checks passed
@devhardiyanto
devhardiyanto deleted the linux-openssl-preflight branch July 30, 2026 02:10
Sign up for freeto 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

@devhardiyanto
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
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 jobsengaja 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 mainJul 26, 2026
5 checks passed
@devhardiyanto
devhardiyanto deleted the linux-openssl-preflight branch July 30, 2026 02:10
Sign up for freeto 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

@devhardiyanto
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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 jobsengaja 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 mainJul 26, 2026
5 checks passed
@devhardiyanto
devhardiyanto deleted the linux-openssl-preflight branch July 30, 2026 02:10
Sign up for freeto 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

@devhardiyanto
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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 jobsengaja 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 mainJul 26, 2026
5 checks passed
@devhardiyanto
devhardiyanto deleted the linux-openssl-preflight branch July 30, 2026 02:10
Sign up for freeto 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

@devhardiyanto
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
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 jobsengaja 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 mainJul 26, 2026
5 checks passed
@devhardiyanto
devhardiyanto deleted the linux-openssl-preflight branch July 30, 2026 02:10
Sign up for freeto 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

@devhardiyanto
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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 jobsengaja 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 mainJul 26, 2026
5 checks passed
@devhardiyanto
devhardiyanto deleted the linux-openssl-preflight branch July 30, 2026 02:10
Sign up for freeto 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

@devhardiyanto
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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 jobsengaja 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 mainJul 26, 2026
5 checks passed
@devhardiyanto
devhardiyanto deleted the linux-openssl-preflight branch July 30, 2026 02:10
Sign up for freeto 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

@devhardiyanto
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
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 jobsengaja 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 mainJul 26, 2026
5 checks passed
@devhardiyanto
devhardiyanto deleted the linux-openssl-preflight branch July 30, 2026 02:10
Sign up for freeto 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

@devhardiyanto