aboutsummaryrefslogtreecommitdiff
path: root/jdhuff.c
diff options
context:
space:
mode:
Diffstat (limited to 'jdhuff.c')
-rw-r--r--jdhuff.c30
1 files changed, 20 insertions, 10 deletions
diff --git a/jdhuff.c b/jdhuff.c
index 83478f3b..f786c105 100644
--- a/jdhuff.c
+++ b/jdhuff.c
@@ -540,6 +540,12 @@ process_restart(j_decompress_ptr cinfo)
}
+#if defined(__has_feature)
+#if __has_feature(undefined_behavior_sanitizer)
+__attribute__((no_sanitize("signed-integer-overflow"),
+ no_sanitize("unsigned-integer-overflow")))
+#endif
+#endif
LOCAL(boolean)
decode_mcu_slow(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
{
@@ -572,11 +578,15 @@ decode_mcu_slow(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
if (entropy->dc_needed[blkn]) {
/* Convert DC difference to actual value, update last_dc_val */
int ci = cinfo->MCU_membership[blkn];
- /* This is really just
- * s += state.last_dc_val[ci];
- * It is written this way in order to shut up UBSan.
+ /* Certain malformed JPEG images produce repeated DC coefficient
+ * differences of 2047 or -2047, which causes state.last_dc_val[ci] to
+ * grow until it overflows or underflows a 32-bit signed integer. This
+ * behavior is, to the best of our understanding, innocuous, and it is
+ * unclear how to work around it without potentially affecting
+ * performance. Thus, we (hopefully temporarily) suppress UBSan integer
+ * overflow errors for this function.
*/
- s = (int)((unsigned int)s + (unsigned int)state.last_dc_val[ci]);
+ s += state.last_dc_val[ci];
state.last_dc_val[ci] = s;
if (block) {
/* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */
@@ -662,7 +672,7 @@ decode_mcu_fast(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
d_derived_tbl *actbl = entropy->ac_cur_tbls[blkn];
register int s, k, r, l;
- HUFF_DECODE_FAST(s, l, dctbl, slow_decode_mcu);
+ HUFF_DECODE_FAST(s, l, dctbl);
if (s) {
FILL_BIT_BUFFER_FAST
r = GET_BITS(s);
@@ -671,7 +681,7 @@ decode_mcu_fast(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
if (entropy->dc_needed[blkn]) {
int ci = cinfo->MCU_membership[blkn];
- s = (int)((unsigned int)s + (unsigned int)state.last_dc_val[ci]);
+ s += state.last_dc_val[ci];
state.last_dc_val[ci] = s;
if (block)
(*block)[0] = (JCOEF)s;
@@ -680,7 +690,7 @@ decode_mcu_fast(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
if (entropy->ac_needed[blkn] && block) {
for (k = 1; k < DCTSIZE2; k++) {
- HUFF_DECODE_FAST(s, l, actbl, slow_decode_mcu);
+ HUFF_DECODE_FAST(s, l, actbl);
r = s >> 4;
s &= 15;
@@ -699,7 +709,7 @@ decode_mcu_fast(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
} else {
for (k = 1; k < DCTSIZE2; k++) {
- HUFF_DECODE_FAST(s, l, actbl, slow_decode_mcu);
+ HUFF_DECODE_FAST(s, l, actbl);
r = s >> 4;
s &= 15;
@@ -716,7 +726,6 @@ decode_mcu_fast(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
}
if (cinfo->unread_marker != 0) {
-slow_decode_mcu:
cinfo->unread_marker = 0;
return FALSE;
}
@@ -779,7 +788,8 @@ use_slow:
}
/* Account for restart interval (no-op if not using restarts) */
- entropy->restarts_to_go--;
+ if (cinfo->restart_interval)
+ entropy->restarts_to_go--;
return TRUE;
}