Cover offset+bounds wrapping in the APNG frame region check. (flutter/engine#57025)

The `offset + bounds` calculation in the bounds checks could wrap around, bypassing the check.

(Follow up to https://github.com/flutter/engine/pull/56928)
This commit is contained in:
Brandon DeRosier 2024-12-06 15:26:31 -08:00 committed by GitHub
parent 849bf8bd37
commit 83d36af187
3 changed files with 29 additions and 1 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 B

View File

@ -110,7 +110,15 @@ bool APNGImageGenerator::GetPixels(const SkImageInfo& info,
<< ") of APNG due to the frame missing data (frame_info).";
return false;
}
if (frame.x_offset + frame_info.width() >
if (
// Check for unsigned integer wrapping for
// frame.{x|y}_offset + frame_info.{width|height}().
frame.x_offset >
std::numeric_limits<uint32_t>::max() - frame_info.width() ||
frame.y_offset >
std::numeric_limits<uint32_t>::max() - frame_info.height() ||
frame.x_offset + frame_info.width() >
static_cast<unsigned int>(info.width()) ||
frame.y_offset + frame_info.height() >
static_cast<unsigned int>(info.height())) {

View File

@ -272,6 +272,26 @@ void main() {
}
}
});
test(
'Animated apng frame decode does not crash with invalid destination region and bounds wrapping',
() async {
final Uint8List data = File(
path.join('flutter', 'lib', 'ui', 'fixtures', 'out_of_bounds_wrapping.apng'),
).readAsBytesSync();
final ui.Codec codec = await ui.instantiateImageCodec(data);
try {
await codec.getNextFrame();
fail('exception not thrown');
} on Exception catch (e) {
if (impellerEnabled) {
expect(e.toString(), contains('Could not decompress image.'));
} else {
expect(e.toString(), contains('Codec failed'));
}
}
});
}
/// Returns a File handle to a file in the skia/resources directory.