iT邦幫忙

0

Day 13:整數溢位/下溢(原理與影響)

  • 分享至 

  • xImage
  •  

看起來最基本的「算術」在智能合約也會變成致命漏洞。
今天我們把整數溢位(overflow)與下溢(underflow)拆解清楚:為什麼會發生、會造成什麼後果,以及如何用最簡單的方法防範。

  1. 整數溢位是當數字超出該資料型別可表示的上限時發生(例如 uint8 的最大值 255),會「繞回」到 0 或低值。
  2. 在合約中,溢位可被利用來偽造餘額、製造額外代幣或繞過條件。
  3. 防範方法:使用 Solidity ≥0.8(內建檢查)或在舊版使用 SafeMath,並對邊界條件寫測試。

🔹 原理簡述(為何會發生)

電腦的整數是有限位元表示(例如 8-bit、256-bit)。
以 uint8 為例,它能表示 0 到 255(共 256 個值)。
若執行 255 + 1,在無檢查的情況下會「溢位」成 0(繞回去)。這種行為稱為 wrap-around。

uint8 max = 255
max + 1 => 0 (溢位)

在合約邏輯中,若假定「某人餘額 > 0」就能提領,但駭客能用溢位操作讓餘額不正確,導致資金錯誤發放。

🔹 實際影響(為何很危險)
• 代幣超發:錯誤的加法使供給數量超出預期。
• 檢查繞過:條件 require(balance + amount >= balance) 在溢位下可能仍成立或失效。
• 會財務邏輯錯亂:分配、累計、利息計算等皆會受影響。

歷史上不乏因溢位導致的資金損失或合約失效案例,教訓是「永遠不要信任沒有邊界檢查的數值運算」。

🔹 Vulnerable 範例
// vulnerable pseudo-code (pre-Solidity 0.8)
uint8 public count;

function increment() public {
count = count + 1; // 若 count == 255 時,會溢位回 0
}
在某些 Token 或計數場景中,攻擊者可反覆觸發或操控輸入導致溢位行為被利用。

🔹 Fixed 範例(Solidity >=0.8,自動檢查)
// Solidity ^0.8.0 內建溢位檢查,會在溢位時 revert
pragma solidity ^0.8.0;
uint8 public count;

function increment() public {
count = count + 1; // 若溢位將自動 revert,避免不正確狀態
}

或者使用 SafeMath
// For older solidity versions
using SafeMath for uint256;
uint256 public total;

function add(uint256 x) public {
total = total.add(x); // SafeMath 會 revert on overflow
}

🔹 邊界測試範例(測試要點)
• 嘗試把變數設成最大值然後再 +1、-1,觀察是否 revert 或 wrap-around。
• 對 token 轉帳、minting、burning 的流程做極端測試(最大 supply、0 值、負值邏輯)。
• 實作 fuzz 測試或單元測試,包含隨機大數與邊界值。

🔹 防禦策略總結
• 儘量使用 Solidity 0.8 以上(內建溢位檢查)。
• 對舊專案或使用舊編譯器的合約,引入 SafeMath。
• 在設計合約時盡量使用 uint256 表示金額與累計(減少溢位風險),並做好邊界條件檢查。
• 編寫單元與 fuzz 測試覆蓋邊界條件。

整數溢位看似是程式語言的基本問題,但在涉及金錢的智能合約世界,這類基礎錯誤的後果可能是致命的。好消息是:大多數溢位問題都可以以相對簡單的方式避免——升級編譯器、使用成熟函式庫、並對邊界情況進行測試。把這些習慣建立起來,就能擋掉很多初級且危險的漏洞。


圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言