C언어의 strcpy는 문자열을 복사하는 함수입니다. 버퍼 오버플로우, BOF에 주의해야 하는 함수 중 하나입니다. 사용법은 다음과 같습니다.

 

 

char *strcpy(char *dest,const char *ori);

 

 

 ori는 복사할 문자열, dest는 붙여 넣을 곳을 의미합니다. 그러면, 위치 ori부터 시작해서 널 문자를 만날 때 까지, dest부터 차례대로 복사한다는 의미가 되겠습니다. 몇 가지 예제를 보면서 이해해 보도록 하겠습니다.

 

 


 

 먼저, src에 "aba"라는 것이 저장되어 있습니다. dest에 "aba"를 복사하려면 어떻게 쓰면 좋을까요? 복사할 문자열의 시작 위치는 src입니다. 이것을 노란색으로 표시해 보겠습니다.

 

 

 그리고 복사가 시작될 위치를 초록색으로 표시해 보겠습니다.

 

 

 dest입니다. 그런가요? 따라서, strcpy(dest,src); 를 쓰면, string src가, dest에 복사가 된다는 것을 의미합니다.

 

 

 이렇게 복사가 되겠네요. 즉, src는 원본, dest는 복사될 위치를 지정해 주면 되는 겁니다.

 

 


 str이 "A-900"입니다. pat에 "900"을 복사하고 싶습니다. 어떻게 하면 좋을까요?

 

 

 original은 어디에 있나요? str+2에 있어요. 이것부터 어디까지 복사를 하나요? str의 끝까지. 그러니까 NULL 문자를 만날 때 까지. 이것을 어디에 복사할 거에요? pat에다가.

 

 

 그러면, 다음과 같이 프로그램을 작성하면 될 거에요.

 

 

 출력 결과는 900입니다.

 

 


 문제 상황을 하나 주겠습니다. 반지가 M개 있습니다. i번째 반지에 새겨진 문자열 R(i)가 주어집니다. R(i)의 0번째 문자는 시작점에 있는 문자를, R(|R(i)|-1)에 있는 문자는 끝점에 있는 문자를 의미합니다. 또, 끝점과 시작점은 이어져 있습니다. 여기서, ring을 시작점에서 끝점으로 향하는 방향으로 읽었을 때, pat이라는 부분 패턴을 찾을 수 있는지 어떻게 판단하면 좋을까요?

 

 가장 좋은 방법은 String 뒤에 또 다시 String을 붙이는 겁니다. 예를 들어서, R(i)가 "ab"였다고 해 봅시다.

 

 

 그러면, "ab" 뒤에 "ab"가 붙여지기 위해서는, 어떻게 하면 좋을까요? 복사가 될 original 배열은 노란색으로, 복사가 될 최초 위치는 초록색으로 표시했습니다.

 

 

 ln을 S(i)의 길이라고 합시다. 그러면, &(s[ln])은 초록색으로 칠한 위치이고, &(s[0])은 노란색으로 칠한 문자열의 시작 위치쯤 될 겁니다. 이렇게 하면 정상적으로 실행이 되는 거 같습니다. 실제로 이 코드로 str 뒤에 str을 붙이는 알고리즘을 수행한 후에 strstr로 패턴을 찾으면, 백준에서는 맞았다고 뜹니다.

 

 그런데, 사실 이는 올바른 코드가 아닙니다. 왜냐하면 dest하고, ori하고 overlap 되기 때문입니다. memcpy와 마찬가지로, 이러한 경우 행동이 정의되지 않아요.

 

 

 strcpy는 overlap이 되는 케이스에 대해서도 취약합니다. 이 경우 또한 마찬가지로 문제될 소지가 있습니다. 따라서, 이 때에는 strcpy를 쓰지 말고, 아래와 같이 처리하는 것이 안전한 방법입니다.

 

 

 이렇게 처리를 하면, memory가 overlap 되는 경우에도 잘 처리할 수 있습니다.

 

 

 널 문자를 만나던 말던 상관 없이, 정확히 ln번만 돌기 때문입니다.