2009-05-26 17 views
5

मैं निम्नलिखित सी कोड टुकड़ा है और त्रुटि की पहचान करनी है और इसे और अधिक सुरक्षित रूप से लेखन का एक तरीका सुझाव देते हैं:यह सी टुकड़ा कैसे अधिक सुरक्षित रूप से लिखा जा सकता है?

char somestring[] = "Send money!\n"; 
char *copy; 

copy = (char *) malloc(strlen(somestring)); 

strcpy(copy, somestring); 
printf(copy); 

तो त्रुटि है कि strlen एक स्ट्रिंग के अनुगामी '\0' पर ध्यान नहीं देता है और इसलिए यह नहीं है प्रतिलिपि के लिए पर्याप्त स्मृति आवंटित करने जा रहा है, लेकिन मुझे यकीन नहीं है कि वे इसे और अधिक सुरक्षित रूप से लिखने के बारे में क्या प्राप्त कर रहे हैं?

मैं केवल malloc(strlen(somestring)+1)) का उपयोग कर सकता हूं, लेकिन मुझे लगता है कि इससे बेहतर तरीका होना चाहिए?


संपादित करें: ठीक है, मैं एक जवाब स्वीकार कर लिया है, मुझे लगता है कि strdup समाधान हम से उम्मीद नहीं की जाएगी के रूप में यह एएनएसआई सी का हिस्सा यह काफी एक व्यक्तिपरक सवाल तो मैं हो रहा है नहीं है मुझे यकीन नहीं है कि मैंने जो स्वीकार किया है वह वास्तव में सबसे अच्छा है। वैसे भी सभी उत्तरों के लिए धन्यवाद।

उत्तर

4
char somestring[] = "Send money!\n"; 
char *copy; 
size_t copysize; 

copysize = strlen(somestring)+1; 
copy = (char *) malloc(copysize); 
if (copy == NULL) 
    bail("Oh noes!\n"); 

strncpy(copy, somestring, copysize); 
printf("%s", copy); 
ऊपर

प्रसिद्घ मतभेद:

  • malloc() का परिणाम जाँच की जानी चाहिए!
  • गणना और स्टोर स्मृति आकार!
  • strncpy() का उपयोग करें क्योंकि strcpy() शरारती है। इस संक्रमित उदाहरण में यह चोट नहीं पहुंचाएगा, लेकिन इसका उपयोग करने की आदत में न आएं।

संपादित करें:

मैं strdup() का उपयोग करना चाहिए सोच लोगों के लिए

... कि तभी काम करता है आप सवाल का बहुत संकीर्ण दृश्य ले लो। आप कुंठित हो सकता है, कम से कम उस पर अच्छा हो जा रहे हैं

char somestring[] = "Send money!\n"; 
char *copy = somestring; 
printf(copy); 

: यह यह एक और भी बेहतर जवाब अनदेखी है मूर्ख न केवल है,।

+3

+1 strncpy के उपयोग के लिए। यह इतने सारे सुरक्षा छेद का स्रोत है, यह मजाकिया नहीं है। –

+8

strncpy() का उपयोग करना बुरी तरह से strcpy() का उपयोग करने से भी बदतर है। यदि आप strncpy() का उपयोग करते हैं, तो आप * नहीं * गारंटीकृत शून्य समाप्त आउटपुट (यह उदाहरण ठीक है, लेकिन सामान्य रूप से नहीं)। साथ ही, यदि आप तीसरे पैरामीटर के लिए strncpy() पर ओवर-साइज बफर और आकार (बफर) का उपयोग करते हैं, तो आपके हाथों पर एक प्रदर्शन मिनी-आपदा है; strncpy() प्रतिलिपि डेटा को पूरी लंबाई में शून्य-पैड शून्य-पैड। * हाँ * स्रोत और लक्ष्य तारों की लंबाई जानने के लिए; यदि आप इसे सही तरीके से करते हैं, तो strcpy() का उपयोग करके strncpy() के अंधेरे उपयोग से सुरक्षित और सुरक्षित है। (यदि यह कोई मदद है, तो strncat() बहुत दूर है, strncpy() से कहीं भी बदतर है; इसका कभी भी उपयोग न करें!) –

+1

