flawopen.com/मेमोरी सुरक्षा/strcpy vs strncpy
क्या strncpy(), strcpy() से अधिक सुरक्षित है?
Fixed-width field को खानों की कतार समझें: यदि आगे का code bytes को C string मानेगा, तो आखिरी खाने में end marker चाहिए। strncpy() अधिकतम n bytes लिखता है और destination से बाहर तभी नहीं लिखता जब n वास्तविक buffer क्षमता से बड़ा न हो। Source सीमा भर दे तो null terminator नहीं जुड़ता। बाद का string function उस marker को खोजते हुए destination के बाहर पढ़ सकता है।
char dst[16]; /* 1. Unbounded — classic overflow */ strcpy(dst, src); /* 2. Bounded, but may not terminate. If strlen(src) >= 16, dst has no '\0' and every later strlen/printf reads out of bounds. */ strncpy(dst, src, sizeof(dst)); /* 3. Off-by-one: room for 16 chars plus a terminator = 17 bytes, but dst only holds 16. */ strncpy(dst, src, sizeof(dst)); dst[sizeof(dst)] = '\0'; /* OOB! */
char dst[16]; /* Preferred: snprintf always null-terminates (when size > 0), and tells you about truncation. */ int n = snprintf(dst, sizeof(dst), "%s", src); if (n < 0 || (size_t)n >= sizeof(dst)) { /* truncated — handle it */ return ERR_TOO_LONG; } /* Or strlcpy where available — always terminates, returns the length it tried to create. */ if (strlcpy(dst, src, sizeof(dst)) >= sizeof(dst)) { return ERR_TOO_LONG; }
strncpy वास्तव में किस काम के लिए बना था
यह व्यवहार defect नहीं है: strncpy() fixed-width, null-padded fields के लिए बनाया गया था, सामान्य सुरक्षित C-string copy के लिए नहीं। Source string n से छोटी हो तो यह destination को n - 1 byte तक null bytes से भरता है। यदि source के पहले n bytes में null byte न हो, तो यह ठीक n bytes copy करता है और destination terminate नहीं करता। यह कुछ fixed-width formats के लिए सही है, लेकिन null-terminated string माँगने वाले API को देने पर खतरनाक है।
Source n से छोटी होने पर padding पूरे field width तक लिखता है। बड़े buffer और छोटी source के लिए यह terminator पर रुकने वाली copy से अधिक काम कर सकता है।
Truncation हमेशा जाँचें
Overflow रोकना केवल आधा काम है। चुपचाप truncation भी सुरक्षा समस्या है: छोटा हुआ hostname, path या authorization value अर्थ बदल सकता है। snprintf वह लंबाई लौटाता है जिसे वह लिखना चाहता था; इसे buffer size से तुलना करें। इस मान को वास्तव में लिखे bytes समझने की गलती Citrix Bleed में भी प्रासंगिक थी।
आम सवाल
वे string terminate और bounds check करते हैं, लेकिन portability समान नहीं है: Windows पर अच्छा समर्थन और अन्य जगहों पर असमान implementation है। कई platforms के लिए snprintf अधिक उपलब्ध विकल्प है।
नहीं। यह OpenBSD में शुरू हुआ और BSD तथा macOS पर उपलब्ध है; नए glibc में भी जोड़ा गया है। अपने target platforms पर उपलब्धता जाँचें।
लंबाई संभालने वाले std::string और std::string_view को प्राथमिकता दें। C functions केवल उस API सीमा पर लें जिसे raw buffer चाहिए।