You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android 14(targetSdkVersion34)下ZipInputStream解压报错求助

问题原因及解决方案

原因

Android 14(对应targetSdkVersion 34)引入了强制的Zip路径安全校验机制,系统会自动拦截包含绝对路径(如以/开头)或../这类目录遍历字符的Zip条目,防止恶意Zip文件通过路径遍历攻击写入应用沙箱外的目录。而targetSdkVersion 33及更低版本没有这个强制校验逻辑,所以相同代码不会触发错误。

从错误栈里的Invalid zip entry path: /xxx可以明确看出,你的Zip文件中存在以/开头的绝对路径条目,被系统的SafeZipPathValidatorCallback拦截。

修复方案

在处理ZipEntry前,先对条目路径做安全预处理:

  1. 移除路径开头的/,避免绝对路径
  2. 过滤包含../的路径,防止目录遍历
  3. 确保处理后的路径是目标目录下的合法子路径

修改后的代码示例:

fun unzip(
    sourceFile: File, targetDirPath: String,
    onSuccess: (() -> Unit)?, onError: ((msg: String?) -> Unit)?
) {
    try {
        var sumLength: Long = 0
        val zis = ZipInputStream(
            BufferedInputStream(
                FileInputStream(sourceFile)
            )
        )
        zis.use {
            var ze: ZipEntry?
            var count: Int
            val buffer = ByteArray(8192)
            while (zis.nextEntry.also { ze = it } != null) {
                var entryName = ze!!.name
                // 移除开头的斜杠,消除绝对路径
                entryName = entryName.removePrefix("/")
                // 拦截包含目录遍历字符的不安全路径
                if (entryName.contains("../") || entryName.startsWith("../")) {
                    throw IllegalArgumentException("Invalid zip entry path: ${ze!!.name}")
                }
                val file = File(targetDirPath, entryName)
                val dir: File = if (ze!!.isDirectory) file else file.parentFile
                if (!dir.isDirectory && !dir.mkdirs()) {
                    throw FileNotFoundException(
                        "Failed to ensure directory: " +
                                dir.absolutePath
                    )
                }

                if (ze!!.isDirectory) {
                    continue
                }
                val fout = FileOutputStream(file)
                fout.use {
                    while (zis.read(buffer).also { count = it } != -1) {
                        sumLength += count.toLong()
                        fout.write(buffer, 0, count)
                        fout.flush()
                    }
                }
            }
        }
        onSuccess?.invoke()
    } catch (e: Exception) {
        onError?.invoke(e.message)
    }
}

补充说明

这个校验是Android 14针对应用沙箱安全的强化措施,属于系统底层的安全防护逻辑,虽未在解压相关的专项文档中单独说明,但处理Zip文件时始终对路径做安全校验是最佳实践,能避免潜在的安全风险。

内容的提问来源于stack exchange,提问作者Warm Man

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 18:41:12