Closed roticv closed 1 month ago
@haixia-meta proposed a possible fix:
@@ -441,18 +441,19 @@
std::vector<int> processed(cinfo->num_scans);
size_t max_refinement_tokens = 0;
size_t num_refinement_bits = 0;
- int num_refinement_scans[DCTSIZE2] = {};
+ int num_refinement_scans[kMaxComponents][DCTSIZE2] = {};
int max_num_refinement_scans = 0;
for (int i = 0; i < cinfo->num_scans; ++i) {
const jpeg_scan_info* si = &cinfo->scan_info[i];
ScanTokenInfo* sti = &m->scan_token_info[i];
if (si->Ss > 0 && si->Ah == 0 && si->Al > 0) {
int offset = m->ac_ctx_offset[i];
+ int comp_idx = si->component_index[0];
TokenizeScan(cinfo, i, offset, sti);
processed[i] = 1;
max_refinement_tokens += sti->num_future_nonzeros;
for (int k = si->Ss; k <= si->Se; ++k) {
- num_refinement_scans[k] = si->Al;
+ num_refinement_scans[comp_idx][k] = si->Al;
}
max_num_refinement_scans = std::max(max_num_refinement_scans, si->Al);
num_refinement_bits += sti->num_nonzeros;
@@ -475,15 +476,17 @@
size_t new_refinement_bits = 0;
for (int i = 0; i < cinfo->num_scans; ++i) {
const jpeg_scan_info* si = &cinfo->scan_info[i];
+ int comp_idx = si->component_index[0];
ScanTokenInfo* sti = &m->scan_token_info[i];
if (si->Ss > 0 && si->Ah > 0 &&
- si->Ah == num_refinement_scans[si->Ss] - j) {
+ si->Ah == num_refinement_scans[comp_idx][si->Ss] - j) {
int offset = m->ac_ctx_offset[i];
TokenizeScan(cinfo, i, offset, sti);
processed[i] = 1;
new_refinement_bits += sti->num_nonzeros;
}
}
+ printf("%llu ?= %llu\n", m->next_refinement_bit, refinement_bits + num_refinement_bits);
JXL_DASSERT(m->next_refinement_bit ==
refinement_bits + num_refinement_bits);
num_refinement_bits += new_refinement_bits;
and he explains the problem as
[the code] only has a single array int num_refinement_scans[DCTSIZE2] and is supposed to find out for each DCT coefficient how many refinement scans there are. the problem is that there are 3 color components and this can differ between component index. for example scan #2 and #3 has Ah = 0 and Al = 1 for chroma components, but the least significant bit is refined at scans #7 and #8.
Describe the bug Under certain conditions, num_refinement_bits is computed wrongly causing a heap-buffer-overflow in jpegli's TokenizeACRefinementScan in https://github.com/google/jpegli/blob/main/lib/jpegli/entropy_coding.cc#L255
To Reproduce There is a need to use a specific scan_info to trigger it. I was able to reproduce it with the following patch:
Steps to reproduce the behavior:
Expected behavior num_refinement_bits is computed correctly and there is no heap-buffer-overflow
Environment