diff --git a/generated/apc.php b/generated/apc.php index 17d7dfda..77bd483e 100644 --- a/generated/apc.php +++ b/generated/apc.php @@ -89,7 +89,7 @@ function apc_compile_file(string $filename, bool $atomic = true) * @throws ApcException * */ -function apc_dec(string $key, int $step = 1, bool &$success = null): int +function apc_dec(string $key, int $step = 1, ?bool &$success = null): int { error_clear_last(); $result = \apc_dec($key, $step, $success); @@ -188,7 +188,7 @@ function apc_delete(string $key) * @throws ApcException * */ -function apc_inc(string $key, int $step = 1, bool &$success = null): int +function apc_inc(string $key, int $step = 1, ?bool &$success = null): int { error_clear_last(); $result = \apc_inc($key, $step, $success); diff --git a/generated/apcu.php b/generated/apcu.php index 08478ba8..dd09a303 100644 --- a/generated/apcu.php +++ b/generated/apcu.php @@ -58,7 +58,7 @@ function apcu_cas(string $key, int $old, int $new): void * @throws ApcuException * */ -function apcu_dec(string $key, int $step = 1, bool &$success = null): int +function apcu_dec(string $key, int $step = 1, ?bool &$success = null): int { error_clear_last(); $result = \apcu_dec($key, $step, $success); @@ -102,7 +102,7 @@ function apcu_delete($key): void * @throws ApcuException * */ -function apcu_inc(string $key, int $step = 1, bool &$success = null): int +function apcu_inc(string $key, int $step = 1, ?bool &$success = null): int { error_clear_last(); $result = \apcu_inc($key, $step, $success); diff --git a/generated/filesystem.php b/generated/filesystem.php index 1250afde..7983be90 100644 --- a/generated/filesystem.php +++ b/generated/filesystem.php @@ -512,7 +512,7 @@ function filesize(string $filename): int * @throws FilesystemException * */ -function flock($handle, int $operation, int &$wouldblock = null): void +function flock($handle, int $operation, ?int &$wouldblock = null): void { error_clear_last(); $result = \flock($handle, $operation, $wouldblock); diff --git a/generated/info.php b/generated/info.php index 2ec09c30..fc597143 100644 --- a/generated/info.php +++ b/generated/info.php @@ -271,7 +271,7 @@ function getmyuid(): int * @throws InfoException * */ -function getopt(string $options, array $longopts = null, int &$optind = null): array +function getopt(string $options, array $longopts = null, ?int &$optind = null): array { error_clear_last(); if ($optind !== null) { diff --git a/generated/ldap.php b/generated/ldap.php index 38adffb9..8a6101e0 100644 --- a/generated/ldap.php +++ b/generated/ldap.php @@ -105,7 +105,7 @@ function ldap_bind($link_identifier, ?string $bind_rdn = null, ?string $bind_pas * @throws LdapException * */ -function ldap_control_paged_result_response($link, $result, string &$cookie = null, int &$estimated = null): void +function ldap_control_paged_result_response($link, $result, ?string &$cookie = null, ?int &$estimated = null): void { error_clear_last(); $result = \ldap_control_paged_result_response($link, $result, $cookie, $estimated); diff --git a/generated/mbstring.php b/generated/mbstring.php index 80c3bf7c..e6cce1d5 100644 --- a/generated/mbstring.php +++ b/generated/mbstring.php @@ -373,7 +373,7 @@ function mb_ord(string $str, string $encoding = null): int * @throws MbstringException * */ -function mb_parse_str(string $encoded_string, array &$result = null): void +function mb_parse_str(string $encoded_string, ?array &$result = null): void { error_clear_last(); $result = \mb_parse_str($encoded_string, $result); diff --git a/generated/network.php b/generated/network.php index 8da5fdff..b97804f8 100644 --- a/generated/network.php +++ b/generated/network.php @@ -242,7 +242,7 @@ function closelog(): void * @throws NetworkException * */ -function dns_get_record(string $hostname, int $type = DNS_ANY, array &$authns = null, array &$addtl = null, bool $raw = false): array +function dns_get_record(string $hostname, int $type = DNS_ANY, ?array &$authns = null, ?array &$addtl = null, bool $raw = false): array { error_clear_last(); $result = \dns_get_record($hostname, $type, $authns, $addtl, $raw); @@ -301,7 +301,7 @@ function dns_get_record(string $hostname, int $type = DNS_ANY, array &$authns = * @throws NetworkException * */ -function fsockopen(string $hostname, int $port = -1, int &$errno = null, string &$errstr = null, float $timeout = null) +function fsockopen(string $hostname, int $port = -1, ?int &$errno = null, ?string &$errstr = null, float $timeout = null) { error_clear_last(); if ($timeout !== null) { diff --git a/generated/oci8.php b/generated/oci8.php index abd29a8e..3c7c6858 100644 --- a/generated/oci8.php +++ b/generated/oci8.php @@ -723,7 +723,7 @@ function oci_execute($statement, int $mode = OCI_COMMIT_ON_SUCCESS): void * @throws Oci8Exception * */ -function oci_fetch_all($statement, array &$output, int $skip = 0, int $maxrows = -1, int $flags = OCI_FETCHSTATEMENT_BY_COLUMN + OCI_ASSOC): int +function oci_fetch_all($statement, ?array &$output, int $skip = 0, int $maxrows = -1, int $flags = OCI_FETCHSTATEMENT_BY_COLUMN + OCI_ASSOC): int { error_clear_last(); $result = \oci_fetch_all($statement, $output, $skip, $maxrows, $flags); diff --git a/generated/openssl.php b/generated/openssl.php index 8a3147f6..709cce1f 100644 --- a/generated/openssl.php +++ b/generated/openssl.php @@ -64,7 +64,7 @@ function openssl_csr_export_to_file($csr, string $outfilename, bool $notext = tr * @throws OpensslException * */ -function openssl_csr_export($csr, string &$out, bool $notext = true): void +function openssl_csr_export($csr, ?string &$out, bool $notext = true): void { error_clear_last(); $result = \openssl_csr_export($csr, $out, $notext); @@ -389,7 +389,7 @@ function openssl_encrypt(string $data, string $method, string $key, int $options * @throws OpensslException * */ -function openssl_open(string $sealed_data, string &$open_data, string $env_key, $priv_key_id, string $method = "RC4", string $iv = null): void +function openssl_open(string $sealed_data, ?string &$open_data, string $env_key, $priv_key_id, string $method = "RC4", string $iv = null): void { error_clear_last(); if ($iv !== null) { @@ -510,7 +510,7 @@ function openssl_pkcs12_export_to_file($x509, string $filename, $priv_key, strin * @throws OpensslException * */ -function openssl_pkcs12_export($x509, string &$out, $priv_key, string $pass, array $args = null): void +function openssl_pkcs12_export($x509, ?string &$out, $priv_key, string $pass, array $args = null): void { error_clear_last(); if ($args !== null) { @@ -535,7 +535,7 @@ function openssl_pkcs12_export($x509, string &$out, $priv_key, string $pass, arr * @throws OpensslException * */ -function openssl_pkcs12_read(string $pkcs12, array &$certs, string $pass): void +function openssl_pkcs12_read(string $pkcs12, ?array &$certs, string $pass): void { error_clear_last(); $result = \openssl_pkcs12_read($pkcs12, $certs, $pass); @@ -708,7 +708,7 @@ function openssl_pkey_export_to_file($key, string $outfilename, string $passphra * @throws OpensslException * */ -function openssl_pkey_export($key, string &$out, string $passphrase = null, array $configargs = null): void +function openssl_pkey_export($key, ?string &$out, string $passphrase = null, array $configargs = null): void { error_clear_last(); if ($configargs !== null) { @@ -832,7 +832,7 @@ function openssl_pkey_new(array $configargs = null) * @throws OpensslException * */ -function openssl_private_decrypt(string $data, string &$decrypted, $key, int $padding = OPENSSL_PKCS1_PADDING): void +function openssl_private_decrypt(string $data, ?string &$decrypted, $key, int $padding = OPENSSL_PKCS1_PADDING): void { error_clear_last(); $result = \openssl_private_decrypt($data, $decrypted, $key, $padding); @@ -860,7 +860,7 @@ function openssl_private_decrypt(string $data, string &$decrypted, $key, int $pa * @throws OpensslException * */ -function openssl_private_encrypt(string $data, string &$crypted, $key, int $padding = OPENSSL_PKCS1_PADDING): void +function openssl_private_encrypt(string $data, ?string &$crypted, $key, int $padding = OPENSSL_PKCS1_PADDING): void { error_clear_last(); $result = \openssl_private_encrypt($data, $crypted, $key, $padding); @@ -889,7 +889,7 @@ function openssl_private_encrypt(string $data, string &$crypted, $key, int $padd * @throws OpensslException * */ -function openssl_public_decrypt(string $data, string &$decrypted, $key, int $padding = OPENSSL_PKCS1_PADDING): void +function openssl_public_decrypt(string $data, ?string &$decrypted, $key, int $padding = OPENSSL_PKCS1_PADDING): void { error_clear_last(); $result = \openssl_public_decrypt($data, $decrypted, $key, $padding); @@ -920,7 +920,7 @@ function openssl_public_decrypt(string $data, string &$decrypted, $key, int $pad * @throws OpensslException * */ -function openssl_public_encrypt(string $data, string &$crypted, $key, int $padding = OPENSSL_PKCS1_PADDING): void +function openssl_public_encrypt(string $data, ?string &$crypted, $key, int $padding = OPENSSL_PKCS1_PADDING): void { error_clear_last(); $result = \openssl_public_encrypt($data, $crypted, $key, $padding); @@ -947,7 +947,7 @@ function openssl_public_encrypt(string $data, string &$crypted, $key, int $paddi * @throws OpensslException * */ -function openssl_random_pseudo_bytes(int $length, bool &$crypto_strong = null): string +function openssl_random_pseudo_bytes(int $length, ?bool &$crypto_strong = null): string { error_clear_last(); $result = \openssl_random_pseudo_bytes($length, $crypto_strong); @@ -982,7 +982,7 @@ function openssl_random_pseudo_bytes(int $length, bool &$crypto_strong = null): * @throws OpensslException * */ -function openssl_seal(string $data, string &$sealed_data, array &$env_keys, array $pub_key_ids, string $method = "RC4", string &$iv = null): int +function openssl_seal(string $data, ?string &$sealed_data, array &$env_keys, array $pub_key_ids, string $method = "RC4", string &$iv = null): int { error_clear_last(); $result = \openssl_seal($data, $sealed_data, $env_keys, $pub_key_ids, $method, $iv); @@ -1012,7 +1012,7 @@ function openssl_seal(string $data, string &$sealed_data, array &$env_keys, arra * @throws OpensslException * */ -function openssl_sign(string $data, string &$signature, $priv_key_id, $signature_alg = OPENSSL_ALGO_SHA1): void +function openssl_sign(string $data, ?string &$signature, $priv_key_id, $signature_alg = OPENSSL_ALGO_SHA1): void { error_clear_last(); $result = \openssl_sign($data, $signature, $priv_key_id, $signature_alg); @@ -1062,7 +1062,7 @@ function openssl_x509_export_to_file($x509, string $outfilename, bool $notext = * @throws OpensslException * */ -function openssl_x509_export($x509, string &$output, bool $notext = true): void +function openssl_x509_export($x509, ?string &$output, bool $notext = true): void { error_clear_last(); $result = \openssl_x509_export($x509, $output, $notext); diff --git a/generated/pcntl.php b/generated/pcntl.php index 784ab6f9..03030f3b 100644 --- a/generated/pcntl.php +++ b/generated/pcntl.php @@ -138,7 +138,7 @@ function pcntl_signal_dispatch(): void * @throws PcntlException * */ -function pcntl_sigprocmask(int $how, array $set, array &$oldset = null): void +function pcntl_sigprocmask(int $how, array $set, ?array &$oldset = null): void { error_clear_last(); $result = \pcntl_sigprocmask($how, $set, $oldset); diff --git a/generated/sem.php b/generated/sem.php index 745ec36b..ec2a68cb 100644 --- a/generated/sem.php +++ b/generated/sem.php @@ -92,7 +92,7 @@ function msg_queue_exists(int $key): void * @throws SemException * */ -function msg_receive($queue, int $desiredmsgtype, int &$msgtype, int $maxsize, &$message, bool $unserialize = true, int $flags = 0, int &$errorcode = null): void +function msg_receive($queue, int $desiredmsgtype, ?int &$msgtype, int $maxsize, &$message, bool $unserialize = true, int $flags = 0, ?int &$errorcode = null): void { error_clear_last(); $result = \msg_receive($queue, $desiredmsgtype, $msgtype, $maxsize, $message, $unserialize, $flags, $errorcode); @@ -151,7 +151,7 @@ function msg_remove_queue($queue): void * @throws SemException * */ -function msg_send($queue, int $msgtype, $message, bool $serialize = true, bool $blocking = true, int &$errorcode = null): void +function msg_send($queue, int $msgtype, $message, bool $serialize = true, bool $blocking = true, ?int &$errorcode = null): void { error_clear_last(); $result = \msg_send($queue, $msgtype, $message, $serialize, $blocking, $errorcode); diff --git a/generated/sockets.php b/generated/sockets.php index b0191f13..483bdc09 100644 --- a/generated/sockets.php +++ b/generated/sockets.php @@ -163,7 +163,7 @@ function socket_create_listen(int $port, int $backlog = 128) * @throws SocketsException * */ -function socket_create_pair(int $domain, int $type, int $protocol, array &$fd): void +function socket_create_pair(int $domain, int $type, int $protocol, ?array &$fd): void { error_clear_last(); $result = \socket_create_pair($domain, $type, $protocol, $fd); @@ -297,7 +297,7 @@ function socket_get_option($socket, int $level, int $optname) * @throws SocketsException * */ -function socket_getpeername($socket, string &$address, int &$port = null): void +function socket_getpeername($socket, string &$address, ?int &$port = null): void { error_clear_last(); $result = \socket_getpeername($socket, $address, $port); @@ -327,7 +327,7 @@ function socket_getpeername($socket, string &$address, int &$port = null): void * @throws SocketsException * */ -function socket_getsockname($socket, string &$addr, int &$port = null): void +function socket_getsockname($socket, ?string &$addr, ?int &$port = null): void { error_clear_last(); $result = \socket_getsockname($socket, $addr, $port); diff --git a/generated/stream.php b/generated/stream.php index eea73b9d..e44e9e3e 100644 --- a/generated/stream.php +++ b/generated/stream.php @@ -331,7 +331,7 @@ function stream_set_timeout($stream, int $seconds, int $microseconds = 0): void * @throws StreamException * */ -function stream_socket_accept($server_socket, float $timeout = null, string &$peername = null) +function stream_socket_accept($server_socket, float $timeout = null, ?string &$peername = null) { error_clear_last(); if ($peername !== null) { diff --git a/generated/uodbc.php b/generated/uodbc.php index cce1b307..44ee414f 100644 --- a/generated/uodbc.php +++ b/generated/uodbc.php @@ -350,7 +350,7 @@ function odbc_execute($result_id, array $parameters_array = null): void * @throws UodbcException * */ -function odbc_fetch_into($result_id, array &$result_array, int $rownumber = null): int +function odbc_fetch_into($result_id, ?array &$result_array, int $rownumber = null): int { error_clear_last(); if ($rownumber !== null) { diff --git a/generator/src/Parameter.php b/generator/src/Parameter.php index 06095b4e..24ff990d 100644 --- a/generator/src/Parameter.php +++ b/generator/src/Parameter.php @@ -27,7 +27,17 @@ public function __construct(\SimpleXMLElement $parameter, ?PhpStanFunction $phpS public function getType(): string { $type = $this->parameter->type->__toString(); - return Type::toRootNamespace($type); + $strType = Type::toRootNamespace($type); + if ($strType !== 'mixed' && $strType !== 'resource' && $this->phpStanFunction !== null) { + $phpStanParameter = $this->phpStanFunction->getParameter($this->getParameter()); + if ($phpStanParameter) { + // Let's make the parameter nullable if it is by reference and is used only for writing. + if ($phpStanParameter->isWriteOnly()) { + $strType = '?'.$strType; + } + } + } + return $strType; } /** diff --git a/generator/src/PhpStanFunctions/PhpStanParameter.php b/generator/src/PhpStanFunctions/PhpStanParameter.php index 8d159b91..57cea136 100644 --- a/generator/src/PhpStanFunctions/PhpStanParameter.php +++ b/generator/src/PhpStanFunctions/PhpStanParameter.php @@ -32,6 +32,11 @@ class PhpStanParameter * @var bool */ private $nullable = false; + /** + * Whether the parameter is "write only" (applies only to "by reference" parameters) + * @var bool + */ + private $writeOnly = false; public function __construct(string $name, string $type) { @@ -44,6 +49,9 @@ public function __construct(string $name, string $type) if (\strpos($name, '&') !== false) { $this->byReference = true; } + if (\strpos($name, '&w_') !== false) { + $this->writeOnly = true; + } $name = \str_replace(['&rw_', '&w_'], '', $name); $name = trim($name, '=.&'); @@ -97,6 +105,15 @@ public function isByReference(): bool return $this->byReference; } + /** + * Whether the parameter is "write only" (applies only to "by reference" parameters) + * @return bool + */ + public function isWriteOnly(): bool + { + return $this->writeOnly; + } + /** * @return bool */ diff --git a/generator/tests/GeneratedFilesTest.php b/generator/tests/GeneratedFilesTest.php index 5c85d1f7..f4f1419b 100644 --- a/generator/tests/GeneratedFilesTest.php +++ b/generator/tests/GeneratedFilesTest.php @@ -102,4 +102,20 @@ public function testStrtotime() $this->assertSame(\strtotime('+1 day'), strtotime('+1 day')); } + + /** + * Tests that parameters signature can be not passed. See https://github.com/thecodingmachine/safe/issues/86 + */ + public function testOpenSslSign() + { + require_once __DIR__.'/../../generated/openssl.php'; + require_once __DIR__.'/../../lib/Exceptions/SafeExceptionInterface.php'; + require_once __DIR__.'/../../lib/Exceptions/AbstractSafeException.php'; + require_once __DIR__.'/../../generated/Exceptions/OpensslException.php'; + + \openssl_sign('foo', $signature, file_get_contents(__DIR__.'/fixtures/id_rsa')); + openssl_sign('foo', $signatureSafe, file_get_contents(__DIR__.'/fixtures/id_rsa')); + + $this->assertSame($signature, $signatureSafe); + } } diff --git a/generator/tests/fixtures/id_rsa b/generator/tests/fixtures/id_rsa new file mode 100644 index 00000000..7d5f0008 --- /dev/null +++ b/generator/tests/fixtures/id_rsa @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAoc4Ay97wfke5L1RLeiUtstzzdiSrzhwdgirjLSUeniEtXI6g +Yj7PxX2rBV6f6a4o9CpkkeoSbj3lA82hkDzc411XVSws+OJ4cz4cc4K5fZ5HLJFA +GpCqgO2ywCXH2pPmse+ACrdX1fPdZPqSyW1M+ZKYUDRAaHjlSsCkR8KSTN8Max2A +4EMsntrWVWiMdOGg5jB7CAAwIz3a6R3gKEmFml2gs77gpYme/bTVERuNW+TCG/x3 +3xUhkdOrvRKPE81K4D6rtCXuBrqfmE8r1vp29yPbjIM6KStKLTCIJHLx1/h34CNj +MXW6d8abQ7KKxAycw4ADwCO4VNhAMxhhyylNGQIDAQABAoIBABBoiaAjDZRgxaDN +FZJfbtDyoyXZ9ipCo6NtofgUCZTTnHwEYrNT11IZulwjCmhyJukL24MIj7HqSO0n +zziHU4cjEhYrEqxymvBk3hHAsfrRMDqOyEdpYEEO2c+uhSPfV8e3l+5+RUQHJO52 +kqgmk2XDvfp0MgvmJqp7+qzkSF3PH2R00c2AdjbPQoFxXv5Tkk7EBWa92pw+81Om +YEK7ch/a5tqqz2AHrcU6P8I7MsqIDLc0AuUg/Xx5Nb9K2phBpQ9Extu1cg3t769C +RR/5gqHRh3QgdaG6PGaGDSpb4ZIxNYdH7DxSVZGtZ/rBCCV8UNFBoiuXemm+QzQ2 +ob8e+/kCgYEA15FgAOTsSINZIFsWnuUTK8vQHTCkf0IL/89vvN8CIvN86Mri2yw8 +n4cQrVKjxBhhCdhu7coLzrMlo9saL9oS14Z43mPtAx6C4ACr5lcFcxcKd4zqoBP7 +YM7TJ6DN9oYd7yWQTPjUJHZXYuuVisqXDMics+rccQrsSdrN7hSFwB8CgYEAwCcn +9SU9BFZ2LnCAmMDve4+xotaxiYJMwkVLr4f/7/fOWxgsmjQUThXNfLMHgFGA0kE2 +tn1Z9axsdlZGkhr7CRQ2gUHhpEldNEKWswoj6I1uKU7fVTPuRQP7FmMYAN0cGtpC +NvQLcQbKI51VDKp6BN1JpDhw4RaWfWAntYOca8cCgYAM65GtfAsNbZHx9oOskl5L +ybN3jGrPlc3ST0SLNXKTVbSu3zopmMUpapb9TG60WiG2zVoYtntusB4ZbBBtvcxT +TqP/8E1MWo/NjTzAWYbiFwdxkuidH5V5f+v3/BNcKz2wD7hOZLuSU+V48FXOM8ZJ +5dw+jF0aCWWQJ6UgF+rMUQKBgQCdnICN+CmAcVsm5GjW4wqMk2TlaKzfWd2UTDq0 +lB0+vEirN7z+D1HIauHOMxsoCbJcw9kY/uDXPsMInePs2+ylmcrLYzquAu9MeoIa +AWtKyRdfEq7luF7shUNjLYz2yGbRL824PZ1U7HjJlbe5V+wWKVzKMvGD738o/8IS +hQ286QKBgQCeIP6DWRAvIYNWs+R1oe5jln8N7SrQUCA2F5AmffBaRU+gLcHHyTBM +VPtwF5uOAU7C7/ZhLe0MuMdVBvHSrfGh4y1qUXj1qu3KKrgF5kohyxlYvmEylDHY +mFgG7Mb6/WmP+RORcAaaIrBg9rAj6v4wdLP5FRcvQY+csP/GmksZXw== +-----END RSA PRIVATE KEY-----