// Copyright (c) the JPEG XL Project Authors. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file.
Status ReadICCProfile(jpeg_decompress_struct* const cinfo,
std::vector<uint8_t>* const icc) {
constexpr size_t kICCSignatureSize = sizeof kICCSignature; // ICC signature + uint8_t index + uint8_t max_index.
constexpr size_t kICCHeadSize = kICCSignatureSize + 2; // Markers are 1-indexed, and we keep them that way in this vector to get a // convenient 0 at the front for when we compute the offsets later.
std::vector<size_t> marker_lengths; int num_markers = 0; int seen_markers_count = 0; bool has_num_markers = false; for (jpeg_saved_marker_ptr marker = cinfo->marker_list; marker != nullptr;
marker = marker->next) { // marker is initialized by libjpeg, which we are not instrumenting with // msan.
msan::UnpoisonMemory(marker, sizeof(*marker));
msan::UnpoisonMemory(marker->data, marker->data_length); if (!MarkerIsICC(marker)) continue;
Status DecodeImageJPG(const Span<const uint8_t> bytes, const ColorHints& color_hints, PackedPixelFile* ppf, const SizeConstraints* constraints, const JPGDecompressParams* dparams) { #if JPEGXL_ENABLE_JPEG // Don't do anything for non-JPEG files (no need to report an error) if (!IsJPG(bytes)) returnfalse;
// TODO(veluca): use JPEGData also for pixels?
// We need to declare all the non-trivial destructor local variables before // the call to setjmp().
std::unique_ptr<JSAMPLE[]> row;
constauto try_catch_block = [&]() -> bool {
jpeg_decompress_struct cinfo = {}; // Setup error handling in jpeg library so we can deal with broken jpegs in // the fuzzer.
jpeg_error_mgr jerr;
jmp_buf env;
cinfo.err = jpeg_std_error(&jerr);
jerr.error_exit = &MyErrorExit;
jerr.output_message = &MyOutputMessage; if (setjmp(env)) { returnfalse;
}
cinfo.client_data = static_cast<void*>(&env);
jpeg_create_decompress(&cinfo);
jpeg_mem_src(&cinfo, reinterpret_cast<constunsignedchar*>(bytes.data()),
bytes.size());
jpeg_save_markers(&cinfo, kICCMarker, 0xFFFF);
jpeg_save_markers(&cinfo, kExifMarker, 0xFFFF); constauto failure = [&cinfo](constchar* str) -> Status {
jpeg_abort_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo); return JXL_FAILURE("%s", str);
}; int read_header_result = jpeg_read_header(&cinfo, TRUE); // TODO(eustas): what about JPEG_HEADER_TABLES_ONLY? if (read_header_result == JPEG_SUSPENDED) { return failure("truncated JPEG input");
} if (!VerifyDimensions(constraints, cinfo.image_width, cinfo.image_height)) { return failure("image too big");
} // Might cause CPU-zip bomb. if (cinfo.arith_code) { return failure("arithmetic code JPEGs are not supported");
} int nbcomp = cinfo.num_components; if (nbcomp != 1 && nbcomp != 3) { return failure("unsupported number of components in JPEG");
} if (ReadICCProfile(&cinfo, &ppf->icc)) {
ppf->primary_color_representation = PackedPixelFile::kIccIsPrimary;
} else {
ppf->primary_color_representation =
PackedPixelFile::kColorEncodingIsPrimary;
ppf->icc.clear(); // Default to SRGB // Actually, (cinfo.output_components == nbcomp) will be checked after // `jpeg_start_decompress`.
ppf->color_encoding.color_space =
(nbcomp == 1) ? JXL_COLOR_SPACE_GRAY : JXL_COLOR_SPACE_RGB;
ppf->color_encoding.white_point = JXL_WHITE_POINT_D65;
ppf->color_encoding.primaries = JXL_PRIMARIES_SRGB;
ppf->color_encoding.transfer_function = JXL_TRANSFER_FUNCTION_SRGB;
ppf->color_encoding.rendering_intent = JXL_RENDERING_INTENT_PERCEPTUAL;
}
ReadExif(&cinfo, &ppf->metadata.exif); if (!ApplyColorHints(color_hints, /*color_already_set=*/true, /*is_gray=*/false, ppf)) { return failure("ApplyColorHints failed");
}
ppf->info.xsize = cinfo.image_width;
ppf->info.ysize = cinfo.image_height; // Original data is uint, so exponent_bits_per_sample = 0.
ppf->info.bits_per_sample = BITS_IN_JSAMPLE;
static_assert(BITS_IN_JSAMPLE == 8 || BITS_IN_JSAMPLE == 16);
ppf->info.exponent_bits_per_sample = 0;
ppf->info.uses_original_profile = JXL_TRUE;
// No alpha in JPG
ppf->info.alpha_bits = 0;
ppf->info.alpha_exponent_bits = 0;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.