@@ -118,10 +118,11 @@ static int buffer_grow(buffer_t buffer, int min_length) {
118118 }
119119 }
120120
121+ /* See struct comment for why the per-object lock is required here.
122+ * Update cached ptr and capacity under the same lock so they stay in sync. */
121123 Py_BEGIN_CRITICAL_SECTION (buffer -> bytearray );
122124 result = PyByteArray_Resize (buffer -> bytearray , size );
123125 if (result == 0 ) {
124- /* Update cached ptr and capacity while we hold the lock. */
125126 buffer -> ptr = PyByteArray_AS_STRING (buffer -> bytearray );
126127 buffer -> capacity = size ;
127128 }
@@ -171,23 +172,27 @@ int pymongo_buffer_write(buffer_t buffer, const char* data, int size) {
171172 if (buffer_assure_space (buffer , size ) != 0 ) {
172173 return 1 ;
173174 }
175+ /* See struct comment for why the per-object lock is required here.
176+ * buffer->ptr is valid: capacity check above guarantees no resize since
177+ * we last updated ptr in buffer_grow. */
174178 Py_BEGIN_CRITICAL_SECTION (buffer -> bytearray );
175- /* buffer->ptr is valid: sole-owner invariant + capacity check above means
176- * no resize can have occurred between the check and this write. */
177179 memcpy (buffer -> ptr + buffer -> position , data , size );
178180 Py_END_CRITICAL_SECTION ();
179181 buffer -> position += size ;
180182 return 0 ;
181183}
182184
183185void pymongo_buffer_write_byte_at (buffer_t buffer , buffer_position pos , char byte ) {
186+ /* See struct comment for why the per-object lock is required here.
187+ * pos was reserved by pymongo_buffer_save_space; no resize occurs. */
184188 Py_BEGIN_CRITICAL_SECTION (buffer -> bytearray );
185189 buffer -> ptr [pos ] = byte ;
186190 Py_END_CRITICAL_SECTION ();
187191}
188192
189193void pymongo_buffer_write_int32_at (buffer_t buffer , buffer_position pos , int32_t data ) {
190194 uint32_t data_le = BSON_UINT32_TO_LE (data );
195+ /* See struct comment for why the per-object lock is required here. */
191196 Py_BEGIN_CRITICAL_SECTION (buffer -> bytearray );
192197 memcpy (buffer -> ptr + pos , & data_le , 4 );
193198 Py_END_CRITICAL_SECTION ();
@@ -209,6 +214,7 @@ PyObject* pymongo_buffer_finish(buffer_t buffer) {
209214 PyObject * ba ;
210215 assert (buffer -> bytearray != NULL );
211216
217+ /* See struct comment for why the per-object lock is required here. */
212218 Py_BEGIN_CRITICAL_SECTION (buffer -> bytearray );
213219 result = PyByteArray_Resize (buffer -> bytearray , buffer -> position );
214220 Py_END_CRITICAL_SECTION ();
0 commit comments