डैंगलिंग पॉइंटर
कंप्यूटर प्रोग्रामिंग में डैंगलिंग पॉइंटर्स और वाइल्ड पॉइंटर्स डेटा पॉइंटर होते हैं जो उपयुक्त प्रकार के वैध ऑब्जेक्ट को इंगित नहीं करते हैं। ये मेमोरी सुरक्षा उल्लंघनों के विशेष स्थिति हैं। अधिक सामान्यतः, डैंगलिंग संदर्भ और वाइल्ड संदर्भ (कंप्यूटर विज्ञान) हैं जो वैध गंतव्य तक हल नहीं होते हैं।
डैंग्लिंग पॉइंटर्स वस्तु के खंडन के समय उत्पन्न होते हैं, जब आवक संदर्भ वाली वस्तु को पॉइंटर के मान को संशोधित किए बिना हटा दिया जाता है या हटा दिया जाता है, जिससे पॉइंटर अभी भी हटाए गए मेमोरी के मेमोरी स्थान को इंगित करे। सिस्टम पहले से मुक्त मेमोरी को फिर से आवंटित कर सकता है, और यदि प्रोग्राम तब डेरेफरेंस ऑपरेटर (अब) डैंगलिंग पॉइंटर, अपरिभाषित व्यवहार का परिणाम हो सकता है , क्योंकि मेमोरी में अब पूरी तरह से अलग डेटा हो सकता है। यदि प्रोग्राम डैंगलिंग वाले पॉइंटर द्वारा संदर्भित मेमोरी को लिखता है, तो असंबंधित डेटा का मूक भ्रष्टाचार हो सकता है, जिससे सूक्ष्म सॉफ्टवेयर बग हो सकता है जिसे खोजना अधिक कठिन हो सकता है। यदि मेमोरी को किसी अन्य प्रक्रिया में पुन: आवंटित किया गया है, तो डैंगलिंग वाले पॉइंटर को डीरेफेरेंस करने का प्रयास विभाजन दोष (यूनिक्स, लिनक्स) या सामान्य सुरक्षा दोष (विंडोज़) का कारण बन सकता है। यदि प्रोग्राम के पास कर्नेल के मेमोरी एलोकेटर द्वारा उपयोग किए जाने वाले बहीखाता डेटा को अधिलेखित करने की अनुमति देने के लिए पर्याप्त विशेषाधिकार हैं, तो भ्रष्टाचार सिस्टम अस्थिरता का कारण बन सकता है। गार्बेज कलेक्शन (कंप्यूटर विज्ञान) के साथ वस्तु-उन्मुख भाषाओं में, डैंगलिंग वाले संदर्भों को केवल उन वस्तुओं को नष्ट करने से रोका जाता है जो अगम्य हैं, जिसका अर्थ है कि उनके पास कोई आने वाला संकेत नहीं है; यह या तो ट्रेसिंग या संदर्भ गिनती द्वारा सुनिश्चित किया जाता है। चूँकि , अंतिमकर्ता किसी वस्तु के लिए नए संदर्भ बना सकता है, जिसके लिए डैंगलिंग वाले संदर्भ को रोकने के लिए वस्तु पुनरुत्थान की आवश्यकता होती है।
इस प्रकार से वाइल्ड पॉइंटर्स तब उत्पन्न होते हैं जब किसी ज्ञात स्थिति को आरंभ करने से पहले पॉइंटर का उपयोग किया जाता है, जो कुछ प्रोग्रामिंग भाषाओं में संभव है। वे डैंगलिंग वाले संकेतकों के समान अनियमित व्यवहार दिखाते हैं, चूँकि उनके असंसूचित रहने की संभावना कम होती है क्योंकि कई संकलक संकलन समय पर चेतावनी देंगे यदि घोषित वेरिएबल ों को आरंभिक होने से पहले एक्सेस किया जाता है।[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 #
}
पॉइंटर से पढ़ने का प्रयास अभी भी कॉल करने के बाद थोड़ी देर के लिए सही मान (1234) लौटा सकता है func
, किन्तु उसके बाद बुलाए जाने वाले किसी भी कार्य के लिए आवंटित स्टैक स्टोरेज को ओवरराइट कर सकते हैं num
अन्य मानो के साथ और पॉइंटर अब ठीक से काम नहीं करता है। यदि पॉइंटर num
लौटा देना चाहिए, num
फंक्शन से परे दायरा होना चाहिए- इसेstatic
घोषित किया जा सकता है .
डैंगलिंग वाले संदर्भ के बिना मैनुअल डीललोकेशन
एंटनी क्रेक्ज़मार (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 */
}
डैंगलिंग वाले संकेतकों से जुड़े सुरक्षा छेद
बफ़र अधिकता की तरह बफर-ओवरफ्लो बग, डैंगलिंग/वाइल्डपॉइंटर बग सदैव सुरक्षा छेद बन जाते हैं। उदाहरण के लिए, यदि पॉइंटर का उपयोग आभासी फंक्शन कॉल करने के लिए किया जाता है, तो व्यवहार्यतालिका पॉइंटर के अधिलेखित होने के कारण अलग पता (संभवतः शोषण कोड की ओर संकेत करते हुए) कहा जा सकता है। वैकल्पिक रूप से, यदि मेमोरी में लिखने के लिए पॉइंटर का उपयोग किया जाता है, तो कुछ अन्य डेटा संरचना दूषित हो सकती है। यहां तक कि अगर पॉइंटर डैंगलिंग के बाद ही मेमोरी को पढ़ा जाता है, तो यह जानकारी लीक हो सकती है (यदि रोचक डेटा वहां आवंटित दूसरी संरचना में रखा जाता है) या विशेषाधिकार वृद्धि के लिए (यदि सुरक्षा जांच में अब-अमान्य मेमोरी का उपयोग किया जाता है)। जब डैंगलिंग पॉइंटर का उपयोग किया जाता है, तो इसे मेमोरी के नए भाग को आवंटित किए बिना इसे मुक्त कर दिया जाता है, इसे मुक्त असुरक्षा के बाद उपयोग के रूप में जाना जाता है।[4] उदाहरण के लिए, CVE-2014-1776 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]
एक अन्य दृष्टिकोण बीओइएचएम क वेरिएबल संग्राहक, रूढ़िवादी गार्बेज कलेक्शन (कंप्यूटर विज्ञान) का उपयोग करना है जो क वेरिएबल संग्राहक के साथ C और C++ में मानक मेमोरी आवंटन फंक्शन को प्रतिस्थापित करता है। यह दृष्टिकोण फ्रीज़ को अक्षम करके और गार्बेज कलेक्शन द्वारा वस्तुओं को पुनः प्राप्त करके डैंगलिंग वाली पॉइंटर त्रुटियों को पूरी तरह से समाप्त कर देता है।
जावा जैसी भाषाओं में, डैंगलिंग पॉइंटर्स नहीं हो सकते क्योंकि मेमोरी को स्पष्ट रूप से हटाने के लिए कोई तंत्र नहीं है। इसके अतिरिक्त , कवेरिएबल संग्राहक मेमोरी को हटा सकता है, किन्तु केवल तभी जब वस्तु किसी भी संदर्भ से पहुंच योग्य नहीं होती है।
भाषा रस्ट (प्रोग्रामिंग भाषा) में, प्रकार प्रणाली को विस्तारित किया गया है जिससे वेरिएबल्स लाइफटाइम भी सम्मिलित हो सकें और संसाधन अधिग्रहण प्रारंभ हो सके। जब तक कोई भाषा की विशेषताओं को अक्षम नहीं करता है, डैंगलिंग वाले पॉइंटर्स संकलन समय पर पकड़े जाएंगे और प्रोग्रामिंग त्रुटियों के रूप में रिपोर्ट किए जाएंगे।
डैंगलिंग पॉइंटर डिटेक्शन
डैंगलिंग वाली पॉइंटर त्रुटियों को उजागर करने के लिए, सामान्य प्रोग्रामिंग विधि है कि पॉइंटर्स को नल पॉइंटर या अमान्य पते पर सेट किया जाता है, जब वे जिस स्टोरेज को इंगित करते हैं, वह जारी हो जाता है। जब अशक्त पॉइंटर (अधिकांश भाषाओं में) को संदर्भित किया जाता है, तो कार्यक्रम तुरंत समाप्त हो जाएगा - डेटा भ्रष्टाचार या अप्रत्याशित व्यवहार की कोई संभावना नहीं है। यह अंतर्निहित प्रोग्रामिंग गलती को खोजने और हल करने में आसान बनाता है। जब पॉइंटर की कई प्रतियाँ हों तो यह विधि मदद नहीं करती है।
कुछ डिबगर्स स्वचालित रूप से मुक्त किए गए डेटा को अधिलेखित और नष्ट कर देंगे, सामान्यतः विशिष्ट पैटर्न के साथ, जैसे 0xDEADBEEF
(माइक्रोसॉफ्ट का विसुअल C/C++ डिबगर, उदाहरण के लिए, उपयोग करता है 0xCC
, 0xCD
या 0xDD
जो मुक्त किया गया है उसके आधार पर[7]). यह सामान्यतः डेटा को बेकार और बहुत प्रमुख बनाकर पुन: उपयोग करने से रोकता है (पैटर्न प्रोग्रामर को यह दिखाने के लिए कार्य करता है कि मेमोरी पहले ही मुक्त हो चुकी है)।
पॉलीस्पेस, दुष्ट लहर सॉफ्टवेयर, चुनाव द्वार, मडफ्लैप, जैसे उपकरण[8] पता प्रक्षालक, या एलएलवीएम पर आधारित उपकरण[9] डैंगलिंग वाले पॉइंटर्स के उपयोग का पता लगाने के लिए भी उपयुक्त किया जा सकता है।
अन्य टूल्स (सॉफ्टबाउंड, बीमा ++ , और CheckPointer) साधन स्रोत कोड को इकट्ठा करने के लिए और पॉइंटर्स (मेटाडेटा) के लिए वैध मानो को ट्रैक करें और वैधता के लिए मेटाडेटा के खिलाफ प्रत्येक पॉइंटर एक्सेस की जांच करें।
एक अन्य रणनीति, जब कक्षाओं के छोटे समूह पर संदेह होता है, अस्थायी रूप से अपने सभी मेम्बर फंक्शन को वर्चुअल विधि बनाना है: कक्षा के उदाहरण को नष्ट/मुक्त करने के बाद, वर्चुअल विधि तालिका में इसका पॉइंटर सेट किया गया है NULL
, और फ़ंक्शन के लिए कोई भी कॉल प्रोग्राम को क्रैश कर देगा और यह डीबगर में दोषी कोड दिखाएगा।
यह भी देखें
- सामान्य असुरक्षाएं और जोखिम
- लिंक आरओटी
- मेमोरी डीबगर
- वाइल्डशाखा
संदर्भ
- ↑ "Warning Options - Using the GNU Compiler Collection (GCC)".
- ↑ Gianna Cioni, Antoni Kreczmar, Programmed deallocation without dangling reference, Information Processing Letters, v. 18, 1984, pp. 179–185
- ↑ 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.
- ↑ 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) - ↑ "CVE-2014-1776". Common Vulnerabilities and Exposures (CVE). 2014-01-29. Archived from the original on 2017-04-30. Retrieved 2017-05-16.
- ↑ 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.
- ↑ Visual C++ 6.0 memory-fill patterns
- ↑ Mudflap Pointer Debugging
- ↑ Dhurjati, D. and Adve, V. Efficiently Detecting All Dangling Pointer Uses in Production Servers