1 #![no_main] 2 use libfuzzer_sys::fuzz_target; 3 extern crate qcms; 4 extern crate libc; 5 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 6 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 7 /* This Source Code Form is subject to the terms of the Mozilla Public 8 * License, v. 2.0. If a copy of the MPL was not distributed with this 9 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ 10 11 use qcms::c_bindings::{qcms_profile, icSigRgbData, icSigCmykData, icSigGrayData, qcms_profile_is_bogus}; 12 use qcms::c_bindings::{qcms_profile_get_color_space, qcms_profile_get_rendering_intent, qcms_profile_from_memory, qcms_profile_release, qcms_profile_sRGB, qcms_transform_create}; 13 use qcms::c_bindings::{qcms_profile_precache_output_transform, qcms_transform_data, qcms_transform_release, qcms_enable_iccv4}; 14 15 use qcms::DataType::*; 16 transform(src_profile: *const qcms_profile, dst_profile: *mut qcms_profile, size: usize)17 unsafe fn transform(src_profile: *const qcms_profile, dst_profile: *mut qcms_profile, size: usize) 18 { 19 // qcms supports GRAY and RGB profiles as input, and RGB as output. 20 21 let src_color_space = qcms_profile_get_color_space(&*src_profile); 22 let mut src_type = if (size & 1) != 0 { RGBA8 } else { RGB8 }; 23 if src_color_space == icSigGrayData { 24 src_type = if (size & 1) != 0 { GrayA8 } else { Gray8 }; 25 } else if src_color_space == icSigCmykData { 26 src_type = CMYK; 27 } else if src_color_space != icSigRgbData { 28 return; 29 } 30 31 let dst_color_space = qcms_profile_get_color_space(&*dst_profile); 32 if dst_color_space != icSigRgbData { 33 return; 34 } 35 let dst_type = if (size & 2) != 0 { RGBA8 } else { RGB8 }; 36 37 let intent = qcms_profile_get_rendering_intent(&*src_profile); 38 // Firefox calls this on the display profile to increase performance. 39 // Skip with low probability to increase coverage. 40 if (size % 15) != 0 { 41 qcms_profile_precache_output_transform(&mut *dst_profile); 42 } 43 44 let transform = 45 qcms_transform_create(&*src_profile, src_type, &*dst_profile, dst_type, intent); 46 if transform == std::ptr::null_mut() { 47 return; 48 } 49 50 const SRC_SIZE: usize = 36; 51 let src:[u8; SRC_SIZE] = [ 52 0x7F, 0x7F, 0x7F, 0x00, 0x00, 0x7F, 0x7F, 0xFF, 0x7F, 0x10, 0x20, 0x30, 53 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xB0, 0xBF, 0xEF, 0x6F, 54 0x3F, 0xC0, 0x9F, 0xE0, 0x90, 0xCF, 0x40, 0xAF, 0x0F, 0x01, 0x60, 0xF0, 55 ]; 56 let mut dst: [u8; 36 * 4] = [0; 144]; // 4x in case of GRAY to RGBA 57 58 qcms_transform_data(&*transform, src.as_ptr() as *const libc::c_void, dst.as_mut_ptr() as *mut libc::c_void, (SRC_SIZE / src_type.bytes_per_pixel()) as usize); 59 qcms_transform_release(transform); 60 } 61 do_fuzz(data: &[u8])62 unsafe fn do_fuzz(data: &[u8]) 63 { 64 let size = data.len(); 65 qcms_enable_iccv4(); 66 67 let profile = qcms_profile_from_memory(data.as_ptr() as *const libc::c_void, size); 68 if profile == std::ptr::null_mut() { 69 return; 70 } 71 72 let srgb_profile = qcms_profile_sRGB(); 73 if srgb_profile == std::ptr::null_mut() { 74 qcms_profile_release(profile); 75 return; 76 } 77 78 transform(profile, srgb_profile, size); 79 80 // Firefox only checks the display (destination) profile. 81 if !qcms_profile_is_bogus(&mut *profile) { 82 83 transform(srgb_profile, profile, size); 84 let identity = qcms::Profile::new_XYZD50(); 85 transform(&*identity, profile, size); 86 } 87 qcms_profile_release(profile); 88 qcms_profile_release(srgb_profile); 89 90 return; 91 } 92 93 94 95 fuzz_target!(|data: &[u8]| { 96 unsafe { do_fuzz(data) } 97 }); 98