From cb6e2823c8b2ca74dd987cc0cc755bd831cd186e Mon Sep 17 00:00:00 2001 From: "pixeebot[bot]" <104101892+pixeebot[bot]@users.noreply.github.com> Date: Thu, 5 Sep 2024 03:27:40 +0000 Subject: [PATCH] Protect `readLine()` against DoS --- event-sourcing/pom.xml | 4 + .../sourcing/processor/JsonFileJournal.java | 3 +- module/pom.xml | 4 + .../iluwatar/module/FileLoggerModuleTest.java | 349 +++++++++--------- pom.xml | 8 + promise/pom.xml | 4 + .../java/com/iluwatar/promise/Utility.java | 3 +- 7 files changed, 199 insertions(+), 176 deletions(-) diff --git a/event-sourcing/pom.xml b/event-sourcing/pom.xml index 569a5fceebd8..c53373b3d3f2 100644 --- a/event-sourcing/pom.xml +++ b/event-sourcing/pom.xml @@ -43,6 +43,10 @@ com.fasterxml.jackson.core jackson-databind + + io.github.pixee + java-security-toolkit + diff --git a/event-sourcing/src/main/java/com/iluwatar/event/sourcing/processor/JsonFileJournal.java b/event-sourcing/src/main/java/com/iluwatar/event/sourcing/processor/JsonFileJournal.java index cfde566dc2fb..affb68dece8e 100644 --- a/event-sourcing/src/main/java/com/iluwatar/event/sourcing/processor/JsonFileJournal.java +++ b/event-sourcing/src/main/java/com/iluwatar/event/sourcing/processor/JsonFileJournal.java @@ -30,6 +30,7 @@ import com.iluwatar.event.sourcing.event.DomainEvent; import com.iluwatar.event.sourcing.event.MoneyDepositEvent; import com.iluwatar.event.sourcing.event.MoneyTransferEvent; +import io.github.pixee.security.BoundedLineReader; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; @@ -62,7 +63,7 @@ public JsonFileJournal() { try (var input = new BufferedReader( new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8))) { String line; - while ((line = input.readLine()) != null) { + while ((line = BoundedLineReader.readLine(input, 5_000_000)) != null) { events.add(line); } } catch (IOException e) { diff --git a/module/pom.xml b/module/pom.xml index 4f6c0dcb86e3..99f646c46902 100644 --- a/module/pom.xml +++ b/module/pom.xml @@ -39,6 +39,10 @@ junit-jupiter-engine test + + io.github.pixee + java-security-toolkit + diff --git a/module/src/test/java/com/iluwatar/module/FileLoggerModuleTest.java b/module/src/test/java/com/iluwatar/module/FileLoggerModuleTest.java index 6d05566b45cf..6d3dd2c1782f 100644 --- a/module/src/test/java/com/iluwatar/module/FileLoggerModuleTest.java +++ b/module/src/test/java/com/iluwatar/module/FileLoggerModuleTest.java @@ -1,174 +1,175 @@ -/* - * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). - * - * The MIT License - * Copyright © 2014-2022 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.module; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; - -import java.io.BufferedReader; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import lombok.extern.slf4j.Slf4j; -import org.junit.jupiter.api.Test; - -/** - * The Module pattern can be considered a Creational pattern and a Structural pattern. It manages - * the creation and organization of other elements, and groups them as the structural pattern does. - * An object that applies this pattern can provide the equivalent of a namespace, providing the - * initialization and finalization process of a static class or a class with static members with - * cleaner, more concise syntax and semantics. - *

- * The below example demonstrates a JUnit test for testing two different modules: File Logger and - * Console Logger - */ -@Slf4j -public final class FileLoggerModuleTest { - - private static final String OUTPUT_FILE = "output.txt"; - private static final String ERROR_FILE = "error.txt"; - - private static final String MESSAGE = "MESSAGE"; - private static final String ERROR = "ERROR"; - - - /** - * This test verify that 'MESSAGE' is perfectly printed in output file - * - * @throws IOException if program is not able to find log files (output.txt and error.txt) - */ - @Test - void testFileMessage() throws IOException { - - /* Get singleton instance of File Logger Module */ - final var fileLoggerModule = FileLoggerModule.getSingleton(); - - /* Prepare the essential sub modules, to perform the sequence of jobs */ - fileLoggerModule.prepare(); - - /* Print 'Message' in file */ - fileLoggerModule.printString(MESSAGE); - - /* Test if 'Message' is printed in file */ - assertEquals(readFirstLine(OUTPUT_FILE), MESSAGE); - - /* Unprepare to cleanup the modules */ - fileLoggerModule.unprepare(); - } - - /** - * This test verify that nothing is printed in output file - * - * @throws IOException if program is not able to find log files (output.txt and error.txt) - */ - @Test - void testNoFileMessage() throws IOException { - - /* Get singleton instance of File Logger Module */ - final var fileLoggerModule = FileLoggerModule.getSingleton(); - - /* Prepare the essential sub modules, to perform the sequence of jobs */ - fileLoggerModule.prepare(); - - /* Test if nothing is printed in file */ - assertNull(readFirstLine(OUTPUT_FILE)); - - /* Unprepare to cleanup the modules */ - fileLoggerModule.unprepare(); - } - - /** - * This test verify that 'ERROR' is perfectly printed in error file - * - * @throws FileNotFoundException if program is not able to find log files (output.txt and - * error.txt) - */ - @Test - void testFileErrorMessage() throws FileNotFoundException { - - /* Get singleton instance of File Logger Module */ - final var fileLoggerModule = FileLoggerModule.getSingleton(); - - /* Prepare the essential sub modules, to perform the sequence of jobs */ - fileLoggerModule.prepare(); - - /* Print 'Error' in file */ - fileLoggerModule.printErrorString(ERROR); - - /* Test if 'Message' is printed in file */ - assertEquals(ERROR, readFirstLine(ERROR_FILE)); - - /* Un-prepare to cleanup the modules */ - fileLoggerModule.unprepare(); - } - - /** - * This test verify that nothing is printed in error file - * - * @throws FileNotFoundException if program is not able to find log files (output.txt and - * error.txt) - */ - @Test - void testNoFileErrorMessage() throws FileNotFoundException { - - /* Get singleton instance of File Logger Module */ - final var fileLoggerModule = FileLoggerModule.getSingleton(); - - /* Prepare the essential sub modules, to perform the sequence of jobs */ - fileLoggerModule.prepare(); - - /* Test if nothing is printed in file */ - assertNull(readFirstLine(ERROR_FILE)); - - /* Unprepare to cleanup the modules */ - fileLoggerModule.unprepare(); - } - - /** - * Utility method to read first line of a file - * - * @param file as file name to be read - * @return a string value as first line in file - */ - private static String readFirstLine(final String file) { - - String firstLine = null; - try (var bufferedReader = new BufferedReader(new FileReader(file))) { - - while (bufferedReader.ready()) { - - /* Read the line */ - firstLine = bufferedReader.readLine(); - } - - LOGGER.info("ModuleTest::readFirstLine() : firstLine : " + firstLine); - - } catch (final IOException e) { - LOGGER.error("ModuleTest::readFirstLine()", e); - } - - return firstLine; - } -} +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.module; + +import io.github.pixee.security.BoundedLineReader; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.Test; + +/** + * The Module pattern can be considered a Creational pattern and a Structural pattern. It manages + * the creation and organization of other elements, and groups them as the structural pattern does. + * An object that applies this pattern can provide the equivalent of a namespace, providing the + * initialization and finalization process of a static class or a class with static members with + * cleaner, more concise syntax and semantics. + *

+ * The below example demonstrates a JUnit test for testing two different modules: File Logger and + * Console Logger + */ +@Slf4j +public final class FileLoggerModuleTest { + + private static final String OUTPUT_FILE = "output.txt"; + private static final String ERROR_FILE = "error.txt"; + + private static final String MESSAGE = "MESSAGE"; + private static final String ERROR = "ERROR"; + + + /** + * This test verify that 'MESSAGE' is perfectly printed in output file + * + * @throws IOException if program is not able to find log files (output.txt and error.txt) + */ + @Test + void testFileMessage() throws IOException { + + /* Get singleton instance of File Logger Module */ + final var fileLoggerModule = FileLoggerModule.getSingleton(); + + /* Prepare the essential sub modules, to perform the sequence of jobs */ + fileLoggerModule.prepare(); + + /* Print 'Message' in file */ + fileLoggerModule.printString(MESSAGE); + + /* Test if 'Message' is printed in file */ + assertEquals(readFirstLine(OUTPUT_FILE), MESSAGE); + + /* Unprepare to cleanup the modules */ + fileLoggerModule.unprepare(); + } + + /** + * This test verify that nothing is printed in output file + * + * @throws IOException if program is not able to find log files (output.txt and error.txt) + */ + @Test + void testNoFileMessage() throws IOException { + + /* Get singleton instance of File Logger Module */ + final var fileLoggerModule = FileLoggerModule.getSingleton(); + + /* Prepare the essential sub modules, to perform the sequence of jobs */ + fileLoggerModule.prepare(); + + /* Test if nothing is printed in file */ + assertNull(readFirstLine(OUTPUT_FILE)); + + /* Unprepare to cleanup the modules */ + fileLoggerModule.unprepare(); + } + + /** + * This test verify that 'ERROR' is perfectly printed in error file + * + * @throws FileNotFoundException if program is not able to find log files (output.txt and + * error.txt) + */ + @Test + void testFileErrorMessage() throws FileNotFoundException { + + /* Get singleton instance of File Logger Module */ + final var fileLoggerModule = FileLoggerModule.getSingleton(); + + /* Prepare the essential sub modules, to perform the sequence of jobs */ + fileLoggerModule.prepare(); + + /* Print 'Error' in file */ + fileLoggerModule.printErrorString(ERROR); + + /* Test if 'Message' is printed in file */ + assertEquals(ERROR, readFirstLine(ERROR_FILE)); + + /* Un-prepare to cleanup the modules */ + fileLoggerModule.unprepare(); + } + + /** + * This test verify that nothing is printed in error file + * + * @throws FileNotFoundException if program is not able to find log files (output.txt and + * error.txt) + */ + @Test + void testNoFileErrorMessage() throws FileNotFoundException { + + /* Get singleton instance of File Logger Module */ + final var fileLoggerModule = FileLoggerModule.getSingleton(); + + /* Prepare the essential sub modules, to perform the sequence of jobs */ + fileLoggerModule.prepare(); + + /* Test if nothing is printed in file */ + assertNull(readFirstLine(ERROR_FILE)); + + /* Unprepare to cleanup the modules */ + fileLoggerModule.unprepare(); + } + + /** + * Utility method to read first line of a file + * + * @param file as file name to be read + * @return a string value as first line in file + */ + private static String readFirstLine(final String file) { + + String firstLine = null; + try (var bufferedReader = new BufferedReader(new FileReader(file))) { + + while (bufferedReader.ready()) { + + /* Read the line */ + firstLine = BoundedLineReader.readLine(bufferedReader, 5_000_000); + } + + LOGGER.info("ModuleTest::readFirstLine() : firstLine : " + firstLine); + + } catch (final IOException e) { + LOGGER.error("ModuleTest::readFirstLine()", e); + } + + return firstLine; + } +} diff --git a/pom.xml b/pom.xml index 10348ef0466a..f987b3fa57e5 100644 --- a/pom.xml +++ b/pom.xml @@ -54,6 +54,7 @@ iluwatar_java-design-patterns ${project.artifactId} Java Design Patterns + 1.2.0 abstract-factory @@ -248,6 +249,13 @@ ${system-lambda.version} test + + io.github.pixee + java-security-toolkit + + + ${versions.java-security-toolkit} + diff --git a/promise/pom.xml b/promise/pom.xml index 7a104ee3bf14..708c43ed0511 100644 --- a/promise/pom.xml +++ b/promise/pom.xml @@ -44,6 +44,10 @@ mockito-core test + + io.github.pixee + java-security-toolkit + diff --git a/promise/src/main/java/com/iluwatar/promise/Utility.java b/promise/src/main/java/com/iluwatar/promise/Utility.java index 0976c8c751bc..7d4f4c4d36e7 100644 --- a/promise/src/main/java/com/iluwatar/promise/Utility.java +++ b/promise/src/main/java/com/iluwatar/promise/Utility.java @@ -24,6 +24,7 @@ */ package com.iluwatar.promise; +import io.github.pixee.security.BoundedLineReader; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; @@ -103,7 +104,7 @@ public static String downloadFile(String urlString) throws IOException { try (var bufferedReader = new BufferedReader(new InputStreamReader(url.openStream())); var writer = new FileWriter(file)) { String line; - while ((line = bufferedReader.readLine()) != null) { + while ((line = BoundedLineReader.readLine(bufferedReader, 5_000_000)) != null) { writer.write(line); writer.write("\n"); }