文書化された安全性の前提条件

// Copyright 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0
#///
/// ...
///
/// # 安全性
///
/// この関数は簡単に未定義動作を引き起こす可能性があります。以下を満たすことを確認してください:
///
///  - `source` ポインタが null ではなく、ダングリングしていない
///  - `source` データは、そのメモリ割り当て内でヌルバイトで終端している
///  - `source` データは解放されない(そのライフタイム不変条件が保たれる)
///  - `source` データは `isize::MAX` バイト未満である
pub unsafe fn copy(dest: &mut [u8], source: *const u8) {
    let source = {
        let mut len = 0;

        let mut end = source;
        // SAFETY: 呼び出し元が null ではないポインタを提供している
        while unsafe { *end != 0 } {
            len += 1;
            // SAFETY: 呼び出し元が長さ < isize:MAX のデータを提供している
            end = unsafe { end.add(1) };
        }

        // SAFETY: 呼び出し元がライフタイムとエイリアシングの要件を維持している
        unsafe { std::slice::from_raw_parts(source, len + 1) }
    };

    for (dest, src) in dest.iter_mut().zip(source) {
        *dest = *src;
    }
}

fn main() {
    let a = [114, 117, 115, 116].as_ptr();
    let b = &mut [82, 85, 83, 84, 0];

    println!("{}", String::from_utf8_lossy(b));
    unsafe {
        copy(b, a);
    }
    println!("{}", String::from_utf8_lossy(b));
}

以前の反復からの変更点:

  • copy を unsafe としてマーク
  • 安全性の前提条件を文書化
  • インラインの安全性コメント

unsafe 関数は、その安全性の前提条件と内部の unsafe ブロックの両方が文書化されているときに健全です。

main に修正が必要です。

  • acopy の前提条件の 1 つを満たしていません(source` データは、 そのメモリ割り当て内でヌルバイトで終端している)
  • SAFETY コメントが必要