bpo-20104: Fix leaks and errors in new os.posix_spawn (GH-5418) · python/cpython@0cd6bca (original) (raw)

`@@ -176,14 +176,6 @@ corresponding Unix manual entries for more information on calls.");

`

176

176

`#else

`

177

177

`/* Unix functions that the configure script doesn't check for */

`

178

178

`#define HAVE_EXECV 1

`

179

``

`-

/* bpo-32705: Current Android does not have posix_spawn

`

180

``

`-

`

181

``

`-

`

182

``

`-

`

183

``

`-

**/

`

184

``

`-

#ifndef ANDROID

`

185

``

`-

#define HAVE_POSIX_SPAWN 1

`

186

``

`-

#endif

`

187

179

`#define HAVE_FORK 1

`

188

180

`#if defined(USLC) && defined(SCO_VERSION) /* SCO UDK Compiler */

`

189

181

`#define HAVE_FORK1 1

`

`@@ -5139,17 +5131,22 @@ os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,

`

5139

5131

`/[clinic end generated code: output=d023521f541c709c input=0ec9f1cfdc890be5]/

`

5140

5132

`{

`

5141

5133

`EXECV_CHAR **argvlist = NULL;

`

5142

``

`-

EXECV_CHAR **envlist;

`

``

5134

`+

EXECV_CHAR **envlist = NULL;

`

``

5135

`+

posix_spawn_file_actions_t _file_actions;

`

``

5136

`+

posix_spawn_file_actions_t *file_actionsp = NULL;

`

5143

5137

`Py_ssize_t argc, envc;

`

``

5138

`+

PyObject* result = NULL;

`

``

5139

`+

PyObject* seq = NULL;

`

``

5140

+

5144

5141

``

5145

5142

`/* posix_spawn has three arguments: (path, argv, env), where

`

5146

5143

` argv is a list or tuple of strings and env is a dictionary

`

5147

5144

` like posix.environ. */

`

5148

5145

``

5149

``

`-

if (!PySequence_Check(argv)){

`

``

5146

`+

if (!PySequence_Check(argv)) {

`

5150

5147

`PyErr_SetString(PyExc_TypeError,

`

5151

5148

`"posix_spawn: argv must be a tuple or list");

`

5152

``

`-

goto fail;

`

``

5149

`+

goto exit;

`

5153

5150

` }

`

5154

5151

`argc = PySequence_Size(argv);

`

5155

5152

`if (argc < 1) {

`

`@@ -5160,50 +5157,47 @@ os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,

`

5160

5157

`if (!PyMapping_Check(env)) {

`

5161

5158

`PyErr_SetString(PyExc_TypeError,

`

5162

5159

`"posix_spawn: environment must be a mapping object");

`

5163

``

`-

goto fail;

`

``

5160

`+

goto exit;

`

5164

5161

` }

`

5165

5162

``

5166

5163

`argvlist = parse_arglist(argv, &argc);

`

5167

5164

`if (argvlist == NULL) {

`

5168

``

`-

goto fail;

`

``

5165

`+

goto exit;

`

5169

5166

` }

`

5170

5167

`if (!argvlist[0][0]) {

`

5171

5168

`PyErr_SetString(PyExc_ValueError,

`

5172

5169

`"posix_spawn: argv first element cannot be empty");

`

5173

``

`-

goto fail;

`

``

5170

`+

goto exit;

`

5174

5171

` }

`

5175

5172

``

5176

5173

`envlist = parse_envlist(env, &envc);

`

5177

``

`-

if (envlist == NULL)

`

5178

``

`-

goto fail;

`

``

5174

`+

if (envlist == NULL) {

`

``

5175

`+

goto exit;

`

``

5176

`+

}

`

5179

5177

``

5180

5178

`pid_t pid;

`

5181

``

`-

posix_spawn_file_actions_t *file_actionsp = NULL;

`

5182

``

`-

if (file_actions != NULL && file_actions != Py_None){

`

5183

``

`-

posix_spawn_file_actions_t _file_actions;

`

``

5179

`+

if (file_actions != NULL && file_actions != Py_None) {

`

5184

5180

