deniz.in

Piyasalar

Hava durumu

Hava durumu yükleniyor

· kaynak Hacker News – Front Page (native)

On yıllık Rust unsoundness hatası, safe kodun type checker'dan non-'static referansları geçirmesine izin veriyor

rust-lang/rust üzerinde açılan bir issue, derleyicinin lifetime kısıtlamalarını ihlal eden programları on yıla varan süre boyunca kabul ettiğini gösteriyor; bu da safe kodun 'static varsayan koda non-'static referansları geçirmesine ve use-after-free sonuçlarına yol açabiliyor.

On yıllık Rust unsoundness hatası, safe kodun type checker'dan non-'static referansları geçirmesine izin veriyor

13 Ekim 2026'da rust-lang/rust deposunda açılan bir bug raporu, Rust derleyicisinin kendi lifetime kurallarını ihlal eden programları çok uzun süredir — bir varyantta Rust 1.4'ten beri — kabul ettiğini ve ortaya çıkan tip ihlallerinin tek bir satır unsafe kod olmadan dangling referanslar ve use-after-free davranışı üretebileceğini gösteriyor.

Issue, GitHub kullanıcısı theemathas tarafından açıldı ve Rust Zulip üzerindeki tartışmanın ardından projenin issue botu tarafından hızla P-high olarak triage edildi. Kök nedeni tanımlamak için yeniden başlıklandı: bir struct'ın bildirilen lifetime gereksinimleri, covariant alan ataması yoluyla atlatılabiliyor.

Exploit nasıl çalışıyor

Orijinal proof of concept, T: 'static + Send bound'u ve bir Drop implementation'ı olan generic bir struct tanımlıyor. Drop kodu değeri struct'tan çıkarıp global, mutex ile korunan boxed 'static trait object koleksiyonuna ekliyor — bu yalnızca type system, T'nin programın geri kalanı boyunca yaşayacağı sözünü verdiği için sound.

Çağıran taraf bu sözü bozuyor. Yerel bir String oluşturuluyor ve ona bir referans struct'ın alanına atanıyor. Shared referanslar lifetime açısından covariant olduğu için, yazılan değerin lifetime'ı type parameter üzerindeki bound'un gerektirdiğinden çok daha kısa olsa bile atama kabul ediliyor. Bloğun sonunda struct drop edildiğinde, ölü yerel değişkene ait referans sanki `'static'miş gibi saklanıyor.

Demonstrasyon daha sonra aynı stack slot'unu tesadüfen yeniden kullanan yeni bir string allocate ediyor ve smuggle edilen referansı başarıyla &'static String'e downcast ederek yeni string'in içeriğini yazdırıyor. AddressSanitizer altında aynı program stack-use-after-scope raporuyla abort ediyor; bu da referansın gerçekten referent'inden uzun yaşadığını doğruluyor. Rapora göre kod güncelik nightly'de ve en az 1.85.0'a kadar geri giden stable sürümlerde derleniyor.

Tek bir bug değil, hatalar ailesi

Yorum thread'i bunun izole bir tuhaflık olmadığını gösteriyor. Derleyici katkıcısı lcnr, hiç global state gerektirmeyen bir varyant paylaştı: daha uzun ömürlü bir referansa mutable referans ile daha kısa ömürlü bir referansı birlikte tutan bir struct, Drop implementation'ı kısa olanı uzun olan üzerinden yazıyor ve iç scope bittikten sonra yazdırılan dangling bir referans bırakıyor.

theemathas belki de en net versiyonuyla katkıda bulundu: Drop, uyuyan bir thread spawn ediyor ve ardından orijinal stack frame çoktan yok olmuşken sözde 'static olan referansı dereference ediyor.

Yorumcu maxdexh daha da ileri giderek, 2015'te yayınlanan Rust 1.4'e kadar geri giden, segfault veren veya freed belleği yazdıran bir varyant bildirdi — kabaca on bir yıllık sürenin kaynağı bu — ve altta yatan sorunun alan atamasına özgü olmadığını savundu. Onların okumasına göre derleyicinin unification mantığı, iki tip eşit kılındığında genel olarak bir tipin lifetime bound'larını yeniden kontrol etmeyi başaramıyor; aynı ihlali üretmek için array elemanları arasında sıradan type unification ve bir alan swap'ı kullanan bir örnek sundular.

theemathas ayrıca kendi versiyonunun 2017'deki Rust 1.18.0'dan beri şikayetsiz derlendiğini belirtti.

Neden önemli

Rust'un temel satış noktası, memory safety'nin derleyici tarafından zorunlu kılınması ve bu nedenle unsafe davranış için denetlenebilecek açık bir unsafe bloğu gerekliliğidir. Böyle bir unsoundness bu sözleşmeyi bozuyor: buna dayanan herhangi bir program, tamamen safe Rust ile yazılmış undefined behavior sergileyebilir.

Pratikte maruziyet ise eşit değil. Lifetime'ları yalnızca normal şekilde kullanan kodun buna takılması olası değil; tehlike, biri 'static veya outlives bound'unu sert bir invariant olarak kabul eden kod — özellikle unsafe kod — yazdığında yoğunlaşıyor. Böyle bir API sunan bir kütüphane, sıradan ve iyi niyetli bir çağırıcıdan dangling bir referans alabilir ve ortaya çıkan bug, onu cause eden atamada değil kütüphanenin içinde su yüzüne çıkar.

Lifetime bound'lu generic kodun ve özel Drop implementation'larının maintainers'ları için bu issue, bu pattern'leri denetleme ve bu hata sınıfını güvenilir şekilde yakalayan sanitizer'lar altında test suite'lerini çalıştırma çağrısıdır. Rust projesi içinse, en yoğun test edilmiş type checker'ların bile on yıl boyunca bir kör nokta taşıyabileceğinin hatırlatmasıdır. Rapor zamanında henüz bir fix landing yapmamıştı.

  • #rust
  • #compiler
  • #type-system
  • #memory-safety
  • #security

İlgili yazılar