एक गलत बाइट काउंट लंबाई के साथ दूषित धारावाहिक स्ट्रिंग की मरम्मत कैसे करें?


97

मैं इमेज अपलोड प्लगइन के साथ हॉटारू सीएमएस का उपयोग कर रहा हूं, अगर मुझे किसी पोस्ट में छवि संलग्न करने की कोशिश की जाती है, तो मुझे यह त्रुटि मिलती है, अन्यथा कोई त्रुटि नहीं है:

unserialize () [function.unserialize]: ऑफ़सेट में त्रुटि

आपत्तिजनक कोड (त्रुटि बिंदु ** के साथ लाइन में):

/**
     * 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";}

संपादित करें: मुझे लगता है कि मैंने क्रमबद्ध बिट प्राप्त किया है ...

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

3
मेरे लिए इस के लिए जल्दी ठीक serialize / unserialize से पहले base64_encode / decode का उपयोग कर रहा था। davidwalsh.name/php-serialize-unserialize-issues
वैलेंटाइन

1
मैं नहीं जानता कि क्यों, लेकिन मेरा @ @ के साथ हल,@unserialize($product->des_txtmopscol);
भावन राणा

2
@BhavinRana जोड़ना @त्रुटि को हल करने के लिए नहीं है, यह त्रुटि चुप करने वाला है - वास्तव में कुछ भी उस तकनीक के साथ "ठीक नहीं होता है"।
मिकमैकुसा

जवाबों:


218

unserialize() [function.unserialize]: Error at offsetinvalid serialization dataअमान्य लंबाई के कारण बकाया था

जल्दी ठीक

आप जो कर सकते हैं वह recalculating the lengthक्रमबद्ध सरणी में तत्वों का है

आप वर्तमान क्रमबद्ध डेटा

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

अनुशंसा .. I

इस तरह के त्वरित फिक्स का उपयोग करने के बजाय ... मैं आपको सलाह देता हूं कि आप इस प्रश्न को अपडेट करें

  • आप अपने डेटा को कैसे क्रमबद्ध कर रहे हैं

  • आप इसे कैसे सहेज रहे हैं ..

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

अतिरिक्त फ़िल्टर

क्रमबद्ध कॉल करने से पहले आप इस सरल फ़िल्टर को भी जोड़ सकते हैं

function satitize(&$value, $key)
{
    $value = addslashes($value);
}

array_walk($h->vars['submitted_data'], "satitize");

यदि आपके पास UTF अक्षर हैं तो आप भी चला सकते हैं

 $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 

1
बाबा, मैंने आपके अद्भुत findSerializeErrorकार्य का उपयोग किया और बहुत सी त्रुटियां पाईं। कृपया मेरे विषय
मैक्स कोरसेटस्की

1
base64डेटाबेस में जोड़ने से पहले अनुच्छेद पर उपयोग करें ... यह अशक्त चरित्र को संरक्षित करेगा
बाबा

1
यह डेटाबेस को बचाने का एक बेहतर तरीका नहीं है। यह है, जब तक आप डेटाबेस के उद्देश्य को पूरी तरह से उपेक्षित नहीं करना चाहते। आप एन्क्रिप्टेड मूल्यों के एक समूह में खोज कैसे करने जा रहे हैं? ब्लोट, ऊग का उल्लेख नहीं करना। उचित एन्कोडिंग उचित उत्तर है।
देजी

4
यदि PHP 5.5 का उपयोग कर रहे हैं, तो @ r00tAcc3ss उत्तर देखें! stackoverflow.com/a/21389439/1003020
विनीसियस गार्सिया

6
यदि आपको यह त्रुटि "preg_replace (): / e संशोधक अब समर्थित नहीं है, तो php7 में" बजाय preg_replace_callback का उपयोग करें - यह उत्तर stackoverflow.com/a/21389439/2034 पर
BenB

82

मेरे पास टिप्पणी करने के लिए पर्याप्त प्रतिष्ठा नहीं है, इसलिए मुझे आशा है कि यह लोग "सही" उत्तर का उपयोग करके देखते हैं:

चूंकि php 5.5 / e modifier in preg_replace () को पूरी तरह से हटा दिया गया है और ऊपर दिए गए 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
ऐसा लगता है कि पृष्ठ पर केवल एकमात्र उत्तर है जो वास्तव में पहले कैप्चर समूह को अच्छे उपयोग के लिए रखता है। जबकि समझदार प्रोग्रामिंग केवल प्रतिस्थापन करने के लिए जहां बाइट गिनती वास्तव में गलत है, यह समाधान कैश नहीं करता है strlen()और इसलिए अनावश्यक फ़ंक्शन कॉल करता है। व्यक्तिगत रूप से, मैं एक इनलाइन स्थिति को बहुत अधिक वर्बोज़ होने के लिए जोड़ता हूं, लेकिन यह स्निपेट अच्छे कारणों के लिए अच्छा काम कर रहा है।
मिकमैकुसा

4
इसने मेरे लिए निम्न रीगेक्स के '!s:(\d+):"(.*?)";!s'साथ (नई लाइनों को लेने के लिए एक अंत 's' के साथ काम किया )। नीचे दिए गए adilbo की टिप्पणी के लिए धन्यवाद।
अरनहोलो

13

एक और कारण unserialize()विफल हो गया है क्योंकि आपने अनुचित रूप से अनुक्रमित डेटा को डेटाबेस में डाल दिया है यहां आधिकारिक स्पष्टीकरण देखें । चूंकि serialize()बाइनरी डेटा और php वैरिएबल एन्कोडिंग विधियों की परवाह नहीं करते हैं, इसलिए इसे TEXT, VARCHAR () में डालने से यह त्रुटि होगी।

समाधान: अपनी तालिका में क्रमबद्ध डेटा को BLOB में संग्रहीत करें।


इसने मेरी समस्या को Laravel 5 में हल किया। मैंने स्ट्रिंग परिभाषा को स्ट्रिंग () से बाइनरी () में बदल दिया।
WNRosenberg 16

ओपी के प्रश्न में mysql कॉलम प्रकार का मुद्दा नहीं है। यह स्पष्ट रूप से imageमूल्य पर एक गलत बाइट गणना द्वारा दूषित है । आपका उत्तर ओपी के विशिष्ट प्रश्न से संबंधित नहीं है। : आप करने के लिए आपकी सलाह ले जाने के लिए इच्छा हो सकती है stackoverflow.com/q/5544749/2943403
mickmackusa

11

जल्दी ठीक

क्रमबद्ध सरणी में तत्वों की लंबाई को याद करते हुए - लेकिन इसका उपयोग न करें (preg_replace) यह पदावनत है - बेहतर उपयोग preg_replace_callback:

संपादित करें: नया संस्करण अब न केवल गलत लंबाई है, बल्कि यह लाइन-ब्रेक को भी ठीक करता है और एज़ेंट के साथ सही वर्णों की गणना करता है (धन्यवाद मिकैकुसा के लिए )

// New Version
$data = preg_replace_callback('!s:\d+:"(.*?)";!s', function($m) { return "s:" . strlen($m[1]) . ':"'.$m[1].'";'; }, $data);

1
इस गलत समाधान में 8 उत्थान कैसे हैं? मैं यह सोचने के लिए शटर करता हूं कि कितने लोग अनजाने में इस एक-लाइनर को कॉपी करेंगे। [उदास चेहरा] यहां दो तरीकों से इस स्निपेट के विफल होने के प्रमाण दिए गए हैं: 3v4l.org/Cf6Nh मेरा परिष्कृत पैटर्न और कस्टम प्रतिस्थापन देखें @ stackoverflow.com/a/55074706/2943403
मिकैकसुसा

1
मेरा समाधान अब दूसरे पेज पर नहीं है क्योंकि यह भयावह रूप से क्षतिग्रस्त धारावाहिक स्ट्रिंग के लिए एक गलत समाधान था। मैंने इस पृष्ठ पर अपना स्निपेट जोड़ा है और स्पष्टीकरण और प्रदर्शन प्रदान किए हैं। stackoverflow.com/a/55566407/2943403
मिकमेकुसा

5

यह त्रुटि इसलिए हुई क्योंकि आपका चार्ट गलत है।

खुले टैग के बाद सेट करें:

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

और अपने डेटाबेस में charset utf8 सेट करें:

mysql_query("SET NAMES 'utf8'");

मुझे ओपी के पोस्ट किए गए सवाल में ऐसा कोई संकेत नहीं दिखाई दे रहा है जो यह बताता है कि भ्रष्टाचार भ्रष्टाचार के कारण हुआ है। अपने दावे का बचाव करने के लिए शुल्क मुक्त करें, लेकिन जहां तक ​​मैं बता सकता हूं, किसी ने मैन्युअल रूप से imageमूल्य को अपडेट किया है और बाइट काउंट को अपडेट करने में विफल रहा है। जब तक अन्यथा सूचित नहीं किया जाता है, मुझे यह मानना ​​होगा कि यह उत्तर ओपी के प्रश्न के लिए गलत है।
मिकमैकुसा

4

आप मल्टीबायट कैरेक्टर हैंडलिंग के साथ फंक्शन का उपयोग करके टूटे हुए सीरियलज स्ट्रिंग को ठीक कर सकते हैं ।

function repairSerializeString($value)
{

    $regex = '/s:([0-9]+):"(.*?)"/';

    return preg_replace_callback(
        $regex, function($match) {
            return "s:".mb_strlen($match[2]).":\"".$match[2]."\""; 
        },
        $value
    );
}

इस उत्तर की सिफारिश करने वाला मूल रूप से गलत है और संभावित रूप से पूरी तरह से मान्य सीरियल स्ट्रिंग्स को नुकसान पहुंचाएगा। इस स्निपेट का उपयोग / भरोसा नहीं किया जाना चाहिए।
मिकमेकुसा

@mickmackusa मुझे आपकी बात नहीं मिल रही है, क्या आप कृपया इसे करने का सबसे अच्छा तरीका सुझा सकते हैं? या इस उत्तर पर सुझाव संपादित करें ..
राजेश मेनिया

मैंने यहां एक सही समाधान प्रदान किया है: stackoverflow.com/a/55566407/2943403 और बताया कि mb_strlen()यह अनुचित है क्योंकि serialize()बाइट काउंट को स्टोर करता है, न कि कैरेक्टर काउंट को। आपके उत्तर को सही मानने से पृष्ठ पर अनावश्यक सलाह पैदा होगी।
मिकमैकुसा

4

सार्वजनिक समारोह 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;
}

php unserialize
परदीप गोयल

यह समाधान कई मामलों के लिए उपयुक्त नहीं है। यह धारणा बनाता है कि हर कोई क्रमबद्ध स्ट्रिंग में मानों को 2-या अधिक व्हाट्सएप वर्णों को शाब्दिक स्थान और trim()प्रत्येक मिलान किए गए प्रतिस्थापन में परिवर्तित करना चाहेगा । वह बिंदु अकेले इस समाधान की सिफारिश करना असंभव बनाता है। इसके अलावा, यह newline वर्णों पर घुट जाएगा और अनावश्यक रूप से पहले से मौजूद बाइट काउंट को पकड़ लेता है जो किसी भी तरह अधिलेखित होने वाला है। अंत में, यह एक "कोड-ओनली उत्तर" है और इस प्रकार के उत्तर निम्न-मूल्य हैं क्योंकि वे भविष्य के शोधकर्ताओं को शिक्षित / सशक्त बनाने के लिए बहुत कम करते हैं।
मिकमैकुसा

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

आप प्रस्तावित रेगेक्स का उपयोग करके टूटी हुई धारावाहिक स्ट्रिंग को ठीक नहीं कर सकते हैं:

$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:' . strlen($m[2]) . ':"' . $m[2] . '";';
    },
    $badData
);
var_dump(@unserialize($data)); // Output: bool(false)

आप regex का उपयोग करके टूटे हुए क्रमबद्ध स्ट्रिंग को ठीक कर सकते हैं:

$data = preg_replace_callback(
    '/(?<=^|\{|;)s:(\d+):\"(.*?)\";(?=[asbdiO]\:\d|N;|\}|$)/s',
    function($m){
        return 's:' . 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"
}

1
@ मिकमैकुसा धन्यवाद मल्टीबीट एनकोडिंग के साथ एक समस्या को ठीक किया।
Даниил Путилин

2

आधिकारिक डॉक्स कहना है कि वह झूठी और सेट E_NOTICE लौटना चाहिए

लेकिन जब से आपको त्रुटि मिली है तब त्रुटि रिपोर्ट E_NOTICE द्वारा ट्रिगर की जानी तय है

आपके द्वारा दिए गए झूठे का पता लगाने की अनुमति देने के लिए यहां एक फिक्स है unserialize

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

आप बेस 64 एनकोड / डिकोड के उपयोग पर विचार करना चाह सकते हैं

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

base64_encodeमेरे लिए चाल चली। Im मेरा मामला हम serializeकमांड लाइन पर डेटा पास कर रहे हैं और ऐसा लग रहा था कि कुछ अजीब अक्षर इसे सही तरीके से काम करने से रोक रहे थे।
क्विकशिफ्टिन

base64_encode()ओपी द्वारा पूछे गए सवाल का समाधान नहीं है। ओपी का प्रश्न / मुद्दा विशेष रूप से इस तथ्य से निपट रहा है कि (धारावाहिक स्ट्रिंग के "अंतिम सरणी तत्व" पर अनुचित प्रतिस्थापन प्रतिस्थापन के लिए) क्रमबद्ध स्ट्रिंग में एक गलत बाइट गिनती है। कृपया केवल उत्तर पोस्ट करें जो सीधे पूछे गए प्रश्न से निपटते हैं।
मिकमैकुसा

2

इस सवाल का भ्रष्टाचार धारावाहिक रूप से तार के अंत में एक एकल प्रतिस्थापन के साथ पृथक है, शायद मैन्युअल रूप से किसी ऐसे व्यक्ति द्वारा प्रतिस्थापित किया गया था जो आलसी रूप से imageफ़ाइल नाम को अपडेट करना चाहता था । यह तथ्य ओपी के पोस्ट किए गए डेटा का उपयोग करके नीचे मेरे प्रदर्शन लिंक में स्पष्ट होगा - संक्षेप में, C:fakepath100.jpgइसकी लंबाई नहीं है 19, यह होना चाहिए 17

चूंकि क्रमबद्ध स्ट्रिंग भ्रष्टाचार एक गलत बाइट / कैरेक्टर काउंट संख्या तक सीमित है, इसलिए निम्नलिखित सही बाइट काउंट मान के साथ दूषित स्ट्रिंग को अपडेट करने का एक अच्छा काम करेगा।

निम्नलिखित रेगेक्स आधारित प्रतिस्थापन केवल बाइट काउंट को दूर करने में प्रभावी होगा, इससे अधिक कुछ नहीं।

ऐसा लगता है कि पहले के कई पोस्ट सिर्फ किसी और से रेगेक्स पैटर्न को कॉपी-पेस्ट कर रहे हैं। यदि यह प्रतिस्थापन में उपयोग नहीं किया जा रहा है, तो संभावित रूप से दूषित बाइट गिनती संख्या को कैप्चर करने का कोई कारण नहीं है। साथ ही, sपैटर्न संशोधक को जोड़ना एक उचित समावेश है यदि स्ट्रिंग मान में newlines / लाइन रिटर्न शामिल हैं।

* उन लोगों के लिए जो सीरीज़िंग के साथ मल्टीबाइट पात्रों के उपचार के बारे में नहीं जानते हैं, आपको कस्टम कॉलबैक में उपयोग नहीं करना चाहिए mb_strlen()क्योंकि यह बाइट काउंट है जो वर्ण गणना नहीं संग्रहीत है , मेरा आउटपुट देखें ...

कोड: ( ओपी के डेटा के साथ डेमो ) ( मनमाने ढंग से नमूना डेटा के साथ डेमो ) ( स्थिति बदलने के साथ डेमो )

$corrupted = <<<STRING
a:4:{i:0;s:3:"three";i:1;s:5:"five";i:2;s:2:"newline1
newline2";i:3;s:6:"garçon";}
STRING;

$repaired = preg_replace_callback(
        '/s:\d+:"(.*?)";/s',
        //  ^^^- matched/consumed but not captured because not used in replacement
        function ($m) {
            return "s:" . strlen($m[1]) . ":\"{$m[1]}\";";
        },
        $corrupted
    );

echo $corrupted , "\n" , $repaired;
echo "\n---\n";
var_export(unserialize($repaired));

आउटपुट:

a:4:{i:0;s:3:"three";i:1;s:5:"five";i:2;s:2:"newline1
Newline2";i:3;s:6:"garçon";}
a:4:{i:0;s:5:"three";i:1;s:4:"five";i:2;s:17:"newline1
Newline2";i:3;s:7:"garçon";}
---
array (
  0 => 'three',
  1 => 'five',
  2 => 'newline1
Newline2',
  3 => 'garçon',
)

खरगोश के छेद के नीचे एक पैर ... ऊपर एक स्ट्रिंग मान में डबल कोट्स होने पर भी ठीक काम करता है, लेकिन अगर एक स्ट्रिंग मूल्य में ";कुछ अन्य मंकीवेरिंगिंग सबस्ट्रिंग होते हैं, तो आपको थोड़ा आगे जाकर "लुकरॉइड्स" को लागू करना होगा। मेरा नया पैटर्न

जाँच करता है कि अग्रणी sहै:

  • पूरे इनपुट स्ट्रिंग की शुरुआत या
  • इससे पहले ;

और जाँचता है कि ";है:

  • संपूर्ण इनपुट स्ट्रिंग के अंत में या
  • इसके बाद }या
  • इसके बाद एक स्ट्रिंग या पूर्णांक घोषणा s:याi:

मैंने प्रत्येक संभावना का परीक्षण नहीं किया है; वास्तव में, मैं एक धारावाहिक स्ट्रिंग में सभी संभावनाओं से अपेक्षाकृत अपरिचित हूं क्योंकि मैं कभी भी क्रमबद्ध डेटा के साथ काम करने का चुनाव नहीं करता हूं - हमेशा आधुनिक अनुप्रयोगों में। यदि अतिरिक्त संभावित प्रमुख या अनुगामी वर्ण हैं, तो एक टिप्पणी छोड़ दें और मैं लुकरॉइड का विस्तार करूंगा।

विस्तारित स्निपेट: ( डेमो )

$corrupted_byte_counts = <<<STRING
a:12:{i:0;s:3:"three";i:1;s:5:"five";i:2;s:2:"newline1
newline2";i:3;s:6:"garçon";i:4;s:111:"double " quote \"escaped";i:5;s:1:"a,comma";i:6;s:9:"a:colon";i:7;s:0:"single 'quote";i:8;s:999:"semi;colon";s:5:"assoc";s:3:"yes";i:9;s:1:"monkey";wrenching doublequote-semicolon";s:3:"s:";s:9:"val s: val";}
STRING;

$repaired = preg_replace_callback(
        '/(?<=^|;)s:\d+:"(.*?)";(?=$|}|[si]:)/s',
        //^^^^^^^^--------------^^^^^^^^^^^^^-- some additional validation
        function ($m) {
            return 's:' . strlen($m[1]) . ":\"{$m[1]}\";";
        },
        $corrupted_byte_counts
    );

echo "corrupted serialized array:\n$corrupted_byte_counts";
echo "\n---\n";
echo "repaired serialized array:\n$repaired";
echo "\n---\n";
print_r(unserialize($repaired));

आउटपुट:

corrupted serialized array:
a:12:{i:0;s:3:"three";i:1;s:5:"five";i:2;s:2:"newline1
newline2";i:3;s:6:"garçon";i:4;s:111:"double " quote \"escaped";i:5;s:1:"a,comma";i:6;s:9:"a:colon";i:7;s:0:"single 'quote";i:8;s:999:"semi;colon";s:5:"assoc";s:3:"yes";i:9;s:1:"monkey";wrenching doublequote-semicolon";s:3:"s:";s:9:"val s: val";}
---
repaired serialized array:
a:12:{i:0;s:5:"three";i:1;s:4:"five";i:2;s:17:"newline1
newline2";i:3;s:7:"garçon";i:4;s:24:"double " quote \"escaped";i:5;s:7:"a,comma";i:6;s:7:"a:colon";i:7;s:13:"single 'quote";i:8;s:10:"semi;colon";s:5:"assoc";s:3:"yes";i:9;s:39:"monkey";wrenching doublequote-semicolon";s:2:"s:";s:10:"val s: val";}
---
Array
(
    [0] => three
    [1] => five
    [2] => newline1
newline2
    [3] => garçon
    [4] => double " quote \"escaped
    [5] => a,comma
    [6] => a:colon
    [7] => single 'quote
    [8] => semi;colon
    [assoc] => yes
    [9] => monkey";wrenching doublequote-semicolon
    [s:] => val s: val
)

1

आपको कोलाज प्रकार को बदलना होगा utf8_unicode_ciऔर समस्या ठीक हो जाएगी।


ओपी के सैंपल डेटा में क्या विशिष्ट चरित्र है जो आपको लगता है कि कोलाज को बदलकर संशोधित किया जाएगा utf8_unicode_ci? मुझे इस पर अपना संदेह है।
मिकमैकुसा

यह वास्तव में मेरे लिए भी काम करता है (r00tAcc3ss के उत्तर के अलावा) किसी से कोई शब्द स्पष्ट क्यों? पृष्ठभूमि के रूप में, मैं एपीआई कॉल से रिसोर्सस्पेस एप्लिकेशन में डेटा लेता हूं, इसे एक ऐरे में स्टोर करता हूं, इसे क्रमबद्ध करता हूं और इसे सहेजता हूं। क्रमबद्ध डेटा सहेजे जाने वाले मुद्दे थे इसलिए मुझे इसे UTF-8 में मैन्युअल रूप से एनकोड करना था, मैं DB में सेटेशन और कैरेक्टर के साथ खेल रहा था, और आखिरकार utf8_general_ci कोलेशन के साथ छोड़ दिया गया था, जब मैंने इसे utf8_unicode_ci से जोड़ा, तो यह काम किया ।
रॉबर्टो बेसेरा

1

मेरे मामले में मैं BLOBMySQL DB के क्षेत्र में क्रमबद्ध डेटा संग्रहीत कर रहा था, जो स्पष्ट रूप से पूरे मूल्य को शामिल करने के लिए काफी बड़ा नहीं था और इसे काट दिया। इस तरह की एक स्ट्रिंग स्पष्ट रूप से गैर-अधिकृत नहीं हो सकती है।
एक बार उस क्षेत्र को MEDIUMBLOBसमस्या में परिवर्तित कर दिया गया। इसके अलावा यह तालिका विकल्प में स्विच करने की जरूरत हो सकती है ROW_FORMATकरने के लिए DYNAMICया COMPRESSED


मुझे - हालांकि मेरा एक TEXTक्षेत्र था और 65kb पर इस तरह से छंटनी की गई थी।
एंटनी

यह प्रश्न ट्रंकेशन से ग्रस्त नहीं है। ओपी का प्रश्न / मुद्दा विशेष रूप से इस तथ्य से निपट रहा है कि (धारावाहिक स्ट्रिंग के "अंतिम सरणी तत्व" पर अनुचित प्रतिस्थापन प्रतिस्थापन के लिए) क्रमबद्ध स्ट्रिंग में एक गलत बाइट गिनती है। कृपया केवल उत्तर पोस्ट करें जो सीधे पूछे गए प्रश्न से निपटते हैं।
मिकमैकुसा

1

सफलता के बिना इस पृष्ठ पर कुछ चीजों की कोशिश करने के बाद, मैंने पृष्ठ-स्रोत में एक नज़र डाली और टिप्पणी की कि धारावाहिक स्ट्रिंग में सभी उद्धरण HTML- संस्थाओं द्वारा प्रतिस्थापित किए गए हैं। इन संस्थाओं को डिकोड करने से सिरदर्द से बचने में मदद मिलती है:

$myVar = html_entity_decode($myVar);

यह प्रश्न क्रमबद्ध स्ट्रिंग में html एन्कोडेड संस्थाओं से ग्रस्त नहीं है। ओपी का प्रश्न / मुद्दा विशेष रूप से इस तथ्य से निपट रहा है कि (धारावाहिक स्ट्रिंग के "अंतिम सरणी तत्व" पर अनुचित प्रतिस्थापन प्रतिस्थापन के लिए) क्रमबद्ध स्ट्रिंग में एक गलत बाइट गिनती है। कृपया केवल उत्तर पोस्ट करें जो सीधे पूछे गए प्रश्न से निपटते हैं।
मिकमैकुसा

@mickmackusa यह प्रश्न लगभग 7 वर्ष पुराना है और मेरा उत्तर ~ 1,5 है। फिर भी अच्छा है कि आप इतना व्यस्त हैं!
डेविड

मुझे SO पेज पसंद हैं - युवा और बूढ़े। मैं उन शोधकर्ताओं की तलाश कर रहा हूं जो एक अच्छे उत्तर और एक नहीं-तो-अच्छे उत्तर के बीच अंतर नहीं जानते हैं। दुर्भाग्यपूर्ण, यह पृष्ठ ऑफ़-टॉपिक सलाह से भरा है।
मिकमैकुसा

महान! पहले से ही क्वालिटी कंट्रोल और वोटिंग है, लेकिन मेरे पास आपको रोकने का कोई कारण नहीं है ;-)
डेविड

अरे नहीं, देखो। उत्कीर्ण उत्तर हैं जिन्हें नीचे किया जाना चाहिए। बहुत से लोग अंतर नहीं कर सकते। इस पृष्ठ पर, वोट टैली गुणवत्ता / उपयुक्तता का कोई संकेत नहीं है। मैं अपना समय बर्बाद नहीं करने जा रहा हूं क्योंकि मेरे डाउनवॉटर टैली पर सेंध नहीं लगाएंगे। जो सबसे अच्छा मैं कर सकता हूं, वह यह बताने के लिए टिप्पणी छोड़ सकता है कि अच्छा / बुरा / बदसूरत क्या है।
मिकमैकुसा

1

एक भ्रष्ट क्रमबद्ध स्ट्रिंग को ठीक करने के लिए यहां एक ऑनलाइन टूल है

मैं यह जोड़ना चाहूंगा कि यह अधिकतर डीबी और क्रमांकन डेटा पर की गई खोज और प्रतिस्थापन के कारण होता है ( विशेष रूप से key length) प्रतिस्थापन के अनुसार अद्यतन नहीं किया जाता है और यह "भ्रष्टाचार" का कारण बनता है।

फिर भी, उपरोक्त उपकरण क्रमांकन डेटा ( यहां से कॉपी किया गया ) को ठीक करने के लिए निम्न तर्क का उपयोग करता है ।

function error_correction_serialise($string){
    // at first, check if "fixing" is really needed at all. After that, security checkup.
    if ( unserialize($string) !== true &&  preg_match('/^[aOs]:/', $string) ) {
         $string = preg_replace_callback( '/s\:(\d+)\:\"(.*?)\";/s',    function($matches){return 's:'.strlen($matches[2]).':"'.$matches[2].'";'; },   $string );
    }
    return $string;
} 

0

इस समस्या का एक अन्य कारण "पेलोड" सत्र तालिका का स्तंभ प्रकार हो सकता है। यदि आपके पास सत्र का विशाल डेटा है, तो एक टेक्स्ट कॉलम पर्याप्त नहीं होगा। आपको MEDIUMTEXT या LONGTEXT की आवश्यकता होगी।


यह प्रश्न ट्रंकेशन से ग्रस्त नहीं है। ओपी का प्रश्न / मुद्दा विशेष रूप से इस तथ्य से निपट रहा है कि (धारावाहिक स्ट्रिंग के "अंतिम सरणी तत्व" पर अनुचित प्रतिस्थापन प्रतिस्थापन के लिए) क्रमबद्ध स्ट्रिंग में एक गलत बाइट गिनती है। कृपया केवल उत्तर पोस्ट करें जो सीधे पूछे गए प्रश्न से निपटते हैं।
मिकमैकुसा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.