- From: Wendell Hicken <whicken@parasoft.com>
- Date: Fri, 21 May 1999 17:01:28 -0700
- To: www-lib@w3.org
Greetings. I think I found a bug in libwww which I do not know how to
solve cleanly (code attached). I apologize for the references to statefarm's
website, but that's where I can reproduce this bug. What
happens is that the first URL loads fine, then on the 2nd URL in
_dispatchParsers, libwww ends up calling the following code from
HTMIME_connection:
if (HTHost_version(host) < HTTP_11) {
HTNet_setPersistent(net, YES, HT_TP_SINGLE);
HTTRACE(STREAM_TRACE, "MIMEParser.. HTTP/1.0 Keep
Alive\n");
} else
The call the HTNet_setPersistent ends up calling HTHost_clearChannel which
deletes the HTStream object being used in _dispatchParsers. Hence, when
libwww comes back from the call the HTMIME_connection, it's using pointers
to free'd data. From there it all goes wrong until the application crashes.
The bug only reproduces if the first URL has been loaded first. This seems
to be because HTHost_setMode has a check:
if (mode == HT_TP_SINGLE && host->mode > mode) {
If the 2nd URL is loaded first, or the cached HTHost object table is cleared,
then the code does not enter this if, triggering the deletion.
Here's the stack trace of the malignant free, in case it's of use to anyone:
HTMemory_free() c:\libwww\w3c-libwww-5.2.8\library\src\htmemory.c, 132
HTChunk_delete() c:\libwww\w3c-libwww-5.2.8\library\src\htchunk.c, 62
HTMIME_free() c:\libwww\w3c-libwww-5.2.8\library\src\htmime.c, 484
HTTPStatus_free() c:\libwww\w3c-libwww-5.2.8\library\src\http.c, 874
HTReader_free() c:\libwww\w3c-libwww-5.2.8\library\src\htreader.c, 46
HTChannel_delete() c:\libwww\w3c-libwww-5.2.8\library\src\htchannl.c, 237
HTHost_free() c:\libwww\w3c-libwww-5.2.8\library\src\hthost.c, 1102
HTHost_deleteNet() c:\libwww\w3c-libwww-5.2.8\library\src\hthost.c, 1133
HTNet_delete() c:\libwww\w3c-libwww-5.2.8\library\src\htnet.c, 910
HTTPCleanup() c:\libwww\w3c-libwww-5.2.8\library\src\http.c, 168
HTTPEvent() c:\libwww\w3c-libwww-5.2.8\library\src\http.c, 1249
HTNet_execute() c:\libwww\w3c-libwww-5.2.8\library\src\htnet.c, 582
HTHost_launchPending() c:\libwww\w3c-libwww-5.2.8\library\src\hthost.c, 1227
HTHost_clearChannel() c:\libwww\w3c-libwww-5.2.8\library\src\hthost.c, 797
HTHost_setMode() c:\libwww\w3c-libwww-5.2.8\library\src\hthost.c, 900
HTHost_setPersistent() c:\libwww\w3c-libwww-5.2.8\library\src\hthost.c, 705
HTNet_setPersistent() c:\libwww\w3c-libwww-5.2.8\library\src\htnet.c, 1071
HTMIME_connection() c:\libwww\w3c-libwww-5.2.8\library\src\htmimimp.c, 142
HTMIMEParseSet_dispatch()
c:\libwww\w3c-libwww-5.2.8\library\src\htmimprs.c, 179
_dispatchParsers() c:\libwww\w3c-libwww-5.2.8\library\src\htmime.c, 270
HTMIME_put_block() c:\libwww\w3c-libwww-5.2.8\library\src\htmime.c, 341
HTTPStatus_put_block() c:\libwww\w3c-libwww-5.2.8\library\src\http.c, 851
HTReader_read() c:\libwww\w3c-libwww-5.2.8\library\src\htreader.c, 201
HTHost_read() c:\libwww\w3c-libwww-5.2.8\library\src\hthost.c, 1598
HTTPEvent() c:\libwww\w3c-libwww-5.2.8\library\src\http.c, 1228
HTLoadHTTP() c:\libwww\w3c-libwww-5.2.8\library\src\http.c, 962
HTNet_newClient() c:\libwww\w3c-libwww-5.2.8\library\src\htnet.c, 807
HTLoad() c:\libwww\w3c-libwww-5.2.8\library\src\htreqman.c, 1643
launch_request() c:\libwww\w3c-libwww-5.2.8\library\src\htaccess.c, 77
HTLoadAbsolute() c:\libwww\w3c-libwww-5.2.8\library\src\htaccess.c, 90
HTLoadToStream() c:\libwww\w3c-libwww-5.2.8\library\src\htaccess.c, 130
load() c:\libwww\w3c-libwww-5.2.8\library\examples\chunk.cpp, 184
main() c:\libwww\w3c-libwww-5.2.8\library\examples\chunk.cpp, 212
Another interesting note is that the HTNet_setPersistent call from inside
HTMIME_connection gets invoked recursively - the delete seems to happen
after the inner HTNet_setPersistent has completed successfully. I don't know
if this is correct behaviour or not, but is seems odd.
Wendell
-----------
#include "WWWLib.h"
#include "WWWApp.h"
#include "WWWInit.h"
char *data[] = {
"http://www.statefarm.com/sponsors/natgeo.htm",
"http://www.statefarm.com/sponsors/images/natgeo.gif"
};
int printer(const char * fmt, va_list pArgs) {
return vfprintf(stderr, fmt, pArgs);
}
int tracer(const char * fmt, va_list pArgs) {
return vfprintf(stderr, fmt, pArgs);
}
int main() {
HTProfile_newNoCacheClient("Test", "1.0");
HTPrint_setCallback(printer);
HTTrace_setCallback(tracer);
HTSetTraceMessageMask("sop");
for (int i = 0; i < sizeof(data)/sizeof(data[0]); ++i) {
HTRequest *req = HTRequest_new();
HTRequest_setPreemptive(req, YES);
HTRequest_setMethod(req, METHOD_GET);
HTRequest_setOutputFormat(req, WWW_SOURCE);
HTRequest_addConnection(req, "close", "");
HTLoadToChunk(data[i], req);
HTRequest_delete(req);
// Adding "HTHost_deleteAll();" here causes the bug not to
// occur, but that's not a good solution.
}
HTProfile_delete();
return 0;
}
Received on Friday, 21 May 1999 19:52:51 UTC