Skip to content

Commit 678f683

Browse files
committed
Use ssize_t for buffer sizes consistently
1 parent 479a82f commit 678f683

24 files changed

+158
-124
lines changed

Diff for: asyncpg/protocol/buffer.pxd

+17-17
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ cdef class Memory:
99
cdef:
1010
char* buf
1111
object owner
12-
int length
12+
ssize_t length
1313

1414
cdef as_bytes(self)
1515

1616
@staticmethod
17-
cdef inline Memory new(char* buf, object owner, int length)
17+
cdef inline Memory new(char* buf, object owner, ssize_t length)
1818

1919

2020
cdef class WriteBuffer:
@@ -26,10 +26,10 @@ cdef class WriteBuffer:
2626
char *_buf
2727

2828
# Allocated size
29-
size_t _size
29+
ssize_t _size
3030

3131
# Length of data in the buffer
32-
size_t _length
32+
ssize_t _length
3333

3434
# Number of memoryviews attached to the buffer
3535
int _view_count
@@ -39,8 +39,8 @@ cdef class WriteBuffer:
3939

4040
cdef inline _check_readonly(self)
4141
cdef inline len(self)
42-
cdef inline _ensure_alloced(self, size_t extra_length)
43-
cdef _reallocate(self, new_size)
42+
cdef inline _ensure_alloced(self, ssize_t extra_length)
43+
cdef _reallocate(self, ssize_t new_size)
4444
cdef inline start_message(self, char type)
4545
cdef inline end_message(self)
4646
cdef write_buffer(self, WriteBuffer buf)
@@ -81,31 +81,31 @@ cdef class ReadBuffer:
8181
int32_t _bufs_len
8282

8383
# A read position in the first buffer in `_bufs`
84-
int32_t _pos0
84+
ssize_t _pos0
8585

8686
# Length of the first buffer in `_bufs`
87-
int32_t _len0
87+
ssize_t _len0
8888

8989
# A total number of buffered bytes in ReadBuffer
90-
int32_t _length
90+
ssize_t _length
9191

9292
char _current_message_type
9393
int _current_message_len
94-
int32_t _current_message_len_unread
94+
ssize_t _current_message_len_unread
9595
bint _current_message_ready
9696

9797
cdef feed_data(self, data)
9898
cdef inline _ensure_first_buf(self)
9999
cdef _switch_to_next_buf(self)
100100
cdef inline read_byte(self)
101-
cdef inline char* _try_read_bytes(self, int nbytes)
102-
cdef inline read(self, int nbytes)
101+
cdef inline char* _try_read_bytes(self, ssize_t nbytes)
102+
cdef inline read(self, ssize_t nbytes)
103103
cdef inline read_bytes(self, ssize_t n)
104104
cdef inline read_int32(self)
105105
cdef inline read_int16(self)
106106
cdef inline read_cstr(self)
107107
cdef int32_t has_message(self) except -1
108-
cdef inline char* try_consume_message(self, int32_t* len)
108+
cdef inline char* try_consume_message(self, ssize_t* len)
109109
cdef Memory consume_message(self)
110110
cdef discard_message(self)
111111
cdef inline _discard_message(self)
@@ -119,13 +119,13 @@ cdef class ReadBuffer:
119119
cdef class FastReadBuffer:
120120
cdef:
121121
const char* buf
122-
size_t len
122+
ssize_t len
123123

124-
cdef inline const char* read(self, size_t n) except NULL
124+
cdef inline const char* read(self, ssize_t n) except NULL
125125
cdef inline const char* read_all(self)
126126
cdef inline FastReadBuffer slice_from(self, FastReadBuffer source,
127-
size_t len)
128-
cdef _raise_ins_err(self, size_t n, size_t len)
127+
ssize_t len)
128+
cdef _raise_ins_err(self, ssize_t n, ssize_t len)
129129

130130
@staticmethod
131131
cdef FastReadBuffer new()

Diff for: asyncpg/protocol/buffer.pyx

+24-22
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ cdef class Memory:
2121
return cpython.PyBytes_FromStringAndSize(self.buf, self.length)
2222

