- cURL 프로젝트가 기존에 strncpy()를 제거한 데 이어, 이제 strcpy()도 코드베이스에서 완전히 금지함
-
strcpy()는 API가 단순하지만 버퍼 크기 검증이 분리될 위험이 있어, 장기 유지보수 시 안전하지 않음
- 이를 대신해 curlx_strcopy() 라는 새 함수가 도입되어, 대상 버퍼 크기와 문자열 길이를 모두 인자로 받아 복사 가능 여부를 검사 후 수행
- 이 함수는 내부적으로 memcpy()를 사용하며, 널 종료 문자 처리까지 보장함
- 이러한 변경으로 보안성과 코드 일관성을 높이고, AI가 잘못된 취약점 보고를 생성하는 문제도 줄일 수 있음
strcpy 제거 배경
- cURL은 과거에 strncpy() 호출을 모두 제거했으며, 이 함수의 비직관적 API와 널 종료 보장 실패, 불필요한 0 패딩 문제를 지적함
- 부분 문자열 복사가 필요한 경우 memcpy()를 사용하고 널 종료를 직접 처리하도록 변경
-
strcpy()는 API가 단순하지만 버퍼 크기를 명시하지 않아 유지보수 중 검증 코드와 복사 호출이 분리될 위험이 있음
- 코드가 수십 년간 여러 개발자에 의해 수정될 경우, 버퍼 크기 검증이 무력화될 가능성이 존재
새로운 문자열 복사 함수 도입
- 이러한 위험을 방지하기 위해 curlx_strcopy() 라는 대체 함수를 도입
- 인자로 대상 버퍼, 버퍼 크기, 원본 버퍼, 원본 문자열 길이를 받음
- 복사와 널 종료가 모두 가능한 경우에만 memcpy()로 수행
- 실패 시 대상 버퍼를 빈 문자열로 초기화
- 이 함수는 strcpy()보다 더 많은 인자와 코드량이 필요하지만, 버퍼 검증을 복사와 밀접하게 결합해 안전성을 확보
- cURL 코드베이스에서 strcpy() 사용을 완전히 금지하고, strncpy()와 동일하게 제거
구현 세부
- 함수 정의 예시는 다음과 같음
void curlx_strcopy(char *dest, size_t dsize, const char *src, size_t slen)
{
DEBUGASSERT(slen < dsize);
if(slen < dsize) {
memcpy(dest, src, slen);
dest[slen] = 0;
}
else if(dsize)
dest[0] = 0;
}
-
DEBUGASSERT를 통해 개발 중 오류를 조기 탐지하며, 실제 배포 환경에서는 항상 성공하도록 설계
-
strcpy처럼 반환값이 없으며, 테스트 및 퍼징 단계에서 오류를 잡는 방식을 채택
커뮤니티 반응
- 일부 개발자는 strcpy_s()(C11 Annex K) 와 유사하다고 지적했으나, cURL은 여전히 C89 표준을 사용 중
- 다른 의견으로는 반환값 추가 필요성이나 버퍼 실패 시 처리 방식 개선 제안이 있었음
- 이에 대해 cURL 측은 “항상 성공하는 함수로 설계되었기 때문에 반환값은 불필요하다”고 설명
AI 관련 부가 효과
- 이번 변경으로 AI 챗봇이 cURL 코드에서 strcpy 사용을 잘못 탐지해 ‘취약하다’고 주장하는 문제를 방지할 수 있음
- 다만, 작성자는 “AI가 다른 허위 보고를 만들어낼 가능성은 여전하다”며 AI 기반 코드 분석의 한계를 언급