William A. Rowe Jr. wrote on 2011-02-08: > On 2/8/2011 8:29 AM, Steve Hay wrote: >> + int len = (int)strlen(newarr[arg]) + 1; + *env = >> (char*)_malloc_dbg(len * sizeof(char), _CRT_BLOCK, __FILE__, __LINE__); >> + strcpy_s(*env, len, newarr[arg]); > > That's just sick ... It's inexcusable to use strcpy when len is already > known :) > > Very interesting observations, are you in a position to try this with > the older > C compilers? Interested to know if we can just apply this to all > flavors without > any headaches.
I'm not sure if strcpy_s() is as sick as strcpy() would be, given that it takes a len argument anyway (?), but I've been looking at saving a little work in the function concerned anyway, by copying the new environment strings into place directly from the return value of the UTF-8 conversion function, rather than going through the intermediate newarr[] array as my quick hack currently does. The function at the foot of this email is more along the lines of what I'm thinking, and is still working correctly. Would this approach be an improvement when suitably tidied up? I wonder if the problem is that malloced data generally has heads and tails on it to catch buffer overruns when freeing and the free which the putenv() call does when *replacing* an existing environment variable is maybe unhappy at the absence of the expected heads and tails on that, given that the APR-ized environment is currently allocated in a single block (with only one head & tail), rather than string-by-string like stdenvp.c did it orignially (giving each string its own head & tail)? It doesn't explain why it still runs on XP/2003, or in debug mode, or with old compilers, though... I have VC98 and VS2005/VS2008/VS2010 all handy and will try release and debug mode builds of my test program with each compiler, and run each binary on XP and 2008. I don't have VS2003 available. I will also do full Apache/Perl/mod_perl tests as well, but since that'll obviously take rather longer maybe just a release mode build for each compiler would suffice? static int warrsztoastr(char*** retarr, wchar_t* arrsz, int args) { const wchar_t* wch; size_t totlen; size_t newlen; size_t wsize; char** env; char* pstrs; char* strs; int arg; if (args < 0) { for (args = 1, wch = arrsz; wch[0] || wch[1]; ++wch) if (!*wch) ++args; } wsize = 1 + wch - arrsz; newlen = totlen = wsize * 3 + 1; pstrs = strs = (char*)_malloc_dbg(newlen * sizeof(char), _CRT_BLOCK, __FILE__, __LINE__); (void)ucs2toutf8(arrsz, &wsize, strs, &newlen); assert(newlen && !wsize); *retarr = env = (char **)_malloc_dbg((args + 1) * sizeof(char*), _CRT_BLOCK, __FILE__, __LINE__); for (arg = 0; arg < args; ++arg) { char* p = pstrs; int len = 0; while (*p++) ++len; len += 1; *env = (char*)_malloc_dbg(len * sizeof(char), _CRT_BLOCK, __FILE__, __LINE__); memcpy(*env, pstrs, len * sizeof(char)); pstrs += len; ++env; } *env = NULL; _free_dbg(strs, _CRT_BLOCK); return args; }