복붙노트

unserialize () [function.unserialize] : 오프셋시 오류

PHP

unserialize () [function.unserialize] : 오프셋시 오류

이미지 업로드 플러그인이있는 Hotaru CMS를 사용하고 있는데 이미지를 게시물에 첨부하려고하면이 오류가 발생합니다. 그렇지 않으면 오류가 없습니다.

문제가되는 코드 (**에 대한 오류 지점) :

/**
     * Retrieve submission step data
     *
     * @param $key - empty when setting
     * @return bool
     */
    public function loadSubmitData($h, $key = '')
    {
        // delete everything in this table older than 30 minutes:
        $this->deleteTempData($h->db);

        if (!$key) { return false; }

        $cleanKey = preg_replace('/[^a-z0-9]+/','',$key);
        if (strcmp($key,$cleanKey) != 0) {
            return false;
        } else {
            $sql = "SELECT tempdata_value FROM " . TABLE_TEMPDATA . " WHERE tempdata_key = %s ORDER BY tempdata_updatedts DESC LIMIT 1";
            $submitted_data = $h->db->get_var($h->db->prepare($sql, $key));
            **if ($submitted_data) { return unserialize($submitted_data); } else { return false; }** 
        }
    }

테이블의 데이터, 마지막 비트가 이미지 정보를 가지고 있음을 주목하라, 나는 PHP 전문가가 아니므로 당신들 / 할아버지가 생각할지도 모르는 것이 궁금하다.

tempdata_value :

a:10:{s:16:"submit_editorial";b:0;s:15:"submit_orig_url";s:13:"www.bbc.co.uk";s:12:"submit_title";s:14:"No title found";s:14:"submit_content";s:12:"dnfsdkfjdfdf";s:15:"submit_category";i:2;s:11:"submit_tags";s:3:"bbc";s:9:"submit_id";b:0;s:16:"submit_subscribe";i:0;s:15:"submit_comments";s:4:"open";s:5:"image";s:19:"C:fakepath100.jpg";}

편집 : 내가 serialize 비트를 찾은 것 같아요 ...

/**
     * Save submission step data
     *
     * @return bool
     */
    public function saveSubmitData($h)
    {
        // delete everything in this table older than 30 minutes:
        $this->deleteTempData($h->db);

        $sid = preg_replace('/[^a-z0-9]+/i', '', session_id());
        $key = md5(microtime() . $sid . rand());
        $sql = "INSERT INTO " . TABLE_TEMPDATA . " (tempdata_key, tempdata_value, tempdata_updateby) VALUES (%s,%s, %d)";
        $h->db->query($h->db->prepare($sql, $key, serialize($h->vars['submitted_data']), $h->currentUser->id));
        return $key;
    }

