diff --git a/ext/pg.c b/ext/pg.c index 67969b1cd..e6e4ef1ac 100644 --- a/ext/pg.c +++ b/ext/pg.c @@ -212,10 +212,10 @@ pg_get_rb_encoding_as_pg_encoding( rb_encoding *enc ) * */ char * -pg_rb_str_ensure_capa( VALUE str, long expand_len, char *curr_ptr, char **end_ptr ) +pg_rb_str_ensure_capa( VALUE str, size_t expand_len, char *curr_ptr, char **end_ptr ) { - long curr_len = curr_ptr - RSTRING_PTR(str); - long curr_capa = rb_str_capacity( str ); + size_t curr_len = curr_ptr - RSTRING_PTR(str); + size_t curr_capa = rb_str_capacity( str ); if( curr_capa < curr_len + expand_len ){ rb_str_set_len( str, curr_len ); rb_str_modify_expand( str, (curr_len + expand_len) * 2 - curr_capa ); diff --git a/ext/pg.h b/ext/pg.h index 58fa630d2..825eaf8eb 100644 --- a/ext/pg.h +++ b/ext/pg.h @@ -319,7 +319,7 @@ VALUE pg_tmbc_allocate _(( void )); void pg_coder_init_encoder _(( VALUE )); void pg_coder_init_decoder _(( VALUE )); void pg_coder_compact _(( void * )); -char *pg_rb_str_ensure_capa _(( VALUE, long, char *, char ** )); +char *pg_rb_str_ensure_capa _(( VALUE, size_t, char *, char ** )); #define PG_RB_STR_ENSURE_CAPA( str, expand_len, curr_ptr, end_ptr ) \ do { \ diff --git a/ext/pg_copy_coder.c b/ext/pg_copy_coder.c index 28bbdab39..6d99d29e4 100644 --- a/ext/pg_copy_coder.c +++ b/ext/pg_copy_coder.c @@ -220,7 +220,7 @@ pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermedia t_pg_copycoder *this = (t_pg_copycoder *)conv; t_pg_coder_enc_func enc_func; static t_pg_coder *p_elem_coder; - int i; + long i; t_typemap *p_typemap; char *current_out; char *end_capa_ptr; @@ -265,7 +265,7 @@ pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermedia strlen = RSTRING_LENINT(subint); /* size of string assuming the worst case, that every character must be escaped. */ - PG_RB_STR_ENSURE_CAPA( *intermediate, strlen * 2, current_out, end_capa_ptr ); + PG_RB_STR_ENSURE_CAPA( *intermediate, (size_t)strlen * 2, current_out, end_capa_ptr ); /* Copy string from subint with backslash escaping */ for(ptr1 = RSTRING_PTR(subint); ptr1 < RSTRING_PTR(subint) + strlen; ptr1++) { @@ -278,7 +278,7 @@ pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermedia } else { /* 2nd pass for writing the data to prepared buffer */ /* size of string assuming the worst case, that every character must be escaped. */ - PG_RB_STR_ENSURE_CAPA( *intermediate, strlen * 2, current_out, end_capa_ptr ); + PG_RB_STR_ENSURE_CAPA( *intermediate, (size_t)strlen * 2, current_out, end_capa_ptr ); /* Place the unescaped string at current output position. */ strlen = enc_func(p_elem_coder, entry, current_out, &subint, enc_idx); @@ -365,7 +365,7 @@ static int pg_bin_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx) { t_pg_copycoder *this = (t_pg_copycoder *)conv; - int i; + long i; t_typemap *p_typemap; char *current_out; char *end_capa_ptr; @@ -409,7 +409,7 @@ pg_bin_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediat /* we can directly use String value in subint */ strlen = RSTRING_LENINT(subint); - PG_RB_STR_ENSURE_CAPA( *intermediate, 4 + strlen, current_out, end_capa_ptr ); + PG_RB_STR_ENSURE_CAPA( *intermediate, (size_t)4 + strlen, current_out, end_capa_ptr ); /* 4 bytes length */ write_nbo32(strlen, current_out); current_out += 4; @@ -418,7 +418,7 @@ pg_bin_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediat current_out += strlen; } else { /* 2nd pass for writing the data to prepared buffer */ - PG_RB_STR_ENSURE_CAPA( *intermediate, 4 + strlen, current_out, end_capa_ptr ); + PG_RB_STR_ENSURE_CAPA( *intermediate, (size_t)4 + strlen, current_out, end_capa_ptr ); /* 4 bytes length */ write_nbo32(strlen, current_out); current_out += 4; @@ -553,7 +553,7 @@ pg_text_dec_copy_row(t_pg_coder *conv, const char *input_line, int len, int _tup int found_delim = 0; const char *start_ptr; const char *end_ptr; - long input_len; + size_t input_len; /* Remember start of field on input side */ start_ptr = cur_ptr; @@ -688,7 +688,7 @@ pg_text_dec_copy_row(t_pg_coder *conv, const char *input_line, int len, int _tup /* Check whether raw input matched null marker */ input_len = end_ptr - start_ptr; - if (input_len == RSTRING_LEN(this->null_string) && + if (input_len == (size_t)RSTRING_LEN(this->null_string) && strncmp(start_ptr, RSTRING_PTR(this->null_string), input_len) == 0) { rb_ary_push(array, Qnil); } else { @@ -830,7 +830,7 @@ pg_bin_dec_copy_row(t_pg_coder *conv, const char *input_line, int len, int _tupl array = rb_ary_new2(expected_fields); for( fieldno = 0; fieldno < nfields; fieldno++){ - long input_len; + int input_len; /* read field size */ if (line_end_ptr - cur_ptr < 4 ) goto length_error; diff --git a/spec/pg/type_spec.rb b/spec/pg/type_spec.rb index ad5e5f9b0..a48e96337 100644 --- a/spec/pg/type_spec.rb +++ b/spec/pg/type_spec.rb @@ -1369,6 +1369,13 @@ def expect_deprecated_coder_init expect( v.encoding ).to eq( Encoding::ISO_8859_1 ) expect( v ).to eq( "Héllo\n".encode(Encoding::ISO_8859_1) ) end + + it "should encode big strings" do + n = 1 << 30 + small = "A" * 100 + large = "\n".b * n + encoder.encode([small, large]) + end end context "with TypeMapByClass" do @@ -1439,6 +1446,13 @@ def expect_deprecated_coder_init expect( v.encoding ).to eq( Encoding::ISO_8859_1 ) expect( v.b ).to eq( "\x00\x01\x00\x00\x00\x05H\xE9llo".b ) end + + it "should encode big strings" do + n = 2_147_483_644 + wrapped = ((n + 4 + (1 << 31)) % (1 << 32)) - (1 << 31) + s = "A".b * n + encoder.encode([s]) + end end context "with TypeMapByClass" do