On Windows 2000 and R 1.8.0 it crashes R. I get a popup windows with a message that says:
"Rgui.exe has generated errors and will be closed by Windows. You will need to restart the program. An error log is being created." although it does not say where this error log is. I have attached a jpg screenshot although I am not sure it will get through to the list. --- Date: Fri, 14 Nov 2003 23:17:06 +0000 From: Mark White <[EMAIL PROTECTED]> To: Prof Brian Ripley <[EMAIL PROTECTED]> Cc: <[EMAIL PROTECTED]>, <[EMAIL PROTECTED]> Subject: Re: [Rd] writeChar potential buffer overrun (PR#5090) Prof Brian Ripley writes: > Could you please give a reproducible example? This breaks a new R session for me: zz <- file("/tmp/test.raw", "wb") hdr <- "" writeChar(hdr,zz,nchars=10000000) Causes sig 11 on two machines, one with R 1.7.1 and the other with R 1.8.0 (both on NetBSD, so YMMV on other OSs, I suppose.) > On Fri, 14 Nov 2003 [EMAIL PROTECTED] wrote: > > Trying to copy the (binary) header of a input file directly > > to an output file, I've had repeatable seg faults. The call: > > > > writeChar(hdr, outfh, nchars=6144) > > > > when hdr just contains one empty string seems to be the > > culprit. The stack traces weren't all that illuminating, > > with sig 11 in memory-related functions following this. But > > in src/main/connections.c it looks like do_writechar doesn't > > check the length of strings when given an explicit nchars > > argument; so I think the strncpy() call will read too far. > > All R strings should be null-terminated, so strncpy will only copy the > number of characters present (plus the null terminator) if less than n. Quite true; I'd forgotten strncpy stopped at null. > I can see that writeChars might write rubbish out, but not why it should > segfault. Ok, I've just had a poke at it with ddd. The above example faults in the memset() call (line 2772 connections.c) in both R versions. I think the problem is underallocation of buf: len = 0; /* line 2757 */ for(i = 0; i < n; i++) { tlen = strlen(CHAR(STRING_ELT(object, i))); if (tlen > len) len = tlen; } buf = (char *) R_alloc(len + slen, sizeof(char)); which sets len to the longest string in object (in this case, 0 bytes), then allocates len+slen to buf. gdb confirms len=0 and slen=1 at this point. But a little later len = INTEGER(nchars)[i]; /* line 2770 */ s = CHAR(STRING_ELT(object, i)); memset(buf, '\0', len + slen); strncpy(buf, s, len); len is now set to [the first element of] nchars, which hasn't been checked, and is 10000000 (gdb confirms). So the call to memset() copies way over the end of allocated buf. Does that sound rational? I'm not very familiar with R's internals. I guess small overruns might not actually fault, because buf is within R's existing heap? > It is also unclear to me what to do in this case: flag a user > error? I'm not sure; perhaps the most logical thing is indeed to pad with nulls (as I think it would do with this fault fixed), and not raise an error at all. > > Using readBin and writeBin with integer() and size=1 seems > > to be the solution for header copying, but the faults still > > seemed worth reporting. > > It's certainly the documented way. Yup. I tried readChar/writeChar thinking it might be quicker (no type conversion?) but it's obviously not feasible with null-terminated strings. Mark <>< --- On Fri 11/14, Mark White < [EMAIL PROTECTED] > wrote: From: Mark White [mailto: [EMAIL PROTECTED] To: [EMAIL PROTECTED] Cc: [EMAIL PROTECTED], [EMAIL PROTECTED] Date: Fri, 14 Nov 2003 23:17:06 +0000 Subject: Re: [Rd] writeChar potential buffer overrun (PR#5090) Prof Brian Ripley writes:<br>> Could you please give a reproducible example?<br><br>This breaks a new R session for me:<br><br> zz <- file("/tmp/test.raw", "wb")<br> hdr <- ""<br> writeChar(hdr,zz,nchars=10000000)<br><br>Causes sig 11 on two machines, one with R 1.7.1 and the<br>other with R 1.8.0 (both on NetBSD, so YMMV on other OSs, I<br>suppose.)<br><br>> On Fri, 14 Nov 2003 [EMAIL PROTECTED] wrote:<br>> > Trying to copy the (binary) header of a input file directly<br>> > to an output file, I've had repeatable seg faults. The call:<br>> > <br>> > writeChar(hdr, outfh, nchars=6144)<br>> > <br>> > when hdr just contains one empty string seems to be the<br>> > culprit. The stack traces weren't all that illuminating,<br>> > with sig 11 in memory-related functions following this. But<br>> > in src/main/connections.c it looks like do_writechar doesn't<br>> > check the length of strings when given an explicit nchars<br>> > argument; so I think the strncpy() call will read t! oo far.<br>> <br>> All R strings should be null-terminated, so strncpy will only copy the<br>> number of characters present (plus the null terminator) if less than n.<br><br>Quite true; I'd forgotten strncpy stopped at null.<br><br>> I can see that writeChars might write rubbish out, but not why it should <br>> segfault. <br><br>Ok, I've just had a poke at it with ddd. The above example<br>faults in the memset() call (line 2772 connections.c) in both<br>R versions. I think the problem is underallocation of buf:<br><br> len = 0; /* line 2757 */<br> for(i = 0; i < n; i++) {<br> tlen = strlen(CHAR(STRING_ELT(object, i)));<br> if (tlen > len) len = tlen;<br> }<br> buf = (char *) R_alloc(len + slen, sizeof(char));<br><br>which sets len to the longest string in object (in this<br>case, 0 bytes), then allocates len+slen to buf. gdb<br>confirms len=0 and slen=1 at this point. But a little later<br><br> len = INTEGER(nchars)[i]; ! /* line 2770 */<br> s = CHAR(STRING_ELT(object, i));<br> mems et(buf, '\0', len + slen);<br> strncpy(buf, s, len);<br><br>len is now set to [the first element of] nchars, which<br>hasn't been checked, and is 10000000 (gdb confirms). So the<br>call to memset() copies way over the end of allocated buf.<br><br>Does that sound rational? I'm not very familiar with R's<br>internals. I guess small overruns might not actually fault,<br>because buf is within R's existing heap?<br><br>> It is also unclear to me what to do in this case: flag a user <br>> error?<br><br>I'm not sure; perhaps the most logical thing is indeed to<br>pad with nulls (as I think it would do with this fault<br>fixed), and not raise an error at all.<br><br>> > Using readBin and writeBin with integer() and size=1 seems<br>> > to be the solution for header copying, but the faults still<br>> > seemed worth reporting.<br>> <br>> It's certainly the documented way.<br><br>Yup. I tried readChar/writeChar thinking it might be<br>quicker (no type conversion?) but it's obviou! sly not<br>feasible with null-terminated strings.<br><br>Mark <><<br><br>______________________________________________<br>[EMAIL PROTECTED] mailing list<br>https://www.stat.math.ethz.ch/mailman/listinfo/r-devel<br> _______________________________________________
______________________________________________ [EMAIL PROTECTED] mailing list https://www.stat.math.ethz.ch/mailman/listinfo/r-devel