ezyang / htmlpurifier

Standards compliant HTML filter written in PHP
http://htmlpurifier.org
GNU Lesser General Public License v2.1
3.06k stars 327 forks source link

[PHP7.2] "A non well formed numeric value encountered" in length conversion #187

Open althaus opened 6 years ago

althaus commented 6 years ago

Hey,

we're using the purifier to clean up HTML mails before display. We recently upgraded to PHP 7.2 and now got a mail (from Outlook 😩 ) which runs into a notice which breaks our app.

The error is thrown in vendor/ezyang/htmlpurifier/library/HTMLPurifier/Length.php while comparing 2 lengths:

HTMLPurifier_Length {#7557 â–¼
  #n: ".5208"
  #unit: "in"
  #isValid: true
}

and

HTMLPurifier_Length {#7645 â–¼
  #n: "1200"
  #unit: "px"
  #isValid: null
}

At the end he tries to substract ".5208" - "0,0000" (the latter with a comma) and that throws the notice. I've dug into the to UnitConverter, but the comma is all the time around. We don't have bcmath installed. After installing that he correctly converts the 1200px into "12.5" and doesn't explode.

Cheers Matthias

ezyang commented 5 years ago

That's pretty weird. Can you post the HTML that broke your install of HTML Purifier?

By any chance, are you in a non-English locale, such that commas are used instead of periods when rendering periods?

            $r = sprintf('%.0f', (float)$r);

Is probably causing the problem, if it's locale related, but I don't want to commit a fix without understanding the situation better.

althaus commented 5 years ago

By any chance, are you in a non-English locale

Yes, German is our default.

glensc commented 5 years ago

@ezyang: comma appears if setlocale is called with appropriate locale:

$ php -r 'setlocale(LC_ALL, "et_EE.UTF-8"); echo (string)(float)4.2;'
4,2

$ php -r 'setlocale(LC_ALL, "et_EE.UTF-8"); printf("%.2f\n", (float)4.2);'
4,20

ps: your test format doesn't emit float at all:

$ php -r 'setlocale(LC_ALL, "et_EE.UTF-8"); printf("%.0f", (float)4.2);'
4

and according to printf documentation, you must use %F to avoid locale-independant results:

$ php -r 'setlocale(LC_ALL, "et_EE.UTF-8"); printf("%.2F\n", (float)4.2);'
4.20
ezyang commented 5 years ago

OK, would be very happy to accept a PR that changes this and adds a little test. Thanks!