「作者の最初のシステムズ言語はRustであり、CにはC23標準になるまでプリミティブなboolean型がなかったことを指摘しています。それ以前は、プログラマーは<stdbool.h>をインクルードしてtrueとfalseのマクロを得ていました。これらのマクロは単に整数定数の1と0に展開されます。つまり、Rustの組み込みboolとは異なり、当時のCコードではbooleanを普通の整数として扱っていたため、trueとfalseがリテラルとして区別される言語から来た開発者には驚きとなる事実です。さらに、記事ではC23でbooleanが真の言語プリミティブとなった後でも、古いコンパイラではフル互換性のためにまだヘッダーが必要であることを観察しています。

「Cの文字列は長さプリフィックスではなくヌル終端です。Cの文字列は最初の文字へのポインタに過ぎず、その長さは終端を示すゼロバイト(⟨0⟩)をスキャンして求められます。したがって、あらゆる文字列はその終端用に余分な1バイトを確保しなければならず、これを忘れたり、割り当てを誤ると、strcpyやstrlenなどの関数が意図したバッファを超えて読み込む際にバッファオーバーランが発生します。この問題の頻度は、画像(IMG-001)に示されるバッファーオーバーフローとout-of-bounds writeの脆弱性カテゴリーにも表れています。記事では、len+1バイトを明示的に確保し、インデックスlenに終端文字を書く手動の文字列反転ルーチンを例示し、これによりポインタと長さをともに持つRustの&strがこうした帳尻合わせを不要にすることを示しています。

Bar chart showing vulnerability categories with buffer overflow and out-of-bounds writes highlighted
Buffer overflow and out-of-bounds writes are common C vulnerability categoriesbd103.dev

This image illustrates the prevalence of buffer overflow and out-of-bounds write vulnerabilities, which relate to C's manual memory management and lack of bounds checking discussed in the article.

「Cの整数型は固定幅ではなく、その正確なサイズはターゲットプラットフォームに依存します。たとえば、longはUnixでは64ビットですがWindowsでは32ビットであり、intは両プラットフォームで一律32ビットですが、標準では少なくとも16ビットであることしか保証されません。この可搬性の問題により、開発者が<stdint.h>の固定幅エイリアス(uint32_t、int64_tなど)を使用しないと、移植可能なコードはもろくなります。さらに、記事ではCのエラーハンドリングが最小限であることにも言及しています。多くの関数は失敗を-1やヌルポインターなどのセンチネル値で返し、errnoにスレッドローカルコードが格納されることがありますが、呼び出し側に結果をチェックさせる言語レベルの仕組みはありません。mallocの戻り値をテストし忘れると、ヌルポインターの参照によりセグメンテーションフォルトが発生し、これがCにおいて安全の責任がプログラマーにあることを示しています。