do_parse( new FrmStringReaderHelper( $string ) ); if ( is_array( $unserialized_data ) && $this->serialized_string_is_invalid( $string ) ) { return array_filter( $unserialized_data, array( $this, 'serialized_value_is_valid' ) ); } return $unserialized_data; } /** * Check if an unserialized value is valid. * * @since 6.20 * * @param mixed $value * @return bool */ private function serialized_value_is_valid( $value ) { return ! is_string( $value ) || strpos( $value, ';s:' ) === false; } /** * @since 6.20 * * @param string $string * @return bool */ private function serialized_string_is_invalid( $string ) { $invalid_substrings = array( ';s:10:\"a"', ';s:";', ); foreach ( $invalid_substrings as $invalid ) { if ( strpos( $string, $invalid ) !== false ) { return true; } } return false; } /** * This is the recursive parser. * * @param FrmStringReaderHelper $string * @return array|bool|float|int|string|null */ private function do_parse( $string ) { // May be : or ; as a terminator, depending on what the data type is. $type = $string->read( 1 ); $string->skip_next_character(); switch ( $type ) { case 'a': return $this->parse_array( $string ); case 's': return $this->parse_string( $string ); case 'i': return $this->parse_int( $string ); case 'd': return $this->parse_float( $string ); case 'b': return $this->parse_bool( $string ); } // Includes case 'N' and case 'O'. // Treat a serialized object or anything unexpected as Null. return null; } /** * @param FrmStringReaderHelper $string * @return array */ private function parse_array( $string ) { // Associative array: a:length:{[index][value]...} $count = (int) $string->read_until( ':' ); // Eat the opening "{" of the array. $string->skip_next_character(); $val = array(); for ( $i = 0; $i < $count; $i++ ) { $array_key = $this->do_parse( $string ); $array_value = $this->do_parse( $string ); if ( ! is_array( $array_key ) ) { $val[ $array_key ] = $array_value; } } // Eat "}" terminating the array. $string->skip_next_character(); return $val; } /** * @param FrmStringReaderHelper $string * @return string */ private function parse_string( $string ) { $len = (int) $string->read_until( ':' ); $val = $string->read( $len + 2 ); // Eat the separator. $string->skip_next_character(); return $val; } /** * @param FrmStringReaderHelper $string * @return int */ private function parse_int( $string ) { return (int) $string->read_until( ';' ); } /** * @param FrmStringReaderHelper $string * @return float */ private function parse_float( $string ) { return (float) $string->read_until( ';' ); } /** * @param FrmStringReaderHelper $string * @return bool */ private function parse_bool( $string ) { // Boolean is 0 or 1. $val = $string->read( 1 ) === '1'; $string->skip_next_character(); return $val; } }