source

C에서 함수를 가져옵니다.

manysource 2023. 10. 17. 20:23

C에서 함수를 가져옵니다.

나는 그것을 사용하는 것이 꽤 멋지다고 생각했습니다.gets()기능을 하는 이유는 그것이 마치scanf()빈 공간으로 입력을 받을 수 있을 겁니다그런데 쓰레드(학생 정보 파일 취급) 중 하나에서 읽었는데, 그들에 따르면 버퍼 오버플로를 만드는 데 악마의 도구이기 때문에 사용하기에 좋지 않다고 합니다(이해할 수 없습니다).

가 을 쓰면.gets()기능, 나는 이것을 할 수 있습니다.이름 입력:Keanu Reeves.

가 을 쓰면.scanf(), 나는 이것밖에 할 수 없었습니다.이름 입력:Keanu

그래서 나는 그들의 조언에 귀를 기울이고 나의 모든 것을 대체했습니다.gets()암호화하다fgets()는 지금 내 중 가 더 문제는 지금 내 코드 중 일부가 더 이상 작동하지 않는다는 것입니다.이외에 다른 기능이 있습니까?gets()그리고.fgets()줄 전체를 읽을 수도 있고 여백을 무시할 수도 있습니다.

버퍼 오버플로를 만들기 위한 악마의 도구입니다.

길이 매개변수를 사용하지 않기 때문에 입력 버퍼의 크기를 알 수 없습니다.10자 버퍼를 입력하고 사용자가 100자를 입력하면 포인트를 얻을 수 있습니다.

fgets 보다 안전한 대안입니다.gets버퍼 길이를 매개 변수로 사용하므로 다음과 같이 부를 수 있습니다.

fgets(str, 10, stdin);

최대 9자까지 읽을 수 있습니다.

문제는 지금 내 코드 중 일부가 더 이상 작동하지 않는다는 것입니다.

