leakpoint: pinpointing the causes of memory leaks (icse 2010)
TRANSCRIPT
LEAKPOINT: Pinpointing the Causes of Memory Leaks
Georgia Institute of TechnologyJames Clause and Alessandro Orso
Supported in part by NSF and IBM Research
Memory leak classification
void *p = malloc(100);
Memory leak classification
void *p = malloc(100); M
Memory leak classification
Lost memory Forgotten memory
M becomes unreachable before being deallocated
M is reachable, but is never accessed or deallocated
void *p = malloc(100); M
Memory leak classification
Lost memory Forgotten memory
M becomes unreachable before being deallocated
M is reachable, but is never accessed or deallocated
void *p = malloc(100); M
Memory leak classification
Lost memory Forgotten memory
M becomes unreachable before being deallocated
M is reachable, but is never accessed or deallocated
void *p = malloc(100); M
• common
• difficult to manually detect
• high impact
Existing techniques
mtrace
M. Bond and K. McKinley ‘06
R. Hastings and B. Joyce ‘92
M. Hauswirth and T. Chilimbi. ‘04
D.Heine and M.Lam ‘03
D. Heine and M. Lam ‘06
M. Jump and K. McKinley ‘07
leaks
J. Maebe, M. Ronsse, and K. D. Bosschere ‘04
N. Mitchell and G. Sevitsky ‘03
G. Novark, E. D. Berger, and B. G. Zorn ‘09
M. Orlovich and R. Rugina ‘06
F. Qin, S. Lu, and Y. Zhou ‘05
MemCheck
Y. Xie and A. Aiken ‘05
G. Xu and A. Rountev ‘08
S. Cherem, L. Princehouse, and R. Rugina ‘06
W. DePauw and G. Sevitsky ’99purify
Publications Tools
addhash(char hname[]) {35. int i;36. HASHPTR hptr;37. unsigned int hsum = 0;
38. for(i = 0 ; i < strlen(hname) ; i++) {39. sum += (unsigned int) hname[i];40. }41. hsum %= 3001;42. if((hptr = hashtab[hsum]) == (HASHPTR) NULL) {43. hptr = hashtab[hsum] = (HASHPTR) malloc(sizeof(HASHBOX));44. hptr->hnext = (HASHPTR) NULL;45. hptr->hnum = ++netctr;46. hptr->hname = (char *) malloc((strlen(hname) + 1) * ! ! ! ! ! ! ! ! ! ! sizeof(char));47. sprintf(hptr->hname , "%s" , hname);48. return(1);49. } else {! ... 67. } }
Detecting leaks is easy
addhash(char hname[]) {35. int i;36. HASHPTR hptr;37. unsigned int hsum = 0;
38. for(i = 0 ; i < strlen(hname) ; i++) {39. sum += (unsigned int) hname[i];40. }41. hsum %= 3001;42. if((hptr = hashtab[hsum]) == (HASHPTR) NULL) {43. hptr = hashtab[hsum] = (HASHPTR) malloc(sizeof(HASHBOX));44. hptr->hnext = (HASHPTR) NULL;45. hptr->hnum = ++netctr;46. hptr->hname = (char *) malloc((strlen(hname) + 1) * ! ! ! ! ! ! ! ! ! ! sizeof(char));47. sprintf(hptr->hname , "%s" , hname);48. return(1);49. } else {! ... 67. } }
Detecting leaks is easy
addhash(char hname[]) {35. int i;36. HASHPTR hptr;37. unsigned int hsum = 0;
38. for(i = 0 ; i < strlen(hname) ; i++) {39. sum += (unsigned int) hname[i];40. }41. hsum %= 3001;42. if((hptr = hashtab[hsum]) == (HASHPTR) NULL) {43. hptr = hashtab[hsum] = (HASHPTR) malloc(sizeof(HASHBOX));44. hptr->hnext = (HASHPTR) NULL;45. hptr->hnum = ++netctr;46. hptr->hname = (char *) malloc((strlen(hname) + 1) * ! ! ! ! ! ! ! ! ! ! sizeof(char));47. sprintf(hptr->hname , "%s" , hname);48. return(1);49. } else {! ... 67. } }
Detecting leaks is easy; fixing them is not
Overview
Overview
Overview
Overview
Leak locations are close to whereleaks should be fixed.
Overview
1 Taintingpointers
Leak locations are close to whereleaks should be fixed.
Overview
1 Taintingpointers
Leak locations are close to whereleaks should be fixed.
Overview
1 Taintingpointers
2 Propagatingtaint marks
Leak locations are close to whereleaks should be fixed.
Overview
1 Taintingpointers
2 Propagatingtaint marks
Leak locations are close to whereleaks should be fixed.
Overview
1 Taintingpointers
2 Propagatingtaint marks
3 Identifyingwhen leaksoccur
Leak locations are close to whereleaks should be fixed.
Overview
1 Taintingpointers
2 Propagatingtaint marks
3 Identifyingwhen leaksoccur
Leak locations are close to whereleaks should be fixed.
addhash(char hname[]) {35. int i;36. HASHPTR hptr;37. unsigned int hsum = 0;
38. for(i = 0 ; i < strlen(hname) ; i++) {39. sum += (unsigned int) hname[i];40. }41. hsum %= 3001;42. if((hptr = hashtab[hsum]) == (HASHPTR) NULL) {43. hptr = hashtab[hsum] = (HASHPTR) malloc(sizeof(HASHBOX));44. hptr->hnext = (HASHPTR) NULL;45. hptr->hnum = ++netctr;46. hptr->hname = (char *) malloc((strlen(hname) + 1) * ! ! ! ! ! ! ! ! ! ! sizeof(char));47. sprintf(hptr->hname , "%s" , hname);48. return(1);49. } else {! ... 67. } }
Detecting leaks is easy
46. hptr->hname = (char *) malloc((strlen(hname) + 1) * ! ! ! ! ! ! ! ! ! ! sizeof(char));
delHtab() {15. int i;16. HASHPTR hptr , zapptr;17. for(i = 0; i < 3001; i++) {18. hptr = hashtab[i];19. if(hptr != (HASHPTR) NULL) {20. zapptr = hptr ;21. while(hptr->hnext != (HASHPTR) NULL) {22.! ! hptr = hptr->hnext;23.! ! free(zapptr);24.! ! zapptr = hptr ;25.! ! }
26.! ! free(hptr);27.! }28. }!29. free(hashtab);30. return; }
Detecting leaks is easy
46. hptr->hname = (char *) malloc((strlen(hname) + 1) * ! ! ! ! ! ! ! ! ! ! sizeof(char));
Detecting leaks is easy; fixing them is too
delHtab() {15. int i;16. HASHPTR hptr , zapptr;17. for(i = 0; i < 3001; i++) {18. hptr = hashtab[i];19. if(hptr != (HASHPTR) NULL) {20. zapptr = hptr ;21. while(hptr->hnext != (HASHPTR) NULL) {22.! ! hptr = hptr->hnext;23.! ! free(zapptr);24.! ! zapptr = hptr ;25.! ! }
26.! ! free(hptr);27.! }28. }!29. free(hashtab);30. return; }
46. hptr->hname = (char *) malloc((strlen(hname) + 1) * ! ! ! ! ! ! ! ! ! ! sizeof(char));
Detecting leaks is easy; fixing them is too
delHtab() {15. int i;16. HASHPTR hptr , zapptr;17. for(i = 0; i < 3001; i++) {18. hptr = hashtab[i];19. if(hptr != (HASHPTR) NULL) {20. zapptr = hptr ;21. while(hptr->hnext != (HASHPTR) NULL) {22.! ! hptr = hptr->hnext;23.! ! free(zapptr);24.! ! zapptr = hptr ;25.! ! }
26.! ! free(hptr);27.! }28. }!29. free(hashtab);30. return; }
free(hptr->hname);
Outline
• Our technique
• Tainting pointers
• Tracking pointers
• Checking for leaks
• Implementation
• Evaluation
• Conclusions and future work
1. Tainting pointersAssign a taint mark to pointers returned from
allocation functions (e.g., malloc)
1. Tainting pointersAssign a taint mark to pointers returned from
allocation functions (e.g., malloc)
1. Tainting pointers
Last use location
Allocation location
Allocation sizeDeallocated indicatorPointer count
Assign a taint mark to pointers returned from allocation functions (e.g., malloc)
Metadata
1. Tainting pointers
Last use location
Allocation location
Allocation sizeDeallocated indicatorPointer count
Assign a taint mark to pointers returned from allocation functions (e.g., malloc)
current location
current location
false
size of the memory area
1
Metadata Initialized to
2. Propagating taint marks
2. Propagating taint marks
1. Track the flow of pointers throughout the execution
2. Propagating taint marks
1. Track the flow of pointers throughout the execution
2. Propagating taint marks
1. Track the flow of pointers throughout the execution
2. Propagating taint marks
1. Track the flow of pointers throughout the execution
2. Update taint marks’ mutable metadata
Tracking pointers
assignment
addition subtraction
and
multiplicationdivision
modulusor, xor,
shift, notcomparison
p2 = p1 ➔ p2
p2 = p1 ➔ p2
p2 = p2 ± 1 ➔ p2
p3 = p2 ± p1 ➔ p3
p2 = p2 & 0xffff ➔ p2
not tainted
Tracking pointers
assignment
addition subtraction
and
multiplicationdivision
modulusor, xor,
shift, notcomparison
p2 = p1 ➔ p2
p2 = p1 ➔ p2
p2 = p2 ± 1 ➔ p2
p3 = p2 ± p1 ➔ p3
p2 = p2 & 0xffff ➔ p2
not tainted
Tracking pointers
assignment
addition subtraction
and
multiplicationdivision
modulusor, xor,
shift, notcomparison
p2 = p1 ➔ p2
p2 = p1 ➔ p2
p2 = p2 ± 1 ➔ p2
p3 = p2 ± p1 ➔ p3
p2 = p2 & 0xffff ➔ p2
not tainted
Tracking pointers
assignment
addition subtraction
and
multiplicationdivision
modulusor, xor,
shift, notcomparison
p2 = p1 ➔ p2
p2 = p1 ➔ p2
p2 = p2 ± 1 ➔ p2
p3 = p2 ± p1 ➔ p3
p2 = p2 & 0xffff ➔ p2
not tainted
Tracking pointers
assignment
addition subtraction
and
multiplicationdivision
modulusor, xor,
shift, notcomparison
p2 = p1 ➔ p2
p2 = p1 ➔ p2
p2 = p2 ± 1 ➔ p2
p3 = p2 ± p1 ➔ p3
p2 = p2 & 0xffff ➔ p2
not tainted
Tracking pointers
assignment
addition subtraction
and
multiplicationdivision
modulusor, xor,
shift, notcomparison
p2 = p1 ➔ p2
p2 = p1 ➔ p2
p2 = p2 ± 1 ➔ p2
p3 = p2 ± p1 ➔ p3
p2 = p2 & 0xffff ➔ p2
not tainted
Tracking pointers
assignment
addition subtraction
and
multiplicationdivision
modulusor, xor,
shift, notcomparison
p2 = p1 ➔ p2
p2 = p1 ➔ p2
p2 = p2 ± 1 ➔ p2
p3 = p2 ± p1 ➔ p3
p2 = p2 & 0xffff ➔ p2
not tainted
Tracking pointers
Based on domain knowledge and expertise
assignment
addition subtraction
and
multiplicationdivision
modulusor, xor,
shift, notcomparison
Update metadata (1)
Pointer Counts
Update metadata (1)
Pointer Counts
• Assignment: increment the count of the pointer that is copied, decrement the count of the pointer that is overwritten
Update metadata (1)
Pointer Counts
• Assignment: increment the count of the pointer that is copied, decrement the count of the pointer that is overwritten
Update metadata (1)
ptr3 = ptr1 ➔ ptr3 , ptr1 1 2 2
ptr1 = NULL ➔ ptr1 , ptr32 1
Pointer Counts
• Assignment: increment the count of the pointer that is copied, decrement the count of the pointer that is overwritten
• Function return: decrement the count of pointers stored in local variables
Update metadata (1)
ptr3 = ptr1 ➔ ptr3 , ptr1 1 2 2
ptr1 = NULL ➔ ptr1 , ptr32 1
Pointer Counts
• Assignment: increment the count of the pointer that is copied, decrement the count of the pointer that is overwritten
• Function return: decrement the count of pointers stored in local variables
• Memory deallocation: decrement the count of pointers reachable from the deallocated memory
Update metadata (1)
ptr3 = ptr1 ➔ ptr3 , ptr1 1 2 2
ptr1 = NULL ➔ ptr1 , ptr32 1
Update metadata (2)
Deallocation indicator
Update metadata (2)
Deallocation indicator
• Set to true when a pointer is passed to a deallocation function (e.g., free)
Update metadata (2)
Deallocation indicator
• Set to true when a pointer is passed to a deallocation function (e.g., free)
Last use location
Update metadata (2)
Deallocation indicator
• Set to true when a pointer is passed to a deallocation function (e.g., free)
Last use location
• Set to the current location whenever a pointer is
- propagated- passed as a function argument- returned from a function- used to access memory
Update metadata (2)
3. Identifying when leaks occur
3. Identifying when leaks occurLost memory Forgotten memory
If a taint mark’s pointer count is zero and it’s deallocated
indicator is false
If, at the end of execution, a taint mark’s deallocated
indicator is false
3. Identifying when leaks occurLost memory Forgotten memory
If a taint mark’s pointer count is zero and it’s deallocated
indicator is false
If, at the end of execution, a taint mark’s deallocated
indicator is false
3. Identifying when leaks occurLost memory Forgotten memory
If a taint mark’s pointer count is zero and it’s deallocated
indicator is false
If, at the end of execution, a taint mark’s deallocated
indicator is false
(Checks are recursive)
3. Identifying when leaks occurLost memory Forgotten memory
If a taint mark’s pointer count is zero and it’s deallocated
indicator is false
If, at the end of execution, a taint mark’s deallocated
indicator is false
Generate a leak report: • allocation location, allocation size, and last use location
(Checks are recursive)
3. Identifying when leaks occurLost memory Forgotten memory
If a taint mark’s pointer count is zero and it’s deallocated
indicator is false
If, at the end of execution, a taint mark’s deallocated
indicator is false
Generate a leak report: • allocation location, allocation size, and last use location
Merge leak reports: • combine reports with identical allocation and last use
locations, add allocation sizes
(Checks are recursive)
Prototype tool
Implemented using Valgrind
Prototype tool
Implemented using Valgrind
30–100x overheads
Prototype tool
16 bytes of memory allocated: at malloc by addhash (hash.c:50) by parser (parser.c:210) by readcell (parser.c:34) by main (main.c:98) was leaked: at free by delHtab (hash.c:28) by grdcell(grdcell.c:354) by main (main.c:227)
Implemented using Valgrind
Prototype tool
16 bytes of memory allocated: at malloc by addhash (hash.c:50) by parser (parser.c:210) by readcell (parser.c:34) by main (main.c:98) was leaked: at free by delHtab (hash.c:28) by grdcell(grdcell.c:354) by main (main.c:227)
Implemented using Valgrind
Prototype tool
16 bytes of memory allocated: at malloc by addhash (hash.c:50) by parser (parser.c:210) by readcell (parser.c:34) by main (main.c:98) was leaked: at free by delHtab (hash.c:28) by grdcell(grdcell.c:354) by main (main.c:227)
Implemented using Valgrind
Prototype tool
16 bytes of memory allocated: at malloc by addhash (hash.c:50) by parser (parser.c:210) by readcell (parser.c:34) by main (main.c:98) was leaked: at free by delHtab (hash.c:28) by grdcell(grdcell.c:354) by main (main.c:227)
Implemented using Valgrind
Can be used to prioritize debugging effort
Evaluation
How does Leakpoint’s ability to detect memory leaks compare
to existing tools?
How effective is Leakpoint at guiding developers to the
locations where memory leaks may be fixed?
RQ1: Comparison with existing tools
Subjects
164.gzip 4 1 4 4175.vpr 47 0 47 47176.gcc 1121 406 (1415) 1121 1121181.mcf 0 0 0 0
186.crafty 37 0 37 37197.parser 2 0 2 2
252.eon 380 380 380 380253.perlbmk 3481 0 (2) 3481 536
254.gap 2 0 (2) 2 2255.vortex 15 1 15 15256.bzip2 10 1 10 10300.twolf 1403 68 (3) 1403 1403
RQ1: Comparison with existing tools
Subjects
164.gzip 4 1 4 4175.vpr 47 0 47 47176.gcc 1121 406 (1415) 1121 1121181.mcf 0 0 0 0
186.crafty 37 0 37 37197.parser 2 0 2 2
252.eon 380 380 380 380253.perlbmk 3481 0 (2) 3481 536
254.gap 2 0 (2) 2 2255.vortex 15 1 15 15256.bzip2 10 1 10 10300.twolf 1403 68 (3) 1403 1403
RQ1: Comparison with existing tools
Leakpoint
Subjects
164.gzip 4 1 4 4175.vpr 47 0 47 47176.gcc 1121 406 (1415) 1121 1121181.mcf 0 0 0 0
186.crafty 37 0 37 37197.parser 2 0 2 2
252.eon 380 380 380 380253.perlbmk 3481 0 (2) 3481 536
254.gap 2 0 (2) 2 2255.vortex 15 1 15 15256.bzip2 10 1 10 10300.twolf 1403 68 (3) 1403 1403
RQ1: Comparison with existing tools
omegaLeakpoint
Subjects
164.gzip 4 1 4 4175.vpr 47 0 47 47176.gcc 1121 406 (1415) 1121 1121181.mcf 0 0 0 0
186.crafty 37 0 37 37197.parser 2 0 2 2
252.eon 380 380 380 380253.perlbmk 3481 0 (2) 3481 536
254.gap 2 0 (2) 2 2255.vortex 15 1 15 15256.bzip2 10 1 10 10300.twolf 1403 68 (3) 1403 1403
RQ1: Comparison with existing tools
omega MemCheckLeakpoint
Subjects
164.gzip 4 1 4 4175.vpr 47 0 47 47176.gcc 1121 406 (1415) 1121 1121181.mcf 0 0 0 0
186.crafty 37 0 37 37197.parser 2 0 2 2
252.eon 380 380 380 380253.perlbmk 3481 0 (2) 3481 536
254.gap 2 0 (2) 2 2255.vortex 15 1 15 15256.bzip2 10 1 10 10300.twolf 1403 68 (3) 1403 1403
RQ1: Comparison with existing tools
mtraceomega MemCheckLeakpoint
Leak detectionLeak identificationSubjects
164.gzip 4 1 4 4175.vpr 47 0 47 47176.gcc 1121 406 (1415) 1121 1121181.mcf 0 0 0 0
186.crafty 37 0 37 37197.parser 2 0 2 2
252.eon 380 380 380 380253.perlbmk 3481 0 (2) 3481 536
254.gap 2 0 (2) 2 2255.vortex 15 1 15 15256.bzip2 10 1 10 10300.twolf 1403 68 (3) 1403 1403
RQ1: Comparison with existing tools
mtraceomega MemCheckLeakpoint
Subjects
164.gzip 4 1 4 4175.vpr 47 0 47 47176.gcc 1121 406 (1415) 1121 1121181.mcf 0 0 0 0
186.crafty 37 0 37 37197.parser 2 0 2 2
252.eon 380 380 380 380253.perlbmk 3481 0 (2) 3481 536
254.gap 2 0 (2) 2 2255.vortex 15 1 15 15256.bzip2 10 1 10 10300.twolf 1403 68 (3) 1403 1403
RQ1: Comparison with existing tools
mtraceomega MemCheckLeakpoint
# Detected memory leaks (# false positives)Subjects
164.gzip 4 1 4 4175.vpr 47 0 47 47176.gcc 1121 406 (1415) 1121 1121181.mcf 0 0 0 0
186.crafty 37 0 37 37197.parser 2 0 2 2
252.eon 380 380 380 380253.perlbmk 3481 0 (2) 3481 536
254.gap 2 0 (2) 2 2255.vortex 15 1 15 15256.bzip2 10 1 10 10300.twolf 1403 68 (3) 1403 1403
RQ1: Comparison with existing tools
mtraceomega MemCheckLeakpoint
# Detected memory leaks (# false positives)Subjects
164.gzip 4 1 4 4175.vpr 47 0 47 47176.gcc 1121 406 (1415) 1121 1121181.mcf 0 0 0 0
186.crafty 37 0 37 37197.parser 2 0 2 2
252.eon 380 380 380 380253.perlbmk 3481 0 (2) 3481 536
254.gap 2 0 (2) 2 2255.vortex 15 1 15 15256.bzip2 10 1 10 10300.twolf 1403 68 (3) 1403 1403
RQ1: Comparison with existing tools
mtraceomega MemCheckLeakpoint
# Detected memory leaks (# false positives)Subjects
164.gzip 4 1 4 4175.vpr 47 0 47 47176.gcc 1121 406 (1415) 1121 1121181.mcf 0 0 0 0
186.crafty 37 0 37 37197.parser 2 0 2 2
252.eon 380 380 380 380253.perlbmk 3481 0 (2) 3481 536
254.gap 2 0 (2) 2 2255.vortex 15 1 15 15256.bzip2 10 1 10 10300.twolf 1403 68 (3) 1403 1403
RQ1: Comparison with existing tools
mtraceomega MemCheckLeakpoint
# Detected memory leaks (# false positives)Subjects
164.gzip 4 1 4 4175.vpr 47 0 47 47176.gcc 1121 406 (1415) 1121 1121181.mcf 0 0 0 0
186.crafty 37 0 37 37197.parser 2 0 2 2
252.eon 380 380 380 380253.perlbmk 3481 0 (2) 3481 536
254.gap 2 0 (2) 2 2255.vortex 15 1 15 15256.bzip2 10 1 10 10300.twolf 1403 68 (3) 1403 1403
RQ1: Comparison with existing tools
mtraceomega MemCheckLeakpoint
# Detected memory leaks (# false positives)Subjects
164.gzip 4 1 4 4175.vpr 47 0 47 47176.gcc 1121 406 (1415) 1121 1121181.mcf 0 0 0 0
186.crafty 37 0 37 37197.parser 2 0 2 2
252.eon 380 380 380 380253.perlbmk 3481 0 (2) 3481 536
254.gap 2 0 (2) 2 2255.vortex 15 1 15 15256.bzip2 10 1 10 10300.twolf 1403 68 (3) 1403 1403
RQ1: Comparison with existing tools
mtraceomega MemCheckLeakpoint
Leakpoint is at least as effective as existing tools at detecting memory leaks
RQ2: Effectiveness at guiding developers
Compare the leak locations identified by Leakpoint with the locations where the leaks were fixed by
the original application developers.
RQ2: Effectiveness at guiding developers
Compare the leak locations identified by Leakpoint with the locations where the leaks were fixed by
the original application developers.
Transmission
RQ2: Effectiveness at guiding developers
Compare the leak locations identified by Leakpoint with the locations where the leaks were fixed by
the original application developers.
Transmission
RQ2: Effectiveness at guiding developers
Compare the leak locations identified by Leakpoint with the locations where the leaks were fixed by
the original application developers.
Transmission
RQ2: Effectiveness at guiding developers
Compare the leak locations identified by Leakpoint with the locations where the leaks were fixed by
the original application developers.
Transmission4 memory leaks total
static void processCompletedTasks(tr_web *web) { ... task->done_func(web->session, ..., task->done_func_user_data); ... evbuffer_free(task->response); tr_free(task->url); tr_free(task); ...}
Transmissionstatic void invokeRequest(void * vreq) { ... hash = tr_new0(uint8_t, SHA_DIGEST_LENGTH); memcpy(hash, req->torrent_hash, SHA_DIGEST_LENGTH); tr_webRun(req->session, req->url, req->done_func, hash); ...}
static void processCompletedTasks(tr_web *web) { ... task->done_func(web->session, ..., task->done_func_user_data); ... evbuffer_free(task->response); tr_free(task->url); tr_free(task); ...}
Transmissionstatic void invokeRequest(void * vreq) { ... hash = tr_new0(uint8_t, SHA_DIGEST_LENGTH); memcpy(hash, req->torrent_hash, SHA_DIGEST_LENGTH); tr_webRun(req->session, req->url, req->done_func, hash); ...}
static void onStoppedResponse(tr_session *session, ..., void *torrent_hash) { dbgmsg(NULL, "got a response ... message");
onReqDone(session);}
// tr_free(torrent_hash);
static void processCompletedTasks(tr_web *web) { ... task->done_func(web->session, ..., task->done_func_user_data); ... evbuffer_free(task->response); tr_free(task->url); tr_free(task); ...}
Transmissionstatic void invokeRequest(void * vreq) { ... hash = tr_new0(uint8_t, SHA_DIGEST_LENGTH); memcpy(hash, req->torrent_hash, SHA_DIGEST_LENGTH); tr_webRun(req->session, req->url, req->done_func, hash); ...}
static void onStoppedResponse(tr_session *session, ..., void *torrent_hash) { dbgmsg(NULL, "got a response ... message");
onReqDone(session);}
// tr_free(torrent_hash);
Distance: 6 statements
URIHANDLER_FUNC(mod_rewrite_uri_handler) { ...
hctx = handler_ctx_init();
con->plugin_ctx[p->id] = hctx;
...}
Lighttpd 1
URIHANDLER_FUNC(mod_rewrite_uri_handler) { ...
hctx = handler_ctx_init();
con->plugin_ctx[p->id] = hctx;
...}
Lighttpd 1
// if(con->plugin_ctx[p->id] == NULL) {
// } // else { // hctx = con->plugin_ctx[p->id]; // }
URIHANDLER_FUNC(mod_rewrite_uri_handler) { ...
hctx = handler_ctx_init();
con->plugin_ctx[p->id] = hctx;
...}
Lighttpd 1
// if(con->plugin_ctx[p->id] == NULL) {
// } // else { // hctx = con->plugin_ctx[p->id]; // }
Distance: overlapping
int http_request_parse(server *srv, connection *con) { ... if(NULL == (ds = (data_string *)array_get_unused_element( con->request.headers, TYPE_STRING))) { ds = data_string_init(); } ... else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Content-Length")))) { char *err unsigned long int r; size_t j if (con_length_set) { con->http_status = 400; con->keep_alive = 0; if(srv->srvconf.log_request_header_on_error) { log_error_write(srv, __FILE__, __LINE__, "s", "duplicate ..."); log_error_write(srv, __FILE__, __LINE__, "Sb", "request-header:\n", con->request.request); }
return 0; } ...}
Lighttpd 2
int http_request_parse(server *srv, connection *con) { ... if(NULL == (ds = (data_string *)array_get_unused_element( con->request.headers, TYPE_STRING))) { ds = data_string_init(); } ... else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Content-Length")))) { char *err unsigned long int r; size_t j if (con_length_set) { con->http_status = 400; con->keep_alive = 0; if(srv->srvconf.log_request_header_on_error) { log_error_write(srv, __FILE__, __LINE__, "s", "duplicate ..."); log_error_write(srv, __FILE__, __LINE__, "Sb", "request-header:\n", con->request.request); }
return 0; } ...}
Lighttpd 2
// array_insert_unique(con->request.headers, (data_unset *)ds);
int http_request_parse(server *srv, connection *con) { ... if(NULL == (ds = (data_string *)array_get_unused_element( con->request.headers, TYPE_STRING))) { ds = data_string_init(); } ... else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Content-Length")))) { char *err unsigned long int r; size_t j if (con_length_set) { con->http_status = 400; con->keep_alive = 0; if(srv->srvconf.log_request_header_on_error) { log_error_write(srv, __FILE__, __LINE__, "s", "duplicate ..."); log_error_write(srv, __FILE__, __LINE__, "Sb", "request-header:\n", con->request.request); }
return 0; } ...}
Lighttpd 2
// array_insert_unique(con->request.headers, (data_unset *)ds);
Distance: 1 statement
static struct spelling *spelling_base;
static void push_string(char *string) { ... spelling_base = xmalloc(spelling_size * sizeof(struct spelling)); ...}
void finish_init() { ...
constructor_decl = p->decl; ... spelling_base = p->spelling_base; ...}
GCC
static struct spelling *spelling_base;
static void push_string(char *string) { ... spelling_base = xmalloc(spelling_size * sizeof(struct spelling)); ...}
void finish_init() { ...
constructor_decl = p->decl; ... spelling_base = p->spelling_base; ...}
GCC
// free(spelling_base);
static struct spelling *spelling_base;
static void push_string(char *string) { ... spelling_base = xmalloc(spelling_size * sizeof(struct spelling)); ...}
void finish_init() { ...
constructor_decl = p->decl; ... spelling_base = p->spelling_base; ...}
GCC
// free(spelling_base);
Distance: 10 statements*
Summary
• A new technique for identifying where memory leaks occur
• at least as effective as existing techniques at detecting memory leaks
• helpful in guiding developers to the locations where memory leaks should be fixed
Future work
Future work
Improvedimplementation
Future work
Additionalexperimentation
Improvedimplementation
Future work
Additionalexperimentation
UserStudies
Improvedimplementation
Questions?
1 Taintingpointers
2 Propagatingtaint marks
3 Identifyingwhen leaksoccur