readline-fix-invalid-read.patch

Akira Tanaka, 07/18/2013 11:02 PM

Download (5.14 KB)

View differences:

ext/readline/readline.c (working copy)
128 128
 * Documented by TAKAO Kouji <kouji at takao7 dot net>.
129 129
 */
130 130

  
131
#if defined HAVE_RL_GETC_FUNCTION
132 131
static VALUE readline_instream;
132
static VALUE readline_outstream;
133

  
134
#if defined HAVE_RL_GETC_FUNCTION
133 135

  
134 136
#ifndef HAVE_RL_GETC
135 137
#define rl_getc(f) EOF
......
298 300
 * Returns nil when the inputted line is empty and user inputs EOF
299 301
 * (Presses ^D on UNIX).
300 302
 *
301
 * Raises IOError exception if below conditions are satisfied.
302
 * 1. stdin is not tty.
303
 * 2. stdin was closed. (errno is EBADF after called isatty(2).)
303
 * Raises IOError exception if one of below conditions are satisfied.
304
 * 1. stdin was closed.
305
 * 2. stdout was closed.
304 306
 *
305 307
 * This method supports thread. Switches the thread context when waits
306 308
 * inputting line.
......
391 393
	prompt = RSTRING_PTR(tmp);
392 394
    }
393 395

  
394
    if (!isatty(fileno(rl_instream)) && errno == EBADF) rb_raise(rb_eIOError, "closed stdin");
395
    if (rl_outstream) {
396
	struct stat stbuf;
397
	int fd = fileno(rl_outstream);
398
	if (fd < 0 || fstat(fd, &stbuf) != 0) {
399
	    rb_raise(rb_eIOError, "closed stdout");
400
	}
396
    if (readline_instream) {
397
            rb_io_t *ifp;
398
            GetOpenFile(readline_instream, ifp);
399
            if (ifp->fd < 0) {
400
                if (rl_instream) {
401
                    fclose(rl_instream);
402
                    rl_instream = NULL;
403
                }
404
                readline_instream = Qfalse;
405
                rb_raise(rb_eIOError, "closed stdin");
406
            }
407
    }
408

  
409
    if (readline_outstream) {
410
            rb_io_t *ofp;
411
            GetOpenFile(readline_outstream, ofp);
412
            if (ofp->fd < 0) {
413
                if (rl_outstream) {
414
                    fclose(rl_outstream);
415
                    rl_outstream = NULL;
416
                }
417
                readline_outstream = Qfalse;
418
                rb_raise(rb_eIOError, "closed stdout");
419
            }
401 420
    }
402 421

  
403 422
#ifdef _WIN32
......
439 458
    return result;
440 459
}
441 460

  
461
static void
462
clear_rl_instream(void)
463
{
464
    rb_io_t *ifp;
465
    if (rl_instream) {
466
        if (readline_instream) {
467
            rb_io_check_initialized(ifp = RFILE(rb_io_taint_check(readline_instream))->fptr);
468
            if (ifp->fd < 0 || fileno(rl_instream) == ifp->fd) {
469
                fclose(rl_instream);
470
                rl_instream = NULL;
471
            }
472
        }
473
        readline_instream = Qfalse;
474
        rl_instream = NULL;
475
    }
476
}
477

  
442 478
/*
443 479
 * call-seq:
444 480
 *   Readline.input = input
......
452 488
readline_s_set_input(VALUE self, VALUE input)
453 489
{
454 490
    rb_io_t *ifp;
491
    int fd;
492
    FILE *f;
455 493

  
456
    Check_Type(input, T_FILE);
457
    GetOpenFile(input, ifp);
458
    rl_instream = rb_io_stdio_file(ifp);
459
#ifdef HAVE_RL_GETC_FUNCTION
460
    readline_instream = input;
461
#endif
494
    if (NIL_P(input)) {
495
        clear_rl_instream();
496
    }
497
    else {
498
        Check_Type(input, T_FILE);
499
        GetOpenFile(input, ifp);
500
        clear_rl_instream();
501
        fd = rb_cloexec_dup(ifp->fd);
502
        if (fd == -1)
503
            rb_sys_fail("dup");
504
        f = fdopen(fd, "r");
505
        if (f == NULL) {
506
            int save_errno = errno;
507
            close(fd);
508
            errno = save_errno;
509
            rb_sys_fail("fdopen");
510
        }
511
        rl_instream = f;
512
        readline_instream = input;
513
    }
462 514
    return input;
463 515
}
464 516

  
517
static void
518
clear_rl_outstream(void)
519
{
520
    rb_io_t *ofp;
521
    if (rl_outstream) {
522
        if (readline_outstream) {
523
            rb_io_check_initialized(ofp = RFILE(rb_io_taint_check(readline_outstream))->fptr);
524
            if (ofp->fd < 0 || fileno(rl_outstream) == ofp->fd) {
525
                fclose(rl_outstream);
526
                rl_outstream = NULL;
527
            }
528
        }
529
        readline_outstream = Qfalse;
530
        rl_outstream = NULL;
531
    }
532
}
533

  
465 534
/*
466 535
 * call-seq:
467 536
 *   Readline.output = output
......
475 544
readline_s_set_output(VALUE self, VALUE output)
476 545
{
477 546
    rb_io_t *ofp;
547
    int fd;
548
    FILE *f;
478 549

  
479
    Check_Type(output, T_FILE);
480
    GetOpenFile(output, ofp);
481
    rl_outstream = rb_io_stdio_file(ofp);
550
    if (NIL_P(output)) {
551
        clear_rl_outstream();
552
    }
553
    else {
554
        Check_Type(output, T_FILE);
555
        GetOpenFile(output, ofp);
556
        clear_rl_outstream();
557
        fd = rb_cloexec_dup(ofp->fd);
558
        if (fd == -1)
559
            rb_sys_fail("dup");
560
        f = fdopen(fd, "w");
561
        if (f == NULL) {
562
            int save_errno = errno;
563
            close(fd);
564
            errno = save_errno;
565
            rb_sys_fail("fdopen");
566
        }
567
        rl_outstream = f;
568
        readline_outstream = output;
569
    }
482 570
    return output;
483 571
}
484 572

  
......
1846 1934
    rl_clear_signals();
1847 1935
#endif
1848 1936

  
1937
    rb_gc_register_address(&readline_instream);
1938
    rb_gc_register_address(&readline_outstream);
1939

  
1849 1940
    readline_s_set_input(mReadline, rb_stdin);
1850 1941
}