From 46df24765a5a2bea1eb1affbef795f7127aaf59c Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Tue, 6 Jun 2023 13:26:12 +0200 Subject: [PATCH 1/6] fixes #173 --- .../cryptomator/cryptofs/fh/ChunkCache.java | 5 +- ...toFileChannelWriteReadIntegrationTest.java | 56 ++++++++++++++++++- 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/cryptomator/cryptofs/fh/ChunkCache.java b/src/main/java/org/cryptomator/cryptofs/fh/ChunkCache.java index 9e8e2a20..ee5eb56f 100644 --- a/src/main/java/org/cryptomator/cryptofs/fh/ChunkCache.java +++ b/src/main/java/org/cryptomator/cryptofs/fh/ChunkCache.java @@ -86,9 +86,10 @@ public Chunk putChunk(long chunkIndex, ByteBuffer chunkData) throws IllegalArgum if (chunk == null) { chunk = new Chunk(chunkData, true, () -> releaseChunk(chunkIndex)); } else { - var dst = chunk.data().duplicate().clear(); + var dst = chunk.data().clear(); Preconditions.checkArgument(chunkData.remaining() == dst.remaining()); - dst.put(chunkData); + dst.put(chunkData) // + .flip(); chunk.dirty().set(true); } chunk.currentAccesses().incrementAndGet(); diff --git a/src/test/java/org/cryptomator/cryptofs/CryptoFileChannelWriteReadIntegrationTest.java b/src/test/java/org/cryptomator/cryptofs/CryptoFileChannelWriteReadIntegrationTest.java index 02bda852..9f0c2b85 100644 --- a/src/test/java/org/cryptomator/cryptofs/CryptoFileChannelWriteReadIntegrationTest.java +++ b/src/test/java/org/cryptomator/cryptofs/CryptoFileChannelWriteReadIntegrationTest.java @@ -53,7 +53,6 @@ import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.IntStream; import java.util.stream.Stream; @@ -175,6 +174,61 @@ public void afterEach() throws IOException { Files.deleteIfExists(file); } + //https://github.com/cryptomator/cryptofs/issues/173 + @Test + public void testPages() throws IOException { + FileChannel writer = null; + try { + writer = FileChannel.open(file, CREATE, WRITE); + writeAndAssert(writer, 81920, 3719); + try (var reader = FileChannel.open(file, CREATE, READ)) { + writeAndAssert(writer, 81920, 17345); + readAndAssert(reader, 98304, 1036, 961); + writeAndAssert(writer, 98304, 65536); + writer.close(); + } + + try (var reader2 = FileChannel.open(file, CREATE, READ)) { + readAndAssert(reader2, 98304, 16384, 16384); + } + } finally { + if (writer != null) { + writer.close(); + } + } + + } + + private void readAndAssert(FileChannel source, int position, int numBytes, int toRead) throws IOException { + var buf = ByteBuffer.allocate(numBytes); + int read = source.read(buf, position); + Assertions.assertEquals(toRead, read); + } + + private void writeAndAssert(FileChannel destination, int position, int numOfBytes) throws IOException { + var buf = createOfSize(numOfBytes); + int written = destination.write(buf, position); + Assertions.assertEquals(numOfBytes, written); + } + + private ByteBuffer createOfSize(int size) { + if (size < 16) { + throw new IllegalArgumentException("too small!"); + } + byte[] content = "16bytesLongtext.".getBytes(StandardCharsets.UTF_8); + int reps = size / 16; + int rest = size % 16; + ByteBuffer buf = ByteBuffer.allocate(size); + for (int i = 0; i < reps; i++) { + buf.put(content); + } + if (rest > 0) { + buf.put(".".repeat(rest).getBytes(StandardCharsets.UTF_8)); + } + buf.flip(); + return buf; + } + @Test public void testLockEmptyChannel() throws IOException { try (FileChannel ch = FileChannel.open(file, CREATE, WRITE)) { From dd19b7045e3464005495fc67b9ed788ecfd74534 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Tue, 6 Jun 2023 15:41:05 +0200 Subject: [PATCH 2/6] create static mock of Files class after all other mocks are instantiated --- .../java/org/cryptomator/cryptofs/CryptoFileSystemsTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/cryptomator/cryptofs/CryptoFileSystemsTest.java b/src/test/java/org/cryptomator/cryptofs/CryptoFileSystemsTest.java index 26dcf5e6..df120142 100644 --- a/src/test/java/org/cryptomator/cryptofs/CryptoFileSystemsTest.java +++ b/src/test/java/org/cryptomator/cryptofs/CryptoFileSystemsTest.java @@ -70,9 +70,9 @@ public class CryptoFileSystemsTest { @BeforeEach public void setup() throws IOException, MasterkeyLoadingFailedException { vaultConficClass = Mockito.mockStatic(VaultConfig.class); - filesClass = Mockito.mockStatic(Files.class); cryptorProviderClass = Mockito.mockStatic(CryptorProvider.class); backupHelperClass = Mockito.mockStatic(BackupHelper.class); + filesClass = Mockito.mockStatic(Files.class); when(pathToVault.normalize()).thenReturn(normalizedPathToVault); when(normalizedPathToVault.resolve("vault.cryptomator")).thenReturn(configFilePath); From 798becdc5ed86764114bfee088a5c77def91a5ed Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Tue, 6 Jun 2023 17:42:00 +0200 Subject: [PATCH 3/6] bump guava to fix CVE --- pom.xml | 2 +- suppression.xml | 8 -------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index 949e3af9..cbe30c2e 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ 2.1.2 4.3.0 2.44.2 - 31.1-jre + 32.0.0-jre 3.1.4 2.0.3 diff --git a/suppression.xml b/suppression.xml index a7fe7425..ebb877b8 100644 --- a/suppression.xml +++ b/suppression.xml @@ -9,12 +9,4 @@ cpe:/a:cryptomator:cryptomator CVE-2022-25366 - - - ^pkg:maven/com\.google\.guava/guava@.*$ - CVE-2020-8908 - CVE-2020-8908 - \ No newline at end of file From a0464924908b2505079a2e53dee350334c25d3f5 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Tue, 6 Jun 2023 18:09:02 +0200 Subject: [PATCH 4/6] improve unit test --- ...toFileChannelWriteReadIntegrationTest.java | 33 ++++++++----------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/src/test/java/org/cryptomator/cryptofs/CryptoFileChannelWriteReadIntegrationTest.java b/src/test/java/org/cryptomator/cryptofs/CryptoFileChannelWriteReadIntegrationTest.java index 9f0c2b85..cfb5090e 100644 --- a/src/test/java/org/cryptomator/cryptofs/CryptoFileChannelWriteReadIntegrationTest.java +++ b/src/test/java/org/cryptomator/cryptofs/CryptoFileChannelWriteReadIntegrationTest.java @@ -176,36 +176,29 @@ public void afterEach() throws IOException { //https://github.com/cryptomator/cryptofs/issues/173 @Test - public void testPages() throws IOException { - FileChannel writer = null; - try { - writer = FileChannel.open(file, CREATE, WRITE); - writeAndAssert(writer, 81920, 3719); - try (var reader = FileChannel.open(file, CREATE, READ)) { - writeAndAssert(writer, 81920, 17345); - readAndAssert(reader, 98304, 1036, 961); - writeAndAssert(writer, 98304, 65536); - writer.close(); + public void testWritingToPreviouslyReadRegionIsSavedCorrectly() throws IOException { + int x = 16_384; //half of cleartext chunk size + try (var reader = FileChannel.open(file, CREATE, READ, WRITE)) { + try (var writer = FileChannel.open(file, CREATE, WRITE)) { + assertWritten(writer, x, x + 1); //write to chunk 0 and 1 + assertRead(reader, 2 * x, 1); //read 1 byte of chunk 1 + assertWritten(writer, 2 * x, 2 * x); //write to chunk 1 } + } - try (var reader2 = FileChannel.open(file, CREATE, READ)) { - readAndAssert(reader2, 98304, 16384, 16384); - } - } finally { - if (writer != null) { - writer.close(); - } + try (var reader2 = FileChannel.open(file, CREATE, READ)) { + assertRead(reader2, 2 * x, x); //read chunk 1 } } - private void readAndAssert(FileChannel source, int position, int numBytes, int toRead) throws IOException { + private void assertRead(FileChannel source, int position, int numBytes) throws IOException { var buf = ByteBuffer.allocate(numBytes); int read = source.read(buf, position); - Assertions.assertEquals(toRead, read); + Assertions.assertEquals(numBytes, read); } - private void writeAndAssert(FileChannel destination, int position, int numOfBytes) throws IOException { + private void assertWritten(FileChannel destination, int position, int numOfBytes) throws IOException { var buf = createOfSize(numOfBytes); int written = destination.write(buf, position); Assertions.assertEquals(numOfBytes, written); From 3e6fe77e2b047502a198aabfa535d2fab637985e Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Wed, 7 Jun 2023 10:43:36 +0200 Subject: [PATCH 5/6] improve unit test --- ...toFileChannelWriteReadIntegrationTest.java | 51 ++++--------------- 1 file changed, 11 insertions(+), 40 deletions(-) diff --git a/src/test/java/org/cryptomator/cryptofs/CryptoFileChannelWriteReadIntegrationTest.java b/src/test/java/org/cryptomator/cryptofs/CryptoFileChannelWriteReadIntegrationTest.java index cfb5090e..2bcbaf42 100644 --- a/src/test/java/org/cryptomator/cryptofs/CryptoFileChannelWriteReadIntegrationTest.java +++ b/src/test/java/org/cryptomator/cryptofs/CryptoFileChannelWriteReadIntegrationTest.java @@ -176,52 +176,23 @@ public void afterEach() throws IOException { //https://github.com/cryptomator/cryptofs/issues/173 @Test - public void testWritingToPreviouslyReadRegionIsSavedCorrectly() throws IOException { - int x = 16_384; //half of cleartext chunk size - try (var reader = FileChannel.open(file, CREATE, READ, WRITE)) { - try (var writer = FileChannel.open(file, CREATE, WRITE)) { - assertWritten(writer, x, x + 1); //write to chunk 0 and 1 - assertRead(reader, 2 * x, 1); //read 1 byte of chunk 1 - assertWritten(writer, 2 * x, 2 * x); //write to chunk 1 - } + @DisplayName("First incomplete, then completely filled chunks are stored completely") + public void testFullChunksAreSavedCompletely() throws IOException { + int halfAChunk = 16_384; //half of cleartext chunk size + try (var writer = FileChannel.open(file, CREATE, WRITE)) { + writer.write(ByteBuffer.allocate(3 * halfAChunk), 0); //fill chunk 0, half fill chunk 1 + writer.write(ByteBuffer.allocate(5 * halfAChunk), 0); //fill chunks 0 and 1, half fill chunk 2 } - try (var reader2 = FileChannel.open(file, CREATE, READ)) { - assertRead(reader2, 2 * x, x); //read chunk 1 + try (var reader = FileChannel.open(file, CREATE, READ)) { + Assertions.assertAll(() -> reader.read(ByteBuffer.allocate(2 * halfAChunk), 0), //read chunk 0 + () -> reader.read(ByteBuffer.allocate(2 * halfAChunk), 2 * halfAChunk), //read chunk 1 + () -> reader.read(ByteBuffer.allocate(halfAChunk), 4 * halfAChunk) //read chunk 2 + ); } } - private void assertRead(FileChannel source, int position, int numBytes) throws IOException { - var buf = ByteBuffer.allocate(numBytes); - int read = source.read(buf, position); - Assertions.assertEquals(numBytes, read); - } - - private void assertWritten(FileChannel destination, int position, int numOfBytes) throws IOException { - var buf = createOfSize(numOfBytes); - int written = destination.write(buf, position); - Assertions.assertEquals(numOfBytes, written); - } - - private ByteBuffer createOfSize(int size) { - if (size < 16) { - throw new IllegalArgumentException("too small!"); - } - byte[] content = "16bytesLongtext.".getBytes(StandardCharsets.UTF_8); - int reps = size / 16; - int rest = size % 16; - ByteBuffer buf = ByteBuffer.allocate(size); - for (int i = 0; i < reps; i++) { - buf.put(content); - } - if (rest > 0) { - buf.put(".".repeat(rest).getBytes(StandardCharsets.UTF_8)); - } - buf.flip(); - return buf; - } - @Test public void testLockEmptyChannel() throws IOException { try (FileChannel ch = FileChannel.open(file, CREATE, WRITE)) { From c494ac622a68dd632d9be9076afd55af333fa5d0 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Wed, 7 Jun 2023 12:10:57 +0200 Subject: [PATCH 6/6] prepare 2.6.5 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index cbe30c2e..c708f3dd 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 org.cryptomator cryptofs - 2.7.0-SNAPSHOT + 2.6.5 Cryptomator Crypto Filesystem This library provides the Java filesystem provider used by Cryptomator. https://github.com/cryptomator/cryptofs