Merge branch '4.4' into 5.2
* 4.4: [Security/Core] fix checking for bcrypt [HttpFoundation] Fixes for PHP 8.1 deprecations [Mime] DataPart: remove confusing fix-me comment expose references detected in inline notation structures
This commit is contained in:
commit
92b6458f60
@ -306,7 +306,7 @@ class Request
|
||||
|
||||
if ($_POST) {
|
||||
$request->request = new InputBag($_POST);
|
||||
} elseif (0 === strpos($request->headers->get('CONTENT_TYPE'), 'application/x-www-form-urlencoded')
|
||||
} elseif (0 === strpos($request->headers->get('CONTENT_TYPE', ''), 'application/x-www-form-urlencoded')
|
||||
&& \in_array(strtoupper($request->server->get('REQUEST_METHOD', 'GET')), ['PUT', 'DELETE', 'PATCH'])
|
||||
) {
|
||||
parse_str($request->getContent(), $data);
|
||||
@ -1405,7 +1405,7 @@ class Request
|
||||
*/
|
||||
public function getContentType()
|
||||
{
|
||||
return $this->getFormat($this->headers->get('CONTENT_TYPE'));
|
||||
return $this->getFormat($this->headers->get('CONTENT_TYPE', ''));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1600,7 +1600,7 @@ class Request
|
||||
*/
|
||||
public function getETags()
|
||||
{
|
||||
return preg_split('/\s*,\s*/', $this->headers->get('if_none_match'), -1, \PREG_SPLIT_NO_EMPTY);
|
||||
return preg_split('/\s*,\s*/', $this->headers->get('if_none_match', ''), -1, \PREG_SPLIT_NO_EMPTY);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1849,13 +1849,13 @@ class Request
|
||||
*/
|
||||
protected function prepareBaseUrl()
|
||||
{
|
||||
$filename = basename($this->server->get('SCRIPT_FILENAME'));
|
||||
$filename = basename($this->server->get('SCRIPT_FILENAME', ''));
|
||||
|
||||
if (basename($this->server->get('SCRIPT_NAME')) === $filename) {
|
||||
if (basename($this->server->get('SCRIPT_NAME', '')) === $filename) {
|
||||
$baseUrl = $this->server->get('SCRIPT_NAME');
|
||||
} elseif (basename($this->server->get('PHP_SELF')) === $filename) {
|
||||
} elseif (basename($this->server->get('PHP_SELF', '')) === $filename) {
|
||||
$baseUrl = $this->server->get('PHP_SELF');
|
||||
} elseif (basename($this->server->get('ORIG_SCRIPT_NAME')) === $filename) {
|
||||
} elseif (basename($this->server->get('ORIG_SCRIPT_NAME', '')) === $filename) {
|
||||
$baseUrl = $this->server->get('ORIG_SCRIPT_NAME'); // 1and1 shared hosting compatibility
|
||||
} else {
|
||||
// Backtrack up the script_filename to find the portion matching
|
||||
@ -1895,7 +1895,7 @@ class Request
|
||||
$truncatedRequestUri = substr($requestUri, 0, $pos);
|
||||
}
|
||||
|
||||
$basename = basename($baseUrl);
|
||||
$basename = basename($baseUrl ?? '');
|
||||
if (empty($basename) || !strpos(rawurldecode($truncatedRequestUri), $basename)) {
|
||||
// no match whatsoever; set it blank
|
||||
return '';
|
||||
@ -2046,7 +2046,7 @@ class Request
|
||||
*/
|
||||
public function isFromTrustedProxy()
|
||||
{
|
||||
return self::$trustedProxies && IpUtils::checkIp($this->server->get('REMOTE_ADDR'), self::$trustedProxies);
|
||||
return self::$trustedProxies && IpUtils::checkIp($this->server->get('REMOTE_ADDR', ''), self::$trustedProxies);
|
||||
}
|
||||
|
||||
private function getTrustedValues(int $type, string $ip = null): array
|
||||
|
@ -9,4 +9,4 @@ $str = '?*():@&+$/%#[]';
|
||||
$r->headers->setCookie(new Cookie($str, $str, 0, '/', null, false, false, true, null));
|
||||
$r->sendHeaders();
|
||||
|
||||
setrawcookie($str, $str, 0, '/', null, false, false);
|
||||
setrawcookie($str, $str, 0, '/', '', false, false);
|
||||
|
@ -46,8 +46,6 @@ class DataPart extends TextPart
|
||||
|
||||
public static function fromPath(string $path, string $name = null, string $contentType = null): self
|
||||
{
|
||||
// FIXME: if file is not readable, exception?
|
||||
|
||||
if (null === $contentType) {
|
||||
$ext = strtolower(substr($path, strrpos($path, '.') + 1));
|
||||
if (null === self::$mimeTypes) {
|
||||
|
@ -51,11 +51,11 @@ final class NativePasswordEncoder implements PasswordEncoderInterface, SelfSalti
|
||||
$algos = [1 => \PASSWORD_BCRYPT, '2y' => \PASSWORD_BCRYPT];
|
||||
|
||||
if (\defined('PASSWORD_ARGON2I')) {
|
||||
$this->algo = $algos[2] = $algos['argon2i'] = (string) \PASSWORD_ARGON2I;
|
||||
$this->algo = $algos[2] = $algos['argon2i'] = \PASSWORD_ARGON2I;
|
||||
}
|
||||
|
||||
if (\defined('PASSWORD_ARGON2ID')) {
|
||||
$this->algo = $algos[3] = $algos['argon2id'] = (string) \PASSWORD_ARGON2ID;
|
||||
$this->algo = $algos[3] = $algos['argon2id'] = \PASSWORD_ARGON2ID;
|
||||
}
|
||||
|
||||
if (null !== $algo) {
|
||||
@ -75,7 +75,7 @@ final class NativePasswordEncoder implements PasswordEncoderInterface, SelfSalti
|
||||
*/
|
||||
public function encodePassword(string $raw, ?string $salt): string
|
||||
{
|
||||
if (\strlen($raw) > self::MAX_PASSWORD_LENGTH || ((string) \PASSWORD_BCRYPT === $this->algo && 72 < \strlen($raw))) {
|
||||
if (\strlen($raw) > self::MAX_PASSWORD_LENGTH || (\PASSWORD_BCRYPT === $this->algo && 72 < \strlen($raw))) {
|
||||
throw new BadCredentialsException('Invalid password.');
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ class Inline
|
||||
*
|
||||
* @throws ParseException
|
||||
*/
|
||||
public static function parse(string $value = null, int $flags = 0, array $references = [])
|
||||
public static function parse(string $value = null, int $flags = 0, array &$references = [])
|
||||
{
|
||||
self::initialize($flags);
|
||||
|
||||
@ -267,7 +267,7 @@ class Inline
|
||||
*
|
||||
* @throws ParseException When malformed inline YAML string is parsed
|
||||
*/
|
||||
public static function parseScalar(string $scalar, int $flags = 0, array $delimiters = null, int &$i = 0, bool $evaluate = true, array $references = [])
|
||||
public static function parseScalar(string $scalar, int $flags = 0, array $delimiters = null, int &$i = 0, bool $evaluate = true, array &$references = [])
|
||||
{
|
||||
if (\in_array($scalar[$i], ['"', "'"], true)) {
|
||||
// quoted scalar
|
||||
@ -343,7 +343,7 @@ class Inline
|
||||
*
|
||||
* @throws ParseException When malformed inline YAML string is parsed
|
||||
*/
|
||||
private static function parseSequence(string $sequence, int $flags, int &$i = 0, array $references = []): array
|
||||
private static function parseSequence(string $sequence, int $flags, int &$i = 0, array &$references = []): array
|
||||
{
|
||||
$output = [];
|
||||
$len = \strlen($sequence);
|
||||
@ -385,6 +385,11 @@ class Inline
|
||||
}
|
||||
}
|
||||
|
||||
if (\is_string($value) && '' !== $value && '&' === $value[0] && Parser::preg_match(Parser::REFERENCE_PATTERN, $value, $matches)) {
|
||||
$references[$matches['ref']] = $matches['value'];
|
||||
$value = $matches['value'];
|
||||
}
|
||||
|
||||
--$i;
|
||||
}
|
||||
|
||||
@ -407,7 +412,7 @@ class Inline
|
||||
*
|
||||
* @throws ParseException When malformed inline YAML string is parsed
|
||||
*/
|
||||
private static function parseMapping(string $mapping, int $flags, int &$i = 0, array $references = [])
|
||||
private static function parseMapping(string $mapping, int $flags, int &$i = 0, array &$references = [])
|
||||
{
|
||||
$output = [];
|
||||
$len = \strlen($mapping);
|
||||
@ -433,14 +438,14 @@ class Inline
|
||||
// key
|
||||
$offsetBeforeKeyParsing = $i;
|
||||
$isKeyQuoted = \in_array($mapping[$i], ['"', "'"], true);
|
||||
$key = self::parseScalar($mapping, $flags, [':', ' '], $i, false, []);
|
||||
$key = self::parseScalar($mapping, $flags, [':', ' '], $i, false);
|
||||
|
||||
if ($offsetBeforeKeyParsing === $i) {
|
||||
throw new ParseException('Missing mapping key.', self::$parsedLineNumber + 1, $mapping);
|
||||
}
|
||||
|
||||
if ('!php/const' === $key) {
|
||||
$key .= ' '.self::parseScalar($mapping, $flags, [':'], $i, false, []);
|
||||
$key .= ' '.self::parseScalar($mapping, $flags, [':'], $i, false);
|
||||
$key = self::evaluateScalar($key, $flags);
|
||||
}
|
||||
|
||||
@ -522,6 +527,11 @@ class Inline
|
||||
if ('<<' === $key) {
|
||||
$output += $value;
|
||||
} elseif ($allowOverwrite || !isset($output[$key])) {
|
||||
if (\is_string($value) && '' !== $value && '&' === $value[0] && Parser::preg_match(Parser::REFERENCE_PATTERN, $value, $matches)) {
|
||||
$references[$matches['ref']] = $matches['value'];
|
||||
$value = $matches['value'];
|
||||
}
|
||||
|
||||
if (null !== $tag) {
|
||||
$output[$key] = new TaggedValue($tag, $value);
|
||||
} else {
|
||||
@ -548,7 +558,7 @@ class Inline
|
||||
*
|
||||
* @throws ParseException when object parsing support was disabled and the parser detected a PHP object or when a reference could not be resolved
|
||||
*/
|
||||
private static function evaluateScalar(string $scalar, int $flags, array $references = [])
|
||||
private static function evaluateScalar(string $scalar, int $flags, array &$references = [])
|
||||
{
|
||||
$scalar = trim($scalar);
|
||||
|
||||
|
@ -25,6 +25,7 @@ class Parser
|
||||
{
|
||||
public const TAG_PATTERN = '(?P<tag>![\w!.\/:-]+)';
|
||||
public const BLOCK_SCALAR_HEADER_PATTERN = '(?P<separator>\||>)(?P<modifiers>\+|\-|\d+|\+\d+|\-\d+|\d+\+|\d+\-)?(?P<comments> +#.*)?';
|
||||
public const REFERENCE_PATTERN = '#^&(?P<ref>[^ ]++) *+(?P<value>.*)#u';
|
||||
|
||||
private $filename;
|
||||
private $offset = 0;
|
||||
@ -161,7 +162,7 @@ class Parser
|
||||
}
|
||||
$context = 'sequence';
|
||||
|
||||
if (isset($values['value']) && '&' === $values['value'][0] && self::preg_match('#^&(?P<ref>[^ ]+) *(?P<value>.*)#u', $values['value'], $matches)) {
|
||||
if (isset($values['value']) && '&' === $values['value'][0] && self::preg_match(self::REFERENCE_PATTERN, $values['value'], $matches)) {
|
||||
$isRef = $matches['ref'];
|
||||
$this->refsBeingParsed[] = $isRef;
|
||||
$values['value'] = $matches['value'];
|
||||
@ -299,7 +300,7 @@ class Parser
|
||||
$data += $parsed; // array union
|
||||
}
|
||||
}
|
||||
} elseif ('<<' !== $key && isset($values['value']) && '&' === $values['value'][0] && self::preg_match('#^&(?P<ref>[^ ]++) *+(?P<value>.*)#u', $values['value'], $matches)) {
|
||||
} elseif ('<<' !== $key && isset($values['value']) && '&' === $values['value'][0] && self::preg_match(self::REFERENCE_PATTERN, $values['value'], $matches)) {
|
||||
$isRef = $matches['ref'];
|
||||
$this->refsBeingParsed[] = $isRef;
|
||||
$values['value'] = $matches['value'];
|
||||
|
@ -190,7 +190,8 @@ class InlineTest extends TestCase
|
||||
*/
|
||||
public function testParseReferences($yaml, $expected)
|
||||
{
|
||||
$this->assertSame($expected, Inline::parse($yaml, 0, ['var' => 'var-value']));
|
||||
$references = ['var' => 'var-value'];
|
||||
$this->assertSame($expected, Inline::parse($yaml, 0, $references));
|
||||
}
|
||||
|
||||
public function getDataForParseReferences()
|
||||
@ -214,7 +215,8 @@ class InlineTest extends TestCase
|
||||
'b' => 'Clark',
|
||||
'c' => 'Brian',
|
||||
];
|
||||
$this->assertSame([$foo], Inline::parse('[*foo]', 0, ['foo' => $foo]));
|
||||
$references = ['foo' => $foo];
|
||||
$this->assertSame([$foo], Inline::parse('[*foo]', 0, $references));
|
||||
}
|
||||
|
||||
public function testParseUnquotedAsterisk()
|
||||
|
@ -1072,6 +1072,10 @@ EOF
|
||||
'map' => ['key' => 'var-value'],
|
||||
'list_in_map' => ['key' => ['var-value']],
|
||||
'map_in_map' => ['foo' => ['bar' => 'var-value']],
|
||||
'foo' => ['bar' => 'baz'],
|
||||
'bar' => ['foo' => 'baz'],
|
||||
'baz' => ['foo'],
|
||||
'foobar' => ['foo'],
|
||||
], Yaml::parse(<<<'EOF'
|
||||
var: &var var-value
|
||||
scalar: *var
|
||||
@ -1082,6 +1086,10 @@ embedded_mapping: [ key: *var ]
|
||||
map: { key: *var }
|
||||
list_in_map: { key: [*var] }
|
||||
map_in_map: { foo: { bar: *var } }
|
||||
foo: { bar: &baz baz }
|
||||
bar: { foo: *baz }
|
||||
baz: [ &foo foo ]
|
||||
foobar: [ *foo ]
|
||||
EOF
|
||||
));
|
||||
}
|
||||
|
Reference in New Issue
Block a user