Skip to content

Commit d6ef464

Browse files
committed
Add color spots number check
DEVSIX-4049
1 parent cf313e7 commit d6ef464

File tree

7 files changed

+141
-2
lines changed

7 files changed

+141
-2
lines changed

kernel/src/main/java/com/itextpdf/kernel/pdf/colorspace/PdfColorSpace.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ else if (PdfName.Indexed.equals(csType))
9797
else if (PdfName.Separation.equals(csType))
9898
return new PdfSpecialCs.Separation(array);
9999
else if (PdfName.DeviceN.equals(csType))
100+
//TODO DEVSIX-4205 Fix colorspace creation
100101
return array.size() == 4 ? new PdfSpecialCs.DeviceN(array) : new PdfSpecialCs.NChannel(array);
101102
else if (PdfName.Pattern.equals(csType))
102103
return new PdfSpecialCs.UncoloredTilingPattern(array);

pdfa/src/main/java/com/itextpdf/pdfa/PdfAConformanceException.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ public class PdfAConformanceException extends PdfException {
139139
public static final String THE_F_KEYS_PRINT_FLAG_BIT_SHALL_BE_SET_TO_1_AND_ITS_HIDDEN_INVISIBLE_AND_NOVIEW_FLAG_BITS_SHALL_BE_SET_TO_0 = "The f keys print flag bit shall be set to 1 and its hidden invisible and noview flag bits shall be set to 0";
140140
public static final String THE_F_KEYS_PRINT_FLAG_BIT_SHALL_BE_SET_TO_1_AND_ITS_HIDDEN_INVISIBLE_NOVIEW_AND_TOGGLENOVIEW_FLAG_BITS_SHALL_BE_SET_TO_0 = "The f keys print flag bit shall be set to 1 and its hidden invisible noview and togglenoview flag bits shall be set to 0";
141141
public static final String THE_INTERACTIVE_FORM_DICTIONARY_SHALL_NOT_CONTAIN_THE_XFA_KEY = "The interactive form dictionary shall not contain the xfa key";
142+
public static final String THE_NUMBER_OF_COLOR_COMPONENTS_IN_DEVICE_N_COLORSPACE_SHOULD_NOT_EXCEED = "The number of color components in DeviceN colorspace should not exceed {0}";
142143
public static final String THE_NUMBER_OF_COLOUR_CHANNELS_IN_THE_JPEG2000_DATA_SHALL_BE_1_3_OR_4 = "The number of colour channels in the jpeg2000 data shall be 1, 3 or 4";
143144
public static final String THE_PAGE_DICTIONARY_SHALL_NOT_CONTAIN_AA_ENTRY = "The page dictionary shall not contain aa entry";
144145
public static final String THE_PAGE_DICTIONARY_SHALL_NOT_CONTAIN_PRESSTEPS_ENTRY = "The page dictionary shall not contain pressteps entry";

pdfa/src/main/java/com/itextpdf/pdfa/checker/PdfA1Checker.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ public class PdfA1Checker extends PdfAChecker {
9999
PdfName.PrevPage, PdfName.FirstPage, PdfName.LastPage));
100100
protected static final Set<PdfName> allowedRenderingIntents = new HashSet<>(Arrays.asList(PdfName.RelativeColorimetric,
101101
PdfName.AbsoluteColorimetric, PdfName.Perceptual, PdfName.Saturation));
102+
private static final int MAX_NUMBER_OF_DEVICEN_COLOR_COMPONENTS = 8;
102103
private static final long serialVersionUID = 5103027349795298132L;
103104

