SimpleMachines / SMF

Simple Machines Forum β€” SMF in short β€” is free and open-source community forum software, delivering professional grade features in a package that allows you to set up your own online community within minutes!
https://www.simplemachines.org/
Other
601 stars 255 forks source link

Call to undefined method Punycode::useStd3() #7572

Closed sbulen closed 2 years ago

sbulen commented 2 years ago

Description

Fatal error: Uncaught Error: Call to undefined method Punycode::useStd3() in blah\blah\Sources\Subs-Compat.php:488 Stack trace: #0 blah\blah\Sources\Subs.php(8025): idn_to_ascii('localhost', 0, 1) #1 blah\blah\Sources\Subs.php(2439): iri_to_url('https://localho...') #2 blah\blah\Sources\Subs.php(3789): {closure}(Array, 'https://localho...', NULL, Array) #3 blah\blah\Sources\Subs.php(4320): parse_bbc('[url="http...', true, 'news0') #4 blah\blah\Sources\Subs.php(4526): setupThemeContext() #5 blah\blah\Sources\Subs.php(4169): template_header() #6 blah\blah\index.php(194): obExit(NULL, true, true) #7 {main} thrown in blah\blah\Sources\Subs-Compat.php on line 488

Fails under php 8.1, but works under php 7.4.

Steps to reproduce

  1. Get this error uninstalling a mod with lots of text replaces under php 8.1. Note I do not get this error under php 7.4. Nor on any hooks only mods.

Environment (complete as necessary)

Additional information/references

Sesquipedalian commented 2 years ago

That's perplexing. Very perplexing. Both the Punycode::useStd3() method and the calls to it in Subs-Compat.php were added in the same commit as part of #7433. The only way I can imagine for this error to occur is for Class-Punycode.php to have somehow been reverted to a version prior to #7433 while Subs-Compat.php was at a version after #7433. What mod is being uninstalled when this error occurs, and what is it doing?

sbulen commented 2 years ago

You are correct, in a way... It's a form of a bootstrap problem. More an issue for pacman than the specific Punycode or the charset changes.

The problem is that pacman is applying changes & updating functions as it goes. In some instances, it is altering the files SMF is actively using...

The file in question is the test 2.1.3 patch. I have moved Subs-Compat.php & class-Punycode to be the very last updates in the xml file, but I am still seeing the problem.

Very interesting it is happening only in PHP 8.1. It must be better at detecting changes in the classes & reloading??? So it has a new Punycode class, but the old Subs-Compat.

Note that it appears the updates are all complete. I think it is just exiting & refreshing the template when this error is thrown...

Sesquipedalian commented 2 years ago

Hm. Well, if it has the new Punycode class but the old Subs-Compat.php, that should work. It would be the inverse that would give the problem.

If messing around with the order of operations in the patch file doesn't resolve the situation, you could try this:

Find: https://github.com/SimpleMachines/SMF/blob/2341c943e4fdf57176a2f0cab38453fb9a1fadfa/Sources/Subs-Compat.php#L488-L489 https://github.com/SimpleMachines/SMF/blob/2341c943e4fdf57176a2f0cab38453fb9a1fadfa/Sources/Subs-Compat.php#L524-L525

Replace (for both cases above):

        if (method_exists($Punycode, 'useStd3')
            $Punycode->useStd3($flags === ($flags | IDNA_USE_STD3_RULES));
        if (method_exists($Punycode, 'useNonTransitional')
            $Punycode->useNonTransitional($flags === ($flags | IDNA_NONTRANSITIONAL_TO_UNICODE));

This change could be added for 2.1.3 and then reverted for 2.1.4, since its only purpose would be to get through the 2.1.2 -> 2.1.3 transition.

sbulen commented 2 years ago

I was using "new" and "old" as in "version after update by pacman" and "version prior to update by pacman". Which, since we're doing a deinstall, means new=prior version (i.e., old...) and old=current version (i.e., new...)... πŸ˜„

I have a nagging suspicion that we might have a deeper issue here with pacman & classes in 8.1+... That this is just a specific example of a broader issue...

Sesquipedalian commented 2 years ago

I was using "new" and "old" as in "version after update by pacman" and "version prior to update by pacman". Which, since we're doing a deinstall, means new=prior version (i.e., old...) and old=current version (i.e., new...)... πŸ˜„

πŸ˜† Now I understand.

I have a nagging suspicion that we might have a deeper issue here with pacman & classes in 8.1+... That this is just a specific example of a broader issue...

I don't know whether you plan to address that broader issue in 2.1.3 or not. If so, cool. If not, the suggested workaround in my previous comment ought to get past the difficulty for this particular case in the meantime.

sbulen commented 2 years ago

No, not a 2.1.3 requirement. Just me worrying, as usual...

This appears to be simply repainting the screen after the updates. If such errors continue (new & old code mixed), I bet a redirect would fix - by forcing everything to be reloaded & in sync. If I understand it correctly, I could see this impacting installs, not just deinstalls. And mods, not just patches.

EDIT: Changing the order didn't address the error...

jdarwood007 commented 2 years ago

Do you have debugging turned on? I wonder if this only applies in scenarios where debugging is turned on

sbulen commented 2 years ago

Nice thought, because, yes, I did in fact have xdebug.mode=debug set...

But I just turned it off & retested & the issue is still there. Definitely worth checking.

jdarwood007 commented 2 years ago

What if, we make a change to Subs-Packages.php to ensure Subs-Combat is loaded prior to any modifications? I'm just thinking out loud. I haven't tried anything here.

sbulen commented 2 years ago

I've tried a few things to alter load sequence, no luck.

I even tried a redirect in package_info.xml (yep, supported!). Didn't work.

I'll try the method_exists next, as suggested by Sesquipedalian. That should work no matter what. (I think...)

jdarwood007 commented 2 years ago

Well thats odd because require_once should ensure we only try to load Subs-Combat once and thus even if it gets updated earlier we shouldn't try to execute the updated code in Subs-Combat.

I've seen a similar error before but it was caused because modSettings is updated during the hook install sequence and then calling certain functions will try to call hooks and those files may not be loaded yet.

sbulen commented 2 years ago

The problem isn't that subs-compat isn't loading.

The problem is that class-Punycode appears to be re-loading immediately upon update by pacman.