Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitee24b5e

Browse files
committed
Tighten array dimensionality checks in Perl -> SQL array conversion.
plperl_array_to_datum() wasn't sufficiently careful about checkingthat nested lists represent a rectangular array structure; it wouldaccept inputs such as "[1, []]". This is a bit related to thePL/Python bug fixed in commit81eaaf6, but it doesn't seem toprovide any direct route to a memory stomp. Instead the likelyfailure mode is for makeMdArrayResult to be passed fewer Datums thanthe claimed array dimensionality requires, possibly leading to a wildpointer dereference and SIGSEGV.Per report from Alexander Lakhin. It's been broken for a longtime, so back-patch to all supported branches.Discussion:https://postgr.es/m/5ebae5e4-d401-fadf-8585-ac3eaf53219c@gmail.com
1 parent7dcd999 commitee24b5e

File tree

3 files changed

+119
-23
lines changed

3 files changed

+119
-23
lines changed

‎src/pl/plperl/expected/plperl_array.out

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,49 @@ select plperl_arrays_inout_l('{{1}, {2}, {3}}');
215215
{{1},{2},{3}}
216216
(1 row)
217217

218+
-- check output of multi-dimensional arrays
219+
CREATE FUNCTION plperl_md_array_out() RETURNS text[] AS $$
220+
return [['a'], ['b'], ['c']];
221+
$$ LANGUAGE plperl;
222+
select plperl_md_array_out();
223+
plperl_md_array_out
224+
---------------------
225+
{{a},{b},{c}}
226+
(1 row)
227+
228+
CREATE OR REPLACE FUNCTION plperl_md_array_out() RETURNS text[] AS $$
229+
return [[], []];
230+
$$ LANGUAGE plperl;
231+
select plperl_md_array_out();
232+
plperl_md_array_out
233+
---------------------
234+
{}
235+
(1 row)
236+
237+
CREATE OR REPLACE FUNCTION plperl_md_array_out() RETURNS text[] AS $$
238+
return [[], [1]];
239+
$$ LANGUAGE plperl;
240+
select plperl_md_array_out(); -- fail
241+
ERROR: multidimensional arrays must have array expressions with matching dimensions
242+
CONTEXT: PL/Perl function "plperl_md_array_out"
243+
CREATE OR REPLACE FUNCTION plperl_md_array_out() RETURNS text[] AS $$
244+
return [[], 1];
245+
$$ LANGUAGE plperl;
246+
select plperl_md_array_out(); -- fail
247+
ERROR: multidimensional arrays must have array expressions with matching dimensions
248+
CONTEXT: PL/Perl function "plperl_md_array_out"
249+
CREATE OR REPLACE FUNCTION plperl_md_array_out() RETURNS text[] AS $$
250+
return [1, []];
251+
$$ LANGUAGE plperl;
252+
select plperl_md_array_out(); -- fail
253+
ERROR: multidimensional arrays must have array expressions with matching dimensions
254+
CONTEXT: PL/Perl function "plperl_md_array_out"
255+
CREATE OR REPLACE FUNCTION plperl_md_array_out() RETURNS text[] AS $$
256+
return [[1], [[]]];
257+
$$ LANGUAGE plperl;
258+
select plperl_md_array_out(); -- fail
259+
ERROR: multidimensional arrays must have array expressions with matching dimensions
260+
CONTEXT: PL/Perl function "plperl_md_array_out"
218261
-- make sure setof works
219262
create or replace function perl_setof_array(integer[]) returns setof integer[] language plperl as $$
220263
my $arr = shift;

‎src/pl/plperl/plperl.c

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -275,9 +275,9 @@ static Datum plperl_sv_to_datum(SV *sv, Oid typid, int32 typmod,
275275
bool*isnull);
276276
staticvoid_sv_to_datum_finfo(Oidtypid,FmgrInfo*finfo,Oid*typioparam);
277277
staticDatumplperl_array_to_datum(SV*src,Oidtypid,int32typmod);
278-
staticvoidarray_to_datum_internal(AV*av,ArrayBuildState*astate,
278+
staticvoidarray_to_datum_internal(AV*av,ArrayBuildState**astatep,
279279
int*ndims,int*dims,intcur_depth,
280-
Oidarraytypid,Oidelemtypid,int32typmod,
280+
Oidelemtypid,int32typmod,
281281
FmgrInfo*finfo,Oidtypioparam);
282282
staticDatumplperl_hash_to_datum(SV*src,TupleDesctd);
283283

@@ -1166,11 +1166,16 @@ get_perl_array_ref(SV *sv)
11661166

11671167
/*
11681168
* helper function for plperl_array_to_datum, recurses for multi-D arrays
1169+
*
1170+
* The ArrayBuildState is created only when we first find a scalar element;
1171+
* if we didn't do it like that, we'd need some other convention for knowing
1172+
* whether we'd already found any scalars (and thus the number of dimensions
1173+
* is frozen).
11691174
*/
11701175
staticvoid
1171-
array_to_datum_internal(AV*av,ArrayBuildState*astate,
1176+
array_to_datum_internal(AV*av,ArrayBuildState**astatep,
11721177
int*ndims,int*dims,intcur_depth,
1173-
Oidarraytypid,Oidelemtypid,int32typmod,
1178+
Oidelemtypid,int32typmod,
11741179
FmgrInfo*finfo,Oidtypioparam)
11751180
{
11761181
dTHX;
@@ -1190,28 +1195,34 @@ array_to_datum_internal(AV *av, ArrayBuildState *astate,
11901195
{
11911196
AV*nav= (AV*)SvRV(sav);
11921197

1193-
/* dimensionality checks */
1194-
if (cur_depth+1>MAXDIM)
1195-
ereport(ERROR,
1196-
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1197-
errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
1198-
cur_depth+1,MAXDIM)));
1199-
12001198
/* set size when at first element in this level, else compare */
12011199
if (i==0&&*ndims==cur_depth)
12021200
{
1201+
/* array after some scalars at same level? */
1202+
if (*astatep!=NULL)
1203+
ereport(ERROR,
1204+
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1205+
errmsg("multidimensional arrays must have array expressions with matching dimensions")));
1206+
/* too many dimensions? */
1207+
if (cur_depth+1>MAXDIM)
1208+
ereport(ERROR,
1209+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1210+
errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
1211+
cur_depth+1,MAXDIM)));
1212+
/* OK, add a dimension */
12031213
dims[*ndims]=av_len(nav)+1;
12041214
(*ndims)++;
12051215
}
1206-
elseif (av_len(nav)+1!=dims[cur_depth])
1216+
elseif (cur_depth >=*ndims||
1217+
av_len(nav)+1!=dims[cur_depth])
12071218
ereport(ERROR,
12081219
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
12091220
errmsg("multidimensional arrays must have array expressions with matching dimensions")));
12101221

