@@ -125,8 +125,8 @@ RealNumber_Check(PyObject *obj);
125
125
static double
126
126
PySequence_GetItem_AsDouble (PyObject * seq , Py_ssize_t index );
127
127
static int
128
- PySequence_AsVectorCoords (PyObject * seq , double * const coords ,
129
- const Py_ssize_t size );
128
+ pg_VectorCoordsFromObjOldDontUseInNewCode (PyObject * seq , double * const coords ,
129
+ Py_ssize_t size );
130
130
static int
131
131
pgVectorCompatible_Check (PyObject * obj , Py_ssize_t dim );
132
132
static int
@@ -397,13 +397,26 @@ PySequence_GetItem_AsDouble(PyObject *seq, Py_ssize_t index)
397
397
return value ;
398
398
}
399
399
400
+ /* Use pg_VectorCoordsFromObj instead of this function. That does exact dim
401
+ * checking.
402
+ * Note that this function sets a python exception on failures */
400
403
static int
401
- PySequence_AsVectorCoords (PyObject * seq , double * const coords ,
402
- const Py_ssize_t size )
404
+ pg_VectorCoordsFromObjOldDontUseInNewCode (PyObject * seq , double * const coords ,
405
+ Py_ssize_t size )
403
406
{
404
407
Py_ssize_t i ;
405
408
409
+ /* This codepath does not do exact size checking, but for compat reasons
410
+ * we are gonna keep it as it is */
406
411
if (pgVector_Check (seq )) {
412
+ int seq_dim = ((pgVector * )seq )-> dim ;
413
+ if (size > seq_dim ) {
414
+ /* Prevent undefined behaviour by consistently 0-ing extra dims */
415
+ for (Py_ssize_t i = seq_dim ; i < size ; ++ i ) {
416
+ coords [i ] = 0.0 ;
417
+ }
418
+ size = seq_dim ;
419
+ }
407
420
memcpy (coords , ((pgVector * )seq )-> coords , sizeof (double ) * size );
408
421
return 1 ;
409
422
}
@@ -464,8 +477,7 @@ pgVectorCompatible_Check(PyObject *obj, Py_ssize_t dim)
464
477
// copies vector coordinates into "coords" array of size >= dim
465
478
// managed by caller. Returns 0 if obj is not compatible or an error
466
479
// occurred. If 0 is returned, the error flag will not normally be set.
467
- // Callers should set error themselves. This function is a combo of
468
- // pgVectorCompatible_Check and PySequence_AsVectorCoords
480
+ // Callers should set error themselves.
469
481
static int
470
482
pg_VectorCoordsFromObj (PyObject * obj , Py_ssize_t dim , double * const coords )
471
483
{
@@ -1129,7 +1141,7 @@ vector_SetSlice(pgVector *self, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject *v)
1129
1141
}
1130
1142
1131
1143
len = ihigh - ilow ;
1132
- if (!PySequence_AsVectorCoords (v , new_coords , len )) {
1144
+ if (!pg_VectorCoordsFromObjOldDontUseInNewCode (v , new_coords , len )) {
1133
1145
return -1 ;
1134
1146
}
1135
1147
@@ -1250,7 +1262,8 @@ vector_ass_subscript(pgVector *self, PyObject *key, PyObject *value)
1250
1262
double seqitems [VECTOR_MAX_SIZE ];
1251
1263
Py_ssize_t cur , i ;
1252
1264
1253
- if (!PySequence_AsVectorCoords (value , seqitems , slicelength )) {
1265
+ if (!pg_VectorCoordsFromObjOldDontUseInNewCode (value , seqitems ,
1266
+ slicelength )) {
1254
1267
return -1 ;
1255
1268
}
1256
1269
for (cur = start , i = 0 ; i < slicelength ; cur += step , i ++ ) {
@@ -1381,7 +1394,7 @@ vector_richcompare(PyObject *o1, PyObject *o2, int op)
1381
1394
vec = (pgVector * )o2 ;
1382
1395
other = o1 ;
1383
1396
}
1384
- if (!pgVectorCompatible_Check (other , vec -> dim )) {
1397
+ if (!pg_VectorCoordsFromObj (other , vec -> dim , other_coords )) {
1385
1398
if (op == Py_EQ ) {
1386
1399
Py_RETURN_FALSE ;
1387
1400
}
@@ -1394,10 +1407,6 @@ vector_richcompare(PyObject *o1, PyObject *o2, int op)
1394
1407
}
1395
1408
}
1396
1409
1397
- if (!PySequence_AsVectorCoords (other , other_coords , vec -> dim )) {
1398
- return NULL ;
1399
- }
1400
-
1401
1410
switch (op ) {
1402
1411
case Py_EQ :
1403
1412
for (i = 0 ; i < vec -> dim ; i ++ ) {
@@ -1493,7 +1502,8 @@ static PyObject *
1493
1502
vector_dot (pgVector * self , PyObject * other )
1494
1503
{
1495
1504
double other_coords [VECTOR_MAX_SIZE ];
1496
- if (!PySequence_AsVectorCoords (other , other_coords , self -> dim )) {
1505
+ if (!pg_VectorCoordsFromObjOldDontUseInNewCode (other , other_coords ,
1506
+ self -> dim )) {
1497
1507
return RAISE (PyExc_TypeError ,
1498
1508
"Cannot perform dot product with this type." );
1499
1509
}
@@ -1630,7 +1640,8 @@ vector_slerp(pgVector *self, PyObject *args)
1630
1640
if (!PyArg_ParseTuple (args , "Od:slerp" , & other , & t )) {
1631
1641
return NULL ;
1632
1642
}
1633
- if (!PySequence_AsVectorCoords (other , other_coords , self -> dim )) {
1643
+ if (!pg_VectorCoordsFromObjOldDontUseInNewCode (other , other_coords ,
1644
+ self -> dim )) {
1634
1645
return RAISE (PyExc_TypeError , "Argument 1 must be a vector." );
1635
1646
}
1636
1647
if (fabs (t ) > 1 ) {
@@ -1701,7 +1712,8 @@ vector_lerp(pgVector *self, PyObject *args)
1701
1712
if (!PyArg_ParseTuple (args , "Od:Vector.lerp" , & other , & t )) {
1702
1713
return NULL ;
1703
1714
}
1704
- if (!PySequence_AsVectorCoords (other , other_coords , self -> dim )) {
1715
+ if (!pg_VectorCoordsFromObjOldDontUseInNewCode (other , other_coords ,
1716
+ self -> dim )) {
1705
1717
return RAISE (PyExc_TypeError , "Expected Vector as argument 1" );
1706
1718
}
1707
1719
if (t < 0 || t > 1 ) {
@@ -1730,7 +1742,8 @@ vector_smoothstep(pgVector *self, PyObject *args)
1730
1742
if (!PyArg_ParseTuple (args , "Od:Vector.smoothstep" , & other , & t )) {
1731
1743
return NULL ;
1732
1744
}
1733
- if (!PySequence_AsVectorCoords (other , other_coords , self -> dim )) {
1745
+ if (!pg_VectorCoordsFromObjOldDontUseInNewCode (other , other_coords ,
1746
+ self -> dim )) {
1734
1747
return RAISE (PyExc_TypeError , "Expected Vector as argument 1" );
1735
1748
}
1736
1749
@@ -1765,7 +1778,7 @@ _vector_reflect_helper(double *dst_coords, const double *src_coords,
1765
1778
double norm_coords [VECTOR_MAX_SIZE ];
1766
1779
1767
1780
/* normalize the normal */
1768
- if (!PySequence_AsVectorCoords (normal , norm_coords , dim )) {
1781
+ if (!pg_VectorCoordsFromObjOldDontUseInNewCode (normal , norm_coords , dim )) {
1769
1782
return 0 ;
1770
1783
}
1771
1784
@@ -1992,7 +2005,8 @@ vector_project_onto(pgVector *self, PyObject *other)
1992
2005
double a_dot_b ;
1993
2006
double b_dot_b ;
1994
2007
1995
- if (!PySequence_AsVectorCoords (other , other_coords , self -> dim )) {
2008
+ if (!pg_VectorCoordsFromObjOldDontUseInNewCode (other , other_coords ,
2009
+ self -> dim )) {
1996
2010
return RAISE (PyExc_TypeError , "Expected Vector as argument 1" );
1997
2011
}
1998
2012
@@ -3795,12 +3809,8 @@ vector_elementwiseproxy_richcompare(PyObject *o1, PyObject *o2, int op)
3795
3809
}
3796
3810
dim = vec -> dim ;
3797
3811
3798
- if (pgVectorCompatible_Check (other , dim )) {
3799
- double other_coords [VECTOR_MAX_SIZE ];
3800
-
3801
- if (!PySequence_AsVectorCoords (other , other_coords , dim )) {
3802
- return NULL ;
3803
- }
3812
+ double other_coords [VECTOR_MAX_SIZE ];
3813
+ if (pg_VectorCoordsFromObj (other , dim , other_coords )) {
3804
3814
/* use diff == diff to check for NaN */
3805
3815
/* TODO: how should NaN be handled with LT/LE/GT/GE? */
3806
3816
switch (op ) {
@@ -3955,11 +3965,8 @@ vector_elementwiseproxy_generic_math(PyObject *o1, PyObject *o2, int op)
3955
3965
other = (PyObject * )((vector_elementwiseproxy * )other )-> vec ;
3956
3966
}
3957
3967
3958
- if (pgVectorCompatible_Check (other , dim )) {
3968
+ if (pg_VectorCoordsFromObj (other , dim , other_coords )) {
3959
3969
op |= OP_ARG_VECTOR ;
3960
- if (!PySequence_AsVectorCoords (other , other_coords , dim )) {
3961
- return NULL ;
3962
- }
3963
3970
}
3964
3971
else {
3965
3972
other_value = PyFloat_AsDouble (other );
0 commit comments