From 427e256ac2566a77cc0d0d328587f70b50c97ad9 Mon Sep 17 00:00:00 2001 From: Dmitry Radchuk Date: Mon, 14 Oct 2024 08:09:45 +0000 Subject: [PATCH 1/2] Remove md5 message digest initialization in security handlers which don't need it DEVSIX-8631 Autoported commit. Original commit hash: [7cd66857c] Manual files: kernel/src/test/java/com/itextpdf/kernel/crypto/PdfEncryptingTest.java --- .../itext/forms/PdfEncryptionTest.cs | 2 -- .../kernel/crypto/EncryptionInApprovedModeTest.cs | 7 +------ .../crypto/pdfencryption/PdfEncryptionTest.cs | 10 ---------- .../securityhandler/PubSecHandlerUsingAesGcmTest.cs | 5 ----- .../StandardHandlerUsingAesGcmTest.cs | 12 ------------ .../kernel/mac/MacIntegrityProtectorCreationTest.cs | 13 +++---------- .../itext/kernel/pdf/PdfStreamTest.cs | 4 ---- .../securityhandler/PubSecHandlerUsingAes256.cs | 5 +++++ .../securityhandler/PubSecHandlerUsingAesGcm.cs | 5 +++++ .../crypto/securityhandler/SecurityHandler.cs | 5 +++-- .../securityhandler/StandardHandlerUsingAes256.cs | 5 +++++ .../securityhandler/StandardHandlerUsingAesGcm.cs | 5 +++++ .../securityhandler/StandardSecurityHandler.cs | 12 +++++++++++- port-hash | 2 +- 14 files changed, 39 insertions(+), 53 deletions(-) diff --git a/itext.tests/itext.forms.tests/itext/forms/PdfEncryptionTest.cs b/itext.tests/itext.forms.tests/itext/forms/PdfEncryptionTest.cs index 4ad61678f7..cf31548705 100644 --- a/itext.tests/itext.forms.tests/itext/forms/PdfEncryptionTest.cs +++ b/itext.tests/itext.forms.tests/itext/forms/PdfEncryptionTest.cs @@ -70,7 +70,6 @@ public virtual void EncryptedDocumentWithFormFields() { } [NUnit.Framework.Test] - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] public virtual void EncryptAes256Pdf2PermissionsTest01() { String filename = "encryptAes256Pdf2PermissionsTest01.pdf"; int permissions = EncryptionConstants.ALLOW_FILL_IN | EncryptionConstants.ALLOW_SCREENREADERS | EncryptionConstants @@ -107,7 +106,6 @@ public virtual void EncryptAes256Pdf2PermissionsTest01() { } [NUnit.Framework.Test] - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] public virtual void EncryptAes256Pdf2PermissionsTest02() { String filename = "encryptAes256Pdf2PermissionsTest02.pdf"; // This test differs from the previous one (encryptAes256Pdf2PermissionsTest01) only in permissions. diff --git a/itext.tests/itext.kernel.tests/itext/kernel/crypto/EncryptionInApprovedModeTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/crypto/EncryptionInApprovedModeTest.cs index 4357e8f488..4abf1be84a 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/crypto/EncryptionInApprovedModeTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/crypto/EncryptionInApprovedModeTest.cs @@ -24,11 +24,9 @@ You should have received a copy of the GNU Affero General Public License using NUnit.Framework; using iText.Bouncycastleconnector; using iText.Commons.Bouncycastle; -using iText.Kernel.Logs; using iText.Kernel.Pdf; using iText.Kernel.Utils; using iText.Test; -using iText.Test.Attributes; namespace iText.Kernel.Crypto { [NUnit.Framework.Category("BouncyCastleIntegrationTest")] @@ -59,7 +57,6 @@ public static void AfterClass() { } [NUnit.Framework.Test] - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT)] public virtual void CheckMD5LogMessageWhileReadingPdfTest() { String fileName = "checkMD5LogMessageWhileReadingPdf.pdf"; using (PdfDocument document = new PdfDocument(new PdfReader(sourceFolder + fileName))) { @@ -68,7 +65,6 @@ public virtual void CheckMD5LogMessageWhileReadingPdfTest() { // this test checks log message [NUnit.Framework.Test] - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT)] public virtual void CheckMD5LogMessageWhileCreatingPdfTest() { String fileName = "checkMD5LogMessageWhileCreatingPdf.pdf"; using (PdfDocument document = new PdfDocument(CompareTool.CreateTestPdfWriter(destinationFolder + fileName @@ -79,7 +75,6 @@ public virtual void CheckMD5LogMessageWhileCreatingPdfTest() { // this test checks log message [NUnit.Framework.Test] - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Count = 3)] public virtual void CheckMD5LogMessageForEachPdfTest() { String fileName = "checkMD5LogMessageForEachPdf.pdf"; for (int i = 0; i < 3; ++i) { @@ -89,6 +84,6 @@ public virtual void CheckMD5LogMessageForEachPdfTest() { } } } - // this test checks log message + // this test checks absence of log messages } } diff --git a/itext.tests/itext.kernel.tests/itext/kernel/crypto/pdfencryption/PdfEncryptionTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/crypto/pdfencryption/PdfEncryptionTest.cs index 3a37d3f5a4..dbcc433ea3 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/crypto/pdfencryption/PdfEncryptionTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/crypto/pdfencryption/PdfEncryptionTest.cs @@ -135,7 +135,6 @@ public virtual void EncryptWithPasswordAes128() { } [NUnit.Framework.Test] - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] public virtual void EncryptWithPasswordAes256() { String filename = "encryptWithPasswordAes256.pdf"; int encryptionType = EncryptionConstants.ENCRYPTION_AES_256; @@ -151,7 +150,6 @@ public virtual void EncryptWithPasswordAes128NoCompression() { } [NUnit.Framework.Test] - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] public virtual void EncryptWithPasswordAes256NoCompression() { String filename = "encryptWithPasswordAes256NoCompression.pdf"; int encryptionType = EncryptionConstants.ENCRYPTION_AES_256; @@ -311,7 +309,6 @@ public virtual void EncryptWithPasswordAes128EmbeddedFilesOnly() { } [NUnit.Framework.Test] - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] public virtual void EncryptWithPasswordAes256EmbeddedFilesOnly() { String filename = "encryptWithPasswordAes256EmbeddedFilesOnly.pdf"; int encryptionType = EncryptionConstants.ENCRYPTION_AES_256 | EncryptionConstants.EMBEDDED_FILES_ONLY; @@ -342,7 +339,6 @@ public virtual void EncryptWithPasswordAes256EmbeddedFilesOnly() { } [NUnit.Framework.Test] - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] public virtual void EncryptAes256Pdf2NotEncryptMetadata() { String filename = "encryptAes256Pdf2NotEncryptMetadata.pdf"; int encryptionType = EncryptionConstants.ENCRYPTION_AES_256 | EncryptionConstants.DO_NOT_ENCRYPT_METADATA; @@ -350,7 +346,6 @@ public virtual void EncryptAes256Pdf2NotEncryptMetadata() { } [NUnit.Framework.Test] - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] public virtual void EncryptAes256Pdf2NotEncryptMetadata02() { String filename = "encryptAes256Pdf2NotEncryptMetadata02.pdf"; int encryptionType = EncryptionConstants.ENCRYPTION_AES_256 | EncryptionConstants.DO_NOT_ENCRYPT_METADATA; @@ -377,7 +372,6 @@ public virtual void EncryptAes256EncryptedStampingUpdate() { } [NUnit.Framework.Test] - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] public virtual void EncryptAes256FullCompression() { String filename = "encryptAes256FullCompression.pdf"; int encryptionType = EncryptionConstants.ENCRYPTION_AES_256; @@ -385,7 +379,6 @@ public virtual void EncryptAes256FullCompression() { } [NUnit.Framework.Test] - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] public virtual void EncryptWithPasswordAes256Pdf2() { String filename = "encryptWithPasswordAes256Pdf2.pdf"; int encryptionType = EncryptionConstants.ENCRYPTION_AES_256; @@ -402,7 +395,6 @@ public virtual void EncryptWithPasswordAes128Pdf2() { } [NUnit.Framework.Test] - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] public virtual void StampAndUpdateVersionNewAes256() { String filename = "stampAndUpdateVersionNewAes256.pdf"; PdfDocument doc = new PdfDocument(new PdfReader(sourceFolder + "encryptedWithPasswordAes256.pdf", new ReaderProperties @@ -414,7 +406,6 @@ public virtual void StampAndUpdateVersionNewAes256() { } [NUnit.Framework.Test] - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] public virtual void EncryptAes256Pdf2Permissions() { String filename = "encryptAes256Pdf2Permissions.pdf"; int permissions = EncryptionConstants.ALLOW_FILL_IN | EncryptionConstants.ALLOW_SCREENREADERS | EncryptionConstants @@ -461,7 +452,6 @@ public virtual void CheckMD5LogAbsenceInUnapprovedMode() { // this test checks log message absence [NUnit.Framework.Test] - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true, Count = 2)] public virtual void DecryptAdobeWithPasswordAes256() { String filename = System.IO.Path.Combine(sourceFolder + "AdobeAes256.pdf").ToString(); DecryptWithPassword(filename, "user".GetBytes()); diff --git a/itext.tests/itext.kernel.tests/itext/kernel/crypto/securityhandler/PubSecHandlerUsingAesGcmTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/crypto/securityhandler/PubSecHandlerUsingAesGcmTest.cs index d63b4c36df..2fdc521f3f 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/crypto/securityhandler/PubSecHandlerUsingAesGcmTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/crypto/securityhandler/PubSecHandlerUsingAesGcmTest.cs @@ -30,7 +30,6 @@ You should have received a copy of the GNU Affero General Public License using iText.Commons.Utils; using iText.Kernel.Crypto; using iText.Kernel.Exceptions; -using iText.Kernel.Logs; using iText.Kernel.Pdf; using iText.Kernel.Utils; using iText.Test; @@ -54,7 +53,6 @@ public static void SetUp() { CreateOrClearDestinationFolder(DESTINATION_FOLDER); } - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] [NUnit.Framework.Test] public virtual void TestSimpleEncryptDecryptTest() { try { @@ -72,7 +70,6 @@ public virtual void TestSimpleEncryptDecryptTest() { } [LogMessage(VersionConforming.NOT_SUPPORTED_AES_GCM, Ignore = true)] - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] [NUnit.Framework.Test] public virtual void TestSimpleEncryptDecryptPdf17Test() { try { @@ -89,7 +86,6 @@ public virtual void TestSimpleEncryptDecryptPdf17Test() { DecryptWithCertificate(fileName, DESTINATION_FOLDER, "test.cer", "test.pem"); } - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] [NUnit.Framework.Test] public virtual void DecryptExternalFileTest() { try { @@ -101,7 +97,6 @@ public virtual void DecryptExternalFileTest() { DecryptWithCertificate("externalFile.pdf", SOURCE_FOLDER, "decrypter.cert.pem", "signerkey.pem"); } - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] [NUnit.Framework.Test] public virtual void InvalidCryptFilterTest() { String fileName = "invalidCryptFilter.pdf"; diff --git a/itext.tests/itext.kernel.tests/itext/kernel/crypto/securityhandler/StandardHandlerUsingAesGcmTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/crypto/securityhandler/StandardHandlerUsingAesGcmTest.cs index 53c1099c7e..c9c5527a6e 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/crypto/securityhandler/StandardHandlerUsingAesGcmTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/crypto/securityhandler/StandardHandlerUsingAesGcmTest.cs @@ -25,7 +25,6 @@ You should have received a copy of the GNU Affero General Public License using iText.Bouncycastleconnector; using iText.Commons.Bouncycastle; using iText.Kernel.Exceptions; -using iText.Kernel.Logs; using iText.Kernel.Pdf; using iText.Kernel.Utils; using iText.Kernel.Utils.Objectpathitems; @@ -52,7 +51,6 @@ public static void SetUp() { } [NUnit.Framework.Test] - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] public virtual void SimpleEncryptDecryptTest() { String srcFile = SRC + "simpleDocument.pdf"; String encryptedCmpFile = SRC + "cmp_encryptedSimpleDocument.pdf"; @@ -74,7 +72,6 @@ public virtual void SimpleEncryptDecryptTest() { [NUnit.Framework.Test] [LogMessage(VersionConforming.NOT_SUPPORTED_AES_GCM)] - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] public virtual void SimpleEncryptDecryptPdf15Test() { String srcFile = SRC + "simpleDocument.pdf"; String outFile = DEST + "notSupportedVersionDocument.pdf"; @@ -87,7 +84,6 @@ public virtual void SimpleEncryptDecryptPdf15Test() { } [NUnit.Framework.Test] - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] public virtual void KnownOutputTest() { String srcFile = SRC + "encryptedDocument.pdf"; String outFile = DEST + "encryptedDocument.pdf"; @@ -100,21 +96,18 @@ public virtual void KnownOutputTest() { } // In all these tampered files, the stream content of object 14 has been modified. - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] [NUnit.Framework.Test] public virtual void MacTamperedTest() { String srcFile = SRC + "encryptedDocumentTamperedMac.pdf"; AssertTampered(srcFile); } - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] [NUnit.Framework.Test] public virtual void InitVectorTamperedTest() { String srcFile = SRC + "encryptedDocumentTamperedIv.pdf"; AssertTampered(srcFile); } - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] [NUnit.Framework.Test] public virtual void CiphertextTamperedTest() { String srcFile = SRC + "encryptedDocumentTamperedCiphertext.pdf"; @@ -122,7 +115,6 @@ public virtual void CiphertextTamperedTest() { } [NUnit.Framework.Test] - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] [LogMessage(iText.IO.Logs.IoLogMessageConstant.ENCRYPTION_ENTRIES_P_AND_ENCRYPT_METADATA_NOT_CORRESPOND_PERMS_ENTRY )] public virtual void PdfEncryptionWithEmbeddedFilesTest() { @@ -158,7 +150,6 @@ public virtual void PdfEncryptionWithEmbeddedFilesTest() { } [NUnit.Framework.Test] - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] public virtual void PdfEncryptionWithMetadataTest() { byte[] documentId = new byte[] { (byte)88, (byte)189, (byte)192, (byte)48, (byte)240, (byte)200, (byte)87, (byte)183, (byte)244, (byte)119, (byte)224, (byte)109, (byte)226, (byte)173, (byte)32, (byte)90 }; @@ -191,7 +182,6 @@ public virtual void PdfEncryptionWithMetadataTest() { } [NUnit.Framework.Test] - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] public virtual void EncryptPdfWithMissingCFTest() { byte[] documentId = new byte[] { (byte)88, (byte)189, (byte)192, (byte)48, (byte)240, (byte)200, (byte)87, (byte)183, (byte)244, (byte)119, (byte)224, (byte)109, (byte)226, (byte)173, (byte)32, (byte)90 }; @@ -206,7 +196,6 @@ public virtual void EncryptPdfWithMissingCFTest() { } [NUnit.Framework.Test] - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] public virtual void EncryptPdfWithMissingStdCFTest() { byte[] documentId = new byte[] { (byte)88, (byte)189, (byte)192, (byte)48, (byte)240, (byte)200, (byte)87, (byte)183, (byte)244, (byte)119, (byte)224, (byte)109, (byte)226, (byte)173, (byte)32, (byte)90 }; @@ -226,7 +215,6 @@ public virtual void EncryptPdfWithMissingStdCFTest() { } [NUnit.Framework.Test] - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] public virtual void EncryptPdfWithMissingCFMTest() { byte[] documentId = new byte[] { (byte)88, (byte)189, (byte)192, (byte)48, (byte)240, (byte)200, (byte)87, (byte)183, (byte)244, (byte)119, (byte)224, (byte)109, (byte)226, (byte)173, (byte)32, (byte)90 }; diff --git a/itext.tests/itext.kernel.tests/itext/kernel/mac/MacIntegrityProtectorCreationTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/mac/MacIntegrityProtectorCreationTest.cs index cc5f8e8de7..a89ddec97c 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/mac/MacIntegrityProtectorCreationTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/mac/MacIntegrityProtectorCreationTest.cs @@ -65,7 +65,6 @@ public static void AfterClass() { } [NUnit.Framework.Test] - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] public virtual void StandaloneMacStandardEncryptionTest() { String fileName = "standaloneMacStandardEncryptionTest.pdf"; String outputFileName = DESTINATION_FOLDER + fileName; @@ -82,7 +81,6 @@ public virtual void StandaloneMacStandardEncryptionTest() { } [NUnit.Framework.Test] - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] public virtual void NoMacProtectionTest() { String fileName = "noMacProtectionTest.pdf"; String outputFileName = DESTINATION_FOLDER + fileName; @@ -115,21 +113,20 @@ public virtual void MacEncryptionWithAesGcmTest() { } [NUnit.Framework.Test] - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] [LogMessage(iText.IO.Logs.IoLogMessageConstant.PDF_WRITER_CLOSING_FAILED)] public virtual void StandaloneMacUnwritableStreamTest() { WriterProperties writerProperties = new WriterProperties().SetPdfVersion(PdfVersion.PDF_2_0).SetStandardEncryption (PASSWORD, PASSWORD, 0, EncryptionConstants.ENCRYPTION_AES_256, new MacProperties(MacProperties.MacDigestAlgorithm .SHA_256)); - MemoryStream unwritableStream = new _MemoryStream_152(); + MemoryStream unwritableStream = new _MemoryStream_147(); using (PdfDocument pdfDoc = new PdfDocument(new PdfWriter(unwritableStream, writerProperties))) { pdfDoc.AddNewPage().AddAnnotation(new PdfTextAnnotation(new Rectangle(100, 100, 100, 100))); } unwritableStream.Dispose(); } - private sealed class _MemoryStream_152 : MemoryStream { - public _MemoryStream_152() { + private sealed class _MemoryStream_147 : MemoryStream { + public _MemoryStream_147() { } public override void Write(byte[] b, int off, int len) { @@ -138,7 +135,6 @@ public override void Write(byte[] b, int off, int len) { } [NUnit.Framework.Test] - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] public virtual void StandaloneMacWithAllHashAlgorithmsTest() { for (int i = 0; i < EnumUtil.GetAllValuesOfEnum().Count; i++) { String fileName = "standaloneMacWithAllHashAlgorithmsTest" + (i + 1) + ".pdf"; @@ -159,7 +155,6 @@ public virtual void StandaloneMacWithAllHashAlgorithmsTest() { } [NUnit.Framework.Test] - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] public virtual void StandaloneMacPdfVersionNotSetTest() { String fileName = "standaloneMacPdfVersionNotSetTest.pdf"; String outputFileName = DESTINATION_FOLDER + fileName; @@ -209,7 +204,6 @@ public virtual void AddMacOnAppendModeTest() { } [NUnit.Framework.Test] - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] public virtual void AddMacWithDisableMacPropertyTest() { // MAC should not be added in disable MAC mode even if it was provided with writer properties String fileName = "addMacWithDisableMacPropertyTest.pdf"; @@ -280,7 +274,6 @@ public virtual void StandaloneMacOldEncryptionAlgorithmTest() { } [NUnit.Framework.Test] - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] public virtual void StandaloneMacPublicKeyEncryptionTest() { try { BouncyCastleFactoryCreator.GetFactory().IsEncryptionFeatureSupported(0, true); diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfStreamTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfStreamTest.cs index 64856563af..475684e6ce 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfStreamTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfStreamTest.cs @@ -23,7 +23,6 @@ You should have received a copy of the GNU Affero General Public License using System; using iText.Commons.Utils; using iText.Kernel.Exceptions; -using iText.Kernel.Logs; using iText.Kernel.Pdf.Xobject; using iText.Kernel.Utils; using iText.Test; @@ -104,7 +103,6 @@ public virtual void IndirectRefInFilterAndNoTaggedPdfTest() { } [NUnit.Framework.Test] - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] public virtual void CryptFilterFlushedBeforeReadStreamTest() { String file = sourceFolder + "cryptFilterTest.pdf"; String destFile = destinationFolder + "cryptFilterReadStreamTest.pdf"; @@ -125,7 +123,6 @@ public virtual void CryptFilterFlushedBeforeReadStreamTest() { } [NUnit.Framework.Test] - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] public virtual void CryptFilterFlushedBeforeStreamTest() { String file = sourceFolder + "cryptFilterTest.pdf"; String destFile = destinationFolder + "cryptFilterStreamNotReadTest.pdf"; @@ -145,7 +142,6 @@ public virtual void CryptFilterFlushedBeforeStreamTest() { } [NUnit.Framework.Test] - [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] public virtual void CryptFilterFlushedAfterStreamTest() { String file = sourceFolder + "cryptFilterTest.pdf"; String cmpFile = sourceFolder + "cmp_cryptFilterTest.pdf"; diff --git a/itext/itext.kernel/itext/kernel/crypto/securityhandler/PubSecHandlerUsingAes256.cs b/itext/itext.kernel/itext/kernel/crypto/securityhandler/PubSecHandlerUsingAes256.cs index 6f77bf566a..e8e7e3a603 100644 --- a/itext/itext.kernel/itext/kernel/crypto/securityhandler/PubSecHandlerUsingAes256.cs +++ b/itext/itext.kernel/itext/kernel/crypto/securityhandler/PubSecHandlerUsingAes256.cs @@ -85,5 +85,10 @@ internal virtual void SetEncryptionDictEntries(PdfDictionary encryptionDictionar } } //\endcond + + /// + protected internal override void InitMd5MessageDigest() { + } + //Do nothing to not initialize md5 message digest, since it's not used by AES256 handler } } diff --git a/itext/itext.kernel/itext/kernel/crypto/securityhandler/PubSecHandlerUsingAesGcm.cs b/itext/itext.kernel/itext/kernel/crypto/securityhandler/PubSecHandlerUsingAesGcm.cs index 4c70abd255..448a7df1d5 100644 --- a/itext/itext.kernel/itext/kernel/crypto/securityhandler/PubSecHandlerUsingAesGcm.cs +++ b/itext/itext.kernel/itext/kernel/crypto/securityhandler/PubSecHandlerUsingAesGcm.cs @@ -107,5 +107,10 @@ protected internal override void SetPubSecSpecificHandlerDicEntries(PdfDictionar PdfName filter = PdfName.AESV4; SetEncryptionDictEntries(encryptionDictionary, encryptMetadata, embeddedFilesOnly, version, filter); } + + /// + protected internal override void InitMd5MessageDigest() { + } + //Do nothing to not initialize md5 message digest, since it's not used by AES-GCM handler } } diff --git a/itext/itext.kernel/itext/kernel/crypto/securityhandler/SecurityHandler.cs b/itext/itext.kernel/itext/kernel/crypto/securityhandler/SecurityHandler.cs index a8c7b91695..33505ed8e4 100644 --- a/itext/itext.kernel/itext/kernel/crypto/securityhandler/SecurityHandler.cs +++ b/itext/itext.kernel/itext/kernel/crypto/securityhandler/SecurityHandler.cs @@ -67,7 +67,7 @@ public abstract class SecurityHandler { protected internal byte[] extra = new byte[5]; protected internal SecurityHandler() { - SafeInitMessageDigest(); + InitMd5MessageDigest(); } /// @@ -125,7 +125,8 @@ public virtual byte[] GetMkey() { return JavaUtil.ArraysCopyOf(mkey, mkey.Length); } - private void SafeInitMessageDigest() { + /// Init md5 message digest. + protected internal virtual void InitMd5MessageDigest() { try { md5 = iText.Bouncycastleconnector.BouncyCastleFactoryCreator.GetFactory().CreateIDigest("MD5"); if (FACTORY.IsInApprovedOnlyMode()) { diff --git a/itext/itext.kernel/itext/kernel/crypto/securityhandler/StandardHandlerUsingAes256.cs b/itext/itext.kernel/itext/kernel/crypto/securityhandler/StandardHandlerUsingAes256.cs index 504c045148..fa2198eb08 100644 --- a/itext/itext.kernel/itext/kernel/crypto/securityhandler/StandardHandlerUsingAes256.cs +++ b/itext/itext.kernel/itext/kernel/crypto/securityhandler/StandardHandlerUsingAes256.cs @@ -137,6 +137,11 @@ internal virtual bool IsPdf2(PdfDictionary encryptionDictionary) { } //\endcond + /// + protected internal override void InitMd5MessageDigest() { + } + + //Do nothing to not initialize md5 message digest, since it's not used by AES256 handler private void InitKeyAndFillDictionary(PdfDictionary encryptionDictionary, byte[] userPassword, byte[] ownerPassword , int permissions, bool encryptMetadata, bool embeddedFilesOnly) { ownerPassword = GenerateOwnerPasswordIfNullOrEmpty(ownerPassword); diff --git a/itext/itext.kernel/itext/kernel/crypto/securityhandler/StandardHandlerUsingAesGcm.cs b/itext/itext.kernel/itext/kernel/crypto/securityhandler/StandardHandlerUsingAesGcm.cs index 21b62f5a4d..81c7358f8f 100644 --- a/itext/itext.kernel/itext/kernel/crypto/securityhandler/StandardHandlerUsingAesGcm.cs +++ b/itext/itext.kernel/itext/kernel/crypto/securityhandler/StandardHandlerUsingAesGcm.cs @@ -100,5 +100,10 @@ internal override bool IsPdf2(PdfDictionary encryptionDictionary) { return true; } //\endcond + + /// + protected internal override void InitMd5MessageDigest() { + } + //Do nothing to not initialize md5 message digest, since it's not used by AES-GCM handler } } diff --git a/itext/itext.kernel/itext/kernel/crypto/securityhandler/StandardSecurityHandler.cs b/itext/itext.kernel/itext/kernel/crypto/securityhandler/StandardSecurityHandler.cs index 4b03dbf8a1..e58d875d48 100644 --- a/itext/itext.kernel/itext/kernel/crypto/securityhandler/StandardSecurityHandler.cs +++ b/itext/itext.kernel/itext/kernel/crypto/securityhandler/StandardSecurityHandler.cs @@ -20,8 +20,11 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ +using System; +using iText.Commons.Digest; using iText.IO.Source; using iText.IO.Util; +using iText.Kernel.Exceptions; using iText.Kernel.Pdf; namespace iText.Kernel.Crypto.Securityhandler { @@ -62,7 +65,14 @@ protected internal virtual void SetStandardHandlerDicEntries(PdfDictionary encry protected internal virtual byte[] GenerateOwnerPasswordIfNullOrEmpty(byte[] ownerPassword) { if (ownerPassword == null || ownerPassword.Length == 0) { - ownerPassword = md5.Digest(PdfEncryption.GenerateNewDocumentId()); + try { + IMessageDigest sha256 = iText.Bouncycastleconnector.BouncyCastleFactoryCreator.GetFactory().CreateIDigest( + "SHA-256"); + ownerPassword = sha256.Digest(PdfEncryption.GenerateNewDocumentId()); + } + catch (Exception e) { + throw new PdfException(KernelExceptionMessageConstant.PDF_ENCRYPTION, e); + } } return ownerPassword; } diff --git a/port-hash b/port-hash index 04815b0f1f..89060896b1 100644 --- a/port-hash +++ b/port-hash @@ -1 +1 @@ -539cff6ef17d323d2ec3e699f4c93f82dadef6b6 +7cd66857cfe109cfd158f09fb9652c5d0ff5fe8f From c61e62843613f525946c27077bf1479253721fb9 Mon Sep 17 00:00:00 2001 From: Dmitry Radchuk Date: Mon, 14 Oct 2024 08:28:34 +0000 Subject: [PATCH 2/2] Fix cyclic references handling while copying form fields DEVSIX-1775 Autoported commit. Original commit hash: [028c9c8e9] --- .../itext/forms/PdfFormFieldTest.cs | 23 ++++++ .../cmp_formFieldCycleRefTest.pdf | Bin 0 -> 3575 bytes .../itext/kernel/utils/PdfMergerTest.cs | 16 +++++ .../cmp_pdfWithCycleRefInFormField.pdf | Bin 0 -> 1880 bytes .../pdfWithCycleRefInFormField.pdf | Bin 0 -> 1505 bytes .../forms/fields/AbstractPdfFormField.cs | 66 ++++++++++++------ .../forms/logs/FormsLogMessageConstants.cs | 3 + .../itext.kernel/itext/kernel/pdf/PdfPage.cs | 10 ++- port-hash | 2 +- 9 files changed, 97 insertions(+), 23 deletions(-) create mode 100644 itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldTest/cmp_formFieldCycleRefTest.pdf create mode 100644 itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfMergerTest/cmp_pdfWithCycleRefInFormField.pdf create mode 100644 itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfMergerTest/pdfWithCycleRefInFormField.pdf diff --git a/itext.tests/itext.forms.tests/itext/forms/PdfFormFieldTest.cs b/itext.tests/itext.forms.tests/itext/forms/PdfFormFieldTest.cs index d297f34141..83f3bc1bc2 100644 --- a/itext.tests/itext.forms.tests/itext/forms/PdfFormFieldTest.cs +++ b/itext.tests/itext.forms.tests/itext/forms/PdfFormFieldTest.cs @@ -1587,6 +1587,29 @@ public virtual void PdfWithSignatureAndFontInBuilderFieldTest() { , destinationFolder, "diff_")); } + [NUnit.Framework.Test] + [LogMessage(FormsLogMessageConstants.FORM_FIELD_HAS_CYCLED_PARENT_STRUCTURE, Ignore = true)] + public virtual void FormFieldCycleRefTest() { + String fileName = destinationFolder + "formFieldCycleRefTest.pdf"; + PdfDocument pdfDoc = new PdfDocument(CompareTool.CreateTestPdfWriter(fileName)); + pdfDoc.SetTagged(); + pdfDoc.InitializeOutlines(); + PdfAcroForm acroForm = PdfAcroForm.GetAcroForm(pdfDoc, true); + PdfFormField formField = new CheckBoxFormFieldBuilder(pdfDoc, "TestCheck").SetWidgetRectangle(new Rectangle + (36, 560, 20, 20)).CreateCheckBox().SetValue("1", true); + PdfFormField child1 = new TextFormFieldBuilder(pdfDoc, "child").SetWidgetRectangle(new Rectangle(100, 300, + 200, 20)).CreateText(); + PdfFormField child2 = new TextFormFieldBuilder(pdfDoc, "another_name").SetWidgetRectangle(new Rectangle(100 + , 250, 200, 20)).CreateText(); + formField.AddKid(child1); + child1.AddKid(child2); + formField.SetParent(child2); + acroForm.AddField(formField); + pdfDoc.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(fileName, sourceFolder + "cmp_formFieldCycleRefTest.pdf" + , destinationFolder, "diff_")); + } + //\cond DO_NOT_DOCUMENT internal class CustomButtonFormField : PdfButtonFormField { private int counter = 0; diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldTest/cmp_formFieldCycleRefTest.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldTest/cmp_formFieldCycleRefTest.pdf new file mode 100644 index 0000000000000000000000000000000000000000..8842eb6adde8d41b0efa16d891001d812b8a9019 GIT binary patch literal 3575 zcmds4OK;p%6mC0IRMSPf0Eu?Pm8#I0R>^(X*JDG7I+^M8nPfCGDvu;Weq1MRXY9fD zR4F?ox`0)em0;C&K{pX%Rm6s6#R8D}2M`3LZuteAYkM-zxS>E7NI3G?K05cD@4UWy zGt+LiX6an5JoC%1KRzkzh@il_UY?)F^)~!0!%Y#RAnxE5*F}uU*9Ew6y^AScx&j)F zdPT2-q>ZSSXtvEz_%W&_A01)GtBQuWM&L$VC+oNyha)@A)Clg5toYVY;CDP{L&OUU zW#Ky#29@6S;6Y4D0Ti6k6lCI!5`vWR&8Gd){r#y$e^LYi<7T~rTNDALo?FGO9`0@7 zmW#-9fiRweVYO)>YzheORZKsKH%0h?Zw^EiU#mb`catI0nI)s;^L==odTSW8okh7j?MYxN5p*JWj>&b$*%?*)@ zFxP&vuU4$bdmZUx~WRZ2VSd|wQ5cIARB-m%>@)E6|& zWFn>wC&_z3!+F4~G%HRLHcEVUAnho1)Wyxf9u1&Q`zJtZj$y7QX2xafg+d_4(}X5d zD<#WfE50IbAq97WzF0DcX*FfV()>!LP7vfqRgPumq53E86jj=xzrq_3-xH#DnGuw+}YJEOl_HcWCd-1E|cRv3?9C6P*-dUSF zb+~c#_SzgWAKWS3`)=(N!FSIdKXP#J`mwi*yq|2|{}?sndDQs|%5F~20{W17^O(C&_(Yc5B*xI47O2T@rsnYRlmCL`CU;gar z{l{zn^YXgM-i9t|QmB#bvMM6<1Hym?KAbSo5Y8N%1fz}v}1Inp>+IC4=YqfCSK z@F1m8Q;`e#enIUlGS)| zE#*agDlf(Xr^jh~iFNryC%GaVzN9RdE26TZJ&nUuOzG9s;#yrP_@%m9um?MCAqR{a zg&M&bppXNmDKHjeEOBUheG$rkK`u4X>O5Bkvx(y>mSBz`3Uv*gt17o@LKUh(gvKq4 z5pD_16?RP!i`kYinZxy(Su<=~H*|#yg}F6@D3)z$OeoZH6peCK0o|I)9oJD*YS=9o_ESVQ~y^rAVrolALBxj^qc|@AsdqgTn Uu^Gn6m@!S)%QG|QS6byi0sJWN&Hw-a literal 0 HcmV?d00001 diff --git a/itext.tests/itext.kernel.tests/itext/kernel/utils/PdfMergerTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/utils/PdfMergerTest.cs index 3e99ba14e0..116ab5a49c 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/utils/PdfMergerTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/utils/PdfMergerTest.cs @@ -150,6 +150,22 @@ public virtual void MergeDocumentWithCycleTagReferenceTest() { , destinationFolder, "diff_")); } + [NUnit.Framework.Test] + public virtual void MergeDocumentWithCycleReferenceInFormFieldTest() { + String filename1 = sourceFolder + "doc1.pdf"; + String filename2 = sourceFolder + "pdfWithCycleRefInFormField.pdf"; + String resultFile = destinationFolder + "pdfWithCycleRefInFormField.pdf"; + using (PdfDocument pdfDocument1 = new PdfDocument(new PdfReader(filename2))) { + using (PdfDocument pdfDocument2 = new PdfDocument(new PdfReader(filename1), CompareTool.CreateTestPdfWriter + (resultFile).SetSmartMode(true))) { + PdfMerger merger = new PdfMerger(pdfDocument2); + merger.Merge(pdfDocument1, 1, pdfDocument1.GetNumberOfPages()); + } + } + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(resultFile, sourceFolder + "cmp_pdfWithCycleRefInFormField.pdf" + , destinationFolder, "diff_")); + } + [NUnit.Framework.Test] [LogMessage(iText.IO.Logs.IoLogMessageConstant.SOURCE_DOCUMENT_HAS_ACROFORM_DICTIONARY)] public virtual void MergeDocumentTest03() { diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfMergerTest/cmp_pdfWithCycleRefInFormField.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfMergerTest/cmp_pdfWithCycleRefInFormField.pdf new file mode 100644 index 0000000000000000000000000000000000000000..fc3dd2a4db6a953d94c30074f1d00a77d29a94fc GIT binary patch literal 1880 zcmbtV&5qkt6sEvpWS}hAAXP|rLDU&4&;9ogiXvr_rW18$8abg|q*+|s*TE=bk8G!% zvV#RL0PNVYDhu9YhQf%#3-sp!kaz*^b)26jj8MgutXvc_qc$pc`h}B0n z?`?ITJ$*{!{PNQN=bgeWgWK!fnBlh5- z3}dmEo(_?EbrJK(XZIx-0&3^Y%& zN4W&IvUGX^j_&TP6n=?S_dc)aQ{Jj23NcB?OK08n`Nh(y<{G>mhxt%5)tj+kwB%8~ zJg9kB9o!SS)P#hC_*mwqmmZ4*-b|F@;$*CNku;M$UcArwqVeEaXnlAYSrd6Z^1hrr zkVPDb{}ET~Vm)q4DJoV&Vu9|p(U!WY!d^acu)D(Zzh`sh0-krTfDhk!`=d?Dmx`;R zUM|zJQzKaFveF})=!H^mhYw;-B@WYrZ(!c7530=usWFnr( zO#g>;+hACyHsiL9Eosq^__if1%XgW@0;yz8Bh;wVNKhI%ArCplZs0N=299s}B9zpL zT+Bn__>6|GZ&?ntxfOfki R6(ub&C9YAc-MrH={sHe`8_oa# literal 0 HcmV?d00001 diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfMergerTest/pdfWithCycleRefInFormField.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfMergerTest/pdfWithCycleRefInFormField.pdf new file mode 100644 index 0000000000000000000000000000000000000000..544ff8f6ae62b7f3afa6c560010f48b03c64f767 GIT binary patch literal 1505 zcmdT^O>Wab6c&O7G8bTjG@GccP%=NBu{{t)Dh+8X`V*xUU8Gse*w4YJ^;EWlTF$}+ z*l>>`p)R-q9Dxfk<0f@!RH<7=8f)hH{lD*<*04Wl(@yBMe*M1s=>>=&qd$7xE?ytn zPruvk_3$1Ft$bup1H|zVad*Q*RX|=LSzksFS7S;Da+_W62|k$V>f#LWQI<@h>h(Ox z6X#wuVFuYr1qB|Qs0#WJn*{I<^%<}2=@445o!#eyw@hTtM0gl$sii;9%TCmnki#F48V=U42=kf%aU?jqkn>Lz)&_OjwW-H`*BU>EnxrI`f+)A^z;gU-+qLi zKYQ|G8RL#%3yeRIlQju&&B-|zk#9L^_x+qaFCg_Ce?1GO>lL9u2w$KSEo7mv1ab@I zjm*;NuFPl4dQ{r>-?61MT9OgE>@VWBq&v3uI+r#1N&i-is!-Vp6z(zG?xS%x)jIM+ zszH*FQ_T~qB { private static readonly PdfName[] TERMINAL_FIELDS = new PdfName[] { PdfName.Btn, PdfName.Tx, PdfName.Ch, PdfName .Sig }; + private static readonly ILogger LOGGER = ITextLogManager.GetLogger(typeof(iText.Forms.Fields.AbstractPdfFormField + )); + /// Index of font value in default appearance element. private const int DA_FONT = 0; @@ -136,26 +142,7 @@ public virtual PdfFormField GetParentField() { /// . /// public virtual PdfString GetFieldName() { - String parentName = ""; - PdfDictionary parentDict = GetParent(); - if (parentDict != null) { - PdfFormField parentField = GetParentField(); - if (parentField == null) { - parentField = PdfFormField.MakeFormField(GetParent(), GetDocument()); - } - PdfString pName = parentField.GetFieldName(); - if (pName != null) { - parentName = pName.ToUnicodeString() + "."; - } - } - PdfString name = GetPdfObject().GetAsString(PdfName.T); - if (name != null) { - return new PdfString(parentName + name.ToUnicodeString(), PdfEncodings.UNICODE_BIG); - } - if (IsTerminalFormField()) { - return new PdfString(parentName, PdfEncodings.UNICODE_BIG); - } - return null; + return GetFieldName(new HashSet()); } /// @@ -463,6 +450,45 @@ public virtual bool IsTerminalFormField() { return false; } +//\cond DO_NOT_DOCUMENT + /// Gets the current field name. + /// list of visited parents which is used to determine cycle references + /// + /// the current field name, as a + /// . + /// + internal virtual PdfString GetFieldName(ICollection visited) { + String parentName = ""; + PdfDictionary parentDict = GetParent(); + if (parentDict != null) { + PdfFormField parentField = GetParentField(); + if (!visited.Contains(parentField)) { + if (parentField == null) { + parentField = PdfFormField.MakeFormField(GetParent(), GetDocument()); + } + visited.Add(parentField); + PdfString pName = parentField.GetFieldName(visited); + if (pName != null) { + parentName = pName.ToUnicodeString() + "."; + } + } + else { + LOGGER.LogWarning(FormsLogMessageConstants.FORM_FIELD_HAS_CYCLED_PARENT_STRUCTURE); + Remove(PdfName.Parent); + this.parent = null; + } + } + PdfString name = GetPdfObject().GetAsString(PdfName.T); + if (name != null) { + return new PdfString(parentName + name.ToUnicodeString(), PdfEncodings.UNICODE_BIG); + } + if (IsTerminalFormField()) { + return new PdfString(parentName, PdfEncodings.UNICODE_BIG); + } + return null; + } +//\endcond + //\cond DO_NOT_DOCUMENT internal virtual void UpdateFontAndFontSize(PdfFont font, float fontSize) { this.font = font; diff --git a/itext/itext.forms/itext/forms/logs/FormsLogMessageConstants.cs b/itext/itext.forms/itext/forms/logs/FormsLogMessageConstants.cs index 7b92b1074c..6f0836f38e 100644 --- a/itext/itext.forms/itext/forms/logs/FormsLogMessageConstants.cs +++ b/itext/itext.forms/itext/forms/logs/FormsLogMessageConstants.cs @@ -72,6 +72,9 @@ public sealed class FormsLogMessageConstants { public const String FORM_FIELD_MUST_HAVE_A_NAME = "Form field must have a name." + " Set it using PdfFormField#setFieldName call."; + public const String FORM_FIELD_HAS_CYCLED_PARENT_STRUCTURE = "Form field contains parent pointing to itself." + + " This form field parent reference will be invalidated."; + public const String DUPLICATE_EXPORT_VALUE = "More than one option with the same value. This is an invalid" + " state."; diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfPage.cs b/itext/itext.kernel/itext/kernel/pdf/PdfPage.cs index 49a637e39c..dd98deff74 100644 --- a/itext/itext.kernel/itext/kernel/pdf/PdfPage.cs +++ b/itext/itext.kernel/itext/kernel/pdf/PdfPage.cs @@ -1876,9 +1876,15 @@ private void CopyInheritedProperties(iText.Kernel.Pdf.PdfPage copyPdfPage, PdfDo } private void RebuildFormFieldParent(PdfDictionary field, PdfDictionary newField, PdfDocument toDocument) { + RebuildFormFieldParent(field, newField, toDocument, new HashSet()); + } + + private void RebuildFormFieldParent(PdfDictionary field, PdfDictionary newField, PdfDocument toDocument, ICollection + visitedForms) { if (newField.ContainsKey(PdfName.Parent)) { return; } + visitedForms.Add(field); PdfDictionary oldParent = field.GetAsDictionary(PdfName.Parent); if (oldParent != null) { PdfDictionary newParent = oldParent.CopyTo(toDocument, JavaUtil.ArraysAsList(PdfName.P, PdfName.Kids, PdfName @@ -1887,10 +1893,10 @@ private void RebuildFormFieldParent(PdfDictionary field, PdfDictionary newField, newParent = oldParent.CopyTo(toDocument, JavaUtil.ArraysAsList(PdfName.P, PdfName.Kids, PdfName.Parent), true , NullCopyFilter.GetInstance()); } - if (oldParent == oldParent.GetAsDictionary(PdfName.Parent)) { + if (visitedForms.Contains(oldParent)) { return; } - RebuildFormFieldParent(oldParent, newParent, toDocument); + RebuildFormFieldParent(oldParent, newParent, toDocument, visitedForms); PdfArray kids = newParent.GetAsArray(PdfName.Kids); if (kids == null) { // no kids are added here, since we do not know at this point which pages are to be copied, diff --git a/port-hash b/port-hash index 89060896b1..54fa537fa1 100644 --- a/port-hash +++ b/port-hash @@ -1 +1 @@ -7cd66857cfe109cfd158f09fb9652c5d0ff5fe8f +028c9c8e959e6073cf53bfa6932a6ef882d4b82f