From d4e67a644d8babe7cb68de122d8b5ccb2ad8f226 Mon Sep 17 00:00:00 2001 From: Luca Versari Date: Fri, 9 Jun 2023 21:26:57 +0200 Subject: [PATCH] Fix an integer underflow bug in patch decoding. When reading patches, the code doesn't properly check that all patches are in bounds. In particular, if the start of a patch becomes negative (due to the delta coding of patch positions), but not negative *enough* to cause `start + size` to still be negative, the decoder happily accepted the patch. Such a patch would then lead the interval tree building code to run into an infinite loop. --- lib/jxl/dec_patch_dictionary.cc | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/lib/jxl/dec_patch_dictionary.cc b/lib/jxl/dec_patch_dictionary.cc index 85e5de3c8d8..56538bc232c 100644 --- a/lib/jxl/dec_patch_dictionary.cc +++ b/lib/jxl/dec_patch_dictionary.cc @@ -107,10 +107,20 @@ Status PatchDictionary::Decode(BitReader* br, size_t xsize, size_t ysize, pos.x = read_num(kPatchPositionContext); pos.y = read_num(kPatchPositionContext); } else { - pos.x = - positions_.back().x + UnpackSigned(read_num(kPatchOffsetContext)); - pos.y = - positions_.back().y + UnpackSigned(read_num(kPatchOffsetContext)); + ssize_t deltax = UnpackSigned(read_num(kPatchOffsetContext)); + if (deltax < 0 && static_cast(-deltax) > positions_.back().x) { + return JXL_FAILURE("Invalid patch: negative x coordinate (%" PRIuS + " base x %" PRIdS " delta x)", + positions_.back().x, deltax); + } + pos.x = positions_.back().x + deltax; + ssize_t deltay = UnpackSigned(read_num(kPatchOffsetContext)); + if (deltay < 0 && static_cast(-deltay) > positions_.back().y) { + return JXL_FAILURE("Invalid patch: negative y coordinate (%" PRIuS + " base y %" PRIdS " delta y)", + positions_.back().y, deltay); + } + pos.y = positions_.back().y + deltay; } if (pos.x + ref_pos.xsize > xsize) { return JXL_FAILURE("Invalid patch x: at %" PRIuS " + %" PRIuS