• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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