Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 4ddbd81

Browse files
committed
Fix crashes in ParametersAcceptorSelector
1 parent 167f9a3 commit 4ddbd81

File tree

4 files changed

+211
-139
lines changed

4 files changed

+211
-139
lines changed

‎build/PHPStan/Build/NamedArgumentsRule.php‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ private function processArgs(ExtendedParametersAcceptor $acceptor, Scope $scope,
116116

117117
$errorBuilders = [];
118118
$parameters = $acceptor->getParameters();
119+
if (count($parameters) !== count($normalizedArgs)) {
120+
return [];
121+
}
122+
119123
$defaultValueWasPassed = [];
120124
foreach ($normalizedArgs as $i => $normalizedArg) {
121125
if ($normalizedArg->unpack) {

‎src/Reflection/ParametersAcceptorSelector.php‎

Lines changed: 154 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -104,27 +104,30 @@ public static function selectFromArgs(
104104
$callbackParameters[] = new DummyParameter('item', $scope->getIterableValueType($argType), false, PassedByReference::createNo(), false, null);
105105
}
106106
}
107-
$parameters[0] = new NativeParameterReflection(
108-
$parameters[0]->getName(),
109-
$parameters[0]->isOptional(),
110-
new UnionType([
111-
new CallableType($callbackParameters, new MixedType(), false),
112-
new NullType(),
113-
]),
114-
$parameters[0]->passedByReference(),
115-
$parameters[0]->isVariadic(),
116-
$parameters[0]->getDefaultValue(),
117-
);
118-
$parametersAcceptors = [
119-
new FunctionVariant(
120-
$acceptor->getTemplateTypeMap(),
121-
$acceptor->getResolvedTemplateTypeMap(),
122-
$parameters,
123-
$acceptor->isVariadic(),
124-
$acceptor->getReturnType(),
125-
$acceptor instanceof ExtendedParametersAcceptor ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(),
126-
),
127-
];
107+
108+
if (isset($parameters[0])) {
109+
$parameters[0] = new NativeParameterReflection(
110+
$parameters[0]->getName(),
111+
$parameters[0]->isOptional(),
112+
new UnionType([
113+
new CallableType($callbackParameters, new MixedType(), false),
114+
new NullType(),
115+
]),
116+
$parameters[0]->passedByReference(),
117+
$parameters[0]->isVariadic(),
118+
$parameters[0]->getDefaultValue(),
119+
);
120+
$parametersAcceptors = [
121+
new FunctionVariant(
122+
$acceptor->getTemplateTypeMap(),
123+
$acceptor->getResolvedTemplateTypeMap(),
124+
$parameters,
125+
$acceptor->isVariadic(),
126+
$acceptor->getReturnType(),
127+
$acceptor instanceof ExtendedParametersAcceptor ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(),
128+
),
129+
];
130+
}
128131
}
129132

130133
if (count($args) >= 3 && (bool) $args[0]->getAttribute(CurlSetOptArgVisitor::ATTRIBUTE_NAME)) {
@@ -146,10 +149,9 @@ public static function selectFromArgs(
146149
$valueTypes[] = $valueType;
147150
}
148151

149-
if (count($valueTypes) !== 0) {
150-
$acceptor = $parametersAcceptors[0];
151-
$parameters = $acceptor->getParameters();
152-
152+
$acceptor = $parametersAcceptors[0];
153+
$parameters = $acceptor->getParameters();
154+
if (count($valueTypes) !== 0 && isset($parameters[2])) {
153155
$parameters[2] = new NativeParameterReflection(
154156
$parameters[2]->getName(),
155157
$parameters[2]->isOptional(),
@@ -163,7 +165,7 @@ public static function selectFromArgs(
163165
new FunctionVariant(
164166
$acceptor->getTemplateTypeMap(),
165167
$acceptor->getResolvedTemplateTypeMap(),
166-
array_values($parameters),
168+
$parameters,
167169
$acceptor->isVariadic(),
168170
$acceptor->getReturnType(),
169171
$acceptor instanceof ExtendedParametersAcceptor ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(),
@@ -196,10 +198,9 @@ public static function selectFromArgs(
196198
);
197199
}
198200

199-
if ($hasTypes) {
200-
$acceptor = $parametersAcceptors[0];
201-
$parameters = $acceptor->getParameters();
202-
201+
$acceptor = $parametersAcceptors[0];
202+
$parameters = $acceptor->getParameters();
203+
if ($hasTypes && isset($parameters[1])) {
203204
$parameters[1] = new NativeParameterReflection(
204205
$parameters[1]->getName(),
205206
$parameters[1]->isOptional(),
@@ -213,7 +214,7 @@ public static function selectFromArgs(
213214
new FunctionVariant(
214215
$acceptor->getTemplateTypeMap(),
215216
$acceptor->getResolvedTemplateTypeMap(),
216-
array_values($parameters),
217+
$parameters,
217218
$acceptor->isVariadic(),
218219
$acceptor->getReturnType(),
219220
$acceptor instanceof ExtendedParametersAcceptor ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(),
@@ -241,44 +242,49 @@ public static function selectFromArgs(
241242

242243
$acceptor = $parametersAcceptors[0];
243244
$parameters = $acceptor->getParameters();
244-
$parameters[1] = new NativeParameterReflection(
245-
$parameters[1]->getName(),
246-
$parameters[1]->isOptional(),
247-
new UnionType([
248-
new CallableType(
249-
$arrayFilterParameters ?? [
250-
new DummyParameter('item', $scope->getIterableValueType($scope->getType($args[0]->value)), false, PassedByReference::createNo(), false, null),
251-
],
252-
new BooleanType(),
253-
false,
245+
if (isset($parameters[1])) {
246+
$parameters[1] = new NativeParameterReflection(
247+
$parameters[1]->getName(),
248+
$parameters[1]->isOptional(),
249+
new UnionType([
250+
new CallableType(
251+
$arrayFilterParameters ?? [
252+
new DummyParameter('item', $scope->getIterableValueType($scope->getType($args[0]->value)), false, PassedByReference::createNo(), false, null),
253+
],
254+
new BooleanType(),
255+
false,
256+
),
257+
new NullType(),
258+
]),
259+
$parameters[1]->passedByReference(),
260+
$parameters[1]->isVariadic(),
261+
$parameters[1]->getDefaultValue(),
262+
);
263+
$parametersAcceptors = [
264+
new FunctionVariant(
265+
$acceptor->getTemplateTypeMap(),
266+
$acceptor->getResolvedTemplateTypeMap(),
267+
$parameters,
268+
$acceptor->isVariadic(),
269+
$acceptor->getReturnType(),
270+
$acceptor instanceof ExtendedParametersAcceptor ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(),
254271
),
255-
new NullType(),
256-
]),
257-
$parameters[1]->passedByReference(),
258-
$parameters[1]->isVariadic(),
259-
$parameters[1]->getDefaultValue(),
260-
);
261-
$parametersAcceptors = [
262-
new FunctionVariant(
263-
$acceptor->getTemplateTypeMap(),
264-
$acceptor->getResolvedTemplateTypeMap(),
265-
array_values($parameters),
266-
$acceptor->isVariadic(),
267-
$acceptor->getReturnType(),
268-
$acceptor instanceof ExtendedParametersAcceptor ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(),
269-
),
270-
];
272+
];
273+
}
271274
}
272275

273276
if (count($args) <= 2 && (bool) $args[0]->getAttribute(ImplodeArgVisitor::ATTRIBUTE_NAME)) {
274277
$acceptor = $namedArgumentsVariants[0] ?? $parametersAcceptors[0];
275278
$parameters = $acceptor->getParameters();
276-
if (isset($args[1]) || ($args[0]->name !== null && $args[0]->name->name === 'array')) {
279+
if (
280+
(isset($args[1]) || ($args[0]->name !== null && $args[0]->name->name === 'array'))
281+
&& isset($parameters[0]) && isset($parameters[1])
282+
) {
277283
$parameters = [
278284
new NativeParameterReflection($parameters[0]->getName(), false, new StringType(), PassedByReference::createNo(), false, null),
279285
new NativeParameterReflection($parameters[1]->getName(), false, new ArrayType(new MixedType(), new MixedType()), PassedByReference::createNo(), false, null),
280286
];
281-
} else {
287+
} elseif (isset($parameters[0])) {
282288
$parameters = [
283289
new NativeParameterReflection($parameters[0]->getName(), false, new ArrayType(new MixedType(), new MixedType()), PassedByReference::createNo(), false, null),
284290
];
@@ -307,55 +313,59 @@ public static function selectFromArgs(
307313

308314
$acceptor = $parametersAcceptors[0];
309315
$parameters = $acceptor->getParameters();
310-
$parameters[1] = new NativeParameterReflection(
311-
$parameters[1]->getName(),
312-
$parameters[1]->isOptional(),
313-
new CallableType($arrayWalkParameters, new MixedType(), false),
314-
$parameters[1]->passedByReference(),
315-
$parameters[1]->isVariadic(),
316-
$parameters[1]->getDefaultValue(),
317-
);
318-
$parametersAcceptors = [
319-
new FunctionVariant(
320-
$acceptor->getTemplateTypeMap(),
321-
$acceptor->getResolvedTemplateTypeMap(),
322-
array_values($parameters),
323-
$acceptor->isVariadic(),
324-
$acceptor->getReturnType(),
325-
$acceptor instanceof ExtendedParametersAcceptor ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(),
326-
),
327-
];
316+
if (isset($parameters[1])) {
317+
$parameters[1] = new NativeParameterReflection(
318+
$parameters[1]->getName(),
319+
$parameters[1]->isOptional(),
320+
new CallableType($arrayWalkParameters, new MixedType(), false),
321+
$parameters[1]->passedByReference(),
322+
$parameters[1]->isVariadic(),
323+
$parameters[1]->getDefaultValue(),
324+
);
325+
$parametersAcceptors = [
326+
new FunctionVariant(
327+
$acceptor->getTemplateTypeMap(),
328+
$acceptor->getResolvedTemplateTypeMap(),
329+
$parameters,
330+
$acceptor->isVariadic(),
331+
$acceptor->getReturnType(),
332+
$acceptor instanceof ExtendedParametersAcceptor ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(),
333+
),
334+
];
335+
}
328336
}
329337

330338
if ((bool) $args[0]->getAttribute(ArrayFindArgVisitor::ATTRIBUTE_NAME)) {
331339
$acceptor = $parametersAcceptors[0];
332340
$parameters = $acceptor->getParameters();
333-
$argType = $scope->getType($args[0]->value);
334-
$parameters[1] = new NativeParameterReflection(
335-
$parameters[1]->getName(),
336-
$parameters[1]->isOptional(),
337-
new CallableType(
338-
[
339-
new DummyParameter('value', $scope->getIterableValueType($argType), false, PassedByReference::createNo(), false, null),
340-
new DummyParameter('key', $scope->getIterableKeyType($argType), false, PassedByReference::createNo(), false, null),
341-
],
342-
new BooleanType(),
343-
false,
344-
),
345-
$parameters[1]->passedByReference(),
346-
$parameters[1]->isVariadic(),
347-
$parameters[1]->getDefaultValue(),
348-
);
349-
$parametersAcceptors = [
350-
new FunctionVariant(
351-
$acceptor->getTemplateTypeMap(),
352-
$acceptor->getResolvedTemplateTypeMap(),
353-
array_values($parameters),
354-
$acceptor->isVariadic(),
355-
$acceptor->getReturnType(),
356-
$acceptor instanceof ExtendedParametersAcceptor ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(),
357-
),
358-
];
341+
if (isset($parameters[1])) {
342+
$argType = $scope->getType($args[0]->value);
343+
$parameters[1] = new NativeParameterReflection(
344+
$parameters[1]->getName(),
345+
$parameters[1]->isOptional(),
346+
new CallableType(
347+
[
348+
new DummyParameter('value', $scope->getIterableValueType($argType), false, PassedByReference::createNo(), false, null),
349+
new DummyParameter('key', $scope->getIterableKeyType($argType), false, PassedByReference::createNo(), false, null),
350+
],
351+
new BooleanType(),
352+
false,
353+
),
354+
$parameters[1]->passedByReference(),
355+
$parameters[1]->isVariadic(),
356+
$parameters[1]->getDefaultValue(),
357+
);
358+
$parametersAcceptors = [
359+
new FunctionVariant(
360+
$acceptor->getTemplateTypeMap(),
361+
$acceptor->getResolvedTemplateTypeMap(),
362+
$parameters,
363+
$acceptor->isVariadic(),
364+
$acceptor->getReturnType(),
365+
$acceptor instanceof ExtendedParametersAcceptor ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(),
366+
),
367+
];
368+
}
359369
}
360370

361371
$closureBindToVar = $args[0]->getAttribute(ClosureBindToVarVisitor::ATTRIBUTE_NAME);
@@ -378,24 +388,26 @@ public static function selectFromArgs(
378388
if ($scope->hasExpressionType(new ParameterVariableOriginalValueExpr($closureBindToVar->name))->yes()) {
379389
$acceptor = $parametersAcceptors[0];
380390
$parameters = $acceptor->getParameters();
381-
$parameters[0] = new NativeParameterReflection(
382-
$parameters[0]->getName(),
383-
$parameters[0]->isOptional(),
384-
$closureThisParameters[$closureBindToVar->name],
385-
$parameters[0]->passedByReference(),
386-
$parameters[0]->isVariadic(),
387-
$parameters[0]->getDefaultValue(),
388-
);
389-
$parametersAcceptors = [
390-
new FunctionVariant(
391-
$acceptor->getTemplateTypeMap(),
392-
$acceptor->getResolvedTemplateTypeMap(),
393-
$parameters,
394-
$acceptor->isVariadic(),
395-
$acceptor->getReturnType(),
396-
$acceptor instanceof ExtendedParametersAcceptor ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(),
397-
),
398-
];
391+
if (isset($parameters[0])) {
392+
$parameters[0] = new NativeParameterReflection(
393+
$parameters[0]->getName(),
394+
$parameters[0]->isOptional(),
395+
$closureThisParameters[$closureBindToVar->name],
396+
$parameters[0]->passedByReference(),
397+
$parameters[0]->isVariadic(),
398+
$parameters[0]->getDefaultValue(),
399+
);
400+
$parametersAcceptors = [
401+
new FunctionVariant(
402+
$acceptor->getTemplateTypeMap(),
403+
$acceptor->getResolvedTemplateTypeMap(),
404+
$parameters,
405+
$acceptor->isVariadic(),
406+
$acceptor->getReturnType(),
407+
$acceptor instanceof ExtendedParametersAcceptor ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(),
408+
),
409+
];
410+
}
399411
}
400412
}
401413
}
@@ -421,24 +433,27 @@ public static function selectFromArgs(
421433
if ($scope->hasExpressionType(new ParameterVariableOriginalValueExpr($closureVarName))->yes()) {
422434
$acceptor = $parametersAcceptors[0];
423435
$parameters = $acceptor->getParameters();
424-
$parameters[1] = new NativeParameterReflection(
425-
$parameters[1]->getName(),
426-
$parameters[1]->isOptional(),
427-
$closureThisParameters[$closureVarName],
428-
$parameters[1]->passedByReference(),
429-
$parameters[1]->isVariadic(),
430-
$parameters[1]->getDefaultValue(),
431-
);
432-
$parametersAcceptors = [
433-
new FunctionVariant(
434-
$acceptor->getTemplateTypeMap(),
435-
$acceptor->getResolvedTemplateTypeMap(),
436-
array_values($parameters),
437-
$acceptor->isVariadic(),
438-
$acceptor->getReturnType(),
439-
$acceptor instanceof ExtendedParametersAcceptor ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(),
440-
),
441-
];
436+
437+
if (isset($parameters[1])) {
438+
$parameters[1] = new NativeParameterReflection(
439+
$parameters[1]->getName(),
440+
$parameters[1]->isOptional(),
441+
$closureThisParameters[$closureVarName],
442+
$parameters[1]->passedByReference(),
443+
$parameters[1]->isVariadic(),
444+
$parameters[1]->getDefaultValue(),
445+
);
446+
$parametersAcceptors = [
447+
new FunctionVariant(
448+
$acceptor->getTemplateTypeMap(),
449+
$acceptor->getResolvedTemplateTypeMap(),
450+
$parameters,
451+
$acceptor->isVariadic(),
452+
$acceptor->getReturnType(),
453+
$acceptor instanceof ExtendedParametersAcceptor ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(),
454+
),
455+
];
456+
}
442457
}
443458
}
444459
}

‎tests/PHPStan/Analyser/AnalyserIntegrationTest.php‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1556,6 +1556,12 @@ public function testBug13310(): void
15561556
$this->assertNoErrors($errors);
15571557
}
15581558

1559+
public function testBug13714(): void
1560+
{
1561+
$errors = $this->runAnalyse(__DIR__ . '/data/bug-13714.php');
1562+
$this->assertCount(19, $errors);
1563+
}
1564+
15591565
/**
15601566
* @param string[]|null $allAnalysedFiles
15611567
* @return list<Error>

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /