यह देखने के लिए जांचें कि क्या किसी स्ट्रिंग को सीरियल किया गया है?


जवाबों:


191

मैं कहता हूँ, unserializeइसे करने की कोशिश; ;-)

मैनुअल का हवाला देते हुए:

यदि उत्तीर्ण स्ट्रिंग अपरिहार्य नहीं है, तो FALSE लौटा दिया जाता है और E_NOTICE जारी किया जाता है।

तो, आप अगर वापसी मान है की जाँच करने के लिए है falseया नहीं (के साथ ===या !==, सुनिश्चित करें के साथ किसी भी समस्या है करने के लिए नहीं होने के लिए 0या nullया कुछ भी है कि करने के लिए बराबर होती है false, मैं कहता हूँ चाहते हैं)

बस नोटिस से सावधान रहें: आप @ ऑपरेटर का उपयोग करना चाहते हैं / कर सकते हैं ।

उदाहरण के लिए :

$str = 'hjkl';
$data = @unserialize($str);
if ($data !== false) {
    echo "ok";
} else {
    echo "not ok";
}

आपको मिलेगा:

not ok


संपादित करें: ओह, और जैसे @Peter ने कहा (उसके लिए धन्यवाद!), आप मुसीबत में दौड़ सकते हैं यदि आप एक बूलियन झूठी के प्रतिनिधित्व को अनसुना करने की कोशिश कर रहे हैं :-(

इसलिए, यह जांचना कि आपका क्रमबद्ध स्ट्रिंग " b:0;" के बराबर नहीं है, सहायक हो सकता है; कुछ इस तरह करना चाहिए चाल, मुझे लगता है:

$data = @unserialize($str);
if ($str === 'b:0;' || $data !== false) {
    echo "ok";
} else {
    echo "not ok";
}

परीक्षण करने से पहले उस विशेष मामले का परीक्षण करने का प्रयास एक अनुकूलन होगा - लेकिन शायद यह उपयोगी नहीं है, यदि आपके पास अक्सर गलत धारावाहिक मूल्य नहीं है।


20
लेकिन क्या होगा अगर गैर-अधिकृत मूल्य FALSE के मूल्य के साथ एक बूलियन है?
पीटर

1
@ पेटर: उत्कृष्ट टिप्पणी; मैंने उस मामले से निपटने के लिए एक प्रस्ताव के साथ अपना जवाब संपादित किया है; धन्यवाद !
पास्कल मार्टिन

धन्यवाद। :) मैंने मान लिया कि यह शायद उत्तर होने जा रहा था .. बस मुझे लगता है कि यह पता लगाने का एक तरीका होना चाहिए कि क्या यह वास्तव में इससे पहले कि इसे संसाधित करने के प्रयास के लिए पार्सर को मजबूर करने से पहले क्रमबद्ध है।
डांग

1
क्या इस पद्धति का डेटा के बड़े टुकड़ों के साथ प्रदर्शन पर कोई उचित प्रभाव पड़ता है?
पीआई

2
महत्वपूर्ण: कभी भी कच्चे उपयोगकर्ता डेटा का उपयोग न करें क्योंकि यह एक हमले के वेक्टर के रूप में इस्तेमाल किया जा सकता है। OWASP: PHP_Object_Injection
ArtBIT

56

मैंने यह कोड नहीं लिखा है, यह वास्तव में वर्डप्रेस से है। सोचा था कि मैं इसे किसी के लिए भी शामिल करूंगा, यह ओवरकिल हो सकता है लेकिन यह काम करता है :)

<?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;
}

1
मुझे मूल रूप से एक मूल पता लगाने के लिए एक रेगेक्स की आवश्यकता थी, मैंने उपयोग करना समाप्त कर दिया:^([adObis]:|N;)
किसान 23

5
वर्तमान वर्डप्रेस संस्करण कुछ हद तक अधिक परिष्कृत है: codex.wordpress.org/Function_Reference/…
क्रिस वी

3
क्रेडिट देने के लिए +1। मुझे नहीं पता था कि वर्डप्रेस में यह बिल्ट-इन है। इस विचार के लिए धन्यवाद - अब मैं आगे जाऊंगा और वर्डप्रेस कोर से उपयोगी कार्यों का एक संग्रह बनाऊंगा।
अमल मुरली

वर्डप्रेस फ़ंक्शन संदर्भ के लिए नवीनतम URL: developer.wordpress.org/reference/functions/is_serialized
सेड्रिक फ्रैन्कॉयज

18

पास्कल मार्टिन की प्रतिक्रिया का अनुकूलन

/**
 * Check if a string is serialized
 * @param string $string
 */
public static function is_serial($string) {
    return (@unserialize($string) !== false);
}

16

यदि $ स्ट्रिंग एक सीरियलाइज्ड falseवैल्यू है, तो $string = 'b:0;' SoN9ne का फंक्शन रिटर्न देता है false, यह गलत है

तो समारोह होगा

/**
 * Check if a string is serialized
 *
 * @param string $string
 *
 * @return bool
 */
function is_serialized_string($string)
{
    return ($string == 'b:0;' || @unserialize($string) !== false);
}

2
इन परीक्षणों के क्रम को स्वैप करना अधिक कुशल होगा।
Artfulrobot

@ (ऑपरेटर पर) हतोत्साहित किया जाना चाहिए। इसके बजाय ट्राई ब्‍लॉक को प्रयोग करें।
फ्रांसिस्को लूज