104105
/**
@@ -161,7 +162,13 @@ public void checkColorSpace(PdfColorSpace colorSpace, PdfDictionary currentColor
161162
if (colorSpace instanceof PdfSpecialCs.Separation) {
162163
colorSpace = ((PdfSpecialCs.Separation) colorSpace).getBaseCs();
163164
} else if (colorSpace instanceof PdfSpecialCs.DeviceN) {
164-
colorSpace = ((PdfSpecialCs.DeviceN) colorSpace).getBaseCs();
165+
PdfSpecialCs.DeviceN deviceNColorspace = (PdfSpecialCs.DeviceN) colorSpace;
166+
if (deviceNColorspace.getNumberOfComponents() > MAX_NUMBER_OF_DEVICEN_COLOR_COMPONENTS) {
167+
throw new PdfAConformanceException(PdfAConformanceException.
168+
THE_NUMBER_OF_COLOR_COMPONENTS_IN_DEVICE_N_COLORSPACE_SHOULD_NOT_EXCEED,
169+
MAX_NUMBER_OF_DEVICEN_COLOR_COMPONENTS);
170+
}
171+
colorSpace = deviceNColorspace.getBaseCs();
165172
}
166173

167174
if (colorSpace instanceof PdfDeviceCs.Rgb) {

pdfa/src/main/java/com/itextpdf/pdfa/checker/PdfA2Checker.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ public class PdfA2Checker extends PdfA1Checker {
103103

104104
static final int MAX_PAGE_SIZE = 14400;
105105
static final int MIN_PAGE_SIZE = 3;
106+
private static final int MAX_NUMBER_OF_DEVICEN_COLOR_COMPONENTS = 32;
106107
private static final long serialVersionUID = -5937712517954260687L;
107108

108109
private boolean currentFillCsIsIccBasedCMYK = false;
@@ -196,14 +197,24 @@ public void checkColorSpace(PdfColorSpace colorSpace, PdfDictionary currentColor
196197
} else if (colorSpace instanceof PdfSpecialCs.DeviceN) {
197198

198199
PdfSpecialCs.DeviceN deviceN = (PdfSpecialCs.DeviceN) colorSpace;
200+
if (deviceN.getNumberOfComponents() > MAX_NUMBER_OF_DEVICEN_COLOR_COMPONENTS) {
201+
throw new PdfAConformanceException(PdfAConformanceException.
202+
THE_NUMBER_OF_COLOR_COMPONENTS_IN_DEVICE_N_COLORSPACE_SHOULD_NOT_EXCEED,
203+
MAX_NUMBER_OF_DEVICEN_COLOR_COMPONENTS);
204+
}
205+
//TODO DEVSIX-4203 Fix IndexOutOfBounds exception being thrown for DeviceN (not NChannel) colorspace without
206+
// attributes. According to the spec PdfAConformanceException should be thrown.
199207
PdfDictionary attributes = ((PdfArray) deviceN.getPdfObject()).getAsDictionary(4);
200208
PdfDictionary colorants = attributes.getAsDictionary(PdfName.Colorants);
209+
//TODO DEVSIX-4203 Colorants dictionary is mandatory in PDF/A-2 spec. Need to throw an appropriate exception
210+
// if it is not present.
201211
if (colorants != null) {
202212
for (Map.Entry<PdfName, PdfObject> entry : colorants.entrySet()) {
203213
PdfArray separation = (PdfArray) entry.getValue();
204214
checkSeparationInsideDeviceN(separation, ((PdfArray) deviceN.getPdfObject()).get(2), ((PdfArray) deviceN.getPdfObject()).get(3));
205215
}
206216
}
217+
207218
if (checkAlternate) {
208219
checkColorSpace(deviceN.getBaseCs(), currentColorSpaces, false, fill);
209220
}
@@ -987,5 +998,4 @@ public void checkFontGlyphs(PdfFont font, PdfStream contentStream) {
987998
}
988999
}
9891000
}
990-
9911001
}

pdfa/src/test/java/com/itextpdf/pdfa/checker/PdfA1ImplementationLimitsCheckerTest.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,21 @@ This file is part of the iText (R) project.
5454
import com.itextpdf.kernel.pdf.PdfObject;
5555
import com.itextpdf.kernel.pdf.PdfStream;
5656
import com.itextpdf.kernel.pdf.PdfString;
57+
import com.itextpdf.kernel.pdf.colorspace.PdfColorSpace;
58+
import com.itextpdf.kernel.pdf.colorspace.PdfDeviceCs;
5759
import com.itextpdf.kernel.pdf.colorspace.PdfPattern;
5860
import com.itextpdf.kernel.pdf.colorspace.PdfPattern.Shading;
5961
import com.itextpdf.kernel.pdf.colorspace.PdfPattern.Tiling;
62+
import com.itextpdf.kernel.pdf.colorspace.PdfSpecialCs;
6063
import com.itextpdf.kernel.pdf.xobject.PdfFormXObject;
6164
import com.itextpdf.kernel.pdf.xobject.PdfXObject;
6265
import com.itextpdf.pdfa.PdfAConformanceException;
6366
import com.itextpdf.test.ExtendedITextTest;
6467
import com.itextpdf.test.annotations.type.UnitTest;
6568

6669
import java.nio.charset.StandardCharsets;
70+
import java.util.ArrayList;
71+
import java.util.List;
6772
import org.junit.Assert;
6873
import org.junit.Before;
6974
import org.junit.Rule;
@@ -442,6 +447,24 @@ public void longStringInType3FontTest() {
442447
checkInType3Font(longString);
443448
}
444449

450+
@Test
451+
public void deviceNColorspaceWithMoreThan8Components() {
452+
junitExpectedException.expect(PdfAConformanceException.class);
453+
junitExpectedException.expectMessage(PdfAConformanceException.THE_NUMBER_OF_COLOR_COMPONENTS_IN_DEVICE_N_COLORSPACE_SHOULD_NOT_EXCEED);
454+
455+
checkColorspace(buildDeviceNColorspace(10));
456+
}
457+
458+
@Test
459+
public void deviceNColorspaceWith8Components() {
460+
checkColorspace(buildDeviceNColorspace(8));
461+
}
462+
463+
@Test
464+
public void deviceNColorspaceWithLessThan8Components() {
465+
checkColorspace(buildDeviceNColorspace(2));
466+
}
467+
445468
private PdfString buildLongString() {
446469

447470
final int maxAllowedLength = pdfA1Checker.getMaxStringLength();
@@ -580,4 +603,24 @@ private void checkInType3Font(PdfObject object) {
580603
dictionary.put(PdfName.CharProcs, charProcs);
581604
pdfA1Checker.checkFont(font);
582605
}
606+
607+
private void checkColorspace(PdfColorSpace colorSpace) {
608+
PdfDictionary currentColorSpaces = new PdfDictionary();
609+
pdfA1Checker.checkColorSpace(colorSpace, currentColorSpaces, false, false);
610+
}
611+
612+
private PdfColorSpace buildDeviceNColorspace(int numberOfComponents) {
613+
List<String> tmpArray = new ArrayList<String>(numberOfComponents);
614+
float[] transformArray = new float[numberOfComponents * 2];
615+
616+
for (int i = 0; i < numberOfComponents; i++) {
617+
tmpArray.add("MyColor" + i + 1);
618+
transformArray[i * 2] = 0;
619+
transformArray[i * 2 + 1] = 1;
620+
}
621+
com.itextpdf.kernel.pdf.function.PdfFunction.Type4 function = new com.itextpdf.kernel.pdf.function.PdfFunction.Type4
622+
(new PdfArray(transformArray), new PdfArray(new float[]{0, 1, 0, 1, 0, 1}), "{0}".getBytes(StandardCharsets.ISO_8859_1));
623+
624+
return new PdfSpecialCs.DeviceN(tmpArray, new PdfDeviceCs.Rgb(), function);
625+
}
583626
}

pdfa/src/test/java/com/itextpdf/pdfa/checker/PdfA2CheckerTest.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,15 @@ This file is part of the iText (R) project.
4848
import com.itextpdf.kernel.pdf.PdfName;
4949
import com.itextpdf.kernel.pdf.PdfStream;
5050
import com.itextpdf.kernel.pdf.PdfString;
51+
import com.itextpdf.kernel.pdf.colorspace.PdfDeviceCs;
52+
import com.itextpdf.kernel.pdf.colorspace.PdfSpecialCs;
5153
import com.itextpdf.pdfa.PdfAConformanceException;
5254
import com.itextpdf.test.ExtendedITextTest;
5355
import com.itextpdf.test.annotations.type.UnitTest;
5456

5557
import java.nio.charset.StandardCharsets;
58+
import java.util.ArrayList;
59+
import java.util.List;
5660
import org.junit.Assert;
5761
import org.junit.Rule;
5862
import org.junit.Test;
@@ -335,4 +339,29 @@ public void checkCatalogDictionaryWithoutRequirements() {
335339

336340
pdfA2Checker.checkCatalogValidEntries(catalog);
337341
}
342+
343+
@Test
344+
public void deviceNColorspaceNoAttributesDictionary() {
345+
//TODO DEVSIX-4203 should not cause an IndexOutOfBoundException.
346+
// Should throw PdfAConformanceException as Colorants dictionary always must be present
347+
// for Pdf/A-2
348+
junitExpectedException.expect(RuntimeException.class);
349+
350+
int numberOfComponents = 2;
351+
List<String> tmpArray = new ArrayList<String>(numberOfComponents);
352+
float[] transformArray = new float[numberOfComponents * 2];
353+
354+
for (int i = 0; i < numberOfComponents; i++) {
355+
tmpArray.add("MyColor" + i + 1);
356+
transformArray[i * 2] = 0;
357+
transformArray[i * 2 + 1] = 1;
358+
}
359+
com.itextpdf.kernel.pdf.function.PdfFunction.Type4 function = new com.itextpdf.kernel.pdf.function.PdfFunction.Type4
360+
(new PdfArray(transformArray), new PdfArray(new float[]{0, 1, 0, 1, 0, 1}), "{0}".getBytes(StandardCharsets.ISO_8859_1));
361+
362+
PdfDictionary currentColorSpaces = new PdfDictionary();
363+
pdfA2Checker.checkColorSpace(new PdfSpecialCs.DeviceN(tmpArray, new PdfDeviceCs.Rgb(), function),
364+
currentColorSpaces, true, false);
365+
366+
}
338367
}

pdfa/src/test/java/com/itextpdf/pdfa/checker/PdfA2ImplementationLimitsCheckerTest.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,16 @@ This file is part of the iText (R) project.
4848
import com.itextpdf.kernel.pdf.PdfNumber;
4949
import com.itextpdf.kernel.pdf.PdfStream;
5050
import com.itextpdf.kernel.pdf.PdfString;
51+
import com.itextpdf.kernel.pdf.colorspace.PdfColorSpace;
52+
import com.itextpdf.kernel.pdf.colorspace.PdfDeviceCs;
53+
import com.itextpdf.kernel.pdf.colorspace.PdfSpecialCs;
5154
import com.itextpdf.pdfa.PdfAConformanceException;
5255
import com.itextpdf.test.ExtendedITextTest;
5356
import com.itextpdf.test.annotations.type.UnitTest;
5457

5558
import java.nio.charset.StandardCharsets;
59+
import java.util.ArrayList;
60+
import java.util.List;
5661
import org.junit.Assert;
5762
import org.junit.Before;
5863
import org.junit.Rule;
@@ -148,4 +153,47 @@ public void independentLargeRealTest() {
148153
// An exception is thrown as any number greater then 32767 is considered as Integer
149154
pdfA2Checker.checkPdfObject(largeNumber);
150155
}
156+
157+
@Test
158+
public void deviceNColorspaceWithMoreThan32Components() {
159+
junitExpectedException.expect(PdfAConformanceException.class);
160+
junitExpectedException.expectMessage(PdfAConformanceException.THE_NUMBER_OF_COLOR_COMPONENTS_IN_DEVICE_N_COLORSPACE_SHOULD_NOT_EXCEED);
161+
162+
checkColorspace(buildDeviceNColorspace(34));
163+
164+
}
165+
166+
@Test
167+
public void deviceNColorspaceWithLessThan32Components() {
168+
checkColorspace(buildDeviceNColorspace(16));
169+
}
170+
171+
@Test
172+
public void deviceNColorspaceWith32Components() {
173+
checkColorspace(buildDeviceNColorspace(32));
174+
}
175+
176+
private void checkColorspace(PdfColorSpace colorSpace) {
177+
PdfDictionary currentColorSpaces = new PdfDictionary();
178+
pdfA2Checker.checkColorSpace(colorSpace, currentColorSpaces, true, false);
179+
}
180+
181+
private PdfColorSpace buildDeviceNColorspace(int numberOfComponents) {
182+
List<String> tmpArray = new ArrayList<String>(numberOfComponents);
183+
float[] transformArray = new float[numberOfComponents * 2];
184+
185+
for (int i = 0; i < numberOfComponents; i++) {
186+
tmpArray.add("MyColor" + i + 1);
187+
transformArray[i * 2] = 0;
188+
transformArray[i * 2 + 1] = 1;
189+
}
190+
com.itextpdf.kernel.pdf.function.PdfFunction.Type4 function = new com.itextpdf.kernel.pdf.function.PdfFunction.Type4
191+
(new PdfArray(transformArray), new PdfArray(new float[]{0, 1, 0, 1, 0, 1}), "{0}".getBytes(StandardCharsets.ISO_8859_1));
192+
193+
//TODO DEVSIX-4205 Replace with a constructor with 4 parameters or use a setter for attributes dictionary
194+
PdfArray deviceNAsArray = ((PdfArray)(new PdfSpecialCs.DeviceN(tmpArray, new PdfDeviceCs.Rgb(), function)).getPdfObject());
195+
PdfDictionary attributes = new PdfDictionary();
196+
deviceNAsArray.add(attributes);
197+
return new PdfSpecialCs.DeviceN(deviceNAsArray);
198+
}
151199
}

0 commit comments

Comments
 (0)