2009-04-06 5 views
2

char 배열이 함수로 전달되고 결과를 출력으로 쓰여진 문자열로 사용하여 C 코드를 유지 관리합니다. 그러나 함수에 의해 처리 된 후에 배열에 대해 수행 된 검사는 없으며 취할 수있는 최선의 방법이 무엇인지 궁금합니다.함수에서 돌아올 때 char []를 보호하는 최선의 방법은 무엇입니까?

한 가지 방법은 배열의 마지막 요소를 반환 한 후 \ 0으로 설정하는 것이지만 더 나은 방법이있을 것이라고 생각합니다.

void Unpack(char* inbuf, char* outbuf); 

int main(int argc, char* argv[]) 
{ 
    char* inData = "abc"; 
    char outData[4]; 
    char result[14]; 

    Unpack(inData, outData); 
    outData[3] = '\0'; // Insert this to safeguard array before using as string. 

    _snprintf(result, sizeof(result), "blah %0s blah", outData); 
    printf(result); 

    return 0; 
} 

void Unpack(char* inbuf, char* outbuf) { 
    for(int index=0; index<3; index++) { 
     *outbuf++ = *inbuf++; 
    } 
} 

답변

4

두 코드를 소유하고 있다면 더 나은 방법은 출력 버퍼 크기를 전달하기 위해 서명을 변경하는 것이므로 '\ 0'문자를 추가 할 책임이 있습니다.

언팩을 제어 할 수없는 경우 작업을 수행 할 얇은 레이어를 작성합니다. 당신 만이 아닌 널 (null)에 대해 보호 할 수있는이와

unpack_safe(char *in, char* out, size_t len) { 
    unpack(in, out); 
    out[len-1]='\0'; 
} 

문자열을 종료하지만, 문자열이 할 수있는 당신이 널 (null) 문자가 포함 된 경우이 예상대로 작동하지 않습니다, 그리고 INTPUT 크기 & 출력 크기를 전달하는 것은 올바른 동작 할 것이다.

4

무엇으로부터 보호합니까? 버퍼 오버런과 같은 것을 방지하려는 경우 너무 늦었습니다. 호출 한 기능에는 사용 및 악용에 대한 모든 권한이 있으며, 선택이 "남용"이었다면 사실 이후에 할 수있는 일이 많지 않습니다.

+0

MarkusQ 잘되는 호출되는 함수에 버퍼 길이를 전달하는 것이 좋습니다. "감지", 즉 메모리 겹쳐 쓰기를 감지 했습니까? – jdigital

+0

아니요. outData가 snprintf 호출에서 사용되면 예기치 않은 결과가 발생하지 않도록하는 데 더 관심이 있습니다. 언팩 기능이 제 통제에서 벗어났습니다. – sipwiz

5

이 문제에 대한 해결책은 두 가지가 있지만, 불행히도 다룰 수없는 다른 많은 문제가 있습니다.

출력 배열에 올바른 '\ 0'종료 C 문자열이 없을 수도 있다고 생각되면 무차별 대입으로 '\ 0'을 삽입하여 해당 문제를 해결했습니다. 또한 최적의 위치를 ​​선택 했으므로 배열의 마지막 바이트는 배열에 '\ 0'종료 문자열을 포함해야하는 경우 사용할 수 없습니다.

불행히도, 호출 된 함수가 할당 된 배열을 넘어 메모리를 넘어서서 짓밟을 수는 없습니다. 그것이 제가 걱정할 가장 중요한 것입니다.

메모리 트램 핑 (버퍼 오버 플로우라고도 함)을 피하는 것은 로켓 과학이 아니라 규율과 일관성을 요구합니다. 일반적으로 관련된 기본 아이디어는 채워지는 일부 메모리의 주소를 단순히 전달하는 것이 아니라 사용 가능한 메모리 블록의 길이로 항상 그 주소를 동반하는 것입니다. 물론 호출 된 코드는 이와 같이 부과 된 제한을 존중해야합니다. 이 접근법의 고전적인 예인 snprintf()를 언급 한 이후로 기본적인 아이디어를 알고있는 것처럼 보입니다.

1

원시 포인터를 사용하면 항상 버퍼 오버런이 발생할 수 있습니다. std :: string, CString 등의 래퍼 클래스를 사용하는 것이 항상 안전합니다.

이 코드는 작성한 새 코드에 유용합니다. 이와 같은 기존 코드의 경우 충돌이 발생하지 않도록기도 할 수 있습니다.

1

0x55AA 또는 일부 예약 문자와 같이 END-MARKER가 걱정된다면. 그러나 걱정되는 데이터의 무결성이 있다면 일부 체크섬 또는 CRC (Cyclic Redundancy Check)로 일부 헤더를 시도 할 수 있습니다.

3

마지막 요소를 '\ 0'으로 설정하면 문자열이 올바르게 종료되지만 함수가 버퍼 외부에서 작성한 손상은 수정되지 않습니다.이 경우 버그 만 숨기고 프로그램은 나중에 완전히 관련없는 함수 호출이나 반환 할 때 잘못된 결과를 생성하거나 충돌 할 수 있습니다.

필자의 의견으로는, 함수가 버퍼 외부에 쓴다면 프로그램을 중단시키는 것이 더 좋을 것입니다. 이로 인해 오류를 쉽게 찾고 수정할 수 있습니다. 이를 달성하기 위해 함수를 호출하기 전에 버퍼의 마지막 바이트를 '\ 0'으로 설정하고 함수가 반환 될 경우에도 assert()를 사용하여 test를 테스트 할 수 있습니다. 빌 포스터는 이미 언급 한 바와 같이

는 그리고, 그것은 또한

관련 문제