Talos Vulnerability Report

TALOS-2026-2413

vtk vtkPNGReader::vtkPNGReaderUpdate2 invalid pointer dereference vulnerability

October 29, 2026

CVE Number

CVE-2026-42057

Summary

A invalid pointer dereference vulnerability exists in the vtkPNGReader::vtkPNGReaderUpdate2 functionality of vtk (version(s): 9.6). A specially crafted .png file can lead to a denial of service. An attacker can provide a malicious file to trigger this vulnerability.

Confirmed Vulnerable Versions

The versions below were either tested or verified to be vulnerable by Talos or confirmed to be vulnerable by the vendor.

vtk (version(s): 9.6)

Product URLs

vtk - https://vtk.org/

CVSSv3 Score

7.5 - CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

CWE

CWE-825 - Expired Pointer Dereference

Details

VTK, or the Visualization Toolkit, is an open-source software system for 3D computer graphics, image processing, and scientific visualization. It provides a large collection of algorithms and data structures for rendering, volume visualization, geometric processing, and interaction.

When loading a malformed file we land in the following situation

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff716bebd in vtkPNGReader::vtkPNGReaderUpdate2<unsigned char> (this=<optimized out>, outPtr=<optimized out>, outExt=<optimized out>, outInc=<optimized out>, pixSize=<optimized out>)
    at /opt/vtk-src/IO/Image/vtkPNGReader.cxx:562

pwndbg> k
#0  0x00007ffff716bebd in vtkPNGReader::vtkPNGReaderUpdate2<unsigned char> (this=<optimized out>, outPtr=<optimized out>, outExt=<optimized out>, outInc=<optimized out>, 
    pixSize=<optimized out>) at /opt/vtk-src/IO/Image/vtkPNGReader.cxx:562
Backtrace stopped: Cannot access memory at address 0xb

The callstack is totally corrupted. When looking into the source code we can observe that vtkPNGReader::vtkInternals::HandleLibPngError is called from vtkPNGReader::vtkPNGReaderUpdate2.

Following source extract of vtkPNGReader::vtkPNGReaderUpdate2 calling HandleLibPngError at LINE68, then continuing normal decode flow.

LINE1   template <class OT>
LINE2   void vtkPNGReader::vtkPNGReaderUpdate2(OT* outPtr, int* outExt, vtkIdType* outInc, long pixSize)
LINE3   {
LINE4     vtkPNGReader::vtkInternals* impl = this->Internals;
          [...]
LINE56    png_structp png_ptr = nullptr;
LINE57    png_infop info_ptr = nullptr;
LINE58    png_infop end_info = nullptr;
LINE59    if (!impl->CreateLibPngStructs(png_ptr, info_ptr, end_info))
LINE60    {
LINE61      if (fp)
LINE62      {
LINE63        fclose(fp);
LINE64      }
LINE65      return;
LINE66    }
LINE67
LINE68    impl->HandleLibPngError(png_ptr, info_ptr, fp);
LINE69    impl->InitLibPngInput(this, png_ptr, &stream, fp);
LINE70
LINE71    png_read_info(png_ptr, info_ptr);
LINE72    [...]
LINE95    png_read_image(png_ptr, row_pointers.data());
LINE96    [...]
LINE120   png_read_end(png_ptr, nullptr);
LINE121   }

Looking into HandleLibPngError source code:

LINE130   void HandleLibPngError(png_structp pngPtr, png_infop infoPtr, FILE* fp)
LINE131   {
LINE132     if (setjmp(png_jmpbuf(pngPtr)))
LINE133     {
LINE134       png_destroy_read_struct(&pngPtr, &infoPtr, (png_infopp) nullptr);
LINE135       if (fp)
LINE136       {
LINE137         fclose(fp);
LINE138       }
LINE139     }
LINE140   }

We can see that setjmp stores context for later error recovery, then HandleLibPngError returns and execution continues in vtkPNGReader::vtkPNGReaderUpdate2. In this second scenario, malformed PNG files are crafted so that metadata parsing succeeds at png_read_info LINE71, and failure is raised later during decode, typically in png_read_image or png_read_end. libpng then triggers longjmp, which returns into HandleLibPngError.

At that moment, HandleLibPngError has already returned, and its stack frame is no longer valid. Its frame has been reused by subsequent calls in vtkPNGReader::vtkPNGReaderUpdate2. Therefore, the fp parameter may contain corrupted data instead of the original FILE pointer. The crash is caused when fclose(fp) is executed with this corrupted fp value at LINE137.

The correct design is to keep setjmp in the same active function frame that performs the libpng operations, so longjmp always returns to a live stack frame. In this path, that means moving setjmp logic into vtkPNGReader::vtkPNGReaderUpdate2 rather than keeping it in a helper that returns before decode operations complete.

fclose dereferences fp as a FILE object:

It reads fp->_IO_file_jumps (vtable pointer). It calls a function pointer from that vtable(_IO_FINISH). If an attacker can influence the memory referenced by fp, this can become a control-flow redirection primitive.

glibc 2.24 and later includes IO_vtable_check, which can convert many exploit attempts into SIGABRT instead of arbitrary code execution. This mitigation is absent or different on older or non-glibc C libraries.

Vendor Response (CVE-2026-42057)

Vendor Link: https://vtk.org/download/

Timeline

2026-06-23 - Vendor Notification
2026-06-25 - Vendor Acknowledged
2026-06-30 - 7-Day
2026-07-02 - Follow-Up Sent
2026-07-07 - Vendor Replied, Dev Team Working
2026-08-07 - 45-Day
2026-08-22 - 60-Day
2026-09-15 - Follow-Up Sent
2026-09-21 - 90-Day
2026-09-23 - Vendor Replied, Dev Team Working
2026-10-12 - Advised Vendor Cisco Will Publish And Close Out

Credit

Emmanuel Tacheau of Cisco Talos