Permalink
Browse files

Doc and simpletests for function `param_check_serialized_array()`

  • Loading branch information...
1 parent 0cafd66 commit 335abf09bcea61717bd00bc1e3889f8100ebd1bb @yurabakhtin yurabakhtin committed Oct 4, 2016
Showing with 114 additions and 2 deletions.
  1. +66 −0 _tests/blogs/evocore/param.funcs.simpletest.php
  2. +2 −2 htsrv/call_plugin.php
  3. +46 −0 inc/_core/_param.funcs.php
@@ -98,6 +98,72 @@ function test_param_check_passwords()
set_param('p2', '2');
$this->assertFalse( param_check_passwords('p1', 'p2') );
}
+
+
+ function test_param_check_serialized_array()
+ {
+ // Simple array:
+ // $params = array( 'a' => 'b' );
+ set_param( 'params', 'a:1:{s:1:"a";s:1:"b";}' );
+ $this->assertTrue( param_check_serialized_array( 'params' ) );
+
+ // Simple object:
+ // $params = new stdClass();
+ // $params->a = 'b';
+ set_param( 'params', 'O:8:"stdClass":1:{s:1:"a";s:1:"b";}' );
+ $this->assertFalse( param_check_serialized_array( 'params' ) );
+
+ // Array contains an object with string key:
+ // $Object = new stdClass();
+ // $Object->a = 'b';
+ // $params = array( 'a' => 'b', 'c' => $Object );
+ set_param( 'params', 'a:2:{s:1:"a";s:1:"b";s:1:"c";O:8:"stdClass":1:{s:1:"a";s:1:"b";}}' );
+ $this->assertFalse( param_check_serialized_array( 'params' ) );
+
+ // Array contains an object with integer key:
+ // $Object = new stdClass();
+ // $Object->a = 'b';
+ // $params = array( 'a' => 'b', 123 => $Object );
+ set_param( 'params', 'a:2:{s:1:"a";s:1:"b";i:123;O:8:"stdClass":1:{s:1:"a";s:1:"b";}}' );
+ $this->assertFalse( param_check_serialized_array( 'params' ) );
+
+ // Array contains a string with PART of fake object structure:
+ // $params = array( 'a' => 'b', 'c' => ';O:8:' );
+ set_param( 'params', 'a:2:{s:1:"a";s:1:"b";s:1:"c";s:5:";O:8:";}' );
+ $this->assertTrue( param_check_serialized_array( 'params' ) );
+
+ // Array contains a string with FULL fake object structure:
+ // $params = array( 'a' => 'b', 'c' => 'a:2:{s:1:"a";s:1:"b";i:123;O:8:"stdClass":1:{s:1:"a";s:1:"b";}}' );
+ set_param( 'params', 'a:2:{s:1:"a";s:1:"b";s:1:"c";s:63:"a:2:{s:1:"a";s:1:"b";i:123;O:8:"stdClass":1:{s:1:"a";s:1:"b";}}";}' );
+ $this->assertTrue( param_check_serialized_array( 'params' ) );
+
+ // Array contains a string with FULL fake object structure AND object:
+ // $Object = new stdClass();
+ // $Object->a = 'b';
+ // $params = array( 'a' => 'b', 'c' => 'a:2:{s:1:"a";s:1:"b";i:123;O:8:"stdClass":1:{s:1:"a";s:1:"b";}}', 'd' => $Object );
+ set_param( 'params', 'a:3:{s:1:"a";s:1:"b";s:1:"c";s:63:"a:2:{s:1:"a";s:1:"b";i:123;O:8:"stdClass":1:{s:1:"a";s:1:"b";}}";s:1:"d";O:8:"stdClass":1:{s:1:"a";s:1:"b";}}' );
+ $this->assertFalse( param_check_serialized_array( 'params' ) );
+
+ // String:
+ // $params = 'a';
+ set_param( 'params', 's:1:"a";' );
+ $this->assertFalse( param_check_serialized_array( 'params' ) );
+
+ // Integer:
+ // $params = 456;
+ set_param( 'params', 'i:456;' );
+ $this->assertFalse( param_check_serialized_array( 'params' ) );
+
+ // Float:
+ // $params = 123.456;
+ set_param( 'params', 'd:123.4560000000000030695446184836328029632568359375;' );
+ $this->assertFalse( param_check_serialized_array( 'params' ) );
+
+ // NULL:
+ // $params = NULL;
+ set_param( 'params', 'N;' );
+ $this->assertFalse( param_check_serialized_array( 'params' ) );
+ }
}
@@ -36,8 +36,8 @@
}
else
{ // Params given:
- if( ( substr( $params, 0, 2 ) == 'a:' ) && ( ! preg_match( '/(s:\d+:"[^"]*"|i:\d+)(;|{|})O:\+?[0-9]+:"/', $params ) ) )
- { // Allow to unserialize only arrays + check there is no Object in the array (We NEVER want to unserialize an object)
+ if( param_check_serialized_array( 'params' ) )
+ { // If the params is a serialized array and doesn't contain any object inside:
// (This may result in "false", but this means that unserializing failed)
$params = @unserialize( $params );
}
@@ -2572,4 +2572,50 @@ function isset_param( $var )
return isset($_POST[$var]) || isset($_GET[$var]);
}
+
+/**
+ * Check if a serialized data is an array and doesn't contain any object inside
+ *
+ * @param string Param name from request
+ * @return boolean TRUE on expected data
+ */
+function param_check_serialized_array( $param_name )
+{
+ $param_value = get_param( $param_name );
+
+ if( ! is_string( $param_value ) )
+ { // A serialized data must be a string:
+ return false;
+ }
+
+ // Search all string items in the serialized array:
+ preg_match_all( '/[{;]s:(\d+):"/', $param_value, $matches, PREG_OFFSET_CAPTURE );
+ foreach( $matches[0] as $m => $match )
+ { // And replace its values with spaces in order to don't decide below the following string values as object structures:
+ // a:2:{s:1:"a";s:1:"b";i:123;O:8:"stdClass":1:{s:1:"a";s:1:"b";}}
+ $param_value = substr_replace( $param_value, str_repeat( ' ', (int)$matches[1][ $m ][0] ), $match[1] + strlen( $match[0] ), (int)$matches[1][ $m ][0] );
+ }
+
+ if(
+ // Allow to unserialize only arrays, main reason is an excluding of object structure like:
+ // - O:7:"Results":1:{s:3:"sql";s:21:"SELECT * FROM T_users";}
+ ( substr( $param_value, 0, 2 ) == 'a:' ) &&
+ // + Check there is no Object in the array (We NEVER want to unserialize an object):
+ // a:1:{s:3:"key";O:8:"stdClass":1:{s:1:"x";i:1;}}
+ // a:1:{i:123;O:8:"stdClass":1:{s:1:"x";i:1;}}
+ // a:1:{s:3:"key";a:1:{s:3:"sub";O:8:"stdClass":1:{s:1:"x";i:1;}}}
+ // a:1:{s:3:"key";a:1:{i:456;O:8:"stdClass":1:{s:1:"x";i:1;}}}
+ // This checking exclude real string with object structure value like ';O:8:':
+ // a:1:{s:3:"key";s:5:";O:8:";}
+ ( ! preg_match( '/(s:\d+:"[^"]*"|i:\d+);O:\+?[0-9]+:"/', $param_value ) )
+ )
+ { // Correct data:
+ return true;
+ }
+ else
+ { // Wrong data:
+ return false;
+ }
+}
+
?>

0 comments on commit 335abf0

Please sign in to comment.