1 / 63

메모리관리 (MEM)

메모리관리 (MEM). 사이버보안학과 김현성. 제안. MEM00-C 동일한 추상화 레벨의 같은 모듈 안에서 메모리를 할당하고 해제하라 MEM01-C free() 후 즉시 포인터에 새로운 값을 저장하라 MEM02-C 메모리 할당 함수의 반환 값을 즉시 할당된 타입의 포인터로 변환시켜라 MEM03-C 재사용을 위해 반환된 재사용 가능한 리소스에 있는 중요한 정보를 클리어하라 MEM04-C 크기가 0 인 할당을 수행하지 마라 MEM05-C 큰 스택 할당을 피하라

monty
Télécharger la présentation

메모리관리 (MEM)

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 메모리관리(MEM) 사이버보안학과 김현성

  2. 제안 • MEM00-C 동일한추상화 레벨의 같은 모듈 안에서 메모리를 할당하고 해제하라 • MEM01-C free() 후즉시 포인터에 새로운 값을 저장하라 • MEM02-C 메모리 할당 함수의 반환 값을 즉시 할당된 타입의 포인터로 변환시켜라 • MEM03-C 재사용을 위해 반환된 재사용 가능한 리소스에 있는 중요한 정보를 클리어하라 • MEM04-C 크기가 0인 할당을 수행하지 마라 • MEM05-C 큰 스택 할당을 피하라 • MEM06-C 중요한 데이터가 디스크에 기록되지 않도록 보장하라 • MEM07-C calloc()의 인자가 곱해지는 경우 size_t로 표현될 수 있게 하라 • MEM08-C 동적으로 할당된 배열을 리사이즈하는 경우에만 realloc()을 사용하라 • MEM09-C 메모리 할당 루틴이 메모리를 초기화해줄 것이라 가정하지 마라 • MEM10-C 포인터 검증 함수를 사용하라

  3. 규칙 • MEM30-C 해제된 메모리에 접근하지 마라 • MEM31-C 동적으로 할당된 메모리는 한 번만 해제하라 • MEM32-C 메모리 할당 에러를 찾아 해결하라 • MEM33-C 유연한 배열 원소에 정확한 문법을 사용하라 • MEM34-C 동적으로 할당된 메모리만 해제하라 • MEM35-C 객체에 충분한 메모리를 할당하라

  4. 제안 • MEM00-C 동일한추상화 레벨의 같은 모듈 안에서 메모리를 할당하고 해제하라 • MEM01-C free() 후즉시 포인터에 새로운 값을 저장하라 • MEM02-C 메모리 할당 함수의 반환 값을 즉시 할당된 타입의 포인터로 변환시켜라 • MEM03-C 재사용을 위해 반환된 재사용 가능한 리소스에 있는 중요한 정보를 클리어하라 • MEM04-C 크기가 0인 할당을 수행하지 마라 • MEM05-C 큰 스택 할당을 피하라 • MEM06-C 중요한 데이터가 디스크에 기록되지 않도록 보장하라 • MEM07-C calloc()의 인자가 곱해지는 경우 size_t로 표현될 수 있게 하라 • MEM08-C 동적으로 할당된 배열을 리사이즈하는 경우에만 realloc()을 사용하라 • MEM09-C 메모리 할당 루틴이 메모리를 초기화해줄 것이라 가정하지 마라 • MEM10-C 포인터 검증 함수를 사용하라

  5. 동일한추상화 레벨의 같은 모듈 안에서 메모리를 할당하고 해제하라 메모리 할당/해제 함수 • void *malloc(size_t size); • void *calloc(size_t nmemb, size_t size); • void *realloc(void *ptr, size_t size); • void free(void *ptr);

  6. 동일한추상화 레벨의 같은 모듈 안에서 메모리를 할당하고 해제하라 MEM00-C 부적절한 코드 예 free(list); enum {MIN_SIZE_ALLOWED = 32 }; int verify_list(char *list, size_t size) { if(size < MIN_SIZE_ALLOWED) { /* 에러상태 처리 */ free(list); return -1; } return 0; } void process_list(size_t number) { char *list = (char *)malloc(number); if(list == NULL) { /* 할당에러 처리 */ } if(verify_list(list, number) == -1) { free(list); return; } /* 리스트 작업을 수행 */ free(list); } free(list); free(list); => 같은 메모리를 중복 해제해 잠정적 악용 가능한 취약성 존재

  7. 동일한추상화 레벨의 같은 모듈 안에서 메모리를 할당하고 해제하라 MEM00-C 해결방법 enum {MIN_SIZE_ALLOWED = 32 }; int verify_list(char *list, size_t size) { if(size < MIN_SIZE_ALLOWED) { /* 에러상태 처리 */ return -1; } return 0; } void process_list(size_t number) { char *list = (char *)malloc(number); if(list == NULL) { /* 할당에러 처리 */ } if(verify_list(list, number) == -1) { free(list); return; } /* 리스트 작업을 수행 */ free(list); }

  8. 제안 • MEM00-C 동일한추상화 레벨의 같은 모듈 안에서 메모리를 할당하고 해제하라 • MEM01-C free() 후즉시 포인터에 새로운 값을 저장하라 • MEM02-C 메모리 할당 함수의 반환 값을 즉시 할당된 타입의 포인터로 변환시켜라 • MEM03-C 재사용을 위해 반환된 재사용 가능한 리소스에 있는 중요한 정보를 클리어하라 • MEM04-C 크기가 0인 할당을 수행하지 마라 • MEM05-C 큰 스택 할당을 피하라 • MEM06-C 중요한 데이터가 디스크에 기록되지 않도록 보장하라 • MEM07-C calloc()의 인자가 곱해지는 경우 size_t로 표현될 수 있게 하라 • MEM08-C 동적으로 할당된 배열을 리사이즈하는 경우에만 realloc()을 사용하라 • MEM09-C 메모리 할당 루틴이 메모리를 초기화해줄 것이라 가정하지 마라 • MEM10-C 포인터 검증 함수를 사용하라

  9. free() 후즉시 포인터에 새로운 값을 저장하라 MEM01-C 부적절한코드 예 char *message; int message_type; /* message와 message_type을 초기화 */ if(message_type == value_1) { /* 메시지 타입 1 처리 */ free(message); } /* ... */ if(message_type == value_2) { /* 메시지 타입 2 처리 */ free(message); } value_1 value_2 => 메시지 타입 고려 1or 2처리 => 메시지 타입이 1과 2 모두 참일 경우 존재

  10. free() 후즉시 포인터에 새로운 값을 저장하라 MEM01-C 해결방법 char *message; int message_type; /* message와 message_type을 초기화 */ if(message_type == value_1) { /* 메시지 타입 1 처리 */ free(message); message = NULL; } /* ... */ if(message_type == value_2) { /* 메시지 타입 2 처리 */ free(message); message = NULL; }

  11. 제안 • MEM00-C 동일한추상화 레벨의 같은 모듈 안에서 메모리를 할당하고 해제하라 • MEM01-C free() 후즉시 포인터에 새로운 값을 저장하라 • MEM02-C 메모리 할당 함수의 반환 값을 즉시 할당된 타입의 포인터로 변환시켜라 • MEM03-C 재사용을 위해 반환된 재사용 가능한 리소스에 있는 중요한 정보를 클리어하라 • MEM04-C 크기가 0인 할당을 수행하지 마라 • MEM05-C 큰 스택 할당을 피하라 • MEM06-C 중요한 데이터가 디스크에 기록되지 않도록 보장하라 • MEM07-C calloc()의 인자가 곱해지는 경우 size_t로 표현될 수 있게 하라 • MEM08-C 동적으로 할당된 배열을 리사이즈하는 경우에만 realloc()을 사용하라 • MEM09-C 메모리 할당 루틴이 메모리를 초기화해줄 것이라 가정하지 마라 • MEM10-C 포인터 검증 함수를 사용하라

  12. 메모리 할당 함수의 반환 값을 즉시 할당된 타입의 포인터로 변환시켜라 MEM02-C 부적절한코드 예 => p->i=0 p->d=0.0 #include <stdlib.h> typedef struct gadget gadget; struct gadget { int i; double d; }; typedef struct widget widget; struct widget { char c[10]; int i; double d; }; widget *p; /* ... */ p = malloc(sizeof(gadget)); If(p != NULL) { p->i = 0; p->d = 0.0; } => 메모리 오버런 발생 가능 malloc(sizeof(gadget)); p->i = 0; p->d = 0.0;

  13. 메모리 할당 함수의 반환 값을 즉시 할당된 타입의 포인터로 변환시켜라 MEM02-C 해결방법 #include <stdlib.h> typedef struct gadget gadget; struct gadget { int i; double d; }; typedef struct widget widget; struct widget { char c[10]; int i; double d; }; widget *p; /* ... */ p = (widget *)malloc(sizeof(widget)); If(p != NULL) { p->i = 0; p->d = 0.0; }

  14. 제안 • MEM00-C 동일한추상화 레벨의 같은 모듈 안에서 메모리를 할당하고 해제하라 • MEM01-C free() 후즉시 포인터에 새로운 값을 저장하라 • MEM02-C 메모리 할당 함수의 반환 값을 즉시 할당된 타입의 포인터로 변환시켜라 • MEM03-C 재사용을 위해 반환된 재사용 가능한 리소스에 있는 중요한 정보를 클리어하라 • MEM04-C 크기가 0인 할당을 수행하지 마라 • MEM05-C 큰 스택 할당을 피하라 • MEM06-C 중요한 데이터가 디스크에 기록되지 않도록 보장하라 • MEM07-C calloc()의 인자가 곱해지는 경우 size_t로 표현될 수 있게 하라 • MEM08-C 동적으로 할당된 배열을 리사이즈하는 경우에만 realloc()을 사용하라 • MEM09-C 메모리 할당 루틴이 메모리를 초기화해줄 것이라 가정하지 마라 • MEM10-C 포인터 검증 함수를 사용하라

  15. 재사용을 위해 반환된 재사용 가능한 리소스에 있는 중요한 정보를 클리어하라 재사용 가능한 리소스 • 동적으로 할당된 메모리 • 정적으로 할당된 메모리 • 자동으로 할당된(스택) 메모리 • 메모리 캐시 • 디스크 • 디스크 개시

  16. 재사용을 위해 반환된 재사용 가능한 리소스에 있는 중요한 정보를 클리어하라 MEM03-C 부적절한코드 예 char*secret; /* secret 초기화 */ char*new_secret; size_t size = strlen(secret); if(size == SIZE_MAX) { /* 에러 처리 */ } new_secret = (char *)malloc(size+1); if(!new_secret) { /* 에러처리 */ } strcpy(new_secret, secret); /* new_secret 처리 ... */ free(new_secret); new_secret = NULL; => new_secret 복사, 이용 후 삭제 strcpy(new_secret, secret); => new_secret 재활용당시 메모리 내용이 공격에 활용가능 free(new_secret);

  17. 재사용을 위해 반환된 재사용 가능한 리소스에 있는 중요한 정보를 클리어하라 MEM03-C 해결방법 char*secret; /* secret 초기화 */ char*new_secret; size_t size = strlen(secret); if(size == SIZE_MAX) { /* 에러 처리 */ } new_secret = (char *)calloc(size+1, sizeof(char)); if(!new_secret) { /* 에러처리 */ } strcpy(new_secret, secret); /* new_secret 처리 ... */ memset((volatile char *)new_secret, ‘\0’, size); free(new_secret); new_secret = NULL;

  18. 제안 • MEM00-C 동일한추상화 레벨의 같은 모듈 안에서 메모리를 할당하고 해제하라 • MEM01-C free() 후즉시 포인터에 새로운 값을 저장하라 • MEM02-C 메모리 할당 함수의 반환 값을 즉시 할당된 타입의 포인터로 변환시켜라 • MEM03-C 재사용을 위해 반환된 재사용 가능한 리소스에 있는 중요한 정보를 클리어하라 • MEM04-C 크기가 0인 할당을 수행하지 마라 • MEM05-C 큰 스택 할당을 피하라 • MEM06-C 중요한 데이터가 디스크에 기록되지 않도록 보장하라 • MEM07-C calloc()의 인자가 곱해지는 경우 size_t로 표현될 수 있게 하라 • MEM08-C 동적으로 할당된 배열을 리사이즈하는 경우에만 realloc()을 사용하라 • MEM09-C 메모리 할당 루틴이 메모리를 초기화해줄 것이라 가정하지 마라 • MEM10-C 포인터 검증 함수를 사용하라

  19. 크기가 0인 할당을 수행하지 마라 MEM04-C 부적절한코드 예 size_t size; /* 사용자입력 값으로 크기를 초기화 */ int*list = (int *)malloc(size); if (list == NULL) { /* 할당 에러 처리 */ } else { /* list 처리 작업 */ } => 0바이트 할당을 위한 malloc(0) 호출이 가능함. 호출 결과는 구현마다 다름

  20. 크기가 0인 할당을 수행하지 마라 MEM04-C 해결방법 size_t size; /* 사용자입력 값으로 크기를 초기화 */ if(size == 0) { /* 에러 처리 */ } int*list = (int *)malloc(size); if (list == NULL) { /* 할당 에러 처리 */ } else { /* list 처리 작업 */ }

  21. 제안 • MEM00-C 동일한추상화 레벨의 같은 모듈 안에서 메모리를 할당하고 해제하라 • MEM01-C free() 후즉시 포인터에 새로운 값을 저장하라 • MEM02-C 메모리 할당 함수의 반환 값을 즉시 할당된 타입의 포인터로 변환시켜라 • MEM03-C 재사용을 위해 반환된 재사용 가능한 리소스에 있는 중요한 정보를 클리어하라 • MEM04-C 크기가 0인 할당을 수행하지 마라 • MEM05-C 큰 스택 할당을 피하라 • MEM06-C 중요한 데이터가 디스크에 기록되지 않도록 보장하라 • MEM07-C calloc()의 인자가 곱해지는 경우 size_t로 표현될 수 있게 하라 • MEM08-C 동적으로 할당된 배열을 리사이즈하는 경우에만 realloc()을 사용하라 • MEM09-C 메모리 할당 루틴이 메모리를 초기화해줄 것이라 가정하지 마라 • MEM10-C 포인터 검증 함수를 사용하라

  22. 큰 스택 할당을 피하라 MEM05-C 부적절한코드 예 intcopy_file(FILE *src, FILE *dst, size_t bufsize) { char buf[bufsize]; while(fgets(buf, bufsize, src)) { if(fputs(buf, dst) == EOF) { /* 에러처리 */ } } return0; } char buf[bufsize]; => src문자열을 buf에 bufsize만큼 복사 => bufsize가 공격자에 의해 제어된다면 DoS 공격 가능

  23. 큰 스택 할당을 피하라 MEM05-C 해결방법 intcopy_file(FILE *src, FILE *dst, size_t bufsize) { if(bufsize == 0) { /* 에러처리 */ char *buf=(char *)malloc(bufsize); if(!buf) { return -1; } while(fgets(buf, bufsize, src)) { if(fputs(buf, dst) == EOF) { /* 에러처리 */ } } free(buf); return0; }

  24. 제안 • MEM00-C 동일한추상화 레벨의 같은 모듈 안에서 메모리를 할당하고 해제하라 • MEM01-C free() 후즉시 포인터에 새로운 값을 저장하라 • MEM02-C 메모리 할당 함수의 반환 값을 즉시 할당된 타입의 포인터로 변환시켜라 • MEM03-C 재사용을 위해 반환된 재사용 가능한 리소스에 있는 중요한 정보를 클리어하라 • MEM04-C 크기가 0인 할당을 수행하지 마라 • MEM05-C 큰 스택 할당을 피하라 • MEM06-C 중요한 데이터가 디스크에 기록되지 않도록 보장하라 • MEM07-C calloc()의 인자가 곱해지는 경우 size_t로 표현될 수 있게 하라 • MEM08-C 동적으로 할당된 배열을 리사이즈하는 경우에만 realloc()을 사용하라 • MEM09-C 메모리 할당 루틴이 메모리를 초기화해줄 것이라 가정하지 마라 • MEM10-C 포인터 검증 함수를 사용하라

  25. 중요한 데이터가 디스크에 기록되지 않도록 보장하라 MEM06-C 부적절한코드 예 char*secret; secret = (char *)malloc(size+1); if(!secret) { /* 에러처리 */ } /* secret을 사용한 작업 수행 */ free(secret); secret = NULL; secret = (char *)malloc(size+1); free(secret); => free() 호출전프로그램 종료시 secret 에 저장된 정보는 코어 덤프에 기록됨

  26. 중요한 데이터가 디스크에 기록되지 않도록 보장하라 MEM06-C 해결방법 #include <ssys/resource.h> /* ... */ struct rlimit limit; char *secret; limit.rlim_cur = 0; limit.rlim_max = 0; if(setrlimit(RLIMIT_CORE, &limit) ! = 0) { /* 에러처리 */ } /* 중요데이터를 생성하거나 수집 */ if(fgets(secret, sizeof(secret), stdin) == EOF) { /* 에러처리 */ } => setrlimit()를 통해 코어덤프의 크기를0으로 설정 가능

  27. 제안 • MEM00-C 동일한추상화 레벨의 같은 모듈 안에서 메모리를 할당하고 해제하라 • MEM01-C free() 후즉시 포인터에 새로운 값을 저장하라 • MEM02-C 메모리 할당 함수의 반환 값을 즉시 할당된 타입의 포인터로 변환시켜라 • MEM03-C 재사용을 위해 반환된 재사용 가능한 리소스에 있는 중요한 정보를 클리어하라 • MEM04-C 크기가 0인 할당을 수행하지 마라 • MEM05-C 큰 스택 할당을 피하라 • MEM06-C 중요한 데이터가 디스크에 기록되지 않도록 보장하라 • MEM07-C calloc()의 인자가 곱해지는 경우 size_t로 표현될 수 있게 하라 • MEM08-C 동적으로 할당된 배열을 리사이즈하는 경우에만 realloc()을 사용하라 • MEM09-C 메모리 할당 루틴이 메모리를 초기화해줄 것이라 가정하지 마라 • MEM10-C 포인터 검증 함수를 사용하라

  28. calloc()의 인자가 곱해지는 경우 size_t로 표현될 수 있게 하라 calloc() • 지정된 크기만큼 메모리 공간 할당 • 할당할원소의 개수 • 원소의 크기 • 저장공간이 size_t로 표현될 수 없는 경우 요구한 크기보다 적은 크기의 메모리가 할당됨

  29. calloc()의 인자가 곱해지는 경우 size_t로 표현될 수 있게 하라 MEM07-C 부적절한코드 예 size_t num_elements = /*필요한 원소 개수 */; long*buffer = (long *)calloc(num_elements, sizeof(long)); if(buffer == NULL) { /* 에러 상태 처리 */ } /* ... */ free(buffer); buffer = NULL; calloc(num_elements, sizeof(long)) => calloc()의 개수가 size_t로 표현될 수 없다면 버퍼 오버플로우 발생 가능 존재

  30. calloc()의 인자가 곱해지는 경우 size_t로 표현될 수 있게 하라 MEM07-C 해결방법 long *buffer; size_t num_elements = /*필요한 원소 개수 */; if(num_elements > SIZE_MAX/sizeof(long)) { /* 에러 상태 처리 */ } buffer = (long *)calloc(num_elements, sizeof(long)); if(buffer == NULL) { /* 에러 상태 처리 */ } /* ... */ free(buffer); buffer = NULL;

  31. 제안 • MEM00-C 동일한추상화 레벨의 같은 모듈 안에서 메모리를 할당하고 해제하라 • MEM01-C free() 후즉시 포인터에 새로운 값을 저장하라 • MEM02-C 메모리 할당 함수의 반환 값을 즉시 할당된 타입의 포인터로 변환시켜라 • MEM03-C 재사용을 위해 반환된 재사용 가능한 리소스에 있는 중요한 정보를 클리어하라 • MEM04-C 크기가 0인 할당을 수행하지 마라 • MEM05-C 큰 스택 할당을 피하라 • MEM06-C 중요한 데이터가 디스크에 기록되지 않도록 보장하라 • MEM07-C calloc()의 인자가 곱해지는 경우 size_t로 표현될 수 있게 하라 • MEM08-C 동적으로 할당된 배열을 리사이즈하는 경우에만 realloc()을 사용하라 • MEM09-C 메모리 할당 루틴이 메모리를 초기화해줄 것이라 가정하지 마라 • MEM10-C 포인터 검증 함수를 사용하라

  32. 동적으로 할당된 배열을 리사이즈하는 경우에만 realloc()을 사용하라 MEM08-C 부적절한코드 예 #include <stdlib.h> typedef struct gadget gadget; struct gadget { int i; double e; char *p; } typedef struct widget widget; struct widget { char *q; int j; double e; }; gadget *gp; widget *wp; /* ... */ wp = (widget *)realloc(gp, sizeof(widget)); =>widget형을 gadget 형 처럼 초기화 하고 있음 realloc(gp, sizeof(widget))

  33. 동적으로 할당된 배열을 리사이즈하는 경우에만 realloc()을 사용하라 MEM08-C 해결방법 #include <stdlib.h> typedef struct widget widget; struct widget { char *q; int j; double e; }; widget *wp; widget *wq; /* ... */ wp = (widget *)malloc(10*sizeof(widget)); /* ... */ wq = (widget *)realloc(wp, 20*sizeof(widget)); /* ... */ wp = (widget *)realloc(wq, 15*sizeof(widget));

  34. 제안 • MEM00-C 동일한추상화 레벨의 같은 모듈 안에서 메모리를 할당하고 해제하라 • MEM01-C free() 후즉시 포인터에 새로운 값을 저장하라 • MEM02-C 메모리 할당 함수의 반환 값을 즉시 할당된 타입의 포인터로 변환시켜라 • MEM03-C 재사용을 위해 반환된 재사용 가능한 리소스에 있는 중요한 정보를 클리어하라 • MEM04-C 크기가 0인 할당을 수행하지 마라 • MEM05-C 큰 스택 할당을 피하라 • MEM06-C 중요한 데이터가 디스크에 기록되지 않도록 보장하라 • MEM07-C calloc()의 인자가 곱해지는 경우 size_t로 표현될 수 있게 하라 • MEM08-C 동적으로 할당된 배열을 리사이즈하는 경우에만 realloc()을 사용하라 • MEM09-C 메모리 할당 루틴이 메모리를 초기화해줄 것이라 가정하지 마라 • MEM10-C 포인터 검증 함수를 사용하라

  35. 메모리 할당 루틴이 메모리를 초기화해줄 것이라 가정하지 마라 메모리할당 함수 • malloc()은 값이정해지지 않은 객체에 대한 공간 할당 • realloc()은 동적으로 할당된 메모리 블록의 크기 변경 • calloc()은 메모리의 모든 비트가 0으로 초기화 됨

  36. 메모리 할당 루틴이 메모리를 초기화해줄 것이라 가정하지 마라 MEM09-C 부적절한코드 예 enum{ MAX_BUF_SIZE = 256 }; char *str = /* 사용자입력 데이터 */; size_t len = strlen(str); if(len >= MAX_BUF_SIZE -1) { /* 너무 긴 문자열 에러 처리 */ } char *buf = (char *)malloc(MAX_BUF_SIZE); if(buf == NULL) { /* 할당에러 처리 */ } strncpy(buf, str, len); /* buf 처리 */ free(buf); buf = NULL; malloc(MAX_BUF_SIZE) => len이 널문자를 포함한 str의 전체 길이보다 작은경우 buf는 종료문자를포함하지 않을 수 있음 strncpy(buf, str, len)

  37. 메모리 할당 루틴이 메모리를 초기화해줄 것이라 가정하지 마라 MEM09-C 해결방법 enum{ MAX_BUF_SIZE = 256 }; char *str = /* 사용자입력 데이터 */; size_t len = strlen(str); if(len >= MAX_BUF_SIZE -1) { /* 너무 긴 문자열 에러 처리 */ } char *buf = (char *)malloc(MAX_BUF_SIZE); if(buf == NULL) { /* 할당에러 처리 */ } strncpy(buf, str, len); /* 문자열 NULL 종료 */ buf[len] = ‘\0’; /* buf 처리 */ free(buf); buf = NULL;

  38. 제안 • MEM00-C 동일한추상화 레벨의 같은 모듈 안에서 메모리를 할당하고 해제하라 • MEM01-C free() 후즉시 포인터에 새로운 값을 저장하라 • MEM02-C 메모리 할당 함수의 반환 값을 즉시 할당된 타입의 포인터로 변환시켜라 • MEM03-C 재사용을 위해 반환된 재사용 가능한 리소스에 있는 중요한 정보를 클리어하라 • MEM04-C 크기가 0인 할당을 수행하지 마라 • MEM05-C 큰 스택 할당을 피하라 • MEM06-C 중요한 데이터가 디스크에 기록되지 않도록 보장하라 • MEM07-C calloc()의 인자가 곱해지는 경우 size_t로 표현될 수 있게 하라 • MEM08-C 동적으로 할당된 배열을 리사이즈하는 경우에만 realloc()을 사용하라 • MEM09-C 메모리 할당 루틴이 메모리를 초기화해줄 것이라 가정하지 마라 • MEM10-C 포인터 검증 함수를 사용하라

  39. 포인터 검증 함수를 사용하라 포인터유효성 체크 • NULL 제외한 모든 포인터 유효int invalid(void *ptr) { return (ptr != NULL);}

  40. 포인터 검증 함수를 사용하라 MEM10-C 부적절한코드 예 void incr(int *intptr) { if(intptr == NULL) { /* 에러처리 */ } *intptr++; } *intptr++ => 포인터가 NULL이 아닌 경우라도 유효 하지 않은 값일 수 있고, 이로 인해 메모리 손상 or 비정상 종료 유발 가능

  41. 포인터 검증 함수를 사용하라 MEM10-C 해결방법 #include <assert.h> void incr(int *intptr) { assert(valid(intptr)); *intptr++; }

  42. 제안 • MEM00-C 동일한추상화 레벨의 같은 모듈 안에서 메모리를 할당하고 해제하라 • MEM01-C free() 후즉시 포인터에 새로운 값을 저장하라 • MEM02-C 메모리 할당 함수의 반환 값을 즉시 할당된 타입의 포인터로 변환시켜라 • MEM03-C 재사용을 위해 반환된 재사용 가능한 리소스에 있는 중요한 정보를 클리어하라 • MEM04-C 크기가 0인 할당을 수행하지 마라 • MEM05-C 큰 스택 할당을 피하라 • MEM06-C 중요한 데이터가 디스크에 기록되지 않도록 보장하라 • MEM07-C calloc()의 인자가 곱해지는 경우 size_t로 표현될 수 있게 하라 • MEM08-C 동적으로 할당된 배열을 리사이즈하는 경우에만 realloc()을 사용하라 • MEM09-C 메모리 할당 루틴이 메모리를 초기화해줄 것이라 가정하지 마라 • MEM10-C 포인터 검증 함수를 사용하라

  43. 규칙 • MEM30-C 해제된 메모리에 접근하지 마라 • MEM31-C 동적으로 할당된 메모리는 한 번만 해제하라 • MEM32-C 메모리 할당 에러를 찾아 해결하라 • MEM33-C 유연한 배열 원소에 정확한 문법을 사용하라 • MEM34-C 동적으로 할당된 메모리만 해제하라 • MEM35-C 객체에 충분한 메모리를 할당하라

  44. 해제된 메모리에 접근하지 마라 MEM30-C 부적절한 코드 예 for (p = head; p != NULL; p = p->next) free(p); free(p); => head와 연계된 모든 메모리 해제 => p->next 처리 전에 p가 해제되어 p->next가 해제된 메모리를 접근함

  45. 해제된 메모리에 접근하지 마라 MEM30-C 해결방법 for (p = head; p != NULL; p = q) { q = p->next; free(p); } head = NULL;

  46. 규칙 • MEM30-C 해제된 메모리에 접근하지 마라 • MEM31-C 동적으로 할당된 메모리는 한 번만 해제하라 • MEM32-C 메모리 할당 에러를 찾아 해결하라 • MEM33-C 유연한 배열 원소에 정확한 문법을 사용하라 • MEM34-C 동적으로 할당된 메모리만 해제하라 • MEM35-C 객체에 충분한 메모리를 할당하라

  47. 동적으로 할당된 메모리는 한 번만 해제하라 MEM31-C 부적절한 코드 예 size_t num_elem = /* 초기값할당 */; interror_condition = 0; int *x = (int *)malloc(num_elem * sizeof(int)); if(x == NULL) { /* 할당에러 처리 */ } /* ... */ if(error_condition == 1) { /* 할당에러 처리 */ free(x); } /* ...*/ free(x); free(x); free(x); => error_condition이 1인경우 두번 메모리 해제

  48. 동적으로 할당된 메모리는 한 번만 해제하라 MEM31-C 해결방법 size_t num_elem = /* 초기값할당 */; interror_condition = 0; if(num_elem > SIZE_MAX/sizeof(int)) { /* 오버플로우 처리 */ } int *x = (int *)malloc(num_elem * sizeof(int)); if(x == NULL) { /* 할당에러 처리 */ } /* ... */ if(error_condition == 1) { /* 에러 상태 처리 */ } /* ...*/ free(x); x = NULL;

  49. 규칙 • MEM30-C 해제된 메모리에 접근하지 마라 • MEM31-C 동적으로 할당된 메모리는 한 번만 해제하라 • MEM32-C 메모리 할당 에러를 찾아 해결하라 • MEM33-C 유연한 배열 원소에 정확한 문법을 사용하라 • MEM34-C 동적으로 할당된 메모리만 해제하라 • MEM35-C 객체에 충분한 메모리를 할당하라

  50. 메모리 할당 에러를 찾아 해결하라 메모리할당 함수 출력 값

More Related