Skip to content

Commit 368964e

Browse files
committed
Fix security and 64-bit issues in contrib/intagg. This code could
stand to be rewritten altogether, but for now just stick a finger in the dike.
1 parent 5e95311 commit 368964e

File tree

2 files changed

+50
-56
lines changed

2 files changed

+50
-56
lines changed

contrib/intagg/int_aggregate.c

Lines changed: 37 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111
* This file is the property of the Digital Music Network (DMN).
1212
* It is being made available to users of the PostgreSQL system
1313
* under the BSD license.
14-
*
15-
* NOTE: This module requires sizeof(void *) to be the same as sizeof(int)
1614
*/
1715
#include "postgres.h"
1816

@@ -36,9 +34,6 @@
3634
#include "utils/lsyscache.h"
3735

3836

39-
/* Uncomment this define if you are compiling for postgres 7.2.x */
40-
/* #define PG_7_2 */
41-
4237
/* This is actually a postgres version of a one dimensional array */
4338

4439
typedef struct
@@ -58,19 +53,17 @@ typedef struct callContext
5853
} CTX;
5954

6055
#define TOASTED 1
61-
#define START_NUM 8
62-
#define PGARRAY_SIZE(n) (sizeof(PGARRAY) + ((n-1)*sizeof(int4)))
56+
#define START_NUM 8 /* initial size of arrays */
57+
#define PGARRAY_SIZE(n) (sizeof(PGARRAY) + (((n)-1)*sizeof(int4)))
6358

64-
static PGARRAY *GetPGArray(int4 state, int fAdd);
65-
static PGARRAY *ShrinkPGArray(PGARRAY * p);
59+
static PGARRAY *GetPGArray(PGARRAY *p, int fAdd);
60+
static PGARRAY *ShrinkPGArray(PGARRAY *p);
6661

6762
Datum int_agg_state(PG_FUNCTION_ARGS);
68-
Datum int_agg_final_count(PG_FUNCTION_ARGS);
6963
Datum int_agg_final_array(PG_FUNCTION_ARGS);
7064
Datum int_enum(PG_FUNCTION_ARGS);
7165

7266
PG_FUNCTION_INFO_V1(int_agg_state);
73-
PG_FUNCTION_INFO_V1(int_agg_final_count);
7467
PG_FUNCTION_INFO_V1(int_agg_final_array);
7568
PG_FUNCTION_INFO_V1(int_enum);
7669

@@ -81,11 +74,9 @@ PG_FUNCTION_INFO_V1(int_enum);
8174
* PortalContext isn't really right, but it's close enough.
8275
*/
8376
static PGARRAY *
84-
GetPGArray(int4 state, int fAdd)
77+
GetPGArray(PGARRAY *p, int fAdd)
8578
{
86-
PGARRAY *p = (PGARRAY *) state;
87-
88-
if (!state)
79+
if (!p)
8980
{
9081
/* New array */
9182
int cb = PGARRAY_SIZE(START_NUM);
@@ -94,9 +85,7 @@ GetPGArray(int4 state, int fAdd)
9485
p->a.size = cb;
9586
p->a.ndim = 0;
9687
p->a.flags = 0;
97-
#ifndef PG_7_2
9888
p->a.elemtype = INT4OID;
99-
#endif
10089
p->items = 0;
10190
p->lower = START_NUM;
10291
}
@@ -118,7 +107,8 @@ GetPGArray(int4 state, int fAdd)
118107
}
119108

120109
/* Shrinks the array to its actual size and moves it into the standard
121-
* memory allocation context, frees working memory */
110+
* memory allocation context, frees working memory
111+
*/
122112
static PGARRAY *
123113
ShrinkPGArray(PGARRAY * p)
124114
{
@@ -139,10 +129,8 @@ ShrinkPGArray(PGARRAY * p)
139129
pnew->a.size = cb;
140130
pnew->a.ndim = 1;
141131
pnew->a.flags = 0;
142-
#ifndef PG_7_2
143132
pnew->a.elemtype = INT4OID;
144-
#endif
145-
pnew->lower = 0;
133+
pnew->lower = 1;
146134

147135
pfree(p);
148136
}
@@ -153,28 +141,37 @@ ShrinkPGArray(PGARRAY * p)
153141
Datum
154142
int_agg_state(PG_FUNCTION_ARGS)
155143
{
156-
int4 state = PG_GETARG_INT32(0);
157-
int4 value = PG_GETARG_INT32(1);
158-
159-
PGARRAY *p = GetPGArray(state, 1);
144+
PGARRAY *state;
145+
PGARRAY *p;
160146

161-
if (!p)
162-
/* internal error */
163-
elog(ERROR, "no aggregate storage");
164-
else if (p->items >= p->lower)
165-
/* internal error */
166-
elog(ERROR, "aggregate storage too small");
147+
if (PG_ARGISNULL(0))
148+
state = NULL;
167149
else
168-
p->array[p->items++] = value;
169-
PG_RETURN_INT32(p);
150+
state = (PGARRAY *) PG_GETARG_POINTER(0);
151+
p = GetPGArray(state, 1);
152+
153+
if (!PG_ARGISNULL(1))
154+
{
155+
int4 value = PG_GETARG_INT32(1);
156+
157+
if (!p) /* internal error */
158+
elog(ERROR, "no aggregate storage");
159+
else if (p->items >= p->lower) /* internal error */
160+
elog(ERROR, "aggregate storage too small");
161+
else
162+
p->array[p->items++] = value;
163+
}
164+
PG_RETURN_POINTER(p);
170165
}
171166

