[ticket/16524] Filter out-of-bounds UTF8 characters for profile fields

PHPBB3-16524
This commit is contained in:
rxu 2020-06-10 17:41:59 +07:00 committed by Marc Alexander
parent 2afa989500
commit acd824d432
No known key found for this signature in database
GPG key ID: 50E0D2423696F995
6 changed files with 58 additions and 2 deletions

View file

@ -82,6 +82,7 @@ services:
profilefields.type.string: profilefields.type.string:
class: phpbb\profilefields\type\type_string class: phpbb\profilefields\type\type_string
arguments: arguments:
- '@auth'
- '@request' - '@request'
- '@template' - '@template'
- '@user' - '@user'
@ -91,6 +92,7 @@ services:
profilefields.type.text: profilefields.type.text:
class: phpbb\profilefields\type\type_text class: phpbb\profilefields\type\type_text
arguments: arguments:
- '@auth'
- '@request' - '@request'
- '@template' - '@template'
- '@user' - '@user'
@ -100,6 +102,7 @@ services:
profilefields.type.url: profilefields.type.url:
class: phpbb\profilefields\type\type_url class: phpbb\profilefields\type\type_url
arguments: arguments:
- '@auth'
- '@request' - '@request'
- '@template' - '@template'
- '@user' - '@user'

View file

@ -254,6 +254,17 @@ class manager
/** @var \phpbb\profilefields\type\type_interface $profile_field */ /** @var \phpbb\profilefields\type\type_interface $profile_field */
$profile_field = $this->type_collection[$row['field_type']]; $profile_field = $this->type_collection[$row['field_type']];
$cp_data['pf_' . $row['field_ident']] = $profile_field->get_profile_field($row); $cp_data['pf_' . $row['field_ident']] = $profile_field->get_profile_field($row);
/**
* Replace Emojis and other 4bit UTF-8 chars not allowed by MySQL with UCR/NCR
* using their Numeric Character Reference's Hexadecimal notation.
* Check the permissions for using Emojis first.
*/
if ($this->auth->acl_get('u_emoji'))
{
$cp_data['pf_' . $row['field_ident']] = utf8_encode_ucr($cp_data['pf_' . $row['field_ident']]);
}
$check_value = $cp_data['pf_' . $row['field_ident']]; $check_value = $cp_data['pf_' . $row['field_ident']];
if (($cp_result = $profile_field->validate_profile_field($check_value, $row)) !== false) if (($cp_result = $profile_field->validate_profile_field($check_value, $row)) !== false)

View file

