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

Commit22b9ce7

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 parentf7ed465 commit22b9ce7

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
@@ -863,18 +863,28 @@ PLySequence_ToArray(PLyObToDatum *arg, int32 typmod, PyObject *plrv)
863863
staticDatum
864864
PLyString_ToComposite(PLyTypeInfo*info,TupleDescdesc,PyObject*string)
865865
{
866+
Datumresult;
866867
HeapTupletypeTup;
868+
PLyTypeInfolocinfo;
869+
870+
/* Create a dummy PLyTypeInfo */
871+
MemSet(&locinfo,0,sizeof(PLyTypeInfo));
872+
PLy_typeinfo_init(&locinfo);
867873

868874
typeTup=SearchSysCache1(TYPEOID,ObjectIdGetDatum(desc->tdtypeid));
869875
if (!HeapTupleIsValid(typeTup))
870876
elog(ERROR,"cache lookup failed for type %u",desc->tdtypeid);
871877

872-
PLy_output_datum_func2(&info->out.d,typeTup);
878+
PLy_output_datum_func2(&locinfo.out.d,typeTup);
873879

874880
ReleaseSysCache(typeTup);
875881
ReleaseTupleDesc(desc);
876882

877-
returnPLyObject_ToDatum(&info->out.d,info->out.d.typmod,string);
883+
result=PLyObject_ToDatum(&locinfo.out.d,desc->tdtypmod,string);
884+
885+
PLy_typeinfo_dealloc(&locinfo);
886+
887+
returnresult;
878888
}
879889

880890

‎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