summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas E. Dickey <dickey@invisible-island.net>2020-06-16 18:36:50 -0400
committerThomas E. Dickey <dickey@invisible-island.net>2020-06-16 18:36:50 -0400
commit08f44086320c6bc5f2c7eb6457a0d53192832805 (patch)
treefc4b6486f65c63b577e9b1f3f1506ff6e632dcff
parentac802fe10221ef3c6426ac1ebf4a250f189d1228 (diff)
eliminate a fixed-size buffer in Execute() function.
Signed-off-by: Thomas E. Dickey <dickey@invisible-island.net>
-rw-r--r--src/menus.c71
1 files changed, 49 insertions, 22 deletions
diff --git a/src/menus.c b/src/menus.c
index 7ce0e49..8b1cb00 100644
--- a/src/menus.c
+++ b/src/menus.c
@@ -919,7 +919,7 @@ PopUpMenu(MenuRoot *menu, int x, int y, Bool center)
TwmWindow **WindowNames;
TwmWindow *tmp_win2, *tmp_win3;
int i;
- int (*compar) (const char *, const char *) =
+ int (*compar)(const char *, const char *) =
(Scr->CaseSensitive ? strcmp : XmuCompareISOLatin1);
if (!menu)
@@ -2281,21 +2281,33 @@ NeedToDefer(MenuRoot *root)
return FALSE;
}
+/*
+ * We cannot safely free a value passed to putenv, but we can cache the most
+ * recent value, reducing the memory leaks.
+ */
+#define cache_env(saved) \
+ if (saved == NULL || strcmp(saved, update)) { \
+ saved = update; \
+ } else { \
+ free(update); \
+ update = saved; \
+ }
+
static void
Execute(const char *s)
{
- /* FIXME: is all this stuff needed? There could be security problems here. */
- static char buf[256];
+ static const char display_eqls[] = "DISPLAY=";
+ static char *main_display;
+ static char *exec_display;
+
char *ds = DisplayString(dpy);
char *colon, *dot1;
- char oldDisplay[256];
- char *doisplay;
- int restorevar = 0;
+ char *oldDisplay = NULL;
+ char *value;
+ Bool restorevar = False;
- oldDisplay[0] = '\0';
- doisplay = getenv("DISPLAY");
- if (doisplay)
- strcpy(oldDisplay, doisplay);
+ value = getenv("DISPLAY");
+ oldDisplay = strdup(value ? value : "");
/*
* Build a display string using the current screen number, so that
@@ -2305,23 +2317,38 @@ Execute(const char *s)
*/
colon = strrchr(ds, ':');
if (colon) { /* if host[:]:dpy */
- strcpy(buf, "DISPLAY=");
- strcat(buf, ds);
- colon = buf + 8 + (colon - ds); /* use version in buf */
- dot1 = strchr(colon, '.'); /* first period after colon */
- if (!dot1)
- dot1 = colon + strlen(colon); /* if not there, append */
- (void) sprintf(dot1, ".%d", Scr->screen);
- putenv(buf);
- restorevar = 1;
+ size_t need = sizeof(display_eqls) + strlen(ds) + 10;
+ char *update = malloc(need);
+
+ if (update != NULL) {
+ strcpy(update, display_eqls);
+ strcat(update, ds);
+ colon = strrchr(update, ':');
+ dot1 = strchr(colon, '.'); /* first period after colon */
+ if (dot1 == NULL)
+ dot1 = colon + strlen(colon); /* if not there, append */
+ (void) sprintf(dot1, ".%d", Scr->screen);
+ cache_env(exec_display);
+ if (strcmp(update, oldDisplay)) {
+ putenv(update);
+ restorevar = True;
+ }
+ }
}
(void) system(s);
- if (restorevar) { /* why bother? */
- (void) snprintf(buf, sizeof(buf), "DISPLAY=%s", oldDisplay);
- putenv(buf);
+ if (restorevar) {
+ size_t need = sizeof(display_eqls) + strlen(oldDisplay);
+ char *update = malloc(need);
+
+ if (update != NULL) {
+ (void) snprintf(update, need, "%s%s", display_eqls, oldDisplay);
+ cache_env(main_display);
+ putenv(update);
+ }
}
+ free(oldDisplay);
}
/**