You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP 8.2.12兼容改造:pack函数H类型报错求助

PHP 6.0.0-dev 迁移到 PHP 8.2.12 的pack函数兼容问题解决

问题描述

将基于PHP 6.0.0-dev的十六进制处理代码适配到PHP 8.2.12时,遇到pack函数报错:Warning: pack(): Type H: not enough characters in string。原环境中某字段以i格式处理值0,升级后该字段变为以H8格式处理0,触发上述警告。尝试修改default分支强制使用i格式处理,但导致原本应使用H8格式的字段(如值16000000、0d000000)也被错误转换为i格式,结果混乱。咨询是否需要新增H8格式处理逻辑,并在switch中单独设置case分支解决问题。

输出对比

PHP 8.2.12 输出

i 0
i 0
H8 0 << 异常结果

Warning: pack(): Type H: not enough characters in string in C:\xampp\htdocs\services\parser\include.php on line 683
H8 16000000
H8 0d000000

原PHP 6.0.0-dev 输出

i 0
i 0
i 0 << 原处理结果
H8 16000000
H8 0d000000

核心parser函数代码

function parser($output, $input, $indexing, $blockheader)
{
    global $typearr, $stop_error_msg;
    $filearray = file($input, FILE_SKIP_EMPTY_LINES);
    $filesize = sizeof($filearray);
    $struct = explode("\t", trim($filearray[0]));
    $col_names = explode("\t", trim($filearray[1]));
    if ($blockheader == 1)
    {
        // Define or replace strsize() function
        // $block = strsize($struct);
        $block = count($struct); // Example replacement
        if ($indexing == 1)
            $block += 4;
        $filesize_bin = pack("i", ($filesize - 2));
        fwrite($output, $filesize_bin);
        $blockbin = pack("i", $block);
        fwrite($output, $blockbin);
    }
    for ($i = 2; $i < $filesize; $i++)
    {
        $store = 0;
        $temporary = explode("\t", trim($filearray[$i]));
        if ($indexing == 1)
            fwrite($output, pack("i", $i - 2));
        for ($st = 0; $st < count($struct) - 1; $st++)
        {
            if ($temporary[$st] == '')
            {
                $stop_error_msg .= "<br>Empty cell. Probably mistake at excel file:<br>ROW:".($i+1)."<br>COLUMN:".($st+1)."<br>NAME:".$col_names[$st]."<br>DATA:".$temporary[$st];
                return false;
            }

            if (stristr($struct[$st], 'string[') !== false)
            {
                preg_match("/^(string\[)?([\d]+)/", $struct[$st], $str_ret);
                if (strlen($temporary[$st]) >= $str_ret[2])
                {
                    $temporary[$st] = substr($temporary[$st], 0, $str_ret[2] - 1);
                    echo "<br>Warning! Text overflow. Tail of string had been cut: ROW:".($i+1)." COLUMN:".($st+1)." NAME:".$col_names[$st]." DATA:'".$temporary[$st]. "' SIZE:". $str_ret[2];
                }
                $resulthex = pack("a".$str_ret[2], trim(str_replace("\x22\x22\x22\x22", "\x22\x22", $temporary[$st]), "\x22"));
                fwrite($output, $resulthex);
                continue;
            }
            $type = $typearr[$struct[$st]]['type'];
            switch($type)
            {
                case "xeh":
                    $resulthex = xeh($temporary[$st]);
                    break;
                case "xeh64":
                    $resulthex = xeh64($temporary[$st]);
                    break;
                case "clcode":
                    $resulthex = clcode($temporary[$st]);
                    break;
                case "exclcode":
                    if(($resulthex = exclcode($temporary[$st])) === false)
                    {
                        $stop_error_msg .= " Probably mistake at excel file:<br>ROW:".($i+1)."<br>COLUMN:".($st+1)."<br>NAME:".$col_names[$st]."<br>DATA:".$temporary[$st];
                        return false;
                    }
                    break;
                case "ccode":
                    $resulthex = ccode($temporary[$st]);
                    break;
                case "f":
                case "d":
                    $trans = array("," => ".");
                    $resulthex = pack($type, strtr("" . $temporary[$st] . "", $trans));
                    break;
                case "bulltype":
                    if(($resulthex = bulltype($temporary[$st])) === false)
                    {
                        $stop_error_msg .= " Probably mistake at excel file:<br>ROW:".($i+1)."<br>COLUMN:".($st+1)."<br>NAME:".$col_names[$st]."<br>DATA:".$temporary[$st];
                        return false;
                    }
                    break;
                case "bttype":
                    if(($resulthex = bttype($temporary[$st])) === false)
                    {
                        $stop_error_msg .= " Probably mistake at excel file:<br>ROW:".($i+1)."<br>COLUMN:".($st+1)."<br>NAME:".$col_names[$st]."<br>DATA:".$temporary[$st];
                        return false;
                    }
                    break;
                case "effbttype":
                    if(($resulthex = effbttype($temporary[$st])) === false)
                    {
                        $stop_error_msg .= " Probably mistake at excel file:<br>ROW:".($i+1)."<br>COLUMN:".($st+1)."<br>NAME:".$col_names[$st]."<br>DATA:".$temporary[$st];
                        return false;
                    }
                    break;
                case "stb":
                    if(($resulthex = stb($temporary[$st])) === false)
                    {
                        $stop_error_msg .= " Probably mistake at excel file:<br>ROW:".($i+1)."<br>COLUMN:".($st+1)."<br>NAME:".$col_names[$st]."<br>DATA:".$temporary[$st];
                        return false;
                    }
                    break;
                case "stb4":
                    if(($resulthex = stb4($temporary[$st])) === false)
                    {
                        $stop_error_msg .= " Probably mistake at excel file:<br>ROW:".($i+1)."<br>COLUMN:".($st+1)."<br>NAME:".$col_names[$st]."<br>DATA:".$temporary[$st];
                        return false;
                    }
                    break;
                case "stb12":
                    if(($resulthex = stb12($temporary[$st])) === false)
                    {
                        $stop_error_msg .= " Probably mistake at excel file:<br>ROW:".($i+1)."<br>COLUMN:".($st+1)."<br>NAME:".$col_names[$st]."<br>DATA:".$temporary[$st];
                        return false;
                    }
                    break;
                case "stb16":
                    if(($resulthex = stb16($temporary[$st])) === false)
                    {
                        $stop_error_msg .= " Probably mistake at excel file:<br>ROW:".($i+1)."<br>COLUMN:".($st+1)."<br>NAME:".$col_names[$st]."<br>DATA:".$temporary[$st];
                        return false;
                    }
                    break;
                case "res":
                    $resulthex = resource($temporary[0]);
                    break;
                case "qitid":
                    $resulthex = qitid($temporary[$st]);
                    break;
                case "lqitem":
                    $resulthex = lqitem($temporary[$st]);
                    break;
                case "store":
                    if(($resulthex = store($temporary[$st], $store, $temporary[10])) === false)
                    {
                        $stop_error_msg .= " Probably mistake at excel file:<br>ROW:".($i+1)."<br>COLUMN:".($st+1)."<br>NAME:".$col_names[$st]."<br>DATA:".$temporary[$st];
                        return false;
                    }
                    $store++;
                    break;
                case "qcode":
                    $resulthex = qcode($temporary[$st]);
                    break;
                case "spcode":
                    $resulthex = spcode($temporary[$st]);
                    break;
                case "text":
                    $len = strlen($temporary[$st]);
                    $len = $len + 1;
                    $resulthex=pack("a".$len, $temporary[$st]);
                    $plen=pack("i", $len);
                    fwrite($output, $plen);
                    break;
                case "param":
                    if(($resulthex = param($temporary[$st], $temporary[$st+1])) === false)
                    {
                        $stop_error_msg .= " Probably mistake at excel file:<br>ROW:".($i+1)."<br>COLUMN:".($st+1)."<br>NAME:".$col_names[$st]."<br>DATA:".$temporary[$st];
                        return false;
                    }
                    $st++;
                    break;
                default:
                    echo $type." ".$temporary[$st]."<br>";
                    $resulthex = pack($type, $temporary[$st]); # error indication is in this script
            }
            if(!empty($err_arr) && isset($err_arr['message']) && stripos($err_arr['message'], 'function.date') !== false) {
                $stop_error_msg .= "<br>Pack error. Probably mistake at excel file:<br>ROW:".($i+1)."<br>COLUMN:".($st+1)."<br>NAME:".$col_names[$st]."<br>DATA:".$temporary[$st];
                return false;
            }
            fwrite($output, $resulthex);
        }
    }
    return true;
}

