1 / 26

Memory-Related Bugs

Learn about common memory-related bugs like bad pointers, uninitialized memory, overwriting memory, and more. Understand the risks and solutions to prevent such issues in your code.

vhux
Download Presentation

Memory-Related Bugs

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. Memory-Related Bugs • Dereferencing bad pointers • Reading uninitialized memory • Overwriting memory • Referencing nonexistent variables • Freeing blocks multiple times • Referencing freed blocks • Failing to free blocks • Dynamically allocating and then losing the pointer to it

  2. int val; ... scanf(“%d”, val);

  3. Does this work? foo(.. .) { int *val; ... scanf(“%d”, val); }

  4. int *foo(.. .) { int *val; ... *val = 34; return val; }

  5. What’s the matter with this? extern int bar(int *zilch); foo(.. .) { int zorch; int *val; ... zorch = bar(val); ... }

  6. Off by one on subscripts • Why do the subscripts start with zero instead of one? • Would it be less bug-prone to start with one? int bar[99000];

  7. What happens if we leave out the #include? • Will the compiler accept this code? • Will the compiler generate object code? • Will the object code be correct? #include <stdlib.h> . . . foo() { char *p = malloc(N); ... }

  8. Reading Uninitialized Memory • Assuming that heap data is initialized to zero /* return y = Ax */ int *matvec(int **A, int *x) { int *y = malloc(N*sizeof(int)); int i, j; for (i=0; i<N; i++) for (j=0; j<N; j++) y[i] += A[i][j]*x[j]; return y; }

  9. int **p; p = malloc(N*sizeof(int)); for (i=0; i<N; i++) { p[i] = malloc(M*sizeof(int)); }

  10. int **p; p = malloc(N*sizeof(int *)); for (i=0; i<=N; i++) { p[i] = malloc(M*sizeof(int)); }

  11. Overwriting Memory • Not checking the max string size • Basis for classic buffer overflow attacks • 1988 Internet worm, AOL/Microsoft IM war • Why should we use fgets instead of gets? • char *fgets(char *s, int n, FILE *stream); char s[8]; int i; gets(s); /* reads “123456789” from stdin */

  12. int func(char *p[], int size) { char tmp[LENGTH]; int i; for (i = 0; /* something */){ /* Do something that creates a string in tmp */ strcpy(p+i, tmp); } }

  13. int *search(int *p, int val) { while (*p && *p != val) p += sizeof(int); return p; }

  14. int *foo () { int val = 0; // initialized ... return &val; }

  15. x = malloc(N*sizeof(int)); <manipulate x> free(x); y = malloc(M*sizeof(int)); <manipulate y> free(x);

  16. x = malloc(N*sizeof(int)); <manipulate x> free(x); ... y = malloc(M*sizeof(int)); for (i=0; i<M; i++) y[i] = x[i]++;

  17. foo() { int *x = malloc(N*sizeof(int)); ... return; }

  18. struct list { int val; struct list *next; }; foo() { struct list *head = malloc(sizeof(struct list)); head->val = 0; head->next = NULL; <create and manipulate the rest of the list> ... free(head); return; }

  19. Loop to compare characters until it finds a pair that do not match, or the end of one string. while((*p == *q) && *p && *q){ *p++; *q++; }

  20. void foo( char *x ) { x = (char *)malloc(100); if( !x ) exit(1); strcpy( x, "this is a test" ); } int main() { char *x; foo(x); printf( "string = %s\n", x ); free(x); return 0; } A hint. When I ran this it printed: *** glibc detected *** free(): invalid pointer: 0x004c3c80 *** Why?

  21. #define Least(x,y) ((x) < (y) ? (x) : (y)) char *puzzle = "A real puzzle"; int main() { int least=10000; char *p = puzzle; while( *p ) { least = Least( least, *p++ ); } printf( "The least char is '%c'\n", least ); return 0; } This program prints out that the least character in the given string is 'e'. This can't be right. What's wrong?

  22. What are three bugs here? char *tokens[NTOKENS]; char delim[] = “ \t\n”; get_command_line() { int i = 0; char *buf = malloc(BUFSIZ); fgets(buf, ...); /* get data into buffer */ buf = strtok(buf, delim); while (buf != NULLSTRING){ tokens[i] = buf; buf = strtok(NULLSTRING, delim); } free(buf); return; }

  23. char *get_command_line() { int i = 0; char *buf = malloc(BUFSIZ); char *p = buf; fgets(buf, ...); /* get data into buffer */ /* pass leading white space */ while ((*p == ‘ ‘) || (*p == ‘\t’)){ p++; } return p; }

  24. char *getline() { char buf[8]; char *result; gets(buf); result = malloc(strlen(buf)); strcpy(result, buf); return(result); } Write down at least three problems with this code.

  25. Dealing With Memory Bugs • Conventional debugger (gdb) • Good for finding bad pointer dereferences • Hard to detect the other memory bugs • Debugging malloc (CSRI UToronto malloc) • Wrapper around conventional malloc • Detects memory bugs at malloc and free boundaries • Memory overwrites that corrupt heap structures • Some instances of freeing blocks multiple times • Memory leaks • Cannot detect all memory bugs • Overwrites into the middle of allocated blocks • Freeing block twice that has been reallocated in the interim • Referencing freed blocks

  26. Dealing With Memory Bugs (cont.) • Use local variables whenever possible • Also aptly called “automatic variables” • Use static variables whenever possible • Garbage collection (C++) • Let the system free blocks instead of the programmer.

More Related