diff -p -u -8 -r3.98 jsstr.c --- mozilla/js/src/jsstr.c 24 Feb 2005 18:59:41 -0000 3.98 +++ mozilla/js/src/jsstr.c 2 Apr 2005 02:36:30 -0000 @@ -1381,21 +1381,27 @@ find_replen(JSContext *cx, ReplaceData * if (lambda) { uintN argc, i, j, m, n, p; jsval *sp, *oldsp, rval; void *mark; JSStackFrame *fp; JSBool ok; /* - * Save the rightContext from the current regexp, since it - * gets stuck at the end of the replacement string and may - * be clobbered by a RegExp usage in the lambda function. + * Save the regExpStatics from the current regexp, since they may be + * clobbered by a RegExp usage in the lambda function. Note that all + * members of JSRegExpStatics are JSSubStrings, so not GC roots, save + * input, which is rooted otherwise via argv[-1] in str_replace. + * + * We need to clear moreParens in the top-of-stack cx->regExpStatics + * to it won't be possibly realloc'ed, leaving the bottom-of-stack + * moreParens pointing to freed memory. */ - JSSubString saveRightContext = cx->regExpStatics.rightContext; + JSRegExpStatics save = cx->regExpStatics; + cx->regExpStatics.moreParens = NULL; /* * In the lambda case, not only do we find the replacement string's * length, we compute repstr and return it via rdata for use within * do_replace. The lambda is called with arguments ($&, $1, $2, ..., * index, input), i.e., all the properties of a regexp match array. * For $&, etc., we must create string jsvals from cx->regExpStatics. * We grab up stack space to keep the newborn strings GC-rooted. @@ -1463,17 +1469,19 @@ find_replen(JSContext *cx, ReplaceData * } else { rdata->repstr = repstr; *sizep = JSSTRING_LENGTH(repstr); } } lambda_out: js_FreeStack(cx, mark); - cx->regExpStatics.rightContext = saveRightContext; + if (cx->regExpStatics.moreParens) + JS_free(cx, cx->regExpStatics.moreParens); + cx->regExpStatics = save; return ok; } #endif /* JS_HAS_REPLACE_LAMBDA */ repstr = rdata->repstr; replen = JSSTRING_LENGTH(repstr); for (dp = rdata->dollar, ep = rdata->dollarEnd; dp; dp = js_strchr_limit(dp, '$', ep)) {