2 puan yazan GN⁺ 2024-08-05 | 1 yorum | WhatsApp'ta paylaş
  • Kriptografik kodlarda kritik olan sabit zaman (constant-time) özelliği, yalnızca derleyici optimizasyonlarıyla bile bozulabildiği için, riskli kalıpları bulmak üzere LLVM içine bir uyarı yaması ekleme deneyi yürütüldü
  • Derleyici “optimizasyonu” bazı benchmark’ları hızlandırabilir, ancak gerçek kritik yollar çoğu zaman intrinsics ve assembly’ye dayanır; optimizasyondan doğan hata maliyetleri ise ayrıca birikir
  • Haziran 2024’te Antoon Purnal, Kyber referans kodunun Clang 15 ve üzerindeki bazı optimizasyon seçeneklerinde gizli değere dayalı koşullu dallanmaya dönüştüğünü ve bunun zamanlama saldırılarına izin verebileceğini doğruladı
  • TIMECOP 2, SUPERCOP içinde sabit zamanlı olarak beyan edilen derleme sonuçlarını denetler; ancak Valgrind’in desteklediği komutlar ve gerçek test çalıştırmalarında ortaya çıkan veri akışları açısından sınırlamaları vardır
  • Pratikteki yanıt, derleyicinin 1 bitlik sonucu bool olarak görmesini engellemek için crypto_{int,uint}{8,16,32,64}.h gibi işlevler kullanmak ya da doğrulanmış assembly, güvenlik odaklı diller veya özel derleyicilere geçmektir

Derleyici “optimizasyonunun” yarattığı sorumluluk boşluğu

  • Güncel LLVM ve GCC değişiklik geçmişlerinde “optimizasyon”, “optimizasyon” testleri, test düzeltmeleri ve “optimizasyon” hata düzeltmeleri sürekli karşımıza çıkar
  • Derlemeden önce iyi çalışan kod, derleyici değişikliğinden sonra farklı davranırsa, çoğu durumda sorumluluk “undefined behavior”a basan programcıya yüklenir
  • Bu tür “language standards” derleyici yazarları tarafından oluşturulur; sonuçta küçük bir derleyici yazarı grubunun değişikliklerinden çok, milyonlarca programcının kodu daha büyük bir sorumluluk üstlenmiş olur
  • Kriptografik kod örneği olarak, birçok CPU benchmark’ında kyber768in avx2 uygulaması, “optimizasyon” derleyicisiyle derlenen taşınabilir koda göre yaklaşık 4 kat daha hızlıdır

Optimizasyon performans ölçümünün sınırları

  • 2000’de Todd A. Proebsting, Proebsting's Law içinde “derleyici ilerlemesi her 18 yılda bir hesaplama gücünü ikiye katlar” diyerek derleyici optimizasyonunun katkısının tali olduğu sonucuna vardı
  • Arseny Kapoulkine, 2022’deki benchmark çalışmasında LLVM 11’in LLVM 2.7’ye göre optimizasyonlu derleme için 2 kat daha uzun sürdüğünü, çalıştırılan kodun ise genel olarak %10–20 daha hızlı olduğunu özetledi
  • Her iki tartışma da gerçek kullanıcıların hissettiği performans ölçümünü kaçırıyor
    • Performansın yoğunlaştığı hotspot’larda çokça intrinsics ve assembly bulunur
    • FFmpeg içinde .asm ve .S dosyaları bazında 160.000 satır assembly vardır
    • Bilgisayarlar ve ağlar daha fazla veri işledikçe, gerçek CPU zamanı bu tür hotspot’lara daha çok yüklenir
  • Güvenlik maliyetleri de optimizasyon tartışmasında ayrıca büyür
    • Deloitte, 2023’te IT güvenliği bütçelerinin şirket gelirlerinin %0,5’i olduğunu bildirdi
    • 2022’de dünya genelinde şirketlerin toplam gelirinin 48 trilyon doların üzerinde olduğu verisiyle birlikte düşünülürse toplam ölçek yüz milyarlarca dolar seviyesinde olabilir
    • Ancak Deloitte’un %0,5 değerinin şirketler bazında basit ortalama olabileceği ve tüm şirketlerin ankete yanıt vermediği notu da vardır

