डैंगलिंग पॉइंटर

From Vigyanwiki
Revision as of 13:16, 26 June 2023 by alpha>Deepak (Deepak moved page लटकता हुआ सूचक to डैंगलिंग पॉइंटर without leaving a redirect)
लटकता हुआ सूचक

कंप्यूटर प्रोग्रामिंग में डैंगलिंग पॉइंटर्स और वाइल्ड पॉइंटर्स डेटा सूचक होते हैं जो उपयुक्त प्रकार के वैध ऑब्जेक्ट को इंगित नहीं करते हैं। ये स्मृति सुरक्षा उल्लंघनों के विशेष मामले हैं। अधिक आम तौर पर, लटकने वाले संदर्भ और जंगली संदर्भ संदर्भ (कंप्यूटर विज्ञान) हैं जो वैध गंतव्य तक हल नहीं होते हैं।

डैंग्लिंग पॉइंटर्स वस्तु के विनाश के दौरान उत्पन्न होते हैं, जब एक आवक संदर्भ वाली वस्तु को पॉइंटर के मान को संशोधित किए बिना हटा दिया जाता है या हटा दिया जाता है, ताकि पॉइंटर अभी भी हटाए गए मेमोरी के मेमोरी स्थान को इंगित करे। सिस्टम पहले से मुक्त मेमोरी को फिर से आवंटित कर सकता है, और यदि प्रोग्राम तब डेरेफरेंस ऑपरेटर (अब) डैंगलिंग पॉइंटर, अपरिभाषित व्यवहार का परिणाम हो सकता है , क्योंकि मेमोरी में अब पूरी तरह से अलग डेटा हो सकता है। यदि प्रोग्राम लटकने वाले सूचक द्वारा संदर्भित मेमोरी को लिखता है, तो असंबंधित डेटा का एक मूक भ्रष्टाचार हो सकता है, जिससे सूक्ष्म सॉफ्टवेयर बग हो सकता है जिसे खोजना बेहद मुश्किल हो सकता है। यदि स्मृति को किसी अन्य प्रक्रिया में पुन: आवंटित किया गया है, तो लटकने वाले सूचक को डीरेफेरेंस करने का प्रयास विभाजन दोष (UNIX, Linux) या सामान्य सुरक्षा दोष (Windows) का कारण बन सकता है। यदि प्रोग्राम के पास कर्नेल के मेमोरी एलोकेटर द्वारा उपयोग किए जाने वाले बहीखाता डेटा को अधिलेखित करने की अनुमति देने के लिए पर्याप्त विशेषाधिकार हैं, तो भ्रष्टाचार सिस्टम अस्थिरता का कारण बन सकता है। कचरा संग्रह (कंप्यूटर विज्ञान) के साथ वस्तु-उन्मुख भाषाओं में, झूलने वाले संदर्भों को केवल उन वस्तुओं को नष्ट करने से रोका जाता है जो अगम्य हैं, जिसका अर्थ है कि उनके पास कोई आने वाला संकेत नहीं है; यह या तो ट्रेसिंग या संदर्भ गिनती द्वारा सुनिश्चित किया जाता है। हालांकि, अंतिमकर्ता किसी वस्तु के लिए नए संदर्भ बना सकता है, जिसके लिए झूलने वाले संदर्भ को रोकने के लिए वस्तु पुनरुत्थान की आवश्यकता होती है।

वाइल्ड पॉइंटर्स तब उत्पन्न होते हैं जब किसी ज्ञात स्थिति को आरंभ करने से पहले एक पॉइंटर का उपयोग किया जाता है, जो कुछ प्रोग्रामिंग भाषाओं में संभव है। वे झूलने वाले संकेतकों के समान अनियमित व्यवहार दिखाते हैं, हालांकि उनके असंसूचित रहने की संभावना कम होती है क्योंकि कई संकलक संकलन समय पर एक चेतावनी देंगे यदि घोषित चरों को आरंभिक होने से पहले एक्सेस किया जाता है।[1]


झूलने वाले संकेतकों का कारण

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

एक सीधा उदाहरण नीचे दिखाया गया है:

{
   char *dp = NULL;
   /* ... */
   {
       char c;
       dp = &c;
   } 
     /* c falls out of scope */
     /* dp is now a dangling pointer */
}

यदि ऑपरेटिंग सिस्टम नल पॉइंटर्स के रन-टाइम संदर्भों का पता लगाने में सक्षम है, तो उपरोक्त का समाधान आंतरिक ब्लॉक से बाहर निकलने से ठीक पहले डीपी को 0 (शून्य) असाइन करना है। एक और समाधान यह होगा कि किसी भी तरह से गारंटी दी जाए कि डीपी को फिर से आरंभ किए बिना फिर से उपयोग नहीं किया जाए।

झूलने वाले संकेतकों का एक और लगातार स्रोत का एक गड़बड़ संयोजन है malloc() और free() लाइब्रेरी कॉल: एक पॉइंटर झूलने लगता है जब मेमोरी का ब्लॉक मुक्त हो जाता है। जैसा कि पिछले उदाहरण के साथ है इससे बचने का एक तरीका यह है कि इसके संदर्भ को मुक्त करने के बाद पॉइंटर को शून्य पर रीसेट करना सुनिश्चित करें - जैसा कि नीचे दिखाया गया है।

#include <stdlib.h>

void func()
{
    char *dp = malloc(A_CONST);
    /* ... */
    free(dp);         /* dp now becomes a dangling pointer */
    dp = NULL;        /* dp is no longer dangling */
    /* ... */
}

स्टैक-आवंटित स्थानीय चर के पतों को लौटाना एक बहुत ही सामान्य गलत कदम है: एक बार कॉल किए गए फ़ंक्शन के वापस आने के बाद, इन चरों के लिए स्थान हटा दिया जाता है और तकनीकी रूप से उनके पास कचरा मान होता है।

int *func(void)
{
    int num = 1234;
    /* ... */
    return &num;
}

सूचक से पढ़ने का प्रयास अभी भी कॉल करने के बाद थोड़ी देर के लिए सही मान (1234) लौटा सकता है func, लेकिन उसके बाद बुलाए जाने वाले किसी भी कार्य के लिए आवंटित स्टैक स्टोरेज को ओवरराइट कर सकते हैं num अन्य मूल्यों के साथ और सूचक अब ठीक से काम नहीं करेगा। यदि एक सूचक num लौटा देना चाहिए, num समारोह से परे दायरा होना चाहिए- इसे घोषित किया जा सकता है static.

लटकने वाले संदर्भ के बिना मैनुअल डीललोकेशन

Antoni Kreczmar [pl] (1945-1996) ने एक संपूर्ण वस्तु प्रबंधन प्रणाली बनाई है जो झूलने वाली संदर्भ घटना से मुक्त है।[2] इसी तरह का दृष्टिकोण फिशर और लेब्लांक द्वारा प्रस्तावित किया गया था[3] ताले और चाबियों के नाम से।

जंगली पॉइंटर्स का कारण

पहले उपयोग से पहले आवश्यक इनिशियलाइज़ेशन को छोड़ कर वाइल्ड पॉइंटर्स बनाए जाते हैं। इस प्रकार, सख्ती से बोलते हुए, प्रोग्रामिंग भाषाओं में प्रत्येक सूचक जो प्रारंभिकरण को लागू नहीं करता है, जंगली सूचक के रूप में शुरू होता है।

यह अक्सर प्रारंभिकरण पर कूदने के कारण होता है, इसे छोड़ने से नहीं। अधिकांश कंपाइलर इसके बारे में चेतावनी देने में सक्षम हैं।

int f(int i)
{
    char *dp;    /* dp is a wild pointer */
    static char *scp;  /* scp is not a wild pointer:
                        * static variables are initialized to 0
                        * at start and retain their values from
                        * the last call afterwards.
                        * Using this feature may be considered bad
                        * style if not commented */
}


झूलने वाले संकेतकों से जुड़े सुरक्षा छेद

