Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/capabilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -804,8 +804,8 @@ Auto-generated by `script/capability-matrix.php`. Do not edit by hand.
| `openssl_cms_read` | yes | no | no | openssl | not implemented for JIT in this compiler build (issue #6592) |
| `openssl_cms_sign` | yes | no | no | openssl | not implemented for JIT in this compiler build (issue #6592) |
| `openssl_cms_verify` | yes | no | no | openssl | not implemented for JIT in this compiler build (issue #6592) |
| `openssl_csr_export` | yes | no | no | openssl | not implemented for JIT in this compiler build (issue #6421) |
| `openssl_csr_export_to_file` | yes | no | no | openssl | not implemented for JIT in this compiler build (issue #6421) |
| `openssl_csr_export` | yes | yes | yes | openssl | AOT PHPT |
| `openssl_csr_export_to_file` | yes | yes | yes | openssl | AOT PHPT |
| `openssl_csr_get_public_key` | yes | no | no | openssl | not implemented for JIT in this compiler build (issue #6421) |
| `openssl_csr_get_subject` | yes | yes | yes | openssl | AOT PHPT |
| `openssl_csr_new` | yes | no | no | openssl | not implemented for JIT in this compiler build (issue #6421) |
Expand Down
4 changes: 2 additions & 2 deletions docs/pages/capability-comparison.html
Original file line number Diff line number Diff line change
Expand Up @@ -983,8 +983,8 @@ <h2>Stdlib builtins</h2>
<tr data-support="partial"><td><code>`openssl_cms_read`</code></td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-no">no</td><td class="status-no">no</td><td>—</td></tr>
<tr data-support="partial"><td><code>`openssl_cms_sign`</code></td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-no">no</td><td class="status-no">no</td><td>—</td></tr>
<tr data-support="partial"><td><code>`openssl_cms_verify`</code></td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-no">no</td><td class="status-no">no</td><td>—</td></tr>
<tr data-support="partial"><td><code>`openssl_csr_export`</code></td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-no">no</td><td class="status-no">no</td><td>—</td></tr>
<tr data-support="partial"><td><code>`openssl_csr_export_to_file`</code></td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-no">no</td><td class="status-no">no</td><td>—</td></tr>
<tr data-support="full"><td><code>`openssl_csr_export`</code></td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-yes">yes</td><td>—</td></tr>
<tr data-support="full"><td><code>`openssl_csr_export_to_file`</code></td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-yes">yes</td><td>—</td></tr>
<tr data-support="partial"><td><code>`openssl_csr_get_public_key`</code></td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-no">no</td><td class="status-no">no</td><td>—</td></tr>
<tr data-support="full"><td><code>`openssl_csr_get_subject`</code></td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-yes">yes</td><td>—</td></tr>
<tr data-support="partial"><td><code>`openssl_csr_new`</code></td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-no">no</td><td class="status-no">no</td><td>—</td></tr>
Expand Down
142 changes: 140 additions & 2 deletions ext/openssl/JitOpensslX509.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@
* openssl_x509_check_private_key() (#32527 leftover of #20285),
* openssl_x509_verify() (#32535 leftover of #6595), and
* openssl_x509_export() (#32557 leftover of #20273),
* openssl_x509_export_to_file() (#32557 leftover of #20273), and
* openssl_csr_get_subject() (#32692 leftover of #6421).
* openssl_x509_export_to_file() (#32557 leftover of #20273),
* openssl_csr_get_subject() (#32692 leftover of #6421),
* openssl_csr_export() (#32697 leftover of #6421), and
* openssl_csr_export_to_file() (#32697 leftover of #6421).
*
* php-src: ext/openssl/xp.c — PHP_FUNCTION(openssl_x509_parse)
* php-src: ext/openssl/openssl.c — PHP_FUNCTION(openssl_x509_fingerprint) / X509_digest
Expand All @@ -30,6 +32,8 @@
* php-src: ext/openssl/openssl.c — PHP_FUNCTION(openssl_x509_export) / PEM_write_bio_X509 / X509_print
* php-src: ext/openssl/openssl.c — PHP_FUNCTION(openssl_x509_export_to_file)
* php-src: ext/openssl/xp.c — PHP_FUNCTION(openssl_csr_get_subject) / X509_REQ_get_subject_name
* php-src: ext/openssl/xp.c — PHP_FUNCTION(openssl_csr_export) / PEM_write_bio_X509_REQ
* php-src: ext/openssl/xp.c — PHP_FUNCTION(openssl_csr_export_to_file)
*
* Thin-standalone AOT has no PHP FFI, so NestedJIT of {@see VmOpensslX509Native} cannot
* call `$ffi->X509_free()` (peer JitOpensslError / #32336). Bake results in the
Expand Down Expand Up @@ -114,6 +118,140 @@ public static function csrGetSubject(Context $context, JITVariable $csr, ?JITVar
return $htVar->value;
}

/**
* openssl_csr_export() — bake {@see VmOpensslCsrNative::normalizeCsrPem} into &$output.
*
* php-src: ext/openssl/xp.c PHP_FUNCTION(openssl_csr_export) / PEM_write_bio_X509_REQ
* VM {@see VmOpenssl::csrExportPem} always writes PEM (no_text text dump is not implemented).
* By-ref $output is written via __value__writeString (peer {@see self::export}).
*/
public static function csrExport(
Context $context,
JITVariable $csr,
JITVariable $output,
?JITVariable $noText = null
): Value {
$pem = JitStringArg::compileTimeLiteral($csr);
if (null === $pem) {
throw new \LogicException(
'openssl_csr_export() csr must be a compile-time string literal '
.'for JIT/AOT in this compiler build (issue #32697)'
);
}
$noTextBool = self::compileTimeBool($noText, true);
if (null === $noTextBool) {
throw new \LogicException(
'openssl_csr_export() no_text must be a compile-time bool '
.'for JIT/AOT in this compiler build (issue #32697)'
);
}
unset($noTextBool);

if (!VmOpensslCsrNative::available()) {
return self::boxedFalse($context);
}

$exported = VmOpensslCsrNative::normalizeCsrPem($pem);
if (false === $exported) {
return self::boxedFalse($context);
}

$outPtr = JitValueBox::valuePtrFromVariable($context, $output);
$str = $context->builder->load($context->constantStringFromString($exported));
$context->builder->call(
$context->lookupFunction('__value__writeString'),
$outPtr,
$str
);
JitValueBox::publishAfterWrite($context, $outPtr);

return self::boxedBool($context, true);
}

/**
* openssl_csr_export_to_file() — bake {@see VmOpensslCsrNative::normalizeCsrPem}, write via
* {@see \PHPCompiler\JIT\Builtin\StringFilePutContents} / __compiler_file_put_contents.
*
* php-src: ext/openssl/xp.c PHP_FUNCTION(openssl_csr_export_to_file)
*/
public static function csrExportToFile(
Context $context,
JITVariable $csr,
JITVariable $outputFilename,
?JITVariable $noText = null
): Value {
$pem = JitStringArg::compileTimeLiteral($csr);
if (null === $pem) {
throw new \LogicException(
'openssl_csr_export_to_file() csr must be a compile-time string literal '
.'for JIT/AOT in this compiler build (issue #32697)'
);
}
$path = JitStringArg::compileTimeLiteral($outputFilename);
if (null === $path) {
throw new \LogicException(
'openssl_csr_export_to_file() output_filename must be a compile-time string literal '
.'for JIT/AOT in this compiler build (issue #32697)'
);
}
$noTextBool = self::compileTimeBool($noText, true);
if (null === $noTextBool) {
throw new \LogicException(
'openssl_csr_export_to_file() no_text must be a compile-time bool '
.'for JIT/AOT in this compiler build (issue #32697)'
);
}
unset($noTextBool);

if (!VmOpensslCsrNative::available()) {
return self::boxedFalse($context);
}

$exported = VmOpensslCsrNative::normalizeCsrPem($pem);
if (false === $exported) {
return self::boxedFalse($context);
}

$pathStr = $context->builder->load($context->constantStringFromString($path));
$dataStr = $context->builder->load($context->constantStringFromString($exported));
$dataOwned = $context->builder->call(
$context->lookupFunction('__string__separate'),
$dataStr
);
$written = $context->builder->call(
$context->lookupFunction('__compiler_file_put_contents'),
$pathStr,
$dataOwned,
$context->getTypeFromString('int64')->constInt(0, false)
);
$i64 = $context->getTypeFromString('int64');
$failed = $context->builder->icmp(
\PHPLLVM\Builder::INT_SLT,
$written,
$i64->constInt(0, false)
);

$id = (string) (++self::$blockSerial);
$slot = JitValueBox::alloc($context);
$ptr = JitValueBox::pointer($context, $slot);
$failBlock = BasicBlockHelper::append($context, 'ossl_csr_export_file_fail_'.$id);
$okBlock = BasicBlockHelper::append($context, 'ossl_csr_export_file_ok_'.$id);
$doneBlock = BasicBlockHelper::append($context, 'ossl_csr_export_file_done_'.$id);
$context->builder->branchIf($failed, $failBlock, $okBlock);

$context->builder->positionAtEnd($failBlock);
JitValueBox::writeBool($context, $slot, $context->constantFromBool(false));
$context->builder->branch($doneBlock);

$context->builder->positionAtEnd($okBlock);
JitValueBox::writeBool($context, $slot, $context->constantFromBool(true));
$context->builder->branch($doneBlock);

$context->builder->positionAtEnd($doneBlock);

return $ptr;
}

/**
* openssl_x509_fingerprint() — bake {@see VmOpensslX509Native::fingerprintCertificatePem}.
*
Expand Down
13 changes: 9 additions & 4 deletions ext/openssl/openssl_csr_export.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
use PHPLLVM\Value;

/**
* openssl_csr_export() — export CSR PEM (php-src ext/openssl/xp.c; #6421).
* openssl_csr_export() — export CSR PEM (php-src ext/openssl/xp.c; #6421 VM, JIT/AOT #32697).
*/
final class openssl_csr_export extends Internal
{
Expand Down Expand Up @@ -46,8 +46,13 @@ public function execute(Frame $frame): void

public function call(Context $context, JITVariable ...$args): Value
{
throw new \LogicException(
'openssl_csr_export() is not implemented for JIT in this compiler build (issue #6421)'
);
$argc = \count($args);
if ($argc < 2 || $argc > 3) {
throw new \ArgumentCountError(
'openssl_csr_export() expects 2 or 3 arguments, '.$argc.' given'
);
}

return JitOpensslX509::csrExport($context, $args[0], $args[1], $args[2] ?? null);
}
}
13 changes: 9 additions & 4 deletions ext/openssl/openssl_csr_export_to_file.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
use PHPLLVM\Value;

/**
* openssl_csr_export_to_file() — write CSR PEM to path (php-src ext/openssl/xp.c; #6421).
* openssl_csr_export_to_file() — write CSR PEM to path (php-src ext/openssl/xp.c; #6421 VM, JIT/AOT #32697).
*/
final class openssl_csr_export_to_file extends Internal
{
Expand Down Expand Up @@ -61,8 +61,13 @@ public function execute(Frame $frame): void

public function call(Context $context, JITVariable ...$args): Value
{
throw new \LogicException(
'openssl_csr_export_to_file() is not implemented for JIT in this compiler build (issue #6421)'
);
$argc = \count($args);
if ($argc < 2 || $argc > 3) {
throw new \ArgumentCountError(
'openssl_csr_export_to_file() expects 2 or 3 arguments, '.$argc.' given'
);
}

return JitOpensslX509::csrExportToFile($context, $args[0], $args[1], $args[2] ?? null);
}
}
36 changes: 36 additions & 0 deletions test/fixtures/aot/cases/openssl_csr_export.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
--TEST--
AOT: openssl_csr_export() PEM + invalid PEM false (#32697 leftover of #6421, ext/openssl/xp.c)
--SKIPIF--
<?php
require_once dirname(__DIR__, 4) . '/vendor/autoload.php';
require_once dirname(__DIR__, 4) . '/ext/openssl/VmOpensslCsrNative.php';
if (!\PHPCompiler\ext\openssl\VmOpensslCsrNative::available()) {
echo 'skip';
}
?>
--FILE--
<?php
declare(strict_types=1);

$pem = <<<'PEM'
-----BEGIN CERTIFICATE REQUEST-----
MIHWMIGBAgEAMBwxCzAJBgNVBAYTAlVTMQ0wCwYDVQQDDAR0ZXN0MFwwDQYJKoZI
hvcNAQEBBQADSwAwSAJBAJvvRzuZyqMSXp+b1ue/y+w5CCj/LLvsH5hBh0lxVOL1
iKowgGV0P/wH22UnOIvpJ7NvIXMu7JexpaqdHln2UEkCAwEAAaAAMA0GCSqGSIb3
DQEBCwUAA0EAXPcbsOj7qZsACzUrR7B0sWkNxUtANNvdwF9UIBu8n+Mkz5mWvmN/
xHd8PFTBAcitzxQQwDAI1Vj3EUW7Qn3lIw==
-----END CERTIFICATE REQUEST-----
PEM;

$out = '';
var_export(openssl_csr_export($pem, $out));
echo '|';
echo (str_contains($out, 'BEGIN CERTIFICATE REQUEST') && str_contains($out, 'END CERTIFICATE REQUEST'))
? 'pem-ok'
: 'pem-bad';
echo '|';
$bad = '';
var_export(openssl_csr_export('not-a-csr', $bad));
echo "\n";
--EXPECT--
true|pem-ok|false
37 changes: 37 additions & 0 deletions test/fixtures/aot/cases/openssl_csr_export_to_file.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
--TEST--
AOT: openssl_csr_export_to_file() PEM + invalid PEM false (#32697 leftover of #6421, ext/openssl/xp.c)
--SKIPIF--
<?php
require_once dirname(__DIR__, 4) . '/vendor/autoload.php';
require_once dirname(__DIR__, 4) . '/ext/openssl/VmOpensslCsrNative.php';
if (!\PHPCompiler\ext\openssl\VmOpensslCsrNative::available()) {
echo 'skip';
}
?>
--FILE--
<?php
declare(strict_types=1);

$pem = <<<'PEM'
-----BEGIN CERTIFICATE REQUEST-----
MIHWMIGBAgEAMBwxCzAJBgNVBAYTAlVTMQ0wCwYDVQQDDAR0ZXN0MFwwDQYJKoZI
hvcNAQEBBQADSwAwSAJBAJvvRzuZyqMSXp+b1ue/y+w5CCj/LLvsH5hBh0lxVOL1
iKowgGV0P/wH22UnOIvpJ7NvIXMu7JexpaqdHln2UEkCAwEAAaAAMA0GCSqGSIb3
DQEBCwUAA0EAXPcbsOj7qZsACzUrR7B0sWkNxUtANNvdwF9UIBu8n+Mkz5mWvmN/
xHd8PFTBAcitzxQQwDAI1Vj3EUW7Qn3lIw==
-----END CERTIFICATE REQUEST-----
PEM;

$file = '/tmp/phpc_csr_export_to_file_32697.pem';
var_export(openssl_csr_export_to_file($pem, $file));
echo '|';
$written = @file_get_contents($file);
echo (\is_string($written) && str_contains($written, 'BEGIN CERTIFICATE REQUEST') && str_contains($written, 'END CERTIFICATE REQUEST'))
? 'file-ok'
: 'file-bad';
echo '|';
var_export(openssl_csr_export_to_file('not-a-csr', $file));
@unlink($file);
echo "\n";
--EXPECT--
true|file-ok|false
24 changes: 24 additions & 0 deletions test/repro/issue_32697_openssl_csr_export_aot.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

$pem = <<<'PEM'
-----BEGIN CERTIFICATE REQUEST-----
MIHWMIGBAgEAMBwxCzAJBgNVBAYTAlVTMQ0wCwYDVQQDDAR0ZXN0MFwwDQYJKoZI
hvcNAQEBBQADSwAwSAJBAJvvRzuZyqMSXp+b1ue/y+w5CCj/LLvsH5hBh0lxVOL1
iKowgGV0P/wH22UnOIvpJ7NvIXMu7JexpaqdHln2UEkCAwEAAaAAMA0GCSqGSIb3
DQEBCwUAA0EAXPcbsOj7qZsACzUrR7B0sWkNxUtANNvdwF9UIBu8n+Mkz5mWvmN/
xHd8PFTBAcitzxQQwDAI1Vj3EUW7Qn3lIw==
-----END CERTIFICATE REQUEST-----
PEM;

$out = '';
var_export(openssl_csr_export($pem, $out));
echo '|';
echo (str_contains($out, 'BEGIN CERTIFICATE REQUEST') && str_contains($out, 'END CERTIFICATE REQUEST'))
? 'pem-ok'
: 'pem-bad';
echo '|';
$bad = '';
var_export(openssl_csr_export('not-a-csr', $bad));
echo "\n";
25 changes: 25 additions & 0 deletions test/repro/issue_32697_openssl_csr_export_to_file_aot.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

$pem = <<<'PEM'
-----BEGIN CERTIFICATE REQUEST-----
MIHWMIGBAgEAMBwxCzAJBgNVBAYTAlVTMQ0wCwYDVQQDDAR0ZXN0MFwwDQYJKoZI
hvcNAQEBBQADSwAwSAJBAJvvRzuZyqMSXp+b1ue/y+w5CCj/LLvsH5hBh0lxVOL1
iKowgGV0P/wH22UnOIvpJ7NvIXMu7JexpaqdHln2UEkCAwEAAaAAMA0GCSqGSIb3
DQEBCwUAA0EAXPcbsOj7qZsACzUrR7B0sWkNxUtANNvdwF9UIBu8n+Mkz5mWvmN/
xHd8PFTBAcitzxQQwDAI1Vj3EUW7Qn3lIw==
-----END CERTIFICATE REQUEST-----
PEM;

$file = '/tmp/phpc_csr_export_to_file_32697.pem';
var_export(openssl_csr_export_to_file($pem, $file));
echo '|';
$written = @file_get_contents($file);
echo (\is_string($written) && str_contains($written, 'BEGIN CERTIFICATE REQUEST') && str_contains($written, 'END CERTIFICATE REQUEST'))
? 'file-ok'
: 'file-bad';
echo '|';
var_export(openssl_csr_export_to_file('not-a-csr', $file));
@unlink($file);
echo "\n";
Loading
Loading