1 #ifndef Py_BUILD_CORE_BUILTIN
2 # define Py_BUILD_CORE_MODULE 1
3 #endif
4
5 #include "blob.h"
6 #include "util.h"
7
8 #define clinic_state() (pysqlite_get_state_by_type(Py_TYPE(self)))
9 #include "clinic/blob.c.h"
10 #undef clinic_state
11
12 /*[clinic input]
13 module _sqlite3
14 class _sqlite3.Blob "pysqlite_Blob *" "clinic_state()->BlobType"
15 [clinic start generated code]*/
16 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=908d3e16a45f8da7]*/
17
18 static void
close_blob(pysqlite_Blob * self)19 close_blob(pysqlite_Blob *self)
20 {
21 if (self->blob) {
22 sqlite3_blob *blob = self->blob;
23 self->blob = NULL;
24
25 Py_BEGIN_ALLOW_THREADS
26 sqlite3_blob_close(blob);
27 Py_END_ALLOW_THREADS
28 }
29 }
30
31 static int
blob_traverse(pysqlite_Blob * self,visitproc visit,void * arg)32 blob_traverse(pysqlite_Blob *self, visitproc visit, void *arg)
33 {
34 Py_VISIT(Py_TYPE(self));
35 Py_VISIT(self->connection);
36 return 0;
37 }
38
39 static int
blob_clear(pysqlite_Blob * self)40 blob_clear(pysqlite_Blob *self)
41 {
42 Py_CLEAR(self->connection);
43 return 0;
44 }
45
46 static void
blob_dealloc(pysqlite_Blob * self)47 blob_dealloc(pysqlite_Blob *self)
48 {
49 PyTypeObject *tp = Py_TYPE(self);
50 PyObject_GC_UnTrack(self);
51
52 close_blob(self);
53
54 if (self->in_weakreflist != NULL) {
55 PyObject_ClearWeakRefs((PyObject*)self);
56 }
57 tp->tp_clear((PyObject *)self);
58 tp->tp_free(self);
59 Py_DECREF(tp);
60 }
61
62 // Return 1 if the blob object is usable, 0 if not.
63 static int
check_blob(pysqlite_Blob * self)64 check_blob(pysqlite_Blob *self)
65 {
66 if (!pysqlite_check_connection(self->connection) ||
67 !pysqlite_check_thread(self->connection)) {
68 return 0;
69 }
70 if (self->blob == NULL) {
71 pysqlite_state *state = self->connection->state;
72 PyErr_SetString(state->ProgrammingError,
73 "Cannot operate on a closed blob.");
74 return 0;
75 }
76 return 1;
77 }
78
79
80 /*[clinic input]
81 _sqlite3.Blob.close as blob_close
82
83 Close the blob.
84 [clinic start generated code]*/
85
86 static PyObject *
blob_close_impl(pysqlite_Blob * self)87 blob_close_impl(pysqlite_Blob *self)
88 /*[clinic end generated code: output=848accc20a138d1b input=7bc178a402a40bd8]*/
89 {
90 if (!pysqlite_check_connection(self->connection) ||
91 !pysqlite_check_thread(self->connection))
92 {
93 return NULL;
94 }
95 close_blob(self);
96 Py_RETURN_NONE;
97 };
98
99 void
pysqlite_close_all_blobs(pysqlite_Connection * self)100 pysqlite_close_all_blobs(pysqlite_Connection *self)
101 {
102 for (int i = 0; i < PyList_GET_SIZE(self->blobs); i++) {
103 PyObject *weakref = PyList_GET_ITEM(self->blobs, i);
104 PyObject *blob;
105 if (!PyWeakref_GetRef(weakref, &blob)) {
106 continue;
107 }
108 close_blob((pysqlite_Blob *)blob);
109 Py_DECREF(blob);
110 }
111 }
112
113 static void
blob_seterror(pysqlite_Blob * self,int rc)114 blob_seterror(pysqlite_Blob *self, int rc)
115 {
116 assert(self->connection != NULL);
117 _pysqlite_seterror(self->connection->state, self->connection->db);
118 }
119
120 static PyObject *
read_single(pysqlite_Blob * self,Py_ssize_t offset)121 read_single(pysqlite_Blob *self, Py_ssize_t offset)
122 {
123 unsigned char buf = 0;
124 int rc;
125 Py_BEGIN_ALLOW_THREADS
126 rc = sqlite3_blob_read(self->blob, (void *)&buf, 1, (int)offset);
127 Py_END_ALLOW_THREADS
128
129 if (rc != SQLITE_OK) {
130 blob_seterror(self, rc);
131 return NULL;
132 }
133 return PyLong_FromUnsignedLong((unsigned long)buf);
134 }
135
136 static PyObject *
read_multiple(pysqlite_Blob * self,Py_ssize_t length,Py_ssize_t offset)137 read_multiple(pysqlite_Blob *self, Py_ssize_t length, Py_ssize_t offset)
138 {
139 assert(length <= sqlite3_blob_bytes(self->blob));
140 assert(offset < sqlite3_blob_bytes(self->blob));
141
142 PyObject *buffer = PyBytes_FromStringAndSize(NULL, length);
143 if (buffer == NULL) {
144 return NULL;
145 }
146
147 char *raw_buffer = PyBytes_AS_STRING(buffer);
148 int rc;
149 Py_BEGIN_ALLOW_THREADS
150 rc = sqlite3_blob_read(self->blob, raw_buffer, (int)length, (int)offset);
151 Py_END_ALLOW_THREADS
152
153 if (rc != SQLITE_OK) {
154 Py_DECREF(buffer);
155 blob_seterror(self, rc);
156 return NULL;
157 }
158 return buffer;
159 }
160
161
162 /*[clinic input]
163 _sqlite3.Blob.read as blob_read
164
165 length: int = -1
166 Read length in bytes.
167 /
168
169 Read data at the current offset position.
170
171 If the end of the blob is reached, the data up to end of file will be returned.
172 When length is not specified, or is negative, Blob.read() will read until the
173 end of the blob.
174 [clinic start generated code]*/
175
176 static PyObject *
blob_read_impl(pysqlite_Blob * self,int length)177 blob_read_impl(pysqlite_Blob *self, int length)
178 /*[clinic end generated code: output=1fc99b2541360dde input=f2e4aa4378837250]*/
179 {
180 if (!check_blob(self)) {
181 return NULL;
182 }
183
184 /* Make sure we never read past "EOB". Also read the rest of the blob if a
185 * negative length is specified. */
186 int blob_len = sqlite3_blob_bytes(self->blob);
187 int max_read_len = blob_len - self->offset;
188 if (length < 0 || length > max_read_len) {
189 length = max_read_len;
190 }
191
192 assert(length >= 0);
193 if (length == 0) {
194 return PyBytes_FromStringAndSize(NULL, 0);
195 }
196
197 PyObject *buffer = read_multiple(self, length, self->offset);
198 if (buffer == NULL) {
199 return NULL;
200 }
201 self->offset += length;
202 return buffer;
203 };
204
205 static int
inner_write(pysqlite_Blob * self,const void * buf,Py_ssize_t len,Py_ssize_t offset)206 inner_write(pysqlite_Blob *self, const void *buf, Py_ssize_t len,
207 Py_ssize_t offset)
208 {
209 Py_ssize_t blob_len = sqlite3_blob_bytes(self->blob);
210 Py_ssize_t remaining_len = blob_len - offset;
211 if (len > remaining_len) {
212 PyErr_SetString(PyExc_ValueError, "data longer than blob length");
213 return -1;
214 }
215
216 assert(offset <= blob_len);
217 int rc;
218 Py_BEGIN_ALLOW_THREADS
219 rc = sqlite3_blob_write(self->blob, buf, (int)len, (int)offset);
220 Py_END_ALLOW_THREADS
221
222 if (rc != SQLITE_OK) {
223 blob_seterror(self, rc);
224 return -1;
225 }
226 return 0;
227 }
228
229
230 /*[clinic input]
231 _sqlite3.Blob.write as blob_write
232
233 data: Py_buffer
234 /
235
236 Write data at the current offset.
237
238 This function cannot change the blob length. Writing beyond the end of the
239 blob will result in an exception being raised.
240 [clinic start generated code]*/
241
242 static PyObject *
blob_write_impl(pysqlite_Blob * self,Py_buffer * data)243 blob_write_impl(pysqlite_Blob *self, Py_buffer *data)
244 /*[clinic end generated code: output=b34cf22601b570b2 input=a84712f24a028e6d]*/
245 {
246 if (!check_blob(self)) {
247 return NULL;
248 }
249
250 int rc = inner_write(self, data->buf, data->len, self->offset);
251 if (rc < 0) {
252 return NULL;
253 }
254 self->offset += (int)data->len;
255 Py_RETURN_NONE;
256 }
257
258
259 /*[clinic input]
260 _sqlite3.Blob.seek as blob_seek
261
262 offset: int
263 origin: int = 0
264 /
265
266 Set the current access position to offset.
267
268 The origin argument defaults to os.SEEK_SET (absolute blob positioning).
269 Other values for origin are os.SEEK_CUR (seek relative to the current position)
270 and os.SEEK_END (seek relative to the blob's end).
271 [clinic start generated code]*/
272
273 static PyObject *
blob_seek_impl(pysqlite_Blob * self,int offset,int origin)274 blob_seek_impl(pysqlite_Blob *self, int offset, int origin)
275 /*[clinic end generated code: output=854c5a0e208547a5 input=5da9a07e55fe6bb6]*/
276 {
277 if (!check_blob(self)) {
278 return NULL;
279 }
280
281 int blob_len = sqlite3_blob_bytes(self->blob);
282 switch (origin) {
283 case SEEK_SET:
284 break;
285 case SEEK_CUR:
286 if (offset > INT_MAX - self->offset) {
287 goto overflow;
288 }
289 offset += self->offset;
290 break;
291 case SEEK_END:
292 if (offset > INT_MAX - blob_len) {
293 goto overflow;
294 }
295 offset += blob_len;
296 break;
297 default:
298 PyErr_SetString(PyExc_ValueError,
299 "'origin' should be os.SEEK_SET, os.SEEK_CUR, or "
300 "os.SEEK_END");
301 return NULL;
302 }
303
304 if (offset < 0 || offset > blob_len) {
305 PyErr_SetString(PyExc_ValueError, "offset out of blob range");
306 return NULL;
307 }
308
309 self->offset = offset;
310 Py_RETURN_NONE;
311
312 overflow:
313 PyErr_SetString(PyExc_OverflowError, "seek offset results in overflow");
314 return NULL;
315 }
316
317
318 /*[clinic input]
319 _sqlite3.Blob.tell as blob_tell
320
321 Return the current access position for the blob.
322 [clinic start generated code]*/
323
324 static PyObject *
blob_tell_impl(pysqlite_Blob * self)325 blob_tell_impl(pysqlite_Blob *self)
326 /*[clinic end generated code: output=3d3ba484a90b3a99 input=7e34057aa303612c]*/
327 {
328 if (!check_blob(self)) {
329 return NULL;
330 }
331 return PyLong_FromLong(self->offset);
332 }
333
334
335 /*[clinic input]
336 _sqlite3.Blob.__enter__ as blob_enter
337
338 Blob context manager enter.
339 [clinic start generated code]*/
340
341 static PyObject *
blob_enter_impl(pysqlite_Blob * self)342 blob_enter_impl(pysqlite_Blob *self)
343 /*[clinic end generated code: output=4fd32484b071a6cd input=fe4842c3c582d5a7]*/
344 {
345 if (!check_blob(self)) {
346 return NULL;
347 }
348 return Py_NewRef(self);
349 }
350
351
352 /*[clinic input]
353 _sqlite3.Blob.__exit__ as blob_exit
354
355 type: object
356 val: object
357 tb: object
358 /
359
360 Blob context manager exit.
361 [clinic start generated code]*/
362
363 static PyObject *
blob_exit_impl(pysqlite_Blob * self,PyObject * type,PyObject * val,PyObject * tb)364 blob_exit_impl(pysqlite_Blob *self, PyObject *type, PyObject *val,
365 PyObject *tb)
366 /*[clinic end generated code: output=fc86ceeb2b68c7b2 input=575d9ecea205f35f]*/
367 {
368 if (!check_blob(self)) {
369 return NULL;
370 }
371 close_blob(self);
372 Py_RETURN_FALSE;
373 }
374
375 static Py_ssize_t
blob_length(pysqlite_Blob * self)376 blob_length(pysqlite_Blob *self)
377 {
378 if (!check_blob(self)) {
379 return -1;
380 }
381 return sqlite3_blob_bytes(self->blob);
382 };
383
384 static Py_ssize_t
get_subscript_index(pysqlite_Blob * self,PyObject * item)385 get_subscript_index(pysqlite_Blob *self, PyObject *item)
386 {
387 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
388 if (i == -1 && PyErr_Occurred()) {
389 return -1;
390 }
391 int blob_len = sqlite3_blob_bytes(self->blob);
392 if (i < 0) {
393 i += blob_len;
394 }
395 if (i < 0 || i >= blob_len) {
396 PyErr_SetString(PyExc_IndexError, "Blob index out of range");
397 return -1;
398 }
399 return i;
400 }
401
402 static PyObject *
subscript_index(pysqlite_Blob * self,PyObject * item)403 subscript_index(pysqlite_Blob *self, PyObject *item)
404 {
405 Py_ssize_t i = get_subscript_index(self, item);
406 if (i < 0) {
407 return NULL;
408 }
409 return read_single(self, i);
410 }
411
412 static int
get_slice_info(pysqlite_Blob * self,PyObject * item,Py_ssize_t * start,Py_ssize_t * stop,Py_ssize_t * step,Py_ssize_t * slicelen)413 get_slice_info(pysqlite_Blob *self, PyObject *item, Py_ssize_t *start,
414 Py_ssize_t *stop, Py_ssize_t *step, Py_ssize_t *slicelen)
415 {
416 if (PySlice_Unpack(item, start, stop, step) < 0) {
417 return -1;
418 }
419 int len = sqlite3_blob_bytes(self->blob);
420 *slicelen = PySlice_AdjustIndices(len, start, stop, *step);
421 return 0;
422 }
423
424 static PyObject *
subscript_slice(pysqlite_Blob * self,PyObject * item)425 subscript_slice(pysqlite_Blob *self, PyObject *item)
426 {
427 Py_ssize_t start, stop, step, len;
428 if (get_slice_info(self, item, &start, &stop, &step, &len) < 0) {
429 return NULL;
430 }
431
432 if (step == 1) {
433 return read_multiple(self, len, start);
434 }
435 PyObject *blob = read_multiple(self, stop - start, start);
436 if (blob == NULL) {
437 return NULL;
438 }
439 PyObject *result = PyBytes_FromStringAndSize(NULL, len);
440 if (result != NULL) {
441 char *blob_buf = PyBytes_AS_STRING(blob);
442 char *res_buf = PyBytes_AS_STRING(result);
443 for (Py_ssize_t i = 0, j = 0; i < len; i++, j += step) {
444 res_buf[i] = blob_buf[j];
445 }
446 Py_DECREF(blob);
447 }
448 return result;
449 }
450
451 static PyObject *
blob_subscript(pysqlite_Blob * self,PyObject * item)452 blob_subscript(pysqlite_Blob *self, PyObject *item)
453 {
454 if (!check_blob(self)) {
455 return NULL;
456 }
457
458 if (PyIndex_Check(item)) {
459 return subscript_index(self, item);
460 }
461 if (PySlice_Check(item)) {
462 return subscript_slice(self, item);
463 }
464
465 PyErr_SetString(PyExc_TypeError, "Blob indices must be integers");
466 return NULL;
467 }
468
469 static int
ass_subscript_index(pysqlite_Blob * self,PyObject * item,PyObject * value)470 ass_subscript_index(pysqlite_Blob *self, PyObject *item, PyObject *value)
471 {
472 if (value == NULL) {
473 PyErr_SetString(PyExc_TypeError,
474 "Blob doesn't support item deletion");
475 return -1;
476 }
477 if (!PyLong_Check(value)) {
478 PyErr_Format(PyExc_TypeError,
479 "'%s' object cannot be interpreted as an integer",
480 Py_TYPE(value)->tp_name);
481 return -1;
482 }
483 Py_ssize_t i = get_subscript_index(self, item);
484 if (i < 0) {
485 return -1;
486 }
487
488 long val = PyLong_AsLong(value);
489 if (val == -1 && PyErr_Occurred()) {
490 PyErr_Clear();
491 val = -1;
492 }
493 if (val < 0 || val > 255) {
494 PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)");
495 return -1;
496 }
497 // Downcast to avoid endianness problems.
498 unsigned char byte = (unsigned char)val;
499 return inner_write(self, (const void *)&byte, 1, i);
500 }
501
502 static int
ass_subscript_slice(pysqlite_Blob * self,PyObject * item,PyObject * value)503 ass_subscript_slice(pysqlite_Blob *self, PyObject *item, PyObject *value)
504 {
505 if (value == NULL) {
506 PyErr_SetString(PyExc_TypeError,
507 "Blob doesn't support slice deletion");
508 return -1;
509 }
510
511 Py_ssize_t start, stop, step, len;
512 if (get_slice_info(self, item, &start, &stop, &step, &len) < 0) {
513 return -1;
514 }
515
516 if (len == 0) {
517 return 0;
518 }
519
520 Py_buffer vbuf;
521 if (PyObject_GetBuffer(value, &vbuf, PyBUF_SIMPLE) < 0) {
522 return -1;
523 }
524
525 int rc = -1;
526 if (vbuf.len != len) {
527 PyErr_SetString(PyExc_IndexError,
528 "Blob slice assignment is wrong size");
529 }
530 else if (step == 1) {
531 rc = inner_write(self, vbuf.buf, len, start);
532 }
533 else {
534 PyObject *blob_bytes = read_multiple(self, stop - start, start);
535 if (blob_bytes != NULL) {
536 char *blob_buf = PyBytes_AS_STRING(blob_bytes);
537 for (Py_ssize_t i = 0, j = 0; i < len; i++, j += step) {
538 blob_buf[j] = ((char *)vbuf.buf)[i];
539 }
540 rc = inner_write(self, blob_buf, stop - start, start);
541 Py_DECREF(blob_bytes);
542 }
543 }
544 PyBuffer_Release(&vbuf);
545 return rc;
546 }
547
548 static int
blob_ass_subscript(pysqlite_Blob * self,PyObject * item,PyObject * value)549 blob_ass_subscript(pysqlite_Blob *self, PyObject *item, PyObject *value)
550 {
551 if (!check_blob(self)) {
552 return -1;
553 }
554
555 if (PyIndex_Check(item)) {
556 return ass_subscript_index(self, item, value);
557 }
558 if (PySlice_Check(item)) {
559 return ass_subscript_slice(self, item, value);
560 }
561
562 PyErr_SetString(PyExc_TypeError, "Blob indices must be integers");
563 return -1;
564 }
565
566
567 static PyMethodDef blob_methods[] = {
568 BLOB_CLOSE_METHODDEF
569 BLOB_ENTER_METHODDEF
570 BLOB_EXIT_METHODDEF
571 BLOB_READ_METHODDEF
572 BLOB_SEEK_METHODDEF
573 BLOB_TELL_METHODDEF
574 BLOB_WRITE_METHODDEF
575 {NULL, NULL}
576 };
577
578 static struct PyMemberDef blob_members[] = {
579 {"__weaklistoffset__", Py_T_PYSSIZET, offsetof(pysqlite_Blob, in_weakreflist), Py_READONLY},
580 {NULL},
581 };
582
583 static PyType_Slot blob_slots[] = {
584 {Py_tp_dealloc, blob_dealloc},
585 {Py_tp_traverse, blob_traverse},
586 {Py_tp_clear, blob_clear},
587 {Py_tp_methods, blob_methods},
588 {Py_tp_members, blob_members},
589
590 // Mapping protocol
591 {Py_mp_length, blob_length},
592 {Py_mp_subscript, blob_subscript},
593 {Py_mp_ass_subscript, blob_ass_subscript},
594 {0, NULL},
595 };
596
597 static PyType_Spec blob_spec = {
598 .name = MODULE_NAME ".Blob",
599 .basicsize = sizeof(pysqlite_Blob),
600 .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
601 Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION),
602 .slots = blob_slots,
603 };
604
605 int
pysqlite_blob_setup_types(PyObject * mod)606 pysqlite_blob_setup_types(PyObject *mod)
607 {
608 PyObject *type = PyType_FromModuleAndSpec(mod, &blob_spec, NULL);
609 if (type == NULL) {
610 return -1;
611 }
612 pysqlite_state *state = pysqlite_get_state(mod);
613 state->BlobType = (PyTypeObject *)type;
614 return 0;
615 }
616