From 0649433da53c7165f839e24e889e131e2894dd32 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 7 Nov 2016 10:55:25 +0100 Subject: realloc: use Curl_saferealloc to avoid common mistakes Discussed: https://curl.haxx.se/mail/lib-2016-11/0087.html --- lib/content_encoding.c | 9 +++------ lib/curl_ntlm_wb.c | 8 ++++---- lib/escape.c | 7 +++---- lib/http.c | 4 ++-- lib/http2.c | 7 +++---- lib/rtsp.c | 5 +++-- lib/security.c | 4 ++-- lib/ssh.c | 7 ++++--- lib/strdup.c | 23 +++++++++++++++++++++++ lib/strdup.h | 1 + 10 files changed, 48 insertions(+), 27 deletions(-) (limited to 'lib') diff --git a/lib/content_encoding.c b/lib/content_encoding.c index fa36aca4c..5a5824db4 100644 --- a/lib/content_encoding.c +++ b/lib/content_encoding.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -28,8 +28,8 @@ #include #include "sendf.h" #include "content_encoding.h" +#include "strdup.h" #include "curl_memory.h" - #include "memdebug.h" /* Comment this out if zlib is always going to be at least ver. 1.2.0.4 @@ -371,12 +371,9 @@ Curl_unencode_gzip_write(struct connectdata *conn, { /* Need more gzip header data state */ ssize_t hlen; - unsigned char *oldblock = z->next_in; - z->avail_in += (uInt)nread; - z->next_in = realloc(z->next_in, z->avail_in); + z->next_in = Curl_saferealloc(z->next_in, z->avail_in); if(z->next_in == NULL) { - free(oldblock); return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY); } /* Append the new block of data to the previous one */ diff --git a/lib/curl_ntlm_wb.c b/lib/curl_ntlm_wb.c index afdea16c0..1d1b3a3f2 100644 --- a/lib/curl_ntlm_wb.c +++ b/lib/curl_ntlm_wb.c @@ -51,6 +51,7 @@ #include "curl_ntlm_wb.h" #include "url.h" #include "strerror.h" +#include "strdup.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" #include "curl_memory.h" @@ -293,11 +294,10 @@ static CURLcode ntlm_wb_response(struct connectdata *conn, buf[len_out - 1] = '\0'; break; } - newbuf = realloc(buf, len_out + NTLM_BUFSIZE); - if(!newbuf) { - free(buf); + newbuf = Curl_saferealloc(buf, len_out + NTLM_BUFSIZE); + if(!newbuf) return CURLE_OUT_OF_MEMORY; - } + buf = newbuf; } diff --git a/lib/escape.c b/lib/escape.c index 66570076e..9fb8d3e15 100644 --- a/lib/escape.c +++ b/lib/escape.c @@ -31,6 +31,7 @@ #include "warnless.h" #include "non-ascii.h" #include "escape.h" +#include "strdup.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" #include "curl_memory.h" @@ -109,11 +110,9 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string, newlen += 2; /* the size grows with two, since this'll become a %XX */ if(newlen > alloc) { alloc *= 2; - testing_ptr = realloc(ns, alloc); - if(!testing_ptr) { - free(ns); + testing_ptr = Curl_saferealloc(ns, alloc); + if(!testing_ptr) return NULL; - } else { ns = testing_ptr; } diff --git a/lib/http.c b/lib/http.c index e7788e767..999d6da87 100644 --- a/lib/http.c +++ b/lib/http.c @@ -76,6 +76,7 @@ #include "pipeline.h" #include "http2.h" #include "connect.h" +#include "strdup.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -1255,14 +1256,13 @@ CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size) if(in->buffer) /* we have a buffer, enlarge the existing one */ - new_rb = realloc(in->buffer, new_size); + new_rb = Curl_saferealloc(in->buffer, new_size); else /* create a new buffer */ new_rb = malloc(new_size); if(!new_rb) { /* If we failed, we cleanup the whole buffer and return error */ - Curl_safefree(in->buffer); free(in); return CURLE_OUT_OF_MEMORY; } diff --git a/lib/http2.c b/lib/http2.c index b0301da56..1484e1515 100644 --- a/lib/http2.c +++ b/lib/http2.c @@ -35,7 +35,7 @@ #include "url.h" #include "connect.h" #include "strtoofft.h" - +#include "strdup.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" #include "curl_memory.h" @@ -841,10 +841,9 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, stream->push_headers_alloc) { char **headp; stream->push_headers_alloc *= 2; - headp = realloc(stream->push_headers, - stream->push_headers_alloc * sizeof(char *)); + headp = Curl_saferealloc(stream->push_headers, + stream->push_headers_alloc * sizeof(char *)); if(!headp) { - free(stream->push_headers); stream->push_headers = NULL; return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; } diff --git a/lib/rtsp.c b/lib/rtsp.c index d1bad19da..5da33d42c 100644 --- a/lib/rtsp.c +++ b/lib/rtsp.c @@ -36,6 +36,7 @@ #include "strcase.h" #include "select.h" #include "connect.h" +#include "strdup.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" #include "curl_memory.h" @@ -614,9 +615,9 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data, if(rtspc->rtp_buf) { /* There was some leftover data the last time. Merge buffers */ - char *newptr = realloc(rtspc->rtp_buf, rtspc->rtp_bufsize + *nread); + char *newptr = Curl_saferealloc(rtspc->rtp_buf, + rtspc->rtp_bufsize + *nread); if(!newptr) { - Curl_safefree(rtspc->rtp_buf); rtspc->rtp_buf = NULL; rtspc->rtp_bufsize = 0; return CURLE_OUT_OF_MEMORY; diff --git a/lib/security.c b/lib/security.c index ff2606669..87c22da07 100644 --- a/lib/security.c +++ b/lib/security.c @@ -62,7 +62,7 @@ #include "sendf.h" #include "strcase.h" #include "warnless.h" - +#include "strdup.h" /* The last #include file should be: */ #include "memdebug.h" @@ -202,7 +202,7 @@ static CURLcode read_data(struct connectdata *conn, if(len) { /* only realloc if there was a length */ len = ntohl(len); - tmp = realloc(buf->data, len); + tmp = Curl_saferealloc(buf->data, len); } if(tmp == NULL) return CURLE_OUT_OF_MEMORY; diff --git a/lib/ssh.c b/lib/ssh.c index 0df030d27..420beb27e 100644 --- a/lib/ssh.c +++ b/lib/ssh.c @@ -71,7 +71,7 @@ #include "url.h" #include "speedcheck.h" #include "getinfo.h" - +#include "strdup.h" #include "strcase.h" #include "vtls/vtls.h" #include "connect.h" @@ -2112,9 +2112,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) /* get room for the filename and extra output */ sshc->readdir_totalLen += 4 + sshc->readdir_len; - new_readdir_line = realloc(sshc->readdir_line, sshc->readdir_totalLen); + new_readdir_line = Curl_saferealloc(sshc->readdir_line, + sshc->readdir_totalLen); if(!new_readdir_line) { - Curl_safefree(sshc->readdir_line); + sshc->readdir_line = NULL; Curl_safefree(sshc->readdir_filename); Curl_safefree(sshc->readdir_longentry); state(conn, SSH_SFTP_CLOSE); diff --git a/lib/strdup.c b/lib/strdup.c index 5a15c2b16..136b69377 100644 --- a/lib/strdup.c +++ b/lib/strdup.c @@ -75,3 +75,26 @@ void *Curl_memdup(const void *src, size_t length) return buffer; } + +/*************************************************************************** + * + * Curl_saferealloc(ptr, size) + * + * Does a normal realloc(), but will free the data pointer if the realloc + * fails. If 'size' is zero, it will free the data and return a failure. + * + * This convenience function is provided and used to help us avoid a common + * mistake pattern when we could pass in a zero, catch the NULL return and end + * up free'ing the memory twice. + * + * Returns the new pointer or NULL on failure. + * + ***************************************************************************/ +void *Curl_saferealloc(void *ptr, size_t size) +{ + void *datap = realloc(ptr, size); + if(size && !datap) + /* only free 'ptr' if size was non-zero */ + free(ptr); + return datap; +} diff --git a/lib/strdup.h b/lib/strdup.h index c74a3b730..ae3d5d011 100644 --- a/lib/strdup.h +++ b/lib/strdup.h @@ -27,5 +27,6 @@ extern char *curlx_strdup(const char *str); #endif void *Curl_memdup(const void *src, size_t buffer_length); +void *Curl_saferealloc(void *ptr, size_t size); #endif /* HEADER_CURL_STRDUP_H */ -- cgit v1.2.3