Открытый небезопасный Rust
// Copyright 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0
pub fn copy(dest: &mut [u8], source: *const u8) {
let source = {
let mut len = 0;
let mut end = source;
while unsafe { *end != 0 } {
len += 1;
end = unsafe { end.add(1) };
}
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));
copy(b, a);
println!("{}", String::from_utf8_lossy(b));
}
Функциональность копирования байтов из одного места в другое остаётся прежней.
«Однако теперь нужно вручную создать срез. Для этого сначала надо найти конец данных».
«Поскольку мы работаем с текстом, используем соглашение C о строках с завершающим нулём».
Скомпилируйте код. Убедитесь, что вывод остался прежним.
«Некорректная функция может всё равно правильно работать на каких-то входных данных. То, что ваши тесты проходят, ещё не значит, что функция корректна».
«Кто-нибудь видит проблемы?»
- Читаемость: код трудно быстро просмотреть
- Указатель
sourceможет быть нулевым - Указатель
sourceможет быть висящим, то есть указывать на освобождённую или неинициализированную память sourceможет не заканчиваться нулевым байтом
«Допустим, мы не можем менять сигнатуру функции. Какие улучшения кода можно сделать, чтобы устранить эти проблемы?»
- Нулевой указатель: добавьте проверку на null с ранним возвратом (
if source.is_null() { return; }) - Читаемость: используйте проверенную библиотеку, а не реализуйте поиск первого нулевого байта сами
«Однако некоторые требования безопасности невозможно проверить защитным кодом, а именно:»
- висящий указатель
- отсутствие завершающего нулевого байта
«Как сделать эту функцию корректной?»
- Либо
- Измените тип входного аргумента
sourceна что-то с известной длиной, то есть используйте срез, как в предыдущем примере.
- Измените тип входного аргумента
- Или
- Пометьте функцию как unsafe
- Задокументируйте предусловия безопасности