Skip to content

Commit 7cf2550

Browse files
committed
python-native: Fix handling of size_t arguments
1 parent a1b91ea commit 7cf2550

File tree

1 file changed

+67
-37
lines changed

1 file changed

+67
-37
lines changed

src/interrogate/interfaceMakerPythonNative.cxx

Lines changed: 67 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -5129,6 +5129,7 @@ write_function_instance(ostream &out, FunctionRemap *remap,
51295129
bool has_keywords = false;
51305130
vector_string pexprs;
51315131
LineStream extra_convert;
5132+
ostringstream extra_type_check;
51325133
ostringstream extra_param_check;
51335134
LineStream extra_cleanup;
51345135
int min_version = 0;
@@ -5589,42 +5590,45 @@ write_function_instance(ostream &out, FunctionRemap *remap,
55895590
only_pyobjects = false;
55905591

55915592
} else if (TypeManager::is_size(type)) {
5593+
// There is no default format specifier mapping to size_t.
55925594
if (args_type == AT_single_arg) {
5595+
param_name = "arg";
55935596
type_check = "PyLongOrInt_Check(arg)";
5597+
} else {
5598+
indent(out, indent_level) << "PyObject *" << param_name << null_assign << ";\n";
5599+
if (is_optional) {
5600+
extra_type_check << " && (" << param_name << " == nullptr || PyLongOrInt_Check(" << param_name << "))";
5601+
} else {
5602+
extra_type_check << " && PyLongOrInt_Check(" << param_name << ")";
5603+
}
5604+
format_specifiers += "O";
5605+
parameter_list += ", &" + param_name;
5606+
}
5607+
expected_params += "int";
5608+
pexpr_string = param_name + "_val";
55945609

5610+
if (is_optional) {
55955611
extra_convert <<
5596-
"size_t arg_val = PyLongOrInt_AsSize_t(arg);\n"
5612+
"size_t " << param_name << "_val" << default_expr << ";\n"
5613+
"if (" << param_name << " != nullptr) {\n"
5614+
" " << param_name << "_val = PyLongOrInt_AsSize_t(" << param_name << ");\n"
55975615
"#ifndef NDEBUG\n"
5598-
"if (arg_val == (size_t)-1 && PyErr_Occurred()) {\n";
5616+
" if (" << param_name << "_val == (size_t)-1 && PyErr_Occurred()) {\n";
5617+
error_return(extra_convert, 5, return_flags);
5618+
extra_convert <<
5619+
" }\n"
5620+
"#endif\n"
5621+
"}";
5622+
} else {
5623+
extra_convert <<
5624+
"size_t " << param_name << "_val = PyLongOrInt_AsSize_t(" << param_name << ");\n"
5625+
"#ifndef NDEBUG\n"
5626+
"if (" << param_name << "_val == (size_t)-1 && PyErr_Occurred()) {\n";
55995627
error_return(extra_convert, 2, return_flags);
56005628
extra_convert <<
56015629
"}\n"
56025630
"#endif\n";
5603-
5604-
pexpr_string = "arg_val";
5605-
5606-
} else {
5607-
// It certainly isn't the exact same thing as size_t, but Py_ssize_t
5608-
// should at least be the same size. The problem with mapping this to
5609-
// unsigned int is that that doesn't work well on 64-bit systems, on
5610-
// which size_t is a 64-bit integer.
5611-
indent(out, indent_level) << "Py_ssize_t " << param_name << default_expr << ";\n";
5612-
format_specifiers += "n";
5613-
parameter_list += ", &" + param_name;
5614-
5615-
extra_convert
5616-
<< "#ifndef NDEBUG\n"
5617-
<< "if (" << param_name << " < 0) {\n";
5618-
5619-
error_raise_return(extra_convert, 2, return_flags, "OverflowError",
5620-
"can't convert negative value %zd to size_t",
5621-
param_name);
5622-
extra_convert
5623-
<< "}\n"
5624-
<< "#endif\n";
56255631
}
5626-
expected_params += "int";
5627-
only_pyobjects = false;
56285632

56295633
} else if (TypeManager::is_longlong(type)) {
56305634
// It's not trivial to do overflow checking for a long long, so we
@@ -6331,6 +6335,15 @@ write_function_instance(ostream &out, FunctionRemap *remap,
63316335
// Track how many curly braces we've opened.
63326336
short open_scopes = 0;
63336337

6338+
// extra_type_check is done before extra_convert, extra_param_check after.
6339+
string extra_type_check_str = extra_type_check.str();
6340+
if (!extra_type_check_str.empty() && args_type == AT_single_arg) {
6341+
if (type_check.empty()) {
6342+
type_check = "true";
6343+
}
6344+
type_check += extra_type_check_str;
6345+
}
6346+
63346347
if (!type_check.empty() && args_type == AT_single_arg) {
63356348
indent(out, indent_level)
63366349
<< "if (" << type_check << ") {\n";
@@ -6350,10 +6363,12 @@ write_function_instance(ostream &out, FunctionRemap *remap,
63506363
// case we have implemented ourselves.
63516364
if (min_num_args == 1) {
63526365
indent(out, indent_level)
6353-
<< "if (Dtool_ExtractArg(&" << param_name << ", args, kwds, " << keyword_list_new << ")) {\n";
6366+
<< "if (Dtool_ExtractArg(&" << param_name << ", args, kwds, " << keyword_list_new << ")"
6367+
<< extra_type_check_str << ") {\n";
63546368
} else {
63556369
indent(out, indent_level)
6356-
<< "if (Dtool_ExtractOptionalArg(&" << param_name << ", args, kwds, " << keyword_list_new << ")) {\n";
6370+
<< "if (Dtool_ExtractOptionalArg(&" << param_name << ", args, kwds, " << keyword_list_new << ")"
6371+
<< extra_type_check_str << ") {\n";
63576372
}
63586373
} else {
63596374
// We have to use the more expensive PyArg_ParseTupleAndKeywords.
@@ -6373,7 +6388,8 @@ write_function_instance(ostream &out, FunctionRemap *remap,
63736388
indent(out, indent_level)
63746389
<< "if (PyArg_ParseTupleAndKeywords(args, kwds, \""
63756390
<< format_specifiers << ":" << method_name
6376-
<< "\", (char **)keyword_list" << parameter_list << ")) {\n";
6391+
<< "\", (char **)keyword_list" << parameter_list << ")"
6392+
<< extra_type_check_str << ") {\n";
63776393
}
63786394

63796395
} else if (only_pyobjects) {
@@ -6382,29 +6398,31 @@ write_function_instance(ostream &out, FunctionRemap *remap,
63826398
if (max_num_args == 1) {
63836399
if (min_num_args == 1) {
63846400
indent(out, indent_level)
6385-
<< "if (Dtool_ExtractArg(&" << param_name << ", args, kwds)) {\n";
6401+
<< "if (Dtool_ExtractArg(&" << param_name << ", args, kwds)"
6402+
<< extra_type_check_str << ") {\n";
63866403
} else {
63876404
indent(out, indent_level)
6388-
<< "if (Dtool_ExtractOptionalArg(&" << param_name << ", args, kwds)) {\n";
6405+
<< "if (Dtool_ExtractOptionalArg(&" << param_name << ", args, kwds)"
6406+
<< extra_type_check_str << ") {\n";
63896407
}
63906408
} else if (max_num_args == 0) {
63916409
indent(out, indent_level)
6392-
<< "if (Dtool_CheckNoArgs(args, kwds)) {\n";
6410+
<< "if (Dtool_CheckNoArgs(args, kwds)" << extra_type_check_str << ") {\n";
63936411
} else {
63946412
clear_error = true;
63956413
indent(out, indent_level)
63966414
<< "if ((kwds == nullptr || PyDict_Size(kwds) == 0) && PyArg_UnpackTuple(args, \""
63976415
<< methodNameFromCppName(remap, "", false)
63986416
<< "\", " << min_num_args << ", " << max_num_args
6399-
<< parameter_list << ")) {\n";
6417+
<< parameter_list << ")" << extra_type_check_str << ") {\n";
64006418
}
64016419

64026420
} else {
64036421
clear_error = true;
64046422
indent(out, indent_level)
64056423
<< "if ((kwds == nullptr || PyDict_Size(kwds) == 0) && PyArg_ParseTuple(args, \""
64066424
<< format_specifiers << ":" << method_name
6407-
<< "\"" << parameter_list << ")) {\n";
6425+
<< "\"" << parameter_list << ")" << extra_type_check_str << ") {\n";
64086426
}
64096427

64106428
++open_scopes;
@@ -6421,21 +6439,27 @@ write_function_instance(ostream &out, FunctionRemap *remap,
64216439
<< "if (PyTuple_GET_SIZE(args) == 1) {\n";
64226440
indent(out, indent_level + 2)
64236441
<< param_name << " = PyTuple_GET_ITEM(args, 0);\n";
6442+
6443+
if (!extra_type_check_str.empty()) {
6444+
indent(out, indent_level + 2)
6445+
<< "if (true" << extra_type_check_str << ") {\n";
6446+
++open_scopes;
6447+
}
64246448
} else {
64256449
clear_error = true;
64266450
indent(out, indent_level)
64276451
<< "if (PyArg_UnpackTuple(args, \""
64286452
<< methodNameFromCppName(remap, "", false)
64296453
<< "\", " << min_num_args << ", " << max_num_args
6430-
<< parameter_list << ")) {\n";
6454+
<< parameter_list << ")" << extra_type_check_str << ") {\n";
64316455
}
64326456

64336457
} else {
64346458
clear_error = true;
64356459
indent(out, indent_level)
64366460
<< "if (PyArg_ParseTuple(args, \""
64376461
<< format_specifiers << ":" << method_name
6438-
<< "\"" << parameter_list << ")) {\n";
6462+
<< "\"" << parameter_list << ")" << extra_type_check_str << ") {\n";
64396463
}
64406464
++open_scopes;
64416465
indent_level += 2;
@@ -6446,14 +6470,20 @@ write_function_instance(ostream &out, FunctionRemap *remap,
64466470
if (!only_pyobjects && format_specifiers != "O") {
64476471
indent(out, indent_level)
64486472
<< "if (PyArg_Parse(arg, \"" << format_specifiers << ":"
6449-
<< method_name << "\"" << parameter_list << ")) {\n";
6473+
<< method_name << "\"" << parameter_list << ")"
6474+
<< extra_type_check_str << ") {\n";
64506475

64516476
++open_scopes;
64526477
clear_error = true;
64536478
indent_level += 2;
64546479
}
64556480

64566481
default:
6482+
if (!extra_type_check_str.empty()) {
6483+
indent(out, indent_level)
6484+
<< "if (true" << extra_type_check_str << ") {\n";
6485+
++open_scopes;
6486+
}
64576487
break;
64586488
}
64596489
}

0 commit comments

Comments
 (0)