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

Commit96b9dc1

Browse files
committed
The attached patch, which incorporates the previous one sent and
currently unapplied regarding spi_internal.c, makes some additionalfixes relating to return types, and also contains the fix forpreventing the use of insecure versions of Safe.pm.There is one remaing return case that does not appear to work, namelyreturn of a composite directly in a select, i.e. if foo returns somecomposite type, 'select * from foo()' works but 'select foo()' doesn't.We will either fix that or document it as a limitation.The function plperl_func_handler is a mess - I will try to get itcleaned up (and split up) in a subsequent patch, time permitting.Also, reiterating previous advice - this changes slightly the API forspi_exec_query - the returned object has either 2 or 3 members: 'status'(string) and 'proceesed' (int,- number of rows) and, if rows arereturned, 'rows' (array of tuple hashes).Andrew Dunstan
1 parentf4c5e06 commit96b9dc1

File tree

3 files changed

+125
-24
lines changed

3 files changed

+125
-24
lines changed

‎src/pl/plperl/plperl.c

Lines changed: 110 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
* ENHANCEMENTS, OR MODIFICATIONS.
3434
*
3535
* IDENTIFICATION
36-
* $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.45 2004/07/01 20:50:22 joe Exp $
36+
* $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.46 2004/07/12 14:31:04 momjian Exp $
3737
*
3838
**********************************************************************/
3939

@@ -80,6 +80,7 @@ typedef struct plperl_proc_desc
8080
CommandIdfn_cmin;
8181
boollanpltrusted;
8282
boolfn_retistuple;/* true, if function returns tuple */
83+
boolfn_retisset;/*true, if function returns set*/
8384
Oidret_oid;/* Oid of returning type */
8485
FmgrInforesult_in_func;
8586
Oidresult_typioparam;
@@ -95,11 +96,13 @@ typedef struct plperl_proc_desc
9596
* Global data
9697
**********************************************************************/
9798
staticintplperl_firstcall=1;
99+
staticboolplperl_safe_init_done= false;
98100
staticPerlInterpreter*plperl_interp=NULL;
99101
staticHV*plperl_proc_hash=NULL;
100-
AV*g_row_keys=NULL;
101-
AV*g_column_keys=NULL;
102-
intg_attr_num=0;
102+
staticAV*g_row_keys=NULL;
103+
staticAV*g_column_keys=NULL;
104+
staticSV*srf_perlret=NULL;/*keep returned value*/
105+
staticintg_attr_num=0;
103106

104107
/**********************************************************************
105108
* Forward declarations
@@ -215,11 +218,7 @@ plperl_init_interp(void)
215218
* no commas between the next lines please. They are supposed to be
216219
* one string
217220
*/
218-
"require Safe; SPI::bootstrap(); use vars qw(%_SHARED);"
219-
"use vars qw($PLContainer); $PLContainer = new Safe('PLPerl');"
220-
"$PLContainer->permit_only(':default');$PLContainer->permit(':base_math');"
221-
"$PLContainer->share(qw[&elog &spi_exec_query &DEBUG &LOG &INFO &NOTICE &WARNING &ERROR %SHARED ]);"
222-
"sub ::mksafefunc { return $PLContainer->reval(qq[sub { $_[0] $_[1]}]); }"
221+
"SPI::bootstrap(); use vars qw(%_SHARED);"
223222
"sub ::mkunsafefunc {return eval(qq[ sub { $_[0] $_[1] } ]); }"
224223
};
225224

@@ -238,6 +237,41 @@ plperl_init_interp(void)
238237

239238
}
240239

