1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-27 04:45:20 +01:00

Merge remote-tracking branch 'upstream/4.x' into upstream-master9

This commit is contained in:
orklah 2022-02-14 00:10:28 +01:00
commit 1142c818c2
5 changed files with 117 additions and 0 deletions

View File

@ -155,6 +155,13 @@ final class Context
*/
public $inside_assignment = false;
/**
* Whether or not we're inside a try block.
*
* @var bool
*/
public $inside_try = false;
/**
* @var null|CodeLocation
*/

View File

@ -85,9 +85,12 @@ class TryAnalyzer
$old_referenced_var_ids = $try_context->referenced_var_ids;
$was_inside_try = $context->inside_try;
$context->inside_try = true;
if ($statements_analyzer->analyze($stmt->stmts, $context) === false) {
return false;
}
$context->inside_try = $was_inside_try;
if ($try_context->finally_scope) {
foreach ($context->vars_in_scope as $var_id => $type) {

View File

@ -326,6 +326,14 @@ class AssignmentAnalyzer
$assign_value_type->parent_nodes = [
$assignment_node->id => $assignment_node
];
if ($context->inside_try) {
// Copy previous assignment's parent nodes inside a try. Since an exception could be thrown at any
// point this is a workaround to ensure that use of a variable also uses all previous assignments.
if (isset($context->vars_in_scope[$extended_var_id])) {
$assign_value_type->parent_nodes += $context->vars_in_scope[$extended_var_id]->parent_nodes;
}
}
}
if ($extended_var_id && isset($context->vars_in_scope[$extended_var_id])) {

View File

@ -2285,6 +2285,25 @@ class TaintTest extends TestCase
echo sinkNotWorking($_GET["taint"]);',
'error_message' => 'TaintedHtml',
],
'taintEscapedInTryMightNotWork' => [
'<?php
/** @psalm-taint-escape html */
function escapeHtml(string $arg): string
{
return htmlspecialchars($arg);
}
$tainted = $_GET["foo"];
try {
$tainted = escapeHtml($tainted);
} catch (Throwable $_) {
}
echo $tainted;
',
'error_message' => 'TaintedHtml',
],
];
}

View File

@ -2462,6 +2462,43 @@ class UnusedVariableTest extends TestCase
$a = false;
}'
],
'usedInCatchIsAlwaysUsedInTry' => [
'<?php
$step = 0;
try {
$step = 1;
$step = 2;
} catch (Throwable $_) {
echo $step;
}
',
],
'usedInFinallyIsAlwaysUsedInTry' => [
'<?php
$step = 0;
try {
$step = 1;
$step = 2;
} finally {
echo $step;
}
',
],
'usedInFinallyIsAlwaysUsedInTryWithNestedTry' => [
'<?php
$step = 0;
try {
try {
$step = 1;
} finally {
}
$step = 2;
$step = 3;
} finally {
echo $step;
}
',
],
'referenceUseUsesReferencedVariable' => [
'code' => '<?php
$a = 1;
@ -3530,6 +3567,49 @@ class UnusedVariableTest extends TestCase
}',
'error_message' => 'MixedArgumentTypeCoercion - src' . DIRECTORY_SEPARATOR . 'somefile.php:12:44 - Argument 1 of takesArrayOfString expects array<array-key, string>, parent type array{mixed} provided. Consider improving the type at src' . DIRECTORY_SEPARATOR . 'somefile.php:10:41'
],
'warnAboutUnusedVariableInTryReassignedInCatch' => [
'<?php
$step = 0;
try {
$step = 1;
$step = 2;
} catch (Throwable $_) {
$step = 3;
echo $step;
}
',
'error_message' => 'UnusedVariable',
],
'warnAboutUnusedVariableInTryReassignedInFinally' => [
'<?php
$step = 0;
try {
$step = 1;
$step = 2;
} finally {
$step = 3;
echo $step;
}
',
'error_message' => 'UnusedVariable',
],
'SKIPPED-warnAboutVariableUsedInNestedTryNotUsedInOuterTry' => [
'<?php
$step = 0;
try {
$step = 1; // Unused
$step = 2;
try {
$step = 3;
$step = 4;
} finally {
echo $step;
}
} finally {
}
',
'error_message' => 'UnusedVariable',
],
'referenceReassignmentUnusedVariable' => [
'code' => '<?php
$a = $b = 1;