`if(posix_spawn_file_actions_init(&_file_actions) != 0){

`

5185

``

`-

PyErr_SetString(PyExc_TypeError,

`

``

5181

`+

PyErr_SetString(PyExc_OSError,

`

5186

5182

`"Error initializing file actions");

`

5187

``

`-

goto fail;

`

``

5183

`+

goto exit;

`

5188

5184

` }

`

5189

5185

``

5190

``

-

5191

5186

`file_actionsp = &_file_actions;

`

5192

5187

``

5193

``

-

5194

``

`-

PyObject* seq = PySequence_Fast(file_actions, "file_actions must be a sequence");

`

5195

``

`-

if(seq == NULL){

`

5196

``

`-

goto fail;

`

``

5188

`+

seq = PySequence_Fast(file_actions, "file_actions must be a sequence");

`

``

5189

`+

if(seq == NULL) {

`

``

5190

`+

goto exit;

`

5197

5191

` }

`

5198

5192

`PyObject* file_actions_obj;

`

5199

5193

`PyObject* mode_obj;

`

5200

5194

``

5201

5195

`for (int i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {

`

5202

5196

`file_actions_obj = PySequence_Fast_GET_ITEM(seq, i);

`

5203

5197

``

5204

``

`-

if(!PySequence_Check(file_actions_obj) | !PySequence_Size(file_actions_obj)){

`

``

5198

`+

if(!PySequence_Check(file_actions_obj) | !PySequence_Size(file_actions_obj)) {

`

5205

5199

`PyErr_SetString(PyExc_TypeError,"Each file_action element must be a non empty sequence");

`

5206

``

`-

goto fail;

`

``

5200

`+

goto exit;

`

5207

5201

` }

`

5208

5202

``

5209

5203

``

`@@ -5215,83 +5209,103 @@ os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,

`

5215

5209

`switch(mode) {

`

5216

5210

``

5217

5211

`case POSIX_SPAWN_OPEN:

`

5218

``

`-

if(PySequence_Size(file_actions_obj) != 5){

`

``

5212

`+

if(PySequence_Size(file_actions_obj) != 5) {

`

5219

5213

`PyErr_SetString(PyExc_TypeError,"A open file_action object must have 5 elements");

`

5220

``

`-

goto fail;

`

``

5214

`+

goto exit;

`

5221

5215

` }

`

5222

5216

``

5223

5217

`long open_fd = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 1));

`

5224

5218

`if(PyErr_Occurred()) {

`

5225

``

`-

goto fail;

`

``

5219

`+

goto exit;

`

5226

5220

` }

`

5227

5221

`const char* open_path = PyUnicode_AsUTF8(PySequence_GetItem(file_actions_obj, 2));

`

5228

``

`-

if(open_path == NULL){

`

5229

``

`-

goto fail;

`

``

5222

`+

if(open_path == NULL) {

`

``

5223

`+

goto exit;

`

5230

5224

` }

`

5231

5225

`long open_oflag = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 3));

`

5232

5226

`if(PyErr_Occurred()) {

`

5233

``

`-

goto fail;

`

``

5227

`+

goto exit;

`

5234

5228

` }

`

5235

5229

`long open_mode = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 4));

`

5236

5230

`if(PyErr_Occurred()) {

`

5237

``

`-

goto fail;

`

``

5231

`+

goto exit;

`

``

5232

`+

}

`

``

5233

`+

if(posix_spawn_file_actions_addopen(file_actionsp, open_fd, open_path, open_oflag, open_mode)) {

`

``

5234

`+

PyErr_SetString(PyExc_OSError,"Failed to add open file action");

`

``

5235

`+

goto exit;

`

5238

5236

` }

`

5239

``

`-

posix_spawn_file_actions_addopen(file_actionsp, open_fd, open_path, open_oflag, open_mode);

`

``

5237

+

5240

5238

`break;

`

5241

5239

``

5242

5240

`case POSIX_SPAWN_CLOSE:

`

5243

5241

`if(PySequence_Size(file_actions_obj) != 2){

`

5244

5242

`PyErr_SetString(PyExc_TypeError,"A close file_action object must have 2 elements");

`

5245

``

`-

goto fail;

`

``

5243

`+

goto exit;

`

5246

5244

` }

`

5247

5245

``

5248

5246

`long close_fd = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 1));

`

5249

5247

`if(PyErr_Occurred()) {

`

5250

``

`-

goto fail;

`

``

5248

`+

goto exit;

`

``

5249

`+

}

`

``

5250

`+

if(posix_spawn_file_actions_addclose(file_actionsp, close_fd)) {

`

``

5251

`+

PyErr_SetString(PyExc_OSError,"Failed to add close file action");

`

``

5252

`+

goto exit;

`

5251

5253

` }

`

5252

``

`-

posix_spawn_file_actions_addclose(file_actionsp, close_fd);

`

5253

5254

`break;

`

5254

5255

``

5255

5256

`case POSIX_SPAWN_DUP2:

`

5256

5257

`if(PySequence_Size(file_actions_obj) != 3){

`

5257

5258

`PyErr_SetString(PyExc_TypeError,"A dup2 file_action object must have 3 elements");

`

5258

``

`-

goto fail;

`

``

5259

`+

goto exit;

`

5259

5260

` }

`

5260

5261

``

5261

5262

`long fd1 = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 1));

`

5262

5263

`if(PyErr_Occurred()) {

`

5263

``

`-

goto fail;

`

``

5264

`+

goto exit;

`

5264

5265

` }

`

5265

5266

`long fd2 = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 2));

`

5266

5267

`if(PyErr_Occurred()) {

`

5267

``

`-

goto fail;

`

``

5268

`+

goto exit;

`

``

5269

`+

}

`

``

5270

`+

if(posix_spawn_file_actions_adddup2(file_actionsp, fd1, fd2)) {

`

``

5271

`+

PyErr_SetString(PyExc_OSError,"Failed to add dup2 file action");

`

``

5272

`+

goto exit;

`

5268

5273

` }

`

5269

``

`-

posix_spawn_file_actions_adddup2(file_actionsp, fd1, fd2);

`

5270

5274

`break;

`

5271

5275

``

5272

5276

`default:

`

5273

5277

`PyErr_SetString(PyExc_TypeError,"Unknown file_actions identifier");

`

5274

``

`-

goto fail;

`

``

5278

`+

goto exit;

`

5275

5279

` }

`

5276

5280

` }

`

5277

``

`-

Py_DECREF(seq);

`

5278

``

`-

}

`

``

5281

`+

}

`

5279

5282

``

5280

5283

`_Py_BEGIN_SUPPRESS_IPH

`

5281

``

`-

posix_spawn(&pid, path->narrow, file_actionsp, NULL, argvlist, envlist);

`

5282

``

`-

return PyLong_FromPid(pid);

`

``

5284

`+

int err_code = posix_spawn(&pid, path->narrow, file_actionsp, NULL, argvlist, envlist);

`

5283

5285

`_Py_END_SUPPRESS_IPH

`

``

5286

`+

if(err_code) {

`

``

5287

`+

PyErr_SetString(PyExc_OSError,"posix_spawn call failed");

`

``

5288

`+

goto exit;

`

``

5289

`+

}

`

``

5290

`+

result = PyLong_FromPid(pid);

`

5284

5291

``

5285

``

`-

path_error(path);

`

``

5292

`+

exit:

`

5286

5293

``

5287

``

`-

free_string_array(envlist, envc);

`

``

5294

`+

Py_XDECREF(seq);

`

5288

5295

``

5289

``

`-

fail:

`

``

5296

`+

if(file_actionsp) {

`

``

5297

`+

posix_spawn_file_actions_destroy(file_actionsp);

`

``

5298

`+

}

`

``

5299

+

``

5300

`+

if (envlist) {

`

``

5301

`+

free_string_array(envlist, envc);

`

``

5302

`+

}

`

5290

5303

``

5291

5304

`if (argvlist) {

`

5292

5305

`free_string_array(argvlist, argc);

`

5293

5306

` }

`

5294

``

`-

return NULL;

`

``

5307

+

``

5308

`+

return result;

`

5295

5309

``

5296

5310

``

5297

5311

`}

`