comparison mercurial/cext/osutil.c @ 45174:f93a4e3d35ab

osutil: fix excessive decref on tuple creation failure in listdir() The stat object would be freed on error for the same reason as the previous patch. makestat() can be inlined, but this patch doesn't change it. https://github.com/python/cpython/blob/2.7/Python/modsupport.c#L292 The __APPLE__ code is untested.
author Yuya Nishihara <yuya@tcha.org>
date Sun, 19 Jul 2020 17:35:41 +0900
parents 0424a9134bcf
children e92ca942ddca
comparison
equal deleted inserted replaced
45173:2bc5d1531235 45174:f93a4e3d35ab
334 } 334 }
335 335
336 static PyObject *_listdir_stat(char *path, int pathlen, int keepstat, 336 static PyObject *_listdir_stat(char *path, int pathlen, int keepstat,
337 char *skip) 337 char *skip)
338 { 338 {
339 PyObject *list, *elem, *stat = NULL, *ret = NULL; 339 PyObject *list, *elem, *ret = NULL;
340 char fullpath[PATH_MAX + 10]; 340 char fullpath[PATH_MAX + 10];
341 int kind, err; 341 int kind, err;
342 struct stat st; 342 struct stat st;
343 struct dirent *ent; 343 struct dirent *ent;
344 DIR *dir; 344 DIR *dir;
407 ret = PyList_New(0); 407 ret = PyList_New(0);
408 goto error; 408 goto error;
409 } 409 }
410 410
411 if (keepstat) { 411 if (keepstat) {
412 stat = makestat(&st); 412 PyObject *stat = makestat(&st);
413 if (!stat) 413 if (!stat)
414 goto error; 414 goto error;
415 elem = Py_BuildValue(PY23("siN", "yiN"), ent->d_name, 415 elem = Py_BuildValue(PY23("siN", "yiN"), ent->d_name,
416 kind, stat); 416 kind, stat);
417 } else 417 } else
418 elem = Py_BuildValue(PY23("si", "yi"), ent->d_name, 418 elem = Py_BuildValue(PY23("si", "yi"), ent->d_name,
419 kind); 419 kind);
420 if (!elem) 420 if (!elem)
421 goto error; 421 goto error;
422 stat = NULL;
423 422
424 PyList_Append(list, elem); 423 PyList_Append(list, elem);
425 Py_DECREF(elem); 424 Py_DECREF(elem);
426 } 425 }
427 426
428 ret = list; 427 ret = list;
429 Py_INCREF(ret); 428 Py_INCREF(ret);
430 429
431 error: 430 error:
432 Py_DECREF(list); 431 Py_DECREF(list);
433 Py_XDECREF(stat);
434 error_list: 432 error_list:
435 closedir(dir); 433 closedir(dir);
436 /* closedir also closes its dirfd */ 434 /* closedir also closes its dirfd */
437 goto error_value; 435 goto error_value;
438 error_dir: 436 error_dir:
478 #define LISTDIR_BATCH_SIZE 50 476 #define LISTDIR_BATCH_SIZE 50
479 477
480 static PyObject *_listdir_batch(char *path, int pathlen, int keepstat, 478 static PyObject *_listdir_batch(char *path, int pathlen, int keepstat,
481 char *skip, bool *fallback) 479 char *skip, bool *fallback)
482 { 480 {
483 PyObject *list, *elem, *stat = NULL, *ret = NULL; 481 PyObject *list, *elem, *ret = NULL;
484 int kind, err; 482 int kind, err;
485 unsigned long index; 483 unsigned long index;
486 unsigned int count, old_state, new_state; 484 unsigned int count, old_state, new_state;
487 bool state_seen = false; 485 bool state_seen = false;
488 attrbuf_entry *entry; 486 attrbuf_entry *entry;
584 ret = PyList_New(0); 582 ret = PyList_New(0);
585 goto error; 583 goto error;
586 } 584 }
587 585
588 if (keepstat) { 586 if (keepstat) {
587 PyObject *stat = NULL;
589 /* from the getattrlist(2) man page: "Only the 588 /* from the getattrlist(2) man page: "Only the
590 permission bits ... are valid". */ 589 permission bits ... are valid". */
591 st.st_mode = (entry->access_mask & ~S_IFMT) | kind; 590 st.st_mode = (entry->access_mask & ~S_IFMT) | kind;
592 st.st_mtime = entry->mtime.tv_sec; 591 st.st_mtime = entry->mtime.tv_sec;
593 st.st_size = entry->size; 592 st.st_size = entry->size;
599 } else 598 } else
600 elem = Py_BuildValue(PY23("si", "yi"), 599 elem = Py_BuildValue(PY23("si", "yi"),
601 filename, kind); 600 filename, kind);
602 if (!elem) 601 if (!elem)
603 goto error; 602 goto error;
604 stat = NULL;
605 603
606 PyList_Append(list, elem); 604 PyList_Append(list, elem);
607 Py_DECREF(elem); 605 Py_DECREF(elem);
608 606
609 entry = (attrbuf_entry *)((char *)entry + entry->length); 607 entry = (attrbuf_entry *)((char *)entry + entry->length);
613 ret = list; 611 ret = list;
614 Py_INCREF(ret); 612 Py_INCREF(ret);
615 613
616 error: 614 error:
617 Py_DECREF(list); 615 Py_DECREF(list);
618 Py_XDECREF(stat);
619 error_dir: 616 error_dir:
620 close(dfd); 617 close(dfd);
621 error_value: 618 error_value:
622 return ret; 619 return ret;
623 } 620 }