This commit is contained in:
Horis
2025-05-21 14:29:58 +08:00
parent d4ba1c7f44
commit 7960ed9a06
7 changed files with 85 additions and 13 deletions
+1
View File
@@ -40,6 +40,7 @@ dependencies {
implementation(libs.kotlinx.coroutines.core)
implementation(libs.okhttp)
implementation(libs.androidx.collection)
// def coroutines_version = '1.7.3'
// implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version")
@@ -0,0 +1,41 @@
package com.script.rhino
import androidx.collection.LruCache
import kotlin.math.min
class ClassNameMatcher(classNames: List<String>) {
private val sortedClassNames = classNames.sorted()
private val matchCache = LruCache<String, Boolean>(64)
fun match(className: String): Boolean {
matchCache[className]?.let {
return it
}
val match = matchInternal(className)
matchCache.put(className, match)
return match
}
private fun matchInternal(className: String): Boolean {
val index = sortedClassNames.fastBinarySearch { prefix ->
comparePrefix(className, prefix)
}
if (index >= 0) {
return true
}
val prefix = sortedClassNames.getOrNull(-index - 2) ?: return false
return className.getOrNull(prefix.length) == '.' && className.startsWith(prefix)
}
private fun comparePrefix(className: String, prefix: String): Int {
val len = min(className.length, prefix.length)
for (i in 0 ..< len) {
val c1 = className[i]
val c2 = prefix[i]
if (c1 != c2) return c2 - c1
}
return prefix.length - className.length
}
}
@@ -0,0 +1,22 @@
package com.script.rhino
inline fun <T> List<T>.fastBinarySearch(
comparison: (T) -> Int
): Int {
var low = 0
var high = lastIndex
while (low <= high) {
val mid = (low + high).ushr(1) // safe from overflows
val midVal = get(mid)
val cmp = comparison(midVal)
if (cmp < 0)
low = mid + 1
else if (cmp > 0)
high = mid - 1
else
return mid // key found
}
return -(low + 1) // key not found
}
@@ -45,8 +45,8 @@ import java.util.Collections
*/
object RhinoClassShutter : ClassShutter {
private val protectedClassNames by lazy {
hashSetOf(
private val protectedClassNamesMatcher by lazy {
listOf(
"java.lang.Class",
"java.lang.ClassLoader",
"java.net.URLClassLoader",
@@ -113,7 +113,7 @@ object RhinoClassShutter : ClassShutter {
"com.script",
"org.mozilla",
"sun",
).let { Collections.unmodifiableSet(it) }
).let { ClassNameMatcher(it) }
}
private val systemClassProtectedName by lazy {
@@ -181,14 +181,7 @@ object RhinoClassShutter : ClassShutter {
}
override fun visibleToScripts(fullClassName: String): Boolean {
var className = fullClassName
while (className.isNotEmpty()) {
if (protectedClassNames.contains(className)) {
return false
}
className = className.substringBeforeLast(".", "")
}
return true
return !protectedClassNamesMatcher.match(fullClassName)
}
}