개발 꿀팁/PHP

php unserialize false 해결 방법 반환

Jammie 2022. 8. 17. 16:56
반응형

php unserialize false 해결 방법 반환



php serialize와 unseria 제공lize(역계열화) 방법.

serialize를 사용하여 serialize한 후 unserializ를 사용합니다e역직렬화하면 원래의 데이터를 얻을 수 있다

 

<?php
$arr = array(
    'name' => 'fdipzone',
    'gender' => 'male'
);
 
$str = serialize($arr); //직렬화
echo 'serialize str:'.$str."\r\n\r\n";
 
$content = unserialize($str); //역계열화
echo "unserialize str:\r\n";
var_dump($content);
?>

출력:

serialize str:a:2:{s:4:"name";s:8:"fdipzone";s:6:"gender";s:4:"male";}

unserialize str:
array(2) {
  ["name"]=>
  string(8) "fdipzone"
  ["gender"]=>
  string(4) "male"
}

하지만 다음 예에서는 역직렬화가 false를 반환한다

<?php
$str = 'a:9:{s:4:"time";i:1405306402;s:4:"name";s:6:"신천";s:5:"url";s:1:"-";s:4:"word";s:1:"-";s:5:"rpage";s:29:"http://www.baidu.com/test.html";s:5:"cpage";s:1:"-";s:2:"ip";s:15:"117.151.180.150";s:7:"ip_city";s:31:"중국 베이징시 베이징시이동하다";s:4:"miao";s:1:"5";}';
var_dump(unserialize($str)); // bool(false)
?>

직렬화된 문자열을 검사한 결과 두 곳에서 문제가 발견되었습니다.
s:5:url

s:29:"http://ㅋㅋㅋㅋㅋ.baidu.com/test.html"

이 두 곳은 마땅히 해야 한다

s:3:url

s:30:"http://ww.baidu.com/test.html"


이런 문제가 발생한 원인은 데이터를 직렬화할 때의 부호화와 역계열이다인코딩이 일치하지 않아 발생합니다.예를 들어 데이터베이스는 latin1과 UTF-8의 문자 길이가 다르다.

또한 문제가 발생할 수 있는 것은 홀짝따옴표, ascii 문자이다.'\0'은 '로 해석됩니다.\0'\0C에서 문자열의 끝자는 chr(0)과 같으며, 잘못 해석하여 2자를 계산하였습니다.

\r 길이 계산에도 문제가 생길 수 있습니다.



해결 방법은 다음과 같습니다

// utf8
function mb_unserialize($serial_str) {
    $serial_str= preg_replace('!s:(\d+):"(.*?)";!se', "'s:'.strlen('$2').':\"$2\";'", $serial_str );
    $serial_str= str_replace("\r", "", $serial_str);
    return unserialize($serial_str);
}
 
// ascii
function asc_unserialize($serial_str) {
    $serial_str = preg_replace('!s:(\d+):"(.*?)";!se', '"s:".strlen("$2").":\"$2\";"', $serial_str );
    $serial_str= str_replace("\r", "", $serial_str);
    return unserialize($serial_str);
}

예:

echo '<meta http-equiv="content-type" content="text/html; charset=utf-8">';
 
// utf8
function mb_unserialize($serial_str) {
    $serial_str= preg_replace('!s:(\d+):"(.*?)";!se', "'s:'.strlen('$2').':\"$2\";'", $serial_str );
    $serial_str= str_replace("\r", "", $serial_str);
    return unserialize($serial_str);
}
 
$str = 'a:9:{s:4:"time";i:1405306402;s:4:"name";s:6:"신천";s:5:"url";s:1:"-";s:4:"word";s:1:"-";s:5:"rpage";s:29:"http://www.baidu.com/test.html";s:5:"cpage";s:1:"-";s:2:"ip";s:15:"117.151.180.150";s:7:"ip_city";s:31:"중국 베이징시 베이징시이동하다";s:4:"miao";s:1:"5";}';
 
var_dump(unserialize($str));    // false
 
var_dump(mb_unserialize($str)); // 정확하다

\r를 필터링하는 mb_unserialize 메소드를 사용하면 역직렬화에 성공할 수 있다

사용하다unserialize
bool(false)

사용하다mb_unserialize
array(9) {
  ["time"]=>
  int(1405306402)
  ["name"]=>
  string(6) "신천"
  ["url"]=>
  string(1) "-"
  ["word"]=>
  string(1) "-"
  ["rpage"]=>
  string(30) "http://www.baidu.com/test.html"
  ["cpage"]=>
  string(1) "-"
  ["ip"]=>
  string(15) "117.151.180.150"
  ["ip_city"]=>
  string(31) "중국 베이징시 베이징시이동하다"
  ["miao"]=>
  string(1) "5"
}

 

반응형