Skip to content
Closed
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
34 changes: 32 additions & 2 deletions lib/JIT/Builtin/OpensslDigestRuntime.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,15 @@
use PHPLLVM\Value\Function_ as LlvmFunction;

/**
* JIT/AOT link for openssl_digest() via OpensslDigestJitHelper PHP (#21081, #22554).
* JIT/AOT link for openssl_digest() via OpensslDigestJitHelper PHP (#21081, #22554, #32868).
*
* Helper compile: {@see JitVmHelperLink::ensureCompiled} (peer MathModf #22519).
* Peer of {@see OpensslEncryptRuntime}. SSOT: {@see \PHPCompiler\ext\openssl\VmOpenssl::digest}
*
* Module-local ABI owner (getNamedFunction first): Builtin\Type no longer always-declares
* an empty shell (#32868 / peer #32866) — leftover Type decls mint openssl_digest.1
* (#31894 / #32122).
*
* php-src: ext/openssl/openssl.c
*/
final class OpensslDigestRuntime
Expand Down Expand Up @@ -77,12 +82,37 @@ private static function implementIfMissing(Context $context, string $name, calla
return;
}

$fn = $context->lookupFunction($name);
$fn = self::declareAbi($context, $name, $probe);
$emit($context, $fn);
$context->registerFunction($name, $fn);
$context->builder->clearInsertionPosition();
}

private static function declareAbi(Context $context, string $name, ?LlvmFunction $probe): LlvmFunction
{
if (null !== $probe) {
return $probe;
}

$strPtr = $context->getTypeFromString('__string__*');
$i64 = $context->getTypeFromString('int64');

$ft = match ($name) {
'__compiler_openssl_digest' => $context->context->functionType(
$strPtr,
false,
$strPtr,
$strPtr,
$i64
),
default => throw new \LogicException(
'OpensslDigestRuntime unknown ABI '.$name.' (#32868)'
),
};

return $context->module->addFunction($name, $ft);
}

private static function implementDigestBridge(Context $context, LlvmFunction $fn): void
{
$entry = $fn->appendBasicBlock('ossl_digest_bridge_entry');
Expand Down
15 changes: 5 additions & 10 deletions lib/JIT/Builtin/Type.php
Original file line number Diff line number Diff line change
Expand Up @@ -527,16 +527,10 @@ public function register(): void {
// always-on shells removed (#32859): NestedJIT/AOT bridge is OpensslEncryptRuntime
// (getNamedFunction first; Type::initialize still ensureLinked). Leftover Type
// empty decls vs Runtime ABI drift mint openssl_encrypt.1 (#31894 / #32122).
// openssl_digest — NestedJIT OpensslDigestJitHelper (#21081)
$fntypeOpensslDigest = $this->context->context->functionType(
$strPtr,
false,
$strPtr,
$strPtr,
$i64
);
$fnOpensslDigest = $this->context->module->addFunction('__compiler_openssl_digest', $fntypeOpensslDigest);
$this->context->registerFunction('__compiler_openssl_digest', $fnOpensslDigest);
// __compiler_openssl_digest always-on shell removed (#32868): NestedJIT/AOT
// bridge is OpensslDigestRuntime (getNamedFunction first; Type::initialize still
// ensureLinked). Leftover Type empty decls vs Runtime ABI drift mint
// openssl_digest.1 (#31894 / #32122).
// openssl_pbkdf2 — HMAC over __compiler_hash (hex) + LLVM hex-decode (#32410)
$fntypeOpensslPbkdf2 = $this->context->context->functionType(
$strPtr,
Expand Down Expand Up @@ -1210,6 +1204,7 @@ public function initialize(): void {
PasswordCryptoRuntime::ensureLinked($this->context);
OpensslEncryptRuntime::ensureLinked($this->context);
OpensslSignRuntime::ensureLinked($this->context);
OpensslDigestRuntime::ensureLinked($this->context);
StringStrtr::ensureLinked($this->context);
StringPhpinfoRuntime::ensureLinked($this->context);
StringDir::ensureLinked($this->context);
Expand Down
78 changes: 78 additions & 0 deletions test/unit/TypeDeadOpensslDigestAbiRuntimeShrinkTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php

declare(strict_types=1);

namespace PHPCompiler\Test\Unit;

use PHPUnit\Framework\TestCase;

/**
* Drop leftover always-on openssl_digest ABI shell from Builtin\Type (#32868).
*
* NestedJIT/AOT bridge stays OpensslDigestRuntime.
* Runtime owner declares module-locally (getNamedFunction first) so leftover Type
* empty decls cannot mint openssl_digest.1 (#31894 / #32122).
*/
final class TypeDeadOpensslDigestAbiRuntimeShrinkTest extends TestCase
{
/** @return list<string> */
private function droppedAbis(): array
{
return [
'__compiler_openssl_digest',
];
}

public function testTypeBuiltinDropsLeftoverAlwaysOnOpensslDigestAbi(): void
{
$type = (string) file_get_contents(__DIR__.'/../../lib/JIT/Builtin/Type.php');
$this->assertStringContainsString('#32868', $type);
foreach ($this->droppedAbis() as $sym) {
$this->assertDoesNotMatchRegularExpression(
'/addFunction\(\s*[\'"]'.preg_quote($sym, '/').'[\'"]/',
$type,
"Builtin\\Type must not always-declare {$sym} (#32868)"
);
$this->assertStringNotContainsString(
"registerFunction('{$sym}'",
$type,
"Builtin\\Type must not always-register {$sym} (#32868)"
);
}
$this->assertStringContainsString("addFunction('exit'", $type);
$this->assertStringContainsString("addFunction('abort'", $type);
$this->assertStringContainsString("registerFunction('__compiler_convert_uuencode'", $type);
$this->assertStringContainsString('OpensslDigestRuntime::ensureLinked', $type);
}

public function testRuntimeOwnerDeclaresOpensslDigestAbiModuleLocally(): void
{
$svc = (string) file_get_contents(__DIR__.'/../../lib/JIT/Builtin/OpensslDigestRuntime.php');
$this->assertStringContainsString('#32868', $svc);
$this->assertStringContainsString('declareAbi(', $svc);
$this->assertStringContainsString('getNamedFunction($name)', $svc);
$this->assertStringContainsString('module->addFunction(', $svc);
$this->assertStringNotContainsString('lookupFunction($name)', $svc);
foreach ($this->droppedAbis() as $sym) {
$this->assertStringContainsString($sym, $svc);
}
}

public function testTypeInitializeStillEnsureLinksOpensslDigestRuntime(): void
{
$type = (string) file_get_contents(__DIR__.'/../../lib/JIT/Builtin/Type.php');
$this->assertStringContainsString('OpensslDigestRuntime::ensureLinked($this->context)', $type);
}

public function testPhpHelpersRemainForDroppedUserScriptBuiltins(): void
{
$this->assertFileExists(__DIR__.'/../../ext/openssl/OpensslDigestJitHelper.php');
$this->assertFileExists(__DIR__.'/../../ext/openssl/openssl_digest.php');
$this->assertFileDoesNotExist(
dirname(__DIR__, 2).'/lib/AOT/runtime/openssl_digest.c'
);
$this->assertFileDoesNotExist(
dirname(__DIR__, 2).'/lib/AOT/runtime/phpc_openssl_digest.c'
);
}
}