From da83f4fc30edd1168491f726bb5b1be36938755b Mon Sep 17 00:00:00 2001 From: Jeffery Date: Fri, 26 Jun 2026 14:05:08 +0800 Subject: [PATCH] =?UTF-8?q?fix(calculate-version):=20=E5=BC=B7=E5=8C=96?= =?UTF-8?q?=E7=89=87=E6=AE=B5=E6=88=AA=E6=96=B7=E8=88=87=20repository=20?= =?UTF-8?q?=E9=A9=97=E8=AD=89=E5=81=A5=E5=85=A8=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - releases 改以 Array.from 依字元截斷回應片段,避免拆分多位元組字元造成亂碼,並標記片段內容 - config assertRepository 加入每段長度上限,並將 valid 更名為語義明確的 isRepoFormatValid Co-Authored-By: Claude Opus 4.8 (1M context) --- app/config.js | 8 +++++--- app/releases.js | 6 +++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/app/config.js b/app/config.js index e2ccd7f..3aa85fb 100644 --- a/app/config.js +++ b/app/config.js @@ -58,9 +58,11 @@ function assertHttpUrl(name, value) { // 驗證 repository 為 owner/repo 格式(僅允許字母數字與 . _ -,且拒絕 . 與 .. 路徑穿越段) function assertRepository(name, value) { const parts = value.split('/'); - const valid = parts.length === 2 - && parts.every((part) => /^[A-Za-z0-9._-]+$/.test(part) && part !== '.' && part !== '..'); - if (!valid) { + const isRepoFormatValid = parts.length === 2 + && parts.every((part) => part.length > 0 && part.length <= 100 + && /^[A-Za-z0-9._-]+$/.test(part) + && part !== '.' && part !== '..'); + if (!isRepoFormatValid) { throw new Error(`${name} 格式錯誤,必須為 owner/repo`); } } diff --git a/app/releases.js b/app/releases.js index e057039..3799e93 100644 --- a/app/releases.js +++ b/app/releases.js @@ -63,9 +63,9 @@ async function fetchReleases(baseUrl, options = {}) { try { pageJson = JSON.parse(text); } catch { - // 附上截斷的回傳內容片段,便於除錯回傳格式異常 - const snippet = text.slice(0, 200); - throw new Error(`release API 回傳資料無法解析 (page=${page}): ${snippet}`); + // 以字元(而非 UTF-16 碼元)截斷回傳內容片段,避免拆分多位元組字元造成亂碼 + const contentSnippet = Array.from(text).slice(0, 200).join(''); + throw new Error(`release API 回傳資料無法解析 (page=${page}),回應內容片段:「${contentSnippet}」`); } if (pageJson === null) {