From: movead.li@highgo.ca <movead.li@highgo.ca>
To: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Cc: pgsql-hackers <pgsql-hackers@lists.postgresql.org>
Cc: ashutosh.bapat <ashutosh.bapat@2ndquadrant.com>
Subject: Re: Re: A bug when use get_bit() function for a long bytea string
Date: Fri, 13 Mar 2020 11:18:47 +0800
Message-ID: <20200313111842791351178@highgo.ca> (raw)
References: <20200312115135445367128@highgo.ca>
<CAExHW5vUSi4-oPvgMdFWvzuyaTmMtbY=JgdZ+u3T7ZdzQmubig@mail.gmail.com>
Thanks for the reply.
>Why have you used size? Shouldn't we use int64?
Yes, thanks for the point, I have changed the patch.
>If get_bit()/set_bit() accept the second argument as int32, it can not
>be used to set bits whose number does not fit 32 bits. I think we need
>to change the type of the second argument as well.
Because int32 can cover the length of bytea that PostgreSQL support,
and I have decided to follow your next point 'not use 64bit int for len',
so I think the second argument can keep int32.
>Also, I think declaring len to be int is fine since 1G would fit an
>int, but what does not fit is len * 8, when performing that
>calculation, we have to widen the result. So, instead of changing the
>datatype of len, it might be better to perform the calculation as
>(int64)len * 8. If we use int64, we could also use INT64_FORMAT
>instead of using %ld.
Have followed and changed the patch.
>Since this is a bug it shouldn't wait another commitfest, but still
>add this patch to the commitfest so that it's not forgotten.
Will do.
Highgo Software (Canada/China/Pakistan)
URL : www.highgo.ca
EMAIL: mailto:movead(dot)li(at)highgo(dot)ca
Attachments:
[application/octet-stream] long_bytea_string_bug_fix_ver2.patch (4.8K, ../20200313111842791351178@highgo.ca/3-long_bytea_string_bug_fix_ver2.patch)
download | inline diff:diff --git a/src/backend/utils/adt/encode.c b/src/backend/utils/adt/encode.cindex b8d9ec7e00..e56ebd707d 100644--- a/src/backend/utils/adt/encode.c+++ b/src/backend/utils/adt/encode.c@@ -20,7 +20,7 @@
struct pg_encoding
{
- unsigned (*encode_len) (const char *data, unsigned dlen);+ int64 (*encode_len) (const char *data, unsigned dlen);
unsigned (*decode_len) (const char *data, unsigned dlen);
unsigned (*encode) (const char *data, unsigned dlen, char *res);
unsigned (*decode) (const char *data, unsigned dlen, char *res);
@@ -40,8 +40,8 @@ binary_encode(PG_FUNCTION_ARGS)
text *result;
char *namebuf;
int datalen,
- resultlen,
res;
+ int64 resultlen;
const struct pg_encoding *enc;
datalen = VARSIZE_ANY_EXHDR(data);
@@ -60,7 +60,7 @@ binary_encode(PG_FUNCTION_ARGS)
res = enc->encode(VARDATA_ANY(data), datalen, VARDATA(result));
/* Make this FATAL 'cause we've trodden on memory ... */
- if (res > resultlen)+ if ((int64)res > resultlen)
elog(FATAL, "overflow - encode estimate too small");
SET_VARSIZE(result, VARHDRSZ + res);
@@ -76,8 +76,8 @@ binary_decode(PG_FUNCTION_ARGS)
bytea *result;
char *namebuf;
int datalen,
- resultlen,
res;
+ unsigned resultlen;
const struct pg_encoding *enc;
datalen = VARSIZE_ANY_EXHDR(data);
@@ -184,10 +184,10 @@ hex_decode(const char *src, unsigned len, char *dst)
return p - dst;
}
-static unsigned+static int64
hex_enc_len(const char *src, unsigned srclen)
{
- return srclen << 1;+ return (int64)(srclen << 1);
}
static unsigned
@@ -331,11 +331,11 @@ pg_base64_decode(const char *src, unsigned len, char *dst)
}
-static unsigned+static int64
pg_base64_enc_len(const char *src, unsigned srclen)
{
/* 3 bytes will be converted to 4, linefeed after 76 chars */
- return (srclen + 2) * 4 / 3 + srclen / (76 * 3 / 4);+ return (int64)((srclen + 2) * 4 / 3 + srclen / (76 * 3 / 4));
}
static unsigned
@@ -448,11 +448,11 @@ esc_decode(const char *src, unsigned srclen, char *dst)
return len;
}
-static unsigned+static int64
esc_enc_len(const char *src, unsigned srclen)
{
const char *end = src + srclen;
- int len = 0;+ int64 len = 0;
while (src < end)
{
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.cindex 907b5ab7b0..b8b06d5e32 100644--- a/src/backend/utils/adt/varlena.c+++ b/src/backend/utils/adt/varlena.c@@ -388,7 +388,7 @@ byteaout(PG_FUNCTION_ARGS)
{
/* Print traditional escaped format */
char *vp;
- int len;+ int64 len;
int i;
len = 1; /* empty string has 1 char */
@@ -3463,11 +3463,11 @@ byteaGetBit(PG_FUNCTION_ARGS)
len = VARSIZE_ANY_EXHDR(v);
- if (n < 0 || n >= len * 8)+ if (n < 0 || (int64)n >= (int64)len * 8)
ereport(ERROR,
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
- errmsg("index %d out of valid range, 0..%d",- n, len * 8 - 1)));+ errmsg("index %d out of valid range, 0.."INT64_FORMAT,+ n, (int64)len * 8 - 1)));
byteNo = n / 8;
bitNo = n % 8;
@@ -3534,11 +3534,11 @@ byteaSetBit(PG_FUNCTION_ARGS)
len = VARSIZE(res) - VARHDRSZ;
- if (n < 0 || n >= len * 8)+ if (n < 0 || (int64)n >= (int64)len * 8)
ereport(ERROR,
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
- errmsg("index %d out of valid range, 0..%d",- n, len * 8 - 1)));+ errmsg("index %d out of valid range, 0.."INT64_FORMAT,+ n, (int64)len * 8 - 1)));
byteNo = n / 8;
bitNo = n % 8;
diff --git a/src/test/regress/expected/bit.out b/src/test/regress/expected/bit.outindex a1fab7ebcb..f7fda19b97 100644--- a/src/test/regress/expected/bit.out+++ b/src/test/regress/expected/bit.out@@ -656,6 +656,22 @@ SELECT set_bit(B'0101011000100100', 15, 1);
SELECT set_bit(B'0101011000100100', 16, 1); -- fail
ERROR: bit index 16 out of valid range (0..15)
+SELECT get_bit(+ set_bit((repeat('Postgres', 512 * 1024 * 1024 / 8))::bytea, 0, 0)+ ,0);+ get_bit +---------+ 0+(1 row)++SELECT get_bit(+ set_bit((repeat('Postgres', 512 * 1024 * 1024 / 8))::bytea, 0, 1)+ ,0);+ get_bit +---------+ 1+(1 row)+
-- Overlay
SELECT overlay(B'0101011100' placing '001' from 2 for 3);
overlay
diff --git a/src/test/regress/sql/bit.sql b/src/test/regress/sql/bit.sqlindex 7681d4ab4d..89323d98e8 100644--- a/src/test/regress/sql/bit.sql+++ b/src/test/regress/sql/bit.sql@@ -200,6 +200,13 @@ DROP TABLE VARBIT_SHIFT_TABLE;
SELECT get_bit(B'0101011000100', 10);
SELECT set_bit(B'0101011000100100', 15, 1);
SELECT set_bit(B'0101011000100100', 16, 1); -- fail
+SELECT get_bit(+ set_bit((repeat('Postgres', 512 * 1024 * 1024 / 8))::bytea, 0, 0)+ ,0);+SELECT get_bit(+ set_bit((repeat('Postgres', 512 * 1024 * 1024 / 8))::bytea, 0, 1)+ ,0);+
-- Overlay
SELECT overlay(B'0101011100' placing '001' from 2 for 3);
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: pgsql-hackers@postgresql.org
Cc: movead.li@highgo.ca, ashutosh.bapat.oss@gmail.com, pgsql-hackers@lists.postgresql.org, ashutosh.bapat@2ndquadrant.com
Subject: Re: Re: A bug when use get_bit() function for a long bytea string
In-Reply-To: <20200313111842791351178@highgo.ca>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox