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

Commit1944628

Browse files
committed
Fix plpython crash when returning string representation of a RECORD result.
PLyString_ToComposite() blithely overwrote proc->result.out.d, even thoughfor a composite result type the other union variant proc->result.out.r isthe one that should be valid. This could result in a crash if out.r hadin fact been filled in (proc->result.is_rowtype == 1) and then somebodylater attempted to use that data; as per bug #13579 from Paweł Michalak.Just to add insult to injury, it didn't work for RECORD results anyway,because record_in() would refuse the case.Fix by doing the I/O function lookup in a local PLyTypeInfo variable,as we were doing already in PLyObject_ToComposite(). This is not a greattechnique because any fn_extra data allocated by the input function willbe leaked permanently (thanks to using TopMemoryContext as fn_mcxt).But that's a pre-existing issue that is much less serious than a crash,so leave it to be fixed separately.This bug would be a potential security issue, except that plpython isonly available to superusers and the crash requires coding the functionin a way that didn't work before today's patches.Add regression test cases covering all the supported methods of convertingcomposite results.Back-patch to 9.1 where the faulty coding was introduced.
1 parent20bef3f commit1944628

File tree

3 files changed

+259
-2
lines changed

3 files changed

+259
-2
lines changed

‎src/pl/plpython/expected/plpython_composite.out

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ elif typ == 'obj':
6565
type_record.first = first
6666
type_record.second = second
6767
return type_record
68+
elif typ == 'str':
69+
return "('%s',%r)" % (first, second)
6870
$$ LANGUAGE plpythonu;
6971
SELECT * FROM multiout_record_as('dict', 'foo', 1, 'f');
7072
first | second
@@ -78,6 +80,138 @@ SELECT multiout_record_as('dict', 'foo', 1, 'f');
7880
(foo,1)
7981
(1 row)
8082

83+
SELECT * FROM multiout_record_as('dict', null, null, false);
84+
first | second
85+
-------+--------
86+
|
87+
(1 row)
88+
89+
SELECT * FROM multiout_record_as('dict', 'one', null, false);
90+
first | second
91+
-------+--------
92+
one |
93+
(1 row)
94+
95+
SELECT * FROM multiout_record_as('dict', null, 2, false);
96+
first | second
97+
-------+--------
98+
| 2
99+
(1 row)
100+
101+
SELECT * FROM multiout_record_as('dict', 'three', 3, false);
102+
first | second
103+
-------+--------
104+
three | 3
105+
(1 row)
106+
107+
SELECT * FROM multiout_record_as('dict', null, null, true);
108+
first | second
109+
-------+--------
110+
|
111+
(1 row)
112+
113+
SELECT * FROM multiout_record_as('tuple', null, null, false);
114+
first | second
115+
-------+--------
116+
|
117+
(1 row)
118+
119+
SELECT * FROM multiout_record_as('tuple', 'one', null, false);
120+
first | second
121+
-------+--------
122+
one |
123+
(1 row)
124+
125+
SELECT * FROM multiout_record_as('tuple', null, 2, false);
126+
first | second
127+
-------+--------
128+
| 2
129+
(1 row)
130+
131+
SELECT * FROM multiout_record_as('tuple', 'three', 3, false);
132+
first | second
133+
-------+--------
134+
three | 3
135+
(1 row)
136+
137+
SELECT * FROM multiout_record_as('tuple', null, null, true);
138+
first | second
139+
-------+--------
140+
|
141+
(1 row)
142+
143+
SELECT * FROM multiout_record_as('list', null, null, false);
144+
first | second
145+
-------+--------
146+
|
147+
(1 row)
148+
149+
SELECT * FROM multiout_record_as('list', 'one', null, false);
150+
first | second
151+
-------+--------
152+
one |
153+
(1 row)
154+
155+
SELECT * FROM multiout_record_as('list', null, 2, false);
156+
first | second
157+
-------+--------
158+
| 2
159+
(1 row)
160+
161+
SELECT * FROM multiout_record_as('list', 'three', 3, false);
162+
first | second
163+
-------+--------
164+
three | 3
165+
(1 row)
166+
167+
SELECT * FROM multiout_record_as('list', null, null, true);
168+
first | second
169+
-------+--------
170+
|
171+
(1 row)
172+
173+
SELECT * FROM multiout_record_as('obj', null, null, false);
174+
first | second
175+
-------+--------
176+
|
177+
(1 row)
178+
179+
SELECT * FROM multiout_record_as('obj', 'one', null, false);
180+
first | second
181+
-------+--------
182+
one |
183+
(1 row)
184+
185+
SELECT * FROM multiout_record_as('obj', null, 2, false);
186+
first | second
187+
-------+--------
188+
| 2
189+
(1 row)
190+
191+
SELECT * FROM multiout_record_as('obj', 'three', 3, false);
192+
first | second
193+
-------+--------
194+
three | 3
195+
(1 row)
196+
197+
SELECT * FROM multiout_record_as('obj', null, null, true);
198+
first | second
199+
-------+--------
200+
|
201+
(1 row)
202+
203+
SELECT * FROM multiout_record_as('str', 'one', 1, false);
204+
first | second
205+
-------+--------
206+
'one' | 1
207+
(1 row)
208+
209+
SELECT * FROM multiout_record_as('str', 'one', 2, false);
210+
first | second
211+
-------+--------
212+
'one' | 2
213+
(1 row)
214+
81215
SELECT *, s IS NULL AS snull FROM multiout_record_as('tuple', 'xxx', NULL, 'f') AS f(f, s);
82216
f | s | snull
83217
-----+---+-------
@@ -179,10 +313,14 @@ elif typ == 'dict':
179313
d = {'first': n * 2, 'second': n * 3, 'extra': 'not important'}
180314
elif typ == 'tuple':
181315
d = (n * 2, n * 3)
316+
elif typ == 'list':
317+
d = [ n * 2, n * 3 ]
182318
elif typ == 'obj':
183319
class d: pass
184320
d.first = n * 2
185321
d.second = n * 3
322+
elif typ == 'str':
323+
d = "(%r,%r)" % (n * 2, n * 3)
186324
for i in range(n):
187325
yield (i, d)
188326
$$ LANGUAGE plpythonu;
@@ -200,13 +338,48 @@ SELECT * FROM multiout_table_type_setof('dict', 'f', 3);
200338
2 | (6,9)
201339
(3 rows)
202340

