Skip to content

Warn on unknown chunk handling (instead of err out); add continuous integration - #51

Closed
ronaldtse wants to merge 3 commits into
pnggroup:mainfrom
claricle:feature/unknown-chunk-fix
Closed

Warn on unknown chunk handling (instead of err out); add continuous integration#51
ronaldtse wants to merge 3 commits into
pnggroup:mainfrom
claricle:feature/unknown-chunk-fix

Conversation

@ronaldtse

Copy link
Copy Markdown
Contributor

This PR fixes two issues:

Description on #49

pngcheck was incorrectly treating unknown chunk types as errors, but PNG Specification 15.2.3 a) & b) specifies that unknown chunk types should not be treated as errors unless they are critical.

pngcheck.c is modified to properly handle unknown chunk types to warn on non-critical unknown chunks and only err out if it is an unknown and critical chunk.

The fix was created by Maxim Samsonov (@maxirmx) of Ribose (@riboseinc).

Description on #50

The current repository did not implement continuous integration and it is hard to ensure that the latest code and build methods work across the multitude of supported platforms.

We have added comprehensive workflows using GitHub Actions that test all supported build methods across multiple platforms, including:

  • Ubuntu: 22.04, 24.04 (both x64 and arm64)
  • macOS: 13 (Intel), 14 (arm64), 15 (arm64)
  • Windows: 2022 (x64), 11 ARM (arm64), MinGW32, MinGW64

In accordance to INSTALL.md which describes CMake and Makefiles as both accepted/supported methods to build, two workflows are created:

  • build-cmake.yml tests the CMake approach on all supported platforms
  • build-makefile.yml tests the Makefile approach on all supported platforms

Both workflows share a build matrix configuration which is encoded at matrix.json.

Specifically:

  • The Windows Makefiles made a return (containing edits from @groelofs and @jbowler) to support the Makefile builds

  • CMake builds use the following setup:

    • Ubuntu/macOS: System zlib integration
    • Windows MSVC: vcpkg integration with arm64 support
    • Windows MSYS2: MinGW32/64 with native toolchain
  • Makefile builds use the following setup:

    • Ubuntu/macOS: normal make
    • Windows MSVC: nmake with Makefile.w32
    • Windows MinGW: make with Makefile.mingw (32/64-bit)
  • An additional workflow for packaging a release at GitHub Releases is added which is triggered by pushing of a version tag (i.e. v*).

Caveat:

  • While a custom/manual zlib is also supported, I did not add that to the CI since it would result in too many jobs, a give or take given that most users would be using the system zlib (across platforms).

Credits

ronaldtse added 3 commits July 8, 2025 16:54
…norma/pngcheck-metanorma#1)

According to https://www.w3.org/TR/2003/REC-PNG-20031110/ 15.2.3 a) & b), an unknown chunk type is not treated as an error.

Contribution from Maxim Samsonov (@maxirmx) of Ribose (@riboseinc/@metanorma)
…ixes pnggroup#50

* Windows Makefiles based on those from Greg Roelofs <newt@pobox.com> and John Bowler <jbowler@acm.org>

Contribution from Ronald Tse (@ronaldtse) of Ribose (@riboseinc/@metanorma)

@jbowler jbowler left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Unknown public chunks should not occur. So far as I am aware all public chunks are now integrated into the pnggroup version of pngcheck and, indeed, the new ones were integrated before PNGv3 became a recommendation.

So this change is wrong; unknown but public chunks are hard errors whether critical or ancillary.

pngcheck is not a PNG decoder, it is a png checker

@jbowler

jbowler commented Jul 8, 2025

Copy link
Copy Markdown
Contributor

I don't know anything about the github change or the add to .gitignore (it's cmake specific, but there is no CMakeLists.txt in the project...) It seems to me that they are different issues. The core change, however, is not about "unknown" chunks, which were, I believe, correctly handled, it's about unexpected public chunks which should never occur.

If there is a public chunk which is not supported it should be added and an issue/PR should identify the public chunk that is missing but this PR does not say which public chunk caused the problem (I do know that there is one :-)

@ronaldtse

ronaldtse commented Jul 8, 2025

Copy link
Copy Markdown
Contributor Author

