mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-10-13 01:40:20 +00:00
Graphics protocol: Fix memory leak when loading corrupt PNG with ICC profile
Some checks are pending
CI / Linux (python=3.14 cc=clang sanitize=1) (push) Waiting to run
CI / Linux (python=3.12 cc=gcc sanitize=0) (push) Waiting to run
CI / Linux (python=3.13 cc=gcc sanitize=1) (push) Waiting to run
CI / Linux package (push) Waiting to run
CI / Bundle test (macos-latest) (push) Waiting to run
CI / Bundle test (ubuntu-latest) (push) Waiting to run
CI / macOS Brew (push) Waiting to run
CI / Test ./dev.sh and benchmark (push) Waiting to run
CodeQL / CodeQL-Build (actions, ubuntu-latest) (push) Waiting to run
CodeQL / CodeQL-Build (c, macos-latest) (push) Waiting to run
CodeQL / CodeQL-Build (c, ubuntu-latest) (push) Waiting to run
CodeQL / CodeQL-Build (go, ubuntu-latest) (push) Waiting to run
CodeQL / CodeQL-Build (python, ubuntu-latest) (push) Waiting to run
Depscan / Scan dependencies for vulnerabilities (push) Waiting to run
Some checks are pending
CI / Linux (python=3.14 cc=clang sanitize=1) (push) Waiting to run
CI / Linux (python=3.12 cc=gcc sanitize=0) (push) Waiting to run
CI / Linux (python=3.13 cc=gcc sanitize=1) (push) Waiting to run
CI / Linux package (push) Waiting to run
CI / Bundle test (macos-latest) (push) Waiting to run
CI / Bundle test (ubuntu-latest) (push) Waiting to run
CI / macOS Brew (push) Waiting to run
CI / Test ./dev.sh and benchmark (push) Waiting to run
CodeQL / CodeQL-Build (actions, ubuntu-latest) (push) Waiting to run
CodeQL / CodeQL-Build (c, macos-latest) (push) Waiting to run
CodeQL / CodeQL-Build (c, ubuntu-latest) (push) Waiting to run
CodeQL / CodeQL-Build (go, ubuntu-latest) (push) Waiting to run
CodeQL / CodeQL-Build (python, ubuntu-latest) (push) Waiting to run
Depscan / Scan dependencies for vulnerabilities (push) Waiting to run
This commit is contained in:
parent
c02f932641
commit
73f5102392
3 changed files with 20 additions and 4 deletions
|
|
@ -205,6 +205,9 @@ Detailed list of changes
|
|||
- Fix an out-of-bounds memory access when drawing a multi-line text sized
|
||||
character with the cursor below the bottom margin of the scroll region
|
||||
|
||||
- Fix a memory leak when loading a corrupt PNG image that has an embedded ICC
|
||||
color profile
|
||||
|
||||
0.49.1 [2026-09-24]
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
|||
|
|
@ -64,6 +64,10 @@ inflate_png_inner(png_read_data *d, const uint8_t *buf, size_t bufsz, int max_im
|
|||
png_structp png = NULL;
|
||||
png_infop info = NULL;
|
||||
struct custom_error_handler eh = {.d = d};
|
||||
// volatile because these are modified after setjmp() and read after a
|
||||
// longjmp() in the error path, so they must not be cached in registers
|
||||
cmsHPROFILE volatile input_profile = NULL;
|
||||
cmsHTRANSFORM volatile colorspace_transform = NULL;
|
||||
png = png_create_read_struct(PNG_LIBPNG_VER_STRING, &eh, read_png_error_handler, read_png_warn_handler);
|
||||
if (!png) ABRT(ENOMEM, "Failed to create PNG read structure");
|
||||
info = png_create_info_struct(png);
|
||||
|
|
@ -82,8 +86,6 @@ inflate_png_inner(png_read_data *d, const uint8_t *buf, size_t bufsz, int max_im
|
|||
bit_depth = png_get_bit_depth(png, info);
|
||||
double image_gamma;
|
||||
int intent;
|
||||
cmsHPROFILE input_profile = NULL;
|
||||
cmsHTRANSFORM colorspace_transform = NULL;
|
||||
if (png_get_sRGB(png, info, &intent)) {
|
||||
// do nothing since we output sRGB
|
||||
} else if (png_get_gAMA(png, info, &image_gamma)) {
|
||||
|
|
@ -132,12 +134,12 @@ inflate_png_inner(png_read_data *d, const uint8_t *buf, size_t bufsz, int max_im
|
|||
|
||||
if (colorspace_transform) {
|
||||
for (int i = 0; i < d->height; i++) { cmsDoTransform(colorspace_transform, d->row_pointers[i], d->row_pointers[i], d->width); }
|
||||
cmsDeleteTransform(colorspace_transform);
|
||||
}
|
||||
if (input_profile) cmsCloseProfile(input_profile);
|
||||
|
||||
d->ok = true;
|
||||
err:
|
||||
if (colorspace_transform) cmsDeleteTransform(colorspace_transform);
|
||||
if (input_profile) cmsCloseProfile(input_profile);
|
||||
if (png) png_destroy_read_struct(&png, info ? &info : NULL, NULL);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -697,6 +697,17 @@ class TestGraphics(BaseTest):
|
|||
# while libpng still expects more compressed data.
|
||||
truncated = full[:-16]
|
||||
self.assertRaisesRegex(ValueError, '[EBADPNG]', load_png_data, truncated)
|
||||
# Same, but with an embedded ICC profile so that lcms2 handles are
|
||||
# allocated before libpng longjmps out, they must be freed in the
|
||||
# error path (detected by LeakSanitizer in ASAN builds).
|
||||
try:
|
||||
from PIL import ImageCms
|
||||
except ImportError:
|
||||
return
|
||||
icc = ImageCms.ImageCmsProfile(ImageCms.createProfile('sRGB')).tobytes()
|
||||
buf = BytesIO()
|
||||
Image.frombytes('RGBA', (w, h), byte_block(w * h * 4)).save(buf, 'PNG', icc_profile=icc)
|
||||
self.assertRaisesRegex(ValueError, '[EBADPNG]', load_png_data, buf.getvalue()[:-16])
|
||||
|
||||
def test_gr_operations_with_numbers(self):
|
||||
s = self.create_screen()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue