parsers: avoid pointer aliasing stable
authorMatt Mackall <mpm@selenic.com>
Wed, 10 Aug 2011 13:40:01 -0500
branchstable
changeset 15033 2ef2d3a5cd2d
parent 15032 eb87fbc6d702
child 15034 72f312f41a4a
child 15040 a494b54b6ed3
parsers: avoid pointer aliasing Newer versions of GCC have aggressive pointer alias optimizations that might get fooled by our pointer manipulations. These issues shouldn't be encountered in practice because distutils compiles extensions with -fno-strict-alias but the code was not valid according to the standard.
mercurial/mpatch.c
mercurial/parsers.c
--- a/mercurial/mpatch.c	Wed Aug 10 13:25:35 2011 -0500
+++ b/mercurial/mpatch.c	Wed Aug 10 13:40:01 2011 -0500
@@ -238,7 +238,7 @@
 	struct flist *l;
 	struct frag *lt;
 	const char *data = bin + 12, *end = bin + len;
-	char decode[12]; /* for dealing with alignment issues */
+	uint32_t decode[3]; /* for dealing with alignment issues */
 
 	/* assume worst case size, we won't have many of these lists */
 	l = lalloc(len / 12);
@@ -249,9 +249,9 @@
 
 	while (data <= end) {
 		memcpy(decode, bin, 12);
-		lt->start = ntohl(*(uint32_t *)decode);
-		lt->end = ntohl(*(uint32_t *)(decode + 4));
-		lt->len = ntohl(*(uint32_t *)(decode + 8));
+		lt->start = ntohl(decode[0]);
+		lt->end = ntohl(decode[1]);
+		lt->len = ntohl(decode[2]);
 		if (lt->start > lt->end)
 			break; /* sanity check */
 		bin = data + lt->len;
@@ -397,7 +397,7 @@
 	long orig, start, end, len, outlen = 0, last = 0;
 	int patchlen;
 	char *bin, *binend, *data;
-	char decode[12]; /* for dealing with alignment issues */
+	uint32_t decode[3]; /* for dealing with alignment issues */
 
 	if (!PyArg_ParseTuple(args, "ls#", &orig, &bin, &patchlen))
 		return NULL;
@@ -407,9 +407,9 @@
 
 	while (data <= binend) {
 		memcpy(decode, bin, 12);
-		start = ntohl(*(uint32_t *)decode);
-		end = ntohl(*(uint32_t *)(decode + 4));
-		len = ntohl(*(uint32_t *)(decode + 8));
+		start = ntohl(decode[0]);
+		end = ntohl(decode[1]);
+		len = ntohl(decode[2]);
 		if (start > end)
 			break; /* sanity check */
 		bin = data + len;
--- a/mercurial/parsers.c	Wed Aug 10 13:25:35 2011 -0500
+++ b/mercurial/parsers.c	Wed Aug 10 13:40:01 2011 -0500
@@ -170,7 +170,7 @@
 	int state, mode, size, mtime;
 	unsigned int flen;
 	int len;
-	char decode[16]; /* for alignment */
+	uint32_t decode[4]; /* for alignment */
 
 	if (!PyArg_ParseTuple(args, "O!O!s#:parse_dirstate",
 			      &PyDict_Type, &dmap,
@@ -194,10 +194,10 @@
 		/* unpack header */
 		state = *cur;
 		memcpy(decode, cur + 1, 16);
-		mode = ntohl(*(uint32_t *)(decode));
-		size = ntohl(*(uint32_t *)(decode + 4));
-		mtime = ntohl(*(uint32_t *)(decode + 8));
-		flen = ntohl(*(uint32_t *)(decode + 12));
+		mode = ntohl(decode[0]);
+		size = ntohl(decode[1]);
+		mtime = ntohl(decode[2]);
+		flen = ntohl(decode[3]);
 		cur += 17;
 		if (cur + flen > end || cur + flen < cur) {
 			PyErr_SetString(PyExc_ValueError, "overflow in dirstate");
@@ -264,27 +264,27 @@
 	int comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2;
 	const char *c_node_id;
 	const char *end = data + size;
-	char decode[64]; /* to enforce alignment with inline data */
+	uint32_t decode[8]; /* to enforce alignment with inline data */
 
 	while (data < end) {
 		unsigned int step;
 
-		memcpy(decode, data, 64);
-		offset_flags = ntohl(*((uint32_t *) (decode + 4)));
+		memcpy(decode, data, 32);
+		offset_flags = ntohl(decode[1]);
 		if (n == 0) /* mask out version number for the first entry */
 			offset_flags &= 0xFFFF;
 		else {
-			uint32_t offset_high =  ntohl(*((uint32_t *)decode));
+			uint32_t offset_high =  ntohl(decode[0]);
 			offset_flags |= ((uint64_t)offset_high) << 32;
 		}
 
-		comp_len = ntohl(*((uint32_t *)(decode + 8)));
-		uncomp_len = ntohl(*((uint32_t *)(decode + 12)));
-		base_rev = ntohl(*((uint32_t *)(decode + 16)));
-		link_rev = ntohl(*((uint32_t *)(decode + 20)));
-		parent_1 = ntohl(*((uint32_t *)(decode + 24)));
-		parent_2 = ntohl(*((uint32_t *)(decode + 28)));
-		c_node_id = decode + 32;
+		comp_len = ntohl(decode[2]);
+		uncomp_len = ntohl(decode[3]);
+		base_rev = ntohl(decode[4]);
+		link_rev = ntohl(decode[5]);
+		parent_1 = ntohl(decode[6]);
+		parent_2 = ntohl(decode[7]);
+		c_node_id = data + 32;
 
 		entry = Py_BuildValue("Liiiiiis#", offset_flags, comp_len,
 			      uncomp_len, base_rev, link_rev,