newsence

Printf-Tac-Toe:僅用單次 printf 呼叫實現的井字遊戲

Hacker News·28 天前

本專案展示了一個完全在單次 printf 呼叫中執行的 C 語言井字遊戲實現,利用了 printf 的圖靈完備性。這是為 2020 年 IOCCC 大賽編寫的,透過複雜的格式說明符與記憶體操作來處理遊戲邏輯與畫面渲染。

背景

這篇文章介紹了一個極致的程式設計挑戰:僅使用單次 printf 函式調用,便在 C 語言中實現了完整的井字遊戲(Tic-Tac-Toe)。作者 Carlini 透過濫用 printf 的格式化字串特性,將其轉化為具備圖靈完備性的運算引擎,不僅能處理遊戲邏輯、判斷勝負,甚至能動態生成 scanf 的格式字串來處理使用者輸入。這項作品最初是為 2020 年的國際混淆 C 代碼大賽(IOCCC)所創作,展示了格式化字串在除錯功能之外,隱藏著極為強大的運算潛力。

社群觀點

Hacker News 的討論主要圍繞在 printf 究竟是如何演變成一個具備圖靈完備性的工具,以及這項特性在歷史發展中的偶然性。社群成員對於這種「非預期功能」感到既驚嘆又恐懼,認為格式化字串的威力遠超大多數開發者的想像。討論的核心聚焦於 %n 格式說明符,這是實現運算的關鍵,它能將目前已輸出的字元數寫回記憶體指標中。網友們對此展開了技術考古,試圖釐清 %n 是從何時開始進入標準函式庫的。

根據社群成員對早期 Unix 原始碼(如 PDP-11 組合語言版本)的考據,早期的 Version 7 Research Unix 並未實作 %n 功能。甚至在 4.1BSD 與 System III 的版本中,系統還會將其視為無效的格式說明符並報錯。直到 System V R4 版本中,才發現了符合現代預期的 %n 實作。這顯示了 printf 的運算能力並非設計之初的本意,而是隨著 POSIX 標準的演進與功能擴充,在無意間賦予了它執行任意運算的能力。

此外,社群也討論到這種技術在安全領域的隱憂。雖然 printf 常被戲稱為「唯一的真除錯器」,但這種能繞過控制流完整性(Control-Flow Integrity)的特性,實際上也為格式化字串攻擊提供了理論基礎。有留言指出,這種將記憶體視為二進位陣列並透過邏輯閘(如 OR 和 NOT)進行運算的手法,雖然在競賽中令人讚嘆,但在實際應用中卻是極其危險的漏洞來源。整體而言,社群達成了一種共識:這項作品不僅是程式美學的極致展現,更是對現代軟體複雜性與非預期行為的深刻警示。

延伸閱讀

在討論中,有參與者推薦了 TUHS(The Unix Heritage Society)的原始碼封存庫,這是一個研究早期 Unix 系統演進的重要資源,能幫助開發者追溯如 printf 等基礎函式庫功能的歷史變遷。此外,作者在文中也提到了他早先發表的學術論文《Control-Flow Bending》,該論文深入探討了如何利用 printf 的圖靈完備性來達成控制流劫持,對於想從資安角度理解此技術的讀者極具參考價值。

https://github.com/carlini/printf-tac-toe