Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Задокументированные предусловия безопасности

// Copyright 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0

/// ...
///
/// # Safety
///
/// Эта функция легко может вызвать неопределённое поведение. Убедитесь, что:
///
///  - указатель `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: вызывающий код передал ненулевой указатель
        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
  • Предусловия безопасности задокументированы
  • встроенные комментарии о безопасности

Небезопасная функция корректна, когда задокументированы и её предусловия безопасности, и её внутренние небезопасные блоки.

Нужны исправления в main.

  • a не удовлетворяет одному из предусловий copy (данные source должны заканчиваться нулевым байтом внутри своего выделения памяти)
  • Нужен комментарий SAFETY