2323
@staticmethod
24-
cdef inline Memory new(char* buf, object owner, int length):
24+
cdef inline Memory new(char* buf, object owner, ssize_t length):
2525
cdef Memory mem
2626
mem = Memory.__new__(Memory)
2727
mem.buf = buf
@@ -70,13 +70,13 @@ cdef class WriteBuffer:
7070
cdef inline len(self):
7171
return self._length
7272

73-
cdef inline _ensure_alloced(self, size_t extra_length):
74-
cdef size_t new_size = extra_length + self._length
73+
cdef inline _ensure_alloced(self, ssize_t extra_length):
74+
cdef ssize_t new_size = extra_length + self._length
7575

7676
if new_size > self._size:
7777
self._reallocate(new_size)
7878

79-
cdef _reallocate(self, new_size):
79+
cdef _reallocate(self, ssize_t new_size):
8080
cdef char *new_buf
8181

8282
if new_size < _BUFFER_MAX_GROW:
@@ -86,18 +86,18 @@ cdef class WriteBuffer:
8686
new_size += _BUFFER_INITIAL_SIZE
8787

8888
if self._smallbuf_inuse:
89-
new_buf = <char*>PyMem_Malloc(sizeof(char) * new_size)
89+
new_buf = <char*>PyMem_Malloc(sizeof(char) * <size_t>new_size)
9090
if new_buf is NULL:
9191
self._buf = NULL
9292
self._size = 0
9393
self._length = 0
9494
raise MemoryError
95-
memcpy(new_buf, self._buf, self._size)
95+
memcpy(new_buf, self._buf, <size_t>self._size)
9696
self._size = new_size
9797
self._buf = new_buf
9898
self._smallbuf_inuse = False
9999
else:
100-
new_buf = <char*>PyMem_Realloc(<void*>self._buf, new_size)
100+
new_buf = <char*>PyMem_Realloc(<void*>self._buf, <size_t>new_size)
101101
if new_buf is NULL:
102102
PyMem_Free(self._buf)
103103
self._buf = NULL
@@ -117,16 +117,18 @@ cdef class WriteBuffer:
117117

118118
cdef inline end_message(self):
119119
# "length-1" to exclude the message type byte
120-
cdef size_t mlen = self._length - 1
120+
cdef ssize_t mlen = self._length - 1
121121

122122
self._check_readonly()
123123
if not self._message_mode:
124124
raise BufferError(
125125
'end_message can only be called with start_message')
126126
if self._length < 5:
127127
raise BufferError('end_message: buffer is too small')
128+
if mlen > _MAXINT32:
129+
raise BufferError('end_message: message is too large')
128130

129-
hton.pack_int32(&self._buf[1], mlen)
131+
hton.pack_int32(&self._buf[1], <int32_t>mlen)
130132
return self
131133

132134
cdef write_buffer(self, WriteBuffer buf):
@@ -138,7 +140,7 @@ cdef class WriteBuffer:
138140
self._ensure_alloced(buf._length)
139141
memcpy(self._buf + self._length,
140142
<void*>buf._buf,
141-
buf._length)
143+
<size_t>buf._length)
142144
self._length += buf._length
143145

144146
cdef write_byte(self, char b):
@@ -171,7 +173,7 @@ cdef class WriteBuffer:
171173
self._check_readonly()
172174
self._ensure_alloced(len)
173175

174-
memcpy(self._buf + self._length, <void*>data, len)
176+
memcpy(self._buf + self._length, <void*>data, <size_t>len)
175177
self._length += len
176178

177179
cdef write_int16(self, int16_t i):
@@ -246,7 +248,7 @@ cdef class ReadBuffer:
246248

247249
cdef feed_data(self, data):
248250
cdef:
249-
int32_t dlen
251+
ssize_t dlen
250252
bytes data_bytes
251253

252254
if not cpython.PyBytes_CheckExact(data):
@@ -293,7 +295,7 @@ cdef class ReadBuffer:
293295
raise RuntimeError(
294296
'debug: second buffer of ReadBuffer is empty')
295297

296-
cdef inline char* _try_read_bytes(self, int nbytes):
298+
cdef inline char* _try_read_bytes(self, ssize_t nbytes):
297299
# Important: caller must call _ensure_first_buf() prior
298300
# to calling try_read_bytes, and must not overread
299301

