Clean up the XDR properly even if JS_XDRScript fails. In particular, don't

double-free things.  Bug 387572, r+sr=brendan
This commit is contained in:
bzbarsky@mit.edu 2007-07-10 20:10:43 -07:00
parent 552e3572df
commit a91172fdd2

View File

@ -369,37 +369,37 @@ ReadScriptFromStream(JSContext *cx, nsIObjectInputStream *stream,
xdr->userdata = stream;
JS_XDRMemSetData(xdr, data, size);
if (JS_XDRScript(xdr, script)) {
// Update data in case ::JS_XDRScript called back into C++ code to
// read an XPCOM object.
//
// In that case, the serialization process must have flushed a run
// of counted bytes containing JS data at the point where the XPCOM
// object starts, after which an encoding C++ callback from the JS
// XDR code must have written the XPCOM object directly into the
// nsIObjectOutputStream.
//
// The deserialization process will XDR-decode counted bytes up to
// but not including the XPCOM object, then call back into C++ to
// read the object, then read more counted bytes and hand them off
// to the JSXDRState, so more JS data can be decoded.
//
// This interleaving of JS XDR data and XPCOM object data may occur
// several times beneath the call to ::JS_XDRScript, above. At the
// end of the day, we need to free (via nsMemory) the data owned by
// the JSXDRState. So we steal it back, nulling xdr's buffer so it
// doesn't get passed to ::JS_free by ::JS_XDRDestroy.
uint32 length;
data = static_cast<char*>(JS_XDRMemGetData(xdr, &length));
if (data) {
JS_XDRMemSetData(xdr, nsnull, 0);
}
JS_XDRDestroy(xdr);
} else {
if (!JS_XDRScript(xdr, script)) {
rv = NS_ERROR_FAILURE;
}
// Update data in case ::JS_XDRScript called back into C++ code to
// read an XPCOM object.
//
// In that case, the serialization process must have flushed a run
// of counted bytes containing JS data at the point where the XPCOM
// object starts, after which an encoding C++ callback from the JS
// XDR code must have written the XPCOM object directly into the
// nsIObjectOutputStream.
//
// The deserialization process will XDR-decode counted bytes up to
// but not including the XPCOM object, then call back into C++ to
// read the object, then read more counted bytes and hand them off
// to the JSXDRState, so more JS data can be decoded.
//
// This interleaving of JS XDR data and XPCOM object data may occur
// several times beneath the call to ::JS_XDRScript, above. At the
// end of the day, we need to free (via nsMemory) the data owned by
// the JSXDRState. So we steal it back, nulling xdr's buffer so it
// doesn't get passed to ::JS_free by ::JS_XDRDestroy.
uint32 length;
data = static_cast<char*>(JS_XDRMemGetData(xdr, &length));
if (data) {
JS_XDRMemSetData(xdr, nsnull, 0);
}
JS_XDRDestroy(xdr);
// If data is null now, it must have been freed while deserializing an
// XPCOM object (e.g., a principal) beneath ::JS_XDRScript.
if (data) {