Skip to content

Commit

Permalink
Prevent string being used in non-empty-string location
Browse files Browse the repository at this point in the history
  • Loading branch information
muglug committed Jan 7, 2020
1 parent 07aaa3f commit cc9e0fa
Show file tree
Hide file tree
Showing 9 changed files with 54 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -561,10 +561,6 @@ function ($c) {
$context->vars_possibly_in_scope
);
} elseif ($stmt instanceof PhpParser\Node\Expr\BinaryOp\Concat) {
$stmt_type = Type::getString();

$statements_analyzer->node_data->setType($stmt, $stmt_type);

if (ExpressionAnalyzer::analyze($statements_analyzer, $stmt->left, $context) === false) {
return false;
}
Expand All @@ -573,16 +569,31 @@ function ($c) {
return false;
}

$stmt_left_type = $statements_analyzer->node_data->getType($stmt->left);
$stmt_right_type = $statements_analyzer->node_data->getType($stmt->right);

if ($stmt_left_type
&& $stmt_right_type
&& $stmt_left_type->getId() === 'non-empty-string'
&& $stmt_right_type->getId() === 'non-empty-string'
) {
$stmt_type = new Type\Union([new Type\Atomic\TNonEmptyString()]);
} else {
$stmt_type = Type::getString();
}

$statements_analyzer->node_data->setType($stmt, $stmt_type);

if ($codebase->taint) {
$sources = [];
$either_tainted = 0;

if ($stmt_left_type = $statements_analyzer->node_data->getType($stmt->left)) {
if ($stmt_left_type) {
$sources = $stmt_left_type->sources ?: [];
$either_tainted = $stmt_left_type->tainted;
}

if ($stmt_right_type = $statements_analyzer->node_data->getType($stmt->right)) {
if ($stmt_right_type) {
$sources = array_merge($sources, $stmt_right_type->sources ?: []);
$either_tainted = $either_tainted | $stmt_right_type->tainted;
}
Expand Down
20 changes: 10 additions & 10 deletions src/Psalm/Internal/Analyzer/TypeAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -767,6 +767,16 @@ public static function isAtomicContainedBy(
}
}

if ($container_type_part instanceof TNonEmptyString
&& get_class($input_type_part) === TString::class
) {
if ($atomic_comparison_result) {
$atomic_comparison_result->type_coerced = true;
}

return false;
}

if ($input_type_part->shallowEquals($container_type_part)
|| ($input_type_part instanceof Type\Atomic\TCallableObjectLikeArray
&& $container_type_part instanceof TArray)
Expand Down Expand Up @@ -1154,16 +1164,6 @@ public static function isAtomicContainedBy(
return true;
}

if ($container_type_part instanceof TNonEmptyString
&& get_class($input_type_part) === TString::class
) {
if ($atomic_comparison_result) {
$atomic_comparison_result->type_coerced = true;
}

return false;
}

if ($container_type_part instanceof TNonEmptyString
&& $input_type_part instanceof TLiteralString
&& $input_type_part->value === ''
Expand Down
8 changes: 4 additions & 4 deletions src/Psalm/Internal/Type/TemplateResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,18 @@
class TemplateResult
{
/**
* @var array<string, array<non-empty-string, array{0: Union}>>
* @var array<string, array<string, array{0: Union}>>
*/
public $template_types;

/**
* @var array<string, array<non-empty-string, array{0: Union, 1?: int}>>
* @var array<string, array<string, array{0: Union, 1?: int}>>
*/
public $generic_params;

/**
* @param array<string, array<non-empty-string, array{0: Union}>> $template_types
* @param array<string, array<non-empty-string, array{0: Union, 1?: int}>> $generic_params
* @param array<string, array<string, array{0: Union}>> $template_types
* @param array<string, array<string, array{0: Union, 1?: int}>> $generic_params
*/
public function __construct(array $template_types, array $generic_params)
{
Expand Down
5 changes: 1 addition & 4 deletions src/Psalm/Type/Atomic/TTemplateIndexedAccess.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,10 @@ class TTemplateIndexedAccess extends \Psalm\Type\Atomic
public $offset_param_name;

/**
* @var non-empty-string
* @var string
*/
public $defining_class;

/**
* @param non-empty-string $defining_class
*/
public function __construct(
string $array_param_name,
string $offset_param_name,
Expand Down
5 changes: 1 addition & 4 deletions src/Psalm/Type/Atomic/TTemplateKeyOf.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,10 @@ class TTemplateKeyOf extends TArrayKey
public $param_name;

/**
* @var non-empty-string
* @var string
*/
public $defining_class;

/**
* @param non-empty-string $defining_class
*/
public function __construct(
string $param_name,
string $defining_class
Expand Down
4 changes: 2 additions & 2 deletions src/Psalm/Type/Atomic/TTemplateParam.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ class TTemplateParam extends \Psalm\Type\Atomic
public $as;

/**
* @var non-empty-string
* @var string
*/
public $defining_class;

/**
* @param non-empty-string $defining_class
* @param string $defining_class
*/
public function __construct(string $param_name, Union $extends, string $defining_class)
{
Expand Down
6 changes: 1 addition & 5 deletions src/Psalm/Type/Atomic/TTemplateParamClass.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,10 @@ class TTemplateParamClass extends TClassString
public $as_type;

/**
* @var non-empty-string
* @var string
*/
public $defining_class;

/**
* @param non-empty-string $defining_class
* @param string $param_name
*/
public function __construct(
string $param_name,
string $as,
Expand Down
2 changes: 1 addition & 1 deletion src/Psalm/Type/Union.php
Original file line number Diff line number Diff line change
Expand Up @@ -1091,7 +1091,7 @@ public function substitute(Union $old_type, Union $new_type = null)
}

/**
* @param array<string, array<non-empty-string, array{Type\Union, 1?:int}>> $template_types
* @param array<string, array<string, array{Type\Union, 1?:int}>> $template_types
*
* @return void
*/
Expand Down
17 changes: 17 additions & 0 deletions tests/TypeReconciliation/ConditionalTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2872,6 +2872,23 @@ function test(App $app) : void {
}',
'error_message' => 'TypeDoesNotContainType',
],
'nonEmptyString' => [
'<?php
/**
* @psalm-param non-empty-string $name
*/
function sayHello(string $name) : void {
echo "Hello " . $name;
}
function takeInput() : void {
if (isset($_GET["name"]) && is_string($_GET["name"])) {
$name = trim($_GET["name"]);
sayHello($name);
}
}',
'error_message' => 'ArgumentTypeCoercion',
],
];
}
}

0 comments on commit cc9e0fa

Please sign in to comment.