diff options
author | Peter Eisentraut <peter_e@gmx.net> | 2001-05-22 16:37:17 +0000 |
---|---|---|
committer | Peter Eisentraut <peter_e@gmx.net> | 2001-05-22 16:37:17 +0000 |
commit | efcecd9eca884776137b156a3f1f93c23b98a648 (patch) | |
tree | c4b92145e8a25105c68da19114e6952ea7d9241c /src/backend/utils/adt/varbit.c | |
parent | c84c3d8fea316359f2336be7287d7037c3b3e46c (diff) | |
download | postgresql-efcecd9eca884776137b156a3f1f93c23b98a648.tar.gz postgresql-efcecd9eca884776137b156a3f1f93c23b98a648.zip |
Make bit and bit varying types reject too long input. (They already tried
to do that, but inconsistently.) Make bit type reject too short input,
too, per SQL. Since it no longer zero pads, 'zpbit*' has been renamed to
'bit*' in the source, hence initdb.
Diffstat (limited to 'src/backend/utils/adt/varbit.c')
-rw-r--r-- | src/backend/utils/adt/varbit.c | 131 |
1 files changed, 39 insertions, 92 deletions
diff --git a/src/backend/utils/adt/varbit.c b/src/backend/utils/adt/varbit.c index 5d03683dd6b..d75d05309df 100644 --- a/src/backend/utils/adt/varbit.c +++ b/src/backend/utils/adt/varbit.c @@ -9,7 +9,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/varbit.c,v 1.17 2001/05/03 19:00:36 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/varbit.c,v 1.18 2001/05/22 16:37:16 petere Exp $ * *------------------------------------------------------------------------- */ @@ -25,10 +25,6 @@ /*---------- - * Prefixes: - * zp -- zero-padded fixed length bit string - * var -- varying bit string - * * attypmod -- contains the length of the bit string in bits, or for * varying bits the maximum length. * @@ -42,13 +38,13 @@ */ /* - * zpbit_in - + * bit_in - * converts a char string to the internal representation of a bitstring. * The length is determined by the number of bits required plus * VARHDRSZ bytes or from atttypmod. */ Datum -zpbit_in(PG_FUNCTION_ARGS) +bit_in(PG_FUNCTION_ARGS) { char *input_string = PG_GETARG_CSTRING(0); @@ -64,8 +60,7 @@ zpbit_in(PG_FUNCTION_ARGS) bitlen, /* Number of bits in the bit string */ slen; /* Length of the input string */ bool bit_not_hex; /* false = hex string true = bit string */ - int bc, - ipad; + int bc; bits8 x = 0; /* Check that the first character is a b or an x */ @@ -99,15 +94,12 @@ zpbit_in(PG_FUNCTION_ARGS) /* * Sometimes atttypmod is not supplied. If it is supplied we need to - * make sure that the bitstring fits. Note that the number of infered - * bits can be larger than the number of actual bits needed, but only - * if we are reading a hex string and not by more than 3 bits, as a - * hex string gives an accurate length up to 4 bits + * make sure that the bitstring fits. */ if (atttypmod <= 0) atttypmod = bitlen; - else if (bit_not_hex ? (bitlen > atttypmod) : (bitlen > atttypmod + 3)) - elog(ERROR, "zpbit_in: bit string too long for bit(%d)", + else if (bitlen != atttypmod) + elog(ERROR, "bit string length does not match type bit(%d)", atttypmod); len = VARBITTOTALLEN(atttypmod); @@ -128,7 +120,7 @@ zpbit_in(PG_FUNCTION_ARGS) if (*sp == '1') *r |= x; else if (*sp != '0') - elog(ERROR, "Cannot parse %c as a binary digit", *sp); + elog(ERROR, "cannot parse %c as a binary digit", *sp); x >>= 1; if (x == 0) { @@ -149,7 +141,7 @@ zpbit_in(PG_FUNCTION_ARGS) else if (*sp >= 'a' && *sp <= 'f') x = (bits8) (*sp - 'a') + 10; else - elog(ERROR, "Cannot parse %c as a hex digit", *sp); + elog(ERROR, "cannot parse %c as a hex digit", *sp); if (bc) { *r++ |= x; @@ -163,31 +155,12 @@ zpbit_in(PG_FUNCTION_ARGS) } } - if (bitlen > atttypmod) - { - /* Check that this fitted */ - r = VARBITEND(result) - 1; - ipad = VARBITPAD(result); - - /* - * The bottom ipad bits of the byte pointed to by r need to be - * zero - */ - if (((*r << (BITS_PER_BYTE - ipad)) & BITMASK) != 0) - elog(ERROR, "zpbit_in: bit string too long for bit(%d)", - atttypmod); - } - PG_RETURN_VARBIT_P(result); } -/* zpbit_out - - * for the time being we print everything as hex strings, as this is likely - * to be more compact than bit strings, and consequently much more efficient - * for long strings - */ + Datum -zpbit_out(PG_FUNCTION_ARGS) +bit_out(PG_FUNCTION_ARGS) { #if 1 /* same as varbit output */ @@ -228,69 +201,59 @@ zpbit_out(PG_FUNCTION_ARGS) #endif } -/* zpbit() +/* bit() * Converts a bit() type to a specific internal length. * len is the bitlength specified in the column definition. */ Datum -zpbit(PG_FUNCTION_ARGS) +bit(PG_FUNCTION_ARGS) { VarBit *arg = PG_GETARG_VARBIT_P(0); int32 len = PG_GETARG_INT32(1); - VarBit *result; - int rlen; /* No work if typmod is invalid or supplied data matches it already */ if (len <= 0 || len == VARBITLEN(arg)) PG_RETURN_VARBIT_P(arg); - - rlen = VARBITTOTALLEN(len); - result = (VarBit *) palloc(rlen); - /* set to 0 so that result is zero-padded if input is shorter */ - memset(result, 0, rlen); - VARATT_SIZEP(result) = rlen; - VARBITLEN(result) = len; - - memcpy(VARBITS(result), VARBITS(arg), - Min(VARBITBYTES(result), VARBITBYTES(arg))); - - PG_RETURN_VARBIT_P(result); + else + elog(ERROR, "bit string length does not match type bit(%d)", + len); + return 0; /* quiet compiler */ } -/* _zpbit() +/* _bit() * Converts an array of bit() elements to a specific internal length. * len is the bitlength specified in the column definition. */ Datum -_zpbit(PG_FUNCTION_ARGS) +_bit(PG_FUNCTION_ARGS) { ArrayType *v = (ArrayType *) PG_GETARG_VARLENA_P(0); int32 len = PG_GETARG_INT32(1); FunctionCallInfoData locfcinfo; /* - * Since zpbit() is a built-in function, we should only need to look + * Since bit() is a built-in function, we should only need to look * it up once per run. */ - static FmgrInfo zpbit_finfo; + static FmgrInfo bit_finfo; - if (zpbit_finfo.fn_oid == InvalidOid) - fmgr_info(F_ZPBIT, &zpbit_finfo); + if (bit_finfo.fn_oid == InvalidOid) + fmgr_info(F_BIT, &bit_finfo); MemSet(&locfcinfo, 0, sizeof(locfcinfo)); - locfcinfo.flinfo = &zpbit_finfo; + locfcinfo.flinfo = &bit_finfo; locfcinfo.nargs = 2; /* We assume we are "strict" and need not worry about null inputs */ locfcinfo.arg[0] = PointerGetDatum(v); locfcinfo.arg[1] = Int32GetDatum(len); - return array_map(&locfcinfo, ZPBITOID, ZPBITOID); + return array_map(&locfcinfo, BITOID, BITOID); } /* * varbit_in - * converts a string to the internal representation of a bitstring. - * This is the same as zpbit_in except that atttypmod is taken as + * This is the same as bit_in except that atttypmod is taken as * the maximum length, not the exact length to force the bitstring to. */ Datum @@ -310,8 +273,7 @@ varbit_in(PG_FUNCTION_ARGS) bitlen, /* Number of bits in the bit string */ slen; /* Length of the input string */ bool bit_not_hex; /* false = hex string true = bit string */ - int bc, - ipad; + int bc; bits8 x = 0; /* Check that the first character is a b or an x */ @@ -340,15 +302,12 @@ varbit_in(PG_FUNCTION_ARGS) /* * Sometimes atttypmod is not supplied. If it is supplied we need to - * make sure that the bitstring fits. Note that the number of infered - * bits can be larger than the number of actual bits needed, but only - * if we are reading a hex string and not by more than 3 bits, as a - * hex string gives an accurate length up to 4 bits + * make sure that the bitstring fits. */ if (atttypmod <= 0) atttypmod = bitlen; - else if (bit_not_hex ? (bitlen > atttypmod) : (bitlen > atttypmod + 3)) - elog(ERROR, "varbit_in: bit string too long for bit varying(%d)", + else if (bitlen > atttypmod) + elog(ERROR, "bit string too long for type bit varying(%d)", atttypmod); len = VARBITTOTALLEN(bitlen); @@ -369,7 +328,7 @@ varbit_in(PG_FUNCTION_ARGS) if (*sp == '1') *r |= x; else if (*sp != '0') - elog(ERROR, "Cannot parse %c as a binary digit", *sp); + elog(ERROR, "cannot parse %c as a binary digit", *sp); x >>= 1; if (x == 0) { @@ -390,7 +349,7 @@ varbit_in(PG_FUNCTION_ARGS) else if (*sp >= 'a' && *sp <= 'f') x = (bits8) (*sp - 'a') + 10; else - elog(ERROR, "Cannot parse %c as a hex digit", *sp); + elog(ERROR, "cannot parse %c as a hex digit", *sp); if (bc) { *r++ |= x; @@ -404,21 +363,6 @@ varbit_in(PG_FUNCTION_ARGS) } } - if (bitlen > atttypmod) - { - /* Check that this fitted */ - r = VARBITEND(result) - 1; - ipad = VARBITPAD(result); - - /* - * The bottom ipad bits of the byte pointed to by r need to be - * zero - */ - if (((*r << (BITS_PER_BYTE - ipad)) & BITMASK) != 0) - elog(ERROR, "varbit_in: bit string too long for bit varying(%d)", - atttypmod); - } - PG_RETURN_VARBIT_P(result); } @@ -477,6 +421,9 @@ varbit(PG_FUNCTION_ARGS) if (len <= 0 || len >= VARBITLEN(arg)) PG_RETURN_VARBIT_P(arg); + if (len < VARBITLEN(arg)) + elog(ERROR, "bit string too long for type bit varying(%d)", len); + rlen = VARBITTOTALLEN(len); result = (VarBit *) palloc(rlen); VARATT_SIZEP(result) = rlen; @@ -868,7 +815,7 @@ bitand(PG_FUNCTION_ARGS) bitlen1 = VARBITLEN(arg1); bitlen2 = VARBITLEN(arg2); if (bitlen1 != bitlen2) - elog(ERROR, "bitand: Cannot AND bitstrings of different sizes"); + elog(ERROR, "cannot AND bit strings of different sizes"); len = VARSIZE(arg1); result = (VarBit *) palloc(len); VARATT_SIZEP(result) = len; @@ -906,7 +853,7 @@ bitor(PG_FUNCTION_ARGS) bitlen1 = VARBITLEN(arg1); bitlen2 = VARBITLEN(arg2); if (bitlen1 != bitlen2) - elog(ERROR, "bitor: Cannot OR bitstrings of different sizes"); + elog(ERROR, "cannot OR bit strings of different sizes"); len = VARSIZE(arg1); result = (VarBit *) palloc(len); VARATT_SIZEP(result) = len; @@ -950,7 +897,7 @@ bitxor(PG_FUNCTION_ARGS) bitlen1 = VARBITLEN(arg1); bitlen2 = VARBITLEN(arg2); if (bitlen1 != bitlen2) - elog(ERROR, "bitxor: Cannot XOR bitstrings of different sizes"); + elog(ERROR, "cannot XOR bit strings of different sizes"); len = VARSIZE(arg1); result = (VarBit *) palloc(len); VARATT_SIZEP(result) = len; @@ -1165,7 +1112,7 @@ bittoint4(PG_FUNCTION_ARGS) /* Check that the bit string is not too long */ if (VARBITLEN(arg) > sizeof(int4) * BITS_PER_BYTE) - elog(ERROR, "Bit string is too large to fit in an int4"); + elog(ERROR, "bit string is too large to fit in type integer"); result = 0; for (r = VARBITS(arg); r < VARBITEND(arg); r++) { |