commit 5043282

shrub  ·  2026-04-28 10:36:16 +0000 UTC
parent ce959b5
functions/foreach: fix temp var restore and interned name ownership issue
1 files changed,  +9, -8
+9, -8
 1@@ -1175,7 +1175,8 @@ fnforeach(struct EvalCtx *ctx, const char *args)
 2 {
 3 	char **raw;
 4 	char *name_raw, *name, *list, *out;
 5-	char *saved_name, *saved_val;
 6+	char *saved_val;
 7+	const char *iname;
 8 	struct Var *saved;
 9 	size_t argc, i, j, len, cap;
10 	int saved_simple;
11@@ -1193,17 +1194,16 @@ fnforeach(struct EvalCtx *ctx, const char *args)
12 	name = trimspacesdup(name_raw);
13 	free(name_raw);
14 	list = expandstr(ctx, raw[1]);
15+	iname = intern(name);
16 
17 	saved = findvar(ctx->env, name);
18 	had_saved = saved != 0;
19 	if (had_saved) {
20-		saved_name = xstrdup(saved->name);
21 		saved_val = xstrdup(saved->val);
22 		saved_simple = saved->simple;
23 		saved_origin = saved->origin;
24 		saved_exported = saved->exported;
25 	} else {
26-		saved_name = 0;
27 		saved_val = 0;
28 		saved_simple = 0;
29 		saved_origin = ORIGIN_FILE;
30@@ -1248,14 +1248,16 @@ fnforeach(struct EvalCtx *ctx, const char *args)
31 	}
32 
33 	if (had_saved) {
34-		envsetvar(ctx->env, saved_name, saved_val, saved_simple, saved_origin, saved_exported);
35-		free(saved_name);
36+		free(saved->val);
37+		saved->val = saved_val;
38+		saved->simple = saved_simple;
39+		saved->origin = saved_origin;
40+		saved->exported = saved_exported;
41 	} else {
42 		size_t k;
43 
44 		for (k = 0; k < ctx->env->n; k++) {
45-			if (strcmp(ctx->env->v[k].name, name) == 0) {
46-				free(ctx->env->v[k].name);
47+			if (ctx->env->v[k].name == iname) {
48 				free(ctx->env->v[k].val);
49 				memmove(&ctx->env->v[k], &ctx->env->v[k + 1],
50 				        (ctx->env->n - k - 1) * sizeof(ctx->env->v[0]));
51@@ -1265,7 +1267,6 @@ fnforeach(struct EvalCtx *ctx, const char *args)
52 		}
53 	}
54 
55-	free(saved_val);
56 	free(list);
57 	free(name);
58 	freeargsraw(raw, argc);