FlawOpen

flawopen.com/मेमोरी सुरक्षा/Rust unsafe

क्या Rust का unsafe ब्लॉक मेमोरी-सुरक्षित है?

CWE-787: सीमा से बाहर लिखनासंदर्भ पृष्ठ
संक्षिप्त उत्तर

unsafe Rust की जाँच बंद नहीं करता। यह उन खास operations की अनुमति देता है जिनकी सुरक्षा compiler साबित नहीं कर सकता; उन शर्तों को पूरा करना प्रोग्रामर की जिम्मेदारी है। इसलिए असाउंड unsafe abstraction साधारण सुरक्षित callers से undefined behaviour (UB) करा सकता है, भले ही उन्होंने unsafe न लिखा हो।

मुख्य शब्द

Unsafe operation:
ऐसा operation जिसकी सुरक्षा शर्त compiler साबित नहीं कर सकता, जैसे raw pointer को dereference करना।
Sound abstraction:
ऐसा सुरक्षित API जिसके सुरक्षित callers undefined behaviour नहीं करा सकते।
size_hint():
अनुकूलन के लिए iterator के आकार का अनुमान; यह सटीक गिनती या मेमोरी-सुरक्षा का प्रमाण नहीं है।
Undefined behaviour (UB):
ऐसा प्रोग्राम व्यवहार जिसे Rust परिभाषित नहीं करता; unsafe कोड को सुरक्षित callers से इसे होने से रोकना चाहिए।

असुरक्षित सुरक्षित abstraction कैसे विफल होता है

चरण 1

सुरक्षित API iterator लेता है

Caller साधारण iterator को ऐसे फ़ंक्शन में देता है जिसकी कोई unsafe precondition नहीं है।

चरण 2

Implementation अनुमान के आधार पर जगह लेता है

फ़ंक्शन बताई गई न्यूनतम संख्या के लिए ही जगह लेता है, जो iterator द्वारा दिए जाने वाले वास्तविक items से कम हो सकती है।

चरण 3

बिना जाँच लिखने से क्षमता पार होती है

Implementation allocation बढ़ाए या हर item पर क्षमता जाँचे बिना raw pointer से सभी items लिखता है।

चरण 4

सुरक्षित उपयोग UB तक पहुँचता है

यदि items की संख्या उपलब्ध जगह से अधिक है, तो सुरक्षित call सीमा से बाहर लिख सकता है। Vec::extend या सुरक्षित रूप से बढ़ने वाला implementation उपयोग करें।

असाउंड
// UNSOUND: reserve uses only the lower hint,
// then unchecked writes consume every item.
fn append_unsound(dst: &mut Vec<u8>, iter: impl Iterator<Item = u8>) {
    let (lower, _) = iter.size_hint();
    dst.reserve(lower);
    let start = dst.len();
    let mut written = 0;
    unsafe {
        let out = dst.as_mut_ptr().add(start);
        for item in iter {
            // UB once writes exceed spare capacity.
            out.add(written).write(item);
            written += 1;
        }
        dst.set_len(start + written);
    }
}
सुरक्षित समाधान
// SOUND: Vec::extend handles capacity
// growth and length updates safely.
fn append(dst: &mut Vec<u8>, iter: impl Iterator<Item = u8>) {
    dst.extend(iter);
}

Rust की गारंटी का वास्तविक अर्थ

सटीक गारंटी है: यदि सुरक्षित Rust जिस unsafe कोड पर निर्भर है वह sound है, तो सुरक्षित Rust undefined behaviour नहीं करा सकता।Rust Reference सीमा पर soundness परिभाषित करता है: unsafe कोड को सुनिश्चित करना चाहिए कि सुरक्षित clients UB न करा सकें। Compiler unsafe operation के भीतर हर proof obligation की जाँच नहीं करता; प्रोग्रामर और reviewers को उन्हें पूरा करना होता है।

C और C++ की तुलना में यह Rust का बड़ा व्यावहारिक लाभ है: Rust मेमोरी-संवेदनशील operations और उनकी सुरक्षा जिम्मेदारियों को अधिक स्पष्ट करता है। इससे reviewers unsafe boundaries और उन पर बनी सुरक्षित abstractions पर ध्यान दे सकते हैं। इनमें unsafe blocks, unsafe function contracts, unsafe trait implementations, FFI declarations और unsafe attributes शामिल हैं; ये हमेशा एक छोटे block तक सीमित नहीं होते। उदाहरण है smallvec का CVE-2021-25900: SmallVec::insert_many ने iterator के size hint की न्यूनतम सीमा के आधार पर जगह ली, फिर allocation से अधिक items लिखे; CVSS 9.8 था।

मानदंड soundness है, केवल सावधानी नहीं

यदि सुरक्षित कोड किसी API का उपयोग करके undefined behaviour करा सकता है, तो वह API unsound है। उदाहरण के लिए, Iterator::size_hint अनुकूलन के लिए सीमाएँ देता है, सटीक item count नहीं: वैध iterator न्यूनतम सीमा से अधिक items दे सकता है और त्रुटिपूर्ण iterator अपना अनुमान तोड़ सकता है। दस्तावेज़ स्पष्ट कहता है कि इस hint के आधार पर unsafe कोड में bounds checks न हटाएँ। सुरक्षित trait का गलत व्यवहार logic errors या panic भी करा सकता है; वे अपने आप UB नहीं होते, फिर भी caller के अप्रत्याशित व्यवहार के दौरान unsafe कोड को memory invariants बनाए रखने चाहिए।

इसलिए unsafe कोड का असर कई जगहों तक जा सकता है: एक स्थान पर स्थापित memory invariant को ऊपर के सुरक्षित APIs मान सकते हैं। invariant गलत हो तो दोष उस abstraction में है जिसने सुरक्षित API उपलब्ध कराया, उन callers में नहीं जो contract के अनुसार उसका उपयोग करते हैं।

व्यावहारिक नियम

अक्सर पूछे जाने वाले प्रश्न

क्या unsafe को पूरी तरह रोक सकता हूँ?

#![forbid(unsafe_code)] जिस crate में सक्षम हो वहाँ unsafe syntax रोक सकता है, जो application crates के लिए उपयोगी है। यह dependencies पर लागू नहीं होता; कुछ implementations, FFI boundaries और libraries को unsafe operations चाहिए।

क्या unsafe कोड किसी trait पर भरोसा कर सकता है?

हाँ। unsafe trait implementers की जिम्मेदारियाँ बताता है, जिन पर unsafe कोड निर्भर कर सकता है। TrustedLen standard library का unstable trait है, जो सटीक size hint का वादा करने वाले iterators के लिए है। सामान्य Iterator::size_hint यह गारंटी नहीं देता।

क्या इससे Rust का लाभ कम हो जाता है?

नहीं। Rust का safety model memory-safety obligations के दायरे को सीमित करता है और unsafe boundaries पर उन्हें स्पष्ट करता है। unsafe कोड, dependencies, FFI contracts और unsafe implementations पर बने सुरक्षित APIs का audit फिर भी जरूरी है।

संदर्भ

यह भी देखें क्या strncpy(), strcpy() से अधिक सुरक्षित है? CWE बनाम CVE: क्या अंतर है? Mass Assignment: जोखिम और सुरक्षित field allowlist Serverless डेटा रिसाव: अनुरोध के अनुसार अलगाव PHP == और Magic Hash तुलना