Skip to content
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

dev: Make the use of stdio FILE robust. #622

Open
wants to merge 1 commit into
base: libpng18
Choose a base branch
from

Conversation

jbowler
Copy link
Contributor

@jbowler jbowler commented Oct 14, 2024

ABI changes:
The three API functions png_init_io, png_begin_read_from_stdio and
png_image_write_to_stdio now require the host fread, fwrite and
fflush functions where appropriate in addition to the host FILE.

Internally libpng uses the provided functions for all operations on
the FILE; it does not use the implementations available when libpng
was built.

API changes:
The original APIs of the above three functions are now implemented
as function-like macros which automatically pass the correct ISO-C
functions. This ensures that there are no net API changes and that
the correct arguments are passed.

Build changes:
The read stdio functionality is now dependent on SEQUENTIAL_READ
rather than READ. This is done for clarity; the progressive read
mechanism does not use FILE.

Internal changes:
png_struct::io_ptr has been supplemented with png_struct::stdio_ptr
used when stdio is used directly by libpng for IO as opposed to
caller-provided callbacks.

Error checking has been added to detect mismatched use of the stdio
(png_init_io etc) API with the callback (png_set_read_fn,
png_set_write_fn APIs.)  Changing from one API to the other
mid-stream should work but has not been tested and is not currently
a documented option.

The changes address an issue which is frequently encountered on
Microsoft Windows systems because Windows NT DLLs each have their own
ISO-C hosted environment. This means that a FILE from one DLL cannot be
used safely from a different DLL unless all access to the object is done
using functionality from the creating DLL. The problem is more general;
passing objects across DLL or other boundaries is frequently supported
but direct access to those objects' internal structure in the receiving
environment is not safe. Other such uses were address early on in the
development of libpng, this addresses the main, almost certainly, sole
remaining issue.

The idea of adding additional function pointers png_init_io was
suggested by github.com user pp383 in pull request #208.

Signed-off-by: John Bowler [email protected]

Copy link
Member

@ctruta ctruta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to think about this particular solution for a little bit. While I do agree with the new function additions, I am not so sure that we should override their names with macros in this manner. Something like this would make perfect sense in a C++ library, where overriding function names is idiomatic, and 100% working out of the box.

But we're stuck with C in here. And, for better or for worse, we've been having the goofy (but 100% working!) naming habit in which we overloaded existing function names with number suffixes: png_get_eXIf_1, png_create_write_struct_2, etc.

I, for one, would prefer leaving the old functions in place, perhaps with a deprecated attribute (to be removed eventually in some far-away future after the users migrate), and adding the new png_init_io_2, png_begin_read_from_stdio_2, etc.

In zlib they also use this practice. See, for example, deflateInit2.

(Yes, these API names are ugly 😝)

contrib/libtests/pngimage.c Outdated Show resolved Hide resolved
@jbowler
Copy link
Contributor Author

jbowler commented Oct 14, 2024

I am not so sure that we should override their names with macros in this manner.

There is no choice. png_init_io and the simplified APIs don't work and are unsafe and there is a lot of code that uses them. They are good APIs even though the implementation (the ABI) is flawed.

Therefore even though it's an ABI-change release this aspect of the API should remain the same. This is particularly true because it must be fread, fwrite and fflush which are passed to libpng, not something else. The OPs fix did what you just suggested but used C99 inline functions and massive unnecessary additions to the ABI while only addressing png_init_io!

The inlines pass a function call across the boundary not the function itself but this seems to be mindbogglingly complex to me and it requires C99 while ISO-C allows functions to be passed as pointers!

The function-like macros stop existing code and new code from doing the wrong thing; they hide the ABI but give an unchanged API which just does the right thing. What is more the result is much simpler and avoids adding yet more ABIs for no purpose.

The whole thing about png_function_666 is that this was some half-baked attempt to pretend that the ABI wasn't being changed because it was "only" an addition. It's completely unnecessary to do that in an ABI-changing release and, anyway, it doesn't work because builds against the ABI-added 1.6 fail against prior DLL versions (and fail badly.)

@jbowler
Copy link
Contributor Author

jbowler commented Oct 14, 2024

Change made using git commit --fixup; git rebase --autosquash is the approved merge approach. I assume github.com does this automatically but since I've never used --fixup before I can't be sure.

@jbowler
Copy link
Contributor Author

jbowler commented Oct 14, 2024

The pngimage.c fix is now #623

@ctruta
Copy link
Member

ctruta commented Oct 15, 2024

Change made using git commit --fixup; git rebase --autosquash is the approved merge approach. I assume github.com does this automatically but since I've never used --fixup before I can't be sure.

No problem. I'm using the command line to integrate PRs anyway.

@ctruta
Copy link
Member

ctruta commented Oct 15, 2024

I still need a little more time to review this. Will be back tomorrow.

ABI changes:
    The three API functions png_init_io, png_begin_read_from_stdio and
    png_image_write_to_stdio now require the host fread, fwrite and
    fflush functions where appropriate in addition to the host FILE.

    Internally libpng uses the provided functions for all operations on
    the FILE; it does not use the implementations available when libpng
    was built.

API changes:
    The original APIs of the above three functions are now implemented
    as function-like macros which automatically pass the correct ISO-C
    functions.  This ensures that there are no net API changes and that
    the correct arguments are passed.

Build changes:
    The read stdio functionality is now dependent on SEQUENTIAL_READ
    rather than READ.  This is done for clarity; the progressive read
    mechanism does not use FILE.

Internal changes:
    png_struct::io_ptr has been supplemented with png_struct::stdio_ptr
    used when stdio is used directly by libpng for IO as opposed to
    caller-provided callbacks.

    Error checking has been added to detect mismatched use of the stdio
    (png_init_io etc) API with the callback (png_set_read_fn,
    png_set_write_fn APIs.)  Changing from one API to the other
    mid-stream should work but has not been tested and is not currently
    a documented option.

The changes address an issue which is frequently encountered on
Microsoft Windows systems because Windows NT DLLs each have their own
ISO-C hosted environment.  This means that a FILE from one DLL cannot be
used safely from a different DLL unless all access to the object is done
using functionality from the creating DLL.  The problem is more general;
passing objects across DLL or other boundaries is frequently supported
but direct access to those objects' internal structure in the receiving
environment is not safe.  Other such uses were address early on in the
development of libpng, this addresses the main, almost certainly, sole
remaining issue.

The idea of adding additional function pointers png_init_io was
suggested by github.com user pp383 in pull request pnggroup#208.

Signed-off-by: John Bowler <[email protected]>
@jbowler jbowler force-pushed the FILE-across-DLL-boundaries branch from cb9b8cd to 912c645 Compare October 15, 2024 21:09
@jbowler
Copy link
Contributor Author

jbowler commented Oct 15, 2024

Change made using git commit --fixup; git rebase --autosquash is the approved merge approach. I assume github.com does this automatically but since I've never used --fixup before I can't be sure.

No problem. I'm using the command line to integrate PRs anyway.

The now separate change to pngimage.c seems to have caused git to do an autosquash anyway, or maybe I did it (I did run --autosquash after fixing the merge conflicts.) Anyway it's back to a single commit now.

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