Lanzamiento de Rust 1.96. Evaluación de la idoneidad de Rust para la creación de firmware para microcontroladores

Se ha publicado la versión del lenguaje de programación Rust 1.96, que fue desarrollado inicialmente por Mozilla pero que ahora se gestiona bajo la tutela de la organización no lucrativa independiente Rust Foundation. El lenguaje se centra en el trabajo seguro con la memoria y proporciona herramientas para lograr un alto paralelismo en la ejecución de tareas, todo ello sin utilizar un recolector de basura y un runtime (el runtime se limita a la inicialización básica y el soporte de la biblioteca estándar).

Los métodos de manejo de memoria en Rust están diseñados para eliminar errores al manipular punteros y protegerse de problemas que surgen del trabajo de bajo nivel con la memoria, como acceder a la memoria después de que se ha liberado, desreferenciar punteros nulos, desbordar búferes, etc. Para la distribución de bibliotecas, la construcción y la gestión de dependencias, se desarrolla el gestor de paquetes Cargo. Para el alojamiento de bibliotecas, se soporta el repositorio crates.io.

La seguridad en el manejo de la memoria se garantiza en Rust en tiempo de compilación a través de la verificación de referencias, el seguimiento de la propiedad de los objetos, la gestión de tiempos de vida de objetos (ámbitos) y la evaluación de la corrección del acceso a la memoria durante la ejecución del código. Rust también ofrece herramientas para protegerse contra desbordamientos enteros, requiere la inicialización obligatoria de los valores de las variables antes de su uso, maneja mejor los errores en la biblioteca estándar, aplica el concepto de inmutabilidad de referencias y variables por defecto, y ofrece una fuerte tipificación estática para minimizar errores lógicos.

Novedades principales:

  • Se ha añadido un módulo de rango con la implementación de nuevos tipos que se están desarrollando para reemplazar los tipos obsoletos Range, RangeInclusive, RangeToInclusive y RangeFrom, permitiendo almacenar rangos en estructuras Copy. El tipo Range define rangos limitados por valores mínimos y máximos permitidos (sin incluir estos valores), el tipo RangeFrom define números a partir de un valor específico, y el tipo RangeInclusive incluye valores dentro de un rango con ambos límites. En futuras versiones se añadirán tipos adicionales RangeFull y RangeTo; la implementación antigua se trasladará a core::range::legacy::*, y la sintaxis "N..M" se traducirá al nuevo tipo.

    Los nuevos tipos se diferencian en que en lugar de implementar el rasgo Iterator, implementan el rasgo IntoIterator, es decir, definen cómo convertir un tipo en un iterador en lugar de usar el iterador incorporado. Este enfoque permite utilizar la operación de copia con los nuevos tipos (rasgo Copy, que indica que los valores de ese tipo pueden ser duplicados mediante una simple copia), lo cual no era posible antes debido a la incompatibilidad con los tipos con iteradores incorporados.
    Por ejemplo, los nuevos tipos permiten guardar los límites de un segmento en una estructura que se copia completamente sin guardar por separado los valores inicial y final:

    use core::range::Range;

    #[derive(Clone, Copy)]
    pub struct Span(Range);

    impl Span {
    pub fn of(self, s: &str) -> &str {
    &s[self.0]
    }
    }

  • Se han añadido los macros "assert_matches!" y "debug_assert_matches!", que verifican si un valor coincide con un patrón especificado y finalizan la ejecución en caso de discrepancia. A diferencia de las expresiones "assert!(matches!(..))" y "debug_assert!(matches!(..))", estos nuevos macros tienen la capacidad de imprimir información de depuración con los valores que causaron la falla. Para evitar colisiones con macros de terceros que se suministran con nombres similares, los nuevos macros requieren la importación explícita de la biblioteca "core::assert_matches".

    use core::assert_matches;

    fn get_random_number() -> u32 {
    4
    }

    fn main() {
    assert_matches!(get_random_number(), 1..=6);
    }

  • Al compilar para la plataforma objetivo WebAssembly, se ha deshabilitado el paso de la opción de enlazador «—allow-undefined», que permitía el enlace cuando había símbolos indefinidos, los cuales se transformaban en importaciones del módulo «env». Ahora, al compilar para WebAssembly, todos los símbolos relacionados con el enlace deben estar definidos obligatoriamente. Para restablecer el comportamiento anterior, se puede utilizar la variable de entorno «RUSTFLAGS=-Clink-arg=—allow-undefined» o la expresión ‘#[link(wasm_import_module = «env»)]’ en el código.
  • Se ha trasladado un nuevo lote de API a la categoría estable, incluyendo la estabilización de métodos e implementaciones de traits:
    • assert_matches!
    • debug_assert_matches!
    • From para AssertUnwindSafe
    • From para LazyCell
    • From para LazyLock
    • core::range::RangeToInclusive
    • core::range::RangeToInclusiveIter
    • core::range::RangeFrom
    • core::range::RangeFromIter
    • core::range::Range
    • core::range::RangeIter
  • Se ha solucionado la vulnerabilidad CVE-2026-5223 en el gestor de paquetes Cargo, que podría ser utilizada para sobrescribir el código fuente de otro paquete crate en la caché local de paquetes del mismo repositorio mediante manipulaciones con enlaces simbólicos dentro del crate. La vulnerabilidad se manifiesta solo cuando se trabaja con repositorios de paquetes de terceros y no afecta a los usuarios del repositorio crates.io, ya que el almacenamiento de paquetes con enlaces simbólicos está prohibido en crates.io.

Además, se destaca la publicación (PDF) de los resultados del análisis de la idoneidad del lenguaje Rust para el desarrollo de firmware para microcontroladores y sistemas embebidos con recursos limitados.
El estudio fue realizado por STMicroelectronics en colaboración con varias universidades europeas. Dos equipos de desarrollo aislados recibieron la tarea de implementar el mismo firmware para microcontroladores STM32U585AI con núcleo Arm Cortex-M33. El primer equipo desarrolló el firmware en C, mientras que el segundo lo hizo en Rust.

Las pruebas del trabajo realizado no encontraron ventajas significativas en el uso del lenguaje C sobre Rust en el desarrollo de firmware para microcontroladores al comparar el consumo de memoria y rendimiento. Además, la utilización del runtime del sistema escrito en Rust del proyecto de código abierto Ariel OS permitió reducir el consumo de memoria en el proyecto en Rust en comparación con la implementación en C, que utilizaba una pila tradicional para el desarrollo de firmware basada en la biblioteca newlib.

El tamaño del firmware resultante fue de 84100 bytes en el proyecto de Rust y 76744 bytes en el proyecto de C (un 10% menos), pero el consumo de memoria RAM en el firmware de Rust fue significativamente menor: 24640 bytes frente a 42608 bytes. En cuanto al rendimiento, durante las pruebas de prototipos iniciales, desarrollados en 6 semanas, la implementación en Rust superó en dos veces la implementación en C, aunque ambas implementaciones estaban muy por detrás del rendimiento máximo teórico esperado. Después de 4 semanas dedicadas a la optimización, ambas implementaciones alcanzaron resultados aproximadamente idénticos, cercanos al máximo teórico.



Fuente: opennet.ru
Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS 🔥 Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS | ProHoster