From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: AS43350 77.247.176.0/21 X-Spam-Status: No, score=-3.3 required=3.0 tests=AWL,BAYES_00, RCVD_IN_MSPIKE_BL,RCVD_IN_MSPIKE_ZBI,RCVD_IN_XBL,SPF_FAIL,SPF_HELO_FAIL, TO_EQ_FM_DOM_SPF_FAIL shortcircuit=no autolearn=no autolearn_force=no version=3.4.0 Received: from 80x24.org (lumumba.torservers.net [77.247.181.163]) by dcvr.yhbt.net (Postfix) with ESMTP id E317820357 for ; Fri, 14 Jul 2017 21:09:20 +0000 (UTC) From: Eric Wong To: spew@80x24.org Subject: [PATCH] prevent premature GC of string buffer in parse_pg_array Date: Fri, 14 Jul 2017 21:09:18 +0000 Message-Id: <20170714210918.3332-1-e@80x24.org> List-Id: To ensure objects are properly marked, RB_GC_GUARD must be placed after the last use of pointers accessed from the object (in this case, the result of RSTRING_PTR). So, instead of passing the result of RSTRING_PTR to read_array, pass the String object itself and move the RB_GC_GUARD to the end of the read_array function. Warning: I've only compile-tested, not actually run since there's no tests bundled. Sidenote: I'm fairly sure the rest of the existing RB_GC_GUARD calls are unnecessary. --- ext/sequel_pg/sequel_pg.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/ext/sequel_pg/sequel_pg.c b/ext/sequel_pg/sequel_pg.c index 4cb4a0f..1f1d687 100644 --- a/ext/sequel_pg/sequel_pg.c +++ b/ext/sequel_pg/sequel_pg.c @@ -127,13 +127,14 @@ static int enc_get_index(VALUE val) } #endif -static VALUE read_array(int *index, char *c_pg_array_string, int array_string_length, char *word, VALUE converter +static VALUE read_array(int *index, char *c_pg_array_string, int array_string_length, VALUE buf, VALUE converter #ifdef SPG_ENCODING , int enc_index #endif ) { int word_index = 0; + char *word = RSTRING_PTR(buf); /* The current character in the input string. */ char c; @@ -203,7 +204,7 @@ static VALUE read_array(int *index, char *c_pg_array_string, int array_string_le else if(c == '{') { (*index)++; - rb_ary_push(array, read_array(index, c_pg_array_string, array_string_length, word, converter + rb_ary_push(array, read_array(index, c_pg_array_string, array_string_length, buf, converter #ifdef SPG_ENCODING , enc_index #endif @@ -236,6 +237,8 @@ static VALUE read_array(int *index, char *c_pg_array_string, int array_string_le } } + RB_GC_GUARD(buf); + return array; } @@ -246,8 +249,6 @@ static VALUE parse_pg_array(VALUE self, VALUE pg_array_string, VALUE converter) char *c_pg_array_string = StringValueCStr(pg_array_string); int array_string_length = RSTRING_LEN(pg_array_string); VALUE buf = rb_str_buf_new(array_string_length); - RB_GC_GUARD(buf); - char *word = RSTRING_PTR(buf); int index = 1; if (array_string_length == 0) { @@ -271,7 +272,7 @@ static VALUE parse_pg_array(VALUE self, VALUE pg_array_string, VALUE converter) rb_raise(rb_eArgError, "unexpected PostgreSQL array format, doesn't start with { or ["); } - return read_array(&index, c_pg_array_string, array_string_length, word, converter + return read_array(&index, c_pg_array_string, array_string_length, buf, converter #ifdef SPG_ENCODING , enc_get_index(pg_array_string) #endif -- EW