@jbowler currently Apple-created PNGs contain the "iDOT" public chunk which is not defined in the registry. (the iDOT chunk was mentioned in metanorma/pngcheck-metanorma#1 that was linked in #49, which admittedly in hindsight was hard to locate...)

Description of the iDOT chunk:

This is an example screenshot image I took on macOS to test:

sample-screenshot

Before the patch:

$ ./pngcheck test-files/sample-screenshot.png 
test-files/sample-screenshot.png  illegal (unless recently approved) unknown, public chunk iDOT
ERROR: test-files/sample-screenshot.png

In this PR:

$ ./pngcheck test-files/sample-screenshot.png 
test-files/sample-screenshot.png  illegal (unless recently approved) unknown, public chunk iDOT
WARN: test-files/sample-screenshot.png (494x212, 32-bit RGB+alpha, non-interlaced, static, 94.5%).

It has been reported to the W3C PNG group back in 2021, there is no formal resolution yet as of now, but seems that it is being considered:

From @ProgramMax :

We discussed this in today's meeting.
We're open to the idea.
We also dismissed it too quickly thinking we didn't have a reference implementation or wide usage. But we have both of those in this thread.

I emailed the Working Group that we should reconsider this since our concerns have already been met.

Happy to remove the patch to pngcheck.c given it is now clear that pngcheck is meant to fail the Apple-created PNGs. Apologies for assuming otherwise.

Originally we were using the return code from pngcheck to assert validity of a PNG file for the Metanorma standards publication suite. Since our software does have to accept Apple-created PNGs, we will have to post process the pngcheck error messages to know what kind of error it is.

@ronaldtse

Copy link
Copy Markdown
Contributor Author

but there is no CMakeLists.txt in the project...

Not sure if this is what you meant but the file does exist...?

pngcheck/CMakeLists.txt

Lines 1 to 66 in 31362d8

cmake_minimum_required(VERSION 3.14...4.0)
project(pngcheck
VERSION 4.0.0
DESCRIPTION "PNG file checker"
HOMEPAGE_URL "http://www.libpng.org/pub/png/apps/pngcheck.html"
LANGUAGES C
)
# Options for zlib support
option(PNGCHECK_USE_SYSTEM_ZLIB "Use the system-installed zlib" ON)
if(PNGCHECK_USE_ZLIB)
message(DEPRECATION "The option PNGCHECK_USE_ZLIB has been discontinued")
endif()
# Source files
set(PNGCHECK_SOURCES pngcheck.c)
if(NOT UNIX)
list(APPEND PNGCHECK_SOURCES third_party/wildargs/wildargs.c)
endif()
# Executables
add_executable(pngcheck ${PNGCHECK_SOURCES})
# Dependency handling
if(PNGCHECK_USE_SYSTEM_ZLIB)
find_package(ZLIB)
if(ZLIB_FOUND)
target_link_libraries(pngcheck PRIVATE ZLIB::ZLIB)
else()
message(WARNING "System ZLIB not found, falling back to FetchContent")
set(PNGCHECK_USE_SYSTEM_ZLIB OFF)
endif()
endif()
if(NOT PNGCHECK_USE_SYSTEM_ZLIB)
include(FetchContent)
FetchContent_Declare(zlib
GIT_REPOSITORY https://github.com/madler/zlib.git
GIT_TAG v1.3.1
)
FetchContent_MakeAvailable(zlib)
get_target_property(PNGCHECK_ZLIB_SOURCE_DIR zlibstatic SOURCE_DIR)
if(PNGCHECK_ZLIB_SOURCE_DIR)
message(STATUS "Using local ZLIB subproject: ${PNGCHECK_ZLIB_SOURCE_DIR}")
else()
message(STATUS "Using local ZLIB subproject (location not available)")
endif()
target_link_libraries(pngcheck PRIVATE zlibstatic)
endif()
# Installation rules
include(GNUInstallDirs)
install(TARGETS pngcheck
RUNTIME
DESTINATION ${CMAKE_INSTALL_BINDIR}
COMPONENT Runtime
)
install(FILES pngcheck.1
DESTINATION ${CMAKE_INSTALL_MANDIR}/man1
COMPONENT Documentation
)
# Package generation
set(CPACK_PACKAGE_NAME ${PROJECT_NAME})
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY ${PROJECT_DESCRIPTION})
include(CPack)

@ronaldtse

Copy link
Copy Markdown
Contributor Author

Closing in favor of #52, which only adds the workflows.

@ronaldtse ronaldtse closed this Jul 8, 2025
@jbowler

jbowler commented Jul 8, 2025

Copy link
Copy Markdown
Contributor

I said:

but there is no CMakeLists.txt in the project...

Ah, Cosmin added it (in March), my mistake I hadn't noticed it for some reason.

@jbowler

jbowler commented Jul 8, 2025

Copy link
Copy Markdown
Contributor

iDOT is considered in the current W3C discussions:

w3c/png#60
w3c/png#54

But releasing PNG files with iDOT in is strictly non-conformant; the files should either never be made public or, better, should be made public along with the specification using a private chunk with a signature, e.g. idOTApple (where Apple are the first five bytes of the chunk data, removed if the chunk is approved.)

@svgeesus, @ProgramMax maybe this needs to be stated in bigger letters in the specification?

It seems unlikely that iDOT will be adopted verbatim given as there is no public specification; it may be patented/trademarked(difficult with that name) and/or copyrighted. My current working approach is something I call baND which is like maRK type 0 and possibly iDOT, see the link to the reverse engineering here:

w3c/png#54 (comment)

The difference is that baND is generalised for interlaced images and for APNG frames (interlaced or not). It's also always at the end of the file (just before IEND) so that it can be found easily and reliably.

In any case the problem with pngcheck is not that it flags a major error in the file but that it stops parsing at that moment and does not consider the remaining chunks. It's easy to fix a file with iDOT; it can be loaded into an editor like TweakPNG and the chunk deleted or it can be run through a command line program which has the ability to delete specific chunks.

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