comparison mercurial/parsers.c @ 25810:82d6a35cf432

parsers: fix buffer overflow by invalid parent revision read from revlog If revlog file is corrupted, it can have parent pointing to invalid revision. So we should validate it before updating nothead[], phases[], seen[], etc. Otherwise it would cause segfault at best. We could use "rev" instead of "maxrev" as upper bound, but I think the explicit "maxrev" can clarify that we just want to avoid possible buffer overflow vulnerability.
author Yuya Nishihara <yuya@tcha.org>
date Thu, 16 Jul 2015 23:36:08 +0900
parents 72b2711f12ea
children 895f04955a49
comparison
equal deleted inserted replaced
25809:ebb5bb9bc32e 25810:82d6a35cf432
750 } 750 }
751 751
752 return PyString_AS_STRING(self->data) + pos * v1_hdrsize; 752 return PyString_AS_STRING(self->data) + pos * v1_hdrsize;
753 } 753 }
754 754
755 static inline void index_get_parents(indexObject *self, Py_ssize_t rev, 755 static inline int index_get_parents(indexObject *self, Py_ssize_t rev,
756 int *ps) 756 int *ps, int maxrev)
757 { 757 {
758 if (rev >= self->length - 1) { 758 if (rev >= self->length - 1) {
759 PyObject *tuple = PyList_GET_ITEM(self->added, 759 PyObject *tuple = PyList_GET_ITEM(self->added,
760 rev - self->length + 1); 760 rev - self->length + 1);
761 ps[0] = (int)PyInt_AS_LONG(PyTuple_GET_ITEM(tuple, 5)); 761 ps[0] = (int)PyInt_AS_LONG(PyTuple_GET_ITEM(tuple, 5));
763 } else { 763 } else {
764 const char *data = index_deref(self, rev); 764 const char *data = index_deref(self, rev);
765 ps[0] = getbe32(data + 24); 765 ps[0] = getbe32(data + 24);
766 ps[1] = getbe32(data + 28); 766 ps[1] = getbe32(data + 28);
767 } 767 }
768 /* If index file is corrupted, ps[] may point to invalid revisions. So
769 * there is a risk of buffer overflow to trust them unconditionally. */
770 if (ps[0] > maxrev || ps[1] > maxrev) {
771 PyErr_SetString(PyExc_ValueError, "parent out of range");
772 return -1;
773 }
774 return 0;
768 } 775 }
769 776
770 777
771 /* 778 /*
772 * RevlogNG format (all in big endian, data may be inlined): 779 * RevlogNG format (all in big endian, data may be inlined):
1147 } 1154 }
1148 /* Propagate the phase information from the roots to the revs */ 1155 /* Propagate the phase information from the roots to the revs */
1149 if (minrevallphases != -1) { 1156 if (minrevallphases != -1) {
1150 int parents[2]; 1157 int parents[2];
1151 for (i = minrevallphases; i < len; i++) { 1158 for (i = minrevallphases; i < len; i++) {
1152 index_get_parents(self, i, parents); 1159 if (index_get_parents(self, i, parents, len - 1) < 0)
1160 goto release_phasesetlist;
1153 set_phase_from_parents(phases, parents[0], parents[1], i); 1161 set_phase_from_parents(phases, parents[0], parents[1], i);
1154 } 1162 }
1155 } 1163 }
1156 /* Transform phase list to a python list */ 1164 /* Transform phase list to a python list */
1157 phaseslist = PyList_New(len); 1165 phaseslist = PyList_New(len);
1246 if (isfiltered) { 1254 if (isfiltered) {
1247 nothead[i] = 1; 1255 nothead[i] = 1;
1248 continue; 1256 continue;
1249 } 1257 }
1250 1258
1251 index_get_parents(self, i, parents); 1259 if (index_get_parents(self, i, parents, len - 1) < 0)
1260 goto bail;
1252 for (j = 0; j < 2; j++) { 1261 for (j = 0; j < 2; j++) {
1253 if (parents[j] >= 0) 1262 if (parents[j] >= 0)
1254 nothead[parents[j]] = 1; 1263 nothead[parents[j]] = 1;
1255 } 1264 }
1256 } 1265 }
1714 if (revs[i] == v) 1723 if (revs[i] == v)
1715 goto done; 1724 goto done;
1716 } 1725 }
1717 } 1726 }
1718 } 1727 }
1719 index_get_parents(self, v, parents); 1728 if (index_get_parents(self, v, parents, maxrev) < 0)
1729 goto bail;
1720 1730
1721 for (i = 0; i < 2; i++) { 1731 for (i = 0; i < 2; i++) {
1722 int p = parents[i]; 1732 int p = parents[i];
1723 if (p == -1) 1733 if (p == -1)
1724 continue; 1734 continue;
1811 1821
1812 if (dv == 0) 1822 if (dv == 0)
1813 continue; 1823 continue;
1814 1824
1815 sv = seen[v]; 1825 sv = seen[v];
1816 index_get_parents(self, v, parents); 1826 if (index_get_parents(self, v, parents, maxrev) < 0)
1827 goto bail;
1817 1828
1818 for (i = 0; i < 2; i++) { 1829 for (i = 0; i < 2; i++) {
1819 int p = parents[i]; 1830 int p = parents[i];
1820 long nsp, sp; 1831 long nsp, sp;
1821 int dp; 1832 int dp;