해결법

  1. ==============================

    1.unserialize () [function.unserialize] : 잘못된 길이 때문에 잘못된 직렬화 데이터에 대한 오프셋 오류가 발생했습니다.

    unserialize () [function.unserialize] : 잘못된 길이 때문에 잘못된 직렬화 데이터에 대한 오프셋 오류가 발생했습니다.

    빠른 수정

    당신이 할 수있는 것은 직렬화 된 배열에서 요소의 길이를 다시 계산하는 것입니다.

    현재 직렬화 된 데이터입니다.

    $data = 'a:10:{s:16:"submit_editorial";b:0;s:15:"submit_orig_url";s:13:"www.bbc.co.uk";s:12:"submit_title";s:14:"No title found";s:14:"submit_content";s:12:"dnfsdkfjdfdf";s:15:"submit_category";i:2;s:11:"submit_tags";s:3:"bbc";s:9:"submit_id";b:0;s:16:"submit_subscribe";i:0;s:15:"submit_comments";s:4:"open";s:5:"image";s:19:"C:fakepath100.jpg";}';
    

    재 계산이없는 예

    var_dump(unserialize($data));
    

    산출

    Notice: unserialize() [function.unserialize]: Error at offset 337 of 338 bytes
    

    재 계산

    $data = preg_replace('!s:(\d+):"(.*?)";!e', "'s:'.strlen('$2').':\"$2\";'", $data);
    var_dump(unserialize($data));
    

    산출

    array
      'submit_editorial' => boolean false
      'submit_orig_url' => string 'www.bbc.co.uk' (length=13)
      'submit_title' => string 'No title found' (length=14)
      'submit_content' => string 'dnfsdkfjdfdf' (length=12)
      'submit_category' => int 2
      'submit_tags' => string 'bbc' (length=3)
      'submit_id' => boolean false
      'submit_subscribe' => int 0
      'submit_comments' => string 'open' (length=4)
      'image' => string 'C:fakepath100.jpg' (length=17)
    

    추천 .. 나는

    이 종류의 빠른 수정 대신 ... 질문을 업데이트하는 조언을드립니다.

    ==================== 편집 1 ================ ===============

    오류

    오류는 C : \ fakepath \ 100.png가 C로 변환 된 이유 인 "작은 따옴표"대신 큰 따옴표를 사용하여 생성되었습니다. fakepath100.jpg

    오류를 수정하려면

    당신은 $ h-> vars [ 'submitted_data']를 바꿀 필요가 있습니다.

    바꾸다

     $h->vars['submitted_data']['image'] = "C:\fakepath\100.png" ;
    

     $h->vars['submitted_data']['image'] = 'C:\fakepath\100.png' ;
    

    추가 필터

    serialize를 호출하기 전에이 간단한 필터를 추가 할 수도 있습니다.

    function satitize(&$value, $key)
    {
        $value = addslashes($value);
    }
    
    array_walk($h->vars['submitted_data'], "satitize");
    

    UTF Characters를 사용하고 있다면 실행할 수도 있습니다.

     $h->vars['submitted_data'] = array_map("utf8_encode",$h->vars['submitted_data']);
    

    향후 직렬화 된 데이터에서 문제를 감지하는 방법

      findSerializeError ( $data1 ) ;
    

    산출

    Diffrence 9 != 7
        -> ORD number 57 != 55
        -> Line Number = 315
        -> Section Data1  = pen";s:5:"image";s:19:"C:fakepath100.jpg
        -> Section Data2  = pen";s:5:"image";s:17:"C:fakepath100.jpg
                                                ^------- The Error (Element Length)
    

    findSerializeError 함수

    function findSerializeError($data1) {
        echo "<pre>";
        $data2 = preg_replace ( '!s:(\d+):"(.*?)";!e', "'s:'.strlen('$2').':\"$2\";'",$data1 );
        $max = (strlen ( $data1 ) > strlen ( $data2 )) ? strlen ( $data1 ) : strlen ( $data2 );
    
        echo $data1 . PHP_EOL;
        echo $data2 . PHP_EOL;
    
        for($i = 0; $i < $max; $i ++) {
    
            if (@$data1 {$i} !== @$data2 {$i}) {
    
                echo "Diffrence ", @$data1 {$i}, " != ", @$data2 {$i}, PHP_EOL;
                echo "\t-> ORD number ", ord ( @$data1 {$i} ), " != ", ord ( @$data2 {$i} ), PHP_EOL;
                echo "\t-> Line Number = $i" . PHP_EOL;
    
                $start = ($i - 20);
                $start = ($start < 0) ? 0 : $start;
                $length = 40;
    
                $point = $max - $i;
                if ($point < 20) {
                    $rlength = 1;
                    $rpoint = - $point;
                } else {
                    $rpoint = $length - 20;
                    $rlength = 1;
                }
    
                echo "\t-> Section Data1  = ", substr_replace ( substr ( $data1, $start, $length ), "<b style=\"color:green\">{$data1 {$i}}</b>", $rpoint, $rlength ), PHP_EOL;
                echo "\t-> Section Data2  = ", substr_replace ( substr ( $data2, $start, $length ), "<b style=\"color:red\">{$data2 {$i}}</b>", $rpoint, $rlength ), PHP_EOL;
            }
    
        }
    
    }
    

    데이터베이스에 저장하는 더 좋은 방법

    $toDatabse = base64_encode(serialize($data));  // Save to database
    $fromDatabase = unserialize(base64_decode($data)); //Getting Save Format 
    
  2. ==============================

    2.나는 사람들이 위의 "올바른"대답을 사용하는 것을 보길 희망한다.

    나는 사람들이 위의 "올바른"대답을 사용하는 것을 보길 희망한다.

    PHP 5.5부터 preg_replace ()의 / e 수정자는 완전히 사용되지 않으며 위의 preg_match는 오류가 발생합니다. php 문서는 대신에 preg_match_callback을 사용할 것을 권장합니다.

    위의 제안 된 preg_match 대신 다음 솔루션을 찾으십시오.

    $fixed_data = preg_replace_callback ( '!s:(\d+):"(.*?)";!', function($match) {      
        return ($match[1] == strlen($match[2])) ? $match[0] : 's:' . strlen($match[2]) . ':"' . $match[2] . '";';
    },$bad_data );
    
  3. ==============================

    3.직렬화 된 데이터를 부적절하게 데이터베이스에 저장했기 때문에 unserialize ()가 실패한 다른 이유가 있습니다. 공식 설명은 여기를 참조하십시오. serialize ()는 바이너리 데이터를 반환하고 php 변수는 메소드 인코딩을 신경 쓰지 않으므로 TEXT, VARCHAR ()에 넣으면이 오류가 발생합니다.

    직렬화 된 데이터를 부적절하게 데이터베이스에 저장했기 때문에 unserialize ()가 실패한 다른 이유가 있습니다. 공식 설명은 여기를 참조하십시오. serialize ()는 바이너리 데이터를 반환하고 php 변수는 메소드 인코딩을 신경 쓰지 않으므로 TEXT, VARCHAR ()에 넣으면이 오류가 발생합니다.

    해결책 : 직렬화 된 데이터를 BLOB에 테이블에 저장하십시오.

  4. ==============================

    4.빠른 수정

    빠른 수정

    직렬화 된 배열에서 요소의 길이를 다시 계산합니다 - 그러나 (preg_replace)를 사용하지 마십시오 (더 이상 사용되지 않습니다) - preg_replace_callback을 더 잘 사용하십시오 :

    $data = preg_replace_callback('!s:(\d+):"(.*?)";!', function($m) { return 's:'.mb_strlen($m[2]).':"'.$m[2].'";'; }, $data);
    
  5. ==============================

    5.이 오류는 문자 집합이 잘못 되었기 때문에 발생합니다.

    이 오류는 문자 집합이 잘못 되었기 때문에 발생합니다.

    열린 태그 뒤에 charset 설정 :

    header('Content-Type: text/html; charset=utf-8');
    

    그리고 데이터베이스에 charset utf8을 설정하십시오.

    mysql_query("SET NAMES 'utf8'");
    
  6. ==============================

    6.공용 함수 unserializeKeySkills ($ 문자열) {

    공용 함수 unserializeKeySkills ($ 문자열) {

        $output = array();
        $string = trim(preg_replace('/\s\s+/', ' ',$string));
        $string = preg_replace_callback('!s:(\d+):"(.*?)";!', function($m) { return 's:'.strlen($m[2]).':"'.$m[2].'";'; }, utf8_encode( trim(preg_replace('/\s\s+/', ' ',$string)) ));
        try {
            $output =  unserialize($string);
        } catch (\Exception $e) {
            \Log::error("unserialize Data : " .print_r($string,true));
        }
        return $output;
    }
    
  7. ==============================

    7.멀티 바이트 문자 처리 기능을 사용하여 다음 기능을 사용하여 깨진 직렬화 문자열을 수정할 수 있습니다.

    멀티 바이트 문자 처리 기능을 사용하여 다음 기능을 사용하여 깨진 직렬화 문자열을 수정할 수 있습니다.

    function repairSerializeString($value)
    {
    
        $regex = '/s:([0-9]+):"(.*?)"/';
    
        return preg_replace_callback(
            $regex, function($match) {
                return "s:".mb_strlen($match[2]).":\"".$match[2]."\""; 
            },
            $value
        );
    }
    
  8. ==============================

    8.

    $badData = 'a:2:{i:0;s:16:"as:45:"d";
    Is \n";i:1;s:19:"as:45:"d";
    Is \r\n";}';
    

    제안 된 regexes를 사용하여 깨진 serialize 문자열을 고칠 수 없습니다.

    $data = preg_replace('!s:(\d+):"(.*?)";!e', "'s:'.strlen('$2').':\"$2\";'", $badData);
    var_dump(@unserialize($data)); // Output: bool(false)
    
    // or
    
    $data = preg_replace_callback(
        '/s:(\d+):"(.*?)";/',
        function($m){
            return 's:' . mb_strlen($m[2]) . ':"' . $m[2] . '";';
        },
        $badData
    );
    var_dump(@unserialize($data)); // Output: bool(false)
    

    다음 정규식을 사용하여 깨진 serialize 문자열을 수정할 수 있습니다.

    $data = preg_replace_callback(
        '/(?<=^|\{|;)s:(\d+):\"(.*?)\";(?=[asbdiO]\:\d|N;|\}|$)/s',
        function($m){
            return 's:' . mb_strlen($m[2]) . ':"' . $m[2] . '";';
        },
        $badData
    );
    
    var_dump(@unserialize($data));
    

    산출

    array(2) {
      [0] =>
      string(17) "as:45:"d";
    Is \n"
      [1] =>
      string(19) "as:45:"d";
    Is \r\n"
    }
    

    또는

    array(2) {
      [0] =>
      string(16) "as:45:"d";
    Is \n"
      [1] =>
      string(18) "as:45:"d";
    Is \r\n"
    }
    
  9. ==============================

    9.공식 문서는 거짓을 반환하고 E_NOTICE를 설정해야한다고 말합니다.

    공식 문서는 거짓을 반환하고 E_NOTICE를 설정해야한다고 말합니다.

    하지만 오류가 발생하면 오류보고는 E_NOTICE에 의해 실행되도록 설정됩니다.

    여기에 unserialize에 의해 반환 된 false를 탐지 할 수있는 픽스가있다.

    $old_err=error_reporting(); 
    error_reporting($old_err & ~E_NOTICE);
    $object = unserialize($serialized_data);
    error_reporting($old_err);
    

    base64 인 코드 / 디코드 사용을 고려할 수 있습니다.

    $string=base64_encode(serialize($obj));
    unserialize(base64_decode($string));
    
  10. ==============================

    10.제 경우에는 직렬화 된 데이터를 MySQL DB의 BLOB 필드에 저장하고있었습니다.이 데이터는 전체 값을 포함 할 정도로 크지 않았고 잘려났습니다. 그러한 문자열은 분명히 비 직렬화 될 수 없습니다. 해당 필드를 MEDIUMBLOB로 변환하면 문제가 사라집니다. 또한 ROW_FORMAT 테이블 옵션을 DYNAMIC 또는 COMPRESSED로 전환해야 할 수도 있습니다.

    제 경우에는 직렬화 된 데이터를 MySQL DB의 BLOB 필드에 저장하고있었습니다.이 데이터는 전체 값을 포함 할 정도로 크지 않았고 잘려났습니다. 그러한 문자열은 분명히 비 직렬화 될 수 없습니다. 해당 필드를 MEDIUMBLOB로 변환하면 문제가 사라집니다. 또한 ROW_FORMAT 테이블 옵션을 DYNAMIC 또는 COMPRESSED로 전환해야 할 수도 있습니다.

  11. ==============================

    11.이 페이지에서 성공하지 못한 채 몇 가지 시도를 한 후에는 페이지 소스를 살펴보고 직렬화 된 문자열의 모든 인용 부호가 html 엔티티로 대체되었다고 언급했습니다. 이러한 개체를 디코딩하면 많은 두통을 피할 수 있습니다.

    이 페이지에서 성공하지 못한 채 몇 가지 시도를 한 후에는 페이지 소스를 살펴보고 직렬화 된 문자열의 모든 인용 부호가 html 엔티티로 대체되었다고 언급했습니다. 이러한 개체를 디코딩하면 많은 두통을 피할 수 있습니다.

    $myVar = html_entity_decode($myVar);
    
  12. ==============================

    12.데이터 정렬 유형을 utf8_unicode_ci로 변경해야하며 문제가 해결됩니다.

    데이터 정렬 유형을 utf8_unicode_ci로 변경해야하며 문제가 해결됩니다.

  13. ==============================

    13.이 문제의 또 다른 이유는 열 유형의 "페이로드"세션 테이블 일 수 있습니다. 세션에 거대한 데이터가있는 경우 텍스트 열이 충분하지 않습니다. MEDIUMTEXT 또는 LONGTEXT가 필요합니다.

    이 문제의 또 다른 이유는 열 유형의 "페이로드"세션 테이블 일 수 있습니다. 세션에 거대한 데이터가있는 경우 텍스트 열이 충분하지 않습니다. MEDIUMTEXT 또는 LONGTEXT가 필요합니다.

  14. ==============================

    14.나는 데이터를 unserializing하는 동안 같은 문제에 직면했다. 배열 값에 ", ', :,, 또는;이있는 경우 직렬화가 손상된다는 것을 알았습니다. 배열에 :을 제거하여 수정했습니다.

    나는 데이터를 unserializing하는 동안 같은 문제에 직면했다. 배열 값에 ", ', :,, 또는;이있는 경우 직렬화가 손상된다는 것을 알았습니다. 배열에 :을 제거하여 수정했습니다.

    누군가가 도움이되기를 바랍니다.

  15. from https://stackoverflow.com/questions/10152904/unserialize-function-unserialize-error-at-offset by cc-by-sa and MIT license