@@ -169,53 +169,80 @@ PLyObject_FromJsonbContainer(JsonbContainer *jsonb)
169169 if (!result )
170170 return NULL ;
171171
172- while (( r = JsonbIteratorNext ( & it , & v , true)) != WJB_DONE )
172+ PG_TRY ();
173173 {
174- if ( r == WJB_ELEM )
174+ while (( r = JsonbIteratorNext ( & it , & v , true)) != WJB_DONE )
175175 {
176- PyObject * elem = PLyObject_FromJsonbValue (& v );
176+ if (r == WJB_ELEM )
177+ {
178+ PyObject * elem = PLyObject_FromJsonbValue (& v );
179+
180+ if (!elem || PyList_Append (result , elem ))
181+ {
182+ Py_XDECREF (elem );
183+ Py_DECREF (result );
184+ return NULL ;
185+ }
177186
178- PyList_Append ( result , elem );
179- Py_XDECREF ( elem );
187+ Py_DECREF ( elem );
188+ }
180189 }
181190 }
191+ PG_CATCH ();
192+ {
193+ Py_DECREF (result );
194+ PG_RE_THROW ();
195+ }
196+ PG_END_TRY ();
182197 }
183198 break ;
184199
185200 case WJB_BEGIN_OBJECT :
186- result = PyDict_New ();
187- if (!result )
188- return NULL ;
189-
190- while ((r = JsonbIteratorNext (& it , & v , true)) != WJB_DONE )
191201 {
192- if (r == WJB_KEY )
193- {
194- PyObject * key = PLyString_FromJsonbValue (& v );
195-
196- if (!key )
197- return NULL ;
202+ PyObject * volatile key = NULL ;
198203
199- r = JsonbIteratorNext (& it , & v , true);
204+ result = PyDict_New ();
205+ if (!result )
206+ return NULL ;
200207
201- if (r == WJB_VALUE )
208+ PG_TRY ();
209+ {
210+ while ((r = JsonbIteratorNext (& it , & v , true)) != WJB_DONE )
202211 {
203- PyObject * value = PLyObject_FromJsonbValue (& v );
212+ JsonbValue v2 ;
213+ PyObject * val = NULL ;
214+
215+ if (r != WJB_KEY )
216+ continue ;
217+
218+ if ((r = JsonbIteratorNext (& it , & v2 , true)) != WJB_VALUE )
219+ elog (ERROR , "unexpected jsonb token: %d" , r );
204220
205- if (!value )
221+ if (!(key = PLyString_FromJsonbValue (& v )) ||
222+ !(val = PLyObject_FromJsonbValue (& v2 )) ||
223+ PyDict_SetItem (result , key , val ))
206224 {
207225 Py_XDECREF (key );
226+ Py_XDECREF (val );
227+ Py_DECREF (result );
208228 return NULL ;
209229 }
210230
211- PyDict_SetItem (result , key , value );
212- Py_XDECREF (value );
231+ Py_DECREF (val );
232+ Py_DECREF (key );
233+ key = NULL ;
213234 }
214-
235+ }
236+ PG_CATCH ();
237+ {
215238 Py_XDECREF (key );
239+ Py_DECREF (result );
240+ PG_RE_THROW ();
216241 }
242+ PG_END_TRY ();
243+
244+ break ;
217245 }
218- break ;
219246
220247 default :
221248 elog (ERROR , "unexpected jsonb token: %d" , r );
@@ -233,30 +260,40 @@ PLyObject_FromJsonbContainer(JsonbContainer *jsonb)
233260static JsonbValue *
234261PLyMapping_ToJsonbValue (PyObject * obj , JsonbParseState * * jsonb_state )
235262{
236- Py_ssize_t pcount ;
237- JsonbValue * out = NULL ;
263+ JsonbValue * out ;
264+ PyObject * items ;
265+ Py_ssize_t pcount = PyMapping_Size (obj );
266+
267+ if (pcount < 0 )
268+ PLy_elog (ERROR , "PyMapping_Size() failed, while converting mapping into jsonb" );
238269
239- /* We need it volatile, since we use it after longjmp */
240- volatile PyObject * items_v = NULL ;
270+ items = PyMapping_Items (obj );
241271
242- pcount = PyMapping_Size ( obj );
243- items_v = PyMapping_Items (obj );
272+ if (! items )
273+ PLy_elog ( ERROR , " PyMapping_Items() failed, while converting mapping into jsonb" );
244274
245275 PG_TRY ();
246276 {
247277 Py_ssize_t i ;
248- PyObject * items ;
249-
250- items = (PyObject * ) items_v ;
251278
252279 pushJsonbValue (jsonb_state , WJB_BEGIN_OBJECT , NULL );
253280
254281 for (i = 0 ; i < pcount ; i ++ )
255282 {
256283 JsonbValue jbvKey ;
257- PyObject * item = PyList_GetItem (items , i );
258- PyObject * key = PyTuple_GetItem (item , 0 );
259- PyObject * value = PyTuple_GetItem (item , 1 );
284+ PyObject * item ;
285+ PyObject * key ;
286+ PyObject * value ;
287+
288+ item = PyList_GetItem (items , i ); /* borrowed reference */
289+ if (!item )
290+ PLy_elog (ERROR , "PyList_GetItem() failed, while converting mapping into jsonb" );
291+
292+ key = PyTuple_GetItem (item , 0 ); /* borrowed references */
293+ value = PyTuple_GetItem (item , 1 );
294+
295+ if (!key || !value )
296+ PLy_elog (ERROR , "PyTuple_GetItem() failed, while converting mapping into jsonb" );
260297
261298 /* Python dictionary can have None as key */
262299 if (key == Py_None )
@@ -279,11 +316,13 @@ PLyMapping_ToJsonbValue(PyObject *obj, JsonbParseState **jsonb_state)
279316 }
280317 PG_CATCH ();
281318 {
282- Py_DECREF (items_v );
319+ Py_DECREF (items );
283320 PG_RE_THROW ();
284321 }
285322 PG_END_TRY ();
286323
324+ Py_DECREF (items );
325+
287326 return out ;
288327}
289328
@@ -296,21 +335,36 @@ PLyMapping_ToJsonbValue(PyObject *obj, JsonbParseState **jsonb_state)
296335static JsonbValue *
297336PLySequence_ToJsonbValue (PyObject * obj , JsonbParseState * * jsonb_state )
298337{
299- Py_ssize_t i ;
300- Py_ssize_t pcount ;
338+ PyObject * seq = PySequence_Fast (obj , "object is not a sequence" );
301339
302- pcount = PySequence_Size (obj );
340+ if (!seq )
341+ PLy_elog (ERROR , "PySequence_Fast() failed, while converting sequence into jsonb" );
303342
304- pushJsonbValue (jsonb_state , WJB_BEGIN_ARRAY , NULL );
305-
306- for (i = 0 ; i < pcount ; i ++ )
343+ PG_TRY ();
307344 {
308- PyObject * value = PySequence_GetItem (obj , i );
345+ Py_ssize_t i ;
346+ Py_ssize_t pcount = PySequence_Fast_GET_SIZE (seq );
309347
310- ( void ) PLyObject_ToJsonbValue ( value , jsonb_state , true );
348+ pushJsonbValue ( jsonb_state , WJB_BEGIN_ARRAY , NULL );
311349
312- Py_XDECREF (value );
350+ for (i = 0 ; i < pcount ; i ++ )
351+ {
352+ PyObject * value = PySequence_Fast_GET_ITEM (seq , i ); /* borrowed reference */
353+
354+ if (!value )
355+ PLy_elog (ERROR , "PySequence_Fast_GET_ITEM() failed, while converting sequence into jsonb" );
356+
357+ (void ) PLyObject_ToJsonbValue (value , jsonb_state , true);
358+ }
313359 }
360+ PG_CATCH ();
361+ {
362+ Py_DECREF (seq );
363+ PG_RE_THROW ();
364+ }
365+ PG_END_TRY ();
366+
367+ Py_DECREF (seq );
314368
315369 return pushJsonbValue (jsonb_state , WJB_END_ARRAY , NULL );
316370}
0 commit comments