240+
241+
staticvoid
242+
plperl_safe_init(void)
243+
{
244+
staticchar*safe_module=
245+
"require Safe; $Safe::VERSION";
246+
247+
staticchar*safe_ok=
248+
"use vars qw($PLContainer); $PLContainer = new Safe('PLPerl');"
249+
"$PLContainer->permit_only(':default');$PLContainer->permit(':base_math');"
250+
"$PLContainer->share(qw[&elog &spi_exec_query &DEBUG &LOG &INFO &NOTICE &WARNING &ERROR %SHARED ]);"
251+
"sub ::mksafefunc { return $PLContainer->reval(qq[sub { $_[0] $_[1]}]); }"
252+
;
253+
254+
staticchar*safe_bad=
255+
"use vars qw($PLContainer); $PLContainer = new Safe('PLPerl');"
256+
"$PLContainer->permit_only(':default');$PLContainer->permit(':base_math');"
257+
"$PLContainer->share(qw[&elog &DEBUG &LOG &INFO &NOTICE &WARNING &ERROR %SHARED ]);"
258+
"sub ::mksafefunc { return $PLContainer->reval(qq[sub { "
259+
"elog(ERROR,'trusted perl functions disabled - please upgrade perl Safe module to at least 2.09');}]); }"
260+
;
261+
262+
SV*res;
263+
264+
floatsafe_version;
265+
266+
res=eval_pv(safe_module,FALSE);/* TRUE = croak if failure */
267+
268+
safe_version=SvNV(res);
269+
270+
eval_pv((safe_version<2.09 ?safe_bad :safe_ok),FALSE);
271+
272+
plperl_safe_init_done= true;
273+
}
274+
241275
/**********************************************************************
242276
* turn a tuple into a hash expression and add it to a list
243277
**********************************************************************/
@@ -596,6 +630,9 @@ plperl_create_sub(char *s, bool trusted)
596630
SV*subref;
597631
intcount;
598632

633+
if(trusted&& !plperl_safe_init_done)
634+
plperl_safe_init();
635+
599636
ENTER;
600637
SAVETMPS;
601638
PUSHMARK(SP);
@@ -839,15 +876,22 @@ plperl_func_handler(PG_FUNCTION_ARGS)
839876
/* Find or compile the function */
840877
prodesc=compile_plperl_function(fcinfo->flinfo->fn_oid, false);
841878
/************************************************************
842-
* Call the Perl function
879+
* Call the Perl function if not returning set
843880
************************************************************/
881+
if (!prodesc->fn_retisset)
844882
perlret=plperl_call_perl_func(prodesc,fcinfo);
845-
if (prodesc->fn_retistuple&&SRF_IS_FIRSTCALL())
883+
else
846884
{
847-
885+
if (SRF_IS_FIRSTCALL())/*call function only once*/
886+
srf_perlret=plperl_call_perl_func(prodesc,fcinfo);
887+
perlret=srf_perlret;
888+
}
889+
890+
if (prodesc->fn_retisset&&SRF_IS_FIRSTCALL())
891+
{
892+
if (prodesc->fn_retistuple)g_column_keys=newAV();
848893
if (SvTYPE(perlret)!=SVt_RV)
849-
elog(ERROR,"plperl: this function must return a reference");
850-
g_column_keys=newAV();
894+
elog(ERROR,"plperl: set-returning function must return reference");
851895
}
852896