Zamanlama sızıntıları ve Kyber örneği

  • “Optimizasyon” derleyicilerinin yarattığı güvenlik sorunları yalnızca geleneksel hataları değil, gizli bilginin çalışma süresinden sızdığı zamanlama sızıntılarını da içerir
  • Laurent Simon, David Chisnall ve Ross Anderson’ın EuroS&P 2018 makalesi, derleyici yükseltmelerinin daha önce güvenli olan kodda haber vermeden zamanlama kanalı açabileceği konusunda uyarır
  • 2018 makalesinde vurgulanan örnek, iki değerden birini bool ile seçen koddu; bool, derleyicinin koşullu atlama üretmesini tetikler
    • Kriptografik uygulamalarda bundan kaçınmak için kritik kodda bool’u kaldırıp sabit zamanlı karşılaştırma işlevleri ayrıca oluşturma pratiği vardır
    • OpenSSL’in bunun için 37 işlev bildirdiği aktarılır
  • 2015’teki curve25519-donna ve MSVC 2015 vakası, yazıda bir yanlış anlama olarak değerlendirilir
    • Gerçekte, 32 bit x86 için derlenirken int64 işlemi Microsoft’un 32 bit int64 kütüphanesi llmul.asm çağrısına dönüştürülmüştür
    • Zamanlama sızıntısı llmul.asm içindeki veriye bağımlı dallanmadan kaynaklanmıştır ve bu kütüphanenin de makul kaynak kodu kavramına dahil edilmesi gerektiği düşünülür
  • Haziran 2024’te Antoon Purnal, Kyber referans kodunun Clang 15 ve üzerindeki bazı optimizasyon seçeneklerinde zamanlama saldırılarına izin verebileceğini doğruladı
    • Sorunlu biçim (-((x>>j)&1))&y idi; bu, xin j’inci biti ayarlıysa y, değilse 0 üreten bir hesaplamadır
    • Clang, bit test komutuyla ilgili biti bool’a dönüştürür, ardından bu bool’a dayalı koşullu dallanma üretir
    • LLVM içinde bu “optimizasyon”u lib/CodeGen/SelectionDAG/DAGCombiner.cpp içindeki combineShiftAnd1ToBitTest işler
    • Bu işlev Sanjay Patel tarafından Eylül 2019’da eklendi ve daha sonra çeşitli kişilerce değiştirildi
  • GCC’de de benzer sınır ihlali örnekleri vardır
    • ARM’ın Kasım 2021 tarihli GCC yaması, (-x)>>31 ifadesini -(x>0) biçimine dönüştürür
    • Nisan 2024’te bununla ilgili bir uyarı çıktı

TIMECOP ve sabit zaman denetimi

  • TIMECOP 2, SUPERCOP kriptografi test çerçevesine gömülüdür ve sabit zamanlı olarak beyan edilen derlenmiş kodda gizli değerden türeyen koşullu dallanmaları otomatik denetler
  • Denetim kapsamı, koşullu dallanmaların yanı sıra gizli değerden türetilmiş dizi indekslerini de içerir
    • KyberSlash makalesi, gizli değerden türeyen bölme işlemlerini denetleyen bir yamayı da açıklar
  • TIMECOP 1, Moritz Neikes’in SUPERCOP’u değiştirerek yaptığı bir araçtı ve Adam Langley’nin ctgrind yaklaşımını otomatikleştirdi
  • TIMECOP 2 mevcut yöntemi birkaç açıdan genişletir
    • RNG çıktısını otomatik olarak gizli değer diye işaretler
    • “declassification” destekler
    • “public inputs” belirtmeyi destekler
    • Birden çok çekirdekte çalışır
  • TIMECOP’un belirgin sınırlamaları vardır
    • Yalnızca Valgrind’in desteklediği komutları ele alabilir; AMD XOP komutları gibi durumlarda durur
    • Yalnızca gerçek test çalıştırmasında görünen veri akışını denetler
  • Sabit zamanlı davranış denetim araçları üzerindeki çalışmalar sürüyor; ilgili araçların listesi ct-tools içindedir
  • TIMECOP’a karşılık gelen denetim libmceliece test paketine girdi ve başka kütüphanelere de yayılabilir

