1 / 28

Pointers and Memory Allocation – part 2 -L. Grewe

Pointers and Memory Allocation – part 2 -L. Grewe. Objectives. Pointers to Functions More potential Issues with Pointers - advanced. Pointers to Functions (this is NOT passing pointers as arguments to functions!!! This is a pointer pointing to a function itself!!!!!!).

Télécharger la présentation

Pointers and Memory Allocation – part 2 -L. Grewe

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. Pointers and Memory Allocation – part 2-L. Grewe

  2. Objectives • Pointers to Functions • More potential Issues with Pointers - advanced

  3. Pointers to Functions(this is NOT passing pointers as arguments to functions!!!This is a pointer pointing to a function itself!!!!!!) • A pointer can also store the address of a function • A function name is the address in memory of the start of the function • Function pointers can be • Passed to a function • Returned to functions • Stored in arrays • Assigned to other function pointers

  4. An Array of Pointers to Functions • #include <stdio.h> • void fun1(void); • void fun2(void); • void fun3(void); • int main(){ • /*declare an array of pointers to functions*/ • void (*array[3])(void) = {fun1,fun2,fun3}; • inti; • for (i=0;i<3;i++) • (*array[i])();/*make a function call*/ • return 0;/*output: 1st 2nd 3rd */ • } • void fun1(void){printf("1st ");} • void fun2(void){printf("2nd ");} • void fun3(void){printf("3rd ");}

  5. Alternative Code • #include <stdio.h> • void fun1(void); • void fun2(void); • void fun3(void); • int main(){ • void (*array[3])(void) = {fun1,fun2,fun3}; • /*declare an array of pointers to functions*/ • inti; • for (i=0;i<3;i++) • array[i](); /*or (*array[i])(); */ • return 0; /*output: 1st 2nd 3rd */ • } • void fun1(void){printf("1st ");} • void fun2(void){printf("2nd ");} • void fun3(void){printf("3rd ");}

  6. Pointers to Functions • void(*array[3])(void)={fun1,fun2,fun3}; • “array” is an array of 3 pointers to 3 functions with no arguments and return type void • (*array[i])(void); //THESE ARE THE SAME • array[i]();

  7. Just some new functions fun1, fun2, fun3 With parameters • An Array of Pointers to Functions 2 • #include <stdio.h> • int fun1(int); • int fun2(int); • int fun3(int); • int main(){ • int (*array[3])(int) = {fun1,fun2,fun3}; • inti; • for (i=0;i<3;i++) • printf("%d ",(*array[i])(i)); /*1 3 5*/ • /* printf("%d ", array[i](i)); */ • return 0; • } • int fun1(intx){return x+1;} • int fun2(intx){return x+2;} • int fun3(intx){return x+3;}

  8. Pointers to Functions 2 • int(*array[3])(int)={fun1,fun2,fun3}; • “array” is an array of 3 pointers to 3 functions with one int argument and return type int • (*array[i])(i); • array[i](i); • The function is dereferenced and integer “i” is passed as an argument to the function

  9. Pointers to functions: WHY? • They allow for a certain amount of polymorphism: • “poly” (many) + “morph” (shape) • A polymorphic language can handle a range of different data types (“shapes”?) with a single statement

  10. Pointers to functions: safety concerns • What if uninitialized function pointer value is accessed? • Safest outcome: memory error, and program is terminated • But what if the “garbage” value is a valid address? • Worst case: address contains program instruction –execution continues, with random results • Hard to trace the cause of the erroneous behavior

  11. Pointer and Memory Failures re-visited and Advanced

  12. 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

  13. 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; }

  14. Overwriting memory • Allocating the (possibly) wrong sized object int **p; p = malloc(N*sizeof(int)); for (i=0; i<N; i++) { p[i] = malloc(M*sizeof(int)); }

  15. Overwriting memory • Off-by-one int **p; p = malloc(N*sizeof(int *)); for (i=0; i<=N; i++) { p[i] = malloc(M*sizeof(int)); }

  16. Overwriting memory • Not checking the max string size char s[8]; int i; gets(s); /* reads “123456789” from stdin */ • Basis for classic buffer overflow attacks • 1988 Internet worm • modern attacks on Web servers • AOL/Microsoft IM war

  17. Buffer overflow attacks • Description of hole: • Servers that use C library routines such as gets() that don’t check input sizes when they write into buffers on the stack. • The following description is based on the IA32 stack conventions. The details will depend on how the stack is organized, which varies between compilers and machines %ebp Saved regs. and Local vars Stack frame for proc a proc a() { b(); # call procedure b } increasing addrs return addr %ebp proc b() { char buffer[64]; # alloc 64 bytes on stack gets(buffer); # read STDIN line into buf } Stack frame for proc b 64 bytes for buffer

  18. Buffer overflow attacks • Vulnerability stems from possibility of the gets() routine overwriting the return address for b. • overwrite stack frame with • machine code instruction(s) that execs a shell • a bogus return address to the instruction proc a() { b(); # call procedure b } # b should return here, instead it # returns to an address inside of buffer %ebp Saved regs. and Local vars Stack frame for proc a incr addrs New return addr proc b() { char buffer[64]; # alloc 64 bytes on stack gets(buffer); # read STDIN line to buffer } padding Stack frame for proc b exec(“/bin/sh”) Stack region overwritten by gets(buffer)

  19. Overwriting memory • Referencing a pointer instead of the object it points to int *BinheapDelete(int **binheap, int *size) { int *packet; packet = binheap[0]; binheap[0] = binheap[*size - 1]; *size--; Heapify(binheap, *size, 0); return(packet); }

  20. Overwriting memory • Misunderstanding pointer arithmetic int *search(int *p, int val) { while (*p && *p != val) p += sizeof(int);//you should increment //array by 1 only //you are missing elements return p; }

  21. Referencing nonexistent variables • Forgetting that local variables disappear when a function returns int *foo () { int val; return &val; }

  22. Freeing blocks multiple times x = malloc(N*sizeof(int)); // ….<manipulate x> free(x); y = malloc(M*sizeof(int)); //…<manipulate y> free(x);

  23. Referencing freed blocks x = malloc(N*sizeof(int)); //….<manipulate x> free(x); ... y = malloc(M*sizeof(int)); for (i=0; i<M; i++) y[i] = x[i]++;

  24. Failing to free blocks(memory leaks) • Run out of memory as you repeatedly call function …foo(), foo(), foo() …. foo() { int *x = malloc(N*sizeof(int)); ... return; }

  25. Failing to free blocks(memory leaks) • Freeing only part of a data structure 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); //not freeing other part of list created. return; }

  26. Dealing with memory bugs • Conventional debugger (gdb) • good for finding bad pointer dereferences • hard to detect the other memory bugs • Debugging 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

  27. Dealing with memory bugs (cont.) • Binary translator (i.e. Purify-IBM product) • powerful debugging and analysis technique • rewrites text section of executable object file • can detect all errors as debugging malloc • can also check each individual reference at runtime • bad pointers • overwriting • referencing outside of allocated block • Garbage collection • let the system free blocks instead of the programmer.

  28. Pointer and Memory Allocation Tips • Use Pointers only when you need to. • Pointer problems can be the most difficult to debug • Whenever you allocate memory – think immediately where/if you need to deallocate it • Use Data Structures implemented in C++ Collections already provided when possible –as they are written to take care of potential problems like class copying we saw previously.

More Related