8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.146 2008/07/16 00:48:53 momjian Exp $
11
+ * $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.147 2008/07/21 04:47:00 tgl Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -97,9 +97,9 @@ static void array_insert_slice(ArrayType *destArray, ArrayType *origArray,
97
97
static int array_cmp (FunctionCallInfo fcinfo );
98
98
static ArrayType * create_array_envelope (int ndims , int * dimv , int * lbv , int nbytes ,
99
99
Oid elmtype , int dataoffset );
100
- static ArrayType * array_fill_internal (ArrayType * dims , ArrayType * lbs , Datum value ,
101
- Oid elmtype , bool isnull ,
102
- FunctionCallInfo fcinfo );
100
+ static ArrayType * array_fill_internal (ArrayType * dims , ArrayType * lbs ,
101
+ Datum value , bool isnull , Oid elmtype ,
102
+ FunctionCallInfo fcinfo );
103
103
104
104
105
105
/*
@@ -4245,7 +4245,7 @@ typedef struct generate_subscripts_fctx
4245
4245
bool reverse ;
4246
4246
} generate_subscripts_fctx ;
4247
4247
4248
- /*
4248
+ /*
4249
4249
* generate_subscripts(array anyarray, dim int [, reverse bool])
4250
4250
* Returns all subscripts of the array for any dimension
4251
4251
*/
@@ -4335,7 +4335,7 @@ array_fill_with_lower_bounds(PG_FUNCTION_ARGS)
4335
4335
bool isnull ;
4336
4336
4337
4337
if (PG_ARGISNULL (1 ) || PG_ARGISNULL (2 ))
4338
- ereport (ERROR ,
4338
+ ereport (ERROR ,
4339
4339
(errcode (ERRCODE_NULL_VALUE_NOT_ALLOWED ),
4340
4340
errmsg ("dimension array or low bound array cannot be NULL" )));
4341
4341
@@ -4353,11 +4353,11 @@ array_fill_with_lower_bounds(PG_FUNCTION_ARGS)
4353
4353
isnull = true;
4354
4354
}
4355
4355
4356
- elmtype = get_fn_expr_argtype (fcinfo -> flinfo , 0 );
4357
- if (!OidIsValid (elmtype ))
4358
- elog (ERROR , "could not determine data type of input" );
4356
+ elmtype = get_fn_expr_argtype (fcinfo -> flinfo , 0 );
4357
+ if (!OidIsValid (elmtype ))
4358
+ elog (ERROR , "could not determine data type of input" );
4359
4359
4360
- result = array_fill_internal (dims , lbs , value , elmtype , isnull , fcinfo );
4360
+ result = array_fill_internal (dims , lbs , value , isnull , elmtype , fcinfo );
4361
4361
PG_RETURN_ARRAYTYPE_P (result );
4362
4362
}
4363
4363
@@ -4375,7 +4375,7 @@ array_fill(PG_FUNCTION_ARGS)
4375
4375
bool isnull ;
4376
4376
4377
4377
if (PG_ARGISNULL (1 ))
4378
- ereport (ERROR ,
4378
+ ereport (ERROR ,
4379
4379
(errcode (ERRCODE_NULL_VALUE_NOT_ALLOWED ),
4380
4380
errmsg ("dimension array or low bound array cannot be NULL" )));
4381
4381
@@ -4392,17 +4392,17 @@ array_fill(PG_FUNCTION_ARGS)
4392
4392
isnull = true;
4393
4393
}
4394
4394
4395
- elmtype = get_fn_expr_argtype (fcinfo -> flinfo , 0 );
4396
- if (!OidIsValid (elmtype ))
4397
- elog (ERROR , "could not determine data type of input" );
4395
+ elmtype = get_fn_expr_argtype (fcinfo -> flinfo , 0 );
4396
+ if (!OidIsValid (elmtype ))
4397
+ elog (ERROR , "could not determine data type of input" );
4398
4398
4399
- result = array_fill_internal (dims , NULL , value , elmtype , isnull , fcinfo );
4399
+ result = array_fill_internal (dims , NULL , value , isnull , elmtype , fcinfo );
4400
4400
PG_RETURN_ARRAYTYPE_P (result );
4401
4401
}
4402
4402
4403
4403
static ArrayType *
4404
4404
create_array_envelope (int ndims , int * dimv , int * lbsv , int nbytes ,
4405
- Oid elmtype , int dataoffset )
4405
+ Oid elmtype , int dataoffset )
4406
4406
{
4407
4407
ArrayType * result ;
4408
4408
@@ -4418,44 +4418,44 @@ create_array_envelope(int ndims, int *dimv, int *lbsv, int nbytes,
4418
4418
}
4419
4419
4420
4420
static ArrayType *
4421
- array_fill_internal (ArrayType * dims , ArrayType * lbs , Datum value ,
4422
- Oid elmtype , bool isnull ,
4423
- FunctionCallInfo fcinfo )
4421
+ array_fill_internal (ArrayType * dims , ArrayType * lbs ,
4422
+ Datum value , bool isnull , Oid elmtype ,
4423
+ FunctionCallInfo fcinfo )
4424
4424
{
4425
4425
ArrayType * result ;
4426
4426
int * dimv ;
4427
4427
int * lbsv ;
4428
4428
int ndims ;
4429
4429
int nitems ;
4430
4430
int deflbs [MAXDIM ];
4431
- int16 elmlen ;
4432
- bool elmbyval ;
4431
+ int16 elmlen ;
4432
+ bool elmbyval ;
4433
4433
char elmalign ;
4434
4434
ArrayMetaState * my_extra ;
4435
4435
4436
- /*
4436
+ /*
4437
4437
* Params checks
4438
4438
*/
4439
4439
if (ARR_NDIM (dims ) != 1 )
4440
4440
ereport (ERROR ,
4441
4441
(errcode (ERRCODE_ARRAY_SUBSCRIPT_ERROR ),
4442
4442
errmsg ("wrong number of array subscripts" ),
4443
- errhint ("Dimension array must be one dimensional." )));
4443
+ errdetail ("Dimension array must be one dimensional." )));
4444
4444
4445
4445
if (ARR_LBOUND (dims )[0 ] != 1 )
4446
4446
ereport (ERROR ,
4447
4447
(errcode (ERRCODE_ARRAY_SUBSCRIPT_ERROR ),
4448
4448
errmsg ("wrong range of array_subscripts" ),
4449
- errhint ("Lower bound of dimension array must be one." )));
4450
-
4449
+ errdetail ("Lower bound of dimension array must be one." )));
4450
+
4451
4451
if (ARR_HASNULL (dims ))
4452
- ereport (ERROR ,
4452
+ ereport (ERROR ,
4453
4453
(errcode (ERRCODE_NULL_VALUE_NOT_ALLOWED ),
4454
4454
errmsg ("dimension values cannot be null" )));
4455
4455
4456
4456
dimv = (int * ) ARR_DATA_PTR (dims );
4457
4457
ndims = ARR_DIMS (dims )[0 ];
4458
-
4458
+
4459
4459
if (ndims < 0 ) /* we do allow zero-dimension arrays */
4460
4460
ereport (ERROR ,
4461
4461
(errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
@@ -4465,38 +4465,38 @@ array_fill_internal(ArrayType *dims, ArrayType *lbs, Datum value,
4465
4465
(errcode (ERRCODE_PROGRAM_LIMIT_EXCEEDED ),
4466
4466
errmsg ("number of array dimensions (%d) exceeds the maximum allowed (%d)" ,
4467
4467
ndims , MAXDIM )));
4468
-
4468
+
4469
4469
if (lbs != NULL )
4470
4470
{
4471
4471
if (ARR_NDIM (lbs ) != 1 )
4472
4472
ereport (ERROR ,
4473
4473
(errcode (ERRCODE_ARRAY_SUBSCRIPT_ERROR ),
4474
4474
errmsg ("wrong number of array subscripts" ),
4475
- errhint ("Dimension array must be one dimensional." )));
4475
+ errdetail ("Dimension array must be one dimensional." )));
4476
4476
4477
4477
if (ARR_LBOUND (lbs )[0 ] != 1 )
4478
4478
ereport (ERROR ,
4479
4479
(errcode (ERRCODE_ARRAY_SUBSCRIPT_ERROR ),
4480
4480
errmsg ("wrong range of array_subscripts" ),
4481
- errhint ("Lower bound of dimension array must be one." )));
4482
-
4481
+ errdetail ("Lower bound of dimension array must be one." )));
4482
+
4483
4483
if (ARR_HASNULL (lbs ))
4484
- ereport (ERROR ,
4484
+ ereport (ERROR ,
4485
4485
(errcode (ERRCODE_NULL_VALUE_NOT_ALLOWED ),
4486
4486
errmsg ("dimension values cannot be null" )));
4487
4487
4488
4488
if (ARR_DIMS (lbs )[0 ] != ndims )
4489
4489
ereport (ERROR ,
4490
4490
(errcode (ERRCODE_ARRAY_SUBSCRIPT_ERROR ),
4491
4491
errmsg ("wrong number of array_subscripts" ),
4492
- errhint ("Low bound array has different size than dimensions array." )));
4493
-
4492
+ errdetail ("Low bound array has different size than dimensions array." )));
4493
+
4494
4494
lbsv = (int * ) ARR_DATA_PTR (lbs );
4495
4495
}
4496
- else
4496
+ else
4497
4497
{
4498
4498
int i ;
4499
-
4499
+
4500
4500
for (i = 0 ; i < MAXDIM ; i ++ )
4501
4501
deflbs [i ] = 1 ;
4502
4502
@@ -4506,9 +4506,8 @@ array_fill_internal(ArrayType *dims, ArrayType *lbs, Datum value,
4506
4506
/* fast track for empty array */
4507
4507
if (ndims == 0 )
4508
4508
return construct_empty_array (elmtype );
4509
-
4510
- nitems = ArrayGetNItems (ndims , dimv );
4511
4509
4510
+ nitems = ArrayGetNItems (ndims , dimv );
4512
4511
4513
4512
/*
4514
4513
* We arrange to look up info about element type only once per series of
@@ -4543,48 +4542,52 @@ array_fill_internal(ArrayType *dims, ArrayType *lbs, Datum value,
4543
4542
int i ;
4544
4543
char * p ;
4545
4544
int nbytes ;
4546
- Datum aux_value = value ;
4545
+ int totbytes ;
4547
4546
4548
4547
/* make sure data is not toasted */
4549
4548
if (elmlen == -1 )
4550
4549
value = PointerGetDatum (PG_DETOAST_DATUM (value ));
4551
4550
4552
4551
nbytes = att_addlength_datum (0 , elmlen , value );
4553
4552
nbytes = att_align_nominal (nbytes , elmalign );
4553
+ Assert (nbytes > 0 );
4554
4554
4555
- nbytes *= nitems ;
4556
- /* check for overflow of total request */
4557
- if (!AllocSizeIsValid (nbytes ))
4555
+ totbytes = nbytes * nitems ;
4556
+
4557
+ /* check for overflow of multiplication or total request */
4558
+ if (totbytes / nbytes != nitems ||
4559
+ !AllocSizeIsValid (totbytes ))
4558
4560
ereport (ERROR ,
4559
4561
(errcode (ERRCODE_PROGRAM_LIMIT_EXCEEDED ),
4560
4562
errmsg ("array size exceeds the maximum allowed (%d)" ,
4561
4563
(int ) MaxAllocSize )));
4562
4564
4563
- nbytes += ARR_OVERHEAD_NONULLS (ndims );
4564
- result = create_array_envelope (ndims , dimv , lbsv , nbytes ,
4565
- elmtype , 0 );
4565
+ /*
4566
+ * This addition can't overflow, but it might cause us to go past
4567
+ * MaxAllocSize. We leave it to palloc to complain in that case.
4568
+ */
4569
+ totbytes += ARR_OVERHEAD_NONULLS (ndims );
4570
+
4571
+ result = create_array_envelope (ndims , dimv , lbsv , totbytes ,
4572
+ elmtype , 0 );
4573
+
4566
4574
p = ARR_DATA_PTR (result );
4567
4575
for (i = 0 ; i < nitems ; i ++ )
4568
4576
p += ArrayCastAndSet (value , elmlen , elmbyval , elmalign , p );
4569
-
4570
- /* cleaning up detoasted copies of datum */
4571
- if (aux_value != value )
4572
- pfree ((Pointer ) value );
4573
4577
}
4574
4578
else
4575
4579
{
4576
4580
int nbytes ;
4577
4581
int dataoffset ;
4578
- bits8 * bitmap ;
4579
4582
4580
4583
dataoffset = ARR_OVERHEAD_WITHNULLS (ndims , nitems );
4581
4584
nbytes = dataoffset ;
4582
4585
4583
4586
result = create_array_envelope (ndims , dimv , lbsv , nbytes ,
4584
- elmtype , dataoffset );
4585
- bitmap = ARR_NULLBITMAP ( result );
4586
- MemSet ( bitmap , 0 , ( nitems + 7 ) / 8 );
4587
+ elmtype , dataoffset );
4588
+
4589
+ /* create_array_envelope already zeroed the bitmap, so we're done */
4587
4590
}
4588
-
4591
+
4589
4592
return result ;
4590
4593
}
0 commit comments