The first observation was part of data on certain input was ruined, when the PNG save was done.
I re-compiled with
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-omit-frame-pointer -fsanitize=address") set (CMAKE_LINKER_FLAGS "${CMAKE_LINKER_FLAGS} -fno-omit-frame-pointer -fsanitize=address")
And noticed that i received an error during write. Now i created simple program that reproduces the error:
#include <memory> #include <QImage> #include <QBuffer> const int xsize = 2557; const int ysize = 2078; int main(void) { uint16_t* spoof_data = new uint16_t[ xsize * ysize ]; memset( spoof_data, 0x00, xsize*ysize * sizeof(uint16_t) ); QImage qimg_out((const unsigned char *)(spoof_data),xsize, ysize, QImage::Format_Grayscale16); auto buffer = std::make_unique<QBuffer>(); buffer->open(QIODevice::WriteOnly); qimg_out.save(buffer.get(), "PNG"); // writes image into ba in PNG format delete[] spoof_data; printf("All good!\n"); }
Compiled with:
cmake_minimum_required(VERSION 3.16) project(helloworld VERSION 1.0.0 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) find_package(Qt6 REQUIRED COMPONENTS Widgets) add_executable(silly test.cpp) set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-omit-frame-pointer -fsanitize=address") set (CMAKE_LINKER_FLAGS "${CMAKE_LINKER_FLAGS} -fno-omit-frame-pointer -fsanitize=address") target_link_libraries(silly PRIVATE Qt6::Widgets)
Produces:
% ./silly
=================================================================
==53193==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7fcce5efef4c at pc 0x7fccedd55490 bp 0x7ffd0371e4a0 sp 0x7ffd0371dc48
READ of size 5114 at 0x7fcce5efef4c thread T0
#0 0x7fccedd5548f in __interceptor_memcpy ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:790
#1 0x7fcced36a8a2 in png_write_row /home/qt/work/qt/qtbase/src/3rdparty/libpng/pngwrite.c:842
#2 0x7fcced36b087 in png_write_image /home/qt/work/qt/qtbase/src/3rdparty/libpng/pngwrite.c:626
#3 0x7fcced36b087 in png_write_image /home/qt/work/qt/qtbase/src/3rdparty/libpng/pngwrite.c:601
#4 0x7fcced1f8644 in QPNGImageWriter::writeImage(QImage const&, int, QString const&, int, int) /home/qt/work/qt/qtbase/src/gui/image/qpnghandler.cpp:1127
#5 0x7fcced1f900a in QPNGImageWriter::writeImage(QImage const&, int, QString const&) /home/qt/work/qt/qtbase/src/gui/image/qpnghandler.cpp:182
#6 0x7fcced1f900a in write_png_image /home/qt/work/qt/qtbase/src/gui/image/qpnghandler.cpp:1179
#7 0x7fcced1f900a in QPngHandler::write(QImage const&) /home/qt/work/qt/qtbase/src/gui/image/qpnghandler.cpp:1226
#8 0x7fccece16f07 in QImageWriter::write(QImage const&) /home/qt/work/qt/qtbase/src/gui/image/qimagewriter.cpp:720
#9 0x7fccecde8cbb in QImage::save(QIODevice*, char const*, int) const /home/qt/work/qt/qtbase/src/gui/image/qimage.cpp:3864
#10 0x56470e47862a in main (/home/xx/DEV/qt-bug-png-write/silly+0x262a)
#11 0x7fccec0850b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x240b2)
#12 0x56470e47832d in _start (/home/xx/DEV/qt-bug-png-write/silly+0x232d)0x7fcce5efef4c is located 0 bytes to the right of 10626892-byte region [0x7fcce54dc800,0x7fcce5efef4c)
allocated by thread T0 here:
#0 0x7fcceddc9787 in operator new[](unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cc:107
#1 0x56470e4784c2 in main (/home/xx/DEV/qt-bug-png-write/silly+0x24c2)
#2 0x7fccec0850b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x240b2)SUMMARY: AddressSanitizer: heap-buffer-overflow ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:790 in __interceptor_memcpy
Shadow bytes around the buggy address:
0x0ffa1cbd7d90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ffa1cbd7da0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ffa1cbd7db0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ffa1cbd7dc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ffa1cbd7dd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0ffa1cbd7de0: 00 00 00 00 00 00 00 00 00[04]fa fa fa fa fa fa
0x0ffa1cbd7df0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0ffa1cbd7e00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0ffa1cbd7e10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0ffa1cbd7e20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0ffa1cbd7e30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==53193==ABORTING
When testing more, seems like if xsize=2558 it works ok, but if xsize is odd (tried few) it causes the issue.
When testing more, seems like 6.2.3 is also affected.