Skip to content

Fix handle validation on PHP 8 #18

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 8, 2021
Merged

Conversation

jtojnar
Copy link
Contributor

@jtojnar jtojnar commented Dec 17, 2020

PHP 8 switched GD handles from resource to \GdImage object:

https://php.watch/versions/8.0/gdimage

We need to update the checks appropriately.

Tested on loading PNG files in selfoss.

PHP 8 switched GD handles from resource to \GdImage object:

https://php.watch/versions/8.0/gdimage

We need to update the checks appropriately.
@jtojnar jtojnar mentioned this pull request Dec 17, 2020
12 tasks
@smottt
Copy link
Owner

smottt commented Jan 8, 2021

Thanks! I'll merge this, run some tests and make a new version soon.

@smottt smottt merged commit 5342238 into smottt:master Jan 8, 2021
@jtojnar jtojnar deleted the php8-handles branch January 8, 2021 12:54
@jtojnar
Copy link
Contributor Author

jtojnar commented Jan 8, 2021

Thanks, this looks good now.

I tried fixing the tests too but got stuck on the BMP code throwing A non-numeric value encountered but this line does not make sense to me:

$size = 54 + ($wid + $wid_pad) * $hei * 3; //fixed

Perhaps it should just be 54 + ($wid * 3 + ($wid * 3) % 4) * $hei; based on

https://en.wikipedia.org/wiki/BMP_file_format#Pixel_storage

Not sure how it could have ever worked.

@smottt
Copy link
Owner

smottt commented Jan 9, 2021

I don't quite have time to dive deep into BMP spec, but I made the following quick fix yesterday and it makes sense to me:

$size = 54 + ($wid * 3 + strlen($wid_pad)) * $hei;

So:

  • 54 = header size
  • $wid * 3 = 3 bytes per pixel (24-bit BMP based on the code there)
  • strlen($wid_pad) = the size of the padding for each row
  • $hei = times the height

From the wiki you shared:

Padding bytes (not necessarily 0) must be appended to the end of the rows in order to bring up the length of the rows to a multiple of four bytes. When the pixel array is loaded into memory, each row must begin at a memory address that is a multiple of 4. This address/offset restriction is mandatory only for Pixel Arrays loaded in memory. For file storage purposes, only the size of each row must be a multiple of 4 bytes while the file offset can be arbitrary.[5] A 24-bit bitmap with Width=1, would have 3 bytes of data per row (blue, green, red) and 1 byte of padding, while Width=2 would have 6 bytes of data and 2 bytes of padding, Width=3 would have 9 bytes of data and 3 bytes of padding, and Width=4 would have 12 bytes of data and no padding.

Unless you see something wrong with this, I'll push this fix up.

There are other issues with PHP 8 support, however. I'm thinking I'll release a last minor version for v1 that does not guarantee that it works on anything but 5.3-5.6 really, but should work for most cases up to 8.0. I'll add a v2.0 which fixes some things for 7.0+, but not everything for 8.0. For tests to be fixed on 8.0 I need to bump the minimum PHP version requirement, so that will probably go to v3.0 with a 7.3 or 7.4 minimum requirement and completely fixed tests as right now phpunit is too old to properly run the tests on 8.0.

@smottt
Copy link
Owner

smottt commented Jan 9, 2021

@jtojnar I've released the v1.1.4 which includes your PR.

@jtojnar
Copy link
Contributor Author

jtojnar commented Jan 9, 2021

Your formula is the same as mine and should be right according to my understanding, if we also correct the $wid_pad to take pixel size into account. Currently, it would make 3 byte padding for Width=1 image, even though the pixel already takes up 24 bits (3 bytes) and only 1 byte of padding is needed.

@jtojnar jtojnar mentioned this pull request Jan 9, 2021
@smottt
Copy link
Owner

smottt commented Jan 10, 2021

I may be missing something very obvious here, please correct me if I'm wrong. :)

My formula: https://3v4l.org/ePRl4
Your formula: https://3v4l.org/KtI0L

Mine calculates the padding for Width=1 as 1 and keeps it that way, no multiplying. So 3 bytes for each pixel + the padding, multiplied by number of rows (height). I believe that is the correct way? All the data matches the quote above, at least.

@jtojnar
Copy link
Contributor Author

jtojnar commented Jan 10, 2021

Sorry for the confusion. For some reason, my brain kept returning a negative congruent number (-1) instead of the smallest positive one (3) as the result of 3 ≡ x (mod 4), and then discarding the sign. If we account for this, we get a correct formula: https://3v4l.org/dYWvq

But your formula does indeed work for 24-bit images since for bytes_for_pixel = 3, width * bytes_per_pixel + width % 4 ≡ width * bytes_per_pixel + width ≡ width * 3 + width ≡ width * 4 ≡ 0 (mod 4). And given that the function does not support writing any other colour depth it should be sufficient.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants