Merge commit 'de5f92937857cccc45080c59c6236561416e5ece' into libraw-copylib

Upgrade LibRaw to 0.21.2.
This commit is contained in:
Lawrence Lee
2023-12-31 12:52:34 -08:00
19 changed files with 150 additions and 49 deletions

View File

@@ -1,3 +1,25 @@
2023-12-19 Alex Tutubalin <lexa@lexa.ru>
LibRaw 0.21.2-Release
* New compile-defined limit LIBRAW_MAX_PROFILE_SIZE_MB:
limits allocation/read size for embedded color profile (default: 256Mb)
* Embedded color profile allocation/read size: limited by input file size.
* Multiple fixes (mostly inspired by oss-fuzz) to improve library stability and/or input checks.
* raw-identify: use fallback if PATH_MAX not available
* Disabled color conversion for Canon 16-bit thumbnails
* docs/changelog: explained the case when no thumbnail is found in specific file
* swapXX renamed to libraw_swapXX to avoid name conflict
* better striped thumbnails handling
2023-01-05 Alex Tutubalin <lexa@lexa.ru>
LibRaw 0.21.1-Release
* fixed typo in panasonic metadata parser
@@ -52,7 +74,11 @@
Notes:
- Only TIFF-based and CR3 files are parsed for thumbnail list, other formats will have
thumbcount = 1 (or 0 if no thumbnail found in file).
thumbcount = 1.
- If no thumbnails are found in file: thumbcount will be set to 1 and
thumblist[0] will be initialized with data from thumbnail fields,
so LibRaw::unpack_thumb_ex(0) will do the same as LibRaw::unpack_thumb()
- Thumbnail image size may be unknown (not recorded in metadata), in this case twidth and theight are zero.
Usually small(er) thumbnails will always have twidth/theight filled, while largest one may have these fields set to zero.

View File

@@ -427,6 +427,12 @@
<dd>Thumbnail data offset in file</dd>
</dl>
</dd>
</dl>
<p>
Note: even if no thumbnails were found in TIFF/CR3 structure, the
thumbcount field will be initialized to 1 and thumblist[0] will be
initialized to thumbnail data from the thumbnail data, so
LibRaw::unpack_thumb_ex(0) will do the same as LibRaw::unpack_thumb().
</p>
<p><a name="libraw_lensinfo_t"></a></p>
<h3>Structure libraw_lensinfo_t: parsed lens data</h3>

View File

@@ -24,6 +24,10 @@ it under the terms of the one of two licenses as you choose:
#define LIBRAW_MAX_ALLOC_MB_DEFAULT 2048L
#endif
#ifndef LIBRAW_MAX_PROFILE_SIZE_MB
#define LIBRAW_MAX_PROFILE_SIZE_MB 256LL
#endif
#ifndef LIBRAW_MAX_NONDNG_RAW_FILE_SIZE
#define LIBRAW_MAX_NONDNG_RAW_FILE_SIZE 2147483647ULL
#endif

View File

@@ -22,7 +22,7 @@ it under the terms of the one of two licenses as you choose:
#define LIBRAW_MAJOR_VERSION 0
#define LIBRAW_MINOR_VERSION 21
#define LIBRAW_PATCH_VERSION 1
#define LIBRAW_PATCH_VERSION 2
#define LIBRAW_VERSION_TAIL Release
#define LIBRAW_SHLIB_CURRENT 23

View File

@@ -40,7 +40,11 @@ it under the terms of the one of two licenses as you choose:
#include <sys/mman.h>
#include <sys/time.h>
#ifndef MAX_PATH
#ifdef PATH_MAX
#define MAX_PATH PATH_MAX
#else
#define MAX_PATH 4096
#endif
#endif
#endif

View File

@@ -577,6 +577,9 @@ void LibRaw::lossless_jpeg_load_raw()
i = jidx / (cr2_slice[1] * raw_height);
if ((j = i >= cr2_slice[0]))
i = cr2_slice[0];
if(!cr2_slice[1+j])
throw LIBRAW_EXCEPTION_IO_CORRUPT;
jidx -= i * (cr2_slice[1] * raw_height);
row = jidx / cr2_slice[1 + j];
col = jidx % cr2_slice[1 + j] + i * cr2_slice[1];
@@ -609,10 +612,16 @@ void LibRaw::canon_sraw_load_raw()
int saved_w = width, saved_h = height;
char *cp;
if(!image)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
if (!ljpeg_start(&jh, 0) || jh.clrs < 4)
return;
jwide = (jh.wide >>= 1) * jh.clrs;
if (jwide < 32 || jwide > 65535)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
if (load_flags & 256)
{
width = raw_width;
@@ -1170,6 +1179,8 @@ void LibRaw::panasonic_load_raw()
}
else
{
if (load_flags >= 0x4000)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
for (row = 0; row < raw_height; row++)
{
checkCancel();

View File

@@ -22,6 +22,9 @@
void LibRaw::sony_arq_load_raw()
{
int row, col;
if (imgdata.idata.filters || imgdata.idata.colors < 3)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
read_shorts(imgdata.rawdata.raw_image,
imgdata.sizes.raw_width * imgdata.sizes.raw_height * 4);
libraw_internal_data.internal_data.input->seek(

View File

@@ -556,7 +556,7 @@ _forceinline
#else
inline
#endif
void swap24(uchar *data, int len)
void libraw_swap24(uchar *data, int len)
{
for (int i = 0; i < len - 2; i += 3)
{
@@ -572,7 +572,7 @@ _forceinline
#else
inline
#endif
void swap32(uchar *data, int len)
void libraw_swap32(uchar *data, int len)
{
unsigned *d = (unsigned*)data;
for (int i = 0; i < len / 4; i++)
@@ -646,9 +646,9 @@ void LibRaw::uncompressed_fp_dng_load_raw()
if (bytesps == 2 && difford)
libraw_swab(dst, fullrowbytes);
else if (bytesps == 3 && (libraw_internal_data.unpacker_data.order == 0x4949)) // II-16bit
swap24(dst, fullrowbytes);
libraw_swap24(dst, fullrowbytes);
if (bytesps == 4 && difford)
swap32(dst, fullrowbytes);
libraw_swap32(dst, fullrowbytes);
float lmax = expandFloats(
dst,

View File

@@ -352,10 +352,17 @@ int LibRaw::phase_one_correct()
{ /* Quadrant linearization */
ushort lc[2][2][16], ref[16];
int qr, qc;
bool baddiv = false;
for (qr = 0; qr < 2; qr++)
for (qc = 0; qc < 2; qc++)
for (i = 0; i < 16; i++)
lc[qr][qc][i] = get4();
for (qc = 0; qc < 2; qc++)
{
for (i = 0; i < 16; i++)
lc[qr][qc][i] = get4();
if (lc[qr][qc][15] == 0)
baddiv = true;
}
if(baddiv)
continue;
for (i = 0; i < 16; i++)
{
int v = 0;

View File

@@ -266,8 +266,9 @@ int LibRaw::unpack_thumb(void)
tiff_ifd[pifd].strip_byte_counts_count)
{
// We found it, calculate final size
unsigned total_size = 0;
for (int i = 0; i < tiff_ifd[pifd].strip_byte_counts_count; i++)
INT64 total_size = 0;
for (int i = 0; i < tiff_ifd[pifd].strip_byte_counts_count
&& i < tiff_ifd[pifd].strip_offsets_count; i++)
total_size += tiff_ifd[pifd].strip_byte_counts[i];
if (total_size != (unsigned)t_length) // recalculate colors
{
@@ -284,15 +285,15 @@ int LibRaw::unpack_thumb(void)
char *dest = T.thumb;
INT64 pos = ID.input->tell();
INT64 remain = T.tlength;
for (int i = 0; i < tiff_ifd[pifd].strip_byte_counts_count &&
i < tiff_ifd[pifd].strip_offsets_count;
i++)
{
int remain = T.tlength;
int sz = tiff_ifd[pifd].strip_byte_counts[i];
int off = tiff_ifd[pifd].strip_offsets[i];
if (off >= 0 && off + sz <= ID.input->size() && sz <= remain)
INT64 off = tiff_ifd[pifd].strip_offsets[i];
if (off >= 0 && off + sz <= ID.input->size() && sz > 0 && INT64(sz) <= remain)
{
ID.input->seek(off, SEEK_SET);
ID.input->read(dest, sz, 1);
@@ -332,13 +333,13 @@ int LibRaw::unpack_thumb(void)
int o_bps = (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_USE_PPM16_THUMBS) ? 2 : 1;
int o_length = T.twidth * T.theight * t_colors * o_bps;
int i_length = T.twidth * T.theight * t_colors * 2;
if (!T.tlength)
T.tlength = o_length;
THUMB_SIZE_CHECKTNZ(o_length);
THUMB_SIZE_CHECKTNZ(o_length);
THUMB_SIZE_CHECKTNZ(i_length);
THUMB_SIZE_CHECKTNZ(T.tlength);
ushort *t_thumb = (ushort *)calloc(i_length, 1);
if (!t_thumb)
throw LIBRAW_EXCEPTION_ALLOC;
ID.input->read(t_thumb, 1, i_length);
if ((libraw_internal_data.unpacker_data.order == 0x4949) ==
(ntohs(0x1234) == 0x1234))
@@ -350,14 +351,18 @@ int LibRaw::unpack_thumb(void)
{
T.thumb = (char *)t_thumb;
T.tformat = LIBRAW_THUMBNAIL_BITMAP16;
T.tlength = i_length;
}
else
{
T.thumb = (char *)malloc(o_length);
if (!T.thumb)
throw LIBRAW_EXCEPTION_ALLOC;
for (int i = 0; i < o_length; i++)
T.thumb[i] = t_thumb[i] >> 8;
free(t_thumb);
T.tformat = LIBRAW_THUMBNAIL_BITMAP;
T.tlength = o_length;
}
SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD);
return 0;

View File

@@ -265,6 +265,10 @@ void LibRaw::xtrans_interpolate(int passes)
{
rix = &rgb[0][row - top][col - left];
int h = fcol(row, col + 1);
if (h == 1) // Incorrect pattern
break;
float diff[6];
memset(diff, 0, sizeof diff);
for (int i = 1, d = 0; d < 6; d++, i ^= LIBRAW_AHD_TILE ^ 1, h ^= 2)

View File

@@ -460,7 +460,7 @@ int LibRaw_buffer_datastream::scanf_one(const char *fmt, void *val)
if (scanf_res > 0)
{
int xcnt = 0;
while (streampos < streamsize)
while (streampos < streamsize-1)
{
streampos++;
xcnt++;

View File

@@ -132,7 +132,7 @@ void LibRaw::parseAdobeRAFMakernote()
}
#define CHECKSPACE(s) \
if (posPrivateMknBuf + (s) > PrivateMknLength) \
if (INT64(posPrivateMknBuf) + INT64(s) > INT64(PrivateMknLength)) \
{ \
free(PrivateMknBuf); \
return; \
@@ -209,7 +209,7 @@ void LibRaw::parseAdobeRAFMakernote()
PrivateOrder = sget2(PrivateMknBuf);
unsigned s, l;
s = ifd_start = sget4(PrivateMknBuf +2)+6;
CHECKSPACE(ifd_start+4);
CHECKSPACE(INT64(ifd_start)+4LL);
l = ifd_len = sget4(PrivateMknBuf +ifd_start);
CHECKSPACE_ABS3(ifd_start, ifd_len, 4);
@@ -767,7 +767,7 @@ void LibRaw::parseAdobeRAFMakernote()
if (wb_section_offset)
{
CHECKSPACE(wb_section_offset + 12);
CHECKSPACE(INT64(wb_section_offset) + 12LL);
}
if (wb_section_offset &&

View File

@@ -39,6 +39,7 @@ void LibRaw::wavelet_denoise()
static const float noise[] = {0.8002f, 0.2735f, 0.1202f, 0.0585f,
0.0291f, 0.0152f, 0.0080f, 0.0044f};
if (iwidth < 65 || iheight < 65) return;
while (maximum << scale < 0x10000)
scale++;
@@ -135,6 +136,9 @@ void LibRaw::wavelet_denoise()
static const float noise[] = {0.8002, 0.2735, 0.1202, 0.0585,
0.0291, 0.0152, 0.0080, 0.0044};
if (iwidth < 65 || iheight < 65)
return;
while (maximum << scale < 0x10000)
scale++;
maximum <<= --scale;
@@ -324,6 +328,9 @@ void LibRaw::recover_highlights()
grow = pow(2.0, 4 - highlight);
FORC(unsigned(colors)) hsat[c] = 32000 * pre_mul[c];
FORC(unsigned(colors))
if(hsat[c]<1)
return;
for (kc = 0, c = 1; c < (unsigned)colors; c++)
if (pre_mul[kc] < pre_mul[c])
kc = c;

View File

@@ -43,6 +43,8 @@ void LibRaw::raw2image_start()
// adjust for half mode!
IO.shrink =
!imgdata.rawdata.color4_image && !imgdata.rawdata.color3_image &&
!imgdata.rawdata.float4_image && !imgdata.rawdata.float3_image &&
P1.filters &&
(O.half_size || ((O.threshold || O.aber[0] != 1 || O.aber[2] != 1)));

View File

@@ -17,15 +17,15 @@
#define _ARR_SZ(a) (sizeof(a)/sizeof(a[0]))
static const int _tagtype_dataunit_bytes [19] = {
1, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8, 4, 2, 8, 8, 8, 8
static const int _tagtype_dataunit_bytes [20] = {
1, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8, 4, 2, 8, 8, 8, 8, 8
};
libraw_static_table_t LibRaw::tagtype_dataunit_bytes(_tagtype_dataunit_bytes, _ARR_SZ(_tagtype_dataunit_bytes));
int libraw_tagtype_dataunit_bytes(int tagtype)
{
return _tagtype_dataunit_bytes[((unsigned)tagtype <= _ARR_SZ(_tagtype_dataunit_bytes)) ? tagtype : 0];
return _tagtype_dataunit_bytes[((unsigned)tagtype < _ARR_SZ(_tagtype_dataunit_bytes)) ? tagtype : 0];
}

View File

@@ -37,8 +37,11 @@ void LibRaw::cubic_spline(const int *x_, const int *y_, const int len)
}
for (i = len - 1; i > 0; i--)
{
b[i] = (y[i] - y[i - 1]) / (x[i] - x[i - 1]);
d[i - 1] = x[i] - x[i - 1];
float _div = x[i] - x[i - 1];
if (fabs(_div) < 1.0e-15)
_div = 1;
b[i] = (y[i] - y[i - 1]) / _div;
d[i - 1] = _div;
}
for (i = 1; i < len - 1; i++)
{

View File

@@ -482,7 +482,10 @@ int LibRaw::open_datastream(LibRaw_abstract_datastream *stream)
// Fuji layout files: either DNG or unpacked_load_raw should be used
if (libraw_internal_data.internal_output_params.fuji_width || libraw_internal_data.unpacker_data.fuji_layout)
{
if (!imgdata.idata.dng_version && load_raw != &LibRaw::unpacked_load_raw)
if (!imgdata.idata.dng_version && load_raw != &LibRaw::unpacked_load_raw
&& load_raw != &LibRaw::unpacked_load_raw_FujiDBP
&& load_raw != &LibRaw::unpacked_load_raw_fuji_f700s20
)
return LIBRAW_FILE_UNSUPPORTED;
}
@@ -1200,9 +1203,15 @@ int LibRaw::open_datastream(LibRaw_abstract_datastream *stream)
{
if (C.profile)
free(C.profile);
C.profile = malloc(C.profile_length);
ID.input->seek(ID.profile_offset, SEEK_SET);
ID.input->read(C.profile, C.profile_length, 1);
INT64 profile_sz = MIN(INT64(C.profile_length), ID.input->size() - ID.profile_offset);
if (profile_sz > 0LL && profile_sz < LIBRAW_MAX_PROFILE_SIZE_MB * 1024LL * 1024LL)
{
C.profile = malloc(size_t(profile_sz));
ID.input->seek(ID.profile_offset, SEEK_SET);
ID.input->read(C.profile, size_t(profile_sz), 1);
}
else
C.profile = NULL;
}
SET_PROC_FLAG(LIBRAW_PROGRESS_IDENTIFY);

View File

@@ -127,26 +127,36 @@ void LibRaw::kodak_thumb_loader()
int(*t_hist)[LIBRAW_HISTOGRAM_SIZE] =
(int(*)[LIBRAW_HISTOGRAM_SIZE])calloc(sizeof(*t_hist), 4);
float out[3], out_cam[3][4] = {{2.81761312f, -1.98369181f, 0.166078627f, 0},
{-0.111855984f, 1.73688626f, -0.625030339f, 0},
{-0.0379119813f, -0.891268849f, 1.92918086f, 0}};
for (img = imgdata.image[0], row = 0; row < S.height; row++)
for (col = 0; col < S.width; col++, img += 4)
{
out[0] = out[1] = out[2] = 0;
int c;
for (c = 0; c < 3; c++)
if (imgdata.idata.maker_index == LIBRAW_CAMERAMAKER_Canon) // Skip color conversion for canon PPM tiffs
{
for (img = imgdata.image[0], row = 0; row < S.height; row++)
for (col = 0; col < S.width; col++, img += 4)
for (int c = 0; c < P1.colors; c++)
t_hist[c][img[c] >> 3]++;
}
else
{
float out[3], out_cam[3][4] = {{2.81761312f, -1.98369181f, 0.166078627f, 0},
{-0.111855984f, 1.73688626f, -0.625030339f, 0},
{-0.0379119813f, -0.891268849f, 1.92918086f, 0}};
for (img = imgdata.image[0], row = 0; row < S.height; row++)
for (col = 0; col < S.width; col++, img += 4)
{
out[0] += out_cam[0][c] * img[c];
out[1] += out_cam[1][c] * img[c];
out[2] += out_cam[2][c] * img[c];
out[0] = out[1] = out[2] = 0;
int c;
for (c = 0; c < 3; c++)
{
out[0] += out_cam[0][c] * img[c];
out[1] += out_cam[1][c] * img[c];
out[2] += out_cam[2][c] * img[c];
}
for (c = 0; c < 3; c++)
img[c] = CLIP((int)out[c]);
for (c = 0; c < P1.colors; c++)
t_hist[c][img[c] >> 3]++;
}
for (c = 0; c < 3; c++)
img[c] = CLIP((int)out[c]);
for (c = 0; c < P1.colors; c++)
t_hist[c][img[c] >> 3]++;
}
}
// from gamma_lut
int(*save_hist)[LIBRAW_HISTOGRAM_SIZE] =