Mercurial > hg
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 } |