From a5cc2a5d2fc7074f50fbaa772232b6e0fea7ce89 Mon Sep 17 00:00:00 2001 From: Dave Beckett Date: Sun, 25 Jan 2015 15:44:27 -0800 Subject: [PATCH] Make form use/free api saner and prevent double free. Fixes Issue #28 --- src/common.c | 31 +++++++++++++++++++++---------- src/flickcurl_internal.h | 2 +- src/oauth.c | 34 ++++++++++++++++++---------------- 3 files changed, 40 insertions(+), 27 deletions(-) diff --git a/src/common.c b/src/common.c index 1fcc67d8..348c78fe 100644 --- a/src/common.c +++ b/src/common.c @@ -1516,14 +1516,18 @@ flickcurl_invoke_get_content(flickcurl *fc, size_t* size_p) } +/* + * INTERNAL - free a form. + */ void -flickcurl_free_form(char **form, int count) +flickcurl_free_form(char **form) { if(!form) return; /* free content which is the first key */ - free(form[0]); + if(form[0]) + free(form[0]); free(form); } @@ -1537,10 +1541,16 @@ flickcurl_free_form(char **form, int count) * INTERNAL - decoded content from current request as HTTP FORM and return fields * * NOTE: The result may be an empty array with just two NULL -* terminating pointers if there are no fields. +* terminating pointers if there are no fields or no content. +* +* If @count_p is not NULL, *@count_p is set to the number of pairs of +* fields. +* +* Index 0 is used to store the raw content. +* +* Return value: NULL on failure or an array of [char* field name, +* char* field value] starting at index 1, terminated by a NULL pair. * -* Return value: array of [char* field name, char* field value] with -* NULL pair terminating or NULL on failure */ char** flickcurl_invoke_get_form_content(flickcurl *fc, int* count_p) @@ -1562,21 +1572,24 @@ flickcurl_invoke_get_form_content(flickcurl *fc, int* count_p) count++; /* counting separators so need +1 for number of contents */ } - /* Allocate count + 1 sized array of char* (key, value) pointers + /* Allocate 1+ count + 1 sized array of char* (key, value) pointers * The last pair are always (NULL, NULL). * * The pointers are into the 'content' buffer which is kept around * and owned by this array and stored in form[0]. */ - form = (char**)calloc(2*(count + 1), sizeof(char*)); + form = (char**)calloc(1 + 2*(count + 1), sizeof(char*)); if(!form) { if(content) free(content); return NULL; } + /* the form owns the content array */ + form[0] = content; + if(content) { - for(p = content, i = 0; *p; p++) { + for(p = content, i = 1; *p; p++) { char *start = p; while(*p && *p != '&' && *p != '=') @@ -1590,8 +1603,6 @@ flickcurl_invoke_get_form_content(flickcurl *fc, int* count_p) } form[i++] = NULL; form[i] = NULL; - - free(content); } if(count_p) diff --git a/src/flickcurl_internal.h b/src/flickcurl_internal.h index 4904341c..30829789 100644 --- a/src/flickcurl_internal.h +++ b/src/flickcurl_internal.h @@ -119,7 +119,7 @@ xmlDocPtr flickcurl_invoke(flickcurl *fc); char* flickcurl_invoke_get_content(flickcurl *fc, size_t* size_p); /* Invoke URI prepared above and get back 'count' key/values */ char** flickcurl_invoke_get_form_content(flickcurl *fc, int* count_p); -void flickcurl_free_form(char **form, int count); +void flickcurl_free_form(char **form); /* args.c */ void flickcurl_free_arg(flickcurl_arg *arg); diff --git a/src/oauth.c b/src/oauth.c index d1f649e3..8ac4e3c1 100644 --- a/src/oauth.c +++ b/src/oauth.c @@ -741,11 +741,12 @@ flickcurl_oauth_create_request_token(flickcurl* fc, const char* callback) uri, count); #endif - for(i = 0; i < (2 * count); i += 2) { - if(!strcmp(form[i], "oauth_token")) { - request_token = form[i+1]; - } else if(!strcmp(form[i], "oauth_token_secret")) { - request_token_secret = form[i+1]; + for(i = 0; i < count; i++) { + int offset = 1 + (2 * i); + if(!strcmp(form[offset], "oauth_token")) { + request_token = form[offset+1]; + } else if(!strcmp(form[offset], "oauth_token_secret")) { + request_token_secret = form[offset+1]; } } @@ -771,7 +772,7 @@ flickcurl_oauth_create_request_token(flickcurl* fc, const char* callback) tidy: if(form) - flickcurl_free_form(form, count); + flickcurl_free_form(form); return rc; } @@ -888,15 +889,16 @@ flickcurl_oauth_create_access_token(flickcurl* fc, const char* verifier) uri, count); #endif - for(i = 0; i < (2 * count); i += 2) { - if(!strcmp(form[i], "oauth_token")) { - access_token = form[i+1]; - } else if(!strcmp(form[i], "oauth_token_secret")) { - access_token_secret = form[i+1]; - } else if(!strcmp(form[i], "username")) { - username = form[i+1]; - } else if(!strcmp(form[i], "user_nsid")) { - user_nsid = form[i+1]; + for(i = 0; i < count; i++) { + int offset = 1 + (2 * i); + if(!strcmp(form[offset], "oauth_token")) { + access_token = form[offset+1]; + } else if(!strcmp(form[offset], "oauth_token_secret")) { + access_token_secret = form[offset+1]; + } else if(!strcmp(form[offset], "username")) { + username = form[offset+1]; + } else if(!strcmp(form[offset], "user_nsid")) { + user_nsid = form[offset+1]; } /* ignoring: fullname */ } @@ -952,7 +954,7 @@ flickcurl_oauth_create_access_token(flickcurl* fc, const char* verifier) tidy: if(form) - flickcurl_free_form(form, count); + flickcurl_free_form(form); return rc; }