[하루한줄] CVE-2026-24450: LibRaw uncompressed_fp_dng_load_raw heap overflow 취약점
URL
Target
- LibRaw 8dc68e2 commit
Explain
LibRaw는 디지털카메라의 RAW 이미지 파일을 처리하기 위한 오픈소스 C/C++ 라이브러리입니다.
LibRaw에서 DNG 파일을 지원하며 CVE-2026-24450는 DNG 파일 디코더 루틴에서 발생했습니다.
void LibRaw::uncompressed_fp_dng_load_raw()
{
[...]
tile_stripe_data_t tiles;
tiles.init(ifd, imgdata.sizes, libraw_internal_data.unpacker_data,
libraw_internal_data.unpacker_data.order,
libraw_internal_data.internal_data.input);
[1] INT64 allocsz = INT64(tiles.tileCnt) * INT64(tiles.tileWidth) *
INT64(tiles.tileHeight) * INT64(ifd->samples) *
INT64(sizeof(float));
[2] if (allocsz > INT64(imgdata.rawparams.max_raw_memory_mb) * INT64(1024 * 1024))
throw LIBRAW_EXCEPTION_TOOBIG;
if (ifd->sample_format == 3)
[3] float_raw_image = (float *)calloc(tiles.tileCnt * tiles.tileWidth *
tiles.tileHeight * ifd->samples,
sizeof(float));
[...]
for (size_t y = 0, t = 0; y < imgdata.sizes.raw_height; y += tiles.tileHeight)
{
for (unsigned x = 0; x < imgdata.sizes.raw_width && t < (unsigned)tiles.tileCnt;
x += tiles.tileWidth, ++t)
{
libraw_internal_data.internal_data.input->seek(tiles.tOffsets[t], SEEK_SET);
size_t rowsInTile = y + tiles.tileHeight > imgdata.sizes.raw_height ? imgdata.sizes.raw_height - y : tiles.tileHeight;
size_t colsInTile = x + tiles.tileWidth > imgdata.sizes.raw_width ? imgdata.sizes.raw_width - x : tiles.tileWidth;
size_t inrowbytes = colsInTile * bytesps * ifd->samples;
int fullrowbytes = tiles.tileWidth *bytesps * ifd->samples;
size_t outrowbytes = colsInTile * sizeof(float) * ifd->samples;
for (size_t row = 0; row < rowsInTile; ++row)
{
[4] unsigned char *dst = fullrowbytes > int(inrowbytes) ? rowbuf.data():
(unsigned char *)&float_raw_image
[((y + row) * imgdata.sizes.raw_width + x) * ifd->samples];
[5] libraw_internal_data.internal_data.input->read(dst, 1, fullrowbytes);
[...]
}
}
}
}
DNG 파일은 TIFF 파일 포맷을 기반으로 하며 [1] allocsz 변수 계산에 사용되는 값은 아래 DNG 태그에서 가져옵니다.
tiles.tileWidth: TileWidth 또는 ImageWidthtiles.tileHeight: TileLength 또는 RowsPerStriptiles.tileCnt: ceil(ImageWidth / TileWidth) * ceil(ImageLength / TileHeight)ifd->samples: SamplesPerPixel
[1] INT64 타입 캐스팅을 사용하여 버퍼 크기를 계산하고 [2] 설정된 최대 메모리 제한 값과 비교합니다. 하지만, [3] 실제 메모리를 할당 과정에서는 INT64 타입 캐스팅을 적용하지 않아 취약점이 발생했습니다.
calloc( tiles.tileCnt * tiles.tileWidth * tiles.tileHeight * ifd->samples, sizeof(float) );
첫 번째 인자 연산 시 32bit로 계산되기 때문에 integer overflow를 트리거 하여 실제 필요한 size보다 작은 size로 float_raw_image 버퍼를 할당할 수 있습니다.
[4] fullrowbytes 변수는 타일 한 행의 전체 크기, inrowbytes 변수는 현재 타일 위치에서 실제로 처리해야 하는 행의 크기입니다.
현재 타일 위치에서 처리해야 하는 행의 크기가 전체 크기일 경우 [4] 조건식이 false가 되어, dst는 float_raw_image를 가리키게 됩니다.
이후 [5] float_raw_image 버퍼에 파일 데이터를 write 할 때 [3] integer overflow로 작게 할당하면 heap overflow를 트리거 할 수 있습니다.
추가로 float_raw_image 버퍼 index 계산 시 raw_width와 raw_height를 통해 OOB Write가 가능합니다.
Patch

해당 취약점은 float_raw_image 버퍼 할당 시 검증에 사용된 allocsz 변수를 사용하도록 패치 되었습니다.
Reference
본 글은 CC BY-SA 4.0 라이선스로 배포됩니다. 공유 또는 변경 시 반드시 출처를 남겨주시기 바랍니다.