1/* 2 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package sun.java2d.cmm; 27 28public class ProfileDataVerifier { 29 /** 30 * Throws an IllegalArgumentException if the data does not correspond 31 * to a valid ICC Profile. 32 * 33 * @param data the specified profile data. 34 */ 35 public static void verify(byte[] data) { 36 if (data == null) { 37 throw new IllegalArgumentException("Invalid ICC Profile Data"); 38 } 39 40 if (data.length < TOC_OFFSET) { 41 // not enough data for profile header 42 throw new IllegalArgumentException("Invalid ICC Profile Data"); 43 } 44 45 // check profile size 46 final int size = readInt32(data, 0); 47 final int tagCount = readInt32(data, HEADER_SIZE); 48 49 if (tagCount < 0 || tagCount > MAX_TAG_COUNT) { 50 throw new IllegalArgumentException("Invalid ICC Profile Data"); 51 } 52 53 if (size < (TOC_OFFSET + (tagCount * TOC_RECORD_SIZE)) || 54 size > data.length) 55 { 56 throw new IllegalArgumentException("Invalid ICC Profile Data"); 57 } 58 59 final int sig = readInt32(data, 36); 60 61 if (PROFILE_FILE_SIGNATURE != sig) { 62 throw new IllegalArgumentException("Invalid ICC Profile Data"); 63 } 64 65 // verify table of content 66 for (int i = 0; i < tagCount; i++) { 67 final int tag_offset = getTagOffset(i, data); 68 final int tag_size = getTagSize(i, data); 69 70 if (tag_offset < TOC_OFFSET || tag_offset > size) { 71 throw new IllegalArgumentException("Invalid ICC Profile Data"); 72 } 73 74 if (tag_size < 0 || 75 tag_size > (Integer.MAX_VALUE - tag_offset) || 76 tag_size + tag_offset > size) 77 { 78 throw new IllegalArgumentException("Invalid ICC Profile Data"); 79 } 80 } 81 } 82 83 private static int getTagOffset(int idx, byte[] data) { 84 final int pos = TOC_OFFSET + idx * TOC_RECORD_SIZE + 4; 85 return readInt32(data, pos); 86 } 87 88 private static int getTagSize(int idx, byte[] data) { 89 final int pos = TOC_OFFSET + idx * TOC_RECORD_SIZE + 8; 90 return readInt32(data, pos); 91 } 92 93 private static int readInt32(byte[] data, int off) { 94 int res = 0; 95 for (int i = 0; i < 4; i++) { 96 res = res << 8; 97 98 res |= (0xff & data[off++]); 99 } 100 return res; 101 } 102 103 /** 104 * Lcms limit for the number of tags: 100 105 * Kcms limit for the number of tags: N/A 106 */ 107 private static final int MAX_TAG_COUNT = 100; 108 109 private static final int HEADER_SIZE = 128; 110 private static final int TOC_OFFSET = HEADER_SIZE + 4; 111 private static final int TOC_RECORD_SIZE = 12; 112 113 private static final int PROFILE_FILE_SIGNATURE = 0x61637370; 114} 115