diff --git a/ChangeLog b/ChangeLog index 9a9e32c08..9980941c9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,7 @@ * Fixed NPE in FontEntry.equals() * Fixed NPE in ZLTextPlainModel.getTextLength() * Fixed skip operation on non-compressed zips +* Fixed possible AOOB in text model ===== 1.10.0.3 (Apr 21, 2014) ===== * Fixed duplicate processing for some CSS properties diff --git a/src/org/geometerplus/zlibrary/text/model/CachedCharStorageBase.java b/src/org/geometerplus/zlibrary/text/model/CachedCharStorageBase.java index 98bcd78f0..9eea9cf1f 100644 --- a/src/org/geometerplus/zlibrary/text/model/CachedCharStorageBase.java +++ b/src/org/geometerplus/zlibrary/text/model/CachedCharStorageBase.java @@ -44,6 +44,9 @@ abstract class CachedCharStorageBase implements CharStorage { } public char[] block(int index) { + if (index < 0 && index >= myArray.size()) { + return null; + } char[] block = myArray.get(index).get(); if (block == null) { try { diff --git a/src/org/geometerplus/zlibrary/text/model/SimpleCharStorage.java b/src/org/geometerplus/zlibrary/text/model/SimpleCharStorage.java index 509336cd9..d078e2400 100644 --- a/src/org/geometerplus/zlibrary/text/model/SimpleCharStorage.java +++ b/src/org/geometerplus/zlibrary/text/model/SimpleCharStorage.java @@ -34,6 +34,9 @@ final class SimpleCharStorage implements CharStorage { } public char[] block(int index) { + if (index < 0 || index >= myArray.size()) { + return null; + } return myArray.get(index); } diff --git a/src/org/geometerplus/zlibrary/text/model/ZLTextParagraph.java b/src/org/geometerplus/zlibrary/text/model/ZLTextParagraph.java index 58d1f49f5..a484b3ada 100644 --- a/src/org/geometerplus/zlibrary/text/model/ZLTextParagraph.java +++ b/src/org/geometerplus/zlibrary/text/model/ZLTextParagraph.java @@ -53,8 +53,7 @@ public interface ZLTextParagraph { short getFixedHSpaceLength(); - boolean hasNext(); - void next(); + boolean next(); } public EntryIterator iterator(); diff --git a/src/org/geometerplus/zlibrary/text/model/ZLTextPlainModel.java b/src/org/geometerplus/zlibrary/text/model/ZLTextPlainModel.java index a3c0726a9..df7906654 100644 --- a/src/org/geometerplus/zlibrary/text/model/ZLTextPlainModel.java +++ b/src/org/geometerplus/zlibrary/text/model/ZLTextPlainModel.java @@ -77,9 +77,7 @@ public class ZLTextPlainModel implements ZLTextModel, ZLTextStyleEntry.Feature { private short myFixedHSpaceLength; EntryIteratorImpl(int index) { - myLength = myParagraphLengths[index]; - myDataIndex = myStartEntryIndices[index]; - myDataOffset = myStartEntryOffsets[index]; + reset(index); } void reset(int index) { @@ -132,20 +130,29 @@ public class ZLTextPlainModel implements ZLTextModel, ZLTextStyleEntry.Feature { return myFixedHSpaceLength; } - public boolean hasNext() { - return myCounter < myLength; - } + public boolean next() { + if (myCounter >= myLength) { + return false; + } - public void next() { int dataOffset = myDataOffset; char[] data = myStorage.block(myDataIndex); + if (data == null) { + return false; + } if (dataOffset >= data.length) { data = myStorage.block(++myDataIndex); + if (data == null) { + return false; + } dataOffset = 0; } byte type = (byte)data[dataOffset]; if (type == 0) { data = myStorage.block(++myDataIndex); + if (data == null) { + return false; + } dataOffset = 0; type = (byte)data[0]; } @@ -252,6 +259,7 @@ public class ZLTextPlainModel implements ZLTextModel, ZLTextStyleEntry.Feature { } ++myCounter; myDataOffset = dataOffset; + return true; } } @@ -341,8 +349,7 @@ public class ZLTextPlainModel implements ZLTextModel, ZLTextStyleEntry.Feature { final EntryIteratorImpl it = new EntryIteratorImpl(index); while (true) { int offset = 0; - while (it.hasNext()) { - it.next(); + while (it.next()) { if (it.getType() == ZLTextParagraph.Entry.TEXT) { char[] textData = it.getTextData(); int textOffset = it.getTextOffset(); diff --git a/src/org/geometerplus/zlibrary/text/view/ZLTextParagraphCursor.java b/src/org/geometerplus/zlibrary/text/view/ZLTextParagraphCursor.java index 7568eee8b..68164b9a4 100644 --- a/src/org/geometerplus/zlibrary/text/view/ZLTextParagraphCursor.java +++ b/src/org/geometerplus/zlibrary/text/view/ZLTextParagraphCursor.java @@ -59,8 +59,7 @@ public final class ZLTextParagraphCursor { ZLTextHyperlink hyperlink = null; final ArrayList elements = myElements; - for (ZLTextParagraph.EntryIterator it = myParagraph.iterator(); it.hasNext(); ) { - it.next(); + for (ZLTextParagraph.EntryIterator it = myParagraph.iterator(); it.next(); ) { switch (it.getType()) { case ZLTextParagraph.Entry.TEXT: processTextEntry(it.getTextData(), it.getTextOffset(), it.getTextLength(), hyperlink); diff --git a/src/org/geometerplus/zlibrary/text/view/ZLTextView.java b/src/org/geometerplus/zlibrary/text/view/ZLTextView.java index 7000c299e..e48dde935 100644 --- a/src/org/geometerplus/zlibrary/text/view/ZLTextView.java +++ b/src/org/geometerplus/zlibrary/text/view/ZLTextView.java @@ -682,10 +682,8 @@ public abstract class ZLTextView extends ZLTextViewBase { } while (paragraph < myModel.getParagraphsNumber() && myLettersBufferLength < myLettersBuffer.length) { - ZLTextParagraph.EntryIterator it = myModel.getParagraph(paragraph++).iterator(); - while (it.hasNext() - && myLettersBufferLength < myLettersBuffer.length) { - it.next(); + final ZLTextParagraph.EntryIterator it = myModel.getParagraph(paragraph++).iterator(); + while (myLettersBufferLength < myLettersBuffer.length && it.next()) { if (it.getType() == ZLTextParagraph.Entry.TEXT) { final int len = Math.min(it.getTextLength(), myLettersBuffer.length - myLettersBufferLength);