Miri es una herramienta de detección de comportamientos indefinidos para Rust. Puede ejecutar binarios y conjuntos de pruebas de proyectos de carga y detectar códigos inseguros que no cumplen con sus requisitos de seguridad. Por ejemplo:
unreachable_unchecked
, llamar copy_nonoverlapping
con rangos superpuestos, ...)bool
que no es 0 o 1, por ejemplo, o un discriminante de enumeración no válido) Además de eso, Miri también le informará sobre las pérdidas de memoria: cuando todavía hay memoria asignada al final de la ejecución y no se puede acceder a esa memoria desde una static
global, Miri generará un error.
Puede utilizar Miri para emular programas en otros objetivos, por ejemplo, para garantizar que la manipulación de datos a nivel de bytes funcione correctamente tanto en sistemas little-endian como big-endian. Véase la interpretación cruzada a continuación.
Miri ya ha descubierto muchos errores del mundo real. Si encontró un error con Miri, le agradeceríamos que nos lo dijera y lo agregaremos a la lista.
De forma predeterminada, Miri garantiza una ejecución totalmente determinista y aísla el programa del sistema host. Algunas API que normalmente accederían al host, como la recopilación de entropía para generadores de números aleatorios, variables de entorno y relojes, se reemplazan por implementaciones "falsas" deterministas. Configure MIRIFLAGS="-Zmiri-disable-isolation"
para acceder a las API del sistema real. (En particular, las API RNG del sistema "falsas" hacen que Miri no sea adecuada para uso criptográfico . No genere claves con Miri).
Dicho todo esto, tenga en cuenta que Miri no detecta todas las violaciones de la especificación Rust en su programa, sobre todo porque no existe tal especificación. Miri usa su propia aproximación de lo que es y no es un comportamiento indefinido en Rust. Hasta donde sabemos, Miri detecta todos los comportamientos indefinidos que tienen el potencial de afectar la corrección de un programa (errores de módulo), pero debe consultar la referencia para obtener la definición oficial de comportamiento indefinido. Miri se actualizará con el compilador Rust para protegerse contra UB tal como lo entiende el compilador actual, pero no hace promesas sobre versiones futuras de Rustc.
Advertencias adicionales que los usuarios de Miri deben tener en cuenta:
-Zrandomize-layout
para detectar algunos de estos casos).-Zmiri-seed
, pero eso aún no explorará todas las ejecuciones posibles.--target x86_64-unknown-linux-gnu
para obtener un mejor soporte.SeqCst
que en realidad no están permitidas por el modelo de memoria Rust, y no puede producir todos los comportamientos posiblemente observables en hardware real.Además, Miri fundamentalmente no puede garantizar que su código sea correcto . La solidez es la propiedad de no causar nunca un comportamiento indefinido cuando se invoca desde un código seguro arbitrario, incluso en combinación con otro código de sonido. Por el contrario, Miri puede simplemente decirle si una forma particular de interactuar con su código (por ejemplo, un conjunto de pruebas) causa algún comportamiento indefinido en una ejecución particular (de las cuales puede haber muchas, por ejemplo, cuando la concurrencia u otras formas de no determinismo están involucrados). Cuando Miri encuentra UB, su código definitivamente no es correcto, pero cuando Miri no encuentra UB, es posible que tenga que probar más entradas o más opciones no deterministas posibles.
Instale Miri en Rust todas las noches mediante rustup
:
rustup +nightly component add miri
Todos los siguientes comandos asumen que la cadena de herramientas nocturna está fijada mediante rustup override set nightly
. Alternativamente, use cargo +nightly
para cada uno de los siguientes comandos.
Ahora puedes ejecutar tu proyecto en Miri:
cargo miri test
.cargo miri run
.La primera vez que ejecute Miri, realizará una configuración adicional e instalará algunas dependencias. Le pedirá confirmación antes de instalar cualquier cosa.
cargo miri run/test
admite exactamente las mismas banderas que cargo run/test
. Por ejemplo, cargo miri test filter
solo ejecuta las pruebas que contienen filter
en su nombre.
Puedes pasar banderas a Miri a través de MIRIFLAGS
. Por ejemplo, MIRIFLAGS="-Zmiri-disable-stacked-borrows" cargo miri run
ejecuta el programa sin comprobar el alias de las referencias.
Al compilar código a través de cargo miri
, el indicador de configuración cfg(miri)
se establece para el código que se interpretará en Miri. Puede usar esto para ignorar los casos de prueba que fallan en Miri porque hacen cosas que Miri no admite:
# [ test ]
# [ cfg_attr ( miri , ignore ) ]
fn does_not_work_on_miri ( ) {
tokio :: run ( futures :: future :: ok :: < _ , ( ) > ( ( ) ) ) ;
}
No hay forma de enumerar todas las infinitas cosas que Miri no puede hacer, pero el intérprete le dirá explícitamente cuando encuentre algo que no sea compatible:
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 no sólo puede ejecutar un binario o un conjunto de pruebas para su destino host, sino que también puede realizar una interpretación cruzada para objetivos externos arbitrarios: cargo miri run --target x86_64-unknown-linux-gnu
ejecutará su programa como si fuera Linux programa, sin importar su sistema operativo anfitrión. Esto es particularmente útil si utiliza Windows, ya que el destino Linux tiene mucho mejor soporte que los destinos Windows.
También puede utilizar esto para probar plataformas con propiedades diferentes a las de su plataforma anfitriona. Por ejemplo, cargo miri test --target s390x-unknown-linux-gnu
ejecutará su conjunto de pruebas en un objetivo big-endian, lo cual es útil para probar código sensible a endian.
Miri selecciona aleatoriamente ciertas partes de la ejecución, como las asignaciones de direcciones base exactas en las que se almacenan y el entrelazado de subprocesos que se ejecutan simultáneamente. A veces, puede ser útil explorar múltiples ejecuciones diferentes, por ejemplo, para asegurarse de que su código no dependa de una "superalineación" incidental de nuevas asignaciones y para probar diferentes intercalados de subprocesos. Esto se puede hacer con la bandera --many-seeds
:
cargo miri test --many-seeds # tries the seeds in 0..64
cargo miri test --many-seeds=0..16
El valor predeterminado de 64 semillas diferentes es bastante lento, por lo que probablemente quieras especificar un rango más pequeño.
Cuando ejecute Miri en CI, use el siguiente fragmento para instalar una cadena de herramientas nocturna con el componente Miri:
rustup toolchain install nightly --component miri
rustup override set nightly
cargo miri test
Aquí hay un trabajo de ejemplo para 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
La cargo miri setup
ayuda a mantener limpio el resultado del paso de prueba real.
Miri no es compatible con todos los objetivos compatibles con Rust. La buena noticia, sin embargo, es que no importa cuál sea su sistema operativo/plataforma host, es fácil ejecutar código para cualquier objetivo usando --target
.
Los siguientes objetivos se prueban en CI y, por lo tanto, siempre deberían funcionar (en el grado que se documenta a continuación):
s390x-unknown-linux-gnu
es compatible como nuestro "objetivo big-endian preferido".linux
, macos
o windows
, Miri generalmente debería funcionar, pero no hacemos promesas ni realizamos pruebas para dichos objetivos.solaris
/ illumos
: mantenido por @devnexen. Admite std::{env, thread, sync}
, pero no std::fs
.freebsd
: se busca mantenedor . Admite std::env
y partes de std::{thread, fs}
, pero no std::sync
.android
: se busca mantenedor . El soporte es muy incompleto, pero funciona un "hola mundo" básico.wasi
: se busca mantenedor . El soporte es muy incompleto, ni siquiera la salida estándar funciona, pero sí una función main
vacía.main
.Sin embargo, incluso para los objetivos que admitimos, el grado de soporte para acceder a las API de la plataforma (como el sistema de archivos) difiere entre los objetivos: generalmente, los objetivos de Linux tienen el mejor soporte y los objetivos de macOS suelen estar a la par. Windows no es tan compatible.
Aunque implementa subprocesos de Rust, Miri en sí es un intérprete de un solo subproceso. Esto significa que al ejecutar cargo miri test
, probablemente verá un aumento dramático en la cantidad de tiempo que lleva ejecutar todo el conjunto de pruebas debido a la desaceleración inherente del intérprete y la pérdida de paralelismo.
Puede recuperar el paralelismo de su conjunto de pruebas ejecutando cargo miri nextest run -jN
(tenga en cuenta que necesitará tener instalado cargo-nextest
). Esto funciona porque cargo-nextest
recopila una lista de todas las pruebas y luego lanza una cargo miri run
separada para cada prueba. Deberá especificar -j
o --test-threads
; De forma predeterminada, cargo miri nextest run
ejecuta una prueba a la vez. Para obtener más detalles, consulte la documentación de Miri cargo-nextest
.
Nota: Este modelo de una prueba por proceso significa que cargo miri test
puede detectar carreras de datos donde dos pruebas corren en un recurso compartido, pero cargo miri nextest run
no detectará dichas carreras.
Nota: cargo-nextest
no admite pruebas de documentos, consulte nextest-rs/nextest#16
Al utilizar las instrucciones anteriores, puede encontrar una serie de errores de compilación confusos.
RUST_BACKTRACE=1
variable de entorno para mostrar un seguimiento" Es posible que veas esto cuando intentes que Miri muestre un seguimiento. De forma predeterminada, Miri no expone ningún entorno al programa, por lo que ejecutar RUST_BACKTRACE=1 cargo miri test
no hará lo que espera.
Para obtener un seguimiento, debe deshabilitar el aislamiento usando -Zmiri-disable-isolation
:
RUST_BACKTRACE=1 MIRIFLAGS= " -Zmiri-disable-isolation " cargo miri test
std
compilado por una versión incompatible de Rustc" Es posible que esté ejecutando cargo miri
con una versión del compilador diferente a la utilizada para crear el libstd personalizado que usa Miri, y Miri no pudo detectarlo. Intente ejecutar cargo miri clean
.
-Z
y variables de entorno Miri agrega su propio conjunto de indicadores -Z
, que generalmente se configuran mediante la variable de entorno MIRIFLAGS
. Primero documentamos las banderas más relevantes y más utilizadas:
-Zmiri-address-reuse-rate=
cambia la probabilidad de que una asignación liberada que no sea de pila se agregue al grupo para la reutilización de direcciones, y la probabilidad de que se tome una nueva asignación que no sea de pila del grupo. Las asignaciones de pila nunca se agregan ni se eliminan del grupo. El valor predeterminado es 0.5
.-Zmiri-address-reuse-cross-thread-rate=
cambia la probabilidad de que una asignación que intenta reutilizar un bloque de memoria previamente liberado también considere bloques liberados por otros subprocesos . El valor predeterminado es 0.1
, lo que significa que, de forma predeterminada, en el 90% de los casos en los que se intenta reutilizar una dirección, solo se considerarán las direcciones del mismo hilo. Reutilizar una dirección de otro subproceso induce la sincronización entre esos subprocesos, lo que puede enmascarar carreras de datos y errores de memoria débil.-Zmiri-compare-exchange-weak-failure-rate=
cambia la tasa de error de las operaciones compare_exchange_weak
. El valor predeterminado es 0.8
(por lo que 4 de cada 5 operaciones débiles fallarán). Puede cambiarlo a cualquier valor entre 0.0
y 1.0
, donde 1.0
significa que siempre fallará y 0.0
significa que nunca fallará. Tenga en cuenta que configurarlo en 1.0
probablemente causará bloqueos, ya que significa que los programas que usan compare_exchange_weak
no pueden progresar.-Zmiri-disable-isolation
deshabilita el aislamiento del host. Como consecuencia, el programa tiene acceso a recursos del host como variables de entorno, sistemas de archivos y aleatoriedad.-Zmiri-disable-leak-backtraces
deshabilita los informes de seguimiento de pérdidas de memoria. De forma predeterminada, se captura un seguimiento de cada asignación cuando se crea, en caso de que se produzca una fuga. Esto genera cierta sobrecarga de memoria para almacenar datos que casi nunca se utilizan. Esta bandera está implícita en -Zmiri-ignore-leaks
.-Zmiri-env-forward=
reenvía la variable de entorno var
al programa interpretado. Se puede utilizar varias veces para reenviar varias variables. La ejecución seguirá siendo determinista si el valor de las variables enviadas permanece igual. No tiene ningún efecto si se establece -Zmiri-disable-isolation
.-Zmiri-env-set==
establece la variable de entorno var
en value
en el programa interpretado. Se puede utilizar para pasar variables de entorno sin necesidad de alterar el entorno del host. Se puede utilizar varias veces para establecer varias variables. Si se establece -Zmiri-disable-isolation
o -Zmiri-env-forward
, los valores establecidos con esta opción tendrán prioridad sobre los valores del entorno host.-Zmiri-ignore-leaks
desactiva el verificador de pérdidas de memoria y también permite que existan algunos subprocesos restantes cuando sale el subproceso principal.-Zmiri-isolation-error=
configura la respuesta de Miri a las operaciones que requieren acceso al host mientras el aislamiento está habilitado. abort
, hide
, warn
y warn-nobacktrace
son las acciones admitidas. El valor predeterminado es abort
, lo que detiene la máquina. Algunas operaciones (pero no todas) también admiten la ejecución continua con un error de "permiso denegado" que se devuelve al programa. warn
imprime un seguimiento completo cada vez que esto sucede; warn-nobacktrace
es menos detallado y se muestra como máximo una vez por operación. hide
oculta la advertencia por completo.-Zmiri-num-cpus
indica la cantidad de CPU disponibles que miri informará. De forma predeterminada, la cantidad de CPU disponibles es 1
. Tenga en cuenta que esta bandera no afecta la forma en que Miri maneja los subprocesos de ninguna manera.-Zmiri-permissive-provenance
deshabilita la advertencia para conversiones de entero a puntero y ptr::with_exposed_provenance
. Esto necesariamente omitirá algunos errores, ya que esas operaciones no se pueden implementar de manera eficiente y precisa en un desinfectante, pero solo omitirá errores que afectan a la memoria/punteros que están sujetos a estas operaciones.-Zmiri-preemption-rate
configura la probabilidad de que al final de un bloque básico, el hilo activo sea reemplazado. El valor predeterminado es 0.01
(es decir, 1%). Establecer esto en 0
desactiva la preferencia.-Zmiri-report-progress
hace que Miri imprima el seguimiento de la pila actual de vez en cuando, para que puedas saber qué está haciendo cuando un programa sigue ejecutándose. Puede personalizar la frecuencia con la que se imprime el informe mediante -Zmiri-report-progress=
, que imprime el informe cada N bloques básicos.-Zmiri-seed=
configura la semilla del RNG que Miri usa para resolver el no determinismo. Este RNG se utiliza para seleccionar direcciones base para asignaciones, determinar la preferencia y el fallo de compare_exchange_weak
y controlar el almacenamiento en búfer para una emulación de memoria débil. Cuando el aislamiento está habilitado (el valor predeterminado), esto también se usa para emular la entropía del sistema. La semilla predeterminada es 0. Puede aumentar la cobertura de la prueba ejecutando Miri varias veces con diferentes semillas.-Zmiri-strict-provenance
permite una verificación estricta de procedencia en Miri. Esto significa que convertir un número entero en un puntero produce un resultado con procedencia "no válida", es decir, con procedencia que no se puede utilizar para ningún acceso a la memoria.-Zmiri-symbolic-alignment-check
hace que la verificación de alineación sea más estricta. De forma predeterminada, la alineación se verifica convirtiendo el puntero en un número entero y asegurándose de que sea un múltiplo de la alineación. Esto puede llevar a casos en los que un programa pasa la verificación de alineación por pura casualidad, porque las cosas "resultaron estar" suficientemente alineadas: no hay UB en esta ejecución, pero sí en otras. Para evitar tales casos, la verificación de alineación simbólica solo tiene en cuenta la alineación solicitada de la asignación relevante y el desplazamiento en esa asignación. Esto evita pasar por alto dichos errores, pero también genera algunos falsos positivos cuando el código realiza aritmética entera manual para garantizar la alineación. (El método align_to
de la biblioteca estándar funciona bien en ambos modos; bajo alineación simbólica solo llena el segmento medio cuando la asignación garantiza una alineación suficiente).Las banderas restantes son solo para uso avanzado y es más probable que cambien o se eliminen. Algunos de estos son incorrectos , lo que significa que pueden hacer que Miri no pueda detectar casos de comportamiento indefinido en un programa.
-Zmiri-disable-alignment-check
desactiva la verificación de la alineación del puntero, por lo que puede concentrarse en otras fallas, pero significa que Miri puede pasar por alto errores en su programa. Usar esta bandera no es correcto .-Zmiri-disable-data-race-detector
desactiva la comprobación de carreras de datos. Usar esta bandera no es correcto . Esto implica -Zmiri-disable-weak-memory-emulation
.-Zmiri-disable-stacked-borrows
desactiva la verificación de las reglas de alias experimentales para rastrear los préstamos (Préstamos apilados y Préstamos de árbol). Esto puede hacer que Miri se ejecute más rápido, pero también significa que no se detectarán violaciones de alias. Usar esta bandera no es correcto (pero las reglas de solidez afectadas son experimentales). Las marcas posteriores tienen prioridad: el seguimiento de préstamos se puede reactivar mediante -Zmiri-tree-borrows
.-Zmiri-disable-validation
deshabilita la aplicación de invariantes de validez, que se aplican de forma predeterminada. Esto resulta especialmente útil para centrarse primero en otros fallos (como los accesos fuera de límites). Establecer esta bandera significa que Miri puede pasar por alto errores en su programa. Sin embargo, esto también puede ayudar a que Miri corra más rápido. Usar esta bandera no es correcto .-Zmiri-disable-weak-memory-emulation
deshabilita la emulación de algunos efectos de memoria débil de C++11.-Zmiri-native-lib=
es un indicador experimental para brindar soporte para llamar a funciones nativas desde el interior del intérprete a través de FFI. Las funciones que no proporciona ese archivo aún se ejecutan a través de las correcciones habituales de Miri. ADVERTENCIA : Si se especifica un archivo .so
no válido/incorrecto, esto puede provocar un comportamiento indefinido en Miri. Y, por supuesto, Miri no puede realizar ninguna verificación de las acciones realizadas por el código nativo. Tenga en cuenta que Miri tiene su propio manejo de descriptores de archivos, por lo que si desea reemplazar algunas funciones que funcionan en descriptores de archivos, tendrá que reemplazarlas todas , o los dos tipos de descriptores de archivos se mezclarán. Este es un trabajo en progreso ; actualmente, solo se admiten argumentos enteros y valores de retorno (y no, las conversiones de puntero/entero para solucionar esta limitación no funcionarán; fallarán terriblemente). Además, por ahora sólo funciona en hosts Unix.-Zmiri-measureme=
habilita el perfilado measureme
para el programa interpretado. Esto se puede utilizar para encontrar qué partes de su programa se ejecutan lentamente en Miri. El perfil se escribe en un archivo dentro de un directorio llamado
y se puede procesar utilizando las herramientas del repositorio https://github.com/rust-lang/measureme.-Zmiri-mute-stdout-stderr
ignora silenciosamente todas las escrituras en stdout y stderr, pero informa al programa que realmente escribió. Esto es útil cuando no está interesado en el resultado real del programa, sino que sólo desea ver los errores y advertencias de Miri.-Zmiri-recursive-validation
es un indicador altamente experimental que hace que la verificación de validez sea recurrente debajo de las referencias.-Zmiri-retag-fields[=]
controla cuándo los préstamos apilados vuelven a etiquetar recursiones en campos. all
significa que siempre se repite (el valor predeterminado y equivalente a -Zmiri-retag-fields
sin un valor explícito), none
significa que nunca se repite, scalar
significa que solo se repite para tipos en los que también emitiríamos anotaciones noalias
en el LLVM IR generado ( tipos pasados como escalares individuales o pares de escalares). Establecer esto en none
no es correcto .-Zmiri-provenance-gc=
configura la frecuencia con la que se ejecuta el recolector de basura de procedencia del puntero. El valor predeterminado es buscar y eliminar procedencias inalcanzables una vez cada 10000
bloques básicos. Establecer esto en 0
deshabilita el recolector de basura, lo que provoca que algunos programas tengan un uso explosivo de la memoria y/o un tiempo de ejecución superlineal.-Zmiri-track-alloc-accesses
muestra no solo la asignación y los eventos gratuitos para las asignaciones rastreadas, sino también las lecturas y escrituras.-Zmiri-track-alloc-id=,,...
muestra un seguimiento cuando las asignaciones dadas se asignan o liberan. Esto ayuda a depurar pérdidas de memoria y a utilizarlo después de eliminar errores. Especificar este argumento varias veces no sobrescribe los valores anteriores, sino que agrega sus valores a la lista. Incluir una identificación varias veces no tiene ningún efecto.-Zmiri-track-pointer-tag=,,...
muestra un seguimiento cuando se crea una etiqueta de puntero determinada y cuando (si alguna vez) se extrae de una pila de préstamo (que es donde la etiqueta se convierte no es válido y cualquier uso futuro del mismo generará errores). Esto le ayuda a descubrir por qué ocurre UB y en qué parte de su código sería un buen lugar para buscarlo. Especificar este argumento varias veces no sobrescribe los valores anteriores, sino que agrega sus valores a la lista. Incluir una etiqueta varias veces no tiene ningún efecto.-Zmiri-track-weak-memory-loads
muestra un seguimiento cuando la emulación de memoria débil devuelve un valor desactualizado de una carga. Esto puede ayudar a diagnosticar problemas que desaparecen con -Zmiri-disable-weak-memory-emulation
.-Zmiri-tree-borrows
reemplaza los Stacked Borrows con las reglas de Tree Borrows. Tree Borrows es incluso más experimental que Stacked Borrows. Si bien Tree Borrows sigue siendo sólido en el sentido de detectar todas las violaciones de alias que las versiones actuales del compilador podrían explotar, es probable que el modelo final de alias de Rust sea más estricto que Tree Borrows. En otras palabras, si utiliza Tree Borrows, incluso si su código se acepta hoy, es posible que se declare UB en el futuro. Esto es mucho menos probable con Stacked Borrows.-Zmiri-force-page-size=
anula el tamaño de página predeterminado para una arquitectura, en múltiplos de 1k. 4
es el valor predeterminado para la mayoría de los objetivos. Este valor siempre debe ser una potencia de 2 y distinto de cero.-Zmiri-unique-is-unique
realiza comprobaciones de alias adicionales para core::ptr::Unique
para garantizar que, en teoría, pueda considerarse noalias
. Esta bandera es experimental y tiene efecto solo cuando se usa con -Zmiri-tree-borrows
. Algunas banderas nativas de rustc -Z
también son muy relevantes para Miri:
-Zmir-opt-level
controla cuántas optimizaciones MIR se realizan. Miri anula el valor predeterminado para que sea 0
; Tenga en cuenta que usar cualquier nivel superior puede hacer que Miri pase por alto errores en su programa porque se optimizaron.-Zalways-encode-mir
hace que Rustc dump MIR incluso para funciones completamente monomórficas. Esto es necesario para que Miri pueda ejecutar dichas funciones, por lo que Miri establece este indicador de forma predeterminada.-Zmir-emit-retag
controla si se emiten declaraciones Retag
. Miri habilita esto de forma predeterminada porque es necesario para préstamos apilados y préstamos de árbol.Además, Miri reconoce algunas variables de entorno:
MIRIFLAGS
define indicadores adicionales que se pasarán a Miri.MIRI_LIB_SRC
define el directorio donde Miri espera las fuentes de la biblioteca estándar que creará y utilizará para la interpretación. Este directorio debe apuntar al subdirectorio de library
de un repositorio rust-lang/rust
.MIRI_SYSROOT
indica el sysroot a utilizar. Cuando se utiliza cargo miri test
/ cargo miri run
, esto omite la configuración automática; configúrelo solo si no desea utilizar el sysroot creado automáticamente. Al invocar cargo miri setup
, esto indica dónde se colocará sysroot.MIRI_NO_STD
se asegura de que el sysroot del objetivo esté construido sin libstd. Esto permite probar y ejecutar programas no_std. Por lo general, esto no debe usarse ; Miri tiene una heurística para detectar objetivos no estándar según el nombre del objetivo. Establecer esto en un objetivo que admita libstd puede generar resultados confusos. extern
de Miri Miri proporciona algunas funciones extern
que los programas pueden importar para acceder a funciones específicas de Miri. Están declarados en /tests/utils/miri_extern.rs.
Se espera que los binarios que no utilizan la biblioteca estándar declaren una función como esta para que Miri sepa dónde se supone que debe iniciar la ejecución:
# [ 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.
}
Si quieres contribuir con Miri, ¡genial! Consulte nuestra guía de contribuciones.
Para obtener ayuda con la ejecución de Miri, puede abrir un problema aquí en GitHub o usar la transmisión de Miri en Rust Zulip.
Este proyecto comenzó como parte de un curso de investigación de pregrado en 2015 impartido por @solson en la Universidad de Saskatchewan. Hay diapositivas y un informe disponibles de ese proyecto. En 2016, @oli-obk se unió para preparar a Miri para eventualmente ser utilizada como evaluadora constante en el propio compilador de Rust (básicamente, para cosas const
y static
), reemplazando al antiguo evaluador que trabajaba directamente en AST. En 2017, @RalfJung realizó una pasantía en Mozilla y comenzó a desarrollar Miri como una herramienta para detectar comportamientos indefinidos, y también a utilizar Miri como una forma de explorar las consecuencias de varias definiciones posibles para comportamientos indefinidos en Rust. El traslado del motor Miri al compilador por parte de @oli-obk finalmente se completó a principios de 2018. Mientras tanto, más tarde ese año, @RalfJung realizó una segunda pasantía, desarrollando aún más Miri con soporte para verificar invariantes de tipo básicos y verificar que las referencias se utilizan de acuerdo a sus restricciones de alias.
Miri ya encontró una serie de errores en la biblioteca estándar de Rust y más allá, algunos de los cuales recopilamos aquí. Si Miri te ayudó a encontrar un error sutil de UB en tu código, ¡apreciaríamos que un PR lo agregue a la lista!
Errores definitivos encontrados:
Debug for vec_deque::Iter
accediendo a memoria no inicializadaVec::into_iter
haciendo una lectura ZST no alineadaFrom<&[T]> for Rc
creando una referencia no suficientemente alineadaBTreeMap
crea una referencia compartida que apunta a una asignación demasiado pequeñaVec::append
creando una referencia colgantestr
convierte una referencia compartida en una mutablerand
realizando lecturas no alineadasposix_memalign
de forma no válidagetrandom
llamando a getrandom
syscall de forma no válidaVec
y BTreeMap
pierden memoria en algunas condiciones (de pánico)beef
perdiendo memoriaEbrCell
usa memoria no inicializada incorrectamenteservo_arc
creando una referencia compartida colganteencoding_rs
haciendo aritmética de punteros fuera de límitesVec::from_raw_parts
incorrectamenteAtomicPtr
y Box::from_raw_in
ThinVec
crossbeam-epoch
llamando assume_init
en un MaybeUninit
parcialmente inicializadointeger-encoding
desreferenciando un puntero desalineadorkyv
construyendo un Box<[u8]>
a partir de una asignación sobrealineadaarc-swap
thread::scope
regex
manejan incorrectamente buffers Vec
no alineadoscompare_exchange_weak
en once_cell
vec::IntoIter
Iterator::collect
in situportable-atomic-util
std::mpsc
(código original en travesaño)Se encontraron violaciones de Stacked Borrows que probablemente sean errores (pero Stacked Borrows actualmente es solo un experimento):
VecDeque::drain
creando referencias mutables superpuestasBTreeMap
BTreeMap
que crean referencias mutables que se superponen con referencias compartidasBTreeMap::iter_mut
creando referencias mutables superpuestasBTreeMap
utilizando punteros sin formato fuera de su área de memoria válidaLinkedList
creando referencias mutables superpuestasVec::push
invalidando referencias existentes en el vectoralign_to_mut
viola la unicidad de las referencias mutablessized-chunks
que crean alias de referencias mutablesString::push_str
invalidando referencias existentes en la cadenaryu
usando punteros sin formato fuera de su área de memoria válidaEnv
que utiliza un puntero sin formato fuera de su área de memoria válidaVecDeque::iter_mut
creando referencias mutables superpuestas<[T]>::copy_within
usando un préstamo después de invalidarlo Con licencia bajo cualquiera de
a tu elección.
A menos que indique explícitamente lo contrario, cualquier contribución enviada intencionalmente para su inclusión en el trabajo tendrá una licencia doble como se indica arriba, sin términos ni condiciones adicionales.