853897
/************************************************************
@@ -882,14 +926,15 @@ plperl_func_handler(PG_FUNCTION_ARGS)
882926
char**values=NULL;
883927
ReturnSetInfo*rsinfo= (ReturnSetInfo*)fcinfo->resultinfo;
884928

885-
if (!rsinfo)
929+
if (prodesc->fn_retisset&&!rsinfo)
886930
ereport(ERROR,
887931
(errcode(ERRCODE_SYNTAX_ERROR),
888932
errmsg("returning a composite type is not allowed in this context"),
889933
errhint("This function is intended for use in the FROM clause.")));
890934

891935
if (SvTYPE(perlret)!=SVt_RV)
892-
elog(ERROR,"plperl: this function must return a reference");
936+
elog(ERROR,"plperl: composite-returning function must return a reference");
937+
893938

894939
isset=plperl_is_set(perlret);
895940

@@ -997,6 +1042,53 @@ plperl_func_handler(PG_FUNCTION_ARGS)
9971042
SRF_RETURN_DONE(funcctx);
9981043
}
9991044
}
1045+
elseif (prodesc->fn_retisset)
1046+
{
1047+
FuncCallContext*funcctx;
1048+
1049+
if (SRF_IS_FIRSTCALL())
1050+
{
1051+
MemoryContextoldcontext;
1052+
inti;
1053+
1054+
funcctx=SRF_FIRSTCALL_INIT();
1055+
oldcontext=MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1056+
1057+
if(SvTYPE(SvRV(perlret))!=SVt_PVAV)elog(ERROR,"plperl: set-returning function must return reference to array");
1058+
elsefuncctx->max_calls=av_len((AV*)SvRV(perlret))+1;
1059+
}
1060+
1061+
funcctx=SRF_PERCALL_SETUP();
1062+
1063+
if (funcctx->call_cntr<funcctx->max_calls)
1064+
{
1065+
Datumresult;
1066+
AV*array;
1067+
SV**svp;
1068+
inti;
1069+
1070+
array= (AV*)SvRV(perlret);
1071+
svp=av_fetch(array,funcctx->call_cntr, FALSE);
1072+
1073+
if (SvTYPE(*svp)!=SVt_NULL)
1074+
result=FunctionCall3(&prodesc->result_in_func,
1075+
PointerGetDatum(SvPV(*svp,PL_na)),
1076+
ObjectIdGetDatum(prodesc->result_typioparam),
1077+
Int32GetDatum(-1));
1078+
else
1079+
{
1080+
fcinfo->isnull= true;
1081+
result= (Datum)0;
1082+
}
1083+
SRF_RETURN_NEXT(funcctx,result);
1084+
fcinfo->isnull= false;
1085+
}
1086+
else
1087+
{
1088+
if (perlret)SvREFCNT_dec(perlret);
1089+
SRF_RETURN_DONE(funcctx);
1090+
}
1091+
}
10001092
elseif (!fcinfo->isnull)
10011093
{
10021094
retval=FunctionCall3(&prodesc->result_in_func,
@@ -1249,6 +1341,8 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
12491341
}
12501342
}
12511343

1344+
prodesc->fn_retisset=procStruct->proretset;/*true, if function returns set*/
1345+
12521346
if (typeStruct->typtype=='c'||procStruct->prorettype==RECORDOID)
12531347
{
12541348
prodesc->fn_retistuple= true;

‎src/pl/plperl/spi_internal.c

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -82,42 +82,48 @@ plperl_hash_from_tuple(HeapTuple tuple, TupleDesc tupdesc)
8282
* Get the attributes value
8383
************************************************************/
8484
attdata=SPI_getvalue(tuple,tupdesc,i+1);
85+
if(attdata)
8586
hv_store(array,attname,strlen(attname),newSVpv(attdata,0),0);
87+
else
88+
hv_store(array,attname,strlen(attname),newSVpv("undef",0),0);
8689
}
8790
returnarray;
8891
}
8992

9093
staticHV*
91-
plperl_spi_execute_fetch_result(SPITupleTable*tuptable,introws,intstatus)
94+
plperl_spi_execute_fetch_result(SPITupleTable*tuptable,intprocessed,intstatus)
9295
{
9396

9497
HV*result;
98+
AV*rows;
9599
inti;
96100

97101
result=newHV();
102+
rows=newAV();
98103

99104
if (status==SPI_OK_UTILITY)
100105
{
101106
hv_store(result,"status",strlen("status"),newSVpv("SPI_OK_UTILITY",0),0);
102-
hv_store(result,"rows",strlen("rows"),newSViv(rows),0);
107+
hv_store(result,"processed",strlen("processed"),newSViv(processed),0);
103108
}
104109
elseif (status!=SPI_OK_SELECT)
105110
{
106111
hv_store(result,"status",strlen("status"),newSVpv((char*)plperl_spi_status_string(status),0),0);
107-
hv_store(result,"rows",strlen("rows"),newSViv(rows),0);
112+
hv_store(result,"processed",strlen("processed"),newSViv(processed),0);
108113
}
109114
else
110115
{
111-
if (rows)
116+
hv_store(result,"status",strlen("status"),newSVpv((char*)plperl_spi_status_string(status),0),0);
117+
hv_store(result,"processed",strlen("processed"),newSViv(processed),0);
118+
if (processed)
112119
{
113-
char*key=palloc(sizeof(int));
114120
HV*row;
115-
for (i=0;i<rows;i++)
121+
for (i=0;i<processed;i++)
116122
{
117123
row=plperl_hash_from_tuple(tuptable->vals[i],tuptable->tupdesc);
118-
sprintf(key,"%i",i);
119-
hv_store(result,key,strlen(key),newRV_noinc((SV*)row),0);
124+
av_store(rows,i,newRV_noinc((SV*)row));
120125
}
126+
hv_store(result,"rows",strlen("rows"),newRV_noinc((SV*)rows),0);
121127
SPI_freetuptable(tuptable);
122128
}
123129
}

‎src/pl/plperl/spi_internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include"EXTERN.h"
22
#include"perl.h"
33
#include"XSUB.h"
4+
#include"ppport.h"
45

56
intspi_DEBUG(void);
67

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp