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

Commitf47004a

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 parent81eaaf6 commitf47004a

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
@@ -272,9 +272,9 @@ static Datum plperl_sv_to_datum(SV *sv, Oid typid, int32 typmod,
272272
bool*isnull);
273273
staticvoid_sv_to_datum_finfo(Oidtypid,FmgrInfo*finfo,Oid*typioparam);
274274
staticDatumplperl_array_to_datum(SV*src,Oidtypid,int32typmod);
275-
staticvoidarray_to_datum_internal(AV*av,ArrayBuildState*astate,
275+
staticvoidarray_to_datum_internal(AV*av,ArrayBuildState**astatep,
276276
int*ndims,int*dims,intcur_depth,
277-
Oidarraytypid,Oidelemtypid,int32typmod,
277+
Oidelemtypid,int32typmod,
278278
FmgrInfo*finfo,Oidtypioparam);
279279
staticDatumplperl_hash_to_datum(SV*src,TupleDesctd);
280280

@@ -1160,11 +1160,16 @@ get_perl_array_ref(SV *sv)
11601160

11611161
/*
11621162
* helper function for plperl_array_to_datum, recurses for multi-D arrays
1163+
*
1164+
* The ArrayBuildState is created only when we first find a scalar element;
1165+
* if we didn't do it like that, we'd need some other convention for knowing
1166+
* whether we'd already found any scalars (and thus the number of dimensions
1167+
* is frozen).
11631168
*/
11641169
staticvoid
1165-
array_to_datum_internal(AV*av,ArrayBuildState*astate,
1170+
array_to_datum_internal(AV*av,ArrayBuildState**astatep,
11661171
int*ndims,int*dims,intcur_depth,
1167-
Oidarraytypid,Oidelemtypid,int32typmod,
1172+
Oidelemtypid,int32typmod,
11681173
FmgrInfo*finfo,Oidtypioparam)
11691174
{
11701175
dTHX;
@@ -1184,28 +1189,34 @@ array_to_datum_internal(AV *av, ArrayBuildState *astate,
11841189
{
11851190
AV*nav= (AV*)SvRV(sav);
11861191

1187-
/* dimensionality checks */
1188-
if (cur_depth+1>MAXDIM)
1189-
ereport(ERROR,
1190-
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1191-
errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
1192-
cur_depth+1,MAXDIM)));
1193-
11941192
/* set size when at first element in this level, else compare */
11951193
if (i==0&&*ndims==cur_depth)
11961194
{
1195+
/* array after some scalars at same level? */
1196+
if (*astatep!=NULL)
1197+
ereport(ERROR,
1198+
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1199+
errmsg("multidimensional arrays must have array expressions with matching dimensions")));
1200+
/* too many dimensions? */
1201+
if (cur_depth+1>MAXDIM)
1202+
ereport(ERROR,
1203+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1204+
errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
1205+
cur_depth+1,MAXDIM)));
1206+
/* OK, add a dimension */
11971207
dims[*ndims]=av_len(nav)+1;
11981208
(*ndims)++;
11991209
}
1200-
elseif (av_len(nav)+1!=dims[cur_depth])
1210+
elseif (cur_depth >=*ndims||
1211+
av_len(nav)+1!=dims[cur_depth])
12011212
ereport(ERROR,
12021213
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
12031214
errmsg("multidimensional arrays must have array expressions with matching dimensions")));
12041215

12051216
/* recurse to fetch elements of this sub-array */
1206-
array_to_datum_internal(nav,astate,
1217+
array_to_datum_internal(nav,astatep,
12071218
ndims,dims,cur_depth+1,
1208-
arraytypid,elemtypid,typmod,
1219+
elemtypid,typmod,
12091220
finfo,typioparam);
12101221
}
12111222
else
@@ -1227,7 +1238,13 @@ array_to_datum_internal(AV *av, ArrayBuildState *astate,
12271238
typioparam,
12281239
&isnull);
12291240

1230-
(void)accumArrayResult(astate,dat,isnull,
1241+
/* Create ArrayBuildState if we didn't already */
1242+
if (*astatep==NULL)
1243+
*astatep=initArrayResult(elemtypid,
1244+
CurrentMemoryContext, true);
1245+
1246+
/* ... and save the element value in it */
1247+
(void)accumArrayResult(*astatep,dat,isnull,
12311248
elemtypid,CurrentMemoryContext);
12321249
}
12331250
}
@@ -1240,7 +1257,8 @@ static Datum
12401257
plperl_array_to_datum(SV*src,Oidtypid,int32typmod)
12411258
{
12421259
dTHX;
1243-
ArrayBuildState*astate;
1260+
AV*nav= (AV*)SvRV(src);
1261+
ArrayBuildState*astate=NULL;
12441262
Oidelemtypid;
12451263
FmgrInfofinfo;
12461264
Oidtypioparam;
@@ -1256,21 +1274,19 @@ plperl_array_to_datum(SV *src, Oid typid, int32 typmod)
12561274
errmsg("cannot convert Perl array to non-array type %s",
12571275
format_type_be(typid))));
12581276

1259-
astate=initArrayResult(elemtypid,CurrentMemoryContext, true);
1260-
12611277
_sv_to_datum_finfo(elemtypid,&finfo,&typioparam);
12621278

12631279
memset(dims,0,sizeof(dims));
1264-
dims[0]=av_len((AV*)SvRV(src))+1;
1280+
dims[0]=av_len(nav)+1;
12651281

1266-
array_to_datum_internal((AV*)SvRV(src),astate,
1282+
array_to_datum_internal(nav,&astate,
12671283
&ndims,dims,1,
1268-
typid,elemtypid,typmod,
1284+
elemtypid,typmod,
12691285
&finfo,typioparam);
12701286

12711287
/* ensure we get zero-D array for no inputs, as per PG convention */
1272-
if (dims[0] <=0)
1273-
ndims=0;
1288+
if (astate==NULL)
1289+
returnPointerGetDatum(construct_empty_array(elemtypid));
12741290

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