@@ -30,8 +30,11 @@ typecast_INTEGER_cast(unsigned char *s, int len, PyObject *curs)
3030 unsigned char buffer [12 ];
3131
3232 if (s == NULL ) {Py_INCREF (Py_None ); return Py_None ;}
33- strncpy (buffer , s , len ); buffer [len ] = '\0' ;
34- return PyInt_FromString (buffer , NULL , 0 );
33+ if (s [len ] != '\0' ) {
34+ strncpy (buffer , s , len ); buffer [len ] = '\0' ;
35+ s = buffer ;
36+ }
37+ return PyInt_FromString (s , NULL , 0 );
3538}
3639
3740/** LONGINTEGER - cast long integers (8 bytes) to python long **/
@@ -42,7 +45,10 @@ typecast_LONGINTEGER_cast(unsigned char *s, int len, PyObject *curs)
4245 unsigned char buffer [24 ];
4346
4447 if (s == NULL ) {Py_INCREF (Py_None ); return Py_None ;}
45- strncpy (buffer , s , len ); buffer [len ] = '\0' ;
48+ if (s [len ] != '\0' ) {
49+ strncpy (buffer , s , len ); buffer [len ] = '\0' ;
50+ s = buffer ;
51+ }
4652 return PyLong_FromString (s , NULL , 0 );
4753}
4854
@@ -51,10 +57,14 @@ typecast_LONGINTEGER_cast(unsigned char *s, int len, PyObject *curs)
5157static PyObject *
5258typecast_FLOAT_cast (unsigned char * s , int len , PyObject * curs )
5359{
60+ /* FIXME: is 64 large enough for any float? */
5461 unsigned char buffer [64 ];
5562
5663 if (s == NULL ) {Py_INCREF (Py_None ); return Py_None ;}
57- strncpy (buffer , s , len ); buffer [len ] = '\0' ;
64+ if (s [len ] != '\0' ) {
65+ strncpy (buffer , s , len ); buffer [len ] = '\0' ;
66+ s = buffer ;
67+ }
5868 return PyFloat_FromDouble (atof (s ));
5969}
6070
@@ -144,17 +154,23 @@ static PyObject *
144154typecast_BINARY_cast (unsigned char * s , int l , PyObject * curs )
145155{
146156 PyObject * res ;
147- unsigned char * str , saved ;
157+ unsigned char * str , * buffer = NULL ;
148158 size_t len ;
149159
150160 if (s == NULL ) {Py_INCREF (Py_None ); return Py_None ;}
151161
152162 /* PQunescapeBytea absolutely wants a 0-terminated string and we don't
153- want to copy the whole buffer, right? Wrong... :/ */
154- saved = s [l ]; s [l ] = '\0' ;
163+ want to copy the whole buffer, right? Wrong, but there isn't any other
164+ way :/ */
165+ if (s [l ] != '\0' ) {
166+ if ((buffer = PyMem_Malloc (l + 1 )) == NULL )
167+ PyErr_NoMemory ();
168+ strncpy (buffer , s , l ); buffer [l ] = '\0' ;
169+ s = buffer ;
170+ }
155171 str = PQunescapeBytea (s , & len );
156172 Dprintf ("typecast_BINARY_cast: unescaped %d bytes" , len );
157- s [ l ] = saved ;
173+ if ( buffer ) PyMem_Free ( buffer ) ;
158174
159175 /* TODO: using a PyBuffer would make this a zero-copy operation but we'll
160176 need to define our own buffer-derived object to keep a reference to the
@@ -196,7 +212,8 @@ typecast_DECIMAL_cast(unsigned char *s, int len, PyObject *curs)
196212
197213 if (s == NULL ) {Py_INCREF (Py_None ); return Py_None ;}
198214
199- buffer = PyMem_Malloc (len + 1 );
215+ if ((buffer = PyMem_Malloc (len + 1 )) == NULL )
216+ PyErr_NoMemory ();
200217 strncpy (buffer , s , len ); buffer [len ] = '\0' ;
201218 res = PyObject_CallFunction (decimalType , "s" , buffer );
202219 PyMem_Free (buffer );
0 commit comments