From 395006a90aa7c5030acb8478a12ff20282a9c42c Mon Sep 17 00:00:00 2001 From: kdletters Date: Sat, 20 Jun 2026 04:04:46 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A1=A5=E9=BD=90=E7=A7=BB=E5=8A=A8=E5=A3=B3?= =?UTF-8?q?=E5=9B=BE=E7=89=87=E5=AF=BC=E5=87=BA=E7=A9=BA=E5=86=85=E5=AE=B9?= =?UTF-8?q?=E8=BE=B9=E7=95=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 移动壳图片导出拒绝零字节 base64 内容 移动壳 HostBridge 测试覆盖图片导出空内容拒绝 移动壳配置检查反查图片导出字节边界 --- apps/mobile-shell/scripts/check-config.mjs | 9 +++++++++ apps/mobile-shell/src/host-bridge/bridge.test.ts | 12 +++++++++++- apps/mobile-shell/src/host-bridge/files.ts | 2 +- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/apps/mobile-shell/scripts/check-config.mjs b/apps/mobile-shell/scripts/check-config.mjs index 92026970f..77ee460cd 100644 --- a/apps/mobile-shell/scripts/check-config.mjs +++ b/apps/mobile-shell/scripts/check-config.mjs @@ -1700,6 +1700,15 @@ assertMobileDocumentPickerBoundary( 'MOBILE_AUDIO_DOCUMENT_PICKER_TYPES', ); +const exportImageFileBody = extractFunctionBody(filesSource, 'exportImageFile'); +if ( + !exportImageFileBody.includes( + 'bytes <= 0 || bytes > HOST_BRIDGE_EXPORT_IMAGE_MAX_BYTES', + ) +) { + throw new Error('mobile shell image export must reject empty and oversized bytes'); +} + for (const [wrapperName, fileCall] of [ ['exportMobileHostBridgeTextFile', 'ok(request, await exportTextFile(request.payload))'], ['importMobileHostBridgeTextFile', 'ok(request, await importTextFile())'], diff --git a/apps/mobile-shell/src/host-bridge/bridge.test.ts b/apps/mobile-shell/src/host-bridge/bridge.test.ts index 8d724606f..7b64f608b 100644 --- a/apps/mobile-shell/src/host-bridge/bridge.test.ts +++ b/apps/mobile-shell/src/host-bridge/bridge.test.ts @@ -1377,7 +1377,7 @@ describe('handleMobileHostBridgeMessage', () => { }); }); - test('file.exportImage 拒绝非图片 MIME 与超限内容', async () => { + test('file.exportImage 拒绝非图片 MIME、空内容与超限内容', async () => { const unsupportedMime = await send( request('file.exportImage', { fileName: '分享卡.txt', @@ -1388,6 +1388,16 @@ describe('handleMobileHostBridgeMessage', () => { expect(expectFailed(unsupportedMime).error.code).toBe('invalid_request'); + const emptyImage = await send( + request('file.exportImage', { + fileName: '分享卡.png', + base64Data: '', + mimeType: 'image/png', + }), + ); + + expect(expectFailed(emptyImage).error.code).toBe('invalid_request'); + const oversized = await send( request('file.exportImage', { fileName: '分享卡.png', diff --git a/apps/mobile-shell/src/host-bridge/files.ts b/apps/mobile-shell/src/host-bridge/files.ts index d448308bf..a49241f7a 100644 --- a/apps/mobile-shell/src/host-bridge/files.ts +++ b/apps/mobile-shell/src/host-bridge/files.ts @@ -514,7 +514,7 @@ export async function exportImageFile( throw invalidRequest('base64Data is required'); } const bytes = base64DecodedByteLength(base64Data); - if (bytes > HOST_BRIDGE_EXPORT_IMAGE_MAX_BYTES) { + if (bytes <= 0 || bytes > HOST_BRIDGE_EXPORT_IMAGE_MAX_BYTES) { throw invalidRequest('image exceeds file export size limit'); } ensureImageBytesMatchMimeType(base64Data, mimeType as HostBridgeImageMimeType);