Closed AltamashShaikh closed 9 months ago
Can you post the exact error message that you're getting?
I just updated bcmath_compat to use GitHub Actions and all branches of bcmath_compat (1.0 / 2.0 / master) are passing on PHP 8.3 on GitHub Actions.
When I tried it locally I got an E_DEPRECATD notice (Deprecated: Use of "self" in callables is deprecated
) on PHP 8.3. Not sure why I'm not getting that error on GitHub Actions but none-the-less I fixed it. And that doesn't sound like the error you're getting anyway. In fact, the error you're getting kinda has me wondering if even a echo 'hello, world!';
script would yield a "module not present" error. Like maybe there's something in your php.ini that's bad or something.
@terrafrost I looked into the issue and we were logging the deprecation notice as a warning, after manually applying return call_user_func_array(self::class.'::' . $name, $arguments);
changes the warning goes away and works for PHP 8.3 :+1:
@terrafrost The issue was coming from the phpseclib repository due to this PR it is throwing the UnexpectedValueException
exception as it is unable to recognize the BCMath polyfill.
If we comment this line everything works well, will open an issue in phpseclib
repository.
Also it will be good to have a new release to remove the Notice
Are you running PHP on Windows? What version of phpseclib are you / were you running?
PHP fixed the JIT issue that was the motivation behind the commit you cited as of PHP 8.2.13 and phpseclib started checking to see if the version of PHP was greater then or equal to that as of 3.0.34 (which was released on Nov 27, 2023). Like if you were running phpseclib 3.0.33 or earlier and PHP 8.3.0+ then I could see how you could have that issue but if you're running the latest version of phpseclib 3.0.x then idk how you could possibly be getting that exception.
@terrafrost I am running PHP on Ubuntu, and this are the versions we are testing
PHP versions: 8.0, 8.1 and 8.3
phpseclib version: 3.0.34
bcmath_compat: 2.0.1
If you're running it on then Ubuntu idk what to say. The exception you commented out is only called if no valid engine is found.
So just before that exception there's this:
$engines = [
['GMP', ['DefaultEngine']],
['PHP64', ['OpenSSL']],
['BCMath', ['OpenSSL']],
['PHP32', ['OpenSSL']],
['PHP64', ['DefaultEngine']],
['PHP32', ['DefaultEngine']]
];
foreach ($engines as $engine) {
try {
self::setEngine($engine[0], $engine[1]);
return;
} catch (\Exception $e) {
}
}
setEngine throws one of 3x exceptions:
if (!class_exists($fqmain) || !method_exists($fqmain, 'isValidEngine')) {
throw new \InvalidArgumentException("$main is not a valid engine");
}
if (!$fqmain::isValidEngine()) {
throw new BadConfigurationException("$main is not setup correctly on this system");
}
...
if (!$found) {
throw new BadConfigurationException("No valid modular exponentiation engine found for $main");
}
I suppose you could modify initialize_static_variables()
to do echo $e->getMessage() . "\n";
in the catch block but my best guess is that the exception you're getting is BadConfigurationException("$main is not setup correctly on this system")
which, in turn, is thrown when !$fqmain::isValidEngine()
.
So like in theory the PHP32 engine should work everywhere. But apparently not even that's working for you.
Here's isValidEngine()
:
public static function isValidEngine()
{
return PHP_INT_SIZE >= 4 && !self::testJITOnWindows();
}
If PHP_INT_SIZE is less than 4 then phpseclib won't work anyway and I don't see how that's possible anyway. This leaves self::testJITOnWindows()
. Here's what testJITOnWindows()
does:
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' && function_exists('opcache_get_status') && PHP_VERSION_ID < 80213 && !defined('PHPSECLIB_ALLOW_JIT')) {
$status = opcache_get_status();
if ($status && isset($status['jit']) && $status['jit']['enabled'] && $status['jit']['on']) {
return true;
}
}
return false;
Note that in the if condition a bunch of AND's need to be true for the function to return true. If you're on Ubuntu then PHP_OS's first three characters should never be WIN so it should be returning false, which is then turned to true.
So, on Ubuntu, isValidEngine()
should always be returning true on Ubuntu and thus a valid engine should be found and thus you shouldn't get the behavior you're getting. And yet you are.
So I guess one thing you could do is to tell me what you're PHP_OS and PHP_INT_SIZE constants are.
Something else that'd prob help...
#
#-----[ OPEN ]------------------------------------------
#
Math/BigInteger.php
#
#-----[ FIND ]------------------------------------------
#
foreach ($engines as $engine) {
try {
self::setEngine($engine[0], $engine[1]);
return;
} catch (\Exception $e) {
#
#-----[ AFTER, ADD ]------------------------------------
#
echo $e->getMessage() . "\n";
This would test my assumption that the exception you're getting is indeed the BadConfigurationException("$main is not setup correctly on this system")
one.
@terrafrost Thanks for your help, we recently started scoping vendor libraries in Matomo and here the path was not scoped correctly and hence led to this error
What do you mean by not scoped out correctly?
I mean, I'm able to kinda reproduce the error if I give phpseclib an actual bad engine. eg.
//BigInteger::setEngine('zzz');
BigInteger::setEngine('PHP32', ['zzz']);
The latter gives a "No valid modular exponentiation engine found for PHP32", which I guess is kinda close to "module is not present" error that your first post described. But based on the line that you commented out that fixed the issue it doesn't seem like you're setting the engine directly - that you're letting phpseclib auto detect the best engine. And, since you're running this on Ubuntu, there should always be at least one "best" engine available - 'PHP32', ['DefaultEngine']]
.
I've already discussed how that works with the main engine but as for the modular exponentiation engine... so you said that this line was the problem:
$fqengine = '\\phpseclib3\\Math\\BigInteger\\Engines\\' . static::ENGINE_DIR . '\\' . $engine;
Here are the possible static::ENGINE_DIR
/ $engine
that are used when the engine is being auto detected:
$engines = [
['GMP', ['DefaultEngine']],
['PHP64', ['OpenSSL']],
['BCMath', ['OpenSSL']],
['PHP32', ['OpenSSL']],
['PHP64', ['DefaultEngine']],
['PHP32', ['DefaultEngine']]
];
PHP32 extends PHP which defines static::ENGINE_DIR
as PHP, which has a DefaultEngine.php file in it. If we crack that file open we see that DefaultEngine extends phpseclib3\Math\BigInteger\Engines\PHP\Reductions\EvalBarrett. After setModExpEngine() checks to see if the class / method exists it calls isValidEngine(). As EvalBarrett extends phpseclib3\Math\BigInteger\Engines\PHP\Base that means that it's that isValidEngine() function that's being called. Here's the definition of that isValidEngine():
public static function isValidEngine()
{
return static::class != __CLASS__;
}
static::class
is PHP\DefaultEngine
and __CLASS__
is PHP\Base
. They don't match so "true" is returned.
Base can't ever be initialized directly because it's an abstract class so isValidEngine() should always return true. I suppose I could make it so that it does just do that but, sufficient to say, it's still not clear to me how you're having an issue.
In Google'ing Matomo I see that that's a open source version of Google Analytics. If it's "scoping vendor libraries" that makes it sound like maybe it's doing static analysis but idk why an open source version of Google Analytics would be doing that.
I still stand by my last post. If you could get me that info that'd help.
I would say giving me the code that reproduces the issue would help but there's a good chance that this is environmental, at which point, code alone would be insufficient. So I guess another alternative would be to give me the code that reproduces the issue and access to the system that is having the issue. If you're willing to do that you could email the info to terrafrost@gmail.com.
@terrafrost Sorry for the late reply. So we have a GoogleAnalyticsImporter Plugin and which requires certain vendor libraries to get the data, this libraries work fine, but create a issue when people uses the matomo-for-wordpress plugin and use other plugins which use different version of this libraries.
To solve this issue, we started scoping this libraries, meaning we make the use statements to be specific to a plugin
eg \phpseclib3\Math\BigInteger\Engines becomes \Matomo\Dependencies\GoogleAnalyticsImporter\phpseclib3\Math\BigInteger\Engines
So when we introduced scoping, we missed scoping in setModExpEngine(), so we updated our scoping logic and the problem was solved.
The polyfill seems to not work with PHP 8.3 and gives a error that module is not present, when I switch back to PHP 8.1 it works as expected