php 检查字符串是否已序列化?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1369936/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 02:13:49  来源:igfitidea点击:

Check to see if a string is serialized?

phpserialization

提问by Dang

What's the best way to determine whether or not a string is the result of the serialize()function?

确定字符串是否为serialize()函数结果的最佳方法是什么?

https://www.php.net/manual/en/function.serialize

https://www.php.net/manual/en/function.serialize

回答by Pascal MARTIN

I'd say, try to unserializeit ;-)

我会说,尝试unserialize一下;-)

Quoting the manual :

引用手册:

In case the passed string is not unserializeable, FALSE is returned and E_NOTICE is issued.

如果传递的字符串不是不可序列化的,则返回 FALSE 并发出 E_NOTICE。

So, you have to check if the return value is falseor not (with ===or !==, to be sure not to have any problem with 0or nullor anything that equals to false, I'd say).

所以,你必须检查返回值是false或不是(有===!==,以确保不会有任何问题0null或任何等于false,我会说)

Just beware the notice : you might want/need to use the @ operator.

请注意通知:您可能想要/需要使用@ 运算符

For instance :

例如 :

$str = 'hjkl';
$data = @unserialize($str);
if ($data !== false) {
    echo "ok";
} else {
    echo "not ok";
}

Will get you :

会让你:

not ok


EDIT : Oh, and like @Peter said (thanks to him!), you might run into trouble if you are trying to unserialize the representation of a boolean false :-(


编辑:哦,就像@Peter 说的(感谢他!),如果您试图反序列化布尔 false 的表示,您可能会遇到麻烦:-(

So, checking that your serialized string is not equal to "b:0;" might be helpful too ; something like this should do the trick, I suppose :

因此,检查您的序列化字符串是否不等于“ b:0;”也可能会有所帮助;我想这样的事情应该可以解决问题:

$data = @unserialize($str);
if ($str === 'b:0;' || $data !== false) {
    echo "ok";
} else {
    echo "not ok";
}

testing that special case before trying to unserialize would be an optimization -- but probably not that usefull, if you don't often have a false serialized value.

在尝试反序列化之前测试这种特殊情况将是一种优化——但可能没有那么有用,如果你不经常有一个错误的序列化值。

回答by Brandon Wamboldt

I didn't write this code, it's from WordPress actually. Thought I'd include it for anybody interested, it might be overkill but it works :)

这段代码不是我写的,它实际上来自 WordPress。以为我会为任何感兴趣的人提供它,这可能有点矫枉过正,但它有效:)

<?php
function is_serialized( $data ) {
    // if it isn't a string, it isn't serialized
    if ( !is_string( $data ) )
        return false;
    $data = trim( $data );
    if ( 'N;' == $data )
        return true;
    if ( !preg_match( '/^([adObis]):/', $data, $badions ) )
        return false;
    switch ( $badions[1] ) {
        case 'a' :
        case 'O' :
        case 's' :
            if ( preg_match( "/^{$badions[1]}:[0-9]+:.*[;}]$/s", $data ) )
                return true;
            break;
        case 'b' :
        case 'i' :
        case 'd' :
            if ( preg_match( "/^{$badions[1]}:[0-9.E-]+;$/", $data ) )
                return true;
            break;
    }
    return false;
}

回答by SoN9ne

Optimizing Pascal MARTIN's response

优化 Pascal MARTIN 的响应

/**
 * Check if a string is serialized
 * @param string $string
 */
public static function is_serial($string) {
    return (@unserialize($string) !== false);
}

回答by Hazem Noor

If the $stringis a serialized falsevalue, ie $string = 'b:0;'SoN9ne's function returns false, it's wrong

如果$string是序列化false值,即$string = 'b:0;'SoN9ne的函数返回false,则错误

so the function would be

所以功能是

/**
 * Check if a string is serialized
 *
 * @param string $string
 *
 * @return bool
 */
function is_serialized_string($string)
{
    return ($string == 'b:0;' || @unserialize($string) !== false);
}

回答by Peter Bailey

Despite Pascal MARTIN's excellent answer, I was curious if you could approach this another way, so I did this just as a mental exercise

尽管 Pascal MARTIN 的回答很好,但我很好奇你是否可以用另一种方式来解决这个问题,所以我这样做只是作为一种心理锻炼

<?php

ini_set( 'display_errors', 1 );
ini_set( 'track_errors', 1 );
error_reporting( E_ALL );

$valueToUnserialize = serialize( false );
//$valueToUnserialize = "a"; # uncomment this for another test

$unserialized = @unserialize( $valueToUnserialize );

if ( FALSE === $unserialized && isset( $php_errormsg ) && strpos( $php_errormsg, 'unserialize' ) !== FALSE )
{
  echo 'Value could not be unserialized<br>';
  echo $valueToUnserialize;
} else {
  echo 'Value was unserialized!<br>';
  var_dump( $unserialized );
}

And it actually works. The only caveat is that it will likely break if you have a registered error handler because of how $php_errormsg works.

它确实有效。唯一需要注意的是,如果您注册了错误处理程序,它可能会因为$php_errormsg 的工作方式而中断

回答by chaos

$data = @unserialize($str);
if($data !== false || $str === 'b:0;')
    echo 'ok';
else
    echo "not ok";

Correctly handles the case of serialize(false). :)

正确处理serialize(false). :)

回答by RossW

build in to a function

内置到函数中

function isSerialized($value)
{
   return preg_match('^([adObis]:|N;)^', $value);
}

回答by ingenious

There is WordPress solution: (detail is here)

有WordPress解决方案:(详细信息在这里)

    function is_serialized($data, $strict = true)
    {
        // if it isn't a string, it isn't serialized.
        if (!is_string($data)) {
            return false;
        }
        $data = trim($data);
        if ('N;' == $data) {
            return true;
        }
        if (strlen($data) < 4) {
            return false;
        }
        if (':' !== $data[1]) {
            return false;
        }
        if ($strict) {
            $lastc = substr($data, -1);
            if (';' !== $lastc && '}' !== $lastc) {
                return false;
            }
        } else {
            $semicolon = strpos($data, ';');
            $brace = strpos($data, '}');
            // Either ; or } must exist.
            if (false === $semicolon && false === $brace)
                return false;
            // But neither must be in the first X characters.
            if (false !== $semicolon && $semicolon < 3)
                return false;
            if (false !== $brace && $brace < 4)
                return false;
        }
        $token = $data[0];
        switch ($token) {
            case 's' :
                if ($strict) {
                    if ('"' !== substr($data, -2, 1)) {
                        return false;
                    }
                } elseif (false === strpos($data, '"')) {
                    return false;
                }
            // or else fall through
            case 'a' :
            case 'O' :
                return (bool)preg_match("/^{$token}:[0-9]+:/s", $data);
            case 'b' :
            case 'i' :
            case 'd' :
                $end = $strict ? '$' : '';
                return (bool)preg_match("/^{$token}:[0-9.E-]+;$end/", $data);
        }
        return false;
    }

回答by Bj?rn3

/**
 * some people will look down on this little puppy
 */
function isSerialized($s){
if(
    stristr($s, '{' ) != false &&
    stristr($s, '}' ) != false &&
    stristr($s, ';' ) != false &&
    stristr($s, ':' ) != false
    ){
    return true;
}else{
    return false;
}

}

回答by Daniel Lichtenberg

This works fine for me

这对我来说很好用

<?php

function is_serialized($data){
    return (is_string($data) && preg_match("#^((N;)|((a|O|s):[0-9]+:.*[;}])|((b|i|d):[0-9.E-]+;))$#um", $data));
    }

?>