172-
/* This is the final function used for the integer aggregator. It returns all the integers
173-
* collected as a one dimensional integer array */
167+
/* This is the final function used for the integer aggregator. It returns all
168+
* the integers collected as a one dimensional integer array
169+
*/
174170
Datum
175171
int_agg_final_array(PG_FUNCTION_ARGS)
176172
{
177-
PGARRAY *pnew = ShrinkPGArray(GetPGArray(PG_GETARG_INT32(0), 0));
173+
PGARRAY *state = (PGARRAY *) PG_GETARG_POINTER(0);
174+
PGARRAY *pnew = ShrinkPGArray(GetPGArray(state, 0));
178175

179176
if (pnew)
180177
PG_RETURN_POINTER(pnew);
@@ -206,30 +203,23 @@ int_enum(PG_FUNCTION_ARGS)
206203
/* Allocate a working context */
207204
pc = (CTX *) palloc(sizeof(CTX));
208205

209-
/* Don't copy attribute if you don't need too */
206+
/* Don't copy attribute if you don't need to */
210207
if (VARATT_IS_EXTENDED(p))
211208
{
212209
/* Toasted!!! */
213210
pc->p = (PGARRAY *) PG_DETOAST_DATUM_COPY(p);
214211
pc->flags = TOASTED;
215-
if (!pc->p)
216-
{
217-
/* internal error */
218-
elog(ERROR, "error in toaster; not detoasting");
219-
PG_RETURN_NULL();
220-
}
221212
}
222213
else
223214
{
224215
/* Untoasted */
225216
pc->p = p;
226217
pc->flags = 0;
227218
}
228-
fcinfo->context = (Node *) pc;
229219
pc->num = 0;
220+
fcinfo->context = (Node *) pc;
230221
}
231-
else
232-
/* use an existing one */
222+
else /* use an existing one */
233223
pc = (CTX *) fcinfo->context;
234224
/* Are we done yet? */
235225
if (pc->num >= pc->p->items)
@@ -242,8 +232,8 @@ int_enum(PG_FUNCTION_ARGS)
242232
rsi->isDone = ExprEndResult;
243233
}
244234
else
245-
/* nope, return the next value */
246235
{
236+
/* nope, return the next value */
247237
int val = pc->p->array[pc->num++];
248238

249239
rsi->isDone = ExprMultipleResult;

contrib/intagg/int_aggregate.sql.in

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,30 +3,34 @@ SET search_path = public;
33

44
-- Internal function for the aggregate
55
-- Is called for each item in an aggregation
6-
CREATE OR REPLACE FUNCTION int_agg_state (int4, int4)
7-
RETURNS int4
6+
CREATE OR REPLACE FUNCTION int_agg_state (int4[], int4)
7+
RETURNS int4[]
88
AS 'MODULE_PATHNAME','int_agg_state'
9-
LANGUAGE 'C' IMMUTABLE STRICT;
9+
LANGUAGE 'C';
1010

1111
-- Internal function for the aggregate
1212
-- Is called at the end of the aggregation, and returns an array.
13-
CREATE OR REPLACE FUNCTION int_agg_final_array (int4)
13+
CREATE OR REPLACE FUNCTION int_agg_final_array (int4[])
1414
RETURNS int4[]
1515
AS 'MODULE_PATHNAME','int_agg_final_array'
16-
LANGUAGE 'C' IMMUTABLE STRICT;
16+
LANGUAGE 'C' STRICT;
1717

1818
-- The aggregate function itself
1919
-- uses the above functions to create an array of integers from an aggregation.
2020
CREATE AGGREGATE int_array_aggregate (
2121
BASETYPE = int4,
2222
SFUNC = int_agg_state,
23-
STYPE = int4,
24-
FINALFUNC = int_agg_final_array,
25-
INITCOND = 0
23+
STYPE = int4[],
24+
FINALFUNC = int_agg_final_array
2625
);
2726

27+
-- The aggregate component functions are not designed to be called
28+
-- independently, so disable public access to them
29+
REVOKE ALL ON FUNCTION int_agg_state (int4[], int4) FROM PUBLIC;
30+
REVOKE ALL ON FUNCTION int_agg_final_array (int4[]) FROM PUBLIC;
31+
2832
-- The enumeration function
29-
-- returns each element in a one dimentional integer array
33+
-- returns each element in a one dimensional integer array
3034
-- as a row.
3135
CREATE OR REPLACE FUNCTION int_array_enum(int4[])
3236
RETURNS setof integer

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy