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

Commit1e868bb

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 parenta1d9aac commit1e868bb

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

@@ -1163,11 +1163,16 @@ get_perl_array_ref(SV *sv)
11631163

11641164
/*
11651165
* helper function for plperl_array_to_datum, recurses for multi-D arrays
1166+
*
1167+
* The ArrayBuildState is created only when we first find a scalar element;
1168+
* if we didn't do it like that, we'd need some other convention for knowing
1169+
* whether we'd already found any scalars (and thus the number of dimensions
1170+
* is frozen).
11661171
*/
11671172
staticvoid
1168-
array_to_datum_internal(AV*av,ArrayBuildState*astate,
1173+
array_to_datum_internal(AV*av,ArrayBuildState**astatep,
11691174
int*ndims,int*dims,intcur_depth,
1170-
Oidarraytypid,Oidelemtypid,int32typmod,
1175+
Oidelemtypid,int32typmod,
11711176
FmgrInfo*finfo,Oidtypioparam)
11721177
{
11731178
dTHX;
@@ -1187,28 +1192,34 @@ array_to_datum_internal(AV *av, ArrayBuildState *astate,
11871192
{
11881193
AV*nav= (AV*)SvRV(sav);
11891194

1190-
/* dimensionality checks */
1191-
if (cur_depth+1>MAXDIM)
1192-
ereport(ERROR,
1193-
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1194-
errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
1195-
cur_depth+1,MAXDIM)));
1196-
11971195
/* set size when at first element in this level, else compare */
11981196
if (i==0&&*ndims==cur_depth)
11991197
{
1198+
/* array after some scalars at same level? */
1199+
if (*astatep!=NULL)
1200+
ereport(ERROR,
1201+
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1202+
errmsg("multidimensional arrays must have array expressions with matching dimensions")));
1203+
/* too many dimensions? */
1204+
if (cur_depth+1>MAXDIM)
1205+
ereport(ERROR,
1206+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1207+
errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
1208+
cur_depth+1,MAXDIM)));
1209+
/* OK, add a dimension */
12001210
dims[*ndims]=av_len(nav)+1;
12011211
(*ndims)++;
12021212
}
1203-
elseif (av_len(nav)+1!=dims[cur_depth])
1213+
elseif (cur_depth >=*ndims||
1214+
av_len(nav)+1!=dims[cur_depth])
12041215
ereport(ERROR,
12051216
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
12061217
errmsg("multidimensional arrays must have array expressions with matching dimensions")));
12071218

12081219
/* recurse to fetch elements of this sub-array */
1209-
array_to_datum_internal(nav,astate,
1220+
array_to_datum_internal(nav,astatep,
12101221
ndims,dims,cur_depth+1,
1211-
arraytypid,elemtypid,typmod,
1222+
elemtypid,typmod,
12121223
finfo,typioparam);
12131224
}
12141225
else
@@ -1230,7 +1241,13 @@ array_to_datum_internal(AV *av, ArrayBuildState *astate,
12301241
typioparam,
12311242
&isnull);
12321243

1233-
(void)accumArrayResult(astate,dat,isnull,
1244+
/* Create ArrayBuildState if we didn't already */
1245+
if (*astatep==NULL)
1246+
*astatep=initArrayResult(elemtypid,
1247+
CurrentMemoryContext, true);
1248+
1249+
/* ... and save the element value in it */
1250+
(void)accumArrayResult(*astatep,dat,isnull,
12341251
elemtypid,CurrentMemoryContext);
12351252
}
12361253
}
@@ -1243,7 +1260,8 @@ static Datum
12431260
plperl_array_to_datum(SV*src,Oidtypid,int32typmod)
12441261
{
12451262
dTHX;
1246-
ArrayBuildState*astate;
1263+
AV*nav= (AV*)SvRV(src);
1264+
ArrayBuildState*astate=NULL;
12471265
Oidelemtypid;
12481266
FmgrInfofinfo;
12491267
Oidtypioparam;
@@ -1259,21 +1277,19 @@ plperl_array_to_datum(SV *src, Oid typid, int32 typmod)
12591277
errmsg("cannot convert Perl array to non-array type %s",
12601278
format_type_be(typid))));
12611279

1262-
astate=initArrayResult(elemtypid,CurrentMemoryContext, true);
1263-
12641280
_sv_to_datum_finfo(elemtypid,&finfo,&typioparam);
12651281

12661282
memset(dims,0,sizeof(dims));
1267-
dims[0]=av_len((AV*)SvRV(src))+1;
1283+
dims[0]=av_len(nav)+1;
12681284

1269-
array_to_datum_internal((AV*)SvRV(src),astate,
1285+
array_to_datum_internal(nav,&astate,
12701286
&ndims,dims,1,
1271-
typid,elemtypid,typmod,
1287+
elemtypid,typmod,
12721288
&finfo,typioparam);
12731289

12741290
/* ensure we get zero-D array for no inputs, as per PG convention */
1275-
if (dims[0] <=0)
1276-
ndims=0;
1291+
if (astate==NULL)
1292+
returnPointerGetDatum(construct_empty_array(elemtypid));
12771293

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