xref: /PHP-8.1/ext/pdo_sqlite/sqlite_driver.c (revision a6a80eef)
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 				zval_ptr_dtor(&agg_context->val);
445 				return FAILURE;
446 			}
447 			zval_ptr_dtor(Z_REFVAL(agg_context->val));
448 			ZVAL_COPY_VALUE(Z_REFVAL(agg_context->val), &retval);
449 			ZVAL_UNDEF(&retval);
450 		}
451 	}
452 
453 	if (!Z_ISUNDEF(retval)) {
454 		zval_ptr_dtor(&retval);
455 	}
456 
457 	return ret;
458 }
459 
php_sqlite3_func_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)460 static void php_sqlite3_func_callback(sqlite3_context *context, int argc,
461 	sqlite3_value **argv)
462 {
463 	struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
464 
465 	do_callback(&func->afunc, &func->func, argc, argv, context, 0);
466 }
467 
php_sqlite3_func_step_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)468 static void php_sqlite3_func_step_callback(sqlite3_context *context, int argc,
469 	sqlite3_value **argv)
470 {
471 	struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
472 
473 	do_callback(&func->astep, &func->step, argc, argv, context, 1);
474 }
475 
php_sqlite3_func_final_callback(sqlite3_context * context)476 static void php_sqlite3_func_final_callback(sqlite3_context *context)
477 {
478 	struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
479 
480 	do_callback(&func->afini, &func->fini, 0, NULL, context, 1);
481 }
482 
php_sqlite3_collation_callback(void * context,int string1_len,const void * string1,int string2_len,const void * string2)483 static int php_sqlite3_collation_callback(void *context,
484 	int string1_len, const void *string1,
485 	int string2_len, const void *string2)
486 {
487 	int ret;
488 	zval zargs[2];
489 	zval retval;
490 	struct pdo_sqlite_collation *collation = (struct pdo_sqlite_collation*) context;
491 
492 	collation->fc.fci.size = sizeof(collation->fc.fci);
493 	ZVAL_COPY_VALUE(&collation->fc.fci.function_name, &collation->callback);
494 	collation->fc.fci.object = NULL;
495 	collation->fc.fci.retval = &retval;
496 
497 	// Prepare the arguments.
498 	ZVAL_STRINGL(&zargs[0], (char *) string1, string1_len);
499 	ZVAL_STRINGL(&zargs[1], (char *) string2, string2_len);
500 	collation->fc.fci.param_count = 2;
501 	collation->fc.fci.params = zargs;
502 
503 	if ((ret = zend_call_function(&collation->fc.fci, &collation->fc.fcc)) == FAILURE) {
504 		php_error_docref(NULL, E_WARNING, "An error occurred while invoking the callback");
505 	} else if (!Z_ISUNDEF(retval)) {
506 		if (Z_TYPE(retval) != IS_LONG) {
507 			convert_to_long(&retval);
508 		}
509 		ret = 0;
510 		if (Z_LVAL(retval) > 0) {
511 			ret = 1;
512 		} else if (Z_LVAL(retval) < 0) {
513 			ret = -1;
514 		}
515 		zval_ptr_dtor(&retval);
516 	}
517 
518 	zval_ptr_dtor(&zargs[0]);
519 	zval_ptr_dtor(&zargs[1]);
520 
521 	return ret;
522 }
523 
524 /* {{{ bool SQLite::sqliteCreateFunction(string name, callable callback [, int argcount, int flags])
525    Registers a UDF with the sqlite db handle */
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateFunction)526 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateFunction)
527 {
528 	struct pdo_sqlite_func *func;
529 	zend_fcall_info fci;
530 	zend_fcall_info_cache fcc;
531 	char *func_name;
532 	size_t func_name_len;
533 	zend_long argc = -1;
534 	zend_long flags = 0;
535 	pdo_dbh_t *dbh;
536 	pdo_sqlite_db_handle *H;
537 	int ret;
538 
539 	ZEND_PARSE_PARAMETERS_START(2, 4)
540 		Z_PARAM_STRING(func_name, func_name_len)
541 		Z_PARAM_FUNC(fci, fcc)
542 		Z_PARAM_OPTIONAL
543 		Z_PARAM_LONG(argc)
544 		Z_PARAM_LONG(flags)
545 	ZEND_PARSE_PARAMETERS_END();
546 
547 	dbh = Z_PDO_DBH_P(ZEND_THIS);
548 	PDO_CONSTRUCT_CHECK;
549 
550 	H = (pdo_sqlite_db_handle *)dbh->driver_data;
551 
552 	func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
553 
554 	ret = sqlite3_create_function(H->db, func_name, argc, flags | SQLITE_UTF8,
555 			func, php_sqlite3_func_callback, NULL, NULL);
556 	if (ret == SQLITE_OK) {
557 		func->funcname = estrdup(func_name);
558 
559 		ZVAL_COPY(&func->func, &fci.function_name);
560 
561 		func->argc = argc;
562 
563 		func->next = H->funcs;
564 		H->funcs = func;
565 
566 		RETURN_TRUE;
567 	}
568 
569 	efree(func);
570 	RETURN_FALSE;
571 }
572 /* }}} */
573 
574 /* {{{ bool SQLite::sqliteCreateAggregate(string name, callable step, callable fini [, int argcount])
575    Registers a UDF with the sqlite db handle */
576 
577 /* The step function should have the prototype:
578    mixed step(mixed $context, int $rownumber, $value [, $value2 [, ...]])
579 
580    $context will be null for the first row; on subsequent rows it will have
581    the value that was previously returned from the step function; you should
582    use this to maintain state for the aggregate.
583 
584    The fini function should have the prototype:
585    mixed fini(mixed $context, int $rownumber)
586 
587    $context will hold the return value from the very last call to the step function.
588    rownumber will hold the number of rows over which the aggregate was performed.
589    The return value of this function will be used as the return value for this
590    aggregate UDF.
591 */
592 
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateAggregate)593 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateAggregate)
594 {
595 	struct pdo_sqlite_func *func;
596 	zend_fcall_info step_fci, fini_fci;
597 	zend_fcall_info_cache step_fcc, fini_fcc;
598 	char *func_name;
599 	size_t func_name_len;
600 	zend_long argc = -1;
601 	pdo_dbh_t *dbh;
602 	pdo_sqlite_db_handle *H;
603 	int ret;
604 
605 	ZEND_PARSE_PARAMETERS_START(3, 4)
606 		Z_PARAM_STRING(func_name, func_name_len)
607 		Z_PARAM_FUNC(step_fci, step_fcc)
608 		Z_PARAM_FUNC(fini_fci, fini_fcc)
609 		Z_PARAM_OPTIONAL
610 		Z_PARAM_LONG(argc)
611 	ZEND_PARSE_PARAMETERS_END();
612 
613 	dbh = Z_PDO_DBH_P(ZEND_THIS);
614 	PDO_CONSTRUCT_CHECK;
615 
616 	H = (pdo_sqlite_db_handle *)dbh->driver_data;
617 
618 	func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
619 
620 	ret = sqlite3_create_function(H->db, func_name, argc, SQLITE_UTF8,
621 			func, NULL, php_sqlite3_func_step_callback, php_sqlite3_func_final_callback);
622 	if (ret == SQLITE_OK) {
623 		func->funcname = estrdup(func_name);
624 
625 		ZVAL_COPY(&func->step, &step_fci.function_name);
626 
627 		ZVAL_COPY(&func->fini, &fini_fci.function_name);
628 
629 		func->argc = argc;
630 
631 		func->next = H->funcs;
632 		H->funcs = func;
633 
634 		RETURN_TRUE;
635 	}
636 
637 	efree(func);
638 	RETURN_FALSE;
639 }
640 /* }}} */
641 
642 /* {{{ bool SQLite::sqliteCreateCollation(string name, callable callback)
643    Registers a collation with the sqlite db handle */
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateCollation)644 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateCollation)
645 {
646 	struct pdo_sqlite_collation *collation;
647 	zend_fcall_info fci;
648 	zend_fcall_info_cache fcc;
649 	char *collation_name;
650 	size_t collation_name_len;
651 	pdo_dbh_t *dbh;
652 	pdo_sqlite_db_handle *H;
653 	int ret;
654 
655 	ZEND_PARSE_PARAMETERS_START(2, 2)
656 		Z_PARAM_STRING(collation_name, collation_name_len)
657 		Z_PARAM_FUNC(fci, fcc)
658 	ZEND_PARSE_PARAMETERS_END();
659 
660 	dbh = Z_PDO_DBH_P(ZEND_THIS);
661 	PDO_CONSTRUCT_CHECK;
662 
663 	H = (pdo_sqlite_db_handle *)dbh->driver_data;
664 
665 	collation = (struct pdo_sqlite_collation*)ecalloc(1, sizeof(*collation));
666 
667 	ret = sqlite3_create_collation(H->db, collation_name, SQLITE_UTF8, collation, php_sqlite3_collation_callback);
668 	if (ret == SQLITE_OK) {
669 		collation->name = estrdup(collation_name);
670 
671 		ZVAL_COPY(&collation->callback, &fci.function_name);
672 
673 		collation->next = H->collations;
674 		H->collations = collation;
675 
676 		RETURN_TRUE;
677 	}
678 
679 	efree(collation);
680 	RETURN_FALSE;
681 }
682 /* }}} */
683 
get_driver_methods(pdo_dbh_t * dbh,int kind)684 static const zend_function_entry *get_driver_methods(pdo_dbh_t *dbh, int kind)
685 {
686 	switch (kind) {
687 		case PDO_DBH_DRIVER_METHOD_KIND_DBH:
688 			return class_PDO_SQLite_Ext_methods;
689 
690 		default:
691 			return NULL;
692 	}
693 }
694 
pdo_sqlite_request_shutdown(pdo_dbh_t * dbh)695 static void pdo_sqlite_request_shutdown(pdo_dbh_t *dbh)
696 {
697 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
698 	/* unregister functions, so that they don't linger for the next
699 	 * request */
700 	if (H) {
701 		pdo_sqlite_cleanup_callbacks(H);
702 	}
703 }
704 
pdo_sqlite_get_gc(pdo_dbh_t * dbh,zend_get_gc_buffer * gc_buffer)705 static void pdo_sqlite_get_gc(pdo_dbh_t *dbh, zend_get_gc_buffer *gc_buffer)
706 {
707 	pdo_sqlite_db_handle *H = dbh->driver_data;
708 
709 	struct pdo_sqlite_func *func = H->funcs;
710 	while (func) {
711 		zend_get_gc_buffer_add_zval(gc_buffer, &func->func);
712 		zend_get_gc_buffer_add_zval(gc_buffer, &func->step);
713 		zend_get_gc_buffer_add_zval(gc_buffer, &func->fini);
714 		func = func->next;
715 	}
716 
717 	struct pdo_sqlite_collation *collation = H->collations;
718 	while (collation) {
719 		zend_get_gc_buffer_add_zval(gc_buffer, &collation->callback);
720 		collation = collation->next;
721 	}
722 }
723 
724 static const struct pdo_dbh_methods sqlite_methods = {
725 	sqlite_handle_closer,
726 	sqlite_handle_preparer,
727 	sqlite_handle_doer,
728 	sqlite_handle_quoter,
729 	sqlite_handle_begin,
730 	sqlite_handle_commit,
731 	sqlite_handle_rollback,
732 	pdo_sqlite_set_attr,
733 	pdo_sqlite_last_insert_id,
734 	pdo_sqlite_fetch_error_func,
735 	pdo_sqlite_get_attribute,
736 	NULL,	/* check_liveness: not needed */
737 	get_driver_methods,
738 	pdo_sqlite_request_shutdown,
739 	NULL, /* in transaction, use PDO's internal tracking mechanism */
740 	pdo_sqlite_get_gc
741 };
742 
make_filename_safe(const char * filename)743 static char *make_filename_safe(const char *filename)
744 {
745 	if (!filename) {
746 		return NULL;
747 	}
748 	if (*filename && strncasecmp(filename, "file:", 5) == 0) {
749 		if (PG(open_basedir) && *PG(open_basedir)) {
750 			return NULL;
751 		}
752 		return estrdup(filename);
753 	}
754 	if (*filename && memcmp(filename, ":memory:", sizeof(":memory:"))) {
755 		char *fullpath = expand_filepath(filename, NULL);
756 
757 		if (!fullpath) {
758 			return NULL;
759 		}
760 
761 		if (php_check_open_basedir(fullpath)) {
762 			efree(fullpath);
763 			return NULL;
764 		}
765 		return fullpath;
766 	}
767 	return estrdup(filename);
768 }
769 
authorizer(void * autharg,int access_type,const char * arg3,const char * arg4,const char * arg5,const char * arg6)770 static int authorizer(void *autharg, int access_type, const char *arg3, const char *arg4,
771 		const char *arg5, const char *arg6)
772 {
773 	char *filename;
774 	switch (access_type) {
775 		case SQLITE_COPY: {
776 			filename = make_filename_safe(arg4);
777 			if (!filename) {
778 				return SQLITE_DENY;
779 			}
780 			efree(filename);
781 			return SQLITE_OK;
782 		}
783 
784 		case SQLITE_ATTACH: {
785 			filename = make_filename_safe(arg3);
786 			if (!filename) {
787 				return SQLITE_DENY;
788 			}
789 			efree(filename);
790 			return SQLITE_OK;
791 		}
792 
793 		default:
794 			/* access allowed */
795 			return SQLITE_OK;
796 	}
797 }
798 
pdo_sqlite_handle_factory(pdo_dbh_t * dbh,zval * driver_options)799 static int pdo_sqlite_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ */
800 {
801 	pdo_sqlite_db_handle *H;
802 	int i, ret = 0;
803 	zend_long timeout = 60, flags;
804 	char *filename;
805 
806 	H = pecalloc(1, sizeof(pdo_sqlite_db_handle), dbh->is_persistent);
807 
808 	H->einfo.errcode = 0;
809 	H->einfo.errmsg = NULL;
810 	dbh->driver_data = H;
811 
812 	/* skip all but this one param event */
813 	dbh->skip_param_evt = 0x7F ^ (1 << PDO_PARAM_EVT_EXEC_PRE);
814 
815 	filename = make_filename_safe(dbh->data_source);
816 
817 	if (!filename) {
818 		zend_throw_exception_ex(php_pdo_get_exception(), 0,
819 			"open_basedir prohibits opening %s",
820 			dbh->data_source);
821 		goto cleanup;
822 	}
823 
824 	flags = pdo_attr_lval(driver_options, PDO_SQLITE_ATTR_OPEN_FLAGS, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
825 
826 	if (!(PG(open_basedir) && *PG(open_basedir))) {
827 		flags |= SQLITE_OPEN_URI;
828 	}
829 	i = sqlite3_open_v2(filename, &H->db, flags, NULL);
830 
831 	efree(filename);
832 
833 	if (i != SQLITE_OK) {
834 		pdo_sqlite_error(dbh);
835 		goto cleanup;
836 	}
837 
838 	if (PG(open_basedir) && *PG(open_basedir)) {
839 		sqlite3_set_authorizer(H->db, authorizer, NULL);
840 	}
841 
842 	if (driver_options) {
843 		timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, timeout);
844 	}
845 	sqlite3_busy_timeout(H->db, timeout * 1000);
846 
847 	dbh->alloc_own_columns = 1;
848 	dbh->max_escaped_char_length = 2;
849 
850 	ret = 1;
851 
852 cleanup:
853 	dbh->methods = &sqlite_methods;
854 
855 	return ret;
856 }
857 /* }}} */
858 
859 const pdo_driver_t pdo_sqlite_driver = {
860 	PDO_DRIVER_HEADER(sqlite),
861 	pdo_sqlite_handle_factory
862 };
863