12111222
/* recurse to fetch elements of this sub-array */
1212-
array_to_datum_internal(nav,astate,
1223+
array_to_datum_internal(nav,astatep,
12131224
ndims,dims,cur_depth+1,
1214-
arraytypid,elemtypid,typmod,
1225+
elemtypid,typmod,
12151226
finfo,typioparam);
12161227
}
12171228
else
@@ -1233,7 +1244,13 @@ array_to_datum_internal(AV *av, ArrayBuildState *astate,
12331244
typioparam,
12341245
&isnull);
12351246

1236-
(void)accumArrayResult(astate,dat,isnull,
1247+
/* Create ArrayBuildState if we didn't already */
1248+
if (*astatep==NULL)
1249+
*astatep=initArrayResult(elemtypid,
1250+
CurrentMemoryContext, true);
1251+
1252+
/* ... and save the element value in it */
1253+
(void)accumArrayResult(*astatep,dat,isnull,
12371254
elemtypid,CurrentMemoryContext);
12381255
}
12391256
}
@@ -1246,7 +1263,8 @@ static Datum
12461263
plperl_array_to_datum(SV*src,Oidtypid,int32typmod)
12471264
{
12481265
dTHX;
1249-
ArrayBuildState*astate;
1266+
AV*nav= (AV*)SvRV(src);
1267+
ArrayBuildState*astate=NULL;
12501268
Oidelemtypid;
12511269
FmgrInfofinfo;
12521270
Oidtypioparam;
@@ -1262,21 +1280,19 @@ plperl_array_to_datum(SV *src, Oid typid, int32 typmod)
12621280
errmsg("cannot convert Perl array to non-array type %s",
12631281
format_type_be(typid))));
12641282

1265-
astate=initArrayResult(elemtypid,CurrentMemoryContext, true);
1266-
12671283
_sv_to_datum_finfo(elemtypid,&finfo,&typioparam);
12681284

12691285
memset(dims,0,sizeof(dims));
1270-
dims[0]=av_len((AV*)SvRV(src))+1;
1286+
dims[0]=av_len(nav)+1;
12711287

1272-
array_to_datum_internal((AV*)SvRV(src),astate,
1288+
array_to_datum_internal(nav,&astate,
12731289
&ndims,dims,1,
1274-
typid,elemtypid,typmod,
1290+
elemtypid,typmod,
12751291
&finfo,typioparam);
12761292

12771293
/* ensure we get zero-D array for no inputs, as per PG convention */
1278-
if (dims[0] <=0)
1279-
ndims=0;
1294+
if (astate==NULL)
1295+
returnPointerGetDatum(construct_empty_array(elemtypid));
12801296

12811297
for (i=0;i<ndims;i++)
12821298
lbs[i]=1;

‎src/pl/plperl/sql/plperl_array.sql

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,43 @@ $$ LANGUAGE plperl;
159159

160160
select plperl_arrays_inout_l('{{1}, {2}, {3}}');
161161

162+
-- check output of multi-dimensional arrays
163+
CREATEFUNCTIONplperl_md_array_out() RETURNStext[]AS $$
164+
return [['a'], ['b'], ['c']];
165+
$$ LANGUAGE plperl;
166+
167+
select plperl_md_array_out();
168+
169+
CREATE OR REPLACEFUNCTIONplperl_md_array_out() RETURNStext[]AS $$
170+
return [[], []];
171+
$$ LANGUAGE plperl;
172+
173+
select plperl_md_array_out();
174+
175+
CREATE OR REPLACEFUNCTIONplperl_md_array_out() RETURNStext[]AS $$
176+
return [[], [1]];
177+
$$ LANGUAGE plperl;
178+
179+
select plperl_md_array_out();-- fail
180+
181+
CREATE OR REPLACEFUNCTIONplperl_md_array_out() RETURNStext[]AS $$
182+
return [[],1];
183+
$$ LANGUAGE plperl;
184+
185+
select plperl_md_array_out();-- fail
186+
187+
CREATE OR REPLACEFUNCTIONplperl_md_array_out() RETURNStext[]AS $$
188+
return [1, []];
189+
$$ LANGUAGE plperl;
190+
191+
select plperl_md_array_out();-- fail
192+
193+
CREATE OR REPLACEFUNCTIONplperl_md_array_out() RETURNStext[]AS $$
194+
return [[1], [[]]];
195+
$$ LANGUAGE plperl;
196+
197+
select plperl_md_array_out();-- fail
198+
162199
-- make sure setof works
163200
create or replacefunctionperl_setof_array(integer[]) returns setofinteger[] language plperlas $$
164201
my $arr= shift;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp