Branch data Line data Source code
1 : : /* statement.c - the statement type
2 : : *
3 : : * Copyright (C) 2005-2010 Gerhard Häring <gh@ghaering.de>
4 : : *
5 : : * This file is part of pysqlite.
6 : : *
7 : : * This software is provided 'as-is', without any express or implied
8 : : * warranty. In no event will the authors be held liable for any damages
9 : : * arising from the use of this software.
10 : : *
11 : : * Permission is granted to anyone to use this software for any purpose,
12 : : * including commercial applications, and to alter it and redistribute it
13 : : * freely, subject to the following restrictions:
14 : : *
15 : : * 1. The origin of this software must not be misrepresented; you must not
16 : : * claim that you wrote the original software. If you use this software
17 : : * in a product, an acknowledgment in the product documentation would be
18 : : * appreciated but is not required.
19 : : * 2. Altered source versions must be plainly marked as such, and must not be
20 : : * misrepresented as being the original software.
21 : : * 3. This notice may not be removed or altered from any source distribution.
22 : : */
23 : :
24 : : #include "connection.h"
25 : : #include "statement.h"
26 : : #include "util.h"
27 : :
28 : : /* prototypes */
29 : : static const char *lstrip_sql(const char *sql);
30 : :
31 : : pysqlite_Statement *
32 : 1581 : pysqlite_statement_create(pysqlite_Connection *connection, PyObject *sql)
33 : : {
34 : 1581 : pysqlite_state *state = connection->state;
35 : : assert(PyUnicode_Check(sql));
36 : : Py_ssize_t size;
37 : 1581 : const char *sql_cstr = PyUnicode_AsUTF8AndSize(sql, &size);
38 [ + + ]: 1581 : if (sql_cstr == NULL) {
39 : 4 : return NULL;
40 : : }
41 : :
42 : 1577 : sqlite3 *db = connection->db;
43 : 1577 : int max_length = sqlite3_limit(db, SQLITE_LIMIT_SQL_LENGTH, -1);
44 [ + + ]: 1577 : if (size > max_length) {
45 : 3 : PyErr_SetString(connection->DataError,
46 : : "query string is too large");
47 : 3 : return NULL;
48 : : }
49 [ + + ]: 1574 : if (strlen(sql_cstr) != (size_t)size) {
50 : 4 : PyErr_SetString(connection->ProgrammingError,
51 : : "the query contains a null character");
52 : 4 : return NULL;
53 : : }
54 : :
55 : : sqlite3_stmt *stmt;
56 : : const char *tail;
57 : : int rc;
58 : 1570 : Py_BEGIN_ALLOW_THREADS
59 : 1570 : rc = sqlite3_prepare_v2(db, sql_cstr, (int)size + 1, &stmt, &tail);
60 : 1570 : Py_END_ALLOW_THREADS
61 : :
62 [ + + ]: 1570 : if (rc != SQLITE_OK) {
63 : 25 : _pysqlite_seterror(state, db);
64 : 25 : return NULL;
65 : : }
66 : :
67 [ + + ]: 1545 : if (lstrip_sql(tail) != NULL) {
68 : 10 : PyErr_SetString(connection->ProgrammingError,
69 : : "You can only execute one statement at a time.");
70 : 10 : goto error;
71 : : }
72 : :
73 : : /* Determine if the statement is a DML statement.
74 : : SELECT is the only exception. See #9924. */
75 : 1535 : int is_dml = 0;
76 : 1535 : const char *p = lstrip_sql(sql_cstr);
77 [ + + ]: 1535 : if (p != NULL) {
78 : 3068 : is_dml = (PyOS_strnicmp(p, "insert", 6) == 0)
79 [ + + ]: 1230 : || (PyOS_strnicmp(p, "update", 6) == 0)
80 [ + + ]: 1223 : || (PyOS_strnicmp(p, "delete", 6) == 0)
81 [ + + + + ]: 2764 : || (PyOS_strnicmp(p, "replace", 7) == 0);
82 : : }
83 : :
84 : 1535 : pysqlite_Statement *self = PyObject_GC_New(pysqlite_Statement,
85 : : state->StatementType);
86 [ - + ]: 1535 : if (self == NULL) {
87 : 0 : goto error;
88 : : }
89 : :
90 : 1535 : self->st = stmt;
91 : 1535 : self->is_dml = is_dml;
92 : :
93 : 1535 : PyObject_GC_Track(self);
94 : 1535 : return self;
95 : :
96 : 10 : error:
97 : 10 : (void)sqlite3_finalize(stmt);
98 : 10 : return NULL;
99 : : }
100 : :
101 : : static void
102 : 1535 : stmt_dealloc(pysqlite_Statement *self)
103 : : {
104 : 1535 : PyTypeObject *tp = Py_TYPE(self);
105 : 1535 : PyObject_GC_UnTrack(self);
106 [ + + ]: 1535 : if (self->st) {
107 : 1534 : Py_BEGIN_ALLOW_THREADS
108 : 1534 : sqlite3_finalize(self->st);
109 : 1534 : Py_END_ALLOW_THREADS
110 : 1534 : self->st = 0;
111 : : }
112 : 1535 : tp->tp_free(self);
113 : 1535 : Py_DECREF(tp);
114 : 1535 : }
115 : :
116 : : static int
117 : 334 : stmt_traverse(pysqlite_Statement *self, visitproc visit, void *arg)
118 : : {
119 [ + - - + ]: 334 : Py_VISIT(Py_TYPE(self));
120 : 334 : return 0;
121 : : }
122 : :
123 : : /*
124 : : * Strip leading whitespace and comments from incoming SQL (null terminated C
125 : : * string) and return a pointer to the first non-whitespace, non-comment
126 : : * character.
127 : : *
128 : : * This is used to check if somebody tries to execute more than one SQL query
129 : : * with one execute()/executemany() command, which the DB-API don't allow.
130 : : *
131 : : * It is also used to harden DML query detection.
132 : : */
133 : : static inline const char *
134 : 3080 : lstrip_sql(const char *sql)
135 : : {
136 : : // This loop is borrowed from the SQLite source code.
137 [ + + ]: 4096 : for (const char *pos = sql; *pos; pos++) {
138 [ + + + + ]: 2563 : switch (*pos) {
139 : 1008 : case ' ':
140 : : case '\t':
141 : : case '\f':
142 : : case '\n':
143 : : case '\r':
144 : : // Skip whitespace.
145 : 1008 : break;
146 : 7 : case '-':
147 : : // Skip line comments.
148 [ + + ]: 7 : if (pos[1] == '-') {
149 : 4 : pos += 2;
150 [ + + + + ]: 24 : while (pos[0] && pos[0] != '\n') {
151 : 20 : pos++;
152 : : }
153 [ + + ]: 4 : if (pos[0] == '\0') {
154 : 2 : return NULL;
155 : : }
156 : 2 : continue;
157 : : }
158 : 3 : return pos;
159 : 9 : case '/':
160 : : // Skip C style comments.
161 [ + + ]: 9 : if (pos[1] == '*') {
162 : 7 : pos += 2;
163 [ + + + + : 93 : while (pos[0] && (pos[0] != '*' || pos[1] != '/')) {
+ + ]
164 : 86 : pos++;
165 : : }
166 [ + + ]: 7 : if (pos[0] == '\0') {
167 : 1 : return NULL;
168 : : }
169 : 6 : pos++;
170 : 6 : continue;
171 : : }
172 : 2 : return pos;
173 : 1539 : default:
174 : 1539 : return pos;
175 : : }
176 : : }
177 : :
178 : 1533 : return NULL;
179 : : }
180 : :
181 : : static PyType_Slot stmt_slots[] = {
182 : : {Py_tp_dealloc, stmt_dealloc},
183 : : {Py_tp_traverse, stmt_traverse},
184 : : {0, NULL},
185 : : };
186 : :
187 : : static PyType_Spec stmt_spec = {
188 : : .name = MODULE_NAME ".Statement",
189 : : .basicsize = sizeof(pysqlite_Statement),
190 : : .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
191 : : Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION),
192 : : .slots = stmt_slots,
193 : : };
194 : :
195 : : int
196 : 5 : pysqlite_statement_setup_types(PyObject *module)
197 : : {
198 : 5 : PyObject *type = PyType_FromModuleAndSpec(module, &stmt_spec, NULL);
199 [ - + ]: 5 : if (type == NULL) {
200 : 0 : return -1;
201 : : }
202 : 5 : pysqlite_state *state = pysqlite_get_state(module);
203 : 5 : state->StatementType = (PyTypeObject *)type;
204 : 5 : return 0;
205 : : }
|