Skip to content

Commit 2e0b13f

Browse files
Jan Kratochvilantonvoznia
authored andcommitted
8347377: Add validation checks for ICC_Profile header fields
Co-authored-by: Anton Voznia <[email protected]> Backport-of: ed8945a68a67dd51a7cfa332905941afccc12b36
1 parent fa91cf4 commit 2e0b13f

File tree

4 files changed

+328
-3
lines changed

4 files changed

+328
-3
lines changed

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2021, 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
@@ -140,10 +140,11 @@ public ICC_ColorSpace(ICC_Profile profile) {
140140
if (profileClass != ICC_Profile.CLASS_INPUT
141141
&& profileClass != ICC_Profile.CLASS_DISPLAY
142142
&& profileClass != ICC_Profile.CLASS_OUTPUT
143+
&& profileClass != ICC_Profile.CLASS_DEVICELINK
143144
&& profileClass != ICC_Profile.CLASS_COLORSPACECONVERSION
144145
&& profileClass != ICC_Profile.CLASS_NAMEDCOLOR
145146
&& profileClass != ICC_Profile.CLASS_ABSTRACT) {
146-
throw new IllegalArgumentException("Invalid profile type");
147+
throw new IllegalArgumentException("Invalid profile class");
147148
}
148149

149150
thisProfile = profile;

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

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2021, 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
@@ -751,6 +751,7 @@ private interface BuiltInProfile {
751751
*/
752752
public static final int icXYZNumberX = 8;
753753

754+
private static final int HEADER_SIZE = 128;
754755

755756
/**
756757
* Constructs an {@code ICC_Profile} object with a given ID.
@@ -799,10 +800,15 @@ public static ICC_Profile getInstance(byte[] data) {
799800
ProfileDataVerifier.verify(data);
800801
Profile p;
801802
try {
803+
byte[] theHeader = new byte[HEADER_SIZE];
804+
System.arraycopy(data, 0, theHeader, 0, HEADER_SIZE);
805+
verifyHeader(theHeader);
806+
802807
p = CMSManager.getModule().loadProfile(data);
803808
} catch (CMMException c) {
804809
throw new IllegalArgumentException("Invalid ICC Profile Data");
805810
}
811+
806812
try {
807813
if (getColorSpaceType(p) == ColorSpace.TYPE_GRAY
808814
&& getData(p, icSigMediaWhitePointTag) != null
@@ -991,6 +997,10 @@ public int getProfileClass() {
991997
return info.profileClass;
992998
}
993999
byte[] theHeader = getData(icSigHead);
1000+
return getProfileClass(theHeader);
1001+
}
1002+
1003+
private static int getProfileClass(byte[] theHeader) {
9941004
int theClassSig = intFromBigEndian(theHeader, icHdrDeviceClass);
9951005
return switch (theClassSig) {
9961006
case icSigInputClass -> CLASS_INPUT;
@@ -1032,6 +1042,11 @@ private static int getColorSpaceType(Profile p) {
10321042
return iccCStoJCS(theColorSpaceSig);
10331043
}
10341044

1045+
private static int getColorSpaceType(byte[] theHeader) {
1046+
int theColorSpaceSig = intFromBigEndian(theHeader, icHdrColorSpace);
1047+
return iccCStoJCS(theColorSpaceSig);
1048+
}
1049+
10351050
/**
10361051
* Returns the color space type of the Profile Connection Space (PCS).
10371052
* Returns one of the color space type constants defined by the ColorSpace
@@ -1051,6 +1066,21 @@ public int getPCSType() {
10511066
return iccCStoJCS(thePCSSig);
10521067
}
10531068

1069+
private static int getPCSType(byte[] theHeader) {
1070+
int thePCSSig = intFromBigEndian(theHeader, icHdrPcs);
1071+
int theDeviceClass = intFromBigEndian(theHeader, icHdrDeviceClass);
1072+
1073+
if (theDeviceClass == icSigLinkClass) {
1074+
return iccCStoJCS(thePCSSig);
1075+
} else {
1076+
return switch (thePCSSig) {
1077+
case icSigXYZData -> ColorSpace.TYPE_XYZ;
1078+
case icSigLabData -> ColorSpace.TYPE_Lab;
1079+
default -> throw new IllegalArgumentException("Unexpected PCS type");
1080+
};
1081+
}
1082+
}
1083+
10541084
/**
10551085
* Write this {@code ICC_Profile} to a file.
10561086
*
@@ -1129,9 +1159,42 @@ private static byte[] getData(Profile p, int tagSignature) {
11291159
* @see #getData
11301160
*/
11311161
public void setData(int tagSignature, byte[] tagData) {
1162+
if (tagSignature == ICC_Profile.icSigHead) {
1163+
verifyHeader(tagData);
1164+
}
11321165
CMSManager.getModule().setTagData(cmmProfile(), tagSignature, tagData);
11331166
}
11341167

1168+
private static void verifyHeader(byte[] data) {
1169+
if (data == null || data.length < HEADER_SIZE) {
1170+
throw new IllegalArgumentException("Invalid header data");
1171+
}
1172+
getProfileClass(data);
1173+
getColorSpaceType(data);
1174+
getPCSType(data);
1175+
checkRenderingIntent(data);
1176+
}
1177+
1178+
private static boolean checkRenderingIntent(byte[] header) {
1179+
int index = ICC_Profile.icHdrRenderingIntent;
1180+
1181+
/* According to ICC spec, only the least-significant 16 bits shall be
1182+
* used to encode the rendering intent. The most significant 16 bits
1183+
* shall be set to zero. Thus, we are ignoring two most significant
1184+
* bytes here. Please refer ICC Spec Document for more details.
1185+
*/
1186+
int renderingIntent = ((header[index+2] & 0xff) << 8) |
1187+
(header[index+3] & 0xff);
1188+
1189+
switch (renderingIntent) {
1190+
case icPerceptual, icMediaRelativeColorimetric,
1191+
icSaturation, icAbsoluteColorimetric -> {
1192+
return true;
1193+
}
1194+
default -> throw new IllegalArgumentException("Unknown Rendering Intent");
1195+
}
1196+
}
1197+
11351198
/**
11361199
* Returns the number of color components in the "input" color space of this
11371200
* profile. For example if the color space type of this profile is

0 commit comments

Comments
 (0)