2009-01-24 15 views
5

में प्रारंभ किया गया है, मैंने एक एपीआई लिखा है जिसके लिए संदर्भ को प्रारंभ करने की आवश्यकता है और उसके बाद प्रत्येक एपीआई कॉल में प्रवेश किया गया है। कॉलर संदर्भ के लिए स्मृति आवंटित करता है, और उसके बाद इसे अन्य पैरामीटर के साथ init फ़ंक्शन में भेजता है जो बताता है कि वे बाद में एपीआई कॉल कैसे व्यवहार करना चाहते हैं। संदर्भ अपारदर्शी है, इसलिए क्लाइंट वास्तव में वहां के आसपास नहीं मिल सकता है; यह केवल एपीआई कार्यों के आंतरिक उपयोग के लिए है।यह सत्यापित करना कि स्मृति को

जिस समस्या में मैं चल रहा हूं वह यह है कि कॉलर संदर्भ आवंटित कर रहे हैं, लेकिन इसे प्रारंभ नहीं कर रहे हैं। नतीजतन, बाद के एपीआई फ़ंक्शन अर्थहीन कचरे का जिक्र कर रहे हैं जैसे कि यह वास्तविक संदर्भ था।

मैं यह सत्यापित करने का एक तरीका ढूंढ रहा हूं कि एक एपीआई फ़ंक्शन में पारित संदर्भ वास्तव में प्रारंभ किया गया है। मुझे यकीन नहीं है कि यह संभव है। मैंने दो विचारों के बारे में सोचा है:

  1. पूर्व परिभाषित स्थिरता का उपयोग करें और इसे संदर्भ के "जादू" फ़ील्ड में एपीआई आमंत्रण समय पर सत्यापित करने के लिए संग्रहीत करें।
  2. संदर्भ की सामग्री का एक चेकसम का प्रयोग करें, इसे "जादू" फ़ील्ड में संग्रहीत करें और इसे आमंत्रण समय पर सत्यापित करें।

दुर्भाग्य से मैं जानता हूँ कि इन विकल्पों में से किसी एक के लिए एक झूठी सकारात्मक सत्यापन में परिणाम सकता है, क्योंकि या तो स्मृति में यादृच्छिक बकवास "जादू" नंबर से मेल खाता है, या एक पहले से प्रारंभ क्योंकि संदर्भ के रूप में एक ही स्थान पर कब्जा करने के लिए होता संदर्भ। मुझे लगता है कि बाद का परिदृश्य अधिक संभावना है।

क्या यह आसानी से संभावना के सवाल पर उबालता है? कि मैं ज्यादातर मामलों में झूठी सकारात्मक से बच सकता हूं, लेकिन सभी नहीं? क्या यह एक प्रणाली का उपयोग करने लायक है जो मुझे केवल सटीकता की उचित संभावना देता है, या क्या यह अन्य समस्याओं को और अधिक कठिन बना देगा?

उत्तर

3

आपका संदर्भ चर शायद इस समय स्मृति आवंटित करने के लिए किसी प्रकार का सूचक है।इसके बजाय, इसे एक टोकन या हैंडल बनाएं जिसे स्पष्ट रूप से सत्यापित किया जा सके। हर बार एक संदर्भ शुरू किया जाता है, तो आप एक नया टोकन (वास्तविक संदर्भ वस्तु नहीं) वापस करते हैं और उस सूची को टोकन को एक आंतरिक सूची में संग्रहीत करते हैं। फिर, जब कोई क्लाइंट आपको बाद में संदर्भ देता है, तो आप जांचते हैं कि यह सूची में देखकर मान्य है। यदि ऐसा है, तो टोकन को वास्तविक संदर्भ में परिवर्तित किया जा सकता है और अन्यथा एक त्रुटि लौटा दी जाती है।

typedef Context long; 

typedef std::map<Context, InternalContext> Contexts; 
Contexts _contexts; 

Context nextContext() 
{ 
    static Context next=0; 
    return next++; 
} 

Context initialise() 
{ 
    Context c=nextContext(); 
    _contexts.insert(make_pair(c, new InternalContext)); 
    return c; 
} 

void doSomethingWithContext(Context c) 
{ 
    Contexts::iterator it=_ _contexts.find(c); 
    if (it==_contexts.end()) 
    throw "invalid context"; 
    // otherwise do stuff with the valid context variable 
    InternalContext *internalContext=*it.second; 
} 