修改尝试及结果

修改后的default分支代码

default:
   echo "i " . $temporary[$st] . "<br>";
   $resulthex = pack("i", $temporary[$st]); # error indication is in this script

修改后输出

i0
i0
i0 << 异常结果
i16000000 << 错误转换为i格式
i0d000000 << 错误转换为i格式

解决方案建议

需要在switch分支中单独添加case "H8"的处理逻辑,针对十六进制字符串长度不足8位的情况做补零处理,同时保留原有的格式映射逻辑,避免混淆不同类型的字段:

switch($type)
{
    // ... 保留原有所有case分支不变
    case "H8":
        // 将输入值补零到8位十六进制字符,确保pack函数不会报错
        $hex_value = str_pad($temporary[$st], 8, '0', STR_PAD_LEFT);
        echo "H8 " . $hex_value . "<br>";
        $resulthex = pack("H8", $hex_value);
        break;
    default:
        echo $type." ".$temporary[$st]."<br>";
        $resulthex = pack($type, $temporary[$st]);
}

处理效果说明

  • 对于值为0的H8类型字段,会被补全为00000000,执行pack("H8")时不会触发警告
  • 原本应使用H8格式的16000000、0d000000会保持原有格式处理,不会被错误转换为i格式
  • 原i格式字段依然会按default分支(当type为"i"时)正常处理

另外需确认$typearr中的类型映射是否正确,确保需要用i格式的字段对应的type值为"i",需要用H8格式的字段对应的type值为"H8",避免类型映射错误导致的兼容问题。


内容的提问来源于stack exchange,提问作者Willy Sudwihartono

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 20:02:01