Sabit zamanlı yeniden yazma yöntemi

  • Değişken zamanlı kod parçaları bulunduktan sonra, bunları hatasız biçimde sabit zamanlı yeniden yazmanın bir yolu gerekir
  • Temmuz 2024 sunumunda libmceliece ve SUPERCOP’un sağladığı bazı sabit zamanlı işlevler tanıtıldı
    • Dosya adları crypto_{int,uint}{8,16,32,64}.h
    • Bu dosyalar başka projelere kopyalanıp kullanılabilir
  • Örnek işlev crypto_uint32_bitmod_mask(x,j), -((x>>(j&31))&1) ile aynı etkiyi yaratır; ancak derleyicinin 1 bitlik sonucu görmesini engeller
  • Daha karmaşık bir örnek olarak crypto_uint32_max(x,y) de vardır
  • 2018 makalesi, Clang/LLVM’e sabit zamanlı __builtin_ct_choose(bool cond, x, y) işlevi ekleyen bir tweak’i ele alır
    • İlgili makale, bu tek işlevin yeterli olduğunu yanlış biçimde öne sürer
    • Bu işlev bir gün derleyiciye girebilir, ancak projelerin ona bağımlı hale gelebilmesi uzun sürebilir
    • Uygulama yöntemi, crypto_{int,uint}{8,16,32,64}.h’den daha kırılgan görünüyor diye değerlendirilir

Sorunu önceden önlemenin yolları

  • Derlenmiş kütüphanenin dağıtım öncesi testleri derleyicinin yol açtığı zamanlama sızıntısını yakalarsa, kod yeniden yazılırken dağıtımda önceki derleyici sürümü kullanılabilir
    • Bu yöntem, kullanıcıları güvende tutmaya devam eden geçici bir yanıttır
  • Bir çözüm, kütüphaneyi assembly olarak dağıtmaktır
    • RWC 2024 sunumu Adoption of high-assurance and highly performant cryptographic algorithms at AWS, tüm girdilerde X25519’u doğru hesapladığı kanıtlanmış hızlı bir X25519 yazılımı sunar
    • Uygulama, 64 bit Intel/AMD CPU’lar için 2 sürüm ve 64 bit ARM CPU’lar için 2 sürüm assembly olarak yazılmıştır
    • Doğruluk önermesi, kullanıcının fiilen çalıştırdığı makine kodu hakkındaki bir teoremdir ve kanıt HOL Light teorem kanıtlayıcısıyla doğrulanır
  • Ancak bu seviyeye ulaşamamış kriptografi yazılımlarında assembly’nin denetlenme zorluğu hâlâ sorun olarak kalır
  • C, C++ vb. ile yazılmış koda zamanlama sızıntısı önleme “aşısını” hızlıca eklemenin yolları da araştırılıyor

clang-vs-clang yama deneyi

  • x&1 ile x>>31in ortak noktası, olası sonuçlarının yalnızca iki tane olmasıdır
    • x&1, 0 veya 1
    • uint32 için x>>31, 0 veya 1
    • int32 için x>>31, 0 veya -1
  • Bu tür biçimlerde derleyici “optimizasyonu” yazarlarının 1 bitlik sonucu bool içine koyması kolaydır
  • GCC ve Clang’in 2’nin tümleyeni aritmetiğini varsayması için her zaman -fwrapv ile derleme yapılması önerilir
  • Kaynakta yalnızca &1, 1&, >>31 vb. taransa da pek çok örnek çıkar; ancak LLVM “optimizer” içine doğrudan yama eklenerek farklı bir şekilde tarama yapıldı
  • Yama, LLVM commit 68df06a0b2998765cb0a41353fcf0919bbf57ddb üzerinden başlayarak &1 ve >>31 arar ve şu uyarıyı verir
    • please take this away before clang does something bad
  • Örnek derleme komutu clang -Rpass-analysis=clang-vs-clang -O -c x.c
  • Test işlevi aşağıdaki gibidir
int sra31(int x)
    {
      x >>= 31;
      return x;
    }
  • Aynı uyarının tekrarlanması şaşırtıcı değildir
    • Derleyici, “optimizasyon” artık ilerlemeyene kadar uygulamaya çalışmayı sürdürür
  • clang-vs-clang çıktısı, shift işleminde signed ve unsigned ayrımı yapar
    • Bu fark, crypto_{int,uint}{8,16,32,64}.h tabanlı elle veya otomatik yeniden yazma için önemlidir
    • Kaynak dönüşümünü otomatikleştirme yöntemlerinden biri olarak clang-tidy gösterilebilir
  • #ifdef ile dışarıda bırakılmış ya da bu “optimizasyon” aşamasından önce kaldırılmış kod, clang-vs-clang uyarısı üretmez

SUPERCOP çalıştırma sonuçları ve bulunan örnekler

  • SUPERCOP 20240716, dual EPYC 7742 üzerinde ./data-do-biglittle ile çalıştırıldı
    • Hız aşırtma devre dışı bırakıldı
    • SUPERCOP derleyici listesi, okcompilers/{c,cpp} içindeki clang satırlarına -Rpass-analysis=clang-vs-clang eklenerek clang-vs-clang kullanacak şekilde ayarlandı
  • Sonuçlar 3 saat sonra hazırdı
    • Clang çıktısı toplam 675.752 satır
    • Özgün boyut 210.786.494 bayt
    • Sıkıştırılmış sonuç 3.595.199 bayt olan 20240803-fromclang.txt.gz
  • Çıktıda public data tabanlı kaynak dallanmalarının Clang içinde &1 üretmesinden kaynaklanan çok fazla gürültü vardır
  • Önceden değiştirmeye açık, net bir örnek şöyledir
a0 += (a0>>15)&106;
  • Basit kaynak taramasıyla bulmak için C ayrıştırma çabası gerektiren bir örnek şöyledir
    • ONE8 makrosu ((uint8_t)1) olarak tanımlanmıştır
*pk2^=(((* pk_cp)>>ir)&ONE8)<<jr;
  • Bulması daha zor bir örnek AVX2 intrinsic tabanlı makrolardan gelir
    • signmask_x16(x), _mm256_srai_epi16((x),15) olarak tanımlıdır
    • Bu, 256 bitlik vektör içindeki her signed 16 bitlik parçayı 15 bit sağa kaydırır
mask = signmask_x16(sub_x16(x,const_x16((q+1)/2)));
  • Bu AVX2 örneğinin önceliği yüksek değildir
    • Vektör işleminin koşullu dallanmaya dönüşmesi için AVX-512 ile derlenmesi ve derleyicinin vektörleştirilmiş bool’u seri bool koşullu dallanmaya çevirmek gibi tuhaf bir karar vermesi gerekir
    • TIMECOP Valgrind kullanır ve Valgrind AVX-512’yi desteklemez
    • Şimdilik AVX-512 derlemesi önerilmez