@@ -319,10 +321,10 @@ cdef class ReadBuffer:
319321
else:
320322
return NULL
321323

322-
cdef inline read(self, int nbytes):
324+
cdef inline read(self, ssize_t nbytes):
323325
cdef:
324326
object result
325-
int nread
327+
ssize_t nread
326328
char *buf
327329

328330
self._ensure_first_buf()
@@ -419,8 +421,8 @@ cdef class ReadBuffer:
419421
'to be in the buffer')
420422

421423
cdef:
422-
int pos
423-
int nread
424+
ssize_t pos
425+
ssize_t nread
424426
bytes result
425427
char* buf
426428
char* buf_start
@@ -504,8 +506,8 @@ cdef class ReadBuffer:
504506
self._current_message_ready = 1
505507
return 1
506508

507-
cdef inline char* try_consume_message(self, int32_t* len):
508-
cdef int32_t buf_len
509+
cdef inline char* try_consume_message(self, ssize_t* len):
510+
cdef ssize_t buf_len
509511

510512
if not self._current_message_ready:
511513
return NULL
@@ -579,7 +581,7 @@ cdef class ReadBuffer:
579581
@cython.freelist(_BUFFER_FREELIST_SIZE)
580582
cdef class FastReadBuffer:
581583

582-
cdef inline const char* read(self, size_t n) except NULL:
584+
cdef inline const char* read(self, ssize_t n) except NULL:
583585
cdef const char *result
584586

585587
if n > self.len:
@@ -599,12 +601,12 @@ cdef class FastReadBuffer:
599601
return result
600602

601603
cdef inline FastReadBuffer slice_from(self, FastReadBuffer source,
602-
size_t len):
604+
ssize_t len):
603605
self.buf = source.read(len)
604606
self.len = len
605607
return self
606608

607-
cdef _raise_ins_err(self, size_t n, size_t len):
609+
cdef _raise_ins_err(self, ssize_t n, ssize_t len):
608610
raise BufferError(
609611
'insufficient data in buffer: requested {}, remaining {}'.
610612
format(n, self.len))

Diff for: asyncpg/protocol/codecs/array.pyx

+11-6
Original file line numberDiff line numberDiff line change
@@ -38,21 +38,26 @@ cdef inline _is_sub_array(object obj):
3838

3939
cdef _get_array_shape(object obj, int32_t *dims, int32_t *ndims):
4040
cdef:
41-
int32_t mylen = len(obj)
42-
int32_t elemlen = -2
41+
ssize_t mylen = len(obj)
42+
ssize_t elemlen = -2
4343
object it
4444

45+
if mylen > _MAXINT32:
46+
raise ValueError('too many elements in array value')
47+
4548
if ndims[0] > ARRAY_MAXDIM:
4649
raise ValueError(
4750
'number of array dimensions ({}) exceed the maximum expected ({})'.
4851
format(ndims[0], ARRAY_MAXDIM))
4952

50-
dims[ndims[0] - 1] = mylen
53+
dims[ndims[0] - 1] = <int32_t>mylen
5154

