Close #4830, #3649
diff --git a/system/libraries/Session/Session.php b/system/libraries/Session/Session.php
index 3b391a8..5aac12f 100644
--- a/system/libraries/Session/Session.php
+++ b/system/libraries/Session/Session.php
@@ -57,6 +57,7 @@
 
 	protected $_driver = 'files';
 	protected $_config;
+	protected $_sid_regexp;
 
 	// ------------------------------------------------------------------------
 
@@ -99,6 +100,7 @@
 
 		// Configuration ...
 		$this->_configure($params);
+		$this->_config['_sid_regexp'] = $this->_sid_regexp;
 
 		$class = new $class($this->_config);
 		if ($class instanceof SessionHandlerInterface)
@@ -131,7 +133,7 @@
 		if (isset($_COOKIE[$this->_config['cookie_name']])
 			&& (
 				! is_string($_COOKIE[$this->_config['cookie_name']])
-				OR ! preg_match('/^[0-9a-f]{40}$/', $_COOKIE[$this->_config['cookie_name']])
+				OR ! preg_match('#\A'.$this->_sid_regexp.'\z#', $_COOKIE[$this->_config['cookie_name']])
 			)
 		)
 		{
@@ -315,8 +317,36 @@
 		ini_set('session.use_strict_mode', 1);
 		ini_set('session.use_cookies', 1);
 		ini_set('session.use_only_cookies', 1);
-		ini_set('session.hash_function', 1);
-		ini_set('session.hash_bits_per_character', 4);
+
+		if (PHP_VERSION_ID < 70100)
+		{
+			if ((int) ini_get('session.hash_function') === 0)
+			{
+				ini_set('session.hash_function', 1);
+				ini_set('session.hash_bits_per_character', $bits_per_character = 4);
+			}
+			else
+			{
+				$bits_per_character = (int) ini_get('session.hash_bits_per_character');
+			}
+		}
+		elseif ((int) ini_get('session.sid_length') < 40 && ($bits_per_character = (int) ini_get('session.sid_bits_per_character')) === 4)
+		{
+			ini_set('session.sid_length', 40);
+		}
+
+		switch ($bits_per_character)
+		{
+			case 4:
+				$this->_sid_regexp = '[0-9a-f]{40,}';
+				break;
+			case 5:
+				$this->_sid_regexp = '[0-9a-v]{40,}';
+				break;
+			case 6:
+				$this->_sid_regexp = '[0-9a-zA-Z,-]{40,}';
+				break;
+		}
 	}
 
 	// ------------------------------------------------------------------------
diff --git a/system/libraries/Session/drivers/Session_files_driver.php b/system/libraries/Session/drivers/Session_files_driver.php
index 5f05396..37315d3 100644
--- a/system/libraries/Session/drivers/Session_files_driver.php
+++ b/system/libraries/Session/drivers/Session_files_driver.php
@@ -77,6 +77,13 @@
 	protected $_file_new;
 
 	/**
+	 * Validate SID regular expression
+	 *
+	 * @var	string
+	 */
+	protected $_sid_regexp;
+
+	/**
 	 * mbstring.func_override flag
 	 *
 	 * @var	bool
@@ -106,6 +113,8 @@
 			$this->_config['save_path'] = rtrim(ini_get('session.save_path'), '/\\');
 		}
 
+		$this->_sid_regexp = $this->_config['_sid_regexp'];
+
 		isset(self::$func_override) OR self::$func_override = (extension_loaded('mbstring') && ini_get('mbstring.func_override'));
 	}
 
@@ -352,10 +361,13 @@
 
 		$ts = time() - $maxlifetime;
 
+		$pattern = ($this->_config['match_ip'] === TRUE)
+			? '[0-9a-f]{32}'
+			: '';
+
 		$pattern = sprintf(
-			'/^%s[0-9a-f]{%d}$/',
-			preg_quote($this->_config['cookie_name'], '/'),
-			($this->_config['match_ip'] === TRUE ? 72 : 40)
+			'#\A%s'.$pattern.$this->_sid_regexp.'\z#',
+			preg_quote($this->_config['cookie_name'])
 		);
 
 		while (($file = readdir($directory)) !== FALSE)