C & C++

[C] (strncpy, strncat) vs (strlcpy, strlcat)

  • -
728x90

strn* strl*

 

strlcpy 함수는 strcpy 함수(src 문자를 대상버퍼(dst)에 복사)를 대상 버퍼를 오버플로우 할 수 없는 보안 버전으로 대체하기 위한 것이다. strcat에 대한 유사한 대안을 제공하는 strlcat도 있다.

버퍼 오버플로우를 방지하는 데 사용할 수 있는 표준 C함수strncpy 및 strncat은 올바르게 사용하기 어렵고 느리게 만드는 결함을 가지고 있다. strlcpy  strlcat 은 올바른 사용법이 가능한 한 간단하도록 설계되었다.

 

strlcpy와 strlcat은 Todd C. Miller와 Theo de Raadt에 의해 개발되었으며 OpenBSD 버전 2.4에서 처음 구현되었다. 이후에 libbsd를 통해 FreeBSD (버전 3.3부터), Solaris, Mac OS X 및 GNU 기반 시스템을 포함한 여러 운영 체제에서 채택되었다. 많은 애플리케이션 패키지와 라이브러리에는 glib, rsync, Samba, KDE 및 Linux 커널 자체를 포함하여 이러한 함수의 자체 사본이 포함되어 있다.


뭐 이런저런 이야기들이 많은데, 구현을 통해 어떤 차이인지 알아보자.

 

strn* 함수들이 strl* 함수들보다 비효율적인 이유는 dst의 맨 마지막에 널을 하나만 넣어주느냐(strlcpy) dst의 남은 공간에 size까지 널을 넣느냐의 차이 같다.

strncpy

char	*ft_strncpy(char *dst, const char *src, size_t n)
{
	if ((dst == NULL && src == NULL) || !n)
		return (0);
    while ((n--) && *src)
        *dst++ = *src++;
    while (n--)
        *dst++ = '\0';
    return (dst);
}

strlcpy

size_t  ft_strlcpy(char * dst, const char *src, size_t size)
{
	size_t	src_len;
	size_t	idx;

	if (dst == NULL && src == NULL)
		return (0);
	src_len	=	ft_strlen(src);
	idx		=	0;
	while (idx < src_len && idx + 1 < size)
	{
		dst[idx] = src[idx];
		idx++;
	}
	if (size > 0)
		dst[idx] = '\0';
	return (src_len);
}

 

strncat

char *ft_strncat(char *dst, const char *src, size_t n)
{
    char *ret;
    
    ret = dst;
    while (*dst)
        dst++;
    while (n--)
        if (!(*dst++ = *src++))
            return ret;
    *dst = 0;
    return (ret);
}

strlcat

size_t  ft_strlcat(char *dst, const char *src, size_t size)
{
	size_t  dst_len;
	size_t  src_len;
	size_t	i;
	size_t	j;

	j = 0;
	while (j < size && dst[j])
		j++;
	dst_len = ft_strlen(dst);
	src_len = ft_strlen(src);
	i = 0;
	while (i < src_len && dst_len + i + 1 < size)
	{
		dst[dst_len + i] = src[i];
		i++;
	}
	dst[dst_len + i] = '\0';
	return (j + src_len);
}

 

어찌됐든 이녀석들은 정적으로 메모리에 할당된 버퍼들에 복사할때 유용하고, 만약 정적으로 할당된 dst 크기를 넘어선다면 오류가 발생한다. 따라서 함수 사용자가 잘 생각해서 사용해야한다.

728x90
300x250
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.