頁面頂部輸出:PHP has encountered a Stack overflow (PHP 遇到堆棧溢出)。
**關鍵特徵**:錯誤發生在**任何業務代碼執行前**,甚至 `echo 'test';` 都不會輸出。整個 PHP 進程啟動階段就崩潰。
**核心原因**:PHP 處理腳本時需訪問**上級目錄** (如解析 `include_path`、解析相對路徑、讀取 `php.ini`、會話存儲目錄等)。若 **父目錄缺少「遍歷/列舉」權限** (Windows 稱「匿名來賓」/ `Users` / `IIS_IUSRS` 的 `Read & Execute` / `List folder / read data`),PHP 內部路徑解析函數會陷入**無限遞歸/重試循環**,最終耗盡 C 棧空間觸發 Stack Overflow。
# 目錄結構
D:\www\jb51\webroot\ <-- DocumentRoot (網站根目錄)
D:\www\jb51\ <-- 父目錄
# 錯誤權限狀態
D:\www\jb51\webroot\ -> 用戶 IIS_IUSRS: 讀取/寫入/執行 ✅
D:\www\jb51\ -> 用戶 IIS_IUSRS: **無任何權限** ❌ (繼承被阻斷或顯式移除)
# PHP 請求流程
1. 請求 D:\www\jb51\webroot\index.php
2. PHP 內部需解析真實路徑 -> 遞歸向上查找 D:\www\jb51\
3. 訪問被拒 -> 內部錯誤處理 -> 重試/回溯 -> 無限遞歸 -> Stack Overflow
# 命令行 (管理員權限)
# 給網站父目錄授予 IIS_IUSRS / IUSR 讀取/執行/列舉權限
icacls "D:\www\jb51" /grant "IIS_IUSRS:(OI)(CI)(RX)" /T
icacls "D:\www\jb51" /grant "IUSR:(OI)(CI)(RX)" /T
# 或圖形界面:右鍵屬性 -> 安全 -> 編輯 -> 添加 IIS_IUSRS / IUSR -> 勾選 "讀取和執行"、"列出文件夾內容"、"讀取"
將 DocumentRoot 指向**權限正確的上級目錄**,或在權限正確的目錄下創建新項目目錄:
# 原結構 (父目錄無權限)
D:\www\jb51\webroot\ -> DocumentRoot
# 新結構 (在有權限的目錄下建站)
D:\www\jb51\new_site\ -> DocumentRoot (繼承 D:\www\jb51\ 權限)
# 或
D:\www\jb51\webroot\new_project\ -> DocumentRoot
**原理**:PHP 只會向上遍歷到 DocumentRoot 所在目錄,不會觸及更上級無權限目錄。
PHP (Zend Engine) 路徑解析函數 (如 `VCWD_REALPATH`、`tsrm_realpath`、Windows 實現 `php_win32_check_trailing_space` 等) 在遇到 `ACCESS_DENIED` 時,**不直接返回錯誤**,而是嘗試替代路徑、標準化路徑、去除尾部空格/點等操作,導致**函數調用棧無限增長**,最終觸發 Windows 結構化異常處理 (SEH) 捕獲 `STATUS_STACK_OVERFLOW` (0xC00000FD),PHP 輸出 "Stack overflow" 並進程退出。
# 1. 父目錄權限檢查腳本 (保存為 check_perms.php 放入網站根目錄訪問)
<?php
$root = realpath($_SERVER['DOCUMENT_ROOT']);
$parent = dirname($root);
echo "Web Root: $root\n";
echo "Parent: $parent\n";
echo "Root readable: " . (is_readable($root) ? 'YES' : 'NO') . "\n";
echo "Parent readable: " . (is_readable($parent) ? 'YES' : 'NO') . "\n";
echo "Parent listable: " . (is_dir($parent) && ($h = @opendir($parent)) ? 'YES' : 'NO') . "\n";
if ($h) closedir($h);
?>
# 2. 部署腳本自動化權限設置 (PowerShell)
$webRoot = "D:\www\jb51\webroot"
$parent = "D:\www\jb51"
$users = @("IIS_IUSRS", "IUSR")
foreach ($u in $users) {
icacls $parent /grant "$u:(OI)(CI)(RX)" /T
icacls $webRoot /grant "$u:(OI)(CI)(RX)" /T
}
# 3. 監控告警:Windows 事件日誌中出現 PHP Stack Overflow 立即告警
Windows PHP 部署鐵律:**DocumentRoot 及其所有父目錄,必須授予運行 PHP 的用戶 (IIS_IUSRS/IUSR/Apache User) 至少 `Read & Execute` / `List folder / read data` 權限。**
這不是建議,是**生存條件**。Stack Overflow 是權限缺失在 Zend Engine 內部路徑解析遞歸中觸發的「心臟驟停」,而非業務代碼錯誤。