341+
SELECT * FROM multiout_table_type_setof('dict', 'f', 7);
342+
n | column2
343+
---+---------
344+
0 | (14,21)
345+
1 | (14,21)
346+
2 | (14,21)
347+
3 | (14,21)
348+
4 | (14,21)
349+
5 | (14,21)
350+
6 | (14,21)
351+
(7 rows)
352+
203353
SELECT * FROM multiout_table_type_setof('tuple', 'f', 2);
204354
n | column2
205355
---+---------
206356
0 | (4,6)
207357
1 | (4,6)
208358
(2 rows)
209359

360+
SELECT * FROM multiout_table_type_setof('tuple', 'f', 3);
361+
n | column2
362+
---+---------
363+
0 | (6,9)
364+
1 | (6,9)
365+
2 | (6,9)
366+
(3 rows)
367+
368+
SELECT * FROM multiout_table_type_setof('list', 'f', 2);
369+
n | column2
370+
---+---------
371+
0 | (4,6)
372+
1 | (4,6)
373+
(2 rows)
374+
375+
SELECT * FROM multiout_table_type_setof('list', 'f', 3);
376+
n | column2
377+
---+---------
378+
0 | (6,9)
379+
1 | (6,9)
380+
2 | (6,9)
381+
(3 rows)
382+
210383
SELECT * FROM multiout_table_type_setof('obj', 'f', 4);
211384
n | column2
212385
---+---------
@@ -216,6 +389,39 @@ SELECT * FROM multiout_table_type_setof('obj', 'f', 4);
216389
3 | (8,12)
217390
(4 rows)
218391

392+
SELECT * FROM multiout_table_type_setof('obj', 'f', 5);
393+
n | column2
394+
---+---------
395+
0 | (10,15)
396+
1 | (10,15)
397+
2 | (10,15)
398+
3 | (10,15)
399+
4 | (10,15)
400+
(5 rows)
401+
402+
SELECT * FROM multiout_table_type_setof('str', 'f', 6);
403+
n | column2
404+
---+---------
405+
0 | (12,18)
406+
1 | (12,18)
407+
2 | (12,18)
408+
3 | (12,18)
409+
4 | (12,18)
410+
5 | (12,18)
411+
(6 rows)
412+
413+
SELECT * FROM multiout_table_type_setof('str', 'f', 7);
414+
n | column2
415+
---+---------
416+
0 | (14,21)
417+
1 | (14,21)
418+
2 | (14,21)
419+
3 | (14,21)
420+
4 | (14,21)
421+
5 | (14,21)
422+
6 | (14,21)
423+
(7 rows)
424+
219425
SELECT * FROM multiout_table_type_setof('dict', 't', 3);
220426
n | column2
221427
---+---------

