pngset: preserve hIST, pCAL and sCAL state on allocation failure - #904
pngset: preserve hIST, pCAL and sCAL state on allocation failure#904carrerasdarren-cell wants to merge 1 commit into
Conversation
Build replacement hIST, pCAL, and sCAL fields separately and install them only after every allocation succeeds. This prevents repeated setter calls from discarding the prior hIST value, leaking old pCAL and sCAL allocations, or leaving mixed old and new state when allocation fails. Add deterministic failing-allocator regressions that verify the prior values remain intact and no allocations leak. Signed-off-by: Darren Carreras <283775510+carrerasdarren-cell@users.noreply.github.com>
9977563 to
dcb14cc
Compare
|
From your comments. Remember that when the app gets an error callback the parse of the stream must be aborted. A damaged stream permits no false assumptions; the only allowed operations are the various "free" or "destroy" operations and, indeed, those are required. png_set_hIST: correct behavior. Submit a bug report which shows that the value passed to ANSI-C free(3) is not the correct value. |
|
I reproduced the incorrect cleanup access requested above on the unpatched base ( Minimal sequence:
ASan then reports: So the loop at The identical reproducer linked against this PR exits 0 with |
|
I think that's a more specific bug, which I would say you should raise first as a bug report then, perhaps after discussion with the maintainers (last I looked there were four, none me) as a fix. BTW I am being very hardnosed here; I think the code deserves a good rewrite, but we live in a time where Russian and Chinese contributors really will happily rewrite our badly written code to the ends of their own State. They might fix a few bugs too. Think about it. |
|
Opened #917 as requested with the focused pCAL cleanup bug and a sanitizer reproduction. I also re-ran the exact negative control today: the unpatched |
Summary
Root cause
png_set_hISTfrees the existing histogram before allocating its replacement. If that allocation fails, the prior valid value is discarded.png_set_pCALwrites replacement fields directly into a livepng_info. In particular, it installs the new parameter count before every replacement allocation succeeds. If a later allocation fails, the old parameter array can remain paired with the new count, which corrupts the previous value and can make later cleanup walk beyond that array. Other failure points also overwrite and leak parts of the previous value.png_set_sCAL_ssimilarly overwrites its unit and string pointers before the replacement is complete. A failed allocation can leave mixed old and new state, while both failed and successful replacements leak the overwritten strings.The change treats each replacement transactionally: build the complete new value first, clean up temporary allocations on failure, then free and replace the old value only after success.
This is API robustness for applications that call these setters repeatedly and encounter an allocation failure. It is not described as a vulnerability triggered by reading attacker-controlled PNG data.
Validation
d1d0abe: hIST loses its prior value, pCAL corrupts prior state and reports five leaked allocations, and sCAL corrupts prior state and reports two leaked allocationspnggetset: passbash ./ci/ci_verify_cmake.sh: release build, 37/37 tests, and install passgit diff --check: pass