mercurial/cext/revlog.c
changeset 48721 a9364de9be29
parent 48499 52034c42c09d
child 48722 92b5a2c4d637
equal deleted inserted replaced
48719:02e9ad08999b 48721:a9364de9be29
   134 static const long v2_entry_size = 96;
   134 static const long v2_entry_size = 96;
   135 
   135 
   136 static const long format_v1 = 1; /* Internal only, could be any number */
   136 static const long format_v1 = 1; /* Internal only, could be any number */
   137 static const long format_v2 = 2; /* Internal only, could be any number */
   137 static const long format_v2 = 2; /* Internal only, could be any number */
   138 
   138 
       
   139 static const long entry_offset_high = 0;
       
   140 static const long entry_offset_offset_flags = 4;
       
   141 static const long entry_offset_comp_len = 8;
       
   142 static const long entry_offset_uncomp_len = 12;
       
   143 static const long entry_offset_base_rev = 16;
       
   144 static const long entry_offset_link_rev = 20;
       
   145 static const long entry_offset_parent_1 = 24;
       
   146 static const long entry_offset_parent_2 = 28;
       
   147 static const long entry_offset_node_id = 32;
       
   148 static const long entry_offset_sidedata_offset = 64;
       
   149 static const long entry_offset_sidedata_comp_len = 72;
       
   150 static const long entry_offset_all_comp_mode = 76;
       
   151 static const long entry_offset_padding_start = 77;
       
   152 
   139 static const char comp_mode_inline = 2;
   153 static const char comp_mode_inline = 2;
   140 static const char rank_unknown = -1;
   154 static const char rank_unknown = -1;
   141 
   155 
   142 static void raise_revlog_error(void)
   156 static void raise_revlog_error(void)
   143 {
   157 {
   204 static inline int index_get_parents(indexObject *self, Py_ssize_t rev, int *ps,
   218 static inline int index_get_parents(indexObject *self, Py_ssize_t rev, int *ps,
   205                                     int maxrev)
   219                                     int maxrev)
   206 {
   220 {
   207 	const char *data = index_deref(self, rev);
   221 	const char *data = index_deref(self, rev);
   208 
   222 
   209 	ps[0] = getbe32(data + 24);
   223 	ps[0] = getbe32(data + entry_offset_parent_1);
   210 	ps[1] = getbe32(data + 28);
   224 	ps[1] = getbe32(data + entry_offset_parent_2);
   211 
   225 
   212 	/* If index file is corrupted, ps[] may point to invalid revisions. So
   226 	/* If index file is corrupted, ps[] may point to invalid revisions. So
   213 	 * there is a risk of buffer overflow to trust them unconditionally. */
   227 	 * there is a risk of buffer overflow to trust them unconditionally. */
   214 	if (ps[0] < -1 || ps[0] > maxrev || ps[1] < -1 || ps[1] > maxrev) {
   228 	if (ps[0] < -1 || ps[0] > maxrev || ps[1] < -1 || ps[1] > maxrev) {
   215 		PyErr_SetString(PyExc_ValueError, "parent out of range");
   229 		PyErr_SetString(PyExc_ValueError, "parent out of range");
   252 
   266 
   253 	if (rev == nullrev)
   267 	if (rev == nullrev)
   254 		return 0;
   268 		return 0;
   255 
   269 
   256 	data = index_deref(self, rev);
   270 	data = index_deref(self, rev);
   257 	offset = getbe32(data + 4);
   271 	offset = getbe32(data + entry_offset_offset_flags);
   258 	if (rev == 0) {
   272 	if (rev == 0) {
   259 		/* mask out version number for the first entry */
   273 		/* mask out version number for the first entry */
   260 		offset &= 0xFFFF;
   274 		offset &= 0xFFFF;
   261 	} else {
   275 	} else {
   262 		uint32_t offset_high = getbe32(data);
   276 		uint32_t offset_high = getbe32(data + entry_offset_high);
   263 		offset |= ((uint64_t)offset_high) << 32;
   277 		offset |= ((uint64_t)offset_high) << 32;
   264 	}
   278 	}
   265 	return (int64_t)(offset >> 16);
   279 	return (int64_t)(offset >> 16);
   266 }
   280 }
   267 
   281 
   273 	if (rev == nullrev)
   287 	if (rev == nullrev)
   274 		return 0;
   288 		return 0;
   275 
   289 
   276 	data = index_deref(self, rev);
   290 	data = index_deref(self, rev);
   277 
   291 
   278 	tmp = (int)getbe32(data + 8);
   292 	tmp = (int)getbe32(data + entry_offset_comp_len);
   279 	if (tmp < 0) {
   293 	if (tmp < 0) {
   280 		PyErr_Format(PyExc_OverflowError,
   294 		PyErr_Format(PyExc_OverflowError,
   281 		             "revlog entry size out of bound (%d)", tmp);
   295 		             "revlog entry size out of bound (%d)", tmp);
   282 		return -1;
   296 		return -1;
   283 	}
   297 	}
   318 
   332 
   319 	data = index_deref(self, pos);
   333 	data = index_deref(self, pos);
   320 	if (data == NULL)
   334 	if (data == NULL)
   321 		return NULL;
   335 		return NULL;
   322 
   336 
   323 	offset_flags = getbe32(data + 4);
   337 	offset_flags = getbe32(data + entry_offset_offset_flags);
   324 	/*
   338 	/*
   325 	 * The first entry on-disk needs the version number masked out,
   339 	 * The first entry on-disk needs the version number masked out,
   326 	 * but this doesn't apply if entries are added to an empty index.
   340 	 * but this doesn't apply if entries are added to an empty index.
   327 	 */
   341 	 */
   328 	if (self->length && pos == 0)
   342 	if (self->length && pos == 0)
   329 		offset_flags &= 0xFFFF;
   343 		offset_flags &= 0xFFFF;
   330 	else {
   344 	else {
   331 		uint32_t offset_high = getbe32(data);
   345 		uint32_t offset_high = getbe32(data + entry_offset_high);
   332 		offset_flags |= ((uint64_t)offset_high) << 32;
   346 		offset_flags |= ((uint64_t)offset_high) << 32;
   333 	}
   347 	}
   334 
   348 
   335 	comp_len = getbe32(data + 8);
   349 	comp_len = getbe32(data + entry_offset_comp_len);
   336 	uncomp_len = getbe32(data + 12);
   350 	uncomp_len = getbe32(data + entry_offset_uncomp_len);
   337 	base_rev = getbe32(data + 16);
   351 	base_rev = getbe32(data + entry_offset_base_rev);
   338 	link_rev = getbe32(data + 20);
   352 	link_rev = getbe32(data + entry_offset_link_rev);
   339 	parent_1 = getbe32(data + 24);
   353 	parent_1 = getbe32(data + entry_offset_parent_1);
   340 	parent_2 = getbe32(data + 28);
   354 	parent_2 = getbe32(data + entry_offset_parent_2);
   341 	c_node_id = data + 32;
   355 	c_node_id = data + entry_offset_node_id;
   342 
   356 
   343 	if (self->format_version == format_v1) {
   357 	if (self->format_version == format_v1) {
   344 		sidedata_offset = 0;
   358 		sidedata_offset = 0;
   345 		sidedata_comp_len = 0;
   359 		sidedata_comp_len = 0;
   346 		data_comp_mode = comp_mode_inline;
   360 		data_comp_mode = comp_mode_inline;
   347 		sidedata_comp_mode = comp_mode_inline;
   361 		sidedata_comp_mode = comp_mode_inline;
   348 	} else {
   362 	} else {
   349 		sidedata_offset = getbe64(data + 64);
   363 		sidedata_offset = getbe64(data + entry_offset_sidedata_offset);
   350 		sidedata_comp_len = getbe32(data + 72);
   364 		sidedata_comp_len =
   351 		data_comp_mode = data[76] & 3;
   365 		    getbe32(data + entry_offset_sidedata_comp_len);
   352 		sidedata_comp_mode = ((data[76] >> 2) & 3);
   366 		data_comp_mode = data[entry_offset_all_comp_mode] & 3;
       
   367 		sidedata_comp_mode =
       
   368 		    ((data[entry_offset_all_comp_mode] >> 2) & 3);
   353 	}
   369 	}
   354 
   370 
   355 	return Py_BuildValue(tuple_format, offset_flags, comp_len, uncomp_len,
   371 	return Py_BuildValue(tuple_format, offset_flags, comp_len, uncomp_len,
   356 	                     base_rev, link_rev, parent_1, parent_2, c_node_id,
   372 	                     base_rev, link_rev, parent_1, parent_2, c_node_id,
   357 	                     self->nodelen, sidedata_offset, sidedata_comp_len,
   373 	                     self->nodelen, sidedata_offset, sidedata_comp_len,
   419 
   435 
   420 	if (pos >= length)
   436 	if (pos >= length)
   421 		return NULL;
   437 		return NULL;
   422 
   438 
   423 	data = index_deref(self, pos);
   439 	data = index_deref(self, pos);
   424 	return data ? data + 32 : NULL;
   440 	return data ? data + entry_offset_node_id : NULL;
   425 }
   441 }
   426 
   442 
   427 /*
   443 /*
   428  * Return the hash of the node corresponding to the given rev. The
   444  * Return the hash of the node corresponding to the given rev. The
   429  * rev is assumed to be existing. If not, an exception is set.
   445  * rev is assumed to be existing. If not, an exception is set.
   502 		self->added = new_added;
   518 		self->added = new_added;
   503 		self->added_length = new_added_length;
   519 		self->added_length = new_added_length;
   504 	}
   520 	}
   505 	rev = self->length + self->new_length;
   521 	rev = self->length + self->new_length;
   506 	data = self->added + self->entry_size * self->new_length++;
   522 	data = self->added + self->entry_size * self->new_length++;
   507 	putbe32(offset_flags >> 32, data);
   523 	putbe32(offset_flags >> 32, data + entry_offset_high);
   508 	putbe32(offset_flags & 0xffffffffU, data + 4);
   524 	putbe32(offset_flags & 0xffffffffU, data + entry_offset_offset_flags);
   509 	putbe32(comp_len, data + 8);
   525 	putbe32(comp_len, data + entry_offset_comp_len);
   510 	putbe32(uncomp_len, data + 12);
   526 	putbe32(uncomp_len, data + entry_offset_uncomp_len);
   511 	putbe32(base_rev, data + 16);
   527 	putbe32(base_rev, data + entry_offset_base_rev);
   512 	putbe32(link_rev, data + 20);
   528 	putbe32(link_rev, data + entry_offset_link_rev);
   513 	putbe32(parent_1, data + 24);
   529 	putbe32(parent_1, data + entry_offset_parent_1);
   514 	putbe32(parent_2, data + 28);
   530 	putbe32(parent_2, data + entry_offset_parent_2);
   515 	memcpy(data + 32, c_node_id, c_node_id_len);
   531 	memcpy(data + entry_offset_node_id, c_node_id, c_node_id_len);
   516 	/* Padding since SHA-1 is only 20 bytes for now */
   532 	/* Padding since SHA-1 is only 20 bytes for now */
   517 	memset(data + 32 + c_node_id_len, 0, 32 - c_node_id_len);
   533 	memset(data + entry_offset_node_id + c_node_id_len, 0,
       
   534 	       entry_offset_node_id - c_node_id_len);
   518 	if (self->format_version == format_v2) {
   535 	if (self->format_version == format_v2) {
   519 		putbe64(sidedata_offset, data + 64);
   536 		putbe64(sidedata_offset, data + entry_offset_sidedata_offset);
   520 		putbe32(sidedata_comp_len, data + 72);
   537 		putbe32(sidedata_comp_len,
       
   538 		        data + entry_offset_sidedata_comp_len);
   521 		comp_field = data_comp_mode & 3;
   539 		comp_field = data_comp_mode & 3;
   522 		comp_field = comp_field | (sidedata_comp_mode & 3) << 2;
   540 		comp_field = comp_field | (sidedata_comp_mode & 3) << 2;
   523 		data[76] = comp_field;
   541 		data[entry_offset_all_comp_mode] = comp_field;
   524 		/* Padding for 96 bytes alignment */
   542 		/* Padding for 96 bytes alignment */
   525 		memset(data + 77, 0, self->entry_size - 77);
   543 		memset(data + entry_offset_padding_start, 0,
       
   544 		       self->entry_size - entry_offset_padding_start);
   526 	}
   545 	}
   527 
   546 
   528 	if (self->ntinitialized)
   547 	if (self->ntinitialized)
   529 		nt_insert(&self->nt, c_node_id, rev);
   548 		nt_insert(&self->nt, c_node_id, rev);
   530 
   549 
   575 	}
   594 	}
   576 
   595 
   577 	/* Find the newly added node, offset from the "already on-disk" length
   596 	/* Find the newly added node, offset from the "already on-disk" length
   578 	 */
   597 	 */
   579 	data = self->added + self->entry_size * (rev - self->length);
   598 	data = self->added + self->entry_size * (rev - self->length);
   580 	putbe64(offset_flags, data);
   599 	putbe64(offset_flags, data + entry_offset_high);
   581 	putbe64(sidedata_offset, data + 64);
   600 	putbe64(sidedata_offset, data + entry_offset_sidedata_offset);
   582 	putbe32(sidedata_comp_len, data + 72);
   601 	putbe32(sidedata_comp_len, data + entry_offset_sidedata_comp_len);
   583 	data[76] = (data[76] & ~(3 << 2)) | ((comp_mode & 3) << 2);
   602 	data[entry_offset_all_comp_mode] =
       
   603 	    (data[entry_offset_all_comp_mode] & ~(3 << 2)) |
       
   604 	    ((comp_mode & 3) << 2);
   584 
   605 
   585 	Py_RETURN_NONE;
   606 	Py_RETURN_NONE;
   586 }
   607 }
   587 
   608 
   588 static PyObject *index_stats(indexObject *self)
   609 static PyObject *index_stats(indexObject *self)
  1121 	int result;
  1142 	int result;
  1122 
  1143 
  1123 	data = index_deref(self, rev);
  1144 	data = index_deref(self, rev);
  1124 	if (data == NULL)
  1145 	if (data == NULL)
  1125 		return -2;
  1146 		return -2;
  1126 	result = getbe32(data + 16);
  1147 	result = getbe32(data + entry_offset_base_rev);
  1127 
  1148 
  1128 	if (result > rev) {
  1149 	if (result > rev) {
  1129 		PyErr_Format(
  1150 		PyErr_Format(
  1130 		    PyExc_ValueError,
  1151 		    PyExc_ValueError,
  1131 		    "corrupted revlog, revision base above revision: %d, %d",
  1152 		    "corrupted revlog, revision base above revision: %d, %d",
  2733 	Py_ssize_t len = 0;
  2754 	Py_ssize_t len = 0;
  2734 
  2755 
  2735 	while (pos + self->entry_size <= end && pos >= 0) {
  2756 	while (pos + self->entry_size <= end && pos >= 0) {
  2736 		uint32_t comp_len, sidedata_comp_len = 0;
  2757 		uint32_t comp_len, sidedata_comp_len = 0;
  2737 		/* 3rd element of header is length of compressed inline data */
  2758 		/* 3rd element of header is length of compressed inline data */
  2738 		comp_len = getbe32(data + pos + 8);
  2759 		comp_len = getbe32(data + pos + entry_offset_comp_len);
  2739 		if (self->entry_size == v2_entry_size) {
  2760 		if (self->entry_size == v2_entry_size) {
  2740 			sidedata_comp_len = getbe32(data + pos + 72);
  2761 			sidedata_comp_len = getbe32(
       
  2762 			    data + pos + entry_offset_sidedata_comp_len);
  2741 		}
  2763 		}
  2742 		incr = self->entry_size + comp_len + sidedata_comp_len;
  2764 		incr = self->entry_size + comp_len + sidedata_comp_len;
  2743 		if (offsets)
  2765 		if (offsets)
  2744 			offsets[len] = data + pos;
  2766 			offsets[len] = data + pos;
  2745 		len++;
  2767 		len++;