php 判断序列化,PHP如何检测字符串是否被序列化?

原文:

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

# Answer 1

4d350fd91e33782268f371d7edaa8a76.png

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.

# Answer 2

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

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;

}

# Answer 3

Optimizing Pascal MARTIN's response

/**

* Check if a string is serialized

* @param string $string

*/

public static function is_serial($string) {

return (@unserialize($string) !== false);

}

# Answer 4

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

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

}

# Answer 5

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

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
';

echo $valueToUnserialize;

} else {

echo 'Value was unserialized!
';

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.

# Answer 6

$data = @unserialize($str);

if($data !== false || $str === 'b:0;')

echo 'ok';

else

echo "not ok";

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

# Answer 7

build in to a function

function isSerialized($value)

{

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

}

# Answer 8

There is WordPress solution: (detail is here)

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;

}

# Answer 9

/**

* 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;

}

}

# Answer 10

This works fine for me

function is_serialized($data){

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

}

?>

# Answer 11

I prefer doing it that way:

if (is_array(unserialize($serialized_string))):

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值