Skip to content

Commit db1aff3

Browse files
committed
add EditableDefensor
1 parent 219fd28 commit db1aff3

File tree

6 files changed

+201
-13
lines changed

6 files changed

+201
-13
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package com.panda912.defensor.plugin.internal.interceptor
2+
3+
import android.text.Editable
4+
import com.panda912.defensor.plugin.internal.BytecodeInterceptor
5+
import com.panda912.defensor.plugin.internal.Output
6+
import com.panda912.defensor.plugin.internal.visitor.BaseClassReader
7+
import com.panda912.defensor.plugin.internal.visitor.BaseClassVisitor
8+
import com.panda912.defensor.plugin.internal.visitor.BaseMethodVisitor
9+
import com.panda912.defensor.plugin.utils.EDITABLE_DEFENSOR
10+
import com.panda912.defensor.plugin.utils.convertToStaticDescriptor
11+
import com.panda912.defensor.plugin.utils.toClassName
12+
import com.panda912.defensor.plugin.utils.toInternalName
13+
import org.objectweb.asm.ClassWriter
14+
import org.objectweb.asm.MethodVisitor
15+
import org.objectweb.asm.Opcodes
16+
17+
/**
18+
* Created by panda on 2022/2/22 15:59
19+
*/
20+
class EditableInterceptor : BytecodeInterceptor {
21+
22+
override fun intercept(chain: BytecodeInterceptor.Chain): Output {
23+
val input = chain.request()
24+
25+
val cr = BaseClassReader(input.bytes)
26+
val cw = ClassWriter(cr, ClassWriter.COMPUTE_MAXS)
27+
cr.accept(object : BaseClassVisitor(cw) {
28+
override fun visitMethod(
29+
access: Int,
30+
name: String?,
31+
descriptor: String?,
32+
signature: String?,
33+
exceptions: Array<out String>?
34+
): MethodVisitor {
35+
val mv = super.visitMethod(access, name, descriptor, signature, exceptions)
36+
return EditableMethodVisitor(mv)
37+
}
38+
})
39+
input.bytes = cw.toByteArray()
40+
return chain.proceed(input)
41+
}
42+
}
43+
44+
private class EditableMethodVisitor(mv: MethodVisitor) : BaseMethodVisitor(mv) {
45+
46+
override fun visitMethodInsn(
47+
opcode: Int,
48+
owner: String,
49+
name: String,
50+
descriptor: String,
51+
isInterface: Boolean
52+
) {
53+
54+
if (
55+
(name == "replace" && descriptor == "(IILjava/lang/CharSequence;II)Landroid/text/Editable;") ||
56+
(name == "replace" && descriptor == "(IILjava/lang/CharSequence;)Landroid/text/Editable;") ||
57+
(name == "insert" && descriptor == "(ILjava/lang/CharSequence;II)Landroid/text/Editable;") ||
58+
(name == "insert" && descriptor == "(ILjava/lang/CharSequence;)Landroid/text/Editable;") ||
59+
(name == "delete" && descriptor == "(II)Landroid/text/Editable;") ||
60+
(name == "append" && descriptor == "(Ljava/lang/CharSequence;)Landroid/text/Editable;") ||
61+
(name == "append" && descriptor == "(Ljava/lang/CharSequence;II)Landroid/text/Editable;") ||
62+
(name == "append" && descriptor == "(C)Landroid/text/Editable;") ||
63+
(name == "replace" && descriptor == "(IILjava/lang/CharSequence;II)Landroid/text/SpannableStringBuilder;") ||
64+
(name == "replace" && descriptor == "(IILjava/lang/CharSequence;)Landroid/text/SpannableStringBuilder;") ||
65+
(name == "insert" && descriptor == "(ILjava/lang/CharSequence;II)Landroid/text/SpannableStringBuilder;") ||
66+
(name == "insert" && descriptor == "(ILjava/lang/CharSequence;)Landroid/text/SpannableStringBuilder;") ||
67+
(name == "delete" && descriptor == "(II)Landroid/text/SpannableStringBuilder;") ||
68+
(name == "append" && descriptor == "(Ljava/lang/CharSequence;)Landroid/text/SpannableStringBuilder;") ||
69+
(name == "append" && descriptor == "(Ljava/lang/CharSequence;II)Landroid/text/SpannableStringBuilder;") ||
70+
(name == "append" && descriptor == "(C)Landroid/text/SpannableStringBuilder;")
71+
) {
72+
try {
73+
if (Editable::class.java.isAssignableFrom(Class.forName(owner.toClassName()))) {
74+
val newDescriptor = descriptor.convertToStaticDescriptor("Landroid/text/Editable;")
75+
.replace("Landroid/text/SpannableStringBuilder;", "Landroid/text/Editable;")
76+
super.visitMethodInsn(
77+
Opcodes.INVOKESTATIC,
78+
EDITABLE_DEFENSOR.toInternalName(),
79+
name,
80+
newDescriptor,
81+
isInterface
82+
)
83+
return
84+
}
85+
} catch (ignored: ClassNotFoundException) {
86+
}
87+
}
88+
89+
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface)
90+
}
91+
}

