From: Pat Eyler Date: 2006-04-27T01:49:35+09:00 Subject: Another class of problem (Well, it looks like someone cleaned up a possible defect in the delete_slaves method in ruby/ext/tk/tcltklib.c without my bringing it up. Cool!) Here's another kind of error pointed out by coverity: Checker: FORWARD_NULL (help) File: ruby/io.c Function: io_fwrite Description: Variable "(fptr)->wbuf" tracked as NULL was passed to a function that dereferences it. 540 /* writing functions */ 541 static long 542 io_fwrite(VALUE str, OpenFile *fptr) 543 { 544 long len, n, r, l, offset = 0; 545 546 len = RSTRING(str)->len; 547 if ((n = len) <= 0) return n; Event var_compare_op: Added "(fptr)->wbuf" due to comparison "(fptr)->wbuf == 0" Also see events: [var_deref_model] At conditional (1): "(fptr)->wbuf == 0" taking true path At conditional (2): "(fptr)->mode & 8 == 0" taking false path 548 if (fptr->wbuf == NULL && !(fptr->mode & FMODE_SYNC)) { 549 fptr->wbuf_off = 0; 550 fptr->wbuf_len = 0; 551 fptr->wbuf_capa = 8192; 552 fptr->wbuf = ALLOC_N(char, fptr->wbuf_capa); 553 } At conditional (3): "(fptr)->mode & 8 != 0" taking true path 554 if ((fptr->mode & FMODE_SYNC) || 555 (fptr->wbuf && fptr->wbuf_capa <= fptr->wbuf_len + len) || 556 ((fptr->mode & FMODE_TTY) && memchr(RSTRING(str)->ptr+offset, '\n', len))) { 557 /* xxx: use writev to avoid double write if available */ At conditional (4): "(fptr)->wbuf_len != 0" taking true path At conditional (5): "((fptr)->wbuf_len + len) <= (fptr)->wbuf_capa" taking true path 558 if (fptr->wbuf_len && fptr->wbuf_len+len <= fptr->wbuf_capa) { At conditional (6): "(fptr)->wbuf_capa < (((fptr)->wbuf_off + (fptr)->wbuf_len) + len)" taking true path 559 if (fptr->wbuf_capa < fptr->wbuf_off+fptr->wbuf_len+len) { Event var_deref_model: Variable "(fptr)->wbuf" tracked as NULL was passed to a function that dereferences it. Also see events: [var_compare_op] 560 MEMMOVE(fptr->wbuf, fptr->wbuf+fptr->wbuf_off, char, fptr->wbuf_len); 561 fptr->wbuf_off = 0; 562 } 563 MEMMOVE(fptr->wbuf+fptr->wbuf_off+fptr->wbuf_len, RSTRING(str)->ptr+offset, char, len); 564 fptr->wbuf_len += len; 565 n = 0; 566 } 567 if (io_fflush(fptr) < 0) 568 return -1L; 569 if (n == 0) 570 return len; 571 /* avoid context switch between "a" and "\n" in STDERR.puts "a". 572 [ruby-dev:25080] */ 573 if (fptr->stdio_file != stderr && !rb_thread_fd_writable(fptr->fd)) { 574 rb_io_check_closed(fptr); 575 } 576 retry: 577 l = n; 578 if (PIPE_BUF < l && 579 !rb_thread_critical && 580 !rb_thread_alone() && 581 wsplit_p(fptr)) { 582 l = PIPE_BUF; 583 } 584 TRAP_BEG; 585 r = write(fptr->fd, RSTRING(str)->ptr+offset, l); 586 TRAP_END; /* xxx: signal handler may modify given string. */ 587 if (r == n) return len; 588 if (0 <= r) { 589 offset += r; 590 n -= r; 591 errno = EAGAIN; 592 } 593 if (rb_io_wait_writable(fptr->fd)) { 594 rb_io_check_closed(fptr); 595 if (offset < RSTRING(str)->len) 596 goto retry; 597 } 598 return -1L; 599 } 600 601 if (fptr->wbuf_off) { 602 if (fptr->wbuf_len) 603 MEMMOVE(fptr->wbuf, fptr->wbuf+fptr->wbuf_off, char, fptr->wbuf_len); 604 fptr->wbuf_off = 0; 605 } 606 MEMMOVE(fptr->wbuf+fptr->wbuf_off+fptr->wbuf_len, RSTRING(str)->ptr+offset, char, len); 607 fptr->wbuf_len += len; 608 return len; 609 }