Skip to content

Commit f1d4c64

Browse files
authored
Support union types in curl_setopt validation
1 parent a4c6efc commit f1d4c64

File tree

3 files changed

+58
-26
lines changed

3 files changed

+58
-26
lines changed

src/Reflection/ParametersAcceptorSelector.php

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
use function constant;
5151
use function count;
5252
use function defined;
53+
use function is_int;
5354
use function is_string;
5455
use function sprintf;
5556
use const ARRAY_FILTER_USE_BOTH;
@@ -126,33 +127,46 @@ public static function selectFromArgs(
126127

127128
if (count($args) >= 3 && (bool) $args[0]->getAttribute(CurlSetOptArgVisitor::ATTRIBUTE_NAME)) {
128129
$optType = $scope->getType($args[1]->value);
129-
if ($optType instanceof ConstantIntegerType) {
130-
$optValueType = self::getCurlOptValueType($optType->getValue());
131-
132-
if ($optValueType !== null) {
133-
$acceptor = $parametersAcceptors[0];
134-
$parameters = $acceptor->getParameters();
135-
136-
$parameters[2] = new NativeParameterReflection(
137-
$parameters[2]->getName(),
138-
$parameters[2]->isOptional(),
139-
$optValueType,
140-
$parameters[2]->passedByReference(),
141-
$parameters[2]->isVariadic(),
142-
$parameters[2]->getDefaultValue(),
143-
);
144-
145-
$parametersAcceptors = [
146-
new FunctionVariant(
147-
$acceptor->getTemplateTypeMap(),
148-
$acceptor->getResolvedTemplateTypeMap(),
149-
array_values($parameters),
150-
$acceptor->isVariadic(),
151-
$acceptor->getReturnType(),
152-
$acceptor instanceof ExtendedParametersAcceptor ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(),
153-
),
154-
];
130+
131+
$valueTypes = [];
132+
foreach ($optType->getConstantScalarValues() as $scalarValue) {
133+
if (!is_int($scalarValue)) {
134+
$valueTypes = [];
135+
break;
136+
}
137+
138+
$valueType = self::getCurlOptValueType($scalarValue);
139+
if ($valueType === null) {
140+
$valueTypes = [];
141+
break;
155142
}
143+
144+
$valueTypes[] = $valueType;
145+
}
146+
147+
if (count($valueTypes) !== 0) {
148+
$acceptor = $parametersAcceptors[0];
149+
$parameters = $acceptor->getParameters();
150+
151+
$parameters[2] = new NativeParameterReflection(
152+
$parameters[2]->getName(),
153+
$parameters[2]->isOptional(),
154+
TypeCombinator::union(...$valueTypes),
155+
$parameters[2]->passedByReference(),
156+
$parameters[2]->isVariadic(),
157+
$parameters[2]->getDefaultValue(),
158+
);
159+
160+
$parametersAcceptors = [
161+
new FunctionVariant(
162+
$acceptor->getTemplateTypeMap(),
163+
$acceptor->getResolvedTemplateTypeMap(),
164+
array_values($parameters),
165+
$acceptor->isVariadic(),
166+
$acceptor->getReturnType(),
167+
$acceptor instanceof ExtendedParametersAcceptor ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(),
168+
),
169+
];
156170
}
157171
}
158172

tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1375,6 +1375,10 @@ public function testCurlSetOpt(): void
13751375
'Parameter #3 $value of function curl_setopt expects array<int, string>, array<string, string> given.',
13761376
77,
13771377
],
1378+
[
1379+
'Parameter #3 $value of function curl_setopt expects bool|int, int|string given.',
1380+
96,
1381+
],
13781382
]);
13791383
}
13801384

tests/PHPStan/Rules/Functions/data/curl_setopt.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,18 @@ public function bug9263() {
8181
];
8282
curl_setopt($curl, CURLOPT_HTTPHEADER, $header_list);
8383
}
84+
85+
public function unionType() {
86+
$curl = curl_init();
87+
88+
if (rand(0,1)) {
89+
$var = CURLOPT_AUTOREFERER;
90+
$value = 'yes'; // invalid, should be bool
91+
} else {
92+
$var = CURLOPT_TIMEOUT;
93+
$value = 1;
94+
}
95+
96+
curl_setopt($curl, $var, $value);
97+
}
8498
}

0 commit comments

Comments
 (0)