defensor-gradle-plugin/src/main/java/com/panda912/defensor/plugin/internal/processor/BytecodeInjectorImpl.kt

+14-13
Original file line numberDiff line numberDiff line change
@@ -20,27 +20,28 @@ class BytecodeInjectorImpl : BytecodeInjector {
2020

2121
override fun inject(fullName: String, className: String, bytes: ByteArray): ByteArray {
2222
val interceptors = listOf(
23+
ActivityInterceptor(),
2324
ArrayInterceptor(),
24-
UnboxingInterceptor(),
25-
PrimitiveInterceptor(),
2625
CollectionInterceptor(),
27-
StringInterceptor(),
26+
ContextInterceptor(),
27+
DeadObjectInterceptor(),
28+
EditableInterceptor(),
2829
FileInterceptor(),
29-
JsonInterceptor(),
30-
ThrowableInterceptor(),
31-
ActivityInterceptor(),
3230
FragmentInterceptor(),
33-
SafeDialogInterceptor(),
31+
GridLayoutManagerInterceptor(),
32+
HandlerInterceptor(),
3433
IntentInterceptor(),
35-
ViewInterceptor(),
36-
DeadObjectInterceptor(),
37-
ContextInterceptor(),
38-
UriInterceptor(),
34+
JsonInterceptor(),
3935
LiveDataInterceptor(),
4036
PaintInterceptor(),
41-
GridLayoutManagerInterceptor(),
37+
PrimitiveInterceptor(),
38+
SafeDialogInterceptor(),
39+
StringInterceptor(),
40+
ThrowableInterceptor(),
41+
UnboxingInterceptor(),
42+
UriInterceptor(),
4243
ValueAnimatorInterceptor(),
43-
HandlerInterceptor()
44+
ViewInterceptor(),
4445
)
4546
val input = Input(fullName, className, bytes)
4647
val chain = BytecodeInterceptorChain(interceptors + FinalInterceptor(), 0, input)

defensor-gradle-plugin/src/main/java/com/panda912/defensor/plugin/utils/Const.kt

+3
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,15 @@ const val TELEPHONY_MANAGER_CLASS = "android.telephony.TelephonyManager"
5454
const val PAINT_CLASS = "android.graphics.Paint"
5555
const val HANDLER_CLASS = "android.os.Handler"
5656
const val BOTTOM_SHEET_BEHAVIOR = "com.google.android.material.bottomsheet.BottomSheetBehavior"
57+
const val SPANNABLE_STRING_BUILDER = "android.text.SpannableStringBuilder"
5758

5859

5960
const val ACTIVITY_DEFENSOR = "com.panda912.defensor.internal.ActivityDefensor"
6061
const val BOTTOM_SHEET_BEHAVIOR_DEFENSOR = "com.panda912.defensor.internal.BottomSheetBehaviorDefensor"
6162
const val COLLECTION_DEFENSOR = "com.panda912.defensor.internal.CollectionDefensor"
6263
const val CONTEXT_DEFENSOR = "com.panda912.defensor.internal.ContextDefensor"
6364
const val DEAD_OBJECT_CRASH_HANDLER = "com.panda912.defensor.internal.DeadObjectCrashHandler"
65+
const val EDITABLE_DEFENSOR = "com.panda912.defensor.internal.EditableDefensor"
6466
const val FILE_DEFENSOR = "com.panda912.defensor.internal.FileDefensor"
6567
const val FRAGMENT_DEFENSOR = "com.panda912.defensor.internal.FragmentDefensor"
6668
const val FRAGMENTX_DEFENSOR = "com.panda912.defensor.internal.FragmentXDefensor"
@@ -79,6 +81,7 @@ const val SAFE_FILE = "com.panda912.defensor.internal.SafeFile"
7981
const val SAFE_JSON_ARRAY = "com.panda912.defensor.internal.SafeJSONArray"
8082
const val SAFE_JSON_OBJECT = "com.panda912.defensor.internal.SafeJSONObject"
8183
const val SAFE_MUTABLE_LIVE_DATA = "com.panda912.defensor.internal.SafeMutableLiveData"
84+
const val SPANNABLE_STRING_BUILDER_DEFENSOR = "com.panda912.defensor.internal.SpannableStringBuilderDefensor"
8285
const val STRING_DEFENSOR = "com.panda912.defensor.internal.StringDefensor"
8386
const val TEXTVIEW_DEFENSOR = "com.panda912.defensor.internal.TextViewDefensor"
8487
const val THROWABLE_DEFENSOR = "com.panda912.defensor.internal.ThrowableDefensor"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package android.text;
2+
3+
public interface Editable {
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package android.text;
2+
3+
public class SpannableStringBuilder implements Editable {
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package com.panda912.defensor.internal;
2+
3+
import android.text.Editable;
4+
5+
import com.panda912.defensor.CrashDefensor;
6+
import com.panda912.defensor.ErrorCode;
7+
8+
/**
9+
* Created by panda on 2022/2/22 15:22
10+
*/
11+
public class EditableDefensor {
12+
13+
public static Editable replace(Editable editable, int st, int en, CharSequence source, int start, int end) {
14+
try {
15+
return editable.replace(st, en, source, start, end);
16+
} catch (IndexOutOfBoundsException e) {
17+
CrashDefensor.onCrash(ErrorCode.IndexOutOfBoundsException, "Editable.replace(int st, int en, CharSequence source, int start, int end) throw IndexOutOfBoundsException", e);
18+
}
19+
return editable;
20+
}
21+
22+
public static Editable replace(Editable editable, int st, int en, CharSequence text) {
23+
try {
24+
return editable.replace(st, en, text);
25+
} catch (IndexOutOfBoundsException e) {
26+
CrashDefensor.onCrash(ErrorCode.IndexOutOfBoundsException, "Editable.replace(int st, int en, CharSequence text) throw IndexOutOfBoundsException", e);
27+
}
28+
return editable;
29+
}
30+
31+
public static Editable insert(Editable editable, int where, CharSequence text, int start, int end) {
32+
try {
33+
return editable.insert(where, text, start, end);
34+
} catch (IndexOutOfBoundsException e) {
35+
CrashDefensor.onCrash(ErrorCode.IndexOutOfBoundsException, "Editable.insert(int where, CharSequence text, int start, int end) throw IndexOutOfBoundsException", e);
36+
}
37+
return editable;
38+
}
39+
40+
public static Editable insert(Editable editable, int where, CharSequence text) {
41+
try {
42+
return editable.insert(where, text);
43+
} catch (IndexOutOfBoundsException e) {
44+
CrashDefensor.onCrash(ErrorCode.IndexOutOfBoundsException, "Editable.insert(int where, CharSequence text) throw IndexOutOfBoundsException", e);
45+
}
46+
return editable;
47+
}
48+
49+
public static Editable delete(Editable editable, int st, int en) {
50+
try {
51+
return editable.delete(st, en);
52+
} catch (IndexOutOfBoundsException e) {
53+
CrashDefensor.onCrash(ErrorCode.IndexOutOfBoundsException, "Editable.delete(int st, int en) throw IndexOutOfBoundsException", e);
54+
}
55+
return editable;
56+
}
57+
58+
public static Editable append(Editable editable, CharSequence text) {
59+
try {
60+
return editable.append(text);
61+
} catch (IndexOutOfBoundsException e) {
62+
CrashDefensor.onCrash(ErrorCode.IndexOutOfBoundsException, "Editable.append(CharSequence text) throw IndexOutOfBoundsException", e);
63+
}
64+
return editable;
65+
}
66+
67+
public static Editable append(Editable editable, CharSequence text, int start, int end) {
68+
try {
69+
return editable.append(text, start, end);
70+
} catch (IndexOutOfBoundsException e) {
71+
CrashDefensor.onCrash(ErrorCode.IndexOutOfBoundsException, "Editable.append(CharSequence text, int start, int end) throw IndexOutOfBoundsException", e);
72+
}
73+
return editable;
74+
}
75+
76+
public static Editable append(Editable editable, char text) {
77+
try {
78+
return editable.append(text);
79+
} catch (IndexOutOfBoundsException e) {
80+
CrashDefensor.onCrash(ErrorCode.IndexOutOfBoundsException, "Editable.append(char text) throw IndexOutOfBoundsException", e);
81+
}
82+
return editable;
83+
}
84+
85+
}

0 commit comments

Comments
 (0)