Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9b3d6859 authored by Ram Mohan's avatar Ram Mohan Committed by Dichen Zhang
Browse files

ultrahdr: update error checks in encode/decode path

1. library assumes the gain map resolution is 1/kMapDimensionScaleFactor
of primary image resolution. If it is not the case the output hdr image
computations are not according to the scale factor. Signal error if map
scale factor is not kMapDimensionScaleFactor.
2. library expects primary image to be 420 and gain map image to be 400.
Validate the same.
3. disallow srgb transfer function way early as this is not handled.
4. avoid nullptr access in metadata.

Bug: 284120011
Test: ./ultrahdr_enc_fuzzer
Change-Id: Ie2cd12ac95306958cbb18679039681fc4eb3d9cc
parent 6bd58d4d
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@
namespace android::ultrahdr {
// Color gamuts for image data
typedef enum {
  ULTRAHDR_COLORGAMUT_UNSPECIFIED,
  ULTRAHDR_COLORGAMUT_UNSPECIFIED = -1,
  ULTRAHDR_COLORGAMUT_BT709,
  ULTRAHDR_COLORGAMUT_P3,
  ULTRAHDR_COLORGAMUT_BT2100,
@@ -52,7 +52,7 @@ typedef enum {
 */
struct ultrahdr_metadata_struct {
  // Ultra HDR library version
  const char* version;
  std::string version;
  // Max Content Boost for the map
  float maxContentBoost;
  // Min Content Boost for the map
+26 −7
Original line number Diff line number Diff line
@@ -145,7 +145,8 @@ status_t JpegR::areInputArgumentsValid(jr_uncompressed_ptr uncompressed_p010_ima
    return ERROR_JPEGR_INVALID_NULL_PTR;
  }

  if (hdr_tf <= ULTRAHDR_TF_UNSPECIFIED || hdr_tf > ULTRAHDR_TF_MAX) {
  if (hdr_tf <= ULTRAHDR_TF_UNSPECIFIED || hdr_tf > ULTRAHDR_TF_MAX
          || hdr_tf == ULTRAHDR_TF_SRGB) {
    ALOGE("Invalid hdr transfer function %d", hdr_tf);
    return ERROR_JPEGR_INVALID_INPUT_TYPE;
  }
@@ -509,11 +510,6 @@ status_t JpegR::decodeJPEGR(jr_compressed_ptr compressed_jpegr_image,
    return ERROR_JPEGR_INVALID_INPUT_TYPE;
  }

  if (gain_map != nullptr && gain_map->data == nullptr) {
    ALOGE("received nullptr address for gain map data");
    return ERROR_JPEGR_INVALID_INPUT_TYPE;
  }

  if (output_format == ULTRAHDR_OUTPUT_SDR) {
    JpegDecoderHelper jpeg_decoder;
    if (!jpeg_decoder.decompressImage(compressed_jpegr_image->data, compressed_jpegr_image->length,
@@ -555,6 +551,11 @@ status_t JpegR::decodeJPEGR(jr_compressed_ptr compressed_jpegr_image,
  if (!gain_map_decoder.decompressImage(compressed_map.data, compressed_map.length)) {
    return ERROR_JPEGR_DECODE_ERROR;
  }
  if ((gain_map_decoder.getDecompressedImageWidth() *
       gain_map_decoder.getDecompressedImageHeight()) >
      gain_map_decoder.getDecompressedImageSize()) {
    return ERROR_JPEGR_CALCULATION_ERROR;
  }

  if (gain_map != nullptr) {
    gain_map->width = gain_map_decoder.getDecompressedImageWidth();
@@ -584,6 +585,11 @@ status_t JpegR::decodeJPEGR(jr_compressed_ptr compressed_jpegr_image,
  if (!jpeg_decoder.decompressImage(compressed_jpegr_image->data, compressed_jpegr_image->length)) {
    return ERROR_JPEGR_DECODE_ERROR;
  }
  if ((jpeg_decoder.getDecompressedImageWidth() *
       jpeg_decoder.getDecompressedImageHeight() * 3 / 2) >
      jpeg_decoder.getDecompressedImageSize()) {
    return ERROR_JPEGR_CALCULATION_ERROR;
  }

  if (exif != nullptr) {
    if (exif->data == nullptr) {
@@ -605,7 +611,6 @@ status_t JpegR::decodeJPEGR(jr_compressed_ptr compressed_jpegr_image,
  uncompressed_yuv_420_image.data = jpeg_decoder.getDecompressedImagePtr();
  uncompressed_yuv_420_image.width = jpeg_decoder.getDecompressedImageWidth();
  uncompressed_yuv_420_image.height = jpeg_decoder.getDecompressedImageHeight();

  JPEGR_CHECK(applyGainMap(&uncompressed_yuv_420_image, &map, &uhdr_metadata, output_format,
                           max_display_boost, dest));
  return NO_ERROR;
@@ -848,6 +853,20 @@ status_t JpegR::applyGainMap(jr_uncompressed_ptr uncompressed_yuv_420_image,
    return ERROR_JPEGR_INVALID_NULL_PTR;
  }

  // TODO: remove once map scaling factor is computed based on actual map dims
  size_t image_width = uncompressed_yuv_420_image->width;
  size_t image_height = uncompressed_yuv_420_image->height;
  size_t map_width = image_width / kMapDimensionScaleFactor;
  size_t map_height = image_height / kMapDimensionScaleFactor;
  map_width = static_cast<size_t>(
          floor((map_width + kJpegBlock - 1) / kJpegBlock)) * kJpegBlock;
  map_height = ((map_height + 1) >> 1) << 1;
  if (map_width != uncompressed_gain_map->width
   || map_height != uncompressed_gain_map->height) {
    ALOGE("gain map dimensions and primary image dimensions are not to scale");
    return ERROR_JPEGR_INVALID_INPUT_TYPE;
  }

  dest->width = uncompressed_yuv_420_image->width;
  dest->height = uncompressed_yuv_420_image->height;
  ShepardsIDW idwTable(kMapDimensionScaleFactor);