mirror of
https://github.com/postgres/postgres.git
synced 2025-04-21 12:05:57 +03:00
Code review for array_fill patch: fix inadequate check for array size overflow
and bogus documentation (dimension arrays are int[] not anyarray). Also the errhint() messages seem to be really errdetail(), since there is nothing heuristic about them. Some other trivial cosmetic improvements.
This commit is contained in:
parent
673a30fbb2
commit
5618ece82b
@ -1,4 +1,4 @@
|
|||||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.442 2008/07/18 03:32:51 tgl Exp $ -->
|
<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.443 2008/07/21 04:47:00 tgl Exp $ -->
|
||||||
|
|
||||||
<chapter id="functions">
|
<chapter id="functions">
|
||||||
<title>Functions and Operators</title>
|
<title>Functions and Operators</title>
|
||||||
@ -9186,17 +9186,16 @@ SELECT NULLIF(value, '(none)') ...
|
|||||||
</sect2>
|
</sect2>
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
|
|
||||||
<sect1 id="functions-array">
|
<sect1 id="functions-array">
|
||||||
<title>Array Functions and Operators</title>
|
<title>Array Functions and Operators</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<xref linkend="array-operators-table"> shows the operators
|
<xref linkend="array-operators-table"> shows the operators
|
||||||
available for <type>array</type> types.
|
available for array types.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<table id="array-operators-table">
|
<table id="array-operators-table">
|
||||||
<title><type>array</type> Operators</title>
|
<title>Array Operators</title>
|
||||||
<tgroup cols="4">
|
<tgroup cols="4">
|
||||||
<thead>
|
<thead>
|
||||||
<row>
|
<row>
|
||||||
@ -9326,7 +9325,7 @@ SELECT NULLIF(value, '(none)') ...
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<table id="array-functions-table">
|
<table id="array-functions-table">
|
||||||
<title><type>array</type> Functions</title>
|
<title>Array Functions</title>
|
||||||
<tgroup cols="5">
|
<tgroup cols="5">
|
||||||
<thead>
|
<thead>
|
||||||
<row>
|
<row>
|
||||||
@ -9374,13 +9373,13 @@ SELECT NULLIF(value, '(none)') ...
|
|||||||
<row>
|
<row>
|
||||||
<entry>
|
<entry>
|
||||||
<literal>
|
<literal>
|
||||||
<function>array_fill</function>(<type>anyelement</type>, <type>anyarray</type>,
|
<function>array_fill</function>(<type>anyelement</type>, <type>int[]</type>,
|
||||||
<optional>, <type>anyarray</type></optional>)
|
<optional>, <type>int[]</type></optional>)
|
||||||
</literal>
|
</literal>
|
||||||
</entry>
|
</entry>
|
||||||
<entry><type>anyarray</type></entry>
|
<entry><type>anyarray</type></entry>
|
||||||
<entry>returns an array initialized with supplied value,
|
<entry>returns an array initialized with supplied value and
|
||||||
dimensions, and lower bounds</entry>
|
dimensions, optionally with lower bounds other than 1</entry>
|
||||||
<entry><literal>array_fill(7, ARRAY[3], ARRAY[2])</literal></entry>
|
<entry><literal>array_fill(7, ARRAY[3], ARRAY[2])</literal></entry>
|
||||||
<entry><literal>[2:4]={7,7,7}</literal></entry>
|
<entry><literal>[2:4]={7,7,7}</literal></entry>
|
||||||
</row>
|
</row>
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.146 2008/07/16 00:48:53 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.147 2008/07/21 04:47:00 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -97,8 +97,8 @@ static void array_insert_slice(ArrayType *destArray, ArrayType *origArray,
|
|||||||
static int array_cmp(FunctionCallInfo fcinfo);
|
static int array_cmp(FunctionCallInfo fcinfo);
|
||||||
static ArrayType *create_array_envelope(int ndims, int *dimv, int *lbv, int nbytes,
|
static ArrayType *create_array_envelope(int ndims, int *dimv, int *lbv, int nbytes,
|
||||||
Oid elmtype, int dataoffset);
|
Oid elmtype, int dataoffset);
|
||||||
static ArrayType *array_fill_internal(ArrayType *dims, ArrayType *lbs, Datum value,
|
static ArrayType *array_fill_internal(ArrayType *dims, ArrayType *lbs,
|
||||||
Oid elmtype, bool isnull,
|
Datum value, bool isnull, Oid elmtype,
|
||||||
FunctionCallInfo fcinfo);
|
FunctionCallInfo fcinfo);
|
||||||
|
|
||||||
|
|
||||||
@ -4357,7 +4357,7 @@ array_fill_with_lower_bounds(PG_FUNCTION_ARGS)
|
|||||||
if (!OidIsValid(elmtype))
|
if (!OidIsValid(elmtype))
|
||||||
elog(ERROR, "could not determine data type of input");
|
elog(ERROR, "could not determine data type of input");
|
||||||
|
|
||||||
result = array_fill_internal(dims, lbs, value, elmtype, isnull, fcinfo);
|
result = array_fill_internal(dims, lbs, value, isnull, elmtype, fcinfo);
|
||||||
PG_RETURN_ARRAYTYPE_P(result);
|
PG_RETURN_ARRAYTYPE_P(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4396,7 +4396,7 @@ array_fill(PG_FUNCTION_ARGS)
|
|||||||
if (!OidIsValid(elmtype))
|
if (!OidIsValid(elmtype))
|
||||||
elog(ERROR, "could not determine data type of input");
|
elog(ERROR, "could not determine data type of input");
|
||||||
|
|
||||||
result = array_fill_internal(dims, NULL, value, elmtype, isnull, fcinfo);
|
result = array_fill_internal(dims, NULL, value, isnull, elmtype, fcinfo);
|
||||||
PG_RETURN_ARRAYTYPE_P(result);
|
PG_RETURN_ARRAYTYPE_P(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4418,8 +4418,8 @@ create_array_envelope(int ndims, int *dimv, int *lbsv, int nbytes,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static ArrayType *
|
static ArrayType *
|
||||||
array_fill_internal(ArrayType *dims, ArrayType *lbs, Datum value,
|
array_fill_internal(ArrayType *dims, ArrayType *lbs,
|
||||||
Oid elmtype, bool isnull,
|
Datum value, bool isnull, Oid elmtype,
|
||||||
FunctionCallInfo fcinfo)
|
FunctionCallInfo fcinfo)
|
||||||
{
|
{
|
||||||
ArrayType *result;
|
ArrayType *result;
|
||||||
@ -4440,13 +4440,13 @@ array_fill_internal(ArrayType *dims, ArrayType *lbs, Datum value,
|
|||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
|
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
|
||||||
errmsg("wrong number of array subscripts"),
|
errmsg("wrong number of array subscripts"),
|
||||||
errhint("Dimension array must be one dimensional.")));
|
errdetail("Dimension array must be one dimensional.")));
|
||||||
|
|
||||||
if (ARR_LBOUND(dims)[0] != 1)
|
if (ARR_LBOUND(dims)[0] != 1)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
|
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
|
||||||
errmsg("wrong range of array_subscripts"),
|
errmsg("wrong range of array_subscripts"),
|
||||||
errhint("Lower bound of dimension array must be one.")));
|
errdetail("Lower bound of dimension array must be one.")));
|
||||||
|
|
||||||
if (ARR_HASNULL(dims))
|
if (ARR_HASNULL(dims))
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
@ -4472,13 +4472,13 @@ array_fill_internal(ArrayType *dims, ArrayType *lbs, Datum value,
|
|||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
|
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
|
||||||
errmsg("wrong number of array subscripts"),
|
errmsg("wrong number of array subscripts"),
|
||||||
errhint("Dimension array must be one dimensional.")));
|
errdetail("Dimension array must be one dimensional.")));
|
||||||
|
|
||||||
if (ARR_LBOUND(lbs)[0] != 1)
|
if (ARR_LBOUND(lbs)[0] != 1)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
|
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
|
||||||
errmsg("wrong range of array_subscripts"),
|
errmsg("wrong range of array_subscripts"),
|
||||||
errhint("Lower bound of dimension array must be one.")));
|
errdetail("Lower bound of dimension array must be one.")));
|
||||||
|
|
||||||
if (ARR_HASNULL(lbs))
|
if (ARR_HASNULL(lbs))
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
@ -4489,7 +4489,7 @@ array_fill_internal(ArrayType *dims, ArrayType *lbs, Datum value,
|
|||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
|
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
|
||||||
errmsg("wrong number of array_subscripts"),
|
errmsg("wrong number of array_subscripts"),
|
||||||
errhint("Low bound array has different size than dimensions array.")));
|
errdetail("Low bound array has different size than dimensions array.")));
|
||||||
|
|
||||||
lbsv = (int *) ARR_DATA_PTR(lbs);
|
lbsv = (int *) ARR_DATA_PTR(lbs);
|
||||||
}
|
}
|
||||||
@ -4509,7 +4509,6 @@ array_fill_internal(ArrayType *dims, ArrayType *lbs, Datum value,
|
|||||||
|
|
||||||
nitems = ArrayGetNItems(ndims, dimv);
|
nitems = ArrayGetNItems(ndims, dimv);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We arrange to look up info about element type only once per series of
|
* We arrange to look up info about element type only once per series of
|
||||||
* calls, assuming the element type doesn't change underneath us.
|
* calls, assuming the element type doesn't change underneath us.
|
||||||
@ -4543,7 +4542,7 @@ array_fill_internal(ArrayType *dims, ArrayType *lbs, Datum value,
|
|||||||
int i;
|
int i;
|
||||||
char *p;
|
char *p;
|
||||||
int nbytes;
|
int nbytes;
|
||||||
Datum aux_value = value;
|
int totbytes;
|
||||||
|
|
||||||
/* make sure data is not toasted */
|
/* make sure data is not toasted */
|
||||||
if (elmlen == -1)
|
if (elmlen == -1)
|
||||||
@ -4551,39 +4550,43 @@ array_fill_internal(ArrayType *dims, ArrayType *lbs, Datum value,
|
|||||||
|
|
||||||
nbytes = att_addlength_datum(0, elmlen, value);
|
nbytes = att_addlength_datum(0, elmlen, value);
|
||||||
nbytes = att_align_nominal(nbytes, elmalign);
|
nbytes = att_align_nominal(nbytes, elmalign);
|
||||||
|
Assert(nbytes > 0);
|
||||||
|
|
||||||
nbytes *= nitems;
|
totbytes = nbytes * nitems;
|
||||||
/* check for overflow of total request */
|
|
||||||
if (!AllocSizeIsValid(nbytes))
|
/* check for overflow of multiplication or total request */
|
||||||
|
if (totbytes / nbytes != nitems ||
|
||||||
|
!AllocSizeIsValid(totbytes))
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
||||||
errmsg("array size exceeds the maximum allowed (%d)",
|
errmsg("array size exceeds the maximum allowed (%d)",
|
||||||
(int) MaxAllocSize)));
|
(int) MaxAllocSize)));
|
||||||
|
|
||||||
nbytes += ARR_OVERHEAD_NONULLS(ndims);
|
/*
|
||||||
result = create_array_envelope(ndims, dimv, lbsv, nbytes,
|
* This addition can't overflow, but it might cause us to go past
|
||||||
|
* MaxAllocSize. We leave it to palloc to complain in that case.
|
||||||
|
*/
|
||||||
|
totbytes += ARR_OVERHEAD_NONULLS(ndims);
|
||||||
|
|
||||||
|
result = create_array_envelope(ndims, dimv, lbsv, totbytes,
|
||||||
elmtype, 0);
|
elmtype, 0);
|
||||||
|
|
||||||
p = ARR_DATA_PTR(result);
|
p = ARR_DATA_PTR(result);
|
||||||
for (i = 0; i < nitems; i++)
|
for (i = 0; i < nitems; i++)
|
||||||
p += ArrayCastAndSet(value, elmlen, elmbyval, elmalign, p);
|
p += ArrayCastAndSet(value, elmlen, elmbyval, elmalign, p);
|
||||||
|
|
||||||
/* cleaning up detoasted copies of datum */
|
|
||||||
if (aux_value != value)
|
|
||||||
pfree((Pointer) value);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int nbytes;
|
int nbytes;
|
||||||
int dataoffset;
|
int dataoffset;
|
||||||
bits8 *bitmap;
|
|
||||||
|
|
||||||
dataoffset = ARR_OVERHEAD_WITHNULLS(ndims, nitems);
|
dataoffset = ARR_OVERHEAD_WITHNULLS(ndims, nitems);
|
||||||
nbytes = dataoffset;
|
nbytes = dataoffset;
|
||||||
|
|
||||||
result = create_array_envelope(ndims, dimv, lbsv, nbytes,
|
result = create_array_envelope(ndims, dimv, lbsv, nbytes,
|
||||||
elmtype, dataoffset);
|
elmtype, dataoffset);
|
||||||
bitmap = ARR_NULLBITMAP(result);
|
|
||||||
MemSet(bitmap, 0, (nitems + 7) / 8);
|
/* create_array_envelope already zeroed the bitmap, so we're done */
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -988,6 +988,6 @@ select array_fill(1, array[2,2], null);
|
|||||||
ERROR: dimension array or low bound array cannot be NULL
|
ERROR: dimension array or low bound array cannot be NULL
|
||||||
select array_fill(1, array[3,3], array[1,1,1]);
|
select array_fill(1, array[3,3], array[1,1,1]);
|
||||||
ERROR: wrong number of array_subscripts
|
ERROR: wrong number of array_subscripts
|
||||||
HINT: Low bound array has different size than dimensions array.
|
DETAIL: Low bound array has different size than dimensions array.
|
||||||
select array_fill(1, array[1,2,null]);
|
select array_fill(1, array[1,2,null]);
|
||||||
ERROR: dimension values cannot be null
|
ERROR: dimension values cannot be null
|
||||||
|
Loading…
x
Reference in New Issue
Block a user