summaryrefslogtreecommitdiffstats
path: root/core/java/android/text/SpannableStringInternal.java
diff options
context:
space:
mode:
authorChet Haase <chet@google.com>2013-10-03 17:21:14 -0700
committerChet Haase <chet@google.com>2013-10-04 07:24:19 -0700
commit1d3c4b396a393515e738cb72782ef564362420fa (patch)
tree73e700050a2f9f91fd7bf57c574af770c1ce4286 /core/java/android/text/SpannableStringInternal.java
parent76a5c86df7902870c87ff07ffd0628cb10f32c00 (diff)
downloadframeworks_base-1d3c4b396a393515e738cb72782ef564362420fa.zip
frameworks_base-1d3c4b396a393515e738cb72782ef564362420fa.tar.gz
frameworks_base-1d3c4b396a393515e738cb72782ef564362420fa.tar.bz2
Fix infinite recursion in hashcode of Spannables
An app created a SpannableStringBuilder, one of which's spans was the instance of the string builder itself (that is, the builder contained a span that was the builder). This caused infinite recursion in the hashcode() method because it computes a hash from its fields, including all of its spans. The fix detects the case where a span equals the current instance and noops the computation on that span. A similar adjustment was made to equals() to avoid the same recursion problem. Issue #11051658 StackOverflowError in android.text.SpannableStringBuilder.hashCode Change-Id: I742687ab32d81ac51c4b9135f698cf5e96a1d295
Diffstat (limited to 'core/java/android/text/SpannableStringInternal.java')
-rw-r--r--core/java/android/text/SpannableStringInternal.java24
1 files changed, 16 insertions, 8 deletions
diff --git a/core/java/android/text/SpannableStringInternal.java b/core/java/android/text/SpannableStringInternal.java
index 9b24a2e..456a3e5 100644
--- a/core/java/android/text/SpannableStringInternal.java
+++ b/core/java/android/text/SpannableStringInternal.java
@@ -363,23 +363,29 @@ import java.lang.reflect.Array;
public boolean equals(Object o) {
if (o instanceof Spanned &&
toString().equals(o.toString())) {
+ Spanned other = (Spanned) o;
// Check span data
- Object[] otherSpans = ((Spanned) o).getSpans(0,
- ((Spanned) o).length(), Object.class);
+ Object[] otherSpans = other.getSpans(0, other.length(), Object.class);
if (mSpanCount == otherSpans.length) {
for (int i = 0; i < mSpanCount; ++i) {
Object thisSpan = mSpans[i];
Object otherSpan = otherSpans[i];
- if (!thisSpan.equals(otherSpan) ||
- getSpanStart(thisSpan) != getSpanStart(otherSpan) ||
- getSpanEnd(thisSpan) != getSpanEnd(otherSpan) ||
- getSpanFlags(thisSpan) != getSpanFlags(otherSpan)) {
+ if (thisSpan == this) {
+ if (other != otherSpan ||
+ getSpanStart(thisSpan) != other.getSpanStart(otherSpan) ||
+ getSpanEnd(thisSpan) != other.getSpanEnd(otherSpan) ||
+ getSpanFlags(thisSpan) != other.getSpanFlags(otherSpan)) {
+ return false;
+ }
+ } else if (!thisSpan.equals(otherSpan) ||
+ getSpanStart(thisSpan) != other.getSpanStart(otherSpan) ||
+ getSpanEnd(thisSpan) != other.getSpanEnd(otherSpan) ||
+ getSpanFlags(thisSpan) != other.getSpanFlags(otherSpan)) {
return false;
}
}
return true;
}
-
}
return false;
}
@@ -391,7 +397,9 @@ import java.lang.reflect.Array;
hash = hash * 31 + mSpanCount;
for (int i = 0; i < mSpanCount; ++i) {
Object span = mSpans[i];
- hash = hash * 31 + span.hashCode();
+ if (span != this) {
+ hash = hash * 31 + span.hashCode();
+ }
hash = hash * 31 + getSpanStart(span);
hash = hash * 31 + getSpanEnd(span);
hash = hash * 31 + getSpanFlags(span);