Incorrect base64 encoding in PHP-FPM with opcache.file_cache_only=1 and sodium
Open
Nobody has claimed this yet.
Bug
Category: Engine
Status: Verified
- Dominant language
- C
- Stars
- 40.4k
- Forks
- 8.1k
- Avg merge
- 2d 13h
- Merged PRs (30d)
- 96
Description
Description
The following code:
<?php
final class SodiumBase64Polyfill
{
public const SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING = 3;
public const SODIUM_BASE64_VARIANT_URLSAFE = 5;
public const SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING = 7;
public static function bin2base64(string $decoded, int $variant): string
{
if (! function_exists('sodium_bin2base64')) {
return self::bin2base64Fallback($decoded, $variant);
}
return sodium_bin2base64($decoded, $variant);
}
public static function bin2base64Fallback(string $decoded, int $variant): string
{
$encoded = base64_encode($decoded);
if (
$variant === self::SODIUM_BASE64_VARIANT_URLSAFE
|| $variant === self::SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING
) {
$encoded = strtr($encoded, '+/', '-_');
}
if (
$variant === self::SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING
|| $variant === self::SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING
) {
$encoded = rtrim($encoded, '=');
}
return $encoded;
}
}
var_dump(SodiumBase64Polyfill::bin2base64("Hello world!", SodiumBase64Polyfill::SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING));
Resulted in this output:
"Hello world!�"
But I expected this output instead:
"SGVsbG8gd29ybGQh"
Steps to reproduce
- Run PHP-FPM with the following php.ini settings:
zend_extension=opcache.so
extension=sodium.so
opcache.enable = 1
opcache.enable_cli = 1
; Tune opcache for read-only application files
opcache.revalidate_freq=0
opcache.validate_timestamps=false
opcache.enable_file_override=1
; Enable pre-warmed opcache
opcache.file_cache = "/var/cache/opcache"
opcache.file_cache_read_only=1
opcache.file_cache_consistency_checks=0
; Enable log
opcache.error_log=/dev/stderr
opcache.log_verbosity_level = 4
- Compile and run the script using:
php -d zend_extension=opcache.so \
-d extension=sodium.so \
-d opcache.enable=1 \
-d opcache.enable_cli=1 \
-d opcache.jit=disable \
-d opcache.file_cache=/var/cache/opcache \
-d opcache.file_cache_only=1 \
-d opcache.file_cache_read_only=0 ./public/index.php
- Send request php-fpm
Additional information
- The issue disappears when opcache.optimization_level=0 is set.
- The bug is tested with the file_cache_only feature introduced in PR #16551, but the issue also reproduces in PHP 8.4.
PHP Version
master, 8.4
Operating System
linux x86 or aarch64
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the failure using the supplied PHP-FPM and CLI commands against public/index.php, with and without opcache.file_cache_only=1 and optimization_level=0. Read the file_cache_only behavior introduced by PR #16551 and trace the interaction with sodium during compilation. Done means the script consistently returns "SGVsbG8gd29ybGQh" under the reported configurations without regressing normal opcache behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- linux, php
- Domain
- backend, performance
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 32/100