बफ़र अधिकता की तरह | बफर-ओवरफ्लो बग, लटकने/जंगली पॉइंटर बग अक्सर सुरक्षा छेद बन जाते हैं। उदाहरण के लिए, यदि पॉइंटर का उपयोग आभासी समारोह कॉल करने के लिए किया जाता है, तो vtable पॉइंटर के अधिलेखित होने के कारण एक अलग पता (संभवतः शोषण कोड की ओर इशारा करते हुए) कहा जा सकता है। वैकल्पिक रूप से, यदि मेमोरी में लिखने के लिए पॉइंटर का उपयोग किया जाता है, तो कुछ अन्य डेटा संरचना दूषित हो सकती है। यहां तक ​​​​कि अगर पॉइंटर लटकने के बाद ही स्मृति को पढ़ा जाता है, तो यह जानकारी लीक हो सकती है (यदि दिलचस्प डेटा वहां आवंटित अगली संरचना में रखा जाता है) या विशेषाधिकार वृद्धि के लिए (यदि सुरक्षा जांच में अब-अमान्य स्मृति का उपयोग किया जाता है)। जब एक डैंगलिंग पॉइंटर का उपयोग किया जाता है, तो इसे स्मृति के एक नए हिस्से को आवंटित किए बिना इसे मुक्त कर दिया जाता है, इसे मुक्त भेद्यता के बाद उपयोग के रूप में जाना जाता है।[4] उदाहरण के लिए, CVE-2014-1776 Microsoft Internet Explorer 6 से 11 में उपयोग-बाद-मुक्त भेद्यता है[5] उन्नत लगातार खतरे द्वारा शून्य-दिन के हमलों द्वारा उपयोग किया जा रहा है।[6]


झूलने वाली सूचक त्रुटियों से बचना

सी में, सबसे सरल तकनीक एक वैकल्पिक संस्करण को लागू करना है free() (या समान) फ़ंक्शन जो सूचक के रीसेट की गारंटी देता है। हालाँकि, यह तकनीक अन्य सूचक चर को साफ़ नहीं करेगी जिसमें सूचक की एक प्रति हो सकती है।

#include <assert.h>
#include <stdlib.h>

/* Alternative version for 'free()' */
static void safefree(void **pp)
{
    /* in debug mode, abort if pp is NULL */
    assert(pp);
    /* free(NULL) works properly, so no check is required besides the assert in debug mode */
    free(*pp);                  /* deallocate chunk, note that free(NULL) is valid */
    *pp = NULL;                 /* reset original pointer */
}

int f(int i)
{
    char *p = NULL, *p2;
    p = malloc(1000);    /* get a chunk */
    p2 = p;              /* copy the pointer */
    /* use the chunk here */
    safefree((void **)&p);       /* safety freeing; does not affect p2 variable */
    safefree((void **)&p);       /* this second call won't fail as p is reset to NULL */
    char c = *p2;       /* p2 is still a dangling pointer, so this is undefined behavior. */
    return i + c;
}

कॉल करने से पहले खाली पॉइंटर की वैधता की गारंटी के लिए भी वैकल्पिक संस्करण का उपयोग किया जा सकता है malloc():

    safefree(&p);        /* i'm not sure if chunk has been released */
    p = malloc(1000);    /* allocate now */

इन उपयोगों के माध्यम से नकाबपोश किया जा सकता है #define उपयोगी मैक्रोज़ बनाने के लिए निर्देश (एक आम जा रहा है #define XFREE(ptr) safefree((void **)&(ptr))), एक धातुभाषा जैसा कुछ बनाना या एक टूल लाइब्रेरी में अलग से एम्बेड किया जा सकता है। हर मामले में, इस तकनीक का उपयोग करने वाले प्रोग्रामर को हर उदाहरण में सुरक्षित संस्करणों का उपयोग करना चाहिए free() इस्तेमाल किया जाएगा; ऐसा करने में विफल रहने से समस्या फिर से पैदा हो जाती है। साथ ही, यह समाधान एकल कार्यक्रम या परियोजना के दायरे तक सीमित है, और इसे ठीक से प्रलेखित किया जाना चाहिए।

अधिक संरचित समाधानों के बीच, C++ में लटकने वाले पॉइंटर्स से बचने के लिए एक लोकप्रिय तकनीक स्मार्ट पॉइंटर्स का उपयोग करना है। एक स्मार्ट सूचक आमतौर पर वस्तुओं को पुनः प्राप्त करने के लिए संदर्भ गणना का उपयोग करता है। कुछ अन्य तकनीकों में समाधि का पत्थर (प्रोग्रामिंग) विधि और लॉक-एंड-की विधि शामिल हैं।[3]

