diff --git a/auth.c b/auth.c index da0c0294..361f656c 100644 --- a/auth.c +++ b/auth.c @@ -150,8 +150,8 @@ static int parse_auth_choice(struct openconnect_info *vpninfo, struct oc_auth_fo continue; opt->nr_choices++; - opt = realloc(opt, sizeof(*opt) + - opt->nr_choices * sizeof(*choice)); + realloc_inplace(opt, sizeof(*opt) + + opt->nr_choices * sizeof(*choice)); if (!opt) return -ENOMEM; diff --git a/compat.c b/compat.c index da59d359..d728c94c 100644 --- a/compat.c +++ b/compat.c @@ -131,7 +131,7 @@ ssize_t openconnect__getline(char **lineptr, size_t *n, FILE *stream) break; *n *= 2; - *lineptr = realloc(*lineptr, *n); + realloc_inplace(*lineptr, *n); if (!*lineptr) return -1; } diff --git a/http.c b/http.c index d6a3636c..9b77be58 100644 --- a/http.c +++ b/http.c @@ -96,7 +96,7 @@ static void buf_append(struct oc_text_buf *buf, const char *fmt, ...) break; } - buf->data = realloc(buf->data, new_buf_len); + realloc_inplace(buf->data, new_buf_len); if (!buf->data) { buf->error = -ENOMEM; break; @@ -353,7 +353,7 @@ static int process_http_response(struct openconnect_info *vpninfo, int *result, lastchunk = 1; goto skip; } - body = realloc(body, done + chunklen + 1); + realloc_inplace(body, done + chunklen + 1); if (!body) return -ENOMEM; while (chunklen) { @@ -394,7 +394,7 @@ static int process_http_response(struct openconnect_info *vpninfo, int *result, /* HTTP 1.0 response. Just eat all we can in 16KiB chunks */ while (1) { - body = realloc(body, done + 16384); + realloc_inplace(body, done + 16384); if (!body) return -ENOMEM; i = openconnect_SSL_read(vpninfo, body + done, 16384); @@ -407,7 +407,7 @@ static int process_http_response(struct openconnect_info *vpninfo, int *result, return i; } else { /* Connection closed. Reduce allocation to just what we need */ - body = realloc(body, done + 1); + realloc_inplace(body, done + 1); if (!body) return -ENOMEM; break; diff --git a/openconnect-internal.h b/openconnect-internal.h index 4b4c4550..ff1b80bf 100644 --- a/openconnect-internal.h +++ b/openconnect-internal.h @@ -347,6 +347,14 @@ ssize_t openconnect__getline(char **lineptr, size_t *n, FILE *stream); char *openconnect__strcasestr(const char *haystack, const char *needle); #endif +/* I always coded as if it worked like this. Now it does. */ +#define realloc_inplace(p, size) do { \ + void *__realloc_old = p; \ + p = realloc(p, size); \ + if (size && !p) \ + free(__realloc_old); \ + } while (0) + /****************************************************************************/ /* tun.c */