इस विधि के साथ, अवैध स्मृति पहुंच का कोई खतरा नहीं है क्योंकि आप केवल वैध संदर्भ संदर्भों का सही उपयोग करेंगे।

0

पिछले संदर्भ के स्मृति स्थान के मुद्दे को दूर करने के लिए, आप संदर्भ को मुक्त करने के अलावा, इसे रीसेट कर सकते हैं और "जादू" संख्या को हटा सकते हैं, यह मानते हुए कि उपयोगकर्ता आपके द्वारा संदर्भ का उपयोग कर संदर्भ को मुक्त करता है एपीआई। इस तरह जब सिस्टम अगले संदर्भ अनुरोध के लिए स्मृति के समान ब्लॉक को लौटाता है, तो जादू संख्या जांच विफल हो जाएगी।

6

सबसे अच्छा समाधान, मुझे लगता है कि, आपके एपीआई में बनाने()/delete() फ़ंक्शन जोड़ते हैं और संरचना आवंटित करने और प्रारंभ करने के लिए उपयोग करते हैं। आप संरचना को शुरू करने से पहले हस्ताक्षर (या पूरे बफर) को ओवरराइट करने के लिए बनाएं() और हटाएं() के साथ आवंटित स्मृति को पॉइंट करने के लिए संरचना की शुरुआत में हस्ताक्षर डाल सकते हैं।

आप वास्तव में सी में झूठी सकारात्मकताओं से बच नहीं सकते हैं क्योंकि कॉलर ने आपके हस्ताक्षर से शुरू होने के लिए "हुआ" स्मृति को malloc'd किया; लेकिन आपको उचित रूप से हस्ताक्षर (8 बाइट्स कहते हैं) बनाते हैं और बाधाएं कम होती हैं। एक बनाना() फ़ंक्शन प्रदान करके कॉलर के हाथों से आवंटन करना एक लंबा रास्ता तय करेगा।

और, हाँ, आपका सबसे बड़ा जोखिम यह है कि प्रारंभिक बफर को हटाए जाने के बिना मुक्त किया जाता है(), और बाद में मॉलोक उस स्मृति ब्लॉक का पुन: उपयोग करने के लिए होता है।

1

आप एक नई एपीआई कॉल परिभाषित कर सकते हैं जो अनियंत्रित स्मृति लेता है और आपको जिस तरह से आवश्यकता है उसे शुरू करता है। फिर, क्लाइंट एपीआई का हिस्सा यह है कि क्लाइंट को संदर्भ प्रारंभिक फ़ंक्शन को कॉल करना होगा, अन्यथा अपरिभाषित व्यवहार परिणाम देगा।

0

देखें कि आपका सिस्टम अनियंत्रित मेनमरी के साथ क्या करता है। एम $ करता है: Uninitialized memory blocks in VC++

+0

यह डीबग बिल्ड के लिए केवल सत्य है - आप रिलीज कोड के लिए इस पर भरोसा नहीं कर सकते –

3

Robust Programming पर मैट बिशप द्वारा पेपर को देखें। टिकट या टोकन का उपयोग (कुछ मामलों में फ़ाइल हैंडल के समान, लेकिन एक बार उपयोग किए जाने वाले गैर-संख्या सहित) आपके लाइब्रेरी कोड को यह सुनिश्चित करने की अनुमति देता है कि वह जिस टोकन का उपयोग कर रहा है वह मान्य है। वास्तव में, आप उपयोगकर्ता की ओर से डेटा संरचना आवंटित करते हैं, और उपयोगकर्ता को वापस टिकट भेजते हैं जो आपके द्वारा परिभाषित एपीआई को प्रत्येक कॉल के लिए प्रदान किया जाना चाहिए।

मेरे पास उस सिस्टम पर बारीकी से कुछ कोड है। शीर्ष लेख टिप्पणियां शामिल हैं:

/* 
** Based on the tickets in qlib.c by Matt Bishop ([email protected]) in 
** Robust Programming. Google terms: Bishop Robust Nonce. 
** http://nob.cs.ucdavis.edu/~bishop/secprog/robust.pdf 
** http://nob.cs.ucdavis.edu/classes/ecs153-1998-04/robust.html 
*/ 

मैं भी एक क्षेत्र आधारित स्मृति आवंटन टिकट का उपयोग कर विभिन्न एरेनास की पहचान के लिए प्रणाली का निर्माण किया।

संबंधित मुद्दे