diff --git a/src/backend/utils/adt/encode.c b/src/backend/utils/adt/encode.c index b8d9ec7e00..d0cbbb272b 100644 --- a/src/backend/utils/adt/encode.c +++ b/src/backend/utils/adt/encode.c @@ -20,9 +20,9 @@ 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); + int64 (*encode) (const char *data, unsigned dlen, char *res); unsigned (*decode) (const char *data, unsigned dlen, char *res); }; @@ -39,9 +39,8 @@ binary_encode(PG_FUNCTION_ARGS) Datum name = PG_GETARG_DATUM(1); text *result; char *namebuf; - int datalen, - resultlen, - res; + int datalen; + int64 res,resultlen; const struct pg_encoding *enc; datalen = VARSIZE_ANY_EXHDR(data); @@ -76,8 +75,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); @@ -122,7 +121,7 @@ static const int8 hexlookup[128] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }; -unsigned +int64 hex_encode(const char *src, unsigned len, char *dst) { const char *end = src + len; @@ -133,7 +132,7 @@ hex_encode(const char *src, unsigned len, char *dst) *dst++ = hextbl[*src & 0xF]; src++; } - return len * 2; + return (int64)len * 2; } static inline char @@ -184,10 +183,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 @@ -214,7 +213,7 @@ static const int8 b64lookup[128] = { 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, }; -static unsigned +static int64 pg_base64_encode(const char *src, unsigned len, char *dst) { char *p, @@ -331,11 +330,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 + (int64)srclen / (76 * 3 / 4); } static unsigned @@ -361,12 +360,12 @@ pg_base64_dec_len(const char *src, unsigned srclen) #define VAL(CH) ((CH) - '0') #define DIG(VAL) ((VAL) + '0') -static unsigned +static int64 esc_encode(const char *src, unsigned srclen, char *dst) { const char *end = src + srclen; char *rp = dst; - int len = 0; + int64 len = 0; while (src < end) { @@ -448,11 +447,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/varbit.c b/src/backend/utils/adt/varbit.c index c3257553bd..e1bcd0cc66 100644 --- a/src/backend/utils/adt/varbit.c +++ b/src/backend/utils/adt/varbit.c @@ -1787,7 +1787,7 @@ Datum bitsetbit(PG_FUNCTION_ARGS) { VarBit *arg1 = PG_GETARG_VARBIT_P(0); - int32 n = PG_GETARG_INT32(1); + int64 n = PG_GETARG_INT64(1); int32 newBit = PG_GETARG_INT32(2); VarBit *result; int len, @@ -1798,10 +1798,10 @@ bitsetbit(PG_FUNCTION_ARGS) bitNo; bitlen = VARBITLEN(arg1); - if (n < 0 || n >= bitlen) + if (n < 0 || n >= (int64)bitlen) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), - errmsg("bit index %d out of valid range (0..%d)", + errmsg("bit index "INT64_FORMAT" out of valid range (0..%d)", n, bitlen - 1))); /* @@ -1822,8 +1822,8 @@ bitsetbit(PG_FUNCTION_ARGS) memcpy(r, p, VARBITBYTES(arg1)); - byteNo = n / BITS_PER_BYTE; - bitNo = BITS_PER_BYTE - 1 - (n % BITS_PER_BYTE); + byteNo = (int32)(n / BITS_PER_BYTE); + bitNo = BITS_PER_BYTE - 1 - (int32)(n % BITS_PER_BYTE); /* * Update the byte. @@ -1849,23 +1849,23 @@ Datum bitgetbit(PG_FUNCTION_ARGS) { VarBit *arg1 = PG_GETARG_VARBIT_P(0); - int32 n = PG_GETARG_INT32(1); + int64 n = PG_GETARG_INT64(1); int bitlen; bits8 *p; int byteNo, bitNo; bitlen = VARBITLEN(arg1); - if (n < 0 || n >= bitlen) + if (n < 0 || n >= (int64)bitlen) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), - errmsg("bit index %d out of valid range (0..%d)", + errmsg("bit index "INT64_FORMAT" out of valid range (0..%d)", n, bitlen - 1))); p = VARBITS(arg1); - byteNo = n / BITS_PER_BYTE; - bitNo = BITS_PER_BYTE - 1 - (n % BITS_PER_BYTE); + byteNo = (int32)(n / BITS_PER_BYTE); + bitNo = BITS_PER_BYTE - 1 - (int32)(n % BITS_PER_BYTE); if (p[byteNo] & (1 << bitNo)) PG_RETURN_INT32(1); diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c index 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/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 7fb574f9dc..e3c819e46d 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -3810,10 +3810,10 @@ proname => 'overlay', prorettype => 'bit', proargtypes => 'bit bit int4', prosrc => 'bitoverlay_no_len' }, { oid => '3032', descr => 'get bit', - proname => 'get_bit', prorettype => 'int4', proargtypes => 'bit int4', + proname => 'get_bit', prorettype => 'int4', proargtypes => 'bit int8', prosrc => 'bitgetbit' }, { oid => '3033', descr => 'set bit', - proname => 'set_bit', prorettype => 'bit', proargtypes => 'bit int4 int4', + proname => 'set_bit', prorettype => 'bit', proargtypes => 'bit int8 int4', prosrc => 'bitsetbit' }, # for macaddr type support diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index e2016a8bc2..40cf539401 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -32,7 +32,7 @@ extern int errdatatype(Oid datatypeOid); extern int errdomainconstraint(Oid datatypeOid, const char *conname); /* encode.c */ -extern unsigned hex_encode(const char *src, unsigned len, char *dst); +extern int64 hex_encode(const char *src, unsigned len, char *dst); extern unsigned hex_decode(const char *src, unsigned len, char *dst); /* int.c */ diff --git a/src/test/regress/expected/bit.out b/src/test/regress/expected/bit.out index a1fab7ebcb..06d100dbdf 100644 --- a/src/test/regress/expected/bit.out +++ b/src/test/regress/expected/bit.out @@ -656,6 +656,38 @@ 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) + +select get_bit( + set_bit((repeat('Postgres', 512 * 1024 * 1024 / 8))::bytea, 1024 * 1024 * 1024 + 1, 0) + ,1024 * 1024 * 1024 + 1); + get_bit +--------- + 0 +(1 row) + +select get_bit( + set_bit((repeat('Postgres', 512 * 1024 * 1024 / 8))::bytea, 1024 * 1024 * 1024 + 1, 1) + ,1024 * 1024 * 1024 + 1); + 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.sql index 7681d4ab4d..5ef4aa42da 100644 --- a/src/test/regress/sql/bit.sql +++ b/src/test/regress/sql/bit.sql @@ -200,6 +200,19 @@ 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); +select get_bit( + set_bit((repeat('Postgres', 512 * 1024 * 1024 / 8))::bytea, 1024 * 1024 * 1024 + 1, 0) + ,1024 * 1024 * 1024 + 1); +select get_bit( + set_bit((repeat('Postgres', 512 * 1024 * 1024 / 8))::bytea, 1024 * 1024 * 1024 + 1, 1) + ,1024 * 1024 * 1024 + 1); + -- Overlay SELECT overlay(B'0101011100' placing '001' from 2 for 3);