int128 ve daha geniş yanıt yönü

  • En ilginç bulgu, int128 üzerinde 64 bit sağa shift’in >> uyarısını tetiklediği vakadır
  • int128 uygulaması, içeride üst 64 bit word’ün işaretini anlamak için 63 bit sağa shift kullanabilir
  • Clang, GCC gibi 63 bit sağa shift’i bool’a, ardından koşullu dallanmaya dönüştürme desteği eklerse, pek çok int128 kodu bir anda değişken zamanlı hale gelebilir
    • Bu durumda 2015 makalesinin başlığının iddia ettiği duruma benzer bir tablo oluşur; ama bu kez kaynakta gerçekten bool olmasa bile gerçekleşir
  • Kaynak düzeyindeki en kolay koruma yöntemi, derleyicinin mevcut int128 uygulamasından kaçınıp crypto_int128 işlevlerini kullanmaktır
    • crypto_int128, GCC ve Clang’in int128’inden farklı olarak küçük 32 bit platformlarda da çalışabilir
  • GCC ve Clang’e gizli veri tipi ekleme fikri iyi görünüyor, ancak iki derleyicinin yapısı gereği bunu sağlam kılmanın yolu pek görünmüyor
  • Baştan güvenlik için tasarlanmış derleyicilerden daha fazla beklenti var
    • Yeni bir girdi dili gerektiren güvenlik odaklı derleyiciler arasında FaCT ve aktif olarak geliştirilen Jasmin bulunur
    • Kodun yeniden yazılması için gereken zaman konusunda endişeler vardır; ancak mevcut derleyicilerin var olan kodu işleme biçimine bakıldığında bir şekilde adım atmak gerekir

