Miri — это инструмент обнаружения неопределенного поведения для Rust. Он может запускать двоичные файлы и наборы тестов грузовых проектов и обнаруживать небезопасный код, который не соответствует требованиям безопасности. Например:
unreachable_unchecked
, вызов copy_nonoverlapping
с перекрывающимися диапазонами,...)bool
, отличное от 0 или 1, или недопустимый дискриминант перечисления) Кроме того, Мири также расскажет вам об утечках памяти: если в конце выполнения все еще выделена память и эта память недоступна из глобальной static
, Мири выдаст ошибку.
Вы можете использовать Miri для эмуляции программ на других целях, например, чтобы гарантировать, что манипуляции с данными на уровне байтов работают правильно как в системах с прямым, так и с прямым порядком байтов. См. перекрестную интерпретацию ниже.
Мири уже обнаружила множество реальных ошибок. Если вы обнаружили ошибку в Мири, мы будем признательны, если вы сообщите нам, и мы добавим ее в список!
По умолчанию Мири обеспечивает полностью детерминированное выполнение и изолирует программу от хост-системы. Некоторые API, которые обычно обращаются к хосту, такие как сбор энтропии для генераторов случайных чисел, переменных среды и часов, заменяются детерминированными «поддельными» реализациями. Вместо этого установите MIRIFLAGS="-Zmiri-disable-isolation"
для доступа к реальным системным API. (В частности, «поддельные» системные API RNG делают Miri непригодным для криптографического использования ! Не создавайте ключи с помощью Miri.)
При этом имейте в виду, что Мири не уловит каждое нарушение спецификации Rust в вашей программе, не в последнюю очередь потому, что такой спецификации не существует. Мири использует свою собственную аппроксимацию того, что такое неопределенное поведение в Rust, а что нет. Насколько нам известно, все неопределенное поведение, которое может повлиять на корректность программы , обнаруживается Мири (по модулю ошибок), но вам следует обратиться к справочнику за официальным определением неопределенного поведения. Miri будет обновлена с помощью компилятора Rust для защиты от UB, как это понимается в текущем компиляторе, но она не дает никаких обещаний относительно будущих версий Rust.
Дополнительные предостережения, о которых следует знать пользователям Miri:
-Zrandomize-layout
, чтобы обнаружить некоторые из этих случаев.)-Zmiri-seed
, но это все равно далеко не исследует все возможные исполнения.--target x86_64-unknown-linux-gnu
чтобы получить лучшую поддержку.SeqCst
, которые фактически не разрешены моделью памяти Rust, и она не может обеспечить все виды поведения, которые возможно наблюдать на реальном оборудовании.Более того, Мири принципиально не может гарантировать работоспособность вашего кода. Рациональность — это свойство никогда не вызывать неопределенного поведения при вызове из произвольного безопасного кода, даже в сочетании с другим звуковым кодом. Напротив, Мири может просто сказать вам, вызывает ли конкретный способ взаимодействия с вашим кодом (например, набор тестов) какое-либо неопределенное поведение при конкретном выполнении (которых может быть много, например, когда параллелизм или другие формы недетерминизма). участвуют). Когда Мири находит UB, ваш код определенно неработоспособен, но когда Мири не находит UB, вам, возможно, просто придется протестировать больше входных данных или больше возможных недетерминированных вариантов.
Устанавливайте Miri на Rust каждую ночь через rustup
:
rustup +nightly component add miri
Все следующие команды предполагают, что Nightly Toolchain закреплен с помощью rustup override set nightly
. Альтернативно используйте cargo +nightly
для каждой из следующих команд.
Теперь вы можете запустить свой проект в Miri:
cargo miri test
.cargo miri run
.При первом запуске Miri она выполнит дополнительную настройку и установит некоторые зависимости. Он попросит вас подтвердить перед установкой чего-либо.
cargo miri run/test
поддерживает те же флаги, что и cargo run/test
. Например, cargo miri test filter
запускает только те тесты, в имени которых содержится filter
.
Вы можете передать флаги Мири через MIRIFLAGS
. Например, MIRIFLAGS="-Zmiri-disable-stacked-borrows" cargo miri run
запускает программу без проверки псевдонимов ссылок.
При компиляции кода через cargo miri
флаг конфигурации cfg(miri)
устанавливается для кода, который будет интерпретироваться под Miri. Вы можете использовать это, чтобы игнорировать тестовые случаи, которые не работают под управлением Miri, потому что они делают то, что Miri не поддерживает:
# [ test ]
# [ cfg_attr ( miri , ignore ) ]
fn does_not_work_on_miri ( ) {
tokio :: run ( futures :: future :: ok :: < _ , ( ) > ( ( ) ) ) ;
}
Невозможно перечислить все бесконечные вещи, которые Мири не может сделать, но интерпретатор явно сообщит вам, когда обнаружит что-то неподдерживаемое:
error: unsupported operation: can't call foreign function: bind
...
= help: this is likely not a bug in the program; it indicates that the program
performed an operation that Miri does not support
Miri может не только запускать двоичный файл или набор тестов для вашего целевого хоста, но также выполнять перекрестную интерпретацию для произвольных внешних целей: cargo miri run --target x86_64-unknown-linux-gnu
запустит вашу программу, как если бы это был Linux. программа, независимо от вашей операционной системы. Это особенно полезно, если вы используете Windows, поскольку цель Linux поддерживается гораздо лучше, чем цели Windows.
Вы также можете использовать это для тестирования платформ со свойствами, отличными от вашей хост-платформы. Например, cargo miri test --target s390x-unknown-linux-gnu
запустит ваш набор тестов на цели с прямым порядком байтов, что полезно для тестирования кода, чувствительного к порядку байтов.
Определенные части выполнения выбираются Мири случайным образом, например, точное распределение базовых адресов сохраняется и чередование одновременно выполняющихся потоков. Иногда может быть полезно изучить несколько различных исполнений, например, чтобы убедиться, что ваш код не зависит от случайного «супервыравнивания» новых выделений, и протестировать различные чередования потоков. Это можно сделать с помощью флага --many-seeds
:
cargo miri test --many-seeds # tries the seeds in 0..64
cargo miri test --many-seeds=0..16
По умолчанию 64 различных начальных числа — это довольно медленно, поэтому вы, вероятно, захотите указать меньший диапазон.
При запуске Miri на CI используйте следующий фрагмент для установки ночной цепочки инструментов с компонентом Miri:
rustup toolchain install nightly --component miri
rustup override set nightly
cargo miri test
Вот пример задания для GitHub Actions:
miri :
name : " Miri "
runs-on : ubuntu-latest
steps :
- uses : actions/checkout@v4
- name : Install Miri
run : |
rustup toolchain install nightly --component miri
rustup override set nightly
cargo miri setup
- name : Test with Miri
run : cargo miri test
Явная cargo miri setup
помогает сохранить чистоту результатов фактического этапа тестирования.
Мири не поддерживает все цели, поддерживаемые Rust. Хорошая новость, однако, заключается в том, что независимо от вашей операционной системы/платформы, с помощью --target
легко запустить код для любой цели!
Следующие цели протестированы на CI и, следовательно, всегда должны работать (в степени, описанной ниже):
s390x-unknown-linux-gnu
поддерживается как наша «предпочтительная цель с прямым порядком байтов».linux
, macos
или windows
Miri обычно работает, но мы не даем никаких обещаний и не проводим тесты для таких целей.solaris
/ illumos
: поддерживается @devnexen. Поддерживает std::{env, thread, sync}
, но не std::fs
.freebsd
: требуется сопровождающий . Поддерживает std::env
и части std::{thread, fs}
, но не std::sync
.android
: требуется сопровождающий . Поддержка очень неполная, но базовый «привет, мир» работает.wasi
: Требуется сопровождающий . Поддержка очень неполная, даже стандартный вывод не работает, но работает пустая main
функция.main
функции.Однако даже для целей, которые мы поддерживаем, степень поддержки доступа к API платформы (например, к файловой системе) различается в зависимости от цели: как правило, цели Linux имеют лучшую поддержку, а цели macOS обычно находятся на одном уровне. Windows поддерживается хуже.
Несмотря на то, что Miri реализует многопоточность Rust, сама по себе является однопоточным интерпретатором. Это означает, что при выполнении cargo miri test
вы, вероятно, увидите резкое увеличение времени, необходимого для запуска всего набора тестов из-за присущего интерпретатору замедления и потери параллелизма.
Вы можете вернуть параллелизм вашего набора тестов, запустив cargo miri nextest run -jN
(обратите внимание, что вам понадобится установленный cargo-nextest
). Это работает, потому что cargo-nextest
собирает список всех тестов, а затем запускает отдельный cargo miri run
для каждого теста. Вам нужно будет указать -j
или --test-threads
; по умолчанию cargo miri nextest run
запускает по одному тесту за раз. Более подробную информацию см. в документации cargo-nextest
Miri.
Примечание. Эта модель «один тест на процесс» означает, что cargo miri test
способен обнаруживать гонки данных, когда два теста соревнуются на общем ресурсе, но cargo miri nextest run
не обнаружит такие гонки.
Примечание. cargo-nextest
не поддерживает документацию, см. nextest-rs/nextest#16.
При использовании приведенных выше инструкций вы можете столкнуться с рядом запутанных ошибок компилятора.
RUST_BACKTRACE=1
, чтобы отобразить обратную трассировку» Вы можете увидеть это, пытаясь заставить Мири отобразить обратную трассировку. По умолчанию Мири не предоставляет программе какую-либо среду, поэтому запуск RUST_BACKTRACE=1 cargo miri test
не даст того, что вы ожидаете.
Чтобы получить обратную трассировку, вам нужно отключить изоляцию с помощью -Zmiri-disable-isolation
:
RUST_BACKTRACE=1 MIRIFLAGS= " -Zmiri-disable-isolation " cargo miri test
std
crate, скомпилированный несовместимой версией Rusc» Возможно, вы используете cargo miri
с версией компилятора, отличной от той, которая использовалась для создания пользовательского libstd, который использует Мири, и Мири не смогла этого обнаружить. Попробуйте запустить cargo miri clean
.
-Z
и переменные среды Miri добавляет свой собственный набор флагов -Z
, которые обычно устанавливаются через переменную среды MIRIFLAGS
. Сначала мы документируем наиболее актуальные и наиболее часто используемые флаги:
-Zmiri-address-reuse-rate=
изменяет вероятность того, что освобожденное нестековое выделение будет добавлено в пул для повторного использования адреса, а также вероятность того, что новое нестековое выделение будет взято из пула. Выделения стека никогда не добавляются в пул и не удаляются из него. Значение по умолчанию — 0.5
.-Zmiri-address-reuse-cross-thread-rate=
изменяет вероятность того, что при выделении, которое пытается повторно использовать ранее освобожденный блок памяти, будут также учитываться блоки, освобожденные другими потоками . Значение по умолчанию — 0.1
, что означает, что по умолчанию в 90% случаев попытки повторного использования адреса будут учитываться только адреса из одного и того же потока. Повторное использование адреса из другого потока вызывает синхронизацию между этими потоками, что может маскировать гонки данных и слабые ошибки памяти.-Zmiri-compare-exchange-weak-failure-rate=
изменяет частоту неудач операций compare_exchange_weak
. Значение по умолчанию — 0.8
(поэтому 4 из 5 слабых операций завершатся неудачно). Вы можете изменить его на любое значение от 0.0
до 1.0
, где 1.0
означает, что он всегда будет терпеть неудачу, а 0.0
означает, что он никогда не будет терпеть неудачу. Обратите внимание, что установка значения 1.0
, скорее всего, приведет к зависанию, поскольку это означает, что программы, использующие compare_exchange_weak
не смогут работать.-Zmiri-disable-isolation
отключает изоляцию хоста. Как следствие, программа имеет доступ к ресурсам хоста, таким как переменные среды, файловые системы и случайные данные.-Zmiri-disable-leak-backtraces
отключает отчеты об обратных трассировках при утечках памяти. По умолчанию обратная трассировка фиксируется для каждого выделения при его создании, на случай утечки. Это влечет за собой некоторые затраты памяти для хранения данных, которые почти никогда не используются. Этот флаг подразумевается -Zmiri-ignore-leaks
.-Zmiri-env-forward=
пересылает переменную среды var
интерпретируемой программе. Может использоваться несколько раз для пересылки нескольких переменных. Выполнение по-прежнему будет детерминированным, если значение пересылаемых переменных останется прежним. Не имеет эффекта, если установлен -Zmiri-disable-isolation
.-Zmiri-env-set==
устанавливает value
переменной среды var
в интерпретируемой программе. Его можно использовать для передачи переменных среды без необходимости изменения среды хоста. Его можно использовать несколько раз для установки нескольких переменных. Если установлен -Zmiri-disable-isolation
или -Zmiri-env-forward
, значения, установленные с помощью этой опции, будут иметь приоритет над значениями из среды хоста.-Zmiri-ignore-leaks
отключает проверку утечки памяти, а также позволяет некоторым оставшимся потокам существовать при выходе из основного потока.-Zmiri-isolation-error=
настраивает реакцию Мири на операции, требующие доступа к хосту, когда изоляция включена. Поддерживаемые действия — abort
, hide
, warn
и warn-nobacktrace
. По умолчанию используется abort
, который останавливает машину. Некоторые (но не все) операции также поддерживают продолжение выполнения с возвратом в программу ошибки «отказано в доступе». warn
печатает полную обратную трассировку каждый раз, когда это происходит; warn-nobacktrace
менее подробный и отображается не чаще одного раза за операцию. hide
полностью скрывает предупреждение.-Zmiri-num-cpus
указывает количество доступных процессоров, о которых должна сообщить miri. По умолчанию количество доступных процессоров равно 1
. Обратите внимание, что этот флаг никак не влияет на то, как miri обрабатывает потоки.-Zmiri-permissive-provenance
отключает предупреждение о приведении целого числа к указателю и ptr::with_exposed_provenance
. Это обязательно пропустит некоторые ошибки, поскольку эти операции не могут быть эффективно и точно реализованы в дезинфицирующем средстве, но будут пропущены только ошибки, касающиеся памяти/указателей, на которые распространяются эти операции.-Zmiri-preemption-rate
настраивает вероятность того, что в конце базового блока активный поток будет вытеснен. Значение по умолчанию — 0.01
(т. е. 1%). Установка значения 0
отключает приоритетное прерывание.-Zmiri-report-progress
заставляет Мири время от времени печатать текущую трассировку стека, чтобы вы могли узнать, что она делает, когда программа просто продолжает работать. Вы можете настроить частоту печати отчета с помощью -Zmiri-report-progress=
, который печатает отчет каждые N базовых блоков.-Zmiri-seed=
настраивает начальное число ГСЧ, которое Мири использует для разрешения недетерминизма. Этот RNG используется для выбора базовых адресов для выделения, для определения вытеснения и отказа compare_exchange_weak
, а также для управления буферизацией хранилища для слабой эмуляции памяти. Когда изоляция включена (по умолчанию), она также используется для эмуляции энтропии системы. Начальное значение по умолчанию — 0. Вы можете увеличить покрытие тестирования, запустив Miri несколько раз с разными начальными значениями.-Zmiri-strict-provenance
включает строгую проверку происхождения в Мири. Это означает, что приведение целого числа к указателю дает результат с «недопустимым» происхождением, т. е. с происхождением, которое нельзя использовать для какого-либо доступа к памяти.-Zmiri-symbolic-alignment-check
делает проверку выравнивания более строгой. По умолчанию выравнивание проверяется путем приведения указателя к целому числу и проверки того, что оно кратно выравниванию. Это может привести к случаям, когда программа проходит проверку выравнивания по чистой случайности, потому что все «оказалось» достаточно выровненным — в этом исполнении UB нет, но в других UB будет. Чтобы избежать таких случаев, проверка символического выравнивания учитывает только запрошенное выравнивание соответствующего выделения и смещение в этом выделении. Это позволяет избежать пропуска таких ошибок, но также приводит к некоторым ложным срабатываниям, когда код выполняет целочисленную арифметику вручную для обеспечения выравнивания. (Метод align_to
из стандартной библиотеки отлично работает в обоих режимах; при символическом выравнивании он заполняет только средний срез, когда выделение гарантирует достаточное выравнивание.)Остальные флаги предназначены только для расширенного использования и, скорее всего, будут изменены или удалены. Некоторые из них являются необоснованными , что означает, что они могут привести к тому, что Мири не сможет обнаружить случаи неопределенного поведения в программе.
-Zmiri-disable-alignment-check
отключает проверку выравнивания указателя, поэтому вы можете сосредоточиться на других ошибках, но это означает, что Мири может пропустить ошибки в вашей программе. Использование этого флага нецелесообразно .-Zmiri-disable-data-race-detector
отключает проверку гонок данных. Использование этого флага нецелесообразно . Это подразумевает -Zmiri-disable-weak-memory-emulation
.-Zmiri-disable-stacked-borrows
отключает проверку экспериментальных правил псевдонимов для отслеживания заимствований (Stacked Borrows и Tree Borrows). Это может ускорить работу Miri, но также означает, что не будет обнаружено никаких нарушений псевдонимов. Использование этого флага недопустимо (но соответствующие правила корректности являются экспериментальными). Более поздние флаги имеют приоритет: отслеживание заимствований можно повторно активировать с помощью -Zmiri-tree-borrows
.-Zmiri-disable-validation
отключает применение инвариантов достоверности, которые применяются по умолчанию. Чаще всего это полезно, чтобы сначала сосредоточиться на других сбоях (например, на доступе за пределами сети). Установка этого флага означает, что Мири может пропустить ошибки в вашей программе. Однако это также может помочь Мири бежать быстрее. Использование этого флага нецелесообразно .-Zmiri-disable-weak-memory-emulation
отключает эмуляцию некоторых эффектов слабой памяти C++11.-Zmiri-native-lib=
— это экспериментальный флаг, обеспечивающий поддержку вызова собственных функций изнутри интерпретатора через FFI. Функции, не предусмотренные этим файлом, по-прежнему выполняются через обычные прокладки Мири. ВНИМАНИЕ : Если указан неверный/неверный файл .so
, это может привести к неопределенному поведению самой Miri! И, конечно же, Мири не может выполнять какие-либо проверки действий, выполняемых нативным кодом. Обратите внимание, что у Miri есть собственная обработка файловых дескрипторов, поэтому, если вы хотите заменить некоторые функции, работающие с файловыми дескрипторами, вам придется заменить их все , иначе два типа файловых дескрипторов будут перепутаны. Это работа в стадии разработки ; в настоящее время поддерживаются только целочисленные аргументы и возвращаемые значения (и нет, приведение указателей/целых чисел для обхода этого ограничения не будет работать; они будут ужасными). Кроме того, пока он работает только на хостах Unix.-Zmiri-measureme=
включает профилирование measureme
для интерпретируемой программы. Это можно использовать, чтобы определить, какие части вашей программы выполняются под Miri медленно. Профиль записывается в файл внутри каталога с именем
и может обрабатываться с помощью инструментов из репозитория https://github.com/rust-lang/measureme.-Zmiri-mute-stdout-stderr
молча игнорирует все записи на stdout и stderr, но сообщает программе, что она действительно записывала. Это полезно, когда вас не интересует фактический вывод программы, а вы хотите видеть только ошибки и предупреждения Мири.-Zmiri-recursive-validation
— это очень экспериментальный флаг, который делает проверку достоверности рекурсивной ниже ссылок.-Zmiri-retag-fields[=]
контролирует, когда рекурсивное присвоение тегов Stacked Borrows происходит в полях. all
означает, что он всегда рекурсивен (по умолчанию и эквивалентен -Zmiri-retag-fields
без явного значения), none
означает, что он никогда не повторяется, scalar
означает, что он рекурсивно работает только для типов, где мы также будем генерировать аннотации noalias
в сгенерированном LLVM IR ( типы передаются как отдельные скаляры или пары скаляров). Установка значения none
некорректна .-Zmiri-provenance-gc=
настраивает частоту запуска сборщика мусора указателя происхождения. По умолчанию поиск и удаление недостижимого источника осуществляется один раз каждые 10000
базовых блоков. Установка значения 0
отключает сборщик мусора, что приводит к взрывному использованию памяти некоторыми программами и/или суперлинейному времени выполнения.-Zmiri-track-alloc-accesses
показывает не только события выделения и освобождения для отслеживаемых выделений, но также операции чтения и записи.-Zmiri-track-alloc-id=,,...
показывает обратную трассировку, когда данные выделения выделяются или освобождаются. Это помогает в отладке утечек памяти и использовании после бесплатных ошибок. Указание этого аргумента несколько раз не перезаписывает предыдущие значения, а добавляет их значения в список. Перечисление идентификатора несколько раз не имеет никакого эффекта.-Zmiri-track-pointer-tag=,,...
показывает обратную трассировку, когда данный тег-указатель создается и когда (если вообще когда-либо) он извлекается из стека заимствований (именно здесь тег становится недействителен, и любое его использование в будущем приведет к ошибке). Это поможет вам выяснить, почему происходит UB и где в вашем коде лучше всего его искать. Указание этого аргумента несколько раз не перезаписывает предыдущие значения, а добавляет их значения в список. Многократное перечисление тега не имеет никакого эффекта.-Zmiri-track-weak-memory-loads
показывает обратную трассировку, когда слабая эмуляция памяти возвращает устаревшее значение из загрузки. Это может помочь диагностировать проблемы, которые исчезают при -Zmiri-disable-weak-memory-emulation
.-Zmiri-tree-borrows
заменяет Stacked Borrows на правила Tree Borrows. Tree Borrows еще более экспериментальна, чем Stacked Borrows. Хотя Tree Borrows по-прежнему хороша в смысле выявления всех нарушений псевдонимов, которые могут использовать текущие версии компилятора, вполне вероятно, что окончательная модель псевдонимов Rust будет более строгой, чем Tree Borrows. Другими словами, если вы используете Tree Borrows, даже если ваш код принят сегодня, в будущем он может быть объявлен UB. В случае с пакетными займами это гораздо менее вероятно.-Zmiri-force-page-size=
переопределяет размер страницы по умолчанию для архитектуры, кратный 1 КБ. 4
является значением по умолчанию для большинства целей. Это значение всегда должно быть степенью 2 и ненулевым.-Zmiri-unique-is-unique
выполняет дополнительные проверки псевдонимов для core::ptr::Unique
, чтобы гарантировать, что теоретически его можно считать noalias
. Этот флаг является экспериментальным и имеет эффект только при использовании с -Zmiri-tree-borrows
. Некоторые встроенные флаги Rusc -Z
также очень актуальны для Мири:
-Zmir-opt-level
контролирует количество выполняемых оптимизаций MIR. Мири переопределяет значение по умолчанию, равное 0
; имейте в виду, что использование любого более высокого уровня может привести к тому, что Мири пропустит ошибки в вашей программе, потому что они были оптимизированы.-Zalways-encode-mir
делает Rusc дамп MIR даже для полностью мономорфных функций. Это необходимо для того, чтобы Мири могла выполнять такие функции, поэтому Мири устанавливает этот флаг по умолчанию.-Zmir-emit-retag
контролирует, создаются ли операторы Retag
. Мири включает это по умолчанию, поскольку это необходимо для многоуровневых и древовидных заимствований.Более того, Мири распознает некоторые переменные среды:
MIRIFLAGS
определяет дополнительные флаги, которые будут переданы Мири.MIRI_LIB_SRC
определяет каталог, в котором Miri ожидает исходные тексты стандартной библиотеки, которую она будет собирать и использовать для интерпретации. Этот каталог должен указывать на подкаталог library
извлечения репозитория rust-lang/rust
.MIRI_SYSROOT
указывает используемый системный корень. При использовании cargo miri test
/ cargo miri run
автоматическая настройка пропускается — устанавливайте это только в том случае, если вы не хотите использовать автоматически созданный sysroot. При вызове cargo miri setup
это указывает, куда будет помещен sysroot.MIRI_NO_STD
гарантирует, что sysroot цели создан без libstd. Это позволяет тестировать и запускать программы no_std. Обычно это не следует использовать ; У Мири есть эвристика для обнаружения нестандартных целей на основе имени цели. Установка этого параметра на цель, которая поддерживает libstd, может привести к запутанным результатам. extern
функции Мири Miri предоставляет некоторые extern
функции, которые программы могут импортировать для доступа к специфичным для Miri функциям. Они объявлены в /tests/utils/miri_extern.rs.
Ожидается, что двоичные файлы, которые не используют стандартную библиотеку, объявят такую функцию, чтобы Мири знала, где она должна начать выполнение:
# [ cfg ( miri ) ]
# [ no_mangle ]
fn miri_start ( argc : isize , argv : * const * const u8 ) -> isize {
// Call the actual start function that your project implements, based on your target's conventions.
}
Если вы хотите внести свой вклад в развитие Мири, отлично! Пожалуйста, ознакомьтесь с нашим руководством по вкладам.
Чтобы получить помощь по запуску Miri, вы можете открыть проблему здесь на GitHub или использовать поток Miri на Rust Zulip.
Этот проект начался в рамках студенческого исследовательского курса @solson в Университете Саскачевана в 2015 году. По этому проекту доступны слайды и отчет. В 2016 году @oli-obk присоединился, чтобы подготовить Мири к использованию в качестве константного оценщика в самом компиляторе Rust (в основном, для const
и static
вещей), заменив старый оценщик, который работал непосредственно с AST. В 2017 году @RalfJung прошел стажировку в Mozilla и начал развивать Miri в направлении инструмента для обнаружения неопределенного поведения, а также использовать Miri как способ изучения последствий различных возможных определений неопределенного поведения в Rust. Перенос движка Miri компанией @oli-obk в компилятор наконец завершился в начале 2018 года. Тем временем, позже в том же году @RalfJung прошел вторую стажировку, продолжая развивать Miri с поддержкой проверки инвариантов базового типа и проверки того, что ссылки используются в соответствии с к их ограничениям на псевдонимы.
Мири уже нашла ряд ошибок в стандартной библиотеке Rust и за ее пределами, некоторые из которых мы собрали здесь. Если Мири помогла вам найти незаметную ошибку UB в вашем коде, мы будем признательны за PR, добавивший ее в список!
Обнаружены явные ошибки:
Debug for vec_deque::Iter
обращающегося к неинициализированной памятиVec::into_iter
выполняет чтение ZST без выравниванияFrom<&[T]> for Rc
создающего недостаточно выровненную ссылкуBTreeMap
создает общую ссылку, указывающую на слишком маленькое выделениеVec::append
создает висячую ссылкуstr
превращает общую ссылку в изменяемуюrand
выполняет чтение без выравниванияposix_memalign
неверным способомgetrandom
вызывает системный вызов getrandom
неверным способомVec
и BTreeMap
происходит утечка памяти в некоторых (панических) условияхbeef
EbrCell
неправильно использует неинициализированную памятьservo_arc
создает висячую общую ссылкуencoding_rs
выполняет арифметику указателя за пределами границVec::from_raw_parts
AtomicPtr
и Box::from_raw_in
ThinVec
crossbeam-epoch
вызывает assume_init
на частично инициализированном MaybeUninit
integer-encoding
разыменовывающее смещенный указательrkyv
создает Box<[u8]>
из перераспределенного распределенияarc-swap
thread::scope
regex
неправильно обрабатывает невыровненные буферы Vec
compare_exchange_weak
в once_cell
vec::IntoIter
Iterator::collect
на местеportable-atomic-util
std::mpsc
(исходный код в перекрестии)Нарушения Stacked Borrows обнаружили, что это, скорее всего, ошибки (но Stacked Borrows в настоящее время является всего лишь экспериментом):
VecDeque::drain
создает перекрывающиеся изменяемые ссылкиBTreeMap
BTreeMap
, создающие изменяемые ссылки, которые перекрываются с общими ссылками.BTreeMap::iter_mut
создание перекрывающихся изменяемых ссылокBTreeMap
с использованием необработанных указателей за пределами их допустимой области памяти.LinkedList
создает перекрывающиеся изменяемые ссылкиVec::push
делает недействительными существующие ссылки в вектореalign_to_mut
нарушает уникальность изменяемых ссылокsized-chunks
создающий псевдонимы изменяемых ссылокString::push_str
делает недействительными существующие ссылки в строкеryu
использует необработанные указатели за пределами их допустимой области памятиEnv
использующий необработанный указатель за пределами допустимой области памятиVecDeque::iter_mut
создает перекрывающиеся изменяемые ссылки<[T]>::copy_within
с использованием кредита после его признания недействительным Лицензировано по любому из
по вашему выбору.
Если вы явно не указали иное, любой вклад, намеренно представленный вами для включения в работу, должен иметь двойную лицензию, как указано выше, без каких-либо дополнительных положений и условий.