2012-09-04 19 views
6

İlkel/POD türleri değerlerini (https://stackoverflow.com/a/11493744/16673 veya http://www.codeproject.com/Articles/825/Using-templates-for-initialization) başlatmak için derleyiciyi zorlamak için şablonları kullanmak yaygın bir kalıptır.İmha durumunda otomatik belleğin üzerine yazma işlemini gerçekleştirme şablonu

Güvenlik nedenleriyle kapsam dışına çıktığında değeri silmek için kullanılabilecek benzer bir model var mı, değişken yok edildiğinde değerin yığında kalmadığından emin olmak için mi? Korkarım ki benzer bir uygulama işe yaramayabilir, çünkü derleyici, herhangi bir atamayı, kapsam dışında kalan bir değere aldırış etmekte serbesttir, çünkü değer, artık kullanılmayacak kadar az kanıtlanabilir. Bazı tutarlı ve makul derecede taşınabilir çözüm var mıdır, örn. uçucu kullanmak?

cevap

3
Bu daha taşınabilir hale getirmek için bazı C++ 11 özelliklerini kullanmak, ancak bu bir başlangıç ​​noktası olarak yeterli olabilir

:

Sınıf

template<typename T> 
class t_secure_destruct { 
    static const size_t Size = sizeof(T); 
    static const size_t Align = alignof(T); 
public: 
    t_secure_destruct() : d_memory() { 
    new(this->d_memory)T; 
    } 

    ~t_secure_destruct() { 
    reinterpret_cast<T*>(this->d_memory)->~T(); 
    this->scribble(); 
    } 

    // @todo implement or delete op-assign and remaining constructors 

public: 
    T& get() { 
    return *reinterpret_cast<T*>(this->d_memory); 
    } 

    const T& get() const { 
    return *reinterpret_cast<const T*>(this->d_memory); 
    } 

private: 
    void scribble() { 
    for (size_t idx(0); idx < Size; ++idx) { 
     this->d_memory[idx] = random(); 
    } 
    } 

private: 
    __attribute__((aligned(Align))) char d_memory[Size]; 
}; 

Demo

#include <iostream> 

class t_test { 
public: 
    t_test() : a(-1) { 
    std::cout << "construct\n"; 
    } 

    ~t_test() { 
    std::cout << "destruct\n"; 
    } 

public: 
    void print() const { 
    std::cout << "a = " << a << "\n"; 
    } 

public: 
    int a; 
}; 

int main(int argc, const char* argv[]) { 
    t_secure_destruct<t_test>test; 
    test.get().print(); 
    test.get().a = 100; 
    test.get().print(); 
    return 0; 
} 

Tabii ki, isterseniz, bu ayırmayı bir yığın ayırma ile de geri alabilirsiniz. Bir optimizatörden daha fazlasına ihtiyacınız varsa, scribbler'ı erişim noktasından çıkarmanız gerekebilir.

+0

Ses makul. Ancak rasgele silme, az fayda sağlamak anlamına gelir, sıfır sıfırlama işi yapmalıdır. Çözüm, bellek yongalarını okuyan birine ya da buna benzer bir şeye karşı, yalnızca belleğe erişen başka bir işleme karşı güvence altına almaya çalışmaz. Veya bu durumda bile rastgele veri kullanmanın bir nedeni var mı? – Suma

+0

Çözüm, GCC'ye özgü özellikleri (öznitelikleri) kullanıyor görünüyor. Char'ı depolama için kullanmak için bir sebep var mı? Orijinal türü neden kullanmıyorsunuz? – Suma

+0

@Suma, tamamlamayı istediğiniz şeylere bağlıdır. sıfırlar da iyi olurdu - sadece bir örnek. – justin

4

Windows API'de SecureZeroMemory adlı bir işlev var. Uygulamasına bakabilirsin. Bununla birlikte, genel olarak, derleyici, uçucu yazmaları onurlandırmak zorunda kalmaktadır. Değişkeni değişken yaptıysanız, yazıyı kaldıramaz.

+0

Uçucu hakkında yazdığınız şey muhtemelen bu sorunun cevabının nasıl görüneceğine dair bir ipucu (şablon muhtemelen yıkıcıda uçucu kullanmalıdır), ama bana göre bu soruya cevap veriyor (güvenli değişken uçucu işaretlenmemiş) ve bunun böyle işaretlenmesini beklemiyorum, gerekirse bir şablonla ele alınmalıdır). – Suma

+1

@Suma: Değişkenin kendisinin uçucu olmaması önemli değil. Yazımın, * * const_cast (this) 'gibi bir uçucu ifadeden geçmesi yeterlidir. Değişkenin kendisini uçucu hale getirmesi, "bu" nın kendisinin "Foo volatile" olduğunu, her yerde atılmadan olmasını sağlar, ancak sadece dtorda bir uçucu ifadeye ihtiyaç duyarsınız. – MSalters

İlgili konular