Verify all approved voice PCM directly in actual APK with negative controls
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
"""Actual inspector rejects missing serialized clips and changed PCM in QA-only APK copies."""
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import sys
|
||||
import zipfile
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--apk', required=True)
|
||||
parser.add_argument('--project', required=True)
|
||||
parser.add_argument('--evidence', required=True)
|
||||
args = parser.parse_args()
|
||||
apk, evidence = Path(args.apk), Path(args.evidence)
|
||||
evidence.mkdir(parents=True, exist_ok=True)
|
||||
inspector = Path(__file__).with_name('inspect-voice-payload.py')
|
||||
checks = []
|
||||
for kind in ('positive', 'missing-clips', 'altered-pcm'):
|
||||
case = evidence / kind
|
||||
case.mkdir(exist_ok=True)
|
||||
target = apk if kind == 'positive' else case / 'qa-mutated.apk'
|
||||
mutation = None
|
||||
if kind != 'positive':
|
||||
with zipfile.ZipFile(apk) as source, zipfile.ZipFile(target, 'w') as output:
|
||||
for entry in source.infolist():
|
||||
if not entry.filename.startswith('assets/bin/Data/'):
|
||||
continue
|
||||
if kind == 'missing-clips' and entry.filename.startswith('assets/bin/Data/sharedassets0.assets'):
|
||||
continue
|
||||
data = source.read(entry)
|
||||
if kind == 'altered-pcm' and entry.filename in ('assets/bin/Data/sharedassets0.resource.split0', 'assets/bin/Data/sharedassets0.resource'):
|
||||
data = bytearray(data)
|
||||
offset = 194000 # Inside first known PCM16 AudioClip resource, outside its FSB header.
|
||||
data[offset] ^= 32
|
||||
data = bytes(data)
|
||||
mutation = {'entry': entry.filename, 'offset': offset, 'xor': 32}
|
||||
output.writestr(entry, data)
|
||||
if kind == 'altered-pcm' and mutation is None:
|
||||
raise RuntimeError('Expected actual PCM split resource is absent')
|
||||
command = [sys.executable, '-I', str(inspector), '--apk', str(target), '--project', args.project, '--evidence', str(case)]
|
||||
process = subprocess.run(command, capture_output=True, text=True)
|
||||
(case / 'stdout.log').write_text(process.stdout, encoding='utf-8')
|
||||
(case / 'stderr.log').write_text(process.stderr, encoding='utf-8')
|
||||
record = json.loads((case / 'apk-voice-payload.json').read_text(encoding='utf-8'))
|
||||
expected = kind == 'positive'
|
||||
passed = process.returncode == (0 if expected else 1) and (record['status'] == 'passed') == expected
|
||||
if kind == 'missing-clips':
|
||||
passed = passed and record.get('actualClipCount') == 0
|
||||
if kind == 'altered-pcm':
|
||||
passed = passed and any(not check['passed'] for check in record['checks']) and 'PCM mismatch' in record.get('error', '')
|
||||
checks.append({'case': kind, 'command': command, 'exitCode': process.returncode, 'passed': passed,
|
||||
'mutation': mutation, 'inspectorRecord': record})
|
||||
result = {'originalApkSha256': hashlib.sha256(apk.read_bytes()).hexdigest(), 'scope': 'QA synthetic negative copies only; never installed',
|
||||
'checks': checks, 'passed': all(check['passed'] for check in checks)}
|
||||
(evidence / 'regression.json').write_text(json.dumps(result, indent=2), encoding='utf-8')
|
||||
sys.exit(0 if result['passed'] else 1)
|
||||
Reference in New Issue
Block a user