From 3eeebb74cd83757756acb2024560e602ee8f9118 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Thu, 11 Mar 2021 09:03:36 -0800 Subject: [PATCH] Com: avoid intentional memory leak in epicsEnvSet Switch default impl. to setenv/unsetenv Switch WIN32 to use _putenv_s On vxWorks putenv() is documented to make a copy. log error, but never halt, if env (un)set not possible. RTEMS <4.10 compat where unsetenv() returns void. --- modules/libcom/src/osi/os/Darwin/osdEnv.c | 72 ---------------------- modules/libcom/src/osi/os/RTEMS/osdEnv.c | 62 ------------------- modules/libcom/src/osi/os/WIN32/osdEnv.c | 31 +++------- modules/libcom/src/osi/os/default/osdEnv.c | 39 +++++------- modules/libcom/src/osi/os/iOS/osdEnv.c | 69 --------------------- modules/libcom/src/osi/os/solaris/osdEnv.c | 62 ------------------- modules/libcom/src/osi/os/vxWorks/osdEnv.c | 36 ++++++----- 7 files changed, 48 insertions(+), 323 deletions(-) delete mode 100644 modules/libcom/src/osi/os/Darwin/osdEnv.c delete mode 100644 modules/libcom/src/osi/os/RTEMS/osdEnv.c delete mode 100644 modules/libcom/src/osi/os/iOS/osdEnv.c delete mode 100644 modules/libcom/src/osi/os/solaris/osdEnv.c diff --git a/modules/libcom/src/osi/os/Darwin/osdEnv.c b/modules/libcom/src/osi/os/Darwin/osdEnv.c deleted file mode 100644 index 8d4b100e3..000000000 --- a/modules/libcom/src/osi/os/Darwin/osdEnv.c +++ /dev/null @@ -1,72 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Saskatchewan -* SPDX-License-Identifier: EPICS -* EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* osdEnv.c */ -/* - * Author: Eric Norum - * Date: May 7, 2001 - * - * Routines to modify/display environment variables and EPICS parameters - * - */ - -#include -#include -#include -#include -#include - -/* - * Starting in Mac OS X 10.5 (Leopard) shared libraries and - * bundles don't have direct access to environ (man environ). - */ -#include -#define environ (*_NSGetEnviron()) - -#include "epicsStdio.h" -#include "envDefs.h" -#include "iocsh.h" - -/* - * Set the value of an environment variable - */ -LIBCOM_API void epicsStdCall epicsEnvSet (const char *name, const char *value) -{ - if (!name) return; - iocshEnvClear(name); - setenv(name, value, 1); -} - -/* - * Unset an environment variable - */ - -LIBCOM_API void epicsStdCall epicsEnvUnset (const char *name) -{ - iocshEnvClear(name); - unsetenv(name); -} - -/* - * Show the value of the specified, or all, environment variables - */ -LIBCOM_API void epicsStdCall epicsEnvShow (const char *name) -{ - if (name == NULL) { - extern char **environ; - char **sp; - - for (sp = environ ; (sp != NULL) && (*sp != NULL) ; sp++) - printf ("%s\n", *sp); - } - else { - const char *cp = getenv (name); - if (cp == NULL) - printf ("%s is not an environment variable.\n", name); - else - printf ("%s=%s\n", name, cp); - } -} diff --git a/modules/libcom/src/osi/os/RTEMS/osdEnv.c b/modules/libcom/src/osi/os/RTEMS/osdEnv.c deleted file mode 100644 index 125aee97e..000000000 --- a/modules/libcom/src/osi/os/RTEMS/osdEnv.c +++ /dev/null @@ -1,62 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Saskatchewan -* SPDX-License-Identifier: EPICS -* EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* osdEnv.c */ -/* - * Author: Eric Norum - * Date: May 7, 2001 - * - * Routines to modify/display environment variables and EPICS parameters - * - */ - -#include -#include - -#include "epicsStdio.h" -#include "envDefs.h" -#include "osiUnistd.h" -#include "iocsh.h" - -/* - * Set the value of an environment variable - */ -LIBCOM_API void epicsStdCall epicsEnvSet (const char *name, const char *value) -{ - iocshEnvClear(name); - setenv(name, value, 1); -} - -/* - * Unset an environment variable - */ - -LIBCOM_API void epicsStdCall epicsEnvUnset (const char *name) -{ - iocshEnvClear(name); - unsetenv(name); -} - -/* - * Show the value of the specified, or all, environment variables - */ -LIBCOM_API void epicsStdCall epicsEnvShow (const char *name) -{ - if (name == NULL) { - extern char **environ; - char **sp; - - for (sp = environ ; (sp != NULL) && (*sp != NULL) ; sp++) - printf ("%s\n", *sp); - } - else { - const char *cp = getenv (name); - if (cp == NULL) - printf ("%s is not an environment variable.\n", name); - else - printf ("%s=%s\n", name, cp); - } -} diff --git a/modules/libcom/src/osi/os/WIN32/osdEnv.c b/modules/libcom/src/osi/os/WIN32/osdEnv.c index be884ac61..adc40b58c 100644 --- a/modules/libcom/src/osi/os/WIN32/osdEnv.c +++ b/modules/libcom/src/osi/os/WIN32/osdEnv.c @@ -21,12 +21,19 @@ #include "epicsStdio.h" #include "errlog.h" -#include "cantProceed.h" #include "envDefs.h" #include "osiUnistd.h" #include "epicsFindSymbol.h" #include "iocsh.h" +static +void setEnv(const char *name, const char *value) +{ + errno_t err = _putenv_s(name, value); + if(err) + errlogPrintf("Can't set environment %s=\"%s\" : %d\n", name, value, (int)err); +} + /* * Set the value of an environment variable * Leaks memory, but the assumption is that this routine won't be @@ -34,25 +41,8 @@ */ LIBCOM_API void epicsStdCall epicsEnvSet (const char *name, const char *value) { - char *cp; - iocshEnvClear(name); - - cp = mallocMustSucceed (strlen (name) + strlen (value) + 2, "epicsEnvSet"); - strcpy (cp, name); - strcat (cp, "="); - strcat (cp, value); - if (putenv (cp) < 0) { - errPrintf( - -1L, - __FILE__, - __LINE__, - "Failed to set environment parameter \"%s\" to \"%s\": %s\n", - name, - value, - strerror (errno)); - free (cp); - } + setEnv(name, value); } /* @@ -63,8 +53,7 @@ LIBCOM_API void epicsStdCall epicsEnvSet (const char *name, const char *value) LIBCOM_API void epicsStdCall epicsEnvUnset (const char *name) { iocshEnvClear(name); - if (getenv(name) != NULL) - epicsEnvSet((char*)name, ""); + setEnv(name, ""); } /* diff --git a/modules/libcom/src/osi/os/default/osdEnv.c b/modules/libcom/src/osi/os/default/osdEnv.c index f95a3f032..7ece253c7 100644 --- a/modules/libcom/src/osi/os/default/osdEnv.c +++ b/modules/libcom/src/osi/os/default/osdEnv.c @@ -20,13 +20,25 @@ #include #include "epicsStdio.h" +#include "epicsVersion.h" #include "errlog.h" -#include "cantProceed.h" #include "envDefs.h" #include "osiUnistd.h" #include "epicsFindSymbol.h" #include "iocsh.h" +#ifdef __rtems__ +# include +# define RTEMS_VERSION_INT VERSION_INT(__RTEMS_MAJOR__, __RTEMS_MINOR__, 0, 0) +#endif + +#if defined(__RTEMS_MAJOR__) && RTEMS_VERSION_INT %d\n", name, value, errno); } /* @@ -64,8 +59,8 @@ LIBCOM_API void epicsStdCall epicsEnvSet (const char *name, const char *value) LIBCOM_API void epicsStdCall epicsEnvUnset (const char *name) { iocshEnvClear(name); - if (getenv(name) != NULL) - putenv((char*)name); + if(unSetEnv(name)) + errlogPrintf("unsetenv(\"%s\") -> %d\n", name, errno); } /* diff --git a/modules/libcom/src/osi/os/iOS/osdEnv.c b/modules/libcom/src/osi/os/iOS/osdEnv.c deleted file mode 100644 index 665141951..000000000 --- a/modules/libcom/src/osi/os/iOS/osdEnv.c +++ /dev/null @@ -1,69 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Saskatchewan -* SPDX-License-Identifier: EPICS -* EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ - -/* osdEnv.c */ -/* - * Author: Eric Norum - * Date: May 7, 2001 - * - * Routines to modify/display environment variables and EPICS parameters - */ - -#include -#include -#include -#include -#include - -#include "epicsStdio.h" -#include -#include -#include -#include -#include "epicsFindSymbol.h" -#include - -/* - * Set the value of an environment variable - */ -LIBCOM_API void epicsStdCall epicsEnvSet (const char *name, const char *value) -{ - if (!name) return; - iocshEnvClear(name); - setenv(name, value, 1); -} - -/* - * Unset an environment variable - */ - -LIBCOM_API void epicsStdCall epicsEnvUnset (const char *name) -{ - iocshEnvClear(name); - unsetenv(name); -} - -/* - * Show the value of the specified, or all, environment variables - */ -LIBCOM_API void epicsStdCall epicsEnvShow (const char *name) -{ - if (name == NULL) { - extern char **environ; - char **sp; - - for (sp = environ ; (sp != NULL) && (*sp != NULL) ; sp++) - printf ("%s\n", *sp); - } - else { - const char *cp = getenv (name); - if (cp == NULL) - printf ("%s is not an environment variable.\n", name); - else - printf ("%s=%s\n", name, cp); - } -} diff --git a/modules/libcom/src/osi/os/solaris/osdEnv.c b/modules/libcom/src/osi/os/solaris/osdEnv.c deleted file mode 100644 index 125aee97e..000000000 --- a/modules/libcom/src/osi/os/solaris/osdEnv.c +++ /dev/null @@ -1,62 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Saskatchewan -* SPDX-License-Identifier: EPICS -* EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* osdEnv.c */ -/* - * Author: Eric Norum - * Date: May 7, 2001 - * - * Routines to modify/display environment variables and EPICS parameters - * - */ - -#include -#include - -#include "epicsStdio.h" -#include "envDefs.h" -#include "osiUnistd.h" -#include "iocsh.h" - -/* - * Set the value of an environment variable - */ -LIBCOM_API void epicsStdCall epicsEnvSet (const char *name, const char *value) -{ - iocshEnvClear(name); - setenv(name, value, 1); -} - -/* - * Unset an environment variable - */ - -LIBCOM_API void epicsStdCall epicsEnvUnset (const char *name) -{ - iocshEnvClear(name); - unsetenv(name); -} - -/* - * Show the value of the specified, or all, environment variables - */ -LIBCOM_API void epicsStdCall epicsEnvShow (const char *name) -{ - if (name == NULL) { - extern char **environ; - char **sp; - - for (sp = environ ; (sp != NULL) && (*sp != NULL) ; sp++) - printf ("%s\n", *sp); - } - else { - const char *cp = getenv (name); - if (cp == NULL) - printf ("%s is not an environment variable.\n", name); - else - printf ("%s=%s\n", name, cp); - } -} diff --git a/modules/libcom/src/osi/os/vxWorks/osdEnv.c b/modules/libcom/src/osi/os/vxWorks/osdEnv.c index 051d80187..d91208f4c 100644 --- a/modules/libcom/src/osi/os/vxWorks/osdEnv.c +++ b/modules/libcom/src/osi/os/vxWorks/osdEnv.c @@ -22,7 +22,6 @@ #include #include -#include "cantProceed.h" #include "epicsFindSymbol.h" #include "epicsStdio.h" #include "errlog.h" @@ -35,25 +34,32 @@ */ LIBCOM_API void epicsStdCall epicsEnvSet (const char *name, const char *value) { - char *cp; + size_t alen = (!name || !value) ? 2u : strlen(name) + strlen(value) + 2u; /* '=' '\0' */ + const int onstack = alen <= 512u; /* use on-stack dynamic array for small strings */ + char stackarr[ onstack ? alen : 1u]; /* gcc specific dynamic array */ + char *allocd = onstack ? NULL : malloc(alen); + char *cp = onstack ? stackarr : allocd; - if (!name) { + if (!name || !value) { printf ("Usage: epicsEnvSet \"name\", \"value\"\n"); - return; - } - iocshEnvClear(name); + } else if(!cp) { + errlogPrintf("epicsEnvSet(\"%s\", \"%s\" insufficient memory\n", name, value); - cp = mallocMustSucceed (strlen (name) + strlen (value) + 2, "epicsEnvSet"); - strcpy (cp, name); - strcat (cp, "="); - strcat (cp, value); - if (putenv (cp) < 0) { - errPrintf(-1L, __FILE__, __LINE__, - "Failed to set environment parameter \"%s\" to \"%s\": %s\n", - name, value, strerror (errno)); - free (cp); + } else { + int err; + + strcpy (cp, name); + strcat (cp, "="); + strcat (cp, value); + + iocshEnvClear(name); + + if((err=putenv(cp)) < 0) + errlogPrintf("epicsEnvSet(\"%s\", \"%s\" -> %d\n", name, value, err); } + /* from at least vxWorks 5.5 putenv() is making a copy, so we can free */ + free (allocd); } /*