> ## Content Index
> Fetch the complete content index at: https://taiwanding.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Integer Overflow 是什麼？從里程表繞一圈到火箭自毀
- URL: https://taiwanding.com/integer-overflow-shi-shi-mo-cong-li-cheng-biao-rao-yi-quan-dao-huo-jian-zi-hui/
- Published: 2026-07-17T08:42:12.000Z
- Updated: 2026-07-20T07:18:41.000Z
- Author: Kevin Chen
- Tags: #Integer overflow, #白話資安

*這是「白話資安」系列的第二篇。上一篇聊了 Buffer Overflow（資料寫太多，超出原本準備的空間），這篇要講它的表親——Integer Overflow（數字超出範圍）。有趣的是，這兩個漏洞常常手牽手：數字先出事，害程式把空間準備錯，接著就引發上一篇那種溢位。一樣不需要任何基礎，看完你會發現，一個超出可表示範圍的數字，怎麼讓程式準備錯空間、讓火箭失控，還催生了「核彈甘地」這則經典都市傳說。*

---

## 先講一句話：電腦的數字，是有「格數上限」的

你手機的計算機可以算到很大很大的數，所以你可能以為電腦裡的數字沒有上限。但在許多底層程式裡，整數會放在一個「固定寬度的格子」裡——就像舊車的里程表只有六格，最多顯示到 999999。

那如果 999999 再跑一公里呢？這台里程表沒有第七格，於是**翻回 000000**。當一個計算結果超出格子能表示的範圍，接下來會怎樣，其實**取決於語言與型別**：可能像里程表一樣繞回、可能直接報錯、也可能產生「未定義行為」（連程式設計師都無法保證會發生什麼）。這篇我們先從最直觀的「繞回」講起。

## 圖解一：里程表繞一圈

整數溢位：里程表繞回數字加到格子上限後，可能不會繼續變大，而是繞回最小值，就像里程表從 999999 跳回 000000。 加到上限 再加 1 999999 六格全滿 000000 翻回最小值 ＋1 

舊車的里程表只有六格，跑破 999999 之後沒有第七格可以進位，只好從頭數起、翻回 000000。當程式裡的數字型別發生這種繞回時，就叫 Integer Overflow（整數溢位）。光是「數字繞回去」聽起來只是個計算錯誤，但接下來你會看到，當程式**信任了這個出錯的數字**去做決定時，事情就會失控。

## 圖解二：算錯的數字，怎麼變成安全漏洞

這就是 Integer Overflow 和上一篇 Buffer Overflow 手牽手的地方。很多程式在放東西進記憶體之前，會先**算一下「要準備多大的空間」**。如果這個計算被溢位動了手腳、算出一個小到離譜的數字，程式就會準備一個太小的空間——然後你把真正的（很大的）東西塞進去，就滿出來了。

整數溢位引發緩衝區溢位的攻擊鏈使用者輸入巨大的數，讓空間計算溢位成很小的值，程式準備了太小的空間，最後被塞爆。 ① 輸入超大的數 攻擊者故意給 ② 計算溢位 空間算成小值 ③ 空間準備太小 程式信任那個數 ④ 塞爆 溢出去 

用個生活比喻：程式問「要訂幾個便當？我照數量準備桌子」，你輸入一個天文數字，害它算「總共要幾張桌子」時溢位、繞成 0，於是它只擺了一張小桌——但便當還是照原本的天文數字送來，桌子擺不下，全部滿出來。這就接回了上一篇的 Buffer Overflow。

所以 Integer Overflow 本身往往**不是最終目的，而是引信**：它負責讓程式「把空間準備錯」，真正造成破壞的溢位，是它點燃的下一步。不過要補一句——**這是最經典的一條攻擊鏈，但不是唯一結果**。整數溢位也可能直接扭曲金額計算、陣列索引、權限判斷或迴圈次數，各自都能單獨釀成問題。

## 另一個方向：Integer Underflow

繞回不只往上發生，也會往下。有一種格子只存 0 和正數（叫「無號整數」）。當無號整數是 0 再**減 1**，結果會低於它能表示的範圍。若語言或運算模式採用回繞規則，它會變成能表示的**最大值**；例如 8 位元無號整數會從 0 繞到 255。這個方向叫 Integer Underflow。