5255
for elem in obj:
5356
if _is_sub_array(elem):
5457
if elemlen == -2:
5558
elemlen = len(elem)
59+
if elemlen > _MAXINT32:
60+
raise ValueError('too many elements in array value')
5661
ndims[0] += 1
5762
_get_array_shape(elem, dims, ndims)
5863
else:
@@ -123,7 +128,7 @@ cdef inline array_encode(ConnectionSettings settings, WriteBuffer buf,
123128
# flags
124129
buf.write_int32(0)
125130
# element type
126-
buf.write_int32(elem_oid)
131+
buf.write_int32(<int32_t>elem_oid)
127132
# upper / lower bounds
128133
for i in range(ndims):
129134
buf.write_int32(dims[i])
@@ -137,9 +142,9 @@ cdef inline array_decode(ConnectionSettings settings, FastReadBuffer buf,
137142
cdef:
138143
int32_t ndims = hton.unpack_int32(buf.read(4))
139144
int32_t flags = hton.unpack_int32(buf.read(4))
140-
uint32_t elem_oid = hton.unpack_int32(buf.read(4))
145+
uint32_t elem_oid = <uint32_t>hton.unpack_int32(buf.read(4))
141146
list result
142-
uint32_t i
147+
int i
143148
int32_t elem_len
144149
int64_t elem_count = 1
145150
FastReadBuffer elem_buf = FastReadBuffer.new()

Diff for: asyncpg/protocol/codecs/base.pyx

+10-5
Original file line numberDiff line numberDiff line change
@@ -95,20 +95,25 @@ cdef class Codec:
9595
object obj):
9696
cdef:
9797
WriteBuffer elem_data
98-
int32_t i
98+
int i
9999
list elem_codecs = self.element_codecs
100+
ssize_t count
101+
102+
count = len(obj)
103+
if count > _MAXINT32:
104+
raise ValueError('too many elements in composite type record')
100105

101106
elem_data = WriteBuffer.new()
102107
i = 0
103108
for item in obj:
104-
elem_data.write_int32(self.element_type_oids[i])
109+
elem_data.write_int32(<int32_t>self.element_type_oids[i])
105110
if item is None:
106111
elem_data.write_int32(-1)
107112
else:
108113
(<Codec>elem_codecs[i]).encode(settings, elem_data, item)
109114
i += 1
110115

111-
record_encode_frame(settings, buf, elem_data, len(obj))
116+
record_encode_frame(settings, buf, elem_data, <int32_t>count)
112117

113118
cdef encode_in_python(self, ConnectionSettings settings, WriteBuffer buf,
114119
object obj):
@@ -145,11 +150,11 @@ cdef class Codec:
145150
Codec elem_codec
146151
FastReadBuffer elem_buf = FastReadBuffer.new()
147152

148-
elem_count = hton.unpack_int32(buf.read(4))
153+
elem_count = <uint32_t>hton.unpack_int32(buf.read(4))
149154
result = record.ApgRecord_New(self.element_names, elem_count)
150155
for i in range(elem_count):
151156
elem_typ = self.element_type_oids[i]
152-
received_elem_typ = hton.unpack_int32(buf.read(4))
157+
received_elem_typ = <uint32_t>hton.unpack_int32(buf.read(4))
153158

154159
if received_elem_typ != elem_typ:
155160
raise RuntimeError(

Diff for: asyncpg/protocol/codecs/bits.pyx

+5-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ cdef bits_encode(ConnectionSettings settings, WriteBuffer wbuf, obj):
1414
bint pybuf_used = False
1515
char *buf
1616
ssize_t len
17-
int32_t bitlen
17+
ssize_t bitlen
1818

1919
if cpython.PyBytes_CheckExact(obj):
2020
buf = cpython.PyBytes_AS_STRING(obj)
@@ -31,7 +31,9 @@ cdef bits_encode(ConnectionSettings settings, WriteBuffer wbuf, obj):
3131
bitlen = len * 8
3232

3333
try:
34-
wbuf.write_int32(4 + len)
34+
if bitlen > _MAXINT32:
35+
raise ValueError('bit value too long')
36+
wbuf.write_int32(4 + <int32_t>len)
3537
wbuf.write_int32(<int32_t>bitlen)
3638
wbuf.write_cstr(buf, len)
3739
finally:
@@ -42,7 +44,7 @@ cdef bits_encode(ConnectionSettings settings, WriteBuffer wbuf, obj):
4244
cdef bits_decode(ConnectionSettings settings, FastReadBuffer buf):
4345
cdef:
4446
int32_t bitlen = hton.unpack_int32(buf.read(4))
45-
size_t buf_len = buf.len
47+
ssize_t buf_len = buf.len
4648

4749
bytes_ = cpython.PyBytes_FromStringAndSize(buf.read_all(), buf_len)
4850
return BitString.frombytes(bytes_, bitlen)

Diff for: asyncpg/protocol/codecs/bytea.pyx

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ cdef bytea_encode(ConnectionSettings settings, WriteBuffer wbuf, obj):
3030

3131

3232
cdef bytea_decode(ConnectionSettings settings, FastReadBuffer buf):
33-
cdef size_t buf_len = buf.len
33+
cdef ssize_t buf_len = buf.len
3434
return cpython.PyBytes_FromStringAndSize(buf.read_all(), buf_len)
3535

3636

0 commit comments

Comments
 (0)