이것은 아마도fgets또한 최종 새 선을 저장합니다(\n버퍼에 있는 문자 - 코드에서 이를 예상하지 않는 경우 수동으로 제거해야 합니다.

int len = strlen(str);
if (len > 0 && str[len-1] == '\n')
  str[len-1] = '\0';

다른 응답자들이 언급했듯이,gets()버퍼 공간을 확인하지 않습니다.이 취약성은 실수로 발생한 오버플로 문제 외에도 악의적인 사용자가 모든 종류의 대혼란을 일으키는 데 사용될 수 있습니다.

1988년에 출시된 최초의 널리 퍼진 벌레들 중 하나는gets()인터넷을 통해 자신을 선전하는 것입니다.다음은 피터 반 데어 린든(Peter Van Der Linden)의 Expert C Programming에서 발췌한 재미있는 내용입니다.

초기 버그로 인해 인터넷 웜이 발생합니다.

C의 문제는 단지 언어에만 국한된 것이 아닙니다.표준 라이브러리의 일부 루틴에는 안전하지 않은 의미론이 있습니다.이것은 1988년 11월에 인터넷 네트워크의 수천 개의 기계를 통해 꿈틀꿈틀 움직이는 웜 프로그램에 의해 극적으로 증명되었습니다.연기가 걷히고 조사가 완료되었을 때, 벌레가 번식한 한가지 방법은 약함을 통해서라고 판단되었습니다.finger현재 로그인되어 있는 사용자에 대한 질의를 네트워크를 통해 수락하는 데몬.finger몬,in.fingerd, 표준 입출력 루틴을 사용했습니다.gets().

의 공칭 작업.gets()스트림에서 문자열을 읽는 것입니다.전화를 건 사람이 문자를 어디에 두어야 하는지 알려주지만,gets()는 버퍼 공간을 확인하지 않으며, 실제로는 버퍼 공간을 확인할 수 없습니다.호출자가 스택에 포인터를 제공하고 버퍼 공간보다 많은 입력을 제공하는 경우,gets()스택을 행복하게 덮어쓸 것입니다.finger데몬은 다음과 같은 코드를 포함하고 있습니다.

main(argc, argv)
char *argv[];
{
char line[512];
...
gets(line);

여기서,line는 스택에 자동으로 할당되는 512바이트 배열입니다.사용자가 그 이상의 입력을 제공하는 경우finger,몬gets()루틴은 스택에 계속 올려놓을 겁니다.대부분의 아키텍처는 스택 중간에 있는 기존의 엔트리를 더 큰 것으로 덮어쓰거나 인접한 엔트리를 덮어쓰기에 취약합니다.각 스택 액세스의 크기와 권한을 검사하는 비용은 소프트웨어에서 엄청난 것입니다.지식이 풍부한 남성 요인은 인수 문자열에 올바른 이진 패턴을 저장하여 스택의 절차 활성화 레코드에서 반환 주소를 수정할 수 있습니다.이렇게 하면 실행 흐름이 원래 위치로 되돌아오는 것이 아니라 다음을 호출하는 특별한 명령 시퀀스(스택에 조심스럽게 저장됨)로 전환됩니다.execv()실행 중인 이미지를 셸로 대체합니다.Voilah, 당신은 지금 원격 기계의 셸과 대화하고 있습니다.finger데몬, 그리고 바이러스의 복사본을 다른 컴퓨터로 드래그하는 명령을 내릴 수 있습니다.

아이러니하게도.gets()루틴은 휴대용 I/O 라이브러리의 첫 번째 버전과 호환성을 제공했던 오래된 기능이며 10여 년 전에 표준 I/O로 대체되었습니다.맨페이지는 심지어 다음을 강력하게 추천합니다.fgets()항상 대신에 사용됩니다. 더fgets()루틴은 읽는 문자의 수에 제한을 설정하여 버퍼의 크기를 초과하지 않도록 합니다.finger데몬은 다음과 같은 두 줄로 된 수정을 통해 보안을 강화했습니다.

gets(line);

행에 따라:

if (fgets(line, sizeof(line), stdin) == NULL)
exit(1);

이것은 제한된 양의 입력을 삼키므로 프로그램을 실행하는 사람이 중요한 위치를 덮어쓰도록 조작할 수 없습니다.그러나 ANSIC Standard는 제거하지 않았습니다.gets()그 말에서 이 특정 되는 동안 C 표준 은 제거되지 따라서 이 특정 프로그램이 안전하게 유지되는 동안 C 표준 라이브러리의 근본적인 결함은 제거되지 않았습니다.

다음 질문을 보실 수 있습니다. 안전한 대안입니다.유용한 답들이 많이 있습니다.

코드가 작동하지 않는 이유에 대해 보다 정확하게 설명해야 합니다.fgets(). 다른 질문의 답이 설명하는 것처럼, 당신은 다음과 같은 새로운 선을 다루어야 합니다.gets()생략한

스캔프를 이용해서 모든 단어를 읽으려면 이렇게 하면 됩니다.

예:

printf("Enter name: ");

scanf("%[^\n]s",name);       //[^\n] is the trick

사용가능scanf흉내를 내다gets 안 예뻐요.

#include <stdio.h>

#define S_HELPER(X) # X
#define STRINGIZE(X) S_HELPER(X)
#define MAX_NAME_LEN 20

int flushinput(void) {
  int ch;
  while (((ch = getchar()) != EOF) && (ch != '\n')) /* void */;
  return ch;
}

int main(void) {
  char name[MAX_NAME_LEN + 1] = {0};

  while (name[0] != '*') {
    printf("Enter a name (* to quit): ");
    fflush(stdout);
    scanf("%" STRINGIZE(MAX_NAME_LEN) "[^\n]", name); /* safe gets */
    if (flushinput() == EOF) break;
    printf("Name: [%s]\n", name);
    puts("");
  }

  return 0;
}

책을 읽는 게 훨씬 낫잖아요fgets(필요한 경우) 를 사용하여 파싱합니다.sscanf.


스캔프 호출 및 주변 코드를 설명하는 EDIT.

의 "%[""의 변환 scanfnull 터미네이터를 포함하지 않는 최대 필드 폭을 허용합니다.따라서 입력을 유지할 배열은 scanf로 읽은 것보다 1자가 더 많아야 합니다.

단 하나의 상수로 이를 수행하기 위해 STRINGIZE 매크로를 사용했습니다.이 매크로를 사용하면 배열 크기(변수 정의의 경우)로 #defin' 상수를 문자열(지정자의 경우)로 사용할 수 있습니다.

한 가지 더 언급해야 할 점이 있습니다.flushinput. 사용하는 경우gets, 모든 데이터는 새 행을 포함하지 않고 버퍼가 오버플로되는 경우에도 메모리에 기록됩니다.성대모사를 하기 위해서는.scanf새 줄을 포함하지 않고 제한된 숫자의 문자를 읽습니다.gets, 새 줄을 입력 버퍼에 유지합니다.그래서 그 새 선을 제거해야 하고 그것이 바로flushinput.다입니다.

나머지 코드는 주로 테스트 환경을 설정하는 것이었습니다.

두 개 이상의 필드를 읽을 수 있습니다.scanf(), 따라서 다음을 수행할 수 있습니다.

scanf("%s %s\n", first_name,  last_name);

그러나 이름만 입력한 것이 아닐 수도 있고, 이름만 입력한 것이 아닐 수도 있기 때문에 문자열을 읽고 직접 분할하는 것이 좋을 것 같습니다.

어떤 문제를 겪고 있습니까?fgets()?

의 .gets()사용자가 입력한 만큼의 문자를 반환한다는 것입니다. 즉, 호출자는 이를 제어할 수 없습니다.그래서 당신은 80자를 할당할 수 있고, 사용자는 100자를 입력할 수 있고, 마지막 20자는 당신이 할당한 메모리의 끝에 쓰여질 것이고, 누가 무엇을 알고 있는지를 짓밟을 것입니다.

언급URL : https://stackoverflow.com/questions/4346598/gets-function-in-c