@@ -9,28 +9,35 @@ import_librt_internal(void)
99 if (mod == NULL )
1010 return -1 ;
1111 Py_DECREF (mod ); // we import just for the side effect of making the below work.
12- void * capsule = PyCapsule_Import ("librt.internal._C_API" , 0 );
12+ void * * capsule = ( void * * ) PyCapsule_Import ("librt.internal._C_API" , 0 );
1313 if (capsule == NULL )
1414 return -1 ;
15- memcpy (NativeInternal_API , capsule , sizeof (NativeInternal_API ));
16- if (NativeInternal_ABI_Version () != LIBRT_INTERNAL_ABI_VERSION ) {
15+
16+ // Each librt capsule gives at least 20 entries. Validate version before copying the table.
17+ int (* abi_version )(void ) = (int (* )(void ))capsule [13 ];
18+ if (abi_version () != LIBRT_INTERNAL_ABI_VERSION ) {
1719 char err [128 ];
1820 snprintf (err , sizeof (err ), "ABI version conflict for librt.internal, expected %d, found %d" ,
1921 LIBRT_INTERNAL_ABI_VERSION ,
20- NativeInternal_ABI_Version ()
22+ abi_version ()
2123 );
2224 PyErr_SetString (PyExc_ValueError , err );
2325 return -1 ;
2426 }
25- if (NativeInternal_API_Version () < LIBRT_INTERNAL_API_VERSION ) {
27+ int (* api_version )(void ) = (int (* )(void ))capsule [19 ];
28+ if (api_version () < LIBRT_INTERNAL_API_VERSION ) {
2629 char err [128 ];
2730 snprintf (err , sizeof (err ),
2831 "API version conflict for librt.internal, expected %d or newer, found %d (hint: upgrade librt)" ,
2932 LIBRT_INTERNAL_API_VERSION ,
30- NativeInternal_API_Version ()
33+ api_version ()
3134 );
3235 PyErr_SetString (PyExc_ValueError , err );
3336 return -1 ;
3437 }
38+ // Provider API version is >= our expected version, which (by the API
39+ // compatibility contract) means it has at least LIBRT_INTERNAL_API_LEN
40+ // entries, so this copy is safe.
41+ memcpy (NativeInternal_API , capsule , sizeof (NativeInternal_API ));
3542 return 0 ;
3643}
0 commit comments