Skip to content

Commit 5a487ba

Browse files
committed
Do not overflow/underflow intermediate predictions
1 parent 8e0c81d commit 5a487ba

File tree

2 files changed

+36
-28
lines changed

2 files changed

+36
-28
lines changed

src/librawspeed/decompressors/AbstractLJpegDecompressor.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,9 +187,9 @@ class AbstractLJpegDecompressor : public AbstractDecompressor {
187187

188188
template <int N_COMP>
189189
[[nodiscard]] [[nodiscard]] [[nodiscard]] __attribute__((pure))
190-
std::array<uint16_t, N_COMP>
190+
std::array<int32_t, N_COMP>
191191
getInitialPredictors() const {
192-
std::array<uint16_t, N_COMP> pred;
192+
std::array<int32_t, N_COMP> pred;
193193
if (frame.prec < (Pt + 1)) {
194194
ThrowRDE("Invalid precision (%u) and point transform (%u) combination!",
195195
frame.prec, Pt);

src/librawspeed/decompressors/LJpegDecompressor.cpp

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,10 @@ template <int N_COMP, bool WeirdWidth> void LJpegDecompressor::decodeN() {
173173

174174
auto ht = getHuffmanTables<N_COMP>();
175175
auto pred = getInitialPredictors<N_COMP>();
176-
uint16_t* predNext = pred.data();
176+
std::array<uint16_t, N_COMP> predNext;
177+
for (int i = 0; i != N_COMP; ++i) {
178+
predNext[i] = uint16_t(pred);
179+
}
177180

178181
BitPumpJPEG bitStream(input);
179182

@@ -191,9 +194,9 @@ template <int N_COMP, bool WeirdWidth> void LJpegDecompressor::decodeN() {
191194
for (unsigned row = 0; row < h; ++row) {
192195
unsigned col = 0;
193196

194-
copy_n(predNext, N_COMP, pred.data());
195-
// the predictor for the next line is the start of this line
196-
predNext = &img(row, col);
197+
for (int i = 0; i != N_COMP; ++i) {
198+
pred[i] = predNext[i];
199+
}
197200
// the predictor mode is always horizontal on the first line
198201
uint32_t predMode = row == 0 ? 1 : predictorMode;
199202

@@ -204,32 +207,32 @@ template <int N_COMP, bool WeirdWidth> void LJpegDecompressor::decodeN() {
204207
for (; col < N_COMP * fullBlocks; col += N_COMP) {
205208
for (int i = 0; i != N_COMP; ++i) {
206209
img(row, col + i) =
207-
uint16_t(pred[i] + ht[i]->decodeDifference(bitStream));
210+
uint16_t(pred[i] + uint16_t(ht[i]->decodeDifference(bitStream)));
208211
if (col < N_COMP * (fullBlocks - 1)) {
209-
int predA = img(row, col + i);
210-
int predB = predMode > 1 ? img(row - 1, col + N_COMP + i) : 0;
211-
int predC = predMode > 1 ? img(row - 1, col + i) : 0;
212+
int32_t predA = img(row, col + i);
213+
int32_t predB = predMode > 1 ? img(row - 1, col + N_COMP + i) : 0;
214+
int32_t predC = predMode > 1 ? img(row - 1, col + i) : 0;
212215
switch (predMode) {
213216
case 1:
214-
pred[i] = uint16_t(predA);
217+
pred[i] = predA;
215218
break;
216219
case 2:
217-
pred[i] = uint16_t(predB);
220+
pred[i] = predB;
218221
break;
219222
case 3:
220-
pred[i] = uint16_t(predC);
223+
pred[i] = predC;
221224
break;
222225
case 4:
223-
pred[i] = uint16_t(predA + predB - predC);
226+
pred[i] = predA + predB - predC;
224227
break;
225228
case 5:
226-
pred[i] = uint16_t(predA + ((predB - predC) >> 1));
229+
pred[i] = predA + ((predB - predC) >> 1);
227230
break;
228231
case 6:
229-
pred[i] = uint16_t(predB + ((predA - predC) >> 1));
232+
pred[i] = predB + ((predA - predC) >> 1);
230233
break;
231234
case 7:
232-
pred[i] = uint16_t((predA + predB) >> 1);
235+
pred[i] = (predA + predB) >> 1;
233236
break;
234237
default:
235238
ThrowRDE("Unsupported predictor mode: %u", predMode);
@@ -238,6 +241,11 @@ template <int N_COMP, bool WeirdWidth> void LJpegDecompressor::decodeN() {
238241
}
239242
}
240243

244+
// the predictor for the next line is the start of this decoded line
245+
for (int i = 0; i != N_COMP; ++i) {
246+
predNext[i] = img(row, i);
247+
}
248+
241249
// Sometimes we also need to consume one more block, and produce part of it.
242250
if /*constexpr*/ (WeirdWidth) {
243251
// FIXME: evaluate i-cache implications due to this being compile-time.
@@ -250,36 +258,36 @@ template <int N_COMP, bool WeirdWidth> void LJpegDecompressor::decodeN() {
250258
unsigned c = 0;
251259
for (; c < trailingPixels; ++c) {
252260
// Continue predictor update skipped at last full block
253-
int predA = img(row, col - N_COMP + c);
254-
int predB = predMode > 1 ? img(row - 1, col + c) : 0;
255-
int predC = predMode > 1 ? img(row - 1, col - N_COMP + c) : 0;
261+
int32_t predA = img(row, col - N_COMP + c);
262+
int32_t predB = predMode > 1 ? img(row - 1, col + c) : 0;
263+
int32_t predC = predMode > 1 ? img(row - 1, col - N_COMP + c) : 0;
256264
switch (predMode) {
257265
case 1:
258-
pred[c] = uint16_t(predA);
266+
pred[c] = predA;
259267
break;
260268
case 2:
261-
pred[c] = uint16_t(predB);
269+
pred[c] = predB;
262270
break;
263271
case 3:
264-
pred[c] = uint16_t(predC);
272+
pred[c] = predC;
265273
break;
266274
case 4:
267-
pred[c] = uint16_t(predA + predB - predC);
275+
pred[c] = predA + predB - predC;
268276
break;
269277
case 5:
270-
pred[c] = uint16_t(predA + ((predB - predC) >> 1));
278+
pred[c] = predA + ((predB - predC) >> 1);
271279
break;
272280
case 6:
273-
pred[c] = uint16_t(predB + ((predA - predC) >> 1));
281+
pred[c] = predB + ((predA - predC) >> 1);
274282
break;
275283
case 7:
276-
pred[c] = uint16_t((predA + predB) >> 1);
284+
pred[c] = (predA + predB) >> 1;
277285
break;
278286
default:
279287
ThrowRDE("Unsupported predictor mode: %u", predMode);
280288
}
281289
img(row, col + c) =
282-
uint16_t(pred[c] + ht[c]->decodeDifference(bitStream));
290+
uint16_t(pred[c] + uint16_t(ht[c]->decodeDifference(bitStream)));
283291
}
284292
// Discard the rest of the block.
285293
assert(c < N_COMP);

0 commit comments

Comments
 (0)