Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/5.x' into v6_fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
danog committed Oct 22, 2023
2 parents 75fcfe3 + c7d7b48 commit 71483b7
Show file tree
Hide file tree
Showing 77 changed files with 806 additions and 207 deletions.
13 changes: 10 additions & 3 deletions dictionaries/CallMap.php
Original file line number Diff line number Diff line change
Expand Up @@ -12886,10 +12886,16 @@
'str_contains' => ['bool', 'haystack'=>'string', 'needle'=>'string'],
'str_ends_with' => ['bool', 'haystack'=>'string', 'needle'=>'string'],
'str_getcsv' => ['non-empty-list<?string>', 'string'=>'string', 'separator='=>'string', 'enclosure='=>'string', 'escape='=>'string'],
'str_ireplace' => ['string|string[]', 'search'=>'string|array', 'replace'=>'string|array', 'subject'=>'string|array', '&w_count='=>'int'],
'str_ireplace' => ['string', 'search'=>'string', 'replace'=>'string', 'subject'=>'string', '&w_count='=>'int'],
'str_ireplace\'1' => ['string[]', 'search'=>'string', 'replace'=>'string', 'subject'=>'array', '&w_count='=>'int'],
'str_ireplace\'2' => ['string', 'search'=>'array', 'replace'=>'string|string[]', 'subject'=>'string', '&w_count='=>'int'],
'str_ireplace\'3' => ['string[]', 'search'=>'array', 'replace'=>'string|string[]', 'subject'=>'array', '&w_count='=>'int'],
'str_pad' => ['string', 'string'=>'string', 'length'=>'int', 'pad_string='=>'string', 'pad_type='=>'int'],
'str_repeat' => ['string', 'string'=>'string', 'times'=>'int'],
'str_replace' => ['string|string[]', 'search'=>'string|array', 'replace'=>'string|array', 'subject'=>'string|array', '&w_count='=>'int'],
'str_replace' => ['string', 'search'=>'string', 'replace'=>'string', 'subject'=>'string', '&w_count='=>'int'],
'str_replace\'1' => ['string[]', 'search'=>'string', 'replace'=>'string', 'subject'=>'array', '&w_count='=>'int'],
'str_replace\'2' => ['string', 'search'=>'array', 'replace'=>'string|string[]', 'subject'=>'string', '&w_count='=>'int'],
'str_replace\'3' => ['string[]', 'search'=>'array', 'replace'=>'string|string[]', 'subject'=>'array', '&w_count='=>'int'],
'str_rot13' => ['string', 'string'=>'string'],
'str_shuffle' => ['string', 'string'=>'string'],
'str_split' => ['list<non-empty-string>', 'string'=>'string', 'length='=>'positive-int'],
Expand Down Expand Up @@ -13015,7 +13021,8 @@
'substr' => ['string', 'string'=>'string', 'offset'=>'int', 'length='=>'?int'],
'substr_compare' => ['int', 'haystack'=>'string', 'needle'=>'string', 'offset'=>'int', 'length='=>'?int', 'case_insensitive='=>'bool'],
'substr_count' => ['int', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int', 'length='=>'?int'],
'substr_replace' => ['string|string[]', 'string'=>'string|string[]', 'replace'=>'string|string[]', 'offset'=>'int|int[]', 'length='=>'int|int[]|null'],
'substr_replace' => ['string', 'string'=>'string', 'replace'=>'string|string[]', 'offset'=>'int|int[]', 'length='=>'int|int[]|null'],
'substr_replace\'1' => ['string[]', 'string'=>'string[]', 'replace'=>'string|string[]', 'offset'=>'int|int[]', 'length='=>'int|int[]|null'],
'suhosin_encrypt_cookie' => ['string|false', 'name'=>'string', 'value'=>'string'],
'suhosin_get_raw_cookies' => ['array'],
'SVM::__construct' => ['void'],
Expand Down
8 changes: 6 additions & 2 deletions dictionaries/CallMap_80_delta.php
Original file line number Diff line number Diff line change
Expand Up @@ -2589,8 +2589,12 @@
'new' => ['string', 'string'=>'string', 'offset'=>'int', 'length='=>'?int'],
],
'substr_replace' => [
'old' => ['string|string[]', 'string'=>'string|string[]', 'replace'=>'string|string[]', 'offset'=>'int|int[]', 'length='=>'int|int[]'],
'new' => ['string|string[]', 'string'=>'string|string[]', 'replace'=>'string|string[]', 'offset'=>'int|int[]', 'length='=>'int|int[]|null'],
'old' => ['string', 'string'=>'string', 'replace'=>'string|string[]', 'offset'=>'int|int[]', 'length='=>'int|int[]'],
'new' => ['string', 'string'=>'string', 'replace'=>'string|string[]', 'offset'=>'int|int[]', 'length='=>'int|int[]|null'],
],
'substr_replace\'1' => [
'old' => ['string[]', 'string'=>'string[]', 'replace'=>'string|string[]', 'offset'=>'int|int[]', 'length='=>'int|int[]'],
'new' => ['string[]', 'string'=>'string[]', 'replace'=>'string|string[]', 'offset'=>'int|int[]', 'length='=>'int|int[]|null'],
],
'tidy_parse_file' => [
'old' => ['tidy', 'filename'=>'string', 'config='=>'array|string', 'encoding='=>'string', 'useIncludePath='=>'bool'],
Expand Down
13 changes: 10 additions & 3 deletions dictionaries/CallMap_historical.php
Original file line number Diff line number Diff line change
Expand Up @@ -14303,10 +14303,16 @@
'stomp_unsubscribe' => ['bool', 'link'=>'resource', 'destination'=>'string', 'headers='=>'?array'],
'stomp_version' => ['string'],
'str_getcsv' => ['non-empty-list<?string>', 'string'=>'string', 'separator='=>'string', 'enclosure='=>'string', 'escape='=>'string'],
'str_ireplace' => ['string|string[]', 'search'=>'string|array', 'replace'=>'string|array', 'subject'=>'string|array', '&w_count='=>'int'],
'str_ireplace' => ['string', 'search'=>'string', 'replace'=>'string', 'subject'=>'string', '&w_count='=>'int'],
'str_ireplace\'1' => ['string[]', 'search'=>'string', 'replace'=>'string', 'subject'=>'array', '&w_count='=>'int'],
'str_ireplace\'2' => ['string', 'search'=>'array', 'replace'=>'string|string[]', 'subject'=>'string', '&w_count='=>'int'],
'str_ireplace\'3' => ['string[]', 'search'=>'array', 'replace'=>'string|string[]', 'subject'=>'array', '&w_count='=>'int'],
'str_pad' => ['string', 'string'=>'string', 'length'=>'int', 'pad_string='=>'string', 'pad_type='=>'int'],
'str_repeat' => ['string', 'string'=>'string', 'times'=>'int'],
'str_replace' => ['string|string[]', 'search'=>'string|array', 'replace'=>'string|array', 'subject'=>'string|array', '&w_count='=>'int'],
'str_replace' => ['string', 'search'=>'string', 'replace'=>'string', 'subject'=>'string', '&w_count='=>'int'],
'str_replace\'1' => ['string[]', 'search'=>'string', 'replace'=>'string', 'subject'=>'array', '&w_count='=>'int'],
'str_replace\'2' => ['string', 'search'=>'array', 'replace'=>'string|string[]', 'subject'=>'string', '&w_count='=>'int'],
'str_replace\'3' => ['string[]', 'search'=>'array', 'replace'=>'string|string[]', 'subject'=>'array', '&w_count='=>'int'],
'str_rot13' => ['string', 'string'=>'string'],
'str_shuffle' => ['string', 'string'=>'string'],
'str_split' => ['non-empty-list<string>', 'string'=>'string', 'length='=>'positive-int'],
Expand Down Expand Up @@ -14430,7 +14436,8 @@
'substr' => ['string|false', 'string'=>'string', 'offset'=>'int', 'length='=>'int'],
'substr_compare' => ['int|false', 'haystack'=>'string', 'needle'=>'string', 'offset'=>'int', 'length='=>'int', 'case_insensitive='=>'bool'],
'substr_count' => ['int', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int', 'length='=>'int'],
'substr_replace' => ['string|string[]', 'string'=>'string|string[]', 'replace'=>'string|string[]', 'offset'=>'int|int[]', 'length='=>'int|int[]'],
'substr_replace' => ['string', 'string'=>'string', 'replace'=>'string|string[]', 'offset'=>'int|int[]', 'length='=>'int|int[]'],
'substr_replace\'1' => ['string[]', 'string'=>'string[]', 'replace'=>'string|string[]', 'offset'=>'int|int[]', 'length='=>'int|int[]'],
'suhosin_encrypt_cookie' => ['string|false', 'name'=>'string', 'value'=>'string'],
'suhosin_get_raw_cookies' => ['array'],
'svm::crossvalidate' => ['float', 'problem'=>'array', 'number_of_folds'=>'int'],
Expand Down
3 changes: 2 additions & 1 deletion dictionaries/ImpureFunctionsList.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@
'socket_set_block' => true,
'socket_set_nonblock' => true,
'socket_listen' => true,
'stream_socket_shutdown' => true,
'socket_shutdown' => true,
// meta calls
'call_user_func' => true,
'call_user_func_array' => true,
Expand All @@ -93,7 +95,6 @@
'mcrypt_generic_deinit' => true,
'mcrypt_module_close' => true,
// internal optimisation
'opcache_compile_file' => true,
'clearstatcache' => true,
// process-related
'pcntl_signal' => true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
$removed_foreign_functions
);

uksort($new_local, fn($a, $b) => strtolower($a) <=> strtolower($b));
uksort($new_local, static fn($a, $b) => strtolower($a) <=> strtolower($b));

foreach ($new_local as $name => $data) {
if (!is_array($data)) {
Expand Down
1 change: 1 addition & 0 deletions docs/security_analysis/custom_taint_sources.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ class BadSqlTainter implements AfterExpressionAnalysisInterface
);
}
}
return null;
}
}
```
2 changes: 1 addition & 1 deletion examples/plugins/ClassUnqualifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public static function afterClassLikeExistenceCheck(
$new_candidate_type = implode(
'',
array_map(
fn($f) => $f[0],
static fn($f) => $f[0],
$type_tokens,
),
);
Expand Down
3 changes: 1 addition & 2 deletions src/Psalm/Codebase.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@
use UnexpectedValueException;

use function array_combine;
use function array_merge;
use function array_pop;
use function array_reverse;
use function array_values;
Expand Down Expand Up @@ -1605,7 +1604,7 @@ public function getCompletionItemsForClassishThing(
);
}

$completion_items = array_merge($completion_items, array_values($pseudo_property_types));
$completion_items = [...$completion_items, ...array_values($pseudo_property_types)];

foreach ($class_storage->declaring_property_ids as $property_name => $declaring_class) {
$property_storage = $this->properties->getStorage(
Expand Down
6 changes: 5 additions & 1 deletion src/Psalm/Internal/Analyzer/ClassLikeAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ public static function checkFullyQualifiedClassLikeName(
?string $calling_method_id,
array $suppressed_issues,
?ClassLikeNameOptions $options = null,
bool $check_classes = true
): ?bool {
if ($options === null) {
$options = new ClassLikeNameOptions();
Expand Down Expand Up @@ -278,6 +279,9 @@ public static function checkFullyQualifiedClassLikeName(
&& !($interface_exists && $options->allow_interface)
&& !($enum_exists && $options->allow_enum)
) {
if (!$check_classes) {
return null;
}
if (!$options->allow_trait || !$codebase->classlikes->traitExists($fq_class_name, $code_location)) {
if ($options->from_docblock) {
if (IssueBuffer::accepts(
Expand Down Expand Up @@ -703,7 +707,7 @@ protected function checkTemplateParams(
&& $storage->template_types
&& $storage->template_covariants
&& ($local_offset
= array_search($t->param_name, array_keys($storage->template_types)))
= array_search($t->param_name, array_keys($storage->template_types), true))
!== false
&& !empty($storage->template_covariants[$local_offset])
) {
Expand Down
3 changes: 1 addition & 2 deletions src/Psalm/Internal/Analyzer/CommentAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
use Psalm\Type\Union;
use UnexpectedValueException;

use function array_merge;
use function count;
use function is_string;
use function preg_match;
Expand Down Expand Up @@ -402,7 +401,7 @@ public static function splitDocLine(string $return_block): array
$remaining = trim((string) preg_replace('@^[ \t]*\* *@m', ' ', substr($return_block, $i + 1)));

if ($remaining) {
return array_merge([rtrim($type)], preg_split('/\s+/', $remaining) ?: []);
return [rtrim($type), ...preg_split('/\s+/', $remaining) ?: []];
}

return [$type];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ public static function verifyReturnType(
)
)
&& !$return_type->isVoid()
&& !$return_type->isNever()
&& !$inferred_yield_types
&& (!$function_like_storage || !$function_like_storage->has_yield)
&& $function_returns_implicitly
Expand All @@ -224,7 +225,7 @@ public static function verifyReturnType(
) {
if (IssueBuffer::accepts(
new InvalidReturnType(
$cased_method_id . ' is not expected to return any values but it does, '
$cased_method_id . ' is not expected to return, but it does, '
. 'either implicitly or explicitly',
$return_type_location,
),
Expand Down
11 changes: 11 additions & 0 deletions src/Psalm/Internal/Analyzer/FunctionLikeAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -1262,6 +1262,17 @@ private function processParams(
);
}

if ($param_type->isNever()) {
IssueBuffer::maybeAdd(
new ReservedWord(
'Parameter cannot be never',
$function_param->type_location,
'never',
),
$this->suppressed_issues,
);
}

if ($param_type->check(
$this->source,
$function_param->type_location,
Expand Down
10 changes: 10 additions & 0 deletions src/Psalm/Internal/Analyzer/MethodComparator.php
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,16 @@ private static function checkForObviousMethodMismatches(
);
}

if ($guide_method_storage->returns_by_ref && !$implementer_method_storage->returns_by_ref) {
IssueBuffer::maybeAdd(
new MethodSignatureMismatch(
'Method ' . $cased_implementer_method_id . ' must return by-reference',
$code_location,
),
$suppressed_issues + $implementer_classlike_storage->suppressed_issues,
);
}

if ($guide_method_storage->external_mutation_free
&& !$implementer_method_storage->external_mutation_free
&& !$guide_method_storage->mutation_free_inferred
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1092,7 +1092,7 @@ private static function getExtendedType(
): ?Union {
if ($calling_class === $template_class) {
if (isset($class_template_types[$template_name]) && $calling_type_params) {
$offset = array_search($template_name, array_keys($class_template_types));
$offset = array_search($template_name, array_keys($class_template_types), true);

if ($offset !== false && isset($calling_type_params[$offset])) {
return $calling_type_params[$offset];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -671,16 +671,14 @@ private static function analyzeAssignment(
return false;
}

if ($context->check_classes) {
if (StaticPropertyAssignmentAnalyzer::analyze(
$statements_analyzer,
$assign_var,
$assign_value,
$assign_value_type,
$context,
) === false) {
return false;
}
if (StaticPropertyAssignmentAnalyzer::analyze(
$statements_analyzer,
$assign_var,
$assign_value,
$assign_value_type,
$context,
) === false) {
return false;
}

if ($var_id) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
use Psalm\Type\Union;
use UnexpectedValueException;

use function array_merge;
use function in_array;
use function strlen;

Expand Down Expand Up @@ -172,6 +173,14 @@ public static function analyze(
$removed_taints = $codebase->config->eventDispatcher->dispatchRemoveTaints($event);

if ($stmt_left_type && $stmt_left_type->parent_nodes) {
// numeric types can't be tainted html or has_quotes, neither can bool
if ($statements_analyzer->data_flow_graph instanceof TaintFlowGraph
&& $stmt_left_type->isSingle()
&& ($stmt_left_type->isInt() || $stmt_left_type->isFloat() || $stmt_left_type->isBool())
) {
$removed_taints = array_merge($removed_taints, array('html', 'has_quotes'));
}

foreach ($stmt_left_type->parent_nodes as $parent_node) {
$statements_analyzer->data_flow_graph->addPath(
$parent_node,
Expand All @@ -184,6 +193,14 @@ public static function analyze(
}

if ($stmt_right_type && $stmt_right_type->parent_nodes) {
// numeric types can't be tainted html or has_quotes, neither can bool
if ($statements_analyzer->data_flow_graph instanceof TaintFlowGraph
&& $stmt_right_type->isSingle()
&& ($stmt_right_type->isInt() || $stmt_right_type->isFloat() || $stmt_right_type->isBool())
) {
$removed_taints = array_merge($removed_taints, array('html', 'has_quotes'));
}

foreach ($stmt_right_type->parent_nodes as $parent_node) {
$statements_analyzer->data_flow_graph->addPath(
$parent_node,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
use Psalm\Type\Atomic\TNamedObject;
use Psalm\Type\Union;

use function array_merge;
use function count;
use function explode;
use function implode;
Expand Down Expand Up @@ -1486,19 +1487,19 @@ private static function processTaintedness(
return;
}

// numeric types can't be tainted, neither can bool
$event = new AddRemoveTaintsEvent($expr, $context, $statements_analyzer, $codebase);

$added_taints = $codebase->config->eventDispatcher->dispatchAddTaints($event);
$removed_taints = $codebase->config->eventDispatcher->dispatchRemoveTaints($event);

// numeric types can't be tainted html or has_quotes, neither can bool
if ($statements_analyzer->data_flow_graph instanceof TaintFlowGraph
&& $input_type->isSingle()
&& ($input_type->isInt() || $input_type->isFloat() || $input_type->isBool())
) {
return;
$removed_taints = array_merge($removed_taints, array('html', 'has_quotes'));
}

$event = new AddRemoveTaintsEvent($expr, $context, $statements_analyzer, $codebase);

$added_taints = $codebase->config->eventDispatcher->dispatchAddTaints($event);
$removed_taints = $codebase->config->eventDispatcher->dispatchRemoveTaints($event);

if ($function_param->type && $function_param->type->isString() && !$input_type->isString()) {
$input_type = CastAnalyzer::castStringAttempt(
$statements_analyzer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ final class AtomicMethodCallAnalysisResult
public array $invalid_method_call_types = [];

/**
* @var array<string>
* @var array<string, bool>
*/
public array $existent_method_ids = [];

Expand Down
Loading

0 comments on commit 71483b7

Please sign in to comment.