Skip to content

Commit 853ca11

Browse files
Harshitha Onkarjankratochvil
authored andcommitted
8347377: Add validation checks for ICC_Profile header fields
Reviewed-by: prr, jdv
1 parent 0fe4334 commit 853ca11

File tree

4 files changed

+345
-11
lines changed

4 files changed

+345
-11
lines changed

jdk/src/share/classes/java/awt/color/ICC_ColorSpace.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -114,13 +114,14 @@ public ICC_ColorSpace (ICC_Profile profile) {
114114
int profileClass = profile.getProfileClass();
115115

116116
/* REMIND - is NAMEDCOLOR OK? */
117-
if ((profileClass != ICC_Profile.CLASS_INPUT) &&
118-
(profileClass != ICC_Profile.CLASS_DISPLAY) &&
119-
(profileClass != ICC_Profile.CLASS_OUTPUT) &&
120-
(profileClass != ICC_Profile.CLASS_COLORSPACECONVERSION) &&
121-
(profileClass != ICC_Profile.CLASS_NAMEDCOLOR) &&
122-
(profileClass != ICC_Profile.CLASS_ABSTRACT)) {
123-
throw new IllegalArgumentException("Invalid profile type");
117+
if (profileClass != ICC_Profile.CLASS_INPUT
118+
&& profileClass != ICC_Profile.CLASS_DISPLAY
119+
&& profileClass != ICC_Profile.CLASS_OUTPUT
120+
&& profileClass != ICC_Profile.CLASS_DEVICELINK
121+
&& profileClass != ICC_Profile.CLASS_COLORSPACECONVERSION
122+
&& profileClass != ICC_Profile.CLASS_NAMEDCOLOR
123+
&& profileClass != ICC_Profile.CLASS_ABSTRACT) {
124+
throw new IllegalArgumentException("Invalid profile class");
124125
}
125126

126127
thisProfile = profile;

jdk/src/share/classes/java/awt/color/ICC_Profile.java

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,7 @@ public class ICC_Profile implements Serializable {
723723
*/
724724
public static final int icXYZNumberX = 8; /* XYZNumber X */
725725

726+
private static final int HEADER_SIZE = 128;
726727

727728
/**
728729
* Constructs an ICC_Profile object with a given ID.
@@ -767,6 +768,10 @@ public static ICC_Profile getInstance(byte[] data) {
767768
ProfileDataVerifier.verify(data);
768769

769770
try {
771+
byte[] theHeader = new byte[HEADER_SIZE];
772+
System.arraycopy(data, 0, theHeader, 0, HEADER_SIZE);
773+
verifyHeader(theHeader);
774+
770775
p = CMSManager.getModule().loadProfile(data);
771776
} catch (CMMException c) {
772777
throw new IllegalArgumentException("Invalid ICC Profile Data");
@@ -1084,16 +1089,18 @@ public int getMinorVersion() {
10841089
* @return One of the predefined profile class constants.
10851090
*/
10861091
public int getProfileClass() {
1087-
byte[] theHeader;
1088-
int theClassSig, theClass;
10891092

10901093
ProfileDeferralInfo info = deferralInfo;
10911094
if (info != null) {
10921095
return info.profileClass;
10931096
}
10941097

1095-
theHeader = getData(icSigHead);
1098+
byte[] theHeader = getData(icSigHead);
1099+
return getProfileClass(theHeader);
1100+
}
10961101

1102+
private static int getProfileClass(byte[] theHeader) {
1103+
int theClassSig, theClass;
10971104
theClassSig = intFromBigEndian (theHeader, icHdrDeviceClass);
10981105

10991106
switch (theClassSig) {
@@ -1163,6 +1170,11 @@ static int getColorSpaceType(Profile p) {
11631170
return theColorSpace;
11641171
}
11651172

1173+
private static int getColorSpaceType(byte[] theHeader) {
1174+
int theColorSpaceSig = intFromBigEndian(theHeader, icHdrColorSpace);
1175+
return iccCStoJCS(theColorSpaceSig);
1176+
}
1177+
11661178
/**
11671179
* Returns the color space type of the Profile Connection Space (PCS).
11681180
* Returns one of the color space type constants defined by the
@@ -1192,6 +1204,29 @@ static int getPCSType(Profile p) {
11921204
}
11931205

11941206

1207+
private static int getPCSType(byte[] theHeader) {
1208+
int thePCSSig = intFromBigEndian(theHeader, icHdrPcs);
1209+
int theDeviceClass = intFromBigEndian(theHeader, icHdrDeviceClass);
1210+
int thePCSType;
1211+
1212+
if (theDeviceClass == icSigLinkClass) {
1213+
return iccCStoJCS(thePCSSig);
1214+
} else {
1215+
switch (thePCSSig) {
1216+
case icSigXYZData:
1217+
thePCSType = ColorSpace.TYPE_XYZ;
1218+
break;
1219+
case icSigLabData:
1220+
thePCSType = ColorSpace.TYPE_Lab;
1221+
break;
1222+
default:
1223+
throw new IllegalArgumentException("Unexpected PCS type");
1224+
};
1225+
}
1226+
1227+
return thePCSType;
1228+
}
1229+
11951230
/**
11961231
* Write this ICC_Profile to a file.
11971232
*
@@ -1316,12 +1351,49 @@ static byte[] getData(Profile p, int tagSignature) {
13161351
* @see #getData
13171352
*/
13181353
public void setData(int tagSignature, byte[] tagData) {
1354+
if (tagSignature == ICC_Profile.icSigHead) {
1355+
verifyHeader(tagData);
1356+
}
13191357

13201358
activate();
13211359

13221360
CMSManager.getModule().setTagData(cmmProfile, tagSignature, tagData);
13231361
}
13241362

1363+
private static void verifyHeader(byte[] data) {
1364+
if (data == null || data.length < HEADER_SIZE) {
1365+
throw new IllegalArgumentException("Invalid header data");
1366+
}
1367+
getProfileClass(data);
1368+
getColorSpaceType(data);
1369+
getPCSType(data);
1370+
checkRenderingIntent(data);
1371+
}
1372+
1373+
private static boolean checkRenderingIntent(byte[] header) {
1374+
int index = ICC_Profile.icHdrRenderingIntent;
1375+
1376+
/* According to ICC spec, only the least-significant 16 bits shall be
1377+
* used to encode the rendering intent. The most significant 16 bits
1378+
* shall be set to zero. Thus, we are ignoring two most significant
1379+
* bytes here. Please refer ICC Spec Document for more details.
1380+
*/
1381+
int renderingIntent = ((header[index+2] & 0xff) << 8) |
1382+
(header[index+3] & 0xff);
1383+
1384+
switch (renderingIntent) {
1385+
case icPerceptual:
1386+
case icMediaRelativeColorimetric:
1387+
case icSaturation:
1388+
case icAbsoluteColorimetric:
1389+
break;
1390+
default:
1391+
throw new IllegalArgumentException("Unknown Rendering Intent");
1392+
}
1393+
1394+
return true;
1395+
}
1396+
13251397
/**
13261398
* Sets the rendering intent of the profile.
13271399
* This is used to select the proper transform from a profile that

0 commit comments

Comments
 (0)