@ -15,6 +15,12 @@ namespace phpbb\profilefields\type;
class type_string extends type_string_common class type_string extends type_string_common
{ {
/**
* Auth object
* @var \phpbb\auth\auth
*/
protected $auth;
/** /**
* Request object * Request object
* @var \phpbb\request\request * @var \phpbb\request\request
@ -36,12 +42,14 @@ class type_string extends type_string_common
/** /**
* Construct * Construct
* *
* @param \phpbb\auth\auth $auth Auth object
* @param \phpbb\request\request $request Request object * @param \phpbb\request\request $request Request object
* @param \phpbb\template\template $template Template object * @param \phpbb\template\template $template Template object
* @param \phpbb\user $user User object * @param \phpbb\user $user User object
*/ */
public function __construct(\phpbb\request\request $request, \phpbb\template\template $template, \phpbb\user $user) public function __construct(\phpbb\auth\auth $auth, \phpbb\request\request $request, \phpbb\template\template $template, \phpbb\user $user)
{ {
$this->auth = $auth;
$this->request = $request; $this->request = $request;
$this->template = $template; $this->template = $template;
$this->user = $user; $this->user = $user;
@ -99,6 +107,17 @@ class type_string extends type_string_common
*/ */
public function validate_profile_field(&$field_value, $field_data) public function validate_profile_field(&$field_value, $field_data)
{ {
/**
* Check for out-of-bounds characters that are currently
* not supported by utf8_bin in MySQL if Emoji is not allowed
*/
if (!$this->auth->acl_get('u_emoji'))
{
if (preg_match_all('/[\x{10000}-\x{10FFFF}]/u', $field_value))
{
return $this->user->lang('FIELD_INVALID_CHARS_INVALID', $this->get_field_name($field_data['lang_name']));
}
}
return $this->validate_string_profile_field('string', $field_value, $field_data); return $this->validate_string_profile_field('string', $field_value, $field_data);
} }

View file

@ -15,6 +15,12 @@ namespace phpbb\profilefields\type;
class type_text extends type_string_common class type_text extends type_string_common
{ {
/**
* Auth object
* @var \phpbb\auth\auth
*/
protected $auth;
/** /**
* Request object * Request object
* @var \phpbb\request\request * @var \phpbb\request\request
@ -36,12 +42,14 @@ class type_text extends type_string_common
/** /**
* Construct * Construct
* *
* @param \phpbb\auth\auth $auth Auth object
* @param \phpbb\request\request $request Request object * @param \phpbb\request\request $request Request object
* @param \phpbb\template\template $template Template object * @param \phpbb\template\template $template Template object
* @param \phpbb\user $user User object * @param \phpbb\user $user User object
*/ */
public function __construct(\phpbb\request\request $request, \phpbb\template\template $template, \phpbb\user $user) public function __construct(\phpbb\auth\auth $auth, \phpbb\request\request $request, \phpbb\template\template $template, \phpbb\user $user)
{ {
$this->auth = $auth;
$this->request = $request; $this->request = $request;
$this->template = $template; $this->template = $template;
$this->user = $user; $this->user = $user;
@ -99,6 +107,17 @@ class type_text extends type_string_common
*/ */
public function validate_profile_field(&$field_value, $field_data) public function validate_profile_field(&$field_value, $field_data)
{ {
/**
* Check for out-of-bounds characters that are currently
* not supported by utf8_bin in MySQL if Emoji is not allowed
*/
if (!$this->auth->acl_get('u_emoji'))
{
if (preg_match_all('/[\x{10000}-\x{10FFFF}]/u', $field_value))
{
return $this->user->lang('FIELD_INVALID_CHARS_INVALID', $this->get_field_name($field_data['lang_name']));
}
}
return $this->validate_string_profile_field('text', $field_value, $field_data); return $this->validate_string_profile_field('text', $field_value, $field_data);
} }

View file

@ -26,6 +26,7 @@ class phpbb_profilefield_type_string_test extends phpbb_test_case
{ {
global $config, $request, $user, $cache, $phpbb_root_path, $phpEx; global $config, $request, $user, $cache, $phpbb_root_path, $phpEx;
$auth = new \phpbb\auth\auth();
$user = $this->getMock('\phpbb\user', array(), array( $user = $this->getMock('\phpbb\user', array(), array(
new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)),
'\phpbb\datetime' '\phpbb\datetime'
@ -40,6 +41,7 @@ class phpbb_profilefield_type_string_test extends phpbb_test_case
$template = $this->getMock('\phpbb\template\template'); $template = $this->getMock('\phpbb\template\template');
$this->cp = new \phpbb\profilefields\type\type_string( $this->cp = new \phpbb\profilefields\type\type_string(
$auth,
$request, $request,
$template, $template,
$user $user

View file

@ -30,6 +30,7 @@ class phpbb_profilefield_type_url_test extends phpbb_test_case
{ {
global $config, $request, $user, $cache, $phpbb_root_path, $phpEx; global $config, $request, $user, $cache, $phpbb_root_path, $phpEx;
$auth = new \phpbb\auth\auth();
$config = new \phpbb\config\config([]); $config = new \phpbb\config\config([]);
$cache = new phpbb_mock_cache; $cache = new phpbb_mock_cache;
$user = $this->getMock('\phpbb\user', array(), array( $user = $this->getMock('\phpbb\user', array(), array(
@ -44,6 +45,7 @@ class phpbb_profilefield_type_url_test extends phpbb_test_case
$template = $this->getMock('\phpbb\template\template'); $template = $this->getMock('\phpbb\template\template');
$this->cp = new \phpbb\profilefields\type\type_url( $this->cp = new \phpbb\profilefields\type\type_url(
$auth,
$request, $request,
$template, $template,
$user $user