समस्या यहाँ है:
strncpy(buffer,str,strlen(str));
^^^^^^^^^^^
यदि स्ट्रिंग लक्ष्य बफर की लंबाई से अधिक है, तो strncpy अभी भी इसे कॉपी करेगा। आप बफर के आकार के बजाय कॉपी करने के लिए स्ट्रिंग के पात्रों की संख्या को आधार बना रहे हैं। ऐसा करने का सही तरीका इस प्रकार है:
strncpy(buffer,str, sizeof(buff) - 1);
buffer[sizeof(buff) - 1] = '\0';
यह क्या करता है शून्य समाप्ति चरित्र के लिए बफर माइनस एक के वास्तविक आकार में कॉपी किए गए डेटा की मात्रा को सीमित करता है। फिर हम बफर में अंतिम बाइट को एक अतिरिक्त सुरक्षा के रूप में शून्य वर्ण में सेट करते हैं। इसका कारण यह है क्योंकि strncpy n बाइट्स तक की प्रतिलिपि बना देगा, जिसमें समाप्ति नल भी शामिल है, यदि strlen (str) <len - 1. यदि नहीं, तो null की प्रतिलिपि नहीं बनाई गई है और आपके पास एक क्रैश परिदृश्य है क्योंकि अब आपके बफ़र में एक अव्यवस्थित है स्ट्रिंग।
उम्मीद है की यह मदद करेगा।
संपादित करें: दूसरों से आगे की परीक्षा और इनपुट पर, फ़ंक्शन के लिए एक संभावित कोडिंग निम्नानुसार है:
int func (char *str)
{
char buffer[100];
unsigned short size = sizeof(buffer);
unsigned short len = strlen(str);
if (len > size - 1) return(-1);
memcpy(buffer, str, len + 1);
buffer[size - 1] = '\0';
return(0);
}
चूँकि हम पहले से ही स्ट्रिंग की लंबाई जानते हैं, इसलिए हम स्ट्रिंग को उस स्थान से कॉपी करने के लिए मेम्पी का उपयोग कर सकते हैं, जिसे बफर में स्ट्रिंग द्वारा संदर्भित किया गया है। ध्यान दें कि strlen (3) (FreeBSD 9.3 सिस्टम पर) के लिए मैनुअल पेज के अनुसार, निम्नलिखित कहा गया है:
The strlen() function returns the number of characters that precede the
terminating NUL character. The strnlen() function returns either the
same result as strlen() or maxlen, whichever is smaller.
जो मैं व्याख्या करता हूं कि स्ट्रिंग की लंबाई में शून्य शामिल नहीं है। यही कारण है कि मैं अशक्त शामिल करने के लिए लेन + 1 बाइट्स की प्रतिलिपि बनाता हूं, और यह सुनिश्चित करने के लिए परीक्षण की जांच करता है कि लंबाई <बफर का आकार - 2. शून्य से एक क्योंकि बफर स्थिति 0 पर शुरू होता है, और शून्य से एक और सुनिश्चित करने के लिए एक कमरा है। अशक्त के लिए।
संपादित करें: बाहर निकलता है, कुछ का आकार 1 से शुरू होता है जबकि पहुंच 0 से शुरू होती है, इसलिए -2 पहले गलत था क्योंकि यह किसी भी चीज के लिए त्रुटि लौटाएगा> 98 बाइट लेकिन यह> 99 बाइट होना चाहिए।
EDIT: यद्यपि एक अहस्ताक्षरित शॉर्ट के बारे में उत्तर आम तौर पर सही होता है क्योंकि अधिकतम लंबाई जिसे 65,535 वर्णों का प्रतिनिधित्व किया जा सकता है, यह वास्तव में मायने नहीं रखता है क्योंकि यदि स्ट्रिंग उससे अधिक लंबी है, तो मान चारों ओर लपेट जाएगा। यह 75,231 (जो कि 0x000125DF है) लेने और शीर्ष 16 बिट्स को आप 9695 (0x000025DF) देने की तरह है। एकमात्र समस्या जो मुझे इसके साथ दिखाई देती है, वह 65,535 के पिछले 100 वर्णों की है, क्योंकि लंबाई की जाँच प्रतिलिपि की अनुमति देगी, लेकिन यह केवल सभी मामलों में स्ट्रिंग के पहले 100 वर्णों की नकल करेगा और स्ट्रिंग को समाप्त कर देगा । तो रैपराउंड मुद्दे के साथ, बफर अभी भी बह नहीं जाएगा।
यह स्ट्रिंग की सामग्री और आप इसके लिए क्या उपयोग कर रहे हैं, इसके आधार पर सुरक्षा जोखिम हो सकता है या नहीं। यदि यह केवल सीधे पाठ है जो मानव पठनीय है, तो आमतौर पर कोई समस्या नहीं है। आपको बस एक काट दिया गया स्ट्रिंग मिलता है। हालाँकि, अगर यह URL या SQL कमांड अनुक्रम जैसा कुछ है, तो आपको समस्या हो सकती है।