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

Commit900a8d5

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 parentff9203f commit900a8d5

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
@@ -276,9 +276,9 @@ static Datum plperl_sv_to_datum(SV *sv, Oid typid, int32 typmod,
276276
bool*isnull);
277277
staticvoid_sv_to_datum_finfo(Oidtypid,FmgrInfo*finfo,Oid*typioparam);
278278
staticDatumplperl_array_to_datum(SV*src,Oidtypid,int32typmod);
279-
staticvoidarray_to_datum_internal(AV*av,ArrayBuildState*astate,
279+
staticvoidarray_to_datum_internal(AV*av,ArrayBuildState**astatep,
280280
int*ndims,int*dims,intcur_depth,
281-
Oidarraytypid,Oidelemtypid,int32typmod,
281+
Oidelemtypid,int32typmod,
282282
FmgrInfo*finfo,Oidtypioparam);
283283
staticDatumplperl_hash_to_datum(SV*src,TupleDesctd);
284284

@@ -1167,11 +1167,16 @@ get_perl_array_ref(SV *sv)
11671167

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

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

12121223
/* recurse to fetch elements of this sub-array */
1213-
array_to_datum_internal(nav,astate,
1224+
array_to_datum_internal(nav,astatep,
12141225
ndims,dims,cur_depth+1,
1215-
arraytypid,elemtypid,typmod,
1226+
elemtypid,typmod,
12161227
finfo,typioparam);
12171228
}
12181229
else
@@ -1234,7 +1245,13 @@ array_to_datum_internal(AV *av, ArrayBuildState *astate,
12341245
typioparam,
12351246
&isnull);
12361247

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

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

12701286
memset(dims,0,sizeof(dims));
1271-
dims[0]=av_len((AV*)SvRV(src))+1;
1287+
dims[0]=av_len(nav)+1;
12721288

1273-
array_to_datum_internal((AV*)SvRV(src),astate,
1289+
array_to_datum_internal(nav,&astate,
12741290
&ndims,dims,1,
1275-
typid,elemtypid,typmod,
1291+
elemtypid,typmod,
12761292
&finfo,typioparam);
12771293

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

12821298
for (i=0;i<ndims;i++)
12831299
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