@@ -1174,6 +1174,50 @@ pyexpat_xmlparser_UseForeignDTD_impl(xmlparseobject *self, PyTypeObject *cls,
11741174}
11751175#endif
11761176
1177+ #if XML_COMBINED_VERSION >= 20702
1178+ static PyObject *
1179+ set_activation_threshold (xmlparseobject * self ,
1180+ PyTypeObject * cls ,
1181+ unsigned long long threshold ,
1182+ XML_Bool (* setter )(XML_Parser , unsigned long long ))
1183+ {
1184+ assert (self -> itself != NULL );
1185+ if (setter (self -> itself , threshold ) == XML_TRUE ) {
1186+ Py_RETURN_NONE ;
1187+ }
1188+ // The setter fails if self->itself is NULL (which is not possible here)
1189+ // or is a non-root parser, which currently only happens for parsers
1190+ // created by ExternalEntityParserCreate().
1191+ pyexpat_state * state = PyType_GetModuleState (cls );
1192+ return set_invalid_arg (state , self , "parser must be a root parser" );
1193+ }
1194+
1195+ static PyObject *
1196+ set_maximum_amplification (xmlparseobject * self ,
1197+ PyTypeObject * cls ,
1198+ float max_factor ,
1199+ XML_Bool (* setter )(XML_Parser , float ))
1200+ {
1201+ assert (self -> itself != NULL );
1202+ if (setter (self -> itself , max_factor ) == XML_TRUE ) {
1203+ Py_RETURN_NONE ;
1204+ }
1205+ // The setter fails if self->itself is NULL (which is not possible here),
1206+ // is a non-root parser, which currently only happens for parsers created
1207+ // by ExternalEntityParserCreate(), or if 'max_factor' is NaN or < 1.0.
1208+ pyexpat_state * state = PyType_GetModuleState (cls );
1209+ // Note: Expat has no API to determine whether a parser is a root parser,
1210+ // and since the Expat functions for defining the various maximum allowed
1211+ // amplifcation factors fail when a bad parser or a out-of-range factor
1212+ // is given without specifying which check failed, we check whether the
1213+ // factor is out-of-range to improve the error message. See also gh-90949.
1214+ const char * message = (isnan (max_factor ) || max_factor < 1.0f )
1215+ ? "'max_factor' must be at least 1.0"
1216+ : "parser must be a root parser" ;
1217+ return set_invalid_arg (state , self , message );
1218+ }
1219+ #endif
1220+
11771221#if XML_COMBINED_VERSION >= 20702
11781222/*[clinic input]
11791223@permit_long_summary
@@ -1195,15 +1239,10 @@ pyexpat_xmlparser_SetAllocTrackerActivationThreshold_impl(xmlparseobject *self,
11951239 unsigned long long threshold )
11961240/*[clinic end generated code: output=bed7e93207ba08c5 input=54182cd71ad69978]*/
11971241{
1198- assert (self -> itself != NULL );
1199- if (XML_SetAllocTrackerActivationThreshold (self -> itself , threshold ) == XML_TRUE ) {
1200- Py_RETURN_NONE ;
1201- }
1202- // XML_SetAllocTrackerActivationThreshold() can only fail if self->itself
1203- // is not a root parser (currently, this is equivalent to be created
1204- // by ExternalEntityParserCreate()).
1205- pyexpat_state * state = PyType_GetModuleState (cls );
1206- return set_invalid_arg (state , self , "parser must be a root parser" );
1242+ return set_activation_threshold (
1243+ self , cls , threshold ,
1244+ XML_SetAllocTrackerActivationThreshold
1245+ );
12071246}
12081247#endif
12091248
@@ -1238,24 +1277,10 @@ pyexpat_xmlparser_SetAllocTrackerMaximumAmplification_impl(xmlparseobject *self,
12381277 float max_factor )
12391278/*[clinic end generated code: output=6e44bd48c9b112a0 input=3544abf9dd7ae055]*/
12401279{
1241- assert (self -> itself != NULL );
1242- if (XML_SetAllocTrackerMaximumAmplification (self -> itself , max_factor ) == XML_TRUE ) {
1243- Py_RETURN_NONE ;
1244- }
1245- // XML_SetAllocTrackerMaximumAmplification() can fail if self->itself
1246- // is not a root parser (currently, this is equivalent to be created
1247- // by ExternalEntityParserCreate()) or if 'max_factor' is NaN or < 1.0.
1248- //
1249- // Expat does not provide a way to determine whether a parser is a root
1250- // or not, nor does it provide a way to distinguish between failures in
1251- // XML_SetAllocTrackerMaximumAmplification() (see gh-90949), we manually
1252- // detect the factor out-of-range issue here so that users have a better
1253- // error message.
1254- pyexpat_state * state = PyType_GetModuleState (cls );
1255- const char * message = (isnan (max_factor ) || max_factor < 1.0f )
1256- ? "'max_factor' must be at least 1.0"
1257- : "parser must be a root parser" ;
1258- return set_invalid_arg (state , self , message );
1280+ return set_maximum_amplification (
1281+ self , cls , max_factor ,
1282+ XML_SetAllocTrackerMaximumAmplification
1283+ );
12591284}
12601285#endif
12611286
0 commit comments