if(str) {
CURLcode result = dyn_nappend(s, (const unsigned char *)str, strlen(str));
- curlx_free(str);
+ curl_free(str);
return result;
}
/* If we failed, we cleanup the whole buffer and return error */
return CURL_WRITEFUNC_ERROR;
}
if(outs->alloc_filename)
- curlx_free(outs->filename);
+ tool_safefree(outs->filename);
if(per->config->output_dir) {
- outs->filename = curl_maprintf("%s/%s", per->config->output_dir,
- filename);
+ char *f = curl_maprintf("%s/%s", per->config->output_dir,
+ filename);
curlx_free(filename);
+ if(!f)
+ return CURL_WRITEFUNC_ERROR;
+ outs->filename = curlx_strdup(f);
+ curl_free(f);
if(!outs->filename)
return CURL_WRITEFUNC_ERROR;
}
return CURL_WRITEFUNC_ERROR;
}
if(outs->alloc_filename)
- curlx_free(outs->filename);
+ tool_safefree(outs->filename);
if(per->config->output_dir) {
- outs->filename = curl_maprintf("%s/%s", per->config->output_dir,
- filename);
+ char *f = curl_maprintf("%s/%s", per->config->output_dir,
+ filename);
curlx_free(filename);
+ if(!f)
+ return CURL_WRITEFUNC_ERROR;
+ outs->filename = curlx_strdup(f);
+ curl_free(f);
if(!outs->filename)
return CURL_WRITEFUNC_ERROR;
}
hdrcbdata->config->show_headers) {
/* still awaiting the Content-Disposition header, store the header in
memory. Since it is not null-terminated, we need an extra dance. */
- char *clone = curl_maprintf("%.*s", (int)cb, str);
+ char *clone = curlx_memdup0(str, cb);
if(clone) {
struct curl_slist *old = hdrcbdata->headlist;
hdrcbdata->headlist = curl_slist_append(old, clone);
*
* The main point is to make sure that what is returned is different than what
* the regular memory functions return so that mixup will trigger problems.
+ *
+ * This test setup currently only works when building with a *shared* libcurl
+ * and not static, as in the latter case the tool and the library share some of
+ * the functions in incompatible ways.
*/
+/*
+ * This code appends this extra chunk of memory in front of every allocation
+ * done by libcurl with the only purpose to cause trouble when using the wrong
+ * free function on memory.
+ */
struct extramem {
size_t extra;
union {
static char *custom_strdup(const char *ptr)
{
struct extramem *m;
- size_t size = strlen(ptr) + 1;
- size_t sz = size + sizeof(struct extramem);
+ size_t len = strlen(ptr);
+ size_t sz = len + sizeof(struct extramem);
m = curlx_malloc(sz);
if(m) {
char *p = (char *)m->mem;
/* since strcpy is banned, we do memcpy */
- memcpy(p, ptr, sz);
- p[sz] = 0;
+ memcpy(p, ptr, len);
+ p[len] = 0;
return (char *)m->mem;
}
return NULL;
-
}
static void *custom_realloc(void *ptr, size_t size)
struct extramem *m = NULL;
size_t sz = size + sizeof(struct extramem);
if(ptr)
- m = (void *)((char *)ptr - offsetof(struct extramem, mem));
+ /* if given a pointer, figure out the original */
+ ptr = (void *)((char *)ptr - offsetof(struct extramem, mem));
m = curlx_realloc(ptr, sz);
if(m)
return m->mem;
global->first = global->last = config_alloc();
if(global->first) {
/* Perform the libcurl initialization */
-#ifdef GLOBAL_MEM
+#ifdef CURL_DEBUG_GLOBAL_MEM
result = curl_global_init_mem(CURL_GLOBAL_ALL, custom_malloc, custom_free,
custom_realloc, custom_strdup,
custom_calloc);
size_t feat_ext_count = feature_count;
#ifdef CURL_CA_EMBED
++feat_ext_count;
+#endif
+#ifdef CURL_DEBUG_GLOBAL_MEM
+ ++feat_ext_count;
#endif
feat_ext = curlx_malloc(sizeof(*feature_names) * (feat_ext_count + 1));
if(feat_ext) {
feat_ext_count = feature_count;
#ifdef CURL_CA_EMBED
feat_ext[feat_ext_count++] = "CAcert";
+#endif
+#ifdef CURL_DEBUG_GLOBAL_MEM
+ feat_ext[feat_ext_count++] = "global-mem-debug";
#endif
feat_ext[feat_ext_count] = NULL;
qsort((void *)feat_ext, feat_ext_count, sizeof(*feat_ext),
tool_safefree(per->etag_save.filename);
if(outs->alloc_filename)
- curlx_free(outs->filename);
+ tool_safefree(outs->filename);
curl_slist_free_all(per->hdrcbdata.headlist);
per->hdrcbdata.headlist = NULL;
return result;
if(uerr)
result = urlerr_cvt(uerr);
else {
+ /* use our new URL instead! */
curlx_free(per->url); /* free previous URL */
- per->url = updated; /* use our new URL instead! */
+ /* make it allocated by tool memory */
+ per->url = curlx_strdup(updated);
+ curl_free(updated);
+ if(!per->url)
+ result = CURLE_OUT_OF_MEMORY;
}
}
curl_url_cleanup(uh);
if((PARAM_OK == file2string(&etag_from_file, file)) &&
etag_from_file) {
- header = curl_maprintf("If-None-Match: %s", etag_from_file);
+ char *h = curl_maprintf("If-None-Match: %s", etag_from_file);
tool_safefree(etag_from_file);
+ if(h) {
+ /* move it to the right memory */
+ header = curlx_strdup(h);
+ curl_free(h);
+ }
}
else
- header = curl_maprintf("If-None-Match: \"\"");
+ header = curlx_strdup("If-None-Match: \"\"");
if(!header) {
if(file)
/* add Etag from file to list of custom headers */
pe = add2list(&config->headers, header);
- tool_safefree(header);
+ curlx_free(header);
if(file)
curlx_fclose(file);
if(config->output_dir && *config->output_dir) {
char *d = curl_maprintf("%s/%s", config->output_dir, per->outfile);
- if(!d)
+ tool_safefree(per->outfile);
+ if(d) {
+ per->outfile = curlx_strdup(d); /* move to right memory */
+ curl_free(d);
+ }
+ if(!d || !per->outfile)
return CURLE_WRITE_ERROR;
- curlx_free(per->outfile);
- per->outfile = d;
}
/* Create the directory hierarchy, if not pre-existent to a multiple
file output call */
if(!newpath)
goto out;
uerr = curl_url_set(uh, CURLUPART_PATH, newpath, 0);
- curlx_free(newpath);
+ curl_free(newpath);
if(uerr) {
result = urlerr_cvt(uerr);
goto out;
goto out;
}
curlx_free(*inurlp);
- *inurlp = newurl;
- result = CURLE_OK;
+ /* make it owned by tool memory */
+ *inurlp = curlx_strdup(newurl);
+ curl_free(newurl);
+ if(*inurlp)
+ result = CURLE_OK;
+ else
+ result = CURLE_OUT_OF_MEMORY;
}
}
else
/* put it in the output */
if(curlx_dyn_addn(out, enc, elen))
err = PARAM_NO_MEM;
- curl_free(enc);
+ curlx_free(enc);
if(err)
break;
}
else {
if(curlx_dyn_addn(out, enc, elen))
err = PARAM_NO_MEM;
- curl_free(enc);
+ curlx_free(enc);
}
if(err)
break;