comparison mercurial/cext/revlog.c @ 51388:cb5175edd225 stable

cext: fix potential memory leaks of list items appended with PyList_Append Also reduce the duplication in the tricky code that uses PyList_Append by extracting it into a function `pylist_append_owned`.
author Arseniy Alekseyev <aalekseyev@janestreet.com>
date Thu, 15 Feb 2024 15:21:43 +0000
parents b670eb3dd6c9
children 3a7ef1398385
comparison
equal deleted inserted replaced
51368:5f62d45e5289 51388:cb5175edd225
907 phases[i] = phases[parent_1]; 907 phases[i] = phases[parent_1];
908 if (parent_2 >= 0 && phases[parent_2] > phases[i]) 908 if (parent_2 >= 0 && phases[parent_2] > phases[i])
909 phases[i] = phases[parent_2]; 909 phases[i] = phases[parent_2];
910 } 910 }
911 911
912 /* Take ownership of a given Python value and add it to a Python list.
913 Return -1 on failure (including if [elem] is NULL). */
914 static int pylist_append_owned(PyObject *list, PyObject *elem)
915 {
916 int res;
917
918 if (elem == NULL)
919 return -1;
920 res = PyList_Append(list, elem);
921 Py_DECREF(elem);
922 return res;
923 }
924
912 static PyObject *reachableroots2(indexObject *self, PyObject *args) 925 static PyObject *reachableroots2(indexObject *self, PyObject *args)
913 { 926 {
914 927
915 /* Input */ 928 /* Input */
916 long minroot; 929 long minroot;
919 /* heads and roots are lists */ 932 /* heads and roots are lists */
920 PyObject *heads = NULL; 933 PyObject *heads = NULL;
921 PyObject *roots = NULL; 934 PyObject *roots = NULL;
922 PyObject *reachable = NULL; 935 PyObject *reachable = NULL;
923 936
924 PyObject *val;
925 Py_ssize_t len = index_length(self); 937 Py_ssize_t len = index_length(self);
926 long revnum; 938 long revnum;
927 Py_ssize_t k; 939 Py_ssize_t k;
928 Py_ssize_t i; 940 Py_ssize_t i;
929 Py_ssize_t l; 941 Py_ssize_t l;
1000 while (k < lentovisit) { 1012 while (k < lentovisit) {
1001 /* Add the node to reachable if it is a root*/ 1013 /* Add the node to reachable if it is a root*/
1002 revnum = tovisit[k++]; 1014 revnum = tovisit[k++];
1003 if (revstates[revnum + 1] & RS_ROOT) { 1015 if (revstates[revnum + 1] & RS_ROOT) {
1004 revstates[revnum + 1] |= RS_REACHABLE; 1016 revstates[revnum + 1] |= RS_REACHABLE;
1005 val = PyLong_FromLong(revnum); 1017 r = pylist_append_owned(reachable,
1006 if (val == NULL) 1018 PyLong_FromLong(revnum));
1007 goto bail;
1008 r = PyList_Append(reachable, val);
1009 Py_DECREF(val);
1010 if (r < 0) 1019 if (r < 0)
1011 goto bail; 1020 goto bail;
1012 if (includepath == 0) 1021 if (includepath == 0)
1013 continue; 1022 continue;
1014 } 1023 }
1045 if (((revstates[parents[0] + 1] | 1054 if (((revstates[parents[0] + 1] |
1046 revstates[parents[1] + 1]) & 1055 revstates[parents[1] + 1]) &
1047 RS_REACHABLE) && 1056 RS_REACHABLE) &&
1048 !(revstates[i + 1] & RS_REACHABLE)) { 1057 !(revstates[i + 1] & RS_REACHABLE)) {
1049 revstates[i + 1] |= RS_REACHABLE; 1058 revstates[i + 1] |= RS_REACHABLE;
1050 val = PyLong_FromSsize_t(i); 1059 r = pylist_append_owned(reachable,
1051 if (val == NULL) 1060 PyLong_FromSsize_t(i));
1052 goto bail;
1053 r = PyList_Append(reachable, val);
1054 Py_DECREF(val);
1055 if (r < 0) 1061 if (r < 0)
1056 goto bail; 1062 goto bail;
1057 } 1063 }
1058 } 1064 }
1059 } 1065 }
1261 len = index_length(self); 1267 len = index_length(self);
1262 heads = PyList_New(0); 1268 heads = PyList_New(0);
1263 if (heads == NULL) 1269 if (heads == NULL)
1264 goto bail; 1270 goto bail;
1265 if (len == 0) { 1271 if (len == 0) {
1266 PyObject *nullid = PyLong_FromLong(-1); 1272 if (pylist_append_owned(heads, PyLong_FromLong(-1)) == -1) {
1267 if (nullid == NULL || PyList_Append(heads, nullid) == -1) {
1268 Py_XDECREF(nullid); 1273 Py_XDECREF(nullid);
1269 goto bail; 1274 goto bail;
1270 } 1275 }
1271 goto done; 1276 goto done;
1272 } 1277 }
1306 nothead[parents[j]] = 1; 1311 nothead[parents[j]] = 1;
1307 } 1312 }
1308 } 1313 }
1309 1314
1310 for (i = 0; i < len; i++) { 1315 for (i = 0; i < len; i++) {
1311 PyObject *head;
1312
1313 if (nothead[i]) 1316 if (nothead[i])
1314 continue; 1317 continue;
1315 head = PyLong_FromSsize_t(i); 1318 if (pylist_append_owned(heads, PyLong_FromSsize_t(i)) == -1) {
1316 if (head == NULL || PyList_Append(heads, head) == -1) {
1317 Py_XDECREF(head);
1318 goto bail; 1319 goto bail;
1319 } 1320 }
1320 } 1321 }
1321 1322
1322 done: 1323 done:
1559 } 1560 }
1560 1561
1561 iterrev = rev; 1562 iterrev = rev;
1562 1563
1563 while (iterrev != baserev && iterrev != stoprev) { 1564 while (iterrev != baserev && iterrev != stoprev) {
1564 PyObject *value = PyLong_FromLong(iterrev); 1565 if (pylist_append_owned(chain, PyLong_FromLong(iterrev))) {
1565 if (value == NULL) {
1566 goto bail; 1566 goto bail;
1567 } 1567 }
1568 if (PyList_Append(chain, value)) {
1569 Py_DECREF(value);
1570 goto bail;
1571 }
1572 Py_DECREF(value);
1573 1568
1574 if (generaldelta) { 1569 if (generaldelta) {
1575 iterrev = baserev; 1570 iterrev = baserev;
1576 } else { 1571 } else {
1577 iterrev--; 1572 iterrev--;
1598 } 1593 }
1599 1594
1600 if (iterrev == stoprev) { 1595 if (iterrev == stoprev) {
1601 stopped = 1; 1596 stopped = 1;
1602 } else { 1597 } else {
1603 PyObject *value = PyLong_FromLong(iterrev); 1598 if (pylist_append_owned(chain, PyLong_FromLong(iterrev))) {
1604 if (value == NULL) {
1605 goto bail; 1599 goto bail;
1606 } 1600 }
1607 if (PyList_Append(chain, value)) {
1608 Py_DECREF(value);
1609 goto bail;
1610 }
1611 Py_DECREF(value);
1612 1601
1613 stopped = 0; 1602 stopped = 0;
1614 } 1603 }
1615 1604
1616 if (PyList_Reverse(chain)) { 1605 if (PyList_Reverse(chain)) {
1725 struct Gap *gaps = NULL; /* array of notable gap in the chain */ 1714 struct Gap *gaps = NULL; /* array of notable gap in the chain */
1726 Py_ssize_t num_gaps = 1715 Py_ssize_t num_gaps =
1727 0; /* total number of notable gap recorded so far */ 1716 0; /* total number of notable gap recorded so far */
1728 Py_ssize_t *selected_indices = NULL; /* indices of gap skipped over */ 1717 Py_ssize_t *selected_indices = NULL; /* indices of gap skipped over */
1729 Py_ssize_t num_selected = 0; /* number of gaps skipped */ 1718 Py_ssize_t num_selected = 0; /* number of gaps skipped */
1730 PyObject *chunk = NULL; /* individual slice */
1731 PyObject *allchunks = NULL; /* all slices */ 1719 PyObject *allchunks = NULL; /* all slices */
1732 Py_ssize_t previdx; 1720 Py_ssize_t previdx;
1733 1721
1734 /* parsing argument */ 1722 /* parsing argument */
1735 if (!PyArg_ParseTuple(args, "O!dn", &PyList_Type, &list_revs, 1723 if (!PyArg_ParseTuple(args, "O!dn", &PyList_Type, &list_revs,
1870 Py_ssize_t endidx = trim_endidx(self, revs, previdx, idx); 1858 Py_ssize_t endidx = trim_endidx(self, revs, previdx, idx);
1871 if (endidx < 0) { 1859 if (endidx < 0) {
1872 goto bail; 1860 goto bail;
1873 } 1861 }
1874 if (previdx < endidx) { 1862 if (previdx < endidx) {
1875 chunk = PyList_GetSlice(list_revs, previdx, endidx); 1863 PyObject *chunk =
1876 if (chunk == NULL) { 1864 PyList_GetSlice(list_revs, previdx, endidx);
1865 if (pylist_append_owned(allchunks, chunk) == -1) {
1877 goto bail; 1866 goto bail;
1878 } 1867 }
1879 if (PyList_Append(allchunks, chunk) == -1) {
1880 goto bail;
1881 }
1882 Py_DECREF(chunk);
1883 chunk = NULL;
1884 } 1868 }
1885 previdx = idx; 1869 previdx = idx;
1886 } 1870 }
1887 result = allchunks; 1871 result = allchunks;
1888 goto done; 1872 goto done;
1889 1873
1890 bail: 1874 bail:
1891 Py_XDECREF(allchunks); 1875 Py_XDECREF(allchunks);
1892 Py_XDECREF(chunk);
1893 done: 1876 done:
1894 free(revs); 1877 free(revs);
1895 free(gaps); 1878 free(gaps);
1896 free(selected_indices); 1879 free(selected_indices);
1897 return result; 1880 return result;
2532 continue; 2515 continue;
2533 2516
2534 if (sv < poison) { 2517 if (sv < poison) {
2535 interesting -= 1; 2518 interesting -= 1;
2536 if (sv == allseen) { 2519 if (sv == allseen) {
2537 PyObject *obj = PyLong_FromLong(v); 2520 if (pylist_append_owned(
2538 if (obj == NULL) 2521 gca, PyLong_FromLong(v)) == -1) {
2539 goto bail;
2540 if (PyList_Append(gca, obj) == -1) {
2541 Py_DECREF(obj);
2542 goto bail; 2522 goto bail;
2543 } 2523 }
2544 sv |= poison; 2524 sv |= poison;
2545 for (i = 0; i < revcount; i++) { 2525 for (i = 0; i < revcount; i++) {
2546 if (revs[i] == v) 2526 if (revs[i] == v)