src: deprecate strdup(), use mem_strdup() explicitly
This fixes a nasty bug that manifests on windows when building without precompiled headers. util/stringops.h used to silently replace strdup with a macro that's compatible with mem_free(). This header would typically be included everywhere due to PCH, but without it the strdup from libc would sometimes be in scope. On most platforms mem_free() is equivalent to free(), but not on windows, because we have to use _aligned_free() there. Attempting to mem_free() the result of a libc strdup() would segfault in such a configuration. Avoid the footgun by banning strdup() entirely. Maybe redefining libc names isn't such a great idea, who knew?
This commit is contained in:
parent
c8a2fb1418
commit
fda8556a39
26 changed files with 50 additions and 47 deletions
|
@ -220,7 +220,7 @@ static void credits_add(char *data, int time) {
|
|||
for(c = data; *c; ++c) {
|
||||
if(*c == '\n') {
|
||||
buf[i] = 0;
|
||||
e->data[l] = strdup(buf);
|
||||
e->data[l] = mem_strdup(buf);
|
||||
i = 0;
|
||||
++l;
|
||||
} else {
|
||||
|
@ -229,7 +229,7 @@ static void credits_add(char *data, int time) {
|
|||
}
|
||||
|
||||
buf[i] = 0;
|
||||
e->data[l] = strdup(buf);
|
||||
e->data[l] = mem_strdup(buf);
|
||||
credits.end += time;
|
||||
}
|
||||
|
||||
|
|
|
@ -156,7 +156,7 @@ static DirWatch *dirwatch_get(const char *path, bool create) {
|
|||
}
|
||||
|
||||
dw = ALLOC(typeof(*dw));
|
||||
dw->path = strdup(path);
|
||||
dw->path = mem_strdup(path);
|
||||
dw->wd = wd;
|
||||
|
||||
WDRecord *wdrec = NOT_NULL(wdrecord_get(wd, true));
|
||||
|
@ -355,7 +355,7 @@ FileWatch *filewatch_watch(const char *syspath) {
|
|||
|
||||
auto fw = list_push(&dw->filewatch_list, ALLOC(FileWatch, {
|
||||
.dw = dw,
|
||||
.filename = strdup(filename),
|
||||
.filename = mem_strdup(filename),
|
||||
}));
|
||||
|
||||
SDL_UnlockMutex(FW.modify_mtx);
|
||||
|
|
|
@ -157,7 +157,7 @@
|
|||
*
|
||||
* Example:
|
||||
*
|
||||
* #define HT_FUNC_COPY_KEY(dst, src) (*(dst) = strdup(src))
|
||||
* #define HT_FUNC_COPY_KEY(dst, src) (*(dst) = mem_strdup(src))
|
||||
*/
|
||||
#ifndef HT_FUNC_COPY_KEY
|
||||
#define HT_FUNC_COPY_KEY(dst, src) (*(dst) = (src))
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#define HT_FUNC_FREE_KEY(key) mem_free(key)
|
||||
#define HT_FUNC_KEYS_EQUAL(key1, key2) (!strcmp(key1, key2))
|
||||
#define HT_FUNC_HASH_KEY(key) htutil_hashfunc_string(key)
|
||||
#define HT_FUNC_COPY_KEY(dst, src) (*(dst) = strdup(src))
|
||||
#define HT_FUNC_COPY_KEY(dst, src) (*(dst) = mem_strdup(src))
|
||||
#define HT_KEY_FMT "s"
|
||||
#define HT_KEY_PRINTABLE(key) (key)
|
||||
#define HT_VALUE_FMT "p"
|
||||
|
@ -41,7 +41,7 @@
|
|||
#define HT_FUNC_FREE_KEY(key) mem_free(key)
|
||||
#define HT_FUNC_KEYS_EQUAL(key1, key2) (!strcmp(key1, key2))
|
||||
#define HT_FUNC_HASH_KEY(key) htutil_hashfunc_string(key)
|
||||
#define HT_FUNC_COPY_KEY(dst, src) (*(dst) = strdup(src))
|
||||
#define HT_FUNC_COPY_KEY(dst, src) (*(dst) = mem_strdup(src))
|
||||
#define HT_KEY_FMT "s"
|
||||
#define HT_KEY_PRINTABLE(key) (key)
|
||||
#define HT_VALUE_FMT "p"
|
||||
|
@ -62,7 +62,7 @@
|
|||
#define HT_FUNC_FREE_KEY(key) mem_free(key)
|
||||
#define HT_FUNC_KEYS_EQUAL(key1, key2) (!strcmp(key1, key2))
|
||||
#define HT_FUNC_HASH_KEY(key) htutil_hashfunc_string(key)
|
||||
#define HT_FUNC_COPY_KEY(dst, src) (*(dst) = strdup(src))
|
||||
#define HT_FUNC_COPY_KEY(dst, src) (*(dst) = mem_strdup(src))
|
||||
#define HT_KEY_FMT "s"
|
||||
#define HT_KEY_PRINTABLE(key) (key)
|
||||
#define HT_VALUE_FMT PRIi64
|
||||
|
@ -81,7 +81,7 @@
|
|||
#define HT_FUNC_FREE_KEY(key) mem_free(key)
|
||||
#define HT_FUNC_KEYS_EQUAL(key1, key2) (!strcmp(key1, key2))
|
||||
#define HT_FUNC_HASH_KEY(key) htutil_hashfunc_string(key)
|
||||
#define HT_FUNC_COPY_KEY(dst, src) (*(dst) = strdup(src))
|
||||
#define HT_FUNC_COPY_KEY(dst, src) (*(dst) = mem_strdup(src))
|
||||
#define HT_KEY_FMT "s"
|
||||
#define HT_KEY_PRINTABLE(key) (key)
|
||||
#define HT_VALUE_FMT PRIi64
|
||||
|
@ -233,7 +233,7 @@
|
|||
#define HT_FUNC_FREE_KEY(key) mem_free(key)
|
||||
#define HT_FUNC_KEYS_EQUAL(key1, key2) (!strcmp(key1, key2))
|
||||
#define HT_FUNC_HASH_KEY(key) htutil_hashfunc_string(key)
|
||||
#define HT_FUNC_COPY_KEY(dst, src) (*(dst) = strdup(src))
|
||||
#define HT_FUNC_COPY_KEY(dst, src) (*(dst) = mem_strdup(src))
|
||||
#define HT_KEY_FMT "s"
|
||||
#define HT_KEY_PRINTABLE(key) (key)
|
||||
#define HT_VALUE_FMT "s"
|
||||
|
|
|
@ -771,7 +771,7 @@ static char *copy_pattern(const char *p) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
return strdup(orig);
|
||||
return mem_strdup(orig);
|
||||
}
|
||||
|
||||
void log_add_filter(LogLevelDiff diff, const char *pmod, const char *pfunc) {
|
||||
|
|
|
@ -56,6 +56,12 @@ void *mem_dup(const void *src, size_t size)
|
|||
|
||||
#define memdup mem_dup
|
||||
|
||||
INLINE attr_returns_allocated attr_nonnull(1)
|
||||
char *mem_strdup(const char *str) {
|
||||
size_t sz = strlen(str) + 1;
|
||||
return memcpy(mem_alloc(sz), str, sz);
|
||||
}
|
||||
|
||||
/*
|
||||
* This macro transparently handles allocation of both normal and over-aligned types.
|
||||
* The allocation must be free'd with mem_free().
|
||||
|
|
|
@ -22,7 +22,7 @@ MenuEntry *add_menu_entry(MenuData *menu, const char *name, MenuAction action, v
|
|||
.action = action,
|
||||
.arg = arg,
|
||||
.transition = menu->transition,
|
||||
.name = name ? strdup(name) : NULL,
|
||||
.name = name ? mem_strdup(name) : NULL,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -313,7 +313,7 @@ static int bind_addvalue(OptionBinding *b, char *val) {
|
|||
}
|
||||
|
||||
b->values = mem_realloc(b->values, (1 + b->valrange_max) * sizeof(char*));
|
||||
b->values[b->valrange_max] = strdup(val);
|
||||
b->values[b->valrange_max] = mem_strdup(val);
|
||||
return b->valrange_max;
|
||||
}
|
||||
|
||||
|
@ -965,7 +965,7 @@ static MenuData* create_options_menu_gamepad(MenuData *parent) {
|
|||
m->end = destroy_options_menu_gamepad;
|
||||
|
||||
OptionsMenuContext *ctx = m->context;
|
||||
ctx->data = strdup(config_get_str(CONFIG_GAMEPAD_DEVICE));
|
||||
ctx->data = mem_strdup(config_get_str(CONFIG_GAMEPAD_DEVICE));
|
||||
ctx->draw_overlay = draw_gamepad_options_overlay;
|
||||
ctx->gamepad_testmode.allowed = true;
|
||||
|
||||
|
|
|
@ -400,7 +400,7 @@ static int fill_replayview_menu(MenuData *m) {
|
|||
|
||||
auto ictx = ALLOC(ReplayviewItemContext, {
|
||||
.replay = rpy,
|
||||
.replayname = strdup(filename),
|
||||
.replayname = mem_strdup(filename),
|
||||
});
|
||||
|
||||
add_menu_entry(m, " ", replayview_run, ictx)->transition = /*rpy->numstages < 2 ? TransFadeBlack :*/ NULL;
|
||||
|
|
|
@ -195,7 +195,7 @@ char *pixmap_source_path(const char *prefix, const char *path) {
|
|||
strcpy(base_path + strlen(prefix), path);
|
||||
|
||||
if(pixmap_check_filename(base_path) && vfs_query(base_path).exists) {
|
||||
return strdup(base_path);
|
||||
return mem_strdup(base_path);
|
||||
}
|
||||
|
||||
char *dot = strrchr(base_path, '.');
|
||||
|
|
|
@ -218,7 +218,7 @@ static spvc_result write_glsl_attribs(spvc_compiler compiler, ShaderSource *out)
|
|||
|
||||
log_debug("[%i] %s\t\tid=%i\t\tbase_type_id=%i\t\ttype_id=%i\t\tlocation=%i", i, res->name, res->id, res->base_type_id, res->type_id, location);
|
||||
|
||||
attrs[i].name = strdup(res->name);
|
||||
attrs[i].name = mem_strdup(res->name);
|
||||
attrs[i].location = location;
|
||||
}
|
||||
|
||||
|
@ -284,7 +284,7 @@ bool _spirv_decompile(const ShaderSource *in, ShaderSource *out, const SPIRVDeco
|
|||
|
||||
assume(code != NULL);
|
||||
|
||||
out->content = strdup(code);
|
||||
out->content = mem_strdup(code);
|
||||
out->content_size = strlen(code) + 1;
|
||||
out->stage = in->stage;
|
||||
out->lang = *options->lang;
|
||||
|
|
|
@ -110,7 +110,7 @@ ShaderObject *gl33_shader_object_compile(ShaderSource *source) {
|
|||
|
||||
for(uint i = 0; i < nattribs; ++i) {
|
||||
GLSLAttribute *a = source->meta.glsl.attributes + i;
|
||||
shobj->attribs[i].name = strdup(a->name);
|
||||
shobj->attribs[i].name = mem_strdup(a->name);
|
||||
shobj->attribs[i].location = a->location;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -573,7 +573,7 @@ static void register_watched_path(InternalResource *ires, const char *vfspath, F
|
|||
free_slot = dynarray_append(&ires->watched_paths, {});
|
||||
}
|
||||
|
||||
free_slot->vfs_path = strdup(vfspath);
|
||||
free_slot->vfs_path = mem_strdup(vfspath);
|
||||
free_slot->watch = w;
|
||||
|
||||
done:
|
||||
|
@ -816,7 +816,7 @@ struct valfunc_arg {
|
|||
static void *valfunc_begin_load_resource(void *varg) {
|
||||
struct valfunc_arg *arg = varg;
|
||||
auto ires = ires_alloc(arg->type);
|
||||
ires->name = strdup(NOT_NULL(arg->name));
|
||||
ires->name = mem_strdup(NOT_NULL(arg->name));
|
||||
ires->refcount.value = 1;
|
||||
return ires;
|
||||
}
|
||||
|
@ -1702,7 +1702,7 @@ void res_util_strip_ext(char *path) {
|
|||
char *res_util_basename(const char *prefix, const char *path) {
|
||||
assert(strstartswith(path, prefix));
|
||||
|
||||
char *out = strdup(path + strlen(prefix));
|
||||
char *out = mem_strdup(path + strlen(prefix));
|
||||
res_util_strip_ext(out);
|
||||
|
||||
return out;
|
||||
|
|
|
@ -43,7 +43,7 @@ static void load_sprite_stage1(ResourceLoadState *st) {
|
|||
auto state = ALLOC(struct sprite_load_state, { .spr = spr });
|
||||
|
||||
if(texture_res_handler.procs.check(st->path)) {
|
||||
state->texture_name = strdup(st->name);
|
||||
state->texture_name = mem_strdup(st->name);
|
||||
res_load_dependency(st, RES_TEXTURE, state->texture_name);
|
||||
res_load_continue_after_dependencies(st, load_sprite_stage2, state);
|
||||
return;
|
||||
|
@ -88,7 +88,7 @@ static void load_sprite_stage1(ResourceLoadState *st) {
|
|||
}
|
||||
|
||||
if(!state->texture_name) {
|
||||
state->texture_name = strdup(st->name);
|
||||
state->texture_name = mem_strdup(st->name);
|
||||
log_info("%s: inferred texture name from sprite name", state->texture_name);
|
||||
}
|
||||
|
||||
|
|
|
@ -669,7 +669,7 @@ void texture_loader_stage1(ResourceLoadState *st) {
|
|||
return;
|
||||
}
|
||||
} else {
|
||||
ld->src_paths.main = strdup(st->path);
|
||||
ld->src_paths.main = mem_strdup(st->path);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -31,8 +31,8 @@ static void add_stage(
|
|||
.type = type,
|
||||
.spell = spell,
|
||||
.difficulty = diff,
|
||||
.title = title ? strdup(title) : NULL,
|
||||
.subtitle = subtitle ? strdup(subtitle) : NULL,
|
||||
.title = title ? mem_strdup(title) : NULL,
|
||||
.subtitle = subtitle ? mem_strdup(subtitle) : NULL,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -96,4 +96,8 @@ INLINE void *libc_realloc(void *ptr, size_t size) { return realloc(ptr, size); }
|
|||
attr_deprecated("Use the memory.h API instead")
|
||||
void *realloc(void *ptr, size_t size);
|
||||
|
||||
#undef strdup
|
||||
attr_deprecated("Use mem_strdup from memory.h instead")
|
||||
char *strdup(const char *s);
|
||||
|
||||
PRAGMA(GCC diagnostic pop)
|
||||
|
|
|
@ -87,7 +87,7 @@ bool parse_keyvalue_file_cb(const char *filename, KVCallback callback, void *dat
|
|||
|
||||
static bool kvcallback_hashtable(const char *key, const char *val, void *data) {
|
||||
ht_str2ptr_t *ht = data;
|
||||
ht_set(ht, key, strdup(val));
|
||||
ht_set(ht, key, mem_strdup(val));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ bool strstartswith_any(const char *s, const char **earray) {
|
|||
|
||||
void stralloc(char **dest, const char *src) {
|
||||
mem_free(*dest);
|
||||
*dest = src ? strdup(src) : NULL;
|
||||
*dest = src ? mem_strdup(src) : NULL;
|
||||
}
|
||||
|
||||
char* strjoin(const char *first, ...) {
|
||||
|
@ -124,7 +124,7 @@ char* strftimealloc(const char *fmt, const struct tm *timeinfo) {
|
|||
char str[sz_allocated];
|
||||
|
||||
if(strftime(str, sz_allocated, fmt, timeinfo)) {
|
||||
return strdup(str);
|
||||
return mem_strdup(str);
|
||||
}
|
||||
|
||||
sz_allocated *= 2;
|
||||
|
@ -133,7 +133,7 @@ char* strftimealloc(const char *fmt, const struct tm *timeinfo) {
|
|||
|
||||
char* strappend(char **dst, const char *src) {
|
||||
if(!*dst) {
|
||||
return *dst = strdup(src);
|
||||
return *dst = mem_strdup(src);
|
||||
}
|
||||
|
||||
*dst = mem_realloc(*dst, strlen(*dst) + strlen(src) + 1);
|
||||
|
|
|
@ -25,13 +25,6 @@
|
|||
#undef strlcpy
|
||||
#define strlcpy SDL_strlcpy
|
||||
|
||||
#undef strdup
|
||||
#define strdup _ts_strdup
|
||||
INLINE attr_returns_allocated attr_nonnull(1) char *strdup(const char *str) {
|
||||
size_t sz = strlen(str) + 1;
|
||||
return memcpy(mem_alloc(sz), str, sz);
|
||||
}
|
||||
|
||||
#ifndef TAISEI_BUILDCONF_HAVE_STRTOK_R
|
||||
#undef strtok_r
|
||||
#define strtok_r _ts_strtok_r
|
||||
|
|
|
@ -61,7 +61,7 @@ char *vfs_path_normalize(const char *path, char *out) {
|
|||
}
|
||||
|
||||
char *vfs_path_normalize_alloc(const char *path) {
|
||||
return vfs_path_normalize(path, strdup(path));
|
||||
return vfs_path_normalize(path, mem_strdup(path));
|
||||
}
|
||||
|
||||
char *vfs_path_normalize_inplace(char *path) {
|
||||
|
@ -145,5 +145,5 @@ char *vfs_syspath_normalize_inplace(char *path) {
|
|||
char *vfs_syspath_join_alloc(const char *parent, const char *child) {
|
||||
char buf[strlen(parent) + strlen(child) + 2];
|
||||
vfs_syspath_join(buf, sizeof(buf), parent, child);
|
||||
return strdup(buf);
|
||||
return mem_strdup(buf);
|
||||
}
|
||||
|
|
|
@ -281,7 +281,7 @@ char** vfs_dir_list_sorted(const char *path, size_t *out_size, int (*compare)(co
|
|||
continue;
|
||||
}
|
||||
|
||||
dynarray_append(&results, strdup(e));
|
||||
dynarray_append(&results, mem_strdup(e));
|
||||
}
|
||||
|
||||
vfs_dir_close(dir);
|
||||
|
|
|
@ -95,7 +95,7 @@ static char *vfs_syspath_repr(VFSNode *node) {
|
|||
}
|
||||
|
||||
static char *vfs_syspath_syspath(VFSNode *node) {
|
||||
char *p = strdup(VFS_NODE_CAST(VFSSysPathNode, node)->path);
|
||||
char *p = mem_strdup(VFS_NODE_CAST(VFSSysPathNode, node)->path);
|
||||
vfs_syspath_normalize_inplace(p);
|
||||
return p;
|
||||
}
|
||||
|
@ -186,5 +186,5 @@ static VFSNode *vfs_syspath_create_internal(char *path) {
|
|||
}
|
||||
|
||||
VFSNode *vfs_syspath_create(const char *path) {
|
||||
return vfs_syspath_create_internal(strdup(path));
|
||||
return vfs_syspath_create_internal(mem_strdup(path));
|
||||
}
|
||||
|
|
|
@ -187,7 +187,7 @@ static char* vfs_syspath_repr(VFSNode *node) {
|
|||
|
||||
static char* vfs_syspath_syspath(VFSNode *node) {
|
||||
auto pnode = VFS_NODE_CAST(VFSSysPathNode, node);
|
||||
char *p = strdup(pnode->path);
|
||||
char *p = mem_strdup(pnode->path);
|
||||
vfs_syspath_normalize_inplace(p);
|
||||
return p;
|
||||
}
|
||||
|
@ -322,5 +322,5 @@ static VFSNode *vfs_syspath_create_internal(char *path) {
|
|||
}
|
||||
|
||||
VFSNode *vfs_syspath_create(const char *path) {
|
||||
return vfs_syspath_create_internal(strdup(path));
|
||||
return vfs_syspath_create_internal(mem_strdup(path));
|
||||
}
|
||||
|
|
|
@ -114,7 +114,7 @@ static bool vfs_vdir_mkdir(VFSNode *node, const char *subdir) {
|
|||
}
|
||||
|
||||
static char *vfs_vdir_repr(VFSNode *node) {
|
||||
return strdup("virtual directory");
|
||||
return mem_strdup("virtual directory");
|
||||
}
|
||||
|
||||
VFS_NODE_FUNCS(VFSVDirNode, {
|
||||
|
|
|
@ -228,7 +228,7 @@ const char *vfs_zipfile_iter_shared(VFSZipFileIterData *idata, VFSZipFileTLS *tl
|
|||
// strip the trailing slash
|
||||
|
||||
mem_free(idata->allocated);
|
||||
idata->allocated = strdup(p);
|
||||
idata->allocated = mem_strdup(p);
|
||||
*strchr(idata->allocated, '/') = 0;
|
||||
r = idata->allocated;
|
||||
} else {
|
||||
|
|
Loading…
Reference in a new issue