‎src/pl/plpython/plpy_typeio.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -912,20 +912,30 @@ PLySequence_ToArray(PLyObToDatum *arg, int32 typmod, PyObject *plrv)
912912
staticDatum
913913
PLyString_ToComposite(PLyTypeInfo*info,TupleDescdesc,PyObject*string)
914914
{
915+
Datumresult;
915916
HeapTupletypeTup;
917+
PLyTypeInfolocinfo;
916918
PLyExecutionContext*exec_ctx=PLy_current_execution_context();
917919

920+
/* Create a dummy PLyTypeInfo */
921+
MemSet(&locinfo,0,sizeof(PLyTypeInfo));
922+
PLy_typeinfo_init(&locinfo);
923+
918924
typeTup=SearchSysCache1(TYPEOID,ObjectIdGetDatum(desc->tdtypeid));
919925
if (!HeapTupleIsValid(typeTup))
920926
elog(ERROR,"cache lookup failed for type %u",desc->tdtypeid);
921927

922-
PLy_output_datum_func2(&info->out.d,typeTup,
928+
PLy_output_datum_func2(&locinfo.out.d,typeTup,
923929
exec_ctx->curr_proc->langid,
924930
exec_ctx->curr_proc->trftypes);
925931

926932
ReleaseSysCache(typeTup);
927933

928-
returnPLyObject_ToDatum(&info->out.d,info->out.d.typmod,string);
934+
result=PLyObject_ToDatum(&locinfo.out.d,desc->tdtypmod,string);
935+
936+
PLy_typeinfo_dealloc(&locinfo);
937+
938+
returnresult;
929939
}
930940

931941

‎src/pl/plpython/sql/plpython_composite.sql

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,40 @@ elif typ == 'obj':
3232
type_record.first= first
3333
type_record.second= second
3434
return type_record
35+
elif typ=='str':
36+
return"('%s',%r)" % (first, second)
3537
$$ LANGUAGE plpythonu;
3638

3739
SELECT*FROM multiout_record_as('dict','foo',1,'f');
3840
SELECT multiout_record_as('dict','foo',1,'f');
41+
42+
SELECT*FROM multiout_record_as('dict',null,null, false);
43+
SELECT*FROM multiout_record_as('dict','one',null, false);
44+
SELECT*FROM multiout_record_as('dict',null,2, false);
45+
SELECT*FROM multiout_record_as('dict','three',3, false);
46+
SELECT*FROM multiout_record_as('dict',null,null, true);
47+
48+
SELECT*FROM multiout_record_as('tuple',null,null, false);
49+
SELECT*FROM multiout_record_as('tuple','one',null, false);
50+
SELECT*FROM multiout_record_as('tuple',null,2, false);
51+
SELECT*FROM multiout_record_as('tuple','three',3, false);
52+
SELECT*FROM multiout_record_as('tuple',null,null, true);
53+
54+
SELECT*FROM multiout_record_as('list',null,null, false);
55+
SELECT*FROM multiout_record_as('list','one',null, false);
56+
SELECT*FROM multiout_record_as('list',null,2, false);
57+
SELECT*FROM multiout_record_as('list','three',3, false);
58+
SELECT*FROM multiout_record_as('list',null,null, true);
59+
60+
SELECT*FROM multiout_record_as('obj',null,null, false);
61+
SELECT*FROM multiout_record_as('obj','one',null, false);
62+
SELECT*FROM multiout_record_as('obj',null,2, false);
63+
SELECT*FROM multiout_record_as('obj','three',3, false);
64+
SELECT*FROM multiout_record_as('obj',null,null, true);
65+
66+
SELECT*FROM multiout_record_as('str','one',1, false);
67+
SELECT*FROM multiout_record_as('str','one',2, false);
68+
3969
SELECT*, s ISNULLAS snullFROM multiout_record_as('tuple','xxx',NULL,'f')AS f(f, s);
4070
SELECT*, f ISNULLAS fnull, s ISNULLAS snullFROM multiout_record_as('tuple','xxx',1,'t')AS f(f, s);
4171
SELECT*FROM multiout_record_as('obj',NULL,10,'f');
@@ -92,18 +122,29 @@ elif typ == 'dict':
92122
d= {'first': n*2,'second': n*3,'extra':'not important'}
93123
elif typ=='tuple':
94124
d= (n*2, n*3)
125+
elif typ=='list':
126+
d= [ n*2, n*3 ]
95127
elif typ=='obj':
96128
class d: pass
97129
d.first= n*2
98130
d.second= n*3
131+
elif typ=='str':
132+
d="(%r,%r)" % (n*2, n*3)
99133
for iin range(n):
100134
yield (i, d)
101135
$$ LANGUAGE plpythonu;
102136

103137
SELECT*FROM multiout_composite(2);
104138
SELECT*FROM multiout_table_type_setof('dict','f',3);
139+
SELECT*FROM multiout_table_type_setof('dict','f',7);
105140
SELECT*FROM multiout_table_type_setof('tuple','f',2);
141+
SELECT*FROM multiout_table_type_setof('tuple','f',3);
142+
SELECT*FROM multiout_table_type_setof('list','f',2);
143+
SELECT*FROM multiout_table_type_setof('list','f',3);
106144
SELECT*FROM multiout_table_type_setof('obj','f',4);
145+
SELECT*FROM multiout_table_type_setof('obj','f',5);
146+
SELECT*FROM multiout_table_type_setof('str','f',6);
147+
SELECT*FROM multiout_table_type_setof('str','f',7);
107148
SELECT*FROM multiout_table_type_setof('dict','t',3);
108149

109150
-- check what happens if a type changes under us

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp