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;
}