libwww bug with malformed URIs

Hi,

It seems there is a bug in libwww when using invalid URIs
(URIs missing an access scheme, like `test') as first argument
to `HTLoadToFile' like this:

    HTRequest *request = HTRequest_new();
    int status = HTLoadToFile("test", request, "/tmp/testa");
    HTRequest_delete(request);

The FILE * obtained for "/tmp/testa" is closed twice in this
case, leading to a segfault/stack corruption (I first observed
this with xdvik - see
http://sourceforge.net/tracker/?func=detail&atid=377580&aid=434836&group_id=23164).
This happens with Linux (RedHat 7.0, gcc 2.96) and libwww 5.3.2.

Here's a stack trace obtained with libefence:

ElectricFence Aborting: free(40832e94): address not from malloc().

Program received signal SIGILL, Illegal instruction.
[Switching to Thread 1024 (LWP 14211)]
0x400514e1 in __kill () from /lib/libc.so.6
(gdb) bt
#0  0x400514e1 in __kill () from /lib/libc.so.6
#1  0x400232ee in do_abort () at print.c:27
#2  0x400235f1 in EF_Abortv (pattern=0x400239c0 "free(%a): address not from malloc().", 
    args=0xbffff264) at print.c:137
#3  0x4002361f in EF_Abort (pattern=0x400239c0 "free(%a): address not from malloc().")
    at print.c:146
#4  0x40022ce9 in free (address=0x40832e94) at efence.c:749
#5  0x40092513 in _IO_new_fclose (fp=0x40832e94) at iofclose.c:87
#6  0x806f4ba in HTFWriter_free (me=0x40834ff4) at HTFWrite.c:65
#7  0x807c214 in HTRequest_delete (me=0x4083aee8) at HTReqMan.c:178
#8  0x8049a1e in main ()
#9  0x40040b65 in __libc_start_main (main=0x804996c <main>, argc=1, ubp_av=0xbffff3b4, 
    init=0x80492f0 <_init>, fini=0x80850bc <_fini>, rtld_fini=0x4000df24 <_dl_fini>, 
    stack_end=0xbffff3ac) at ../sysdeps/generic/libc-start.c:111


In HTLoadToFile (in HTAccess.c) the following happens:

    if ((fp = fopen(filename, "wb")) == NULL) {
        HTRequest_addError(request, ERR_FATAL, NO, HTERR_NO_FILE, 
    		           (char *) filename, strlen(filename),
    		           "HTLoadToFile"); 
        return NO;
    }

HTFWriter_new sets the `private' fp member of the HTStream object
to the fp returned by fopen():

    HTRequest_setOutputStream(request, HTFWriter_new(request, fp, NO));

HTLoadAbsolute returns NO (via launch_request (HTAccess.c),
HTLoad (HTReqMan.c), HTNet_newClient (HTNet.c)) in the following
line, so fp is closed for the first time:

    if (HTLoadAbsolute(url, request) == NO) {
        fclose(fp);
        /* FIX??? request->orig_output_stream = NULL; */
        return NO;
    } else
        return YES;

When the user later calls HTRequest_delete(request),
me->orig_output_stream (which is still the fp from above)
is closed for the second time (in HTReqMan.c):

    (*me->orig_output_stream->isa->_free)(me->orig_output_stream);

A possible fix might be to set `request->orig_output_stream' to
NULL (as indicated in the `FIX???' comment above), or maybe not
to fclose(fp) at all; but I'm not sure about how this fits into
the overall picture. Maybe someone who knows the library better
than me has a better approach for this ;-)

Best regards,
-- 
Stefan Ulrich

Received on Saturday, 23 June 2001 13:01:23 UTC