Skip to content

Commit 9f450b2

Browse files
author
James William Pye
committed
Correct areas of potential misaligned reads.
Per report by Leonardo Francalanci.
1 parent ee7369f commit 9f450b2

5 files changed

Lines changed: 46 additions & 25 deletions

File tree

postgresql/documentation/changes.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
Changes
22
=======
33

4+
0.9.1
5+
-----
6+
7+
* Fix misaligned reads in C extensions [Reported by Leonardo Francalanci]
8+
* Fix protocol tests on linux systems
9+
* Abort cluster startup waits on ProtocolError
10+
411
0.9.0 released on 2009-06-13
512
----------------------------
613

postgresql/protocol/optimized/buffer.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ p_memcpy(char *dst, struct p_place *p, uint32_t amount)
181181

182182
while (amount_left > 0)
183183
{
184-
unsigned long this_read =
184+
uint32_t this_read =
185185
chunk_size < amount_left ? chunk_size : amount_left;
186186

187187
memcpy(dst, src, this_read);
@@ -220,7 +220,8 @@ p_length(PyObject *self)
220220
break;
221221
p_seek(&p, copy_amount);
222222

223-
msg_length = local_ntohl(*((uint32_t *) (header + 1)));
223+
memcpy(&msg_length, header + 1, 4);
224+
msg_length = local_ntohl(msg_length);
224225
if (msg_length < 4)
225226
{
226227
PyErr_Format(PyExc_ValueError,
@@ -262,7 +263,8 @@ p_build_tuple(struct p_place *p)
262263
return(NULL);
263264
p_seek(p, copy_amount);
264265

265-
msg_length = local_ntohl(*((uint32_t *) (header + 1)));
266+
memcpy(&msg_length, header + 1, 4);
267+
msg_length = local_ntohl(msg_length);
266268
if (msg_length < 4)
267269
{
268270
PyErr_Format(PyExc_ValueError,
@@ -341,7 +343,7 @@ p_write(PyObject *self, PyObject *data)
341343
if (!PyBytes_Check(data))
342344
{
343345
PyErr_SetString(PyExc_TypeError,
344-
"PQ buffer.write() method requires a bytes object");
346+
"pq buffer.write() method requires a bytes object");
345347
return(NULL);
346348
}
347349
pb = ((struct p_buffer *) self);
@@ -461,8 +463,9 @@ p_has_message(PyObject *self)
461463
return(Py_False);
462464
}
463465
p_seek(&p, copy_amount);
466+
memcpy(&msg_length, header + 1, 4);
464467

465-
msg_length = local_ntohl(*((uint32_t *) (header + 1)));
468+
msg_length = local_ntohl(msg_length);
466469
if (msg_length < 4)
467470
{
468471
PyErr_Format(PyExc_ValueError,

postgresql/protocol/optimized/client3.c

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,17 @@ cat_messages(PyObject *self, PyObject *messages_in)
8585
*/
8686
while (cmsg < eofc)
8787
{
88+
uint32_t msg_length;
89+
char *localbuf = buf + bufpos + 1;
90+
buf[bufpos] = 'd'; /* COPY data message type */
91+
8892
ob = PyList_GET_ITEM(msgs, cmsg);
89-
buf[bufpos] = 'd';
90-
*((uint32_t *)(buf + bufpos + 1)) =
91-
(uint32_t) local_ntohl(PyBytes_GET_SIZE(ob) + 4);
92-
memcpy(buf + bufpos + 5, PyBytes_AS_STRING(ob), PyBytes_GET_SIZE(ob));
93-
bufpos = bufpos + 5 + PyBytes_GET_SIZE(ob);
93+
msg_length = PyBytes_GET_SIZE(ob) + 4;
94+
95+
bufpos = bufpos + 1 + msg_length;
96+
msg_length = local_ntohl(msg_length);
97+
memcpy(localbuf, &msg_length, 4);
98+
memcpy(localbuf + 4, PyBytes_AS_STRING(ob), PyBytes_GET_SIZE(ob));
9499
++cmsg;
95100
}
96101
}
@@ -99,6 +104,7 @@ cat_messages(PyObject *self, PyObject *messages_in)
99104
PyObject *serialized;
100105
PyObject *msg_type;
101106
int msg_type_size;
107+
uint32_t msg_length;
102108

103109
/*
104110
* Call the serialize() method on the element object.
@@ -166,9 +172,9 @@ cat_messages(PyObject *self, PyObject *messages_in)
166172
* All necessary information acquired, so fill in the message's data.
167173
*/
168174
buf[bufpos] = *(PyBytes_AS_STRING(msg_type));
169-
/* data size */
170-
*((uint32_t *)(buf + bufpos + msg_type_size)) =
171-
(uint32_t) local_ntohl(PyBytes_GET_SIZE(serialized) + 4);
175+
msg_length = PyBytes_GET_SIZE(serialized) + 4;
176+
msg_length = local_ntohl(msg_length);
177+
memcpy(buf + bufpos + msg_type_size, &msg_length, 4);
172178
memcpy(
173179
buf + bufpos + 4 + msg_type_size,
174180
PyBytes_AS_STRING(serialized),

postgresql/protocol/optimized/element3.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,20 +80,23 @@ _pack_tuple_data(PyObject *tup)
8080
ob = PyTuple_GET_ITEM(tup, catt);
8181
if (ob == Py_None)
8282
{
83-
*((uint32_t *) bufpos) = (uint32_t) 0xFFFFFFFFL;
83+
uint32_t attsize = 0xFFFFFFFFL; /* Indicates NULL */
84+
memcpy(bufpos, &attsize, 4);
8485
bufpos = bufpos + 4;
8586
}
8687
else
8788
{
8889
Py_ssize_t size = PyBytes_GET_SIZE(ob);
90+
uint32_t msg_size;
8991
if (size > 0xFFFFFFFE)
9092
{
9193
PyErr_Format(PyExc_OverflowError,
9294
"data size of %d is greater than attribute capacity",
9395
catt
9496
);
9597
}
96-
*((uint32_t *) bufpos) = local_ntohl((uint32_t) size);
98+
msg_size = local_ntohl((uint32_t) size);
99+
memcpy(bufpos, &msg_size, 4);
97100
bufpos = bufpos + 4;
98101
memcpy(bufpos, PyBytes_AS_STRING(ob), PyBytes_GET_SIZE(ob));
99102
bufpos = bufpos + PyBytes_GET_SIZE(ob);
@@ -131,7 +134,8 @@ _unpack_tuple_data(PyObject *dst, uint16_t natts, const char *data, Py_ssize_t d
131134
return(-1);
132135
}
133136

134-
attsize = local_ntohl(*((uint32_t *) (data + position)));
137+
memcpy(&attsize, data + position, 4);
138+
attsize = local_ntohl(attsize);
135139
position += 4;
136140
/*
137141
* NULL.
@@ -214,7 +218,8 @@ parse_tuple_message(PyObject *self, PyObject *args)
214218
"invalid tuple message: %d bytes is too small", dlen);
215219
return(NULL);
216220
}
217-
natts = local_ntohs(*((uint16_t *) (data)));
221+
memcpy(&natts, data, 2);
222+
natts = local_ntohs(natts);
218223

219224
prerob = PyTuple_New(natts);
220225
if (prerob == NULL)

postgresql/protocol/optimized/typio.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@
1717
mFUNC(swap_int2_unpack, METH_O, "PyInt from swapped serialized, int2") \
1818
mFUNC(swap_int4_pack, METH_O, "PyInt to swapped serialized, int4") \
1919
mFUNC(swap_int4_unpack, METH_O, "PyInt from swapped serialized, int4") \
20-
mFUNC(uint2_pack, METH_O, "PyInt to serialized, int2") \
21-
mFUNC(uint2_unpack, METH_O, "PyInt from serialized, int2") \
22-
mFUNC(uint4_pack, METH_O, "PyInt to serialized, int4") \
23-
mFUNC(uint4_unpack, METH_O, "PyInt from serialized, int4") \
24-
mFUNC(swap_uint2_pack, METH_O, "PyInt to swapped serialized, int2") \
25-
mFUNC(swap_uint2_unpack, METH_O, "PyInt from swapped serialized, int2") \
26-
mFUNC(swap_uint4_pack, METH_O, "PyInt to swapped serialized, int4") \
27-
mFUNC(swap_uint4_unpack, METH_O, "PyInt from swapped serialized, int4") \
20+
mFUNC(uint2_pack, METH_O, "PyInt to serialized, uint2") \
21+
mFUNC(uint2_unpack, METH_O, "PyInt from serialized, uint2") \
22+
mFUNC(uint4_pack, METH_O, "PyInt to serialized, uint4") \
23+
mFUNC(uint4_unpack, METH_O, "PyInt from serialized, uint4") \
24+
mFUNC(swap_uint2_pack, METH_O, "PyInt to swapped serialized, uint2") \
25+
mFUNC(swap_uint2_unpack, METH_O, "PyInt from swapped serialized, uint2") \
26+
mFUNC(swap_uint4_pack, METH_O, "PyInt to swapped serialized, uint4") \
27+
mFUNC(swap_uint4_unpack, METH_O, "PyInt from swapped serialized, uint4") \
2828

2929
/*
3030
* Define the swap functionality for those endians.

0 commit comments

Comments
 (0)