整數 underflow 與核彈甘地傳說以採回繞規則的 8 位元無號整數為例，從 0 再減 1 會往下繞回成最大值 255。 無號整數的 0 再減 1 0 255 −1 經典都市傳說：核彈甘地 遊戲《文明帝國》裡甘地的侵略性被減到繞回成最大值，和平大師秒變核彈狂人。 

這個 underflow 有個超有名的都市傳說：遊戲《文明帝國》裡，甘地的「侵略性」數值本來設成最低的 1，當系統把它「減 2」時變成 −1——但那個無號格子存不了負數，於是往下繞回成 255，讓和平的甘地瞬間變成全場最好戰、最愛射核彈的狂人。要強調的是，這故事**後來被開發者本人闢謠、其實是虛構的**，但它太完美地演示了 underflow，早已成為工程圈的經典教材。

（技術上還有第三種情況：在明確採用二補數回繞規則的環境中，能存負數的「有號整數」從最大正值再加 1，可能翻成最小負值——「加一個正數，結果反而變負」；但不同語言與設定的處理方式並不相同。）

## 真實事故：Ariane 5 火箭

這不是只出現在教科書裡的理論。1996 年 Ariane 5 的事故鏈中，慣性參考系統嘗試把一個 **64 位元浮點值轉成 16 位元有號整數**。數值超出可表示範圍，未處理的例外使兩套慣性參考系統先後停止。火箭在主引擎點火序列開始約 37 秒、也就是離地約 30 秒後失去導引，隨即急劇偏航並解體，之後自毀機制才被觸發。

注意這個案例的細節——它**不是里程表式的默默繞回**，而是數字超出範圍後觸發例外、導致整個系統停擺的另一種結果（呼應前面說的「接下來會怎樣取決於語言與設計」）。這次事故讓火箭與四枚 Cluster 科學衛星全毀，成了史上最常被引用的軟體 bug 之一。

## 現代程式怎麼防住它？

跟上一篇一樣，現代的工具與語言早就準備了防線。Integer Overflow 的防禦重點是「**在算錯之前就攔下來**」：

三種防止整數溢位的方式設定合理的輸入範圍、使用有檢查的計算、以及轉換型別前先檢查。 限制輸入範圍 先擋掉不合理的 超大／超小值 用有檢查的計算 checked arithmetic： 溢位時回報、不硬算 轉換前先檢查 縮小型別或轉換時 確認值在範圍內 

關於「換個語言就沒事」要講精確一點，別過度樂觀。**Rust** 開發模式下遇到溢位預設會直接 panic 中止，但 release 模式預設是*回繞*，除非另外開檢查；它同時提供 `checked_*`、`wrapping_*`、`saturating_*` 等不同策略讓你明確選擇要哪種行為。**Python** 的整數確實是任意精度、可以長到很大，但仍受記憶體限制，而且一旦你把它轉進固定寬度的型別（例如寫進某個二進位格式），一樣可能出事。所以「用更大的格子」只能**延後**溢位，不能保證根本繞不回去——真正的關鍵，始終是「別讓算錯的數字被下游默默信任」。

## 收尾

把兩篇串起來，記憶體漏洞的一條經典劇本就完整了：

> 攻擊者餵一個超出範圍的數 → 程式算「要準備多少空間」時溢位、繞成一個小數 → 準備了太小的空間 → 真正的資料塞進來、滿出去（Buffer Overflow）→ 蓋掉關鍵資料、接管程式。

Integer Overflow 教會我們一件反直覺的事：**許多底層程式使用的固定寬度整數都有表示上限**，它們住在有大小的格子裡，超出範圍就會出事——可能繞回、可能報錯、可能引發更嚴重的連鎖。而只要有任何一段程式「毫不懷疑地相信」了這個出錯的數字，缺口就開了。

下一篇，我們會走進記憶體漏洞的另一個家族——不是「空間寫太多」，也不是「數字超出範圍」，而是「東西還了、卻又偷偷拿回來用」的 Use After Free。一樣用生活比喻、一樣配圖，敬請期待。