Skip to content

Validate callback signatures for curl_setopt callback options like CURLOPT_PREREQFUNCTION#6050

Open
phpstan-bot wants to merge 1 commit into
phpstan:2.2.xfrom
phpstan-bot:create-pull-request/patch-8en2bji
Open

Validate callback signatures for curl_setopt callback options like CURLOPT_PREREQFUNCTION#6050
phpstan-bot wants to merge 1 commit into
phpstan:2.2.xfrom
phpstan-bot:create-pull-request/patch-8en2bji

Conversation

@phpstan-bot

Copy link
Copy Markdown
Collaborator

Summary

curl_setopt($ch, CURLOPT_PREREQFUNCTION, $cb) (and the other curl callback
options) accepted any value: passing a callback with the wrong return type was
not reported. PHPStan now knows the exact signature each curl callback option
expects and reports a mismatch such as a bool-returning callback where int
is required.

Changes

  • src/Reflection/ParametersAcceptorSelector.php: getCurlOptValueType() now
    maps the curl callback options to a (callable(...): ...)|null value type:
    • CURLOPT_WRITEFUNCTIONcallable(CurlHandle, string): int
    • CURLOPT_HEADERFUNCTIONcallable(CurlHandle, string): int
    • CURLOPT_READFUNCTIONcallable(CurlHandle, resource, int): string
    • CURLOPT_PROGRESSFUNCTIONcallable(CurlHandle, int, int, int, int): int
    • CURLOPT_XFERINFOFUNCTIONcallable(CurlHandle, int, int, int, int): int
    • CURLOPT_PREREQFUNCTIONcallable(CurlHandle, string, string, int, int): int
      The handle parameter is typed CurlHandle on PHP 8+ and resource otherwise,
      reusing the existing PhpVersion::supportsCurlShareHandle() gate. null is
      part of the union so resetting a callback is still allowed.
  • Tests: new curl_setopt_callback.php data file plus testCurlSetOptCallback
    in CallToFunctionParametersRuleTest, a PHP 8.4-gated curl_setopt_prereq.php
    / testCurlSetOptPrereqCallback for CURLOPT_PREREQFUNCTION, and a callback
    case added to the curl-setopt-array.php data / testCurlSetOptArray to cover
    the array form.

Root cause

getCurlOptValueType() had entries for bool/int/string/array/resource options
but none for the callback options, so it returned null and no override was
applied — the third curl_setopt argument (and the option array values) stayed
mixed and were never checked. Adding callable value types for the whole family
of curl callback options lets the existing argument-type check verify both the
parameters and the return type of the passed callback.

Test

  • testCurlSetOptCallback asserts errors for write/header/read/progress/xferinfo
    callbacks with the wrong return type, and no error for correctly-typed
    callbacks or null.
  • testCurlSetOptPrereqCallback (PHP 8.4+) covers the reported
    CURLOPT_PREREQFUNCTION case.
  • testCurlSetOptArray now also covers a callback option passed through the
    curl_setopt_array options array.

Fixes phpstan/phpstan#14956

…RLOPT_PREREQFUNCTION

- Map curl callback options (CURLOPT_WRITEFUNCTION, CURLOPT_HEADERFUNCTION,
  CURLOPT_READFUNCTION, CURLOPT_PROGRESSFUNCTION, CURLOPT_XFERINFOFUNCTION and
  CURLOPT_PREREQFUNCTION) to precise `(callable(...): ...)|null` value types in
  ParametersAcceptorSelector::getCurlOptValueType().
- The callback's first parameter is typed as `CurlHandle` (PHP 8+) or `resource`,
  followed by the option-specific parameters, and the expected return type (`int`
  for the write/header/progress/xferinfo/prereq callbacks, `string` for the read
  callback). Passing a callback with a wrong return type (e.g. returning `bool`)
  now triggers an argument.type error.
- `null` is accepted so resetting a callback keeps working.
- The same value types flow through the curl_setopt_array path, so callbacks
  supplied via the options array are validated identically.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

validate curl_setopt($ch, CURLOPT_PREREQFUNCTION, $cb) callback signature

1 participant