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