Check to see if a string is serialized?

前端 未结 11 1527
情歌与酒
情歌与酒 2020-11-29 17:16

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

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

相关标签:
11条回答
  • 2020-11-29 17:53

    Optimizing Pascal MARTIN's response

    /**
     * Check if a string is serialized
     * @param string $string
     */
    public static function is_serial($string) {
        return (@unserialize($string) !== false);
    }
    
    0 讨论(0)
  • 2020-11-29 17:54

    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 :)

    <?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;
    }
    
    0 讨论(0)
  • 2020-11-29 17:54

    build in to a function

    function isSerialized($value)
    {
       return preg_match('^([adObis]:|N;)^', $value);
    }
    
    0 讨论(0)
  • 2020-11-29 17:58

    see the wordpress function is_serialized

    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;
    

    }

    0 讨论(0)
  • 2020-11-29 18:02

    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));
        }
    
    ?>
    
    0 讨论(0)
  • 2020-11-29 18:06

    I'd say, try to unserialize it ;-)

    Quoting the manual :

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

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

    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 :-(

    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 :

    $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.

    0 讨论(0)
提交回复
热议问题