From 0896a251b154113c8ee7359b2aedb7f440c54b0b Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Mon, 14 Jul 2014 13:00:55 +0200 Subject: [PATCH] avoid accessing invalid buffer --- ...bleStorageBackedByResizableMappedFile.java | 4 +-- .../com/intellij/util/io/IntToIntBtree.java | 10 +++++-- .../intellij/util/io/PagedFileStorage.java | 30 +++++++++++-------- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/platform/util/src/com/intellij/util/io/AppendableStorageBackedByResizableMappedFile.java b/platform/util/src/com/intellij/util/io/AppendableStorageBackedByResizableMappedFile.java index 6f936d75849a..c4381da1a406 100644 --- a/platform/util/src/com/intellij/util/io/AppendableStorageBackedByResizableMappedFile.java +++ b/platform/util/src/com/intellij/util/io/AppendableStorageBackedByResizableMappedFile.java @@ -158,7 +158,7 @@ public class AppendableStorageBackedByResizableMappedFile extends ResizeableMapp int base = addr; int address = storage.getOffsetInPage(addr); boolean same = true; - ByteBuffer buffer = storage.getByteBuffer(addr, false); + ByteBuffer buffer = storage.getByteBuffer(addr, false).getCachedBuffer(); final int myPageSize = storage.myPageSize; @Override @@ -166,7 +166,7 @@ public class AppendableStorageBackedByResizableMappedFile extends ResizeableMapp if (same) { if (myPageSize == address && address < myFileLength) { // reached end of current byte buffer base += address; - buffer = storage.getByteBuffer(base, false); + buffer = storage.getByteBuffer(base, false).getCachedBuffer(); address = 0; } same = address < myFileLength && buffer.get(address++) == (byte)b; diff --git a/platform/util/src/com/intellij/util/io/IntToIntBtree.java b/platform/util/src/com/intellij/util/io/IntToIntBtree.java index 8cddbcee32c8..b17fc6cc5c6c 100644 --- a/platform/util/src/com/intellij/util/io/IntToIntBtree.java +++ b/platform/util/src/com/intellij/util/io/IntToIntBtree.java @@ -203,7 +203,7 @@ class IntToIntBtree { boolean canUseLastKey = myCanUseLastKey; if (canUseLastKey) { myCanUseLastKey = false; - if (key == myLastGetKey && !myAccessNodeView.myHasFullPagesAlongPath) { + if (key == myLastGetKey && !myAccessNodeView.myHasFullPagesAlongPath && myAccessNodeView.isValid()) { ++myOptimizedInserts; ++count; myAccessNodeView.insert(key, value); @@ -284,6 +284,7 @@ class IntToIntBtree { private short myChildrenCount; protected int myAddressInBuffer; protected ByteBuffer myBuffer; + protected ByteBufferWrapper myBufferWrapper; protected boolean myHasFullPagesAlongPath; protected boolean myIsDirty; @@ -302,7 +303,8 @@ class IntToIntBtree { protected void syncWithStore() { PagedFileStorage pagedFileStorage = btree.storage.getPagedFileStorage(); myAddressInBuffer = pagedFileStorage.getOffsetInPage(address); - myBuffer = pagedFileStorage.getByteBuffer(address, false); + myBufferWrapper = pagedFileStorage.getByteBuffer(address, false); + myBuffer = myBufferWrapper.getCachedBuffer(); myIsDirty = false; // we will mark dirty on child count change, attrs change or existing key put doInitFlags(myBuffer.getInt(myAddressInBuffer)); } @@ -541,6 +543,10 @@ class IntToIntBtree { setAddress(address); } + public boolean isValid() { + return myBufferWrapper.getCachedBuffer() == myBuffer; + } + private static class HashLeafData { final BtreeIndexNodeView nodeView; final int[] keys; diff --git a/platform/util/src/com/intellij/util/io/PagedFileStorage.java b/platform/util/src/com/intellij/util/io/PagedFileStorage.java index 1d5e9d76d04e..69315f1b3764 100644 --- a/platform/util/src/com/intellij/util/io/PagedFileStorage.java +++ b/platform/util/src/com/intellij/util/io/PagedFileStorage.java @@ -151,7 +151,7 @@ public class PagedFileStorage implements Forceable { if (myValuesAreBufferAligned) { long page = addr / myPageSize; int page_offset = (int) (addr % myPageSize); - return getBuffer(page, false).getInt(page_offset); + return getReadOnlyBuffer(page).getInt(page_offset); } else { get(addr, myTypedIOBuffer, 0, 4); return Bits.getInt(myTypedIOBuffer, 0); @@ -173,15 +173,15 @@ public class PagedFileStorage implements Forceable { return (int)(addr % myPageSize); } - ByteBuffer getByteBuffer(long address, boolean modify) { - return getBuffer(address / myPageSize, modify); + ByteBufferWrapper getByteBuffer(long address, boolean modify) { + return getBufferWrapper(address / myPageSize, modify); } public final short getShort(long addr) { if (myValuesAreBufferAligned) { long page = addr / myPageSize; int page_offset = (int)(addr % myPageSize); - return getBuffer(page, false).getShort(page_offset); + return getReadOnlyBuffer(page).getShort(page_offset); } else { get(addr, myTypedIOBuffer, 0, 2); return Bits.getShort(myTypedIOBuffer, 0); @@ -212,7 +212,7 @@ public class PagedFileStorage implements Forceable { if (myValuesAreBufferAligned) { long page = addr / myPageSize; int page_offset = (int)(addr % myPageSize); - return getBuffer(page, false).getLong(page_offset); + return getReadOnlyBuffer(page).getLong(page_offset); } else { get(addr, myTypedIOBuffer, 0, 8); return Bits.getLong(myTypedIOBuffer, 0); @@ -223,7 +223,7 @@ public class PagedFileStorage implements Forceable { long page = index / myPageSize; int offset = (int)(index % myPageSize); - return getBuffer(page, false).get(offset); + return getReadOnlyBuffer(page).get(offset); } public void put(long index, byte value) { @@ -243,7 +243,7 @@ public class PagedFileStorage implements Forceable { int page_offset = (int) (i % myPageSize); int page_len = Math.min(l, myPageSize - page_offset); - final ByteBuffer buffer = getBuffer(page, false); + final ByteBuffer buffer = getReadOnlyBuffer(page); try { buffer.position(page_offset); } @@ -369,28 +369,32 @@ public class PagedFileStorage implements Forceable { } private ByteBuffer getBuffer(long page) { - return getBuffer(page, true); + return getBufferWrapper(page, true).getCachedBuffer(); } - private ByteBuffer getBuffer(long page, boolean modify) { + private ByteBuffer getReadOnlyBuffer(long page) { + return getBufferWrapper(page, false).getCachedBuffer(); + } + + private ByteBufferWrapper getBufferWrapper(long page, boolean modify) { synchronized (myLastAccessedBufferCacheLock) { if (myLastPage == page) { ByteBuffer buf = myLastBuffer.getCachedBuffer(); if (buf != null && myLastChangeCount == myStorageLockContext.myStorageLock.myMappingChangeCount) { if (modify) markDirty(myLastBuffer); - return buf; + return myLastBuffer; } } else if (myLastPage2 == page) { ByteBuffer buf = myLastBuffer2.getCachedBuffer(); if (buf != null && myLastChangeCount2 == myStorageLockContext.myStorageLock.myMappingChangeCount) { if (modify) markDirty(myLastBuffer2); - return buf; + return myLastBuffer2; } } else if (myLastPage3 == page) { ByteBuffer buf = myLastBuffer3.getCachedBuffer(); if (buf != null && myLastChangeCount3 == myStorageLockContext.myStorageLock.myMappingChangeCount) { if (modify) markDirty(myLastBuffer3); - return buf; + return myLastBuffer3; } } } @@ -427,7 +431,7 @@ public class PagedFileStorage implements Forceable { myLastChangeCount = myStorageLockContext.myStorageLock.myMappingChangeCount; } - return buf; + return byteBufferWrapper; } catch (IOException e) { throw new MappingFailedException("Cannot map buffer", e);