FlawOpen

flawopen.com/मेमोरी सुरक्षा/strcpy vs strncpy

क्या strncpy(), strcpy() से अधिक सुरक्षित है?

CWE-787: सीमा से बाहर लेखन; CWE-170: अनुचित null terminationसंदर्भ पृष्ठ
संक्षिप्त उत्तर

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 में भी प्रासंगिक थी।

आम सवाल

strcpy_s और Annex K functions के बारे में क्या?

वे string terminate और bounds check करते हैं, लेकिन portability समान नहीं है: Windows पर अच्छा समर्थन और अन्य जगहों पर असमान implementation है। कई platforms के लिए snprintf अधिक उपलब्ध विकल्प है।

क्या strlcpy C standard में है?

नहीं। यह OpenBSD में शुरू हुआ और BSD तथा macOS पर उपलब्ध है; नए glibc में भी जोड़ा गया है। अपने target platforms पर उपलब्धता जाँचें।

C++ में इनमें से क्या उपयोग करना चाहिए?

लंबाई संभालने वाले std::string और std::string_view को प्राथमिकता दें। C functions केवल उस API सीमा पर लें जिसे raw buffer चाहिए।

संदर्भ

यह भी देखें CWE बनाम CVE: क्या अंतर है? Mass Assignment: जोखिम और सुरक्षित field allowlist Serverless डेटा रिसाव: अनुरोध के अनुसार अलगाव PHP == और Magic Hash तुलना क्या Rust का unsafe ब्लॉक मेमोरी-सुरक्षित है?