Project

General

Profile

Bug #1189 » IC-DCMTK-0002_REPORT.md

Jörg Riesmeier, 2026-03-09 16:54

 

IC-DCMTK-0002: Double-Free in DcmJSONReader via decodeBase64()

Version: DCMTK master 418274445 (DCMTK-3.7.0+64)
CWE: CWE-415 (Double Free)

Description

DcmJSONReader::parseElement() at dcjsonrd.cc:744-752 calls OFStandard::decodeBase64() to decode an inlineBinary field. When the base64 input is invalid (fewer than 4 characters), decodeBase64() frees the output buffer at ofstd.cc:1892 but does not nullify the caller's pointer. parseElement() then unconditionally executes delete[] data at line 752, causing a double-free.

// ofstd.cc:1892 — first free
if (count == 0)
{
    delete[] result;   // frees buffer, but result NOT set to NULL
}
return count;          // returns 0

// dcjsonrd.cc:744-752 — second free
const size_t length = OFStandard::decodeBase64(value, data);
if (length > 0)
    result = storeInlineBinaryValue(*newElem, data, length);
delete[] data;         // DOUBLE FREE — data already freed above

Reproduction

echo '{"7FE00010":{"vr":"OB","inlinebinary":"A"}}' > poc.json
json2dcm poc.json /dev/null

Actual output:

=================================================================
==2185581==ERROR: AddressSanitizer: attempting double-free on 0x7c1ff6fcc990 in thread T0:
    #0 0x55555570cb1d in operator delete[](void*) (build-asan/bin/json2dcm+0x1b8b1d)
    #1 0x5555557931bf in DcmJSONReader::parseElement(DcmItem*, DcmItem*, jsmntok*&) dcmdata/libsrc/dcjsonrd.cc:752:9
    #2 0x555555797e03 in DcmJSONReader::parseDataSet(DcmItem*, DcmItem*, jsmntok*&) dcmdata/libsrc/dcjsonrd.cc:923:18
    #3 0x5555557a19c7 in DcmJSONReader::readAndConvertJSONFile(DcmFileFormat&, char const*) dcmdata/libsrc/dcjsonrd.cc:1279:18
    #4 0x55555571339b in main dcmdata/apps/json2dcm.cc:435:25
    #5 0x7ffff7989082 in __libc_start_main /build/glibc-LcI20x/glibc-2.31/csu/../csu/libc-start.c:308:16

0x7c1ff6fcc990 is located 0 bytes inside of 3-byte region [0x7c1ff6fcc990,0x7c1ff6fcc993)
freed by thread T0 here:
    #0 0x55555570cb1d in operator delete[](void*) (build-asan/bin/json2dcm+0x1b8b1d)
    #1 0x555555986ac2 in OFStandard::decodeBase64(OFString const&, unsigned char*&) ofstd/libsrc/ofstd.cc:1892:17
    #2 0x555555792cce in DcmJSONReader::parseElement(DcmItem*, DcmItem*, jsmntok*&) dcmdata/libsrc/dcjsonrd.cc:746:31
    #3 0x555555797e03 in DcmJSONReader::parseDataSet(DcmItem*, DcmItem*, jsmntok*&) dcmdata/libsrc/dcjsonrd.cc:923:18
    #4 0x5555557a19c7 in DcmJSONReader::readAndConvertJSONFile(DcmFileFormat&, char const*) dcmdata/libsrc/dcjsonrd.cc:1279:18
    #5 0x55555571339b in main dcmdata/apps/json2dcm.cc:435:25

previously allocated by thread T0 here:
    #0 0x55555570c2cd in operator new[](unsigned long) (build-asan/bin/json2dcm+0x1b82cd)
    #1 0x5555559860b6 in OFStandard::decodeBase64(OFString const&, unsigned char*&) ofstd/libsrc/ofstd.cc:1847:18
    #2 0x555555792cce in DcmJSONReader::parseElement(DcmItem*, DcmItem*, jsmntok*&) dcmdata/libsrc/dcjsonrd.cc:746:31
    #3 0x555555797e03 in DcmJSONReader::parseDataSet(DcmItem*, DcmItem*, jsmntok*&) dcmdata/libsrc/dcjsonrd.cc:923:18
    #4 0x5555557a19c7 in DcmJSONReader::readAndConvertJSONFile(DcmFileFormat&, char const*) dcmdata/libsrc/dcjsonrd.cc:1279:18
    #5 0x55555571339b in main dcmdata/apps/json2dcm.cc:435:25

SUMMARY: AddressSanitizer: double-free (build-asan/bin/json2dcm+0x1b8b1d) in operator delete[](void*)
==2185581==ABORTING

Fix

Nullify the pointer after freeing to prevent the caller's unconditional delete[] from causing a double-free:

// ofstd.cc:1892
if (count == 0)
{
    delete[] result;
    result = NULL;
}
(3-3/3)