1 yorum

 
GN⁺ 2024-08-05
Hacker News yorumları
  • Tanımsız davranış içeren bir kod istendiği gibi çalışmıyor diye buna derleyici hatası demek doğru değil
    Yanlış argümanlarla dd çalıştırıp verileri uçurduktan sonra dd hatalı demeye benziyor

    • Yazar burada uygulama tanımlı davranış ile tanımsız davranışı karıştırmış gibi görünüyor. Yazıdaki örneklerin çoğu geçerli kod; asıl sorun, bit işlemi aritmetiğini dallanmaya çeviren derleyici optimizasyonunun kripto kodlarında zamanlama saldırılarını mümkün kılması
      Kaynak kodu ya da derleyiciyi hatalı görmek zor; daha doğrusu C standardının, yazarın ölçütlerine göre fazla eksik tanımlanmış olduğu ve bazı hedeflerde güvenlik hataları yarattığı söylenebilir
      Sonuçta C standardını yazanlar donanımın davranışını tanımlayamaz, yalnızca dil semantiğini tanımlayabilir; bu yüzden kripto tarafı, donanımdan kaynaklanan hatalar yüzünden sıkıntı çekmek zorunda kalıyor
    • Sorun, C ve C++’taki tanımsız davranışların saçma derecede çok olması ve bunların hepsinden kaçınmanın aşırı zor olması
      Rust’ın avantajlarından biri, potansiyel tanımsız davranışı unsafe bloklarının içine sınırlaması. Yine de C’de tanımsız davranış olan pek çok noktayı Rust tanımlamış olsa bile, unsafe koda girildiğinde ince tanımsız davranışlara yanlışlıkla basmak çok kolay
    • Derleyici kullanıcıları için yararlı olan yalnızca iki tanımsız davranış modeli var: kötü bir fikirse derlemeyi reddetmek ya da makul ve kararlı bir şey yapmak
      Sessizce başarısız olup öngörülemez kod üreten üçüncü model yalnızca derleyici yazarları için yararlı. Şartnamenin arkasına saklanmak gerçek kullanıcılara fayda sağlamıyor
    • Russ Cox’un C and C++ Prioritize Performance over Correctness yazısı bu konuyu iyi ele alıyor: https://research.swtch.com/ub
    • Bu karşı çıkış daha çok bir saman adamı dövmeye benziyor. Esas nokta, derleyici yazarlarının neyin tanımsız davranış olduğuna kendilerinin karar vermesi ve standardı daha fazla optimizasyon alanı elde edecek şekilde tanımlaması
      Bu optimizasyonlar daha önce düzgün çalışan kodları bozuyor. Derleyici yazarları geriye dönük uyumluluğu önceleyebilirlerdi ama bunu yapmıyorlar
      Üstelik bu tür optimizasyonlar gerçek kod performansını anlamlı biçimde iyileştirmediğinden, kodu bozma pahasına yapılan bu ödünün değersiz olduğu iddiasını çürütmeleri gerekiyor
  • Bernstein’ı severim ama bazen yönünü şaşırıp sertleştiği oluyor; bu yazı bunun iyi bir örneği. Yazının sonunda kendisi de bunu yarı yarıya kabul ediyor
    Yazının büyük bir kısmı optimizasyon kazancının ne kadar iyi olduğu gibi ikincil bir tartışma; veri olsa bile kullanım senaryosuna göre değişecek bir değerlendirme
    Asıl şikâyet, C derleyicisinin dilde ifade edilemeyen semantiği dikkate almaması; bu da şaşırtıcı değil
    Sonda “ihtiyaç duyduğunuz semantiği ifade edebilen bir dil kullanın” diyor; yazının tamamı o tek cümleyle değiştirilebilirdi

    • Önemli nokta, C ve C++ semantiğini tanımlayan tarafın çok fazla davranışı “tanımsız davranış” sepetine atması
      Bunların önemli bir kısmının gerekçesi şüpheli ve doğru program yazmayı zorlaştırıyor
    • Optimizasyon kazancının kullanım senaryosuna göre değiştiği kısmı yararlı bir bağlamdı ve epey ufuk açıcıydı
    • Burada DJB pek ikna edici değildi. Dayanaksız elitist bir dinî bakış çokça görünüyordu
  • C ve C++, sabit zaman garantisi olan algoritmalar yazmaya uygun değil
    Standartta gerçek zaman kavramı neredeyse yok ve derleyiciler de eklenti/uzantı olarak ek garantiler sunmuyor
    Ama bunu derleyici geliştiricilerine yüklemek yanlış yöne gitmek olur

    • Dallanmalardan bağımsız olarak her zaman sabit zamanda işlem yapan makine kodu üretmek istiyorsanız, bunu ifade edebilen bir dil kullanmalısınız. C bunu desteklemiyor
    • Sabit zaman garantisi olan algoritmalar yazmaya uygun dilin hangisi olduğunu merak ediyorum
  • Intel CPU’larda clang olsun başka bir şey olsun, kullanıcı modunda doğru kod üretemez. Çünkü en başta doğru kod diye bir şey yok
    https://www.intel.com/content/www/us/en/developer/articles/t...
    Belgede DOITM bölümüne bakarsanız, kullanıcı alanındaki kripto kütüphanesinin gerekli biti ayarlaması basitçe imkânsız

    • Kullanıcı modu kodu yine de doğru modda çalıştırılabilir. Sadece o modu açıp kapatan anahtarı doğrudan kullanamaz
      Bir kez açıldığında kullanıcı alanında da düzgün çalıştığı için, örneğin prctl sistem çağrısıyla etkinleştirilen süreç başına bir bayrak haline getirilebilir ve zamanlayıcının görev değişimi sırasında MSR ayarlaması gibi bir yol izlenebilir
    • Çekirdeğe sistem çağrısı yapıp bayrağı ayarladıktan sonra, o durumda kullanıcı moduna geri dönmek mümkün değil mi?
  • “Derleyici yazarları, mümkün olan her durumda kendi yarattıkları hataların sorumluluğunu üstlenmeyi reddediyor” cümlesi bile, bir blog yazısında uzmanlığın bu kadar hızlı çöktüğü örneğin nadir olduğunu gösteriyor
    Bağlantıyı takip edince de bunun, tanımsız davranışın “rastgele bir değer” ürettiği anlamına gelmediğine dair son derece temel bir C meselesi olduğu görülüyor

    • Görünüşe göre farklı şeylere bakıp “bug” diyorlar. Bir taraf kaynak koddaki bug’dan, diğer taraf üretilen programdaki bug’dan söz ediyor
      Tanımsız davranış olsa bile kaynak kod bug’lıdır, ama üretilen programın hâlâ doğru olduğu sıkça görülür. Daha sonra derleyici yazarı yeni bir optimizasyon ekleyip o tanımsız davranışı gerekçe göstererek hatalı bir program üretirse, sorumluluk tartışması başlar
      Kabul etmek istemedikleri nokta, kullanıcıya karşı sorumluluğun tüm taraflara bölünmüş olduğudur. Bir CRUD uygulaması NULL dereference yaptığı için pil alev aldıysa, aklı başında biri yalnızca uygulama yazarını NULL kontrolünü unuttu diye suçlamaz
      Derleyici, işletim sistemi ve donanım üreticileri de sorumsuzca tasarladıkları ürünler için sorumluluk taşımalıdır; ISO standardında “tanımsız davranış” denmesiyle mesele kapanmaz. Tedarik zincirinin tüm üyeleri, ürünün nasıl kötüye kullanılabileceğini öngörme ve bunu makul biçimde ele alma sorumluluğunu paylaşır
    • Yazarı, tanımsız davranışın ne olduğunu iyi biliyor diye düşünüyorum. Sadece tüm sisteme eleştirel bakıyor
      Tanımsız davranış değer sağlamak için vardır. Böyle şeyler olmadan da bir dil yapılabilir; buna rağmen bulunmasının nedeni taşınabilirlik ve derleyici yazarlarına sağladığı esnekliktir
      Yazının özü, bu esnekliğin tanımsız davranış olmadan program yazmanın zorluğuyla karşılaştırıldığında değip değmediğidir
      Yazar, bug’lar yüzünden kaybedilen paranın daha hızlı bytecode ile tasarruf edilen paradan büyük göründüğünü ve dil standardına nelerin gireceğini belirlerken derleyici yazarlarının etkisi büyük olduğu için bunu düzeltme isteğinin zayıf kaldığını düşünüyor
  • Not olarak, clang’de işlev bazında tüm optimizasyonları kapatan clang::optnone niteliği var; GCC’de ise optimizasyonları ada göre ekleyip kaldırabilen veya derleyici bayraklarından bağımsız olarak optimizasyon düzeyini belirleyebilen harika bir gnu::optimize niteliği var
    gnu::optimize(0), o clang bayrağına benzer. clang’de özellikle memcpy ve memset optimizasyonlarını kapatan clang::no_builtins de var

  • Kripto tarafındaki insanların istediği hedeflere, örneğin sabit zamanlı değerlendirme ve gizli değerleri saklama konusuna bir ölçüde katılıyorum
    Ama genel amaçlı derleyiciler çoğu zaman böyle şeyleri düşünmediği için, bunun genelde çalışan bir hack’ten öteye geçmesi zor görünüyor
    Ciddi yapmak için ya özel bir derleyici gerekir ya da assembly ile devam etmek gerekebilir

  • Bir gün bugünü kötü eski günler olarak görüp, C’den tanımsız davranışı çok daha az olan bir dile geçmiş olacağımızı düşünüyorum
    C’de derlenen ama derleyicinin niyeti anlamasının neredeyse imkânsız olduğu ifadeler yazmak fazlasıyla kolay
    Örneğin Python’da result = [something(value) for value in set_object] gibi kod yazılabilir. set nesnesi sırasız olduğu için öğelerin işlenme sırasının ve sonuç sırasının önemli olmadığı açıktır; bu da derleyicinin yazarın niyetini tahmin etmesine gerek kalmadan dil düzeyinde pek çok optimizasyonun önünü açar
    Değişmez veriye sahip başka dillerdeki benzer kod bir adım daha ileri gider: something(value1), something(value2)’yi etkileyemeyeceği için ister thread ister process olsun paralel çalıştırılabilir
    C derleyici optimizasyonlarının önemli bir bölümü, kod kalıplarına bakıp yazarın muhtemelen yapmak istediği şeyi daha hızlı yapmanın yolunu bulmaktır. C, modern dillere kıyasla niyeti ifade etme gücünden yoksun olduğu için tahminde bulunma özgürlüğü vardır; ama makul performans elde etmek için bu tür çıkarımlar yapmak zorundadır
    Yine de bu, Hubble teleskobunun gözlüğe ihtiyaç duyması gibi kılık değiştirmiş bir lütuf da olabilir. Sınırları aşmak için harika teknikler geliştirildi ve sorun düzeltildikten sonra bu teknikler başlangıçta beklenenden çok daha yüksek performans sağladı. C derleyici optimizasyonlarını C dışındaki dillere uygulamak belki süper güç gibi çalışabilir

    • Python örneğinin dezavantajı şu: sıra belirtilmemiş olsa bile insanlar bazı özelliklere bel bağlayabilir ve optimizer sırayı değiştirirse kod bozulabilir
      Temelde tanımsız davranışa benzer, ancak doğrudan bir güvenlik sorunu olarak değil, yanlış sonuçlar olarak ortaya çıkabilir. Elbette yanlış sonuçlar daha sonra güvenlik sorunlarına yol açabilir
      Tanımsız davranıştan farklı olarak, kodun olası tüm set sıralarında çalışıp çalışmadığını kontrol eden bir “sanitizer” yapmak pratikte imkânsızdır
      gcc ve clang’de, diğer dillerde sık bulunmayan çok sayıda düşük seviyeli ipucu vardır. __builtin_expect/__builtin_unpredictable, __builtin_unreachable/__builtin_assume, #pragma clang loop vectorize(assume_safety)/#pragma GCC ivdep, döngü açmayı veya vektörleştirmeyi kapatan ya da belirli değerleri seçen pragma’lar gibi
      Bana göre en büyük eksik, derleyicinin değerlerin kaynağına dayanarak çıkarım yapmasını açıkça engelleyen bir optimizasyon bariyeri. __asm__ bunu bir ölçüde sağlayabiliyor, ama istenmeyen yan etkileri var ve platforma özgü register türü adları gerektiriyor
      Üst düzey niyet temelli optimizasyonun potansiyeli de kesinlikle var. Bir döngüde n kez push yapmadan önce array list alanı ayırmak, aynı anahtarla yapılan contains→get→put hash map sorgularını birleştirmek ya da global ayırma davranışını yerel olarak çıkarımlayıp nesneleri ve allocation’ları ortadan kaldırmak akla geliyor
    • Teorik olarak mantıklı, ama pratikte C’den daha hızlı olduğunu kanıtlayan bir şey yok
      C gerçek donanıma yeterince yakın olduğu için programcı ne yapılacağını doğrudan söyleyebilir; dolayısıyla derleyicinin programcının niyetini tahmin etmesine gerek yoktur
    • Semantik tabanlı optimizasyon için alan olduğu doğru, ancak gözleme göre bu optimizasyonlar çoğunlukla bellek ayırma çevresinde oluyor
      Bu tür bellek optimizasyonlarını uygulayan diller çoğunlukla Java türü diller ve zaten baştan agresif bir ön kötümserleştirme olduğu için bu optimizasyonları yapma motivasyonu doğuyor. Ancak bu optimizasyonlar bile kaybı telafi edemiyor
      Özetle C de pek iyi değil, ama diğer taraf daha kötü
  • C’nin semantiğini beğenmiyorsanız derleyici mühendislerine kızmak yerine başka bir programlama dili kullanabilirsiniz

    • Açıkçası djb’nin kendi qhasm’i dışında herhangi bir şeye tahammül edip edemeyeceğini bilmiyorum. Zig’e bile. Bu değerlendirme ondan gelince pek şaşırtıcı değil
  • Pek sık duyulmayan bir bakış açısı aktaran ferahlatıcı bir yazı. Birlikte bakmaya değer: https://gavinhoward.com/2023/08/the-scourge-of-00ub/