xref: /PHP-8.2/ext/pdo_sqlite/sqlite_driver.c (revision 2a1aa8ca)
1 /*
2   +----------------------------------------------------------------------+
3   | Copyright (c) The PHP Group                                          |
4   +----------------------------------------------------------------------+
5   | This source file is subject to version 3.01 of the PHP license,      |
6   | that is bundled with this package in the file LICENSE, and is        |
7   | available through the world-wide-web at the following url:           |
8   | https://www.php.net/license/3_01.txt                                 |
9   | If you did not receive a copy of the PHP license and are unable to   |
10   | obtain it through the world-wide-web, please send a note to          |
11   | license@php.net so we can mail you a copy immediately.               |
12   +----------------------------------------------------------------------+
13   | Author: Wez Furlong <wez@php.net>                                    |
14   +----------------------------------------------------------------------+
15 */
16 
17 #ifdef HAVE_CONFIG_H
18 #include "config.h"
19 #endif
20 
21 #include "php.h"
22 #include "php_ini.h"
23 #include "ext/standard/info.h"
24 #include "pdo/php_pdo.h"
25 #include "pdo/php_pdo_driver.h"
26 #include "php_pdo_sqlite.h"
27 #include "php_pdo_sqlite_int.h"
28 #include "zend_exceptions.h"
29 #include "sqlite_driver_arginfo.h"
30 
_pdo_sqlite_error(pdo_dbh_t * dbh,pdo_stmt_t * stmt,const char * file,int line)31 int _pdo_sqlite_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *file, int line) /* {{{ */
32 {
33 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
34 	pdo_error_type *pdo_err = stmt ? &stmt->error_code : &dbh->error_code;
35 	pdo_sqlite_error_info *einfo = &H->einfo;
36 
37 	einfo->errcode = sqlite3_errcode(H->db);
38 	einfo->file = file;
39 	einfo->line = line;
40 
41 	if (einfo->errcode != SQLITE_OK) {
42 		if (einfo->errmsg) {
43 			pefree(einfo->errmsg, dbh->is_persistent);
44 		}
45 		einfo->errmsg = pestrdup((char*)sqlite3_errmsg(H->db), dbh->is_persistent);
46 	} else { /* no error */
47 		strncpy(*pdo_err, PDO_ERR_NONE, sizeof(*pdo_err));
48 		return 0;
49 	}
50 	switch (einfo->errcode) {
51 		case SQLITE_NOTFOUND:
52 			strncpy(*pdo_err, "42S02", sizeof(*pdo_err));
53 			break;
54 
55 		case SQLITE_INTERRUPT:
56 			strncpy(*pdo_err, "01002", sizeof(*pdo_err));
57 			break;
58 
59 		case SQLITE_NOLFS:
60 			strncpy(*pdo_err, "HYC00", sizeof(*pdo_err));
61 			break;
62 
63 		case SQLITE_TOOBIG:
64 			strncpy(*pdo_err, "22001", sizeof(*pdo_err));
65 			break;
66 
67 		case SQLITE_CONSTRAINT:
68 			strncpy(*pdo_err, "23000", sizeof(*pdo_err));
69 			break;
70 
71 		case SQLITE_ERROR:
72 		default:
73 			strncpy(*pdo_err, "HY000", sizeof(*pdo_err));
74 			break;
75 	}
76 
77 	if (!dbh->methods) {
78 		pdo_throw_exception(einfo->errcode, einfo->errmsg, pdo_err);
79 	}
80 
81 	return einfo->errcode;
82 }
83 /* }}} */
84 
pdo_sqlite_fetch_error_func(pdo_dbh_t * dbh,pdo_stmt_t * stmt,zval * info)85 static void pdo_sqlite_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info)
86 {
87 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
88 	pdo_sqlite_error_info *einfo = &H->einfo;
89 
90 	if (einfo->errcode) {
91 		add_next_index_long(info, einfo->errcode);
92 		add_next_index_string(info, einfo->errmsg);
93 	}
94 }
95 
pdo_sqlite_cleanup_callbacks(pdo_sqlite_db_handle * H)96 static void pdo_sqlite_cleanup_callbacks(pdo_sqlite_db_handle *H)
97 {
98 	struct pdo_sqlite_func *func;
99 
100 	while (H->funcs) {
101 		func = H->funcs;
102 		H->funcs = func->next;
103 
104 		if (H->db) {
105 			/* delete the function from the handle */
106 			sqlite3_create_function(H->db,
107 				func->funcname,
108 				func->argc,
109 				SQLITE_UTF8,
110 				func,
111 				NULL, NULL, NULL);
112 		}
113 
114 		efree((char*)func->funcname);
115 		if (!Z_ISUNDEF(func->func)) {
116 			zval_ptr_dtor(&func->func);
117 		}
118 		if (!Z_ISUNDEF(func->step)) {
119 			zval_ptr_dtor(&func->step);
120 		}
121 		if (!Z_ISUNDEF(func->fini)) {
122 			zval_ptr_dtor(&func->fini);
123 		}
124 		efree(func);
125 	}
126 
127 	while (H->collations) {
128 		struct pdo_sqlite_collation *collation;
129 		collation = H->collations;
130 		H->collations = collation->next;
131 
132 		if (H->db) {
133 			/* delete the collation from the handle */
134 			sqlite3_create_collation(H->db,
135 				collation->name,
136 				SQLITE_UTF8,
137 				collation,
138 				NULL);
139 		}
140 
141 		efree((char*)collation->name);
142 		if (!Z_ISUNDEF(collation->callback)) {
143 			zval_ptr_dtor(&collation->callback);
144 		}
145 		efree(collation);
146 	}
147 }
148 
sqlite_handle_closer(pdo_dbh_t * dbh)149 static void sqlite_handle_closer(pdo_dbh_t *dbh) /* {{{ */
150 {
151 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
152 
153 	if (H) {
154 		pdo_sqlite_error_info *einfo = &H->einfo;
155 
156 		pdo_sqlite_cleanup_callbacks(H);
157 		if (H->db) {
158 #ifdef HAVE_SQLITE3_CLOSE_V2
159 			sqlite3_close_v2(H->db);
160 #else
161 			sqlite3_close(H->db);
162 #endif
163 			H->db = NULL;
164 		}
165 		if (einfo->errmsg) {
166 			pefree(einfo->errmsg, dbh->is_persistent);
167 			einfo->errmsg = NULL;
168 		}
169 		pefree(H, dbh->is_persistent);
170 		dbh->driver_data = NULL;
171 	}
172 }
173 /* }}} */
174 
sqlite_handle_preparer(pdo_dbh_t * dbh,zend_string * sql,pdo_stmt_t * stmt,zval * driver_options)175 static bool sqlite_handle_preparer(pdo_dbh_t *dbh, zend_string *sql, pdo_stmt_t *stmt, zval *driver_options)
176 {
177 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
178 	pdo_sqlite_stmt *S = ecalloc(1, sizeof(pdo_sqlite_stmt));
179 	int i;
180 	const char *tail;
181 
182 	S->H = H;
183 	stmt->driver_data = S;
184 	stmt->methods = &sqlite_stmt_methods;
185 	stmt->supports_placeholders = PDO_PLACEHOLDER_POSITIONAL|PDO_PLACEHOLDER_NAMED;
186 
187 	if (PDO_CURSOR_FWDONLY != pdo_attr_lval(driver_options, PDO_ATTR_CURSOR, PDO_CURSOR_FWDONLY)) {
188 		H->einfo.errcode = SQLITE_ERROR;
189 		pdo_sqlite_error(dbh);
190 		return false;
191 	}
192 
193 	i = sqlite3_prepare_v2(H->db, ZSTR_VAL(sql), ZSTR_LEN(sql), &S->stmt, &tail);
194 	if (i == SQLITE_OK) {
195 		return true;
196 	}
197 
198 	pdo_sqlite_error(dbh);
199 
200 	return false;
201 }
202 
sqlite_handle_doer(pdo_dbh_t * dbh,const zend_string * sql)203 static zend_long sqlite_handle_doer(pdo_dbh_t *dbh, const zend_string *sql)
204 {
205 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
206 	char *errmsg = NULL;
207 
208 	if (sqlite3_exec(H->db, ZSTR_VAL(sql), NULL, NULL, &errmsg) != SQLITE_OK) {
209 		pdo_sqlite_error(dbh);
210 		if (errmsg)
211 			sqlite3_free(errmsg);
212 
213 		return -1;
214 	} else {
215 		return sqlite3_changes(H->db);
216 	}
217 }
218 
pdo_sqlite_last_insert_id(pdo_dbh_t * dbh,const zend_string * name)219 static zend_string *pdo_sqlite_last_insert_id(pdo_dbh_t *dbh, const zend_string *name)
220 {
221 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
222 
223 	return zend_i64_to_str(sqlite3_last_insert_rowid(H->db));
224 }
225 
226 /* NB: doesn't handle binary strings... use prepared stmts for that */
sqlite_handle_quoter(pdo_dbh_t * dbh,const zend_string * unquoted,enum pdo_param_type paramtype)227 static zend_string* sqlite_handle_quoter(pdo_dbh_t *dbh, const zend_string *unquoted, enum pdo_param_type paramtype)
228 {
229 	char *quoted;
230 	if (ZSTR_LEN(unquoted) > (INT_MAX - 3) / 2) {
231 		return NULL;
232 	}
233 	quoted = safe_emalloc(2, ZSTR_LEN(unquoted), 3);
234 	/* TODO use %Q format? */
235 	sqlite3_snprintf(2*ZSTR_LEN(unquoted) + 3, quoted, "'%q'", ZSTR_VAL(unquoted));
236 	zend_string *quoted_str = zend_string_init(quoted, strlen(quoted), 0);
237 	efree(quoted);
238 	return quoted_str;
239 }
240 
sqlite_handle_begin(pdo_dbh_t * dbh)241 static bool sqlite_handle_begin(pdo_dbh_t *dbh)
242 {
243 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
244 	char *errmsg = NULL;
245 
246 	if (sqlite3_exec(H->db, "BEGIN", NULL, NULL, &errmsg) != SQLITE_OK) {
247 		pdo_sqlite_error(dbh);
248 		if (errmsg)
249 			sqlite3_free(errmsg);
250 		return false;
251 	}
252 	return true;
253 }
254 
sqlite_handle_commit(pdo_dbh_t * dbh)255 static bool sqlite_handle_commit(pdo_dbh_t *dbh)
256 {
257 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
258 	char *errmsg = NULL;
259 
260 	if (sqlite3_exec(H->db, "COMMIT", NULL, NULL, &errmsg) != SQLITE_OK) {
261 		pdo_sqlite_error(dbh);
262 		if (errmsg)
263 			sqlite3_free(errmsg);
264 		return false;
265 	}
266 	return true;
267 }
268 
sqlite_handle_rollback(pdo_dbh_t * dbh)269 static bool sqlite_handle_rollback(pdo_dbh_t *dbh)
270 {
271 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
272 	char *errmsg = NULL;
273 
274 	if (sqlite3_exec(H->db, "ROLLBACK", NULL, NULL, &errmsg) != SQLITE_OK) {
275 		pdo_sqlite_error(dbh);
276 		if (errmsg)
277 			sqlite3_free(errmsg);
278 		return false;
279 	}
280 	return true;
281 }
282 
pdo_sqlite_get_attribute(pdo_dbh_t * dbh,zend_long attr,zval * return_value)283 static int pdo_sqlite_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *return_value)
284 {
285 	switch (attr) {
286 		case PDO_ATTR_CLIENT_VERSION:
287 		case PDO_ATTR_SERVER_VERSION:
288 			ZVAL_STRING(return_value, (char *)sqlite3_libversion());
289 			break;
290 
291 		default:
292 			return 0;
293 	}
294 
295 	return 1;
296 }
297 
pdo_sqlite_set_attr(pdo_dbh_t * dbh,zend_long attr,zval * val)298 static bool pdo_sqlite_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val)
299 {
300 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
301 	zend_long lval;
302 
303 	switch (attr) {
304 		case PDO_ATTR_TIMEOUT:
305 			if (!pdo_get_long_param(&lval, val)) {
306 				return false;
307 			}
308 			sqlite3_busy_timeout(H->db, lval * 1000);
309 			return true;
310 		case PDO_SQLITE_ATTR_EXTENDED_RESULT_CODES:
311 			if (!pdo_get_long_param(&lval, val)) {
312 				return false;
313 			}
314 			sqlite3_extended_result_codes(H->db, lval);
315 			return true;
316 	}
317 	return false;
318 }
319 
320 typedef struct {
321 	zval val;
322 	zend_long row;
323 } aggregate_context;
324 
do_callback(struct pdo_sqlite_fci * fc,zval * cb,int argc,sqlite3_value ** argv,sqlite3_context * context,int is_agg)325 static int do_callback(struct pdo_sqlite_fci *fc, zval *cb,
326 		int argc, sqlite3_value **argv, sqlite3_context *context,
327 		int is_agg)
328 {
329 	zval *zargs = NULL;
330 	zval retval;
331 	int i;
332 	int ret;
333 	int fake_argc;
334 	aggregate_context *agg_context = NULL;
335 
336 	if (is_agg) {
337 		is_agg = 2;
338 	}
339 
340 	fake_argc = argc + is_agg;
341 
342 	fc->fci.size = sizeof(fc->fci);
343 	ZVAL_COPY_VALUE(&fc->fci.function_name, cb);
344 	fc->fci.object = NULL;
345 	fc->fci.retval = &retval;
346 	fc->fci.param_count = fake_argc;
347 
348 	/* build up the params */
349 
350 	if (fake_argc) {
351 		zargs = safe_emalloc(fake_argc, sizeof(zval), 0);
352 	}
353 
354 	if (is_agg) {
355 		agg_context = sqlite3_aggregate_context(context, sizeof(aggregate_context));
356 		if (!agg_context) {
357 			efree(zargs);
358 			return FAILURE;
359 		}
360 		if (Z_ISUNDEF(agg_context->val)) {
361 			ZVAL_NEW_REF(&agg_context->val, &EG(uninitialized_zval));
362 		}
363 		ZVAL_COPY_VALUE(&zargs[0], &agg_context->val);
364 		ZVAL_LONG(&zargs[1], ++agg_context->row);
365 	}
366 
367 	for (i = 0; i < argc; i++) {
368 		/* get the value */
369 		switch (sqlite3_value_type(argv[i])) {
370 			case SQLITE_INTEGER:
371 				ZVAL_LONG(&zargs[i + is_agg], sqlite3_value_int(argv[i]));
372 				break;
373 
374 			case SQLITE_FLOAT:
375 				ZVAL_DOUBLE(&zargs[i + is_agg], sqlite3_value_double(argv[i]));
376 				break;
377 
378 			case SQLITE_NULL:
379 				ZVAL_NULL(&zargs[i + is_agg]);
380 				break;
381 
382 			case SQLITE_BLOB:
383 			case SQLITE3_TEXT:
384 			default:
385 				ZVAL_STRINGL(&zargs[i + is_agg], (char*)sqlite3_value_text(argv[i]), sqlite3_value_bytes(argv[i]));
386 				break;
387 		}
388 	}
389 
390 	fc->fci.params = zargs;
391 
392 	if ((ret = zend_call_function(&fc->fci, &fc->fcc)) == FAILURE) {
393 		php_error_docref(NULL, E_WARNING, "An error occurred while invoking the callback");
394 	}
395 
396 	/* clean up the params */
397 	if (zargs) {
398 		for (i = is_agg; i < fake_argc; i++) {
399 			zval_ptr_dtor(&zargs[i]);
400 		}
401 		if (is_agg) {
402 			zval_ptr_dtor(&zargs[1]);
403 		}
404 		efree(zargs);
405 	}
406 
407 	if (!is_agg || !argv) {
408 		/* only set the sqlite return value if we are a scalar function,
409 		 * or if we are finalizing an aggregate */
410 		if (!Z_ISUNDEF(retval)) {
411 			switch (Z_TYPE(retval)) {
412 				case IS_LONG:
413 					sqlite3_result_int(context, Z_LVAL(retval));
414 					break;
415 
416 				case IS_NULL:
417 					sqlite3_result_null(context);
418 					break;
419 
420 				case IS_DOUBLE:
421 					sqlite3_result_double(context, Z_DVAL(retval));
422 					break;
423 
424 				default:
425 					if (!try_convert_to_string(&retval)) {
426 						ret = FAILURE;
427 						break;
428 					}
429 					sqlite3_result_text(context, Z_STRVAL(retval), Z_STRLEN(retval), SQLITE_TRANSIENT);
430 					break;
431 			}
432 		} else {
433 			sqlite3_result_error(context, "failed to invoke callback", 0);
434 		}
435 
436 		if (agg_context) {
437 			zval_ptr_dtor(&agg_context->val);
438 		}
439 	} else {
440 		/* we're stepping in an aggregate; the return value goes into
441 		 * the context */
442 		if (agg_context) {
443 			if (Z_ISUNDEF(retval)) {
444 				return FAILURE;
445 			}
446 			zval_ptr_dtor(Z_REFVAL(agg_context->val));
447 			ZVAL_COPY_VALUE(Z_REFVAL(agg_context->val), &retval);
448 			ZVAL_UNDEF(&retval);
449 		}
450 	}
451 
452 	if (!Z_ISUNDEF(retval)) {
453 		zval_ptr_dtor(&retval);
454 	}
455 
456 	return ret;
457 }
458 
php_sqlite3_func_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)459 static void php_sqlite3_func_callback(sqlite3_context *context, int argc,
460 	sqlite3_value **argv)
461 {
462 	struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
463 
464 	do_callback(&func->afunc, &func->func, argc, argv, context, 0);
465 }
466 
php_sqlite3_func_step_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)467 static void php_sqlite3_func_step_callback(sqlite3_context *context, int argc,
468 	sqlite3_value **argv)
469 {
470 	struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
471 
472 	do_callback(&func->astep, &func->step, argc, argv, context, 1);
473 }
474 
php_sqlite3_func_final_callback(sqlite3_context * context)475 static void php_sqlite3_func_final_callback(sqlite3_context *context)
476 {
477 	struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
478 
479 	do_callback(&func->afini, &func->fini, 0, NULL, context, 1);
480 }
481 
php_sqlite3_collation_callback(void * context,int string1_len,const void * string1,int string2_len,const void * string2)482 static int php_sqlite3_collation_callback(void *context,
483 	int string1_len, const void *string1,
484 	int string2_len, const void *string2)
485 {
486 	int ret;
487 	zval zargs[2];
488 	zval retval;
489 	struct pdo_sqlite_collation *collation = (struct pdo_sqlite_collation*) context;
490 
491 	collation->fc.fci.size = sizeof(collation->fc.fci);
492 	ZVAL_COPY_VALUE(&collation->fc.fci.function_name, &collation->callback);
493 	collation->fc.fci.object = NULL;
494 	collation->fc.fci.retval = &retval;
495 
496 	// Prepare the arguments.
497 	ZVAL_STRINGL(&zargs[0], (char *) string1, string1_len);
498 	ZVAL_STRINGL(&zargs[1], (char *) string2, string2_len);
499 	collation->fc.fci.param_count = 2;
500 	collation->fc.fci.params = zargs;
501 
502 	if ((ret = zend_call_function(&collation->fc.fci, &collation->fc.fcc)) == FAILURE) {
503 		php_error_docref(NULL, E_WARNING, "An error occurred while invoking the callback");
504 	} else if (!Z_ISUNDEF(retval)) {
505 		if (Z_TYPE(retval) != IS_LONG) {
506 			convert_to_long(&retval);
507 		}
508 		ret = 0;
509 		if (Z_LVAL(retval) > 0) {
510 			ret = 1;
511 		} else if (Z_LVAL(retval) < 0) {
512 			ret = -1;
513 		}
514 		zval_ptr_dtor(&retval);
515 	}
516 
517 	zval_ptr_dtor(&zargs[0]);
518 	zval_ptr_dtor(&zargs[1]);
519 
520 	return ret;
521 }
522 
523 /* {{{ bool SQLite::sqliteCreateFunction(string name, callable callback [, int argcount, int flags])
524    Registers a UDF with the sqlite db handle */
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateFunction)525 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateFunction)
526 {
527 	struct pdo_sqlite_func *func;
528 	zend_fcall_info fci;
529 	zend_fcall_info_cache fcc;
530 	char *func_name;
531 	size_t func_name_len;
532 	zend_long argc = -1;
533 	zend_long flags = 0;
534 	pdo_dbh_t *dbh;
535 	pdo_sqlite_db_handle *H;
536 	int ret;
537 
538 	ZEND_PARSE_PARAMETERS_START(2, 4)
539 		Z_PARAM_STRING(func_name, func_name_len)
540 		Z_PARAM_FUNC(fci, fcc)
541 		Z_PARAM_OPTIONAL
542 		Z_PARAM_LONG(argc)
543 		Z_PARAM_LONG(flags)
544 	ZEND_PARSE_PARAMETERS_END();
545 
546 	dbh = Z_PDO_DBH_P(ZEND_THIS);
547 	PDO_CONSTRUCT_CHECK;
548 
549 	H = (pdo_sqlite_db_handle *)dbh->driver_data;
550 
551 	func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
552 
553 	ret = sqlite3_create_function(H->db, func_name, argc, flags | SQLITE_UTF8,
554 			func, php_sqlite3_func_callback, NULL, NULL);
555 	if (ret == SQLITE_OK) {
556 		func->funcname = estrdup(func_name);
557 
558 		ZVAL_COPY(&func->func, &fci.function_name);
559 
560 		func->argc = argc;
561 
562 		func->next = H->funcs;
563 		H->funcs = func;
564 
565 		RETURN_TRUE;
566 	}
567 
568 	efree(func);
569 	RETURN_FALSE;
570 }
571 /* }}} */
572 
573 /* {{{ bool SQLite::sqliteCreateAggregate(string name, callable step, callable fini [, int argcount])
574    Registers a UDF with the sqlite db handle */
575 
576 /* The step function should have the prototype:
577    mixed step(mixed $context, int $rownumber, $value [, $value2 [, ...]])
578 
579    $context will be null for the first row; on subsequent rows it will have
580    the value that was previously returned from the step function; you should
581    use this to maintain state for the aggregate.
582 
583    The fini function should have the prototype:
584    mixed fini(mixed $context, int $rownumber)
585 
586    $context will hold the return value from the very last call to the step function.
587    rownumber will hold the number of rows over which the aggregate was performed.
588    The return value of this function will be used as the return value for this
589    aggregate UDF.
590 */
591 
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateAggregate)592 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateAggregate)
593 {
594 	struct pdo_sqlite_func *func;
595 	zend_fcall_info step_fci, fini_fci;
596 	zend_fcall_info_cache step_fcc, fini_fcc;
597 	char *func_name;
598 	size_t func_name_len;
599 	zend_long argc = -1;
600 	pdo_dbh_t *dbh;
601 	pdo_sqlite_db_handle *H;
602 	int ret;
603 
604 	ZEND_PARSE_PARAMETERS_START(3, 4)
605 		Z_PARAM_STRING(func_name, func_name_len)
606 		Z_PARAM_FUNC(step_fci, step_fcc)
607 		Z_PARAM_FUNC(fini_fci, fini_fcc)
608 		Z_PARAM_OPTIONAL
609 		Z_PARAM_LONG(argc)
610 	ZEND_PARSE_PARAMETERS_END();
611 
612 	dbh = Z_PDO_DBH_P(ZEND_THIS);
613 	PDO_CONSTRUCT_CHECK;
614 
615 	H = (pdo_sqlite_db_handle *)dbh->driver_data;
616 
617 	func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
618 
619 	ret = sqlite3_create_function(H->db, func_name, argc, SQLITE_UTF8,
620 			func, NULL, php_sqlite3_func_step_callback, php_sqlite3_func_final_callback);
621 	if (ret == SQLITE_OK) {
622 		func->funcname = estrdup(func_name);
623 
624 		ZVAL_COPY(&func->step, &step_fci.function_name);
625 
626 		ZVAL_COPY(&func->fini, &fini_fci.function_name);
627 
628 		func->argc = argc;
629 
630 		func->next = H->funcs;
631 		H->funcs = func;
632 
633 		RETURN_TRUE;
634 	}
635 
636 	efree(func);
637 	RETURN_FALSE;
638 }
639 /* }}} */
640 
641 /* {{{ bool SQLite::sqliteCreateCollation(string name, callable callback)
642    Registers a collation with the sqlite db handle */
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateCollation)643 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateCollation)
644 {
645 	struct pdo_sqlite_collation *collation;
646 	zend_fcall_info fci;
647 	zend_fcall_info_cache fcc;
648 	char *collation_name;
649 	size_t collation_name_len;
650 	pdo_dbh_t *dbh;
651 	pdo_sqlite_db_handle *H;
652 	int ret;
653 
654 	ZEND_PARSE_PARAMETERS_START(2, 2)
655 		Z_PARAM_STRING(collation_name, collation_name_len)
656 		Z_PARAM_FUNC(fci, fcc)
657 	ZEND_PARSE_PARAMETERS_END();
658 
659 	dbh = Z_PDO_DBH_P(ZEND_THIS);
660 	PDO_CONSTRUCT_CHECK;
661 
662 	H = (pdo_sqlite_db_handle *)dbh->driver_data;
663 
664 	collation = (struct pdo_sqlite_collation*)ecalloc(1, sizeof(*collation));
665 
666 	ret = sqlite3_create_collation(H->db, collation_name, SQLITE_UTF8, collation, php_sqlite3_collation_callback);
667 	if (ret == SQLITE_OK) {
668 		collation->name = estrdup(collation_name);
669 
670 		ZVAL_COPY(&collation->callback, &fci.function_name);
671 
672 		collation->next = H->collations;
673 		H->collations = collation;
674 
675 		RETURN_TRUE;
676 	}
677 
678 	efree(collation);
679 	RETURN_FALSE;
680 }
681 /* }}} */
682 
get_driver_methods(pdo_dbh_t * dbh,int kind)683 static const zend_function_entry *get_driver_methods(pdo_dbh_t *dbh, int kind)
684 {
685 	switch (kind) {
686 		case PDO_DBH_DRIVER_METHOD_KIND_DBH:
687 			return class_PDO_SQLite_Ext_methods;
688 
689 		default:
690 			return NULL;
691 	}
692 }
693 
pdo_sqlite_request_shutdown(pdo_dbh_t * dbh)694 static void pdo_sqlite_request_shutdown(pdo_dbh_t *dbh)
695 {
696 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
697 	/* unregister functions, so that they don't linger for the next
698 	 * request */
699 	if (H) {
700 		pdo_sqlite_cleanup_callbacks(H);
701 	}
702 }
703 
pdo_sqlite_get_gc(pdo_dbh_t * dbh,zend_get_gc_buffer * gc_buffer)704 static void pdo_sqlite_get_gc(pdo_dbh_t *dbh, zend_get_gc_buffer *gc_buffer)
705 {
706 	pdo_sqlite_db_handle *H = dbh->driver_data;
707 
708 	struct pdo_sqlite_func *func = H->funcs;
709 	while (func) {
710 		zend_get_gc_buffer_add_zval(gc_buffer, &func->func);
711 		zend_get_gc_buffer_add_zval(gc_buffer, &func->step);
712 		zend_get_gc_buffer_add_zval(gc_buffer, &func->fini);
713 		func = func->next;
714 	}
715 
716 	struct pdo_sqlite_collation *collation = H->collations;
717 	while (collation) {
718 		zend_get_gc_buffer_add_zval(gc_buffer, &collation->callback);
719 		collation = collation->next;
720 	}
721 }
722 
723 static const struct pdo_dbh_methods sqlite_methods = {
724 	sqlite_handle_closer,
725 	sqlite_handle_preparer,
726 	sqlite_handle_doer,
727 	sqlite_handle_quoter,
728 	sqlite_handle_begin,
729 	sqlite_handle_commit,
730 	sqlite_handle_rollback,
731 	pdo_sqlite_set_attr,
732 	pdo_sqlite_last_insert_id,
733 	pdo_sqlite_fetch_error_func,
734 	pdo_sqlite_get_attribute,
735 	NULL,	/* check_liveness: not needed */
736 	get_driver_methods,
737 	pdo_sqlite_request_shutdown,
738 	NULL, /* in transaction, use PDO's internal tracking mechanism */
739 	pdo_sqlite_get_gc
740 };
741 
make_filename_safe(const char * filename)742 static char *make_filename_safe(const char *filename)
743 {
744 	if (!filename) {
745 		return NULL;
746 	}
747 	if (*filename && strncasecmp(filename, "file:", 5) == 0) {
748 		if (PG(open_basedir) && *PG(open_basedir)) {
749 			return NULL;
750 		}
751 		return estrdup(filename);
752 	}
753 	if (*filename && strcmp(filename, ":memory:")) {
754 		char *fullpath = expand_filepath(filename, NULL);
755 
756 		if (!fullpath) {
757 			return NULL;
758 		}
759 
760 		if (php_check_open_basedir(fullpath)) {
761 			efree(fullpath);
762 			return NULL;
763 		}
764 		return fullpath;
765 	}
766 	return estrdup(filename);
767 }
768 
authorizer(void * autharg,int access_type,const char * arg3,const char * arg4,const char * arg5,const char * arg6)769 static int authorizer(void *autharg, int access_type, const char *arg3, const char *arg4,
770 		const char *arg5, const char *arg6)
771 {
772 	char *filename;
773 	switch (access_type) {
774 		case SQLITE_ATTACH: {
775 			filename = make_filename_safe(arg3);
776 			if (!filename) {
777 				return SQLITE_DENY;
778 			}
779 			efree(filename);
780 			return SQLITE_OK;
781 		}
782 
783 		default:
784 			/* access allowed */
785 			return SQLITE_OK;
786 	}
787 }
788 
pdo_sqlite_handle_factory(pdo_dbh_t * dbh,zval * driver_options)789 static int pdo_sqlite_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ */
790 {
791 	pdo_sqlite_db_handle *H;
792 	int i, ret = 0;
793 	zend_long timeout = 60, flags;
794 	char *filename;
795 
796 	H = pecalloc(1, sizeof(pdo_sqlite_db_handle), dbh->is_persistent);
797 
798 	H->einfo.errcode = 0;
799 	H->einfo.errmsg = NULL;
800 	dbh->driver_data = H;
801 
802 	/* skip all but this one param event */
803 	dbh->skip_param_evt = 0x7F ^ (1 << PDO_PARAM_EVT_EXEC_PRE);
804 
805 	filename = make_filename_safe(dbh->data_source);
806 
807 	if (!filename) {
808 		zend_throw_exception_ex(php_pdo_get_exception(), 0,
809 			"open_basedir prohibits opening %s",
810 			dbh->data_source);
811 		goto cleanup;
812 	}
813 
814 	flags = pdo_attr_lval(driver_options, PDO_SQLITE_ATTR_OPEN_FLAGS, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
815 
816 	if (!(PG(open_basedir) && *PG(open_basedir))) {
817 		flags |= SQLITE_OPEN_URI;
818 	}
819 	i = sqlite3_open_v2(filename, &H->db, flags, NULL);
820 
821 	efree(filename);
822 
823 	if (i != SQLITE_OK) {
824 		pdo_sqlite_error(dbh);
825 		goto cleanup;
826 	}
827 
828 	if (PG(open_basedir) && *PG(open_basedir)) {
829 		sqlite3_set_authorizer(H->db, authorizer, NULL);
830 	}
831 
832 	if (driver_options) {
833 		timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, timeout);
834 	}
835 	sqlite3_busy_timeout(H->db, timeout * 1000);
836 
837 	dbh->alloc_own_columns = 1;
838 	dbh->max_escaped_char_length = 2;
839 
840 	ret = 1;
841 
842 cleanup:
843 	dbh->methods = &sqlite_methods;
844 
845 	return ret;
846 }
847 /* }}} */
848 
849 const pdo_driver_t pdo_sqlite_driver = {
850 	PDO_DRIVER_HEADER(sqlite),
851 	pdo_sqlite_handle_factory
852 };
853