@FranciscoLuz पुस्तिका से php.net/manual/en/function.unserialize.php In case the passed string is not unserializeable, FALSE is returned and E_NOTICE is issued. हम E_NOTICE त्रुटि को नहीं पकड़ सकते, क्योंकि यह एक फेंक दिया अपवाद नहीं है।
हेज़म नूर

@ हज़मन्नूर I ने इसे PHP 7 के साथ परीक्षण किया और यह पकड़ा गया। इसके अलावा, PHP 7 में, कैच (\ Throwable $ e) है जो हुड के नीचे गलत होने वाली हर चीज को पकड़ता है।
फ्रांसिस्को लूज

@FranciscoLuz आपने PHP 7 में E_Notice को कैसे पकड़ा?
user427969

13

पास्कल मार्टिन के शानदार जवाब के बावजूद, मैं उत्सुक था कि क्या आप इस तरह से संपर्क कर सकते हैं, इसलिए मैंने मानसिक अभ्यास के रूप में ऐसा किया

<?php

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<br>';
  echo $valueToUnserialize;
} else {
  echo 'Value was unserialized!<br>';
  var_dump( $unserialized );
}

और यह वास्तव में काम करता है। एकमात्र चेतावनी यह है कि यदि $ php_errormsg काम करता है तो आपके पास पंजीकृत त्रुटि हैंडलर होने पर यह टूट जाएगा ।


1
+1: यह एक मजेदार है, मुझे मानना ​​होगा - इसके बारे में नहीं सोचा होगा! और मुझे यह असफल बनाने का कोई तरीका नहीं मिला, ^ ^ नाइस वर्क! और मेरे उत्तर पर टिप्पणी के लिए धन्यवाद: इसके बिना, मैंने शायद यह उत्तर नहीं देखा होगा।
पास्कल मार्टिन

$ a = 'bla'; $ b = 'b: 0;'; $ A को $ b के साथ इस तरह से जोड़ने का प्रयास करें, दोनों ही विफल रहेंगे जबकि $ b को नहीं करना चाहिए।
बारदिर

नहीं अगर वहाँ पहले एक विफलता थी। क्योंकि $ php_errormsg में अभी भी पहले से क्रमांकन त्रुटि होगी और एक बार जब आप असत्य का वर्णन कर देंगे तो यह विफल हो जाएगा।
बड़दिर

हाँ, लेकिन केवल अगर आप डीसर्विलाइज़िंग $aऔर डिसेरिएलाइज़िंग के बीच त्रुटि की जाँच नहीं करते हैं $b, जो व्यावहारिक अनुप्रयोग डिज़ाइन नहीं है।
पीटर बेली

11
$data = @unserialize($str);
if($data !== false || $str === 'b:0;')
    echo 'ok';
else
    echo "not ok";

सही ढंग से के मामले को संभालता है serialize(false)। :)


3

एक समारोह के लिए निर्माण

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

1
यह रेगेक्स खतरनाक है, यह सकारात्मक लौट रहा है जब a:(या b:आदि) $ मूल्य के अंदर कहीं मौजूद है, शुरुआत में नहीं। और ^यहाँ एक स्ट्रिंग की शुरुआत का मतलब नहीं है। यह पूरी तरह से भ्रामक है।
डेनिस चमेल 14'18

3

वर्डप्रेस समाधान है: (विवरण यहाँ है)

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

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

}

5
ठीक है, यह कई JSON तार के लिए भी सच है, यह नहीं होगा? इसलिए यह निर्धारित करना विश्वसनीय नहीं है कि क्या स्ट्रिंग संयुक्त / क्रमबद्ध हो सकती है।
गॉर्डन

यह सच हो सकता है, लेकिन यदि विकल्प क्रमबद्ध है, या सिर्फ सादा पाठ, जैसा कि मेरे लिए था, यह एक आकर्षण की तरह काम करता है।
ब्योर्न 3

1
@ Björn3 "अच्छी तरह से यह मेरे लिए इस विशिष्ट मामले में काम करता है" कोडिंग करते समय एक बहुत बुरी मानसिकता है। बहुत सारे डेवलपर ऐसे हैं जो आलसी हैं या आगे की सोच नहीं है और यह आगे चलकर एक बुरे सपने का कारण बनता है जब अन्य डेवलपर्स को अपने कोड के साथ काम करना होता है या कुछ बदलने की कोशिश करनी होती है और अचानक कुछ भी ठीक से काम नहीं करता है।
BadHorsie

पूरी तरह से ठोस कोड बनाना (यदि वह भी संभव था) हमेशा लक्ष्य या सर्वोत्तम अभ्यास नहीं है। नहीं जब यह समय की समाप्ति पर आता है। यह केवल प्रोग्रामर के नजरिए से सही है। वास्तविक जीवन में बहुत सारे circomstances हैं जहां त्वरित और गंदा पसंदीदा तरीका है।
ब्योर्न 3

1

यह मेरे लिए ठीक काम करता है

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

?>

कृपया ध्यान दें कि अगर यह स्ट्रिंग क्रमबद्ध-दिखने वाली स्ट्रिंग है - तो यह वास्तव में उस स्ट्रिंग की वैधता की जाँच नहीं करेगा।
eithed

-2

मैं इसे इस तरह से करना पसंद करता हूं:

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

क्रमबद्ध चर एक सरणी क्यों होना चाहिए? यह वास्तव में जो भी प्रकार का हो सकता है।
वेलेरियो बोज
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.