ext/zlib/zlib.c in zlib-1.0.0 vs ext/zlib/zlib.c in zlib-1.1.0

- old
+ new

@@ -23,12 +23,16 @@ #else # define VALGRIND_MAKE_MEM_DEFINED(p, n) 0 # define VALGRIND_MAKE_MEM_UNDEFINED(p, n) 0 #endif -#define RUBY_ZLIB_VERSION "0.6.0" +#define RUBY_ZLIB_VERSION "1.1.0" +#ifndef RB_PASS_CALLED_KEYWORDS +# define rb_class_new_instance_kw(argc, argv, klass, kw_splat) rb_class_new_instance(argc, argv, klass) +#endif + #ifndef GZIP_SUPPORT #define GZIP_SUPPORT 1 #endif /* from zutil.h */ @@ -83,10 +87,11 @@ static void zstream_reset_input(struct zstream*); static void zstream_passthrough_input(struct zstream*); static VALUE zstream_detach_input(struct zstream*); static void zstream_reset(struct zstream*); static VALUE zstream_end(struct zstream*); +static VALUE zstream_ensure_end(VALUE v); static void zstream_run(struct zstream*, Bytef*, long, int); static VALUE zstream_sync(struct zstream*, Bytef*, long); static void zstream_mark(void*); static void zstream_free(void*); static VALUE zstream_new(VALUE, const struct zstream_funcs*); @@ -138,23 +143,23 @@ static VALUE gzfile_new(VALUE, const struct zstream_funcs*, void (*) _((struct gzfile*))); static void gzfile_reset(struct gzfile*); static void gzfile_close(struct gzfile*, int); static void gzfile_write_raw(struct gzfile*); static VALUE gzfile_read_raw_partial(VALUE); -static VALUE gzfile_read_raw_rescue(VALUE); -static VALUE gzfile_read_raw(struct gzfile*); -static int gzfile_read_raw_ensure(struct gzfile*, long); +static VALUE gzfile_read_raw_rescue(VALUE,VALUE); +static VALUE gzfile_read_raw(struct gzfile*, VALUE outbuf); +static int gzfile_read_raw_ensure(struct gzfile*, long, VALUE outbuf); static char *gzfile_read_raw_until_zero(struct gzfile*, long); static unsigned int gzfile_get16(const unsigned char*); static unsigned long gzfile_get32(const unsigned char*); static void gzfile_set32(unsigned long n, unsigned char*); static void gzfile_make_header(struct gzfile*); static void gzfile_make_footer(struct gzfile*); -static void gzfile_read_header(struct gzfile*); -static void gzfile_check_footer(struct gzfile*); +static void gzfile_read_header(struct gzfile*, VALUE outbuf); +static void gzfile_check_footer(struct gzfile*, VALUE outbuf); static void gzfile_write(struct gzfile*, Bytef*, long); -static long gzfile_read_more(struct gzfile*); +static long gzfile_read_more(struct gzfile*, VALUE outbuf); static void gzfile_calc_crc(struct gzfile*, VALUE); static VALUE gzfile_read(struct gzfile*, long); static VALUE gzfile_read_all(struct gzfile*); static void gzfile_ungets(struct gzfile*, const Bytef*, long); static void gzfile_ungetbyte(struct gzfile*, int); @@ -358,15 +363,11 @@ * Returns the string which represents the version of zlib library. */ static VALUE rb_zlib_version(VALUE klass) { - VALUE str; - - str = rb_str_new2(zlibVersion()); - OBJ_TAINT(str); /* for safe */ - return str; + return rb_str_new2(zlibVersion()); } #if SIZEOF_LONG > SIZEOF_INT static uLong checksum_long(uLong (*func)(uLong, const Bytef*, uInt), uLong sum, const Bytef *ptr, long len) @@ -625,14 +626,12 @@ if (!ZSTREAM_IS_GZFILE(z) && rb_block_given_p()) { long buf_filled = ZSTREAM_BUF_FILLED(z); if (buf_filled >= ZSTREAM_AVAIL_OUT_STEP_MAX) { int state = 0; - VALUE self = (VALUE)z->stream.opaque; rb_obj_reveal(z->buf, rb_cString); - OBJ_INFECT(z->buf, self); rb_protect(rb_yield, z->buf, &state); z->buf = Qnil; zstream_expand_buffer_into(z, ZSTREAM_AVAIL_OUT_STEP_MAX); @@ -736,11 +735,11 @@ zstream_append_buffer((z),(Bytef*)RSTRING_PTR(v),RSTRING_LEN(v)) static VALUE zstream_detach_buffer(struct zstream *z) { - VALUE dst, self = (VALUE)z->stream.opaque; + VALUE dst; if (!ZSTREAM_IS_FINISHED(z) && !ZSTREAM_IS_GZFILE(z) && rb_block_given_p()) { /* prevent tiny yields mid-stream, save for next * zstream_expand_buffer() or stream end */ @@ -753,12 +752,10 @@ else { dst = z->buf; rb_obj_reveal(dst, rb_cString); } - OBJ_INFECT(dst, self); - z->buf = Qnil; z->stream.next_out = 0; z->stream.avail_out = 0; if (!ZSTREAM_IS_GZFILE(z) && rb_block_given_p()) { @@ -843,23 +840,54 @@ zstream_append_input((z), (Bytef*)RSTRING_PTR(v), RSTRING_LEN(v)) static void zstream_discard_input(struct zstream *z, long len) { - if (NIL_P(z->input) || RSTRING_LEN(z->input) <= len) { - z->input = Qnil; + if (NIL_P(z->input)) { } - else { - z->input = rb_str_substr(z->input, len, - RSTRING_LEN(z->input) - len); + else if (RBASIC_CLASS(z->input) == 0) { + /* hidden, we created z->input and have complete control */ + char *ptr; + long oldlen, newlen; + + RSTRING_GETMEM(z->input, ptr, oldlen); + newlen = oldlen - len; + if (newlen > 0) { + memmove(ptr, ptr + len, newlen); + } + if (newlen < 0) { + newlen = 0; + } + rb_str_resize(z->input, newlen); + if (newlen == 0) { + rb_gc_force_recycle(z->input); + z->input = Qnil; + } + else { + rb_str_set_len(z->input, newlen); + } } + else { /* do not mangle user-provided data */ + if (RSTRING_LEN(z->input) <= len) { + z->input = Qnil; + } + else { + z->input = rb_str_substr(z->input, len, + RSTRING_LEN(z->input) - len); + } + } } static void zstream_reset_input(struct zstream *z) { - z->input = Qnil; + if (!NIL_P(z->input) && RBASIC_CLASS(z->input) == 0) { + rb_str_resize(z->input, 0); + } + else { + z->input = Qnil; + } } static void zstream_passthrough_input(struct zstream *z) { @@ -880,11 +908,10 @@ else { dst = z->input; rb_obj_reveal(dst, rb_cString); } z->input = Qnil; - rb_obj_reveal(dst, rb_cString); return dst; } static void zstream_reset(struct zstream *z) @@ -923,10 +950,16 @@ } z->flags = 0; return Qnil; } +static VALUE +zstream_ensure_end(VALUE v) +{ + return zstream_end((struct zstream *)v); +} + static void * zstream_run_func(void *ptr) { struct zstream_run_args *args = (struct zstream_run_args *)ptr; int err, state, flush = args->flush; @@ -979,10 +1012,11 @@ return (void *)(VALUE)err; } /* * There is no safe way to interrupt z->run->func(). + * async-signal-safe */ static void zstream_unblock_func(void *ptr) { struct zstream_run_args *args = (struct zstream_run_args *)ptr; @@ -993,11 +1027,11 @@ static void zstream_run(struct zstream *z, Bytef *src, long len, int flush) { struct zstream_run_args args; int err; - VALUE guard = Qnil; + VALUE old_input = Qnil; args.z = z; args.flush = flush; args.interrupt = 0; args.jump_state = 0; @@ -1007,25 +1041,32 @@ z->stream.next_in = (Bytef*)""; z->stream.avail_in = 0; } else { zstream_append_input(z, src, len); - z->stream.next_in = (Bytef*)RSTRING_PTR(z->input); - z->stream.avail_in = MAX_UINT(RSTRING_LEN(z->input)); /* keep reference to `z->input' so as not to be garbage collected after zstream_reset_input() and prevent `z->stream.next_in' from dangling. */ - guard = z->input; + old_input = zstream_detach_input(z); + rb_obj_hide(old_input); /* for GVL release and later recycle */ + z->stream.next_in = (Bytef*)RSTRING_PTR(old_input); + z->stream.avail_in = MAX_UINT(RSTRING_LEN(old_input)); } if (z->stream.avail_out == 0) { zstream_expand_buffer(z); } loop: +#ifndef RB_NOGVL_UBF_ASYNC_SAFE err = (int)(VALUE)rb_thread_call_without_gvl(zstream_run_func, (void *)&args, zstream_unblock_func, (void *)&args); +#else + err = (int)(VALUE)rb_nogvl(zstream_run_func, (void *)&args, + zstream_unblock_func, (void *)&args, + RB_NOGVL_UBF_ASYNC_SAFE); +#endif if (flush != Z_FINISH && err == Z_BUF_ERROR && z->stream.avail_out > 0) { z->flags |= ZSTREAM_FLAG_IN_STREAM; } @@ -1050,12 +1091,15 @@ raise_zlib_error(err, z->stream.msg); } if (z->stream.avail_in > 0) { zstream_append_input(z, z->stream.next_in, z->stream.avail_in); - RB_GC_GUARD(guard); /* prevent tail call to make guard effective */ } + if (!NIL_P(old_input)) { + rb_str_resize(old_input, 0); + rb_gc_force_recycle(old_input); + } if (args.jump_state) rb_jump_tag(args.jump_state); } @@ -1283,11 +1327,10 @@ struct zstream *z; VALUE dst; TypedData_Get_Struct(obj, struct zstream, &zstream_data_type, z); dst = zstream_detach_input(z); - OBJ_INFECT(dst, obj); return dst; } /* * call-seq: @@ -1602,13 +1645,12 @@ } ZSTREAM_READY(&z); args[0] = (VALUE)&z; args[1] = src; - dst = rb_ensure(deflate_run, (VALUE)args, zstream_end, (VALUE)&z); + dst = rb_ensure(deflate_run, (VALUE)args, zstream_ensure_end, (VALUE)&z); - OBJ_INFECT(dst, src); return dst; } static void do_deflate(struct zstream *z, VALUE src, int flush) @@ -1654,11 +1696,10 @@ { struct zstream *z = get_zstream(obj); VALUE src, flush; rb_scan_args(argc, argv, "11", &src, &flush); - OBJ_INFECT(obj, src); do_deflate(z, src, ARG_FLUSH(flush)); return zstream_detach_buffer(z); } @@ -1672,11 +1713,10 @@ * preserved in output buffer. */ static VALUE rb_deflate_addstr(VALUE obj, VALUE src) { - OBJ_INFECT(obj, src); do_deflate(get_zstream(obj), src, Z_NO_FLUSH); return obj; } /* @@ -1772,11 +1812,10 @@ { struct zstream *z = get_zstream(obj); VALUE src = dic; int err; - OBJ_INFECT(obj, dic); StringValue(src); err = deflateSetDictionary(&z->stream, (Bytef*)RSTRING_PTR(src), RSTRING_LENINT(src)); if (err != Z_OK) { raise_zlib_error(err, z->stream.msg); @@ -1917,13 +1956,12 @@ } ZSTREAM_READY(&z); args[0] = (VALUE)&z; args[1] = src; - dst = rb_ensure(inflate_run, (VALUE)args, zstream_end, (VALUE)&z); + dst = rb_ensure(inflate_run, (VALUE)args, zstream_ensure_end, (VALUE)&z); - OBJ_INFECT(dst, src); return dst; } static void do_inflate(struct zstream *z, VALUE src) @@ -1999,21 +2037,18 @@ rb_inflate_inflate(VALUE obj, VALUE src) { struct zstream *z = get_zstream(obj); VALUE dst; - OBJ_INFECT(obj, src); - if (ZSTREAM_IS_FINISHED(z)) { if (NIL_P(src)) { dst = zstream_detach_buffer(z); } else { StringValue(src); zstream_append_buffer2(z, src); dst = rb_str_new(0, 0); - OBJ_INFECT(dst, obj); } } else { do_inflate(z, src); dst = zstream_detach_buffer(z); @@ -2035,12 +2070,10 @@ static VALUE rb_inflate_addstr(VALUE obj, VALUE src) { struct zstream *z = get_zstream(obj); - OBJ_INFECT(obj, src); - if (ZSTREAM_IS_FINISHED(z)) { if (!NIL_P(src)) { StringValue(src); zstream_append_buffer2(z, src); } @@ -2066,11 +2099,10 @@ static VALUE rb_inflate_sync(VALUE obj, VALUE src) { struct zstream *z = get_zstream(obj); - OBJ_INFECT(obj, src); StringValue(src); return zstream_sync(z, (Bytef*)RSTRING_PTR(src), RSTRING_LEN(src)); } /* @@ -2108,11 +2140,10 @@ { struct zstream *z = get_zstream(obj); VALUE src = dic; int err; - OBJ_INFECT(obj, dic); StringValue(src); err = inflateSetDictionary(&z->stream, (Bytef*)RSTRING_PTR(src), RSTRING_LENINT(src)); if (err != Z_OK) { raise_zlib_error(err, z->stream.msg); @@ -2189,24 +2220,34 @@ void (*end)(struct gzfile *); rb_encoding *enc; rb_encoding *enc2; rb_econv_t *ec; VALUE ecopts; - char *cbuf; VALUE path; }; #define GZFILE_CBUF_CAPA 10 #define GZFILE_FLAG_SYNC ZSTREAM_FLAG_UNUSED #define GZFILE_FLAG_HEADER_FINISHED (ZSTREAM_FLAG_UNUSED << 1) #define GZFILE_FLAG_FOOTER_FINISHED (ZSTREAM_FLAG_UNUSED << 2) +#define GZFILE_FLAG_MTIME_IS_SET (ZSTREAM_FLAG_UNUSED << 3) #define GZFILE_IS_FINISHED(gz) \ (ZSTREAM_IS_FINISHED(&(gz)->z) && ZSTREAM_BUF_FILLED(&(gz)->z) == 0) #define GZFILE_READ_SIZE 2048 +struct read_raw_arg { + VALUE io; + union { + const VALUE argv[2]; /* for rb_funcallv */ + struct { + VALUE len; + VALUE buf; + } in; + } as; +}; static void gzfile_mark(void *p) { struct gzfile *gz = p; @@ -2229,26 +2270,17 @@ if (z->func == &deflate_funcs) { finalizer_warn("Zlib::GzipWriter object must be closed explicitly."); } zstream_finalize(z); } - if (gz->cbuf) { - xfree(gz->cbuf); - } xfree(gz); } static size_t gzfile_memsize(const void *p) { - const struct gzfile *gz = p; - size_t size = sizeof(struct gzfile); - - if (gz->cbuf) - size += GZFILE_CBUF_CAPA; - - return size; + return sizeof(struct gzfile); } static const rb_data_type_t gzfile_data_type = { "gzfile", { gzfile_mark, gzfile_free, gzfile_memsize, }, @@ -2273,11 +2305,10 @@ gz->enc = rb_default_external_encoding(); gz->enc2 = 0; gz->ec = NULL; gz->ecflags = 0; gz->ecopts = Qnil; - gz->cbuf = 0; gz->path = Qnil; } static VALUE gzfile_new(VALUE klass, const struct zstream_funcs *funcs, void (*endfunc)(struct gzfile *)) @@ -2327,62 +2358,69 @@ { VALUE str; if (ZSTREAM_BUF_FILLED(&gz->z) > 0) { str = zstream_detach_buffer(&gz->z); - OBJ_TAINT(str); /* for safe */ rb_funcall(gz->io, id_write, 1, str); if ((gz->z.flags & GZFILE_FLAG_SYNC) && rb_respond_to(gz->io, id_flush)) rb_funcall(gz->io, id_flush, 0); } } static VALUE gzfile_read_raw_partial(VALUE arg) { - struct gzfile *gz = (struct gzfile*)arg; + struct read_raw_arg *ra = (struct read_raw_arg *)arg; VALUE str; + int argc = NIL_P(ra->as.argv[1]) ? 1 : 2; - str = rb_funcall(gz->io, id_readpartial, 1, INT2FIX(GZFILE_READ_SIZE)); + str = rb_funcallv(ra->io, id_readpartial, argc, ra->as.argv); Check_Type(str, T_STRING); return str; } static VALUE -gzfile_read_raw_rescue(VALUE arg) +gzfile_read_raw_rescue(VALUE arg, VALUE _) { - struct gzfile *gz = (struct gzfile*)arg; + struct read_raw_arg *ra = (struct read_raw_arg *)arg; VALUE str = Qnil; if (rb_obj_is_kind_of(rb_errinfo(), rb_eNoMethodError)) { - str = rb_funcall(gz->io, id_read, 1, INT2FIX(GZFILE_READ_SIZE)); + int argc = NIL_P(ra->as.argv[1]) ? 1 : 2; + str = rb_funcallv(ra->io, id_read, argc, ra->as.argv); if (!NIL_P(str)) { Check_Type(str, T_STRING); } } return str; /* return nil when EOFError */ } static VALUE -gzfile_read_raw(struct gzfile *gz) +gzfile_read_raw(struct gzfile *gz, VALUE outbuf) { - return rb_rescue2(gzfile_read_raw_partial, (VALUE)gz, - gzfile_read_raw_rescue, (VALUE)gz, + struct read_raw_arg ra; + + ra.io = gz->io; + ra.as.in.len = INT2FIX(GZFILE_READ_SIZE); + ra.as.in.buf = outbuf; + + return rb_rescue2(gzfile_read_raw_partial, (VALUE)&ra, + gzfile_read_raw_rescue, (VALUE)&ra, rb_eEOFError, rb_eNoMethodError, (VALUE)0); } static int -gzfile_read_raw_ensure(struct gzfile *gz, long size) +gzfile_read_raw_ensure(struct gzfile *gz, long size, VALUE outbuf) { VALUE str; if (gz->io == Qundef) { /* Zlib.gunzip */ if (NIL_P(gz->z.input) || RSTRING_LEN(gz->z.input) < size) rb_raise(cGzError, "unexpected end of string"); } while (NIL_P(gz->z.input) || RSTRING_LEN(gz->z.input) < size) { - str = gzfile_read_raw(gz); + str = gzfile_read_raw(gz, outbuf); if (NIL_P(str)) return 0; zstream_append_input2(&gz->z, str); } return 1; } @@ -2395,11 +2433,11 @@ for (;;) { p = memchr(RSTRING_PTR(gz->z.input) + offset, '\0', RSTRING_LEN(gz->z.input) - offset); if (p) break; - str = gzfile_read_raw(gz); + str = gzfile_read_raw(gz, Qnil); if (NIL_P(str)) { rb_raise(cGzError, "unexpected end of file"); } offset = RSTRING_LEN(gz->z.input); zstream_append_input2(&gz->z, str); @@ -2476,11 +2514,11 @@ flags |= GZ_FLAG_ORIG_NAME; } if (!NIL_P(gz->comment)) { flags |= GZ_FLAG_COMMENT; } - if (gz->mtime == 0) { + if (!(gz->z.flags & GZFILE_FLAG_MTIME_IS_SET)) { gz->mtime = time(0); } if (gz->level == Z_BEST_SPEED) { extraflags |= GZ_EXTRAFLAG_FAST; @@ -2520,17 +2558,18 @@ zstream_append_buffer(&gz->z, buf, (long)sizeof(buf)); gz->z.flags |= GZFILE_FLAG_FOOTER_FINISHED; } static void -gzfile_read_header(struct gzfile *gz) +gzfile_read_header(struct gzfile *gz, VALUE outbuf) { const unsigned char *head; long len; char flags, *p; - if (!gzfile_read_raw_ensure(gz, 10)) { /* 10 is the size of gzip header */ + /* 10 is the size of gzip header */ + if (!gzfile_read_raw_ensure(gz, 10, outbuf)) { gzfile_raise(gz, cGzError, "not in gzip format"); } head = (unsigned char*)RSTRING_PTR(gz->z.input); @@ -2565,53 +2604,52 @@ gz->mtime = gzfile_get32(&head[4]); gz->os_code = head[9]; zstream_discard_input(&gz->z, 10); if (flags & GZ_FLAG_EXTRA) { - if (!gzfile_read_raw_ensure(gz, 2)) { + if (!gzfile_read_raw_ensure(gz, 2, outbuf)) { rb_raise(cGzError, "unexpected end of file"); } len = gzfile_get16((Bytef*)RSTRING_PTR(gz->z.input)); - if (!gzfile_read_raw_ensure(gz, 2 + len)) { + if (!gzfile_read_raw_ensure(gz, 2 + len, outbuf)) { rb_raise(cGzError, "unexpected end of file"); } zstream_discard_input(&gz->z, 2 + len); } if (flags & GZ_FLAG_ORIG_NAME) { - if (!gzfile_read_raw_ensure(gz, 1)) { + if (!gzfile_read_raw_ensure(gz, 1, outbuf)) { rb_raise(cGzError, "unexpected end of file"); } p = gzfile_read_raw_until_zero(gz, 0); len = p - RSTRING_PTR(gz->z.input); gz->orig_name = rb_str_new(RSTRING_PTR(gz->z.input), len); - OBJ_TAINT(gz->orig_name); /* for safe */ zstream_discard_input(&gz->z, len + 1); } if (flags & GZ_FLAG_COMMENT) { - if (!gzfile_read_raw_ensure(gz, 1)) { + if (!gzfile_read_raw_ensure(gz, 1, outbuf)) { rb_raise(cGzError, "unexpected end of file"); } p = gzfile_read_raw_until_zero(gz, 0); len = p - RSTRING_PTR(gz->z.input); gz->comment = rb_str_new(RSTRING_PTR(gz->z.input), len); - OBJ_TAINT(gz->comment); /* for safe */ zstream_discard_input(&gz->z, len + 1); } if (gz->z.input != Qnil && RSTRING_LEN(gz->z.input) > 0) { zstream_run(&gz->z, 0, 0, Z_SYNC_FLUSH); } } static void -gzfile_check_footer(struct gzfile *gz) +gzfile_check_footer(struct gzfile *gz, VALUE outbuf) { unsigned long crc, length; gz->z.flags |= GZFILE_FLAG_FOOTER_FINISHED; - if (!gzfile_read_raw_ensure(gz, 8)) { /* 8 is the size of gzip footer */ + /* 8 is the size of gzip footer */ + if (!gzfile_read_raw_ensure(gz, 8, outbuf)) { gzfile_raise(gz, cNoFooter, "footer is not found"); } crc = gzfile_get32((Bytef*)RSTRING_PTR(gz->z.input)); length = gzfile_get32((Bytef*)RSTRING_PTR(gz->z.input) + 4); @@ -2641,16 +2679,16 @@ } gzfile_write_raw(gz); } static long -gzfile_read_more(struct gzfile *gz) +gzfile_read_more(struct gzfile *gz, VALUE outbuf) { VALUE str; while (!ZSTREAM_IS_FINISHED(&gz->z)) { - str = gzfile_read_raw(gz); + str = gzfile_read_raw(gz, outbuf); if (NIL_P(str)) { if (!ZSTREAM_IS_FINISHED(&gz->z)) { rb_raise(cGzError, "unexpected end of file"); } break; @@ -2681,17 +2719,15 @@ static VALUE gzfile_newstr(struct gzfile *gz, VALUE str) { if (!gz->enc2) { rb_enc_associate(str, gz->enc); - OBJ_TAINT(str); /* for safe */ return str; } if (gz->ec && rb_enc_dummy_p(gz->enc2)) { str = rb_econv_str_convert(gz->ec, str, ECONV_PARTIAL_INPUT); rb_enc_associate(str, gz->enc); - OBJ_TAINT(str); return str; } return rb_str_conv_enc_opts(str, gz->enc2, gz->enc, gz->ecflags, gz->ecopts); } @@ -2702,15 +2738,15 @@ if (len < 0) rb_raise(rb_eArgError, "negative length %ld given", len); if (len == 0) return 0; while (!ZSTREAM_IS_FINISHED(&gz->z) && ZSTREAM_BUF_FILLED(&gz->z) < len) { - gzfile_read_more(gz); + gzfile_read_more(gz, Qnil); } if (GZFILE_IS_FINISHED(gz)) { if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) { - gzfile_check_footer(gz); + gzfile_check_footer(gz, Qnil); } return -1; } return len < ZSTREAM_BUF_FILLED(&gz->z) ? len : ZSTREAM_BUF_FILLED(&gz->z); } @@ -2734,27 +2770,24 @@ VALUE dst; if (len < 0) rb_raise(rb_eArgError, "negative length %ld given", len); - if (!NIL_P(outbuf)) - OBJ_TAINT(outbuf); - if (len == 0) { if (NIL_P(outbuf)) return rb_str_new(0, 0); else { rb_str_resize(outbuf, 0); return outbuf; } } while (!ZSTREAM_IS_FINISHED(&gz->z) && ZSTREAM_BUF_FILLED(&gz->z) == 0) { - gzfile_read_more(gz); + gzfile_read_more(gz, outbuf); } if (GZFILE_IS_FINISHED(gz)) { if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) { - gzfile_check_footer(gz); + gzfile_check_footer(gz, outbuf); } if (!NIL_P(outbuf)) rb_str_resize(outbuf, 0); rb_raise(rb_eEOFError, "end of file reached"); } @@ -2763,36 +2796,35 @@ gzfile_calc_crc(gz, dst); if (!NIL_P(outbuf)) { rb_str_resize(outbuf, RSTRING_LEN(dst)); memcpy(RSTRING_PTR(outbuf), RSTRING_PTR(dst), RSTRING_LEN(dst)); - RB_GC_GUARD(dst); + rb_str_resize(dst, 0); + rb_gc_force_recycle(dst); dst = outbuf; } - OBJ_TAINT(dst); /* for safe */ return dst; } static VALUE gzfile_read_all(struct gzfile *gz) { VALUE dst; while (!ZSTREAM_IS_FINISHED(&gz->z)) { - gzfile_read_more(gz); + gzfile_read_more(gz, Qnil); } if (GZFILE_IS_FINISHED(gz)) { if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) { - gzfile_check_footer(gz); + gzfile_check_footer(gz, Qnil); } return rb_str_new(0, 0); } dst = zstream_detach_buffer(&gz->z); if (NIL_P(dst)) return dst; gzfile_calc_crc(gz, dst); - OBJ_TAINT(dst); return gzfile_newstr(gz, dst); } static VALUE gzfile_getc(struct gzfile *gz) @@ -2800,38 +2832,34 @@ VALUE buf, dst = 0; int len; len = rb_enc_mbmaxlen(gz->enc); while (!ZSTREAM_IS_FINISHED(&gz->z) && ZSTREAM_BUF_FILLED(&gz->z) < len) { - gzfile_read_more(gz); + gzfile_read_more(gz, Qnil); } if (GZFILE_IS_FINISHED(gz)) { if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) { - gzfile_check_footer(gz); + gzfile_check_footer(gz, Qnil); } return Qnil; } if (gz->ec && rb_enc_dummy_p(gz->enc2)) { const unsigned char *ss, *sp, *se; unsigned char *ds, *dp, *de; + VALUE cbuf = rb_enc_str_new(0, GZFILE_CBUF_CAPA, gz->enc); - if (!gz->cbuf) { - gz->cbuf = ALLOC_N(char, GZFILE_CBUF_CAPA); - } ss = sp = (const unsigned char*)RSTRING_PTR(gz->z.buf); se = sp + ZSTREAM_BUF_FILLED(&gz->z); - ds = dp = (unsigned char *)gz->cbuf; + ds = dp = (unsigned char *)RSTRING_PTR(cbuf); de = (unsigned char *)ds + GZFILE_CBUF_CAPA; (void)rb_econv_convert(gz->ec, &sp, se, &dp, de, ECONV_PARTIAL_INPUT|ECONV_AFTER_OUTPUT); rb_econv_check_error(gz->ec); dst = zstream_shift_buffer(&gz->z, sp - ss); gzfile_calc_crc(gz, dst); - dst = rb_str_new(gz->cbuf, dp - ds); - rb_enc_associate(dst, gz->enc); - OBJ_TAINT(dst); - return dst; + rb_str_resize(cbuf, dp - ds); + return cbuf; } else { buf = gz->z.buf; len = rb_enc_mbclen(RSTRING_PTR(buf), RSTRING_END(buf), gz->enc); dst = gzfile_read(gz, len); @@ -2874,21 +2902,21 @@ gzfile_writer_end(struct gzfile *gz) { if (ZSTREAM_IS_CLOSING(&gz->z)) return; gz->z.flags |= ZSTREAM_FLAG_CLOSING; - rb_ensure(gzfile_writer_end_run, (VALUE)gz, zstream_end, (VALUE)&gz->z); + rb_ensure(gzfile_writer_end_run, (VALUE)gz, zstream_ensure_end, (VALUE)&gz->z); } static VALUE gzfile_reader_end_run(VALUE arg) { struct gzfile *gz = (struct gzfile *)arg; if (GZFILE_IS_FINISHED(gz) && !(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) { - gzfile_check_footer(gz); + gzfile_check_footer(gz, Qnil); } return Qnil; } @@ -2896,11 +2924,11 @@ gzfile_reader_end(struct gzfile *gz) { if (ZSTREAM_IS_CLOSING(&gz->z)) return; gz->z.flags |= ZSTREAM_FLAG_CLOSING; - rb_ensure(gzfile_reader_end_run, (VALUE)gz, zstream_end, (VALUE)&gz->z); + rb_ensure(gzfile_reader_end_run, (VALUE)gz, zstream_ensure_end, (VALUE)&gz->z); } static void gzfile_reader_rewind(struct gzfile *gz) { @@ -2921,16 +2949,15 @@ VALUE str; if (!ZSTREAM_IS_READY(&gz->z)) return Qnil; if (!GZFILE_IS_FINISHED(gz)) return Qnil; if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) { - gzfile_check_footer(gz); + gzfile_check_footer(gz, Qnil); } if (NIL_P(gz->z.input)) return Qnil; str = rb_str_resurrect(gz->z.input); - OBJ_TAINT(str); /* for safe */ return str; } static struct gzfile * get_gzfile(VALUE obj) @@ -2993,11 +3020,11 @@ static VALUE new_wrap(VALUE tmp) { new_wrap_arg_t *arg = (new_wrap_arg_t *)tmp; - return rb_class_new_instance(arg->argc, arg->argv, arg->klass); + return rb_class_new_instance_kw(arg->argc, arg->argv, arg->klass, RB_PASS_CALLED_KEYWORDS); } static VALUE gzfile_ensure_close(VALUE obj) { @@ -3026,11 +3053,11 @@ rb_io_close(argv[0]); rb_jump_tag(state); } } else { - obj = rb_class_new_instance(argc, argv, klass); + obj = rb_class_new_instance_kw(argc, argv, klass, RB_PASS_CALLED_KEYWORDS); } if (rb_block_given_p()) { return rb_ensure(rb_yield, obj, gzfile_ensure_close, obj); } @@ -3143,11 +3170,10 @@ { VALUE str = get_gzfile(obj)->orig_name; if (!NIL_P(str)) { str = rb_str_dup(str); } - OBJ_TAINT(str); /* for safe */ return str; } /* * Document-method: Zlib::GzipFile#comment @@ -3160,11 +3186,10 @@ { VALUE str = get_gzfile(obj)->comment; if (!NIL_P(str)) { str = rb_str_dup(str); } - OBJ_TAINT(str); /* for safe */ return str; } /* * Document-method: Zlib::GzipFile#lineno @@ -3219,10 +3244,11 @@ rb_raise(cGzError, "header is already written"); } val = rb_Integer(mtime); gz->mtime = NUM2UINT(val); + gz->z.flags |= GZFILE_FLAG_MTIME_IS_SET; return mtime; } /* @@ -3729,11 +3755,11 @@ if (err != Z_OK) { raise_zlib_error(err, gz->z.stream.msg); } gz->io = io; ZSTREAM_READY(&gz->z); - gzfile_read_header(gz); + gzfile_read_header(gz, Qnil); rb_gzfile_ecopts(gz, opt); if (rb_respond_to(io, id_path)) { gz->path = rb_funcall(gz->io, id_path, 0); rb_define_singleton_method(obj, "path", rb_gzfile_path, 0); @@ -3979,22 +4005,22 @@ char *p; int n; while (ZSTREAM_BUF_FILLED(&gz->z) == 0) { if (GZFILE_IS_FINISHED(gz)) return; - gzfile_read_more(gz); + gzfile_read_more(gz, Qnil); } n = 0; p = RSTRING_PTR(gz->z.buf); while (n++, *(p++) == '\n') { if (n >= ZSTREAM_BUF_FILLED(&gz->z)) { str = zstream_detach_buffer(&gz->z); gzfile_calc_crc(gz, str); while (ZSTREAM_BUF_FILLED(&gz->z) == 0) { if (GZFILE_IS_FINISHED(gz)) return; - gzfile_read_more(gz); + gzfile_read_more(gz, Qnil); } n = 0; p = RSTRING_PTR(gz->z.buf); } } @@ -4112,20 +4138,20 @@ while (ZSTREAM_BUF_FILLED(&gz->z) < rslen) { if (ZSTREAM_IS_FINISHED(&gz->z)) { if (ZSTREAM_BUF_FILLED(&gz->z) > 0) gz->lineno++; return gzfile_read(gz, rslen); } - gzfile_read_more(gz); + gzfile_read_more(gz, Qnil); } p = RSTRING_PTR(gz->z.buf); n = rslen; for (;;) { long filled; if (n > ZSTREAM_BUF_FILLED(&gz->z)) { if (ZSTREAM_IS_FINISHED(&gz->z)) break; - gzfile_read_more(gz); + gzfile_read_more(gz, Qnil); p = RSTRING_PTR(gz->z.buf) + n - rslen; } if (!rspara) rscheck(rsptr, rslen, rs); filled = ZSTREAM_BUF_FILLED(&gz->z); if (limit > 0 && filled >= limit) { @@ -4249,17 +4275,23 @@ { return rb_enc_from_encoding(get_gzfile(self)->enc); } static VALUE -zlib_gzip_ensure(VALUE arg) +zlib_gzip_end_rescue(VALUE arg) { struct gzfile *gz = (struct gzfile *)arg; - rb_rescue((VALUE(*)())gz->end, arg, NULL, Qnil); + gz->end(gz); return Qnil; } +static VALUE +zlib_gzip_ensure(VALUE arg) +{ + return rb_rescue(zlib_gzip_end_rescue, arg, NULL, Qnil); +} + static void zlib_gzip_end(struct gzfile *gz) { gz->z.flags |= ZSTREAM_FLAG_CLOSING; zstream_run(&gz->z, (Bytef*)"", 0, Z_FINISH); @@ -4401,28 +4433,29 @@ zlib_gunzip_run(VALUE arg) { struct gzfile *gz = (struct gzfile *)arg; VALUE dst; - gzfile_read_header(gz); + gzfile_read_header(gz, Qnil); dst = zstream_detach_buffer(&gz->z); gzfile_calc_crc(gz, dst); if (!ZSTREAM_IS_FINISHED(&gz->z)) { rb_raise(cGzError, "unexpected end of file"); } if (NIL_P(gz->z.input)) { rb_raise(cNoFooter, "footer is not found"); } - gzfile_check_footer(gz); + gzfile_check_footer(gz, Qnil); return dst; } #endif /* GZIP_SUPPORT */ void Init_zlib(void) { +#undef rb_intern VALUE mZlib, cZStream, cDeflate, cInflate; #if GZIP_SUPPORT VALUE cGzipFile, cGzipWriter, cGzipReader; #endif @@ -4842,7 +4875,5 @@ * Document-class: Zlib::GzipFile::LengthError * * Raised when the data length recorded in the gzip file footer is not equivalent * to the length of the actual uncompressed data. */ - -