#include <stdlib.h> static void f_system_putenv(INT32 args) { int rv; char *envvar; get_all_args("putenv", args, "%s", &envvar); pop_n_elems(args);
This pop is too early - envvar might point to freed memory after it since it only points to the data block of the string without adding a reference to it.
I saw exactly this error in many places in the Caudium C module. Did you start from that code, or is there some other bad examples out there that people are copying?
rv=putenv(envvar);
Note that pike strings can contain NUL chars, so if you pass them directly to a libc function like this it might read a truncated string. Maybe you should check that the passed string doesn't contain NUL?
push_int(rv); }
Most functions of this type return 0 on failure and nonzero on success, so maybe you should invert the return value.
Or even better would be to declare putenv as returning void and throw an error instead, since the only possible error is ENOMEM, and pike generally throws errors when running out of memory.
Also, wouldn't it be nicer to let the function take the name and the value in separate strings, so that the user doesn't have to glue together one with "="? Then you could also check that the name doesn't contain "=" already.
static void f_system_getenv(INT32 args) { char *rv; char *envvar; get_all_args("getenv", args, "%s", &envvar); pop_n_elems(args);
Same thing here, of course.
/ Martin Stjernholm, Roxen IS
Previous text:
2003-10-16 21:06: Subject: putenv/getenv
I've cobbled together a System.putenv() and System.getenv(), but I'm having some odd problems. The code itself works most of the time, but randomly getenv() fails to get an envvar I've putenv()ed (ie getenv(2) returns NULL). The functions are below, along with a short test script that demonstrates the problem. Any suggestions are welcome, as my C skills are quite rusty.
Bill
in modules/system/system.c:
#include <stdlib.h> static void f_system_putenv(INT32 args) { int rv; char *envvar; get_all_args("putenv", args, "%s", &envvar); pop_n_elems(args); rv=putenv(envvar); push_int(rv); }
static void f_system_getenv(INT32 args) { char *rv; char *envvar; get_all_args("getenv", args, "%s", &envvar); pop_n_elems(args); rv=getenv(envvar); if(rv==NULL) push_int(0); else push_text(rv); }
and later:
ADD_FUNCTION("putenv", f_system_putenv, tFunc(tStr, tInt), 0); ADD_FUNCTION("getenv", f_system_getenv, tFunc(tStr, tOr(tStr, tInt)), 0);
test script:
int fail=0; int main() { string var="DISPLAY"; string val="BASE"; int a='A'; for(int i=0; i<2050; i++) { val+=String.int2char(a); werror("iteration " + i + "\n"); doit(var,val); } werror("failures: " + fail + "\n"); return 1; } void doit(string var, string val) { if(System.putenv(var+"="+ val)) werror("failed putenv\n"); string r=System.getenv(var); if(r!=val) { fail++; }
The test fails consistently and in the same locations for a given environment variable. The manpage doesn't say what might cause failures like this.
Any thoughts?
Bill
/ Brevbäraren