जोनाथन, strlcpy() बहुत अधिक है। जब भी यह उपलब्ध हो, मैं इसका उपयोग करता हूं, और कभी-कभी मैं एक संस्करण के साथ लाता हूं जब यह नहीं होता है। बहुत बुरा ड्रेपर ऐसा डोर है। – dwc

6
char somestring[] = "Send money!\n"; 
char *copy = strdup(something); 

if (copy == NULL) { 
    // error 
} 

या सिर्फ एक अलग समारोह xstrdup में इस तर्क रख:

char * xstrdup(const char *src) 
{ 
    char *copy = strdup(src); 

    if (copy == NULL) { 
     abort(); 
    } 

    return copy; 
} 
+5

यह ध्यान देने योग्य है कि strdup() है एएनएसआई सी –

+1

का हिस्सा नहीं होना चाहिए: यदि (कॉपी == न्यूल) { – hiena

+2

यदि आपकी सी लाइब्रेरी के लिए strdup() मौजूद नहीं है, तो आपको इसे लिखना चाहिए। इसका मतलब है कि आपके पास एक बिंदु है जहां सैकड़ों की बजाय एक बग हो सकती है। –

-2

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

char somestring[] = "Send money!\n"; 
char *copy; 

copy = (char *) malloc(strlen(somestring)); 

strncpy(copy, somestring, strlen(somestring)); 
printf(copy); 
+0

strncpy के लिए +1; किसी और चीज से अधिक, जो इस कोड को सुरक्षित बनाता है। कम से कम मॉलोक विफलता मामले में, आप segfault करेंगे; strcpy() पागल सुरक्षा छेद के लिए अनुमति देता है जो खोजने के लिए मुश्किल हैं। –

+1

-1 एक-ऑफ त्रुटि और मेमोरी भ्रष्टाचार के लिए –

+0

@McWafflestix: नहीं, इस मामले में, strncpy() का दुरुपयोग किया जाता है और परिणाम एक गड़बड़ है। जैसा कि हारून डिगुल्ला बताते हैं, strncpy() को कॉल की लंबाई 'strlen (somestring) +1' की आवश्यकता होती है; जैसा कि लिखा गया है, प्रतिलिपि की गारंटी है कि इसे निरस्त न किया जाए। Printf() सामान्य रूप से खतरनाक है - एक यादृच्छिक स्ट्रिंग का उपयोग करके printf() के प्रारूप के रूप में खराब है (puts() शायद यहां सेन पसंद के नजदीक है)। (कल्पना कीजिए "20% अतिरिक्त पैसे भेजें!" इसके बजाए! –

3
  1. strlen + 1, के लिए \ 0 टर्मिनेटर
  2. malloc विफल हो सकता है; हमेशा malloc वापसी मान की जाँच
0

इसे अधिक सुरक्षित रूप से लिखने का सबसे अच्छा तरीका, अगर कोई ऐसी चीज़ में वास्तव में रूचि रखता है, तो उसे एडा में लिखना होगा।

somestring : constant string := "Send money!"; 
declare 
    copy : constant string := somestring; 
begin 
    put_line (somestring); 
end; 

वही परिणाम, तो अंतर क्या हैं?

  • पूरी बात स्टैक (कोई पॉइंटर्स) पर नहीं की जाती है। Deallocation स्वचालित और सुरक्षित है।
  • सब कुछ स्वत: सीमा-चेक किया जाता है तो वहाँ बफर-अतिप्रवाह का कोई मौका नहीं कारनामे
  • दोनों तार स्थिरांक हैं है, तो वहाँ पंगा लेना और उन्हें संशोधित करने का कोई मौका नहीं है।
  • शायद यह गतिशील आवंटन की कमी के कारण सी 0 की तुलना में तेज होगा, लेकिन स्ट्रेल() द्वारा आवश्यक स्ट्रिंग के माध्यम से अतिरिक्त स्कैन नहीं है।

ध्यान दें कि एडा "स्ट्रिंग" में कुछ विशेष गतिशील निर्माण नहीं है। यह वर्णों की अंतर्निहित सरणी है। हालांकि, आपके द्वारा असाइन किए गए सरणी द्वारा घोषणा में एडा एरे का आकार बदला जा सकता है।

3

आईक ... strdup() का उपयोग करें जैसे सभी ने कहा और यदि आपको करना है तो इसे स्वयं लिखें। चूंकि आपके पास अब इस बारे में सोचने का समय है ... 25 Most Dangerous Programming Errors at Mitre देखें, फिर विचार करें कि printf(copy) वाक्यांश कभी कोड में दिखाई दे सकता है। यही कारण है कि यह दु: ख के बहुत सारे कारण बनता है जब प्रतिलिपि "%s%n" की तरह कुछ है पर नज़र रखने के सिरदर्द का उल्लेख नहीं करने के लिए सही वहाँ malloc(strlen(str)) साथ बोलना बुराई के मामले में है ...

7

मैं ऊपर प्रतिक्रियाओं पर टिप्पणी नहीं कर सकता, लेकिन वापसी कोड जाँच और strncpy का उपयोग कर के अलावा, आपको क्या करना चाहिए कभी नहीं:

printf(string) 

लेकिन का उपयोग करें:

printf("%s", string); 

रेफरी: http://en.wikipedia.org/wiki/Format_string_attack

+2

+1। जब आपके पास लाइब्रेरी फ़ंक्शन होता है तो पहिया को फिर से न चलाएं। –

1

मैं पिछले समाधानों पर टिप्पणी करता हूं लेकिन मेरे पास पर्याप्त प्रतिनिधि नहीं है। strncpy का उपयोग करना strcpy (जैसा कि ओवरफ़्लो का बिल्कुल कोई जोखिम नहीं है) का उपयोग करना गलत है। memcpy< string.h> में एक फ़ंक्शन है और यह वास्तव में इसके लिए है। यह केवल काफी तेजी नहीं है, लेकिन यह भी सही समारोह मानक सी

में ज्ञात लंबाई के तार कॉपी करने के लिए स्वीकार किए जाते हैं जवाब से उपयोग करने के लिए:

char somestring[] = "Send money!\n"; 
char *copy; 
size_t copysize; 

copysize = strlen(somestring)+1; 
copy = (char *) malloc(copysize); 
if (copy == NULL) 
    bail("Oh noes!\n"); 

memcpy(copy, somestring, copysize); /* You don't use str* functions for this! */ 
printf("%s", copy); 
+0

-1 में अप्रत्याशित सुरक्षा छेद के लिए –

+0

@Aaron जैसा कि पहले उल्लेख किया गया है, strdup() एएनएसआई नहीं है, यह सभी प्रणालियों पर मौजूद नहीं होगा। जब आप strdup() का अपना संस्करण लिखते हैं तो इस उत्तर का बिंदु लागू किया जा सकता है। – Trent

1

तरीके बनाने के लिए कोड सुरक्षित (और अधिक सही)।

  1. एक अनावश्यक प्रतिलिपि न बनाएं। उदाहरण से, आपको कोई स्पष्ट आवश्यकता नहीं है कि आपको वास्तव में somestring कॉपी करने की आवश्यकता है। आप इसे सीधे आउटपुट कर सकते हैं।
  2. यदि आपको स्ट्रिंग की एक प्रति बनाना है, तो ऐसा करने के लिए एक फ़ंक्शन लिखें (या यदि आपके पास स्ट्रडअप है तो इसका उपयोग करें)। तब आपको केवल एक ही स्थान पर इसे सही करना होगा।
  3. जब भी संभव हो, जब आप इसे घोषित करते हैं तो प्रतिलिपि को तुरंत प्रतिलिपि में प्रारंभ करें।
  4. शून्य टर्मिनेटर के लिए स्थान आवंटित करना याद रखें।
  5. malloc से वापसी मूल्य की जांच करना याद रखें।
  6. malloc 'ed memory को मुक्त करना याद रखें।
  7. अविश्वसनीय प्रारूप स्ट्रिंग के साथ printf पर कॉल न करें। printf("%s", copy) या puts(copy) का उपयोग करें।
  8. इन समस्याओं में से अधिकांश से बचने के लिए एक स्ट्रिंग क्लास या अंतर्निहित स्ट्रिंग समर्थन वाली किसी भी भाषा के साथ ऑब्जेक्ट-उन्मुख भाषा का उपयोग करें।
1

त्रुटियों के इस प्रकार की खोज करने में सुरक्षित कोड बनाने के लिए एड्रियन मैककार्थी के तरीके के लिए और अधिक जोड़ने के लिए,

एक स्थिर कोड विश्लेषक का उपयोग करें, वे बहुत अच्छे हैं