एक अन्य दृष्टिकोण Boehm कचरा संग्राहक, एक रूढ़िवादी कचरा संग्रह (कंप्यूटर विज्ञान) का उपयोग करना है जो कचरा संग्राहक के साथ C और C++ में मानक स्मृति आवंटन कार्यों को प्रतिस्थापित करता है। यह दृष्टिकोण फ्रीज़ को अक्षम करके और कचरा संग्रह द्वारा वस्तुओं को पुनः प्राप्त करके झूलने वाली सूचक त्रुटियों को पूरी तरह से समाप्त कर देता है।

जावा जैसी भाषाओं में, डैंगलिंग पॉइंटर्स नहीं हो सकते क्योंकि मेमोरी को स्पष्ट रूप से हटाने के लिए कोई तंत्र नहीं है। इसके बजाय, कचरा संग्राहक स्मृति को हटा सकता है, लेकिन केवल तभी जब वस्तु किसी भी संदर्भ से पहुंच योग्य नहीं होती है।

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

डैंगलिंग पॉइंटर डिटेक्शन

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

कुछ डिबगर्स स्वचालित रूप से मुक्त किए गए डेटा को अधिलेखित और नष्ट कर देंगे, आमतौर पर एक विशिष्ट पैटर्न के साथ, जैसे 0xDEADBEEF (Microsoft का Visual C/C++ डिबगर, उदाहरण के लिए, उपयोग करता है 0xCC, 0xCD या 0xDD जो मुक्त किया गया है उसके आधार पर[7]). यह आमतौर पर डेटा को बेकार और बहुत प्रमुख बनाकर पुन: उपयोग करने से रोकता है (पैटर्न प्रोग्रामर को यह दिखाने के लिए कार्य करता है कि मेमोरी पहले ही मुक्त हो चुकी है)।

पॉलीस्पेस, दुष्ट लहर सॉफ्टवेयर, चुनाव द्वार, मडफ्लैप, जैसे उपकरण[8] पता प्रक्षालक, या एलएलवीएम पर आधारित उपकरण[9] लटकने वाले पॉइंटर्स के उपयोग का पता लगाने के लिए भी इस्तेमाल किया जा सकता है।

अन्य टूल्स (सॉफ्टबाउंड, बीमा ++ , और CheckPointer) साधन स्रोत कोड को इकट्ठा करने के लिए और पॉइंटर्स (मेटाडेटा) के लिए वैध मूल्यों को ट्रैक करें और वैधता के लिए मेटाडेटा के खिलाफ प्रत्येक पॉइंटर एक्सेस की जांच करें।

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

यह भी देखें

संदर्भ

  1. "Warning Options - Using the GNU Compiler Collection (GCC)".
  2. Gianna Cioni, Antoni Kreczmar, Programmed deallocation without dangling reference, Information Processing Letters, v. 18, 1984, pp. 179–185
  3. 3.0 3.1 C. N. Fisher, R. J. Leblanc, The implementation of run-time diagnostics in Pascal , IEEE Transactions on Software Engineering, 6(4):313–319, 1980.
  4. Dalci, Eric; anonymous author; CWE Content Team (May 11, 2012). "CWE-416: Use After Free". Common Weakness Enumeration. Mitre Corporation. Retrieved April 28, 2014. {{cite web}}: |author2= has generic name (help)
  5. "CVE-2014-1776". Common Vulnerabilities and Exposures (CVE). 2014-01-29. Archived from the original on 2017-04-30. Retrieved 2017-05-16.
  6. Chen, Xiaobo; Caselden, Dan; Scott, Mike (April 26, 2014). "New Zero-Day Exploit targeting Internet Explorer Versions 9 through 11 Identified in Targeted Attacks". FireEye Blog. FireEye. Retrieved April 28, 2014.
  7. Visual C++ 6.0 memory-fill patterns
  8. Mudflap Pointer Debugging
  9. Dhurjati, D. and Adve, V. Efficiently Detecting All Dangling Pointer Uses in Production Servers