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

低端设备运行Android OTA签名校验脚本被终止,求分块读取优化方案

问题描述

在低端计算机上运行Android的check_ota_package_signature.py脚本校验OTA更新包签名时,程序意外终止。从运行日志判断,是一次性读取约1.1GB的文件导致内存耗尽。

原代码中引发问题的片段:

with open(package, 'rb') as package_file:
 package_bytes = package_file.read()
length = len(package_bytes)
footer = bytearray(package_bytes[-6:])
signature_start_from_end = (footer[1] << 8) + footer[0]
signature_start = length - signature_start_from_end
comment_len = (footer[5] << 8) + footer[4]
signed_len = length - comment_len - 2

comment_len = (footer[5] << 8) + footer[4]
signed_len = length - comment_len - 2

print('Package length: %d' % (length,))
print('Comment length: %d' % (comment_len,))
print('Signed data length: %d' % (signed_len,))
print('Signature start: %d' % (signature_start,))

use_sha256 = CertUsesSha256(cert)
print('Use SHA-256: %s' % (use_sha256,))

h = sha256() if use_sha256 else sha1()
h.update(package_bytes[:signed_len])

package_digest = h.hexdigest().lower()

程序运行日志:

Package length: 1182903653
Comment length: 1983
Signed data length: 1182901668
Signature start: 1182901688
Use SHA-256: True
Killed

问题根源在于package_file.read()一次性将整个1.1GB文件加载到内存,后续h.update(package_bytes[:signed_len])又复制了近1.1GB的内存块,直接耗尽低端机器的内存。

解决方案

通过分块读取文件计算哈希的方式解决内存不足问题,修改后的代码如下:

# 仅读取文件末尾6字节获取footer和文件总长度,避免加载整个文件
with open(package, 'rb') as package_file:
    package_file.seek(-6, 2)  # 定位到文件末尾前6字节
    footer = bytearray(package_file.read(6))
    package_file.seek(0, 2)  # 定位到文件末尾获取总长度
    length = package_file.tell()

signature_start_from_end = (footer[1] << 8) + footer[0]
signature_start = length - signature_start_from_end
comment_len = (footer[5] << 8) + footer[4]
signed_len = length - comment_len - 2

print('Package length: %d' % (length,))
print('Comment length: %d' % (comment_len,))
print('Signed data length: %d' % (signed_len,))
print('Signature start: %d' % (signature_start,))

use_sha256 = CertUsesSha256(cert)
print('Use SHA-256: %s' % (use_sha256,))

h = sha256() if use_sha256 else sha1()

# 分块读取文件,每次读取64KB(可根据机器内存调整大小)
block_size = 64 * 1024
with open(package, 'rb') as package_file:
    remaining_bytes = signed_len
    while remaining_bytes > 0:
        read_size = min(block_size, remaining_bytes)
        block = package_file.read(read_size)
        if not block:
            break  # 可在此处添加文件读取异常处理
        h.update(block)
        remaining_bytes -= read_size

package_digest = h.hexdigest().lower()

关键修改说明

  • 避免一次性加载整个文件:通过seek定位到文件末尾,仅读取6字节的footer数据,同时获取文件总长度,内存占用极低。
  • 分块计算哈希:每次读取固定大小的块(示例为64KB),逐步更新哈希对象,内存占用仅为单个块的大小,完全适配低端机器的内存限制。
  • 移除冗余内存复制:不再将整个文件内容存入package_bytes变量,也避免了package_bytes[:signed_len]的大内存切片操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 08:10:33