xref: /PHP-8.3/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 
207 	if (sqlite3_exec(H->db, ZSTR_VAL(sql), NULL, NULL, NULL) != SQLITE_OK) {
208 		pdo_sqlite_error(dbh);
209 		return -1;
210 	} else {
211 		return sqlite3_changes(H->db);
212 	}
213 }
214 
pdo_sqlite_last_insert_id(pdo_dbh_t * dbh,const zend_string * name)215 static zend_string *pdo_sqlite_last_insert_id(pdo_dbh_t *dbh, const zend_string *name)
216 {
217 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
218 
219 	return zend_i64_to_str(sqlite3_last_insert_rowid(H->db));
220 }
221 
222 /* 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)223 static zend_string* sqlite_handle_quoter(pdo_dbh_t *dbh, const zend_string *unquoted, enum pdo_param_type paramtype)
224 {
225 	char *quoted;
226 	if (ZSTR_LEN(unquoted) > (INT_MAX - 3) / 2) {
227 		return NULL;
228 	}
229 	quoted = safe_emalloc(2, ZSTR_LEN(unquoted), 3);
230 	/* TODO use %Q format? */
231 	sqlite3_snprintf(2*ZSTR_LEN(unquoted) + 3, quoted, "'%q'", ZSTR_VAL(unquoted));
232 	zend_string *quoted_str = zend_string_init(quoted, strlen(quoted), 0);
233 	efree(quoted);
234 	return quoted_str;
235 }
236 
sqlite_handle_begin(pdo_dbh_t * dbh)237 static bool sqlite_handle_begin(pdo_dbh_t *dbh)
238 {
239 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
240 
241 	if (sqlite3_exec(H->db, "BEGIN", NULL, NULL, NULL) != SQLITE_OK) {
242 		pdo_sqlite_error(dbh);
243 		return false;
244 	}
245 	return true;
246 }
247 
sqlite_handle_commit(pdo_dbh_t * dbh)248 static bool sqlite_handle_commit(pdo_dbh_t *dbh)
249 {
250 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
251 
252 	if (sqlite3_exec(H->db, "COMMIT", NULL, NULL, NULL) != SQLITE_OK) {
253 		pdo_sqlite_error(dbh);
254 		return false;
255 	}
256 	return true;
257 }
258 
sqlite_handle_rollback(pdo_dbh_t * dbh)259 static bool sqlite_handle_rollback(pdo_dbh_t *dbh)
260 {
261 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
262 
263 	if (sqlite3_exec(H->db, "ROLLBACK", NULL, NULL, NULL) != SQLITE_OK) {
264 		pdo_sqlite_error(dbh);
265 		return false;
266 	}
267 	return true;
268 }
269 
pdo_sqlite_get_attribute(pdo_dbh_t * dbh,zend_long attr,zval * return_value)270 static int pdo_sqlite_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *return_value)
271 {
272 	switch (attr) {
273 		case PDO_ATTR_CLIENT_VERSION:
274 		case PDO_ATTR_SERVER_VERSION:
275 			ZVAL_STRING(return_value, (char *)sqlite3_libversion());
276 			break;
277 
278 		default:
279 			return 0;
280 	}
281 
282 	return 1;
283 }
284 
pdo_sqlite_set_attr(pdo_dbh_t * dbh,zend_long attr,zval * val)285 static bool pdo_sqlite_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val)
286 {
287 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
288 	zend_long lval;
289 
290 	switch (attr) {
291 		case PDO_ATTR_TIMEOUT:
292 			if (!pdo_get_long_param(&lval, val)) {
293 				return false;
294 			}
295 			sqlite3_busy_timeout(H->db, lval * 1000);
296 			return true;
297 		case PDO_SQLITE_ATTR_EXTENDED_RESULT_CODES:
298 			if (!pdo_get_long_param(&lval, val)) {
299 				return false;
300 			}
301 			sqlite3_extended_result_codes(H->db, lval);
302 			return true;
303 	}
304 	return false;
305 }
306 
307 typedef struct {
308 	zval val;
309 	zend_long row;
310 } aggregate_context;
311 
do_callback(struct pdo_sqlite_fci * fc,zval * cb,int argc,sqlite3_value ** argv,sqlite3_context * context,int is_agg)312 static int do_callback(struct pdo_sqlite_fci *fc, zval *cb,
313 		int argc, sqlite3_value **argv, sqlite3_context *context,
314 		int is_agg)
315 {
316 	zval *zargs = NULL;
317 	zval retval;
318 	int i;
319 	int ret;
320 	int fake_argc;
321 	aggregate_context *agg_context = NULL;
322 
323 	if (is_agg) {
324 		is_agg = 2;
325 	}
326 
327 	fake_argc = argc + is_agg;
328 
329 	fc->fci.size = sizeof(fc->fci);
330 	ZVAL_COPY_VALUE(&fc->fci.function_name, cb);
331 	fc->fci.object = NULL;
332 	fc->fci.retval = &retval;
333 	fc->fci.param_count = fake_argc;
334 
335 	/* build up the params */
336 
337 	if (fake_argc) {
338 		zargs = safe_emalloc(fake_argc, sizeof(zval), 0);
339 	}
340 
341 	if (is_agg) {
342 		agg_context = sqlite3_aggregate_context(context, sizeof(aggregate_context));
343 		if (!agg_context) {
344 			efree(zargs);
345 			return FAILURE;
346 		}
347 		if (Z_ISUNDEF(agg_context->val)) {
348 			ZVAL_NEW_REF(&agg_context->val, &EG(uninitialized_zval));
349 		}
350 		ZVAL_COPY_VALUE(&zargs[0], &agg_context->val);
351 		ZVAL_LONG(&zargs[1], ++agg_context->row);
352 	}
353 
354 	for (i = 0; i < argc; i++) {
355 		/* get the value */
356 		switch (sqlite3_value_type(argv[i])) {
357 			case SQLITE_INTEGER:
358 				ZVAL_LONG(&zargs[i + is_agg], sqlite3_value_int(argv[i]));
359 				break;
360 
361 			case SQLITE_FLOAT:
362 				ZVAL_DOUBLE(&zargs[i + is_agg], sqlite3_value_double(argv[i]));
363 				break;
364 
365 			case SQLITE_NULL:
366 				ZVAL_NULL(&zargs[i + is_agg]);
367 				break;
368 
369 			case SQLITE_BLOB:
370 			case SQLITE3_TEXT:
371 			default:
372 				ZVAL_STRINGL(&zargs[i + is_agg], (char*)sqlite3_value_text(argv[i]), sqlite3_value_bytes(argv[i]));
373 				break;
374 		}
375 	}
376 
377 	fc->fci.params = zargs;
378 
379 	if ((ret = zend_call_function(&fc->fci, &fc->fcc)) == FAILURE) {
380 		php_error_docref(NULL, E_WARNING, "An error occurred while invoking the callback");
381 	}
382 
383 	/* clean up the params */
384 	if (zargs) {
385 		for (i = is_agg; i < fake_argc; i++) {
386 			zval_ptr_dtor(&zargs[i]);
387 		}
388 		if (is_agg) {
389 			zval_ptr_dtor(&zargs[1]);
390 		}
391 		efree(zargs);
392 	}
393 
394 	if (!is_agg || !argv) {
395 		/* only set the sqlite return value if we are a scalar function,
396 		 * or if we are finalizing an aggregate */
397 		if (!Z_ISUNDEF(retval)) {
398 			switch (Z_TYPE(retval)) {
399 				case IS_LONG:
400 					sqlite3_result_int(context, Z_LVAL(retval));
401 					break;
402 
403 				case IS_NULL:
404 					sqlite3_result_null(context);
405 					break;
406 
407 				case IS_DOUBLE:
408 					sqlite3_result_double(context, Z_DVAL(retval));
409 					break;
410 
411 				default:
412 					if (!try_convert_to_string(&retval)) {
413 						ret = FAILURE;
414 						break;
415 					}
416 					sqlite3_result_text(context, Z_STRVAL(retval), Z_STRLEN(retval), SQLITE_TRANSIENT);
417 					break;
418 			}
419 		} else {
420 			sqlite3_result_error(context, "failed to invoke callback", 0);
421 		}
422 
423 		if (agg_context) {
424 			zval_ptr_dtor(&agg_context->val);
425 		}
426 	} else {
427 		/* we're stepping in an aggregate; the return value goes into
428 		 * the context */
429 		if (agg_context) {
430 			if (Z_ISUNDEF(retval)) {
431 				return FAILURE;
432 			}
433 			zval_ptr_dtor(Z_REFVAL(agg_context->val));
434 			ZVAL_COPY_VALUE(Z_REFVAL(agg_context->val), &retval);
435 			ZVAL_UNDEF(&retval);
436 		}
437 	}
438 
439 	if (!Z_ISUNDEF(retval)) {
440 		zval_ptr_dtor(&retval);
441 	}
442 
443 	return ret;
444 }
445 
php_sqlite3_func_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)446 static void php_sqlite3_func_callback(sqlite3_context *context, int argc,
447 	sqlite3_value **argv)
448 {
449 	struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
450 
451 	do_callback(&func->afunc, &func->func, argc, argv, context, 0);
452 }
453 
php_sqlite3_func_step_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)454 static void php_sqlite3_func_step_callback(sqlite3_context *context, int argc,
455 	sqlite3_value **argv)
456 {
457 	struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
458 
459 	do_callback(&func->astep, &func->step, argc, argv, context, 1);
460 }
461 
php_sqlite3_func_final_callback(sqlite3_context * context)462 static void php_sqlite3_func_final_callback(sqlite3_context *context)
463 {
464 	struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
465 
466 	do_callback(&func->afini, &func->fini, 0, NULL, context, 1);
467 }
468 
php_sqlite3_collation_callback(void * context,int string1_len,const void * string1,int string2_len,const void * string2)469 static int php_sqlite3_collation_callback(void *context,
470 	int string1_len, const void *string1,
471 	int string2_len, const void *string2)
472 {
473 	int ret;
474 	zval zargs[2];
475 	zval retval;
476 	struct pdo_sqlite_collation *collation = (struct pdo_sqlite_collation*) context;
477 
478 	collation->fc.fci.size = sizeof(collation->fc.fci);
479 	ZVAL_COPY_VALUE(&collation->fc.fci.function_name, &collation->callback);
480 	collation->fc.fci.object = NULL;
481 	collation->fc.fci.retval = &retval;
482 
483 	// Prepare the arguments.
484 	ZVAL_STRINGL(&zargs[0], (char *) string1, string1_len);
485 	ZVAL_STRINGL(&zargs[1], (char *) string2, string2_len);
486 	collation->fc.fci.param_count = 2;
487 	collation->fc.fci.params = zargs;
488 
489 	if ((ret = zend_call_function(&collation->fc.fci, &collation->fc.fcc)) == FAILURE) {
490 		php_error_docref(NULL, E_WARNING, "An error occurred while invoking the callback");
491 	} else if (!Z_ISUNDEF(retval)) {
492 		if (Z_TYPE(retval) != IS_LONG) {
493 			convert_to_long(&retval);
494 		}
495 		ret = 0;
496 		if (Z_LVAL(retval) > 0) {
497 			ret = 1;
498 		} else if (Z_LVAL(retval) < 0) {
499 			ret = -1;
500 		}
501 		zval_ptr_dtor(&retval);
502 	}
503 
504 	zval_ptr_dtor(&zargs[0]);
505 	zval_ptr_dtor(&zargs[1]);
506 
507 	return ret;
508 }
509 
510 /* {{{ bool SQLite::sqliteCreateFunction(string name, callable callback [, int argcount, int flags])
511    Registers a UDF with the sqlite db handle */
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateFunction)512 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateFunction)
513 {
514 	struct pdo_sqlite_func *func;
515 	zend_fcall_info fci;
516 	zend_fcall_info_cache fcc;
517 	char *func_name;
518 	size_t func_name_len;
519 	zend_long argc = -1;
520 	zend_long flags = 0;
521 	pdo_dbh_t *dbh;
522 	pdo_sqlite_db_handle *H;
523 	int ret;
524 
525 	ZEND_PARSE_PARAMETERS_START(2, 4)
526 		Z_PARAM_STRING(func_name, func_name_len)
527 		Z_PARAM_FUNC(fci, fcc)
528 		Z_PARAM_OPTIONAL
529 		Z_PARAM_LONG(argc)
530 		Z_PARAM_LONG(flags)
531 	ZEND_PARSE_PARAMETERS_END();
532 
533 	dbh = Z_PDO_DBH_P(ZEND_THIS);
534 	PDO_CONSTRUCT_CHECK;
535 
536 	H = (pdo_sqlite_db_handle *)dbh->driver_data;
537 
538 	func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
539 
540 	ret = sqlite3_create_function(H->db, func_name, argc, flags | SQLITE_UTF8,
541 			func, php_sqlite3_func_callback, NULL, NULL);
542 	if (ret == SQLITE_OK) {
543 		func->funcname = estrdup(func_name);
544 
545 		ZVAL_COPY(&func->func, &fci.function_name);
546 
547 		func->argc = argc;
548 
549 		func->next = H->funcs;
550 		H->funcs = func;
551 
552 		RETURN_TRUE;
553 	}
554 
555 	efree(func);
556 	RETURN_FALSE;
557 }
558 /* }}} */
559 
560 /* {{{ bool SQLite::sqliteCreateAggregate(string name, callable step, callable fini [, int argcount])
561    Registers a UDF with the sqlite db handle */
562 
563 /* The step function should have the prototype:
564    mixed step(mixed $context, int $rownumber, $value [, $value2 [, ...]])
565 
566    $context will be null for the first row; on subsequent rows it will have
567    the value that was previously returned from the step function; you should
568    use this to maintain state for the aggregate.
569 
570    The fini function should have the prototype:
571    mixed fini(mixed $context, int $rownumber)
572 
573    $context will hold the return value from the very last call to the step function.
574    rownumber will hold the number of rows over which the aggregate was performed.
575    The return value of this function will be used as the return value for this
576    aggregate UDF.
577 */
578 
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateAggregate)579 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateAggregate)
580 {
581 	struct pdo_sqlite_func *func;
582 	zend_fcall_info step_fci, fini_fci;
583 	zend_fcall_info_cache step_fcc, fini_fcc;
584 	char *func_name;
585 	size_t func_name_len;
586 	zend_long argc = -1;
587 	pdo_dbh_t *dbh;
588 	pdo_sqlite_db_handle *H;
589 	int ret;
590 
591 	ZEND_PARSE_PARAMETERS_START(3, 4)
592 		Z_PARAM_STRING(func_name, func_name_len)
593 		Z_PARAM_FUNC(step_fci, step_fcc)
594 		Z_PARAM_FUNC(fini_fci, fini_fcc)
595 		Z_PARAM_OPTIONAL
596 		Z_PARAM_LONG(argc)
597 	ZEND_PARSE_PARAMETERS_END();
598 
599 	dbh = Z_PDO_DBH_P(ZEND_THIS);
600 	PDO_CONSTRUCT_CHECK;
601 
602 	H = (pdo_sqlite_db_handle *)dbh->driver_data;
603 
604 	func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
605 
606 	ret = sqlite3_create_function(H->db, func_name, argc, SQLITE_UTF8,
607 			func, NULL, php_sqlite3_func_step_callback, php_sqlite3_func_final_callback);
608 	if (ret == SQLITE_OK) {
609 		func->funcname = estrdup(func_name);
610 
611 		ZVAL_COPY(&func->step, &step_fci.function_name);
612 
613 		ZVAL_COPY(&func->fini, &fini_fci.function_name);
614 
615 		func->argc = argc;
616 
617 		func->next = H->funcs;
618 		H->funcs = func;
619 
620 		RETURN_TRUE;
621 	}
622 
623 	efree(func);
624 	RETURN_FALSE;
625 }
626 /* }}} */
627 
628 /* {{{ bool SQLite::sqliteCreateCollation(string name, callable callback)
629    Registers a collation with the sqlite db handle */
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateCollation)630 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateCollation)
631 {
632 	struct pdo_sqlite_collation *collation;
633 	zend_fcall_info fci;
634 	zend_fcall_info_cache fcc;
635 	char *collation_name;
636 	size_t collation_name_len;
637 	pdo_dbh_t *dbh;
638 	pdo_sqlite_db_handle *H;
639 	int ret;
640 
641 	ZEND_PARSE_PARAMETERS_START(2, 2)
642 		Z_PARAM_STRING(collation_name, collation_name_len)
643 		Z_PARAM_FUNC(fci, fcc)
644 	ZEND_PARSE_PARAMETERS_END();
645 
646 	dbh = Z_PDO_DBH_P(ZEND_THIS);
647 	PDO_CONSTRUCT_CHECK;
648 
649 	H = (pdo_sqlite_db_handle *)dbh->driver_data;
650 
651 	collation = (struct pdo_sqlite_collation*)ecalloc(1, sizeof(*collation));
652 
653 	ret = sqlite3_create_collation(H->db, collation_name, SQLITE_UTF8, collation, php_sqlite3_collation_callback);
654 	if (ret == SQLITE_OK) {
655 		collation->name = estrdup(collation_name);
656 
657 		ZVAL_COPY(&collation->callback, &fci.function_name);
658 
659 		collation->next = H->collations;
660 		H->collations = collation;
661 
662 		RETURN_TRUE;
663 	}
664 
665 	efree(collation);
666 	RETURN_FALSE;
667 }
668 /* }}} */
669 
get_driver_methods(pdo_dbh_t * dbh,int kind)670 static const zend_function_entry *get_driver_methods(pdo_dbh_t *dbh, int kind)
671 {
672 	switch (kind) {
673 		case PDO_DBH_DRIVER_METHOD_KIND_DBH:
674 			return class_PDO_SQLite_Ext_methods;
675 
676 		default:
677 			return NULL;
678 	}
679 }
680 
pdo_sqlite_request_shutdown(pdo_dbh_t * dbh)681 static void pdo_sqlite_request_shutdown(pdo_dbh_t *dbh)
682 {
683 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
684 	/* unregister functions, so that they don't linger for the next
685 	 * request */
686 	if (H) {
687 		pdo_sqlite_cleanup_callbacks(H);
688 	}
689 }
690 
pdo_sqlite_get_gc(pdo_dbh_t * dbh,zend_get_gc_buffer * gc_buffer)691 static void pdo_sqlite_get_gc(pdo_dbh_t *dbh, zend_get_gc_buffer *gc_buffer)
692 {
693 	pdo_sqlite_db_handle *H = dbh->driver_data;
694 
695 	struct pdo_sqlite_func *func = H->funcs;
696 	while (func) {
697 		zend_get_gc_buffer_add_zval(gc_buffer, &func->func);
698 		zend_get_gc_buffer_add_zval(gc_buffer, &func->step);
699 		zend_get_gc_buffer_add_zval(gc_buffer, &func->fini);
700 		func = func->next;
701 	}
702 
703 	struct pdo_sqlite_collation *collation = H->collations;
704 	while (collation) {
705 		zend_get_gc_buffer_add_zval(gc_buffer, &collation->callback);
706 		collation = collation->next;
707 	}
708 }
709 
710 static const struct pdo_dbh_methods sqlite_methods = {
711 	sqlite_handle_closer,
712 	sqlite_handle_preparer,
713 	sqlite_handle_doer,
714 	sqlite_handle_quoter,
715 	sqlite_handle_begin,
716 	sqlite_handle_commit,
717 	sqlite_handle_rollback,
718 	pdo_sqlite_set_attr,
719 	pdo_sqlite_last_insert_id,
720 	pdo_sqlite_fetch_error_func,
721 	pdo_sqlite_get_attribute,
722 	NULL,	/* check_liveness: not needed */
723 	get_driver_methods,
724 	pdo_sqlite_request_shutdown,
725 	NULL, /* in transaction, use PDO's internal tracking mechanism */
726 	pdo_sqlite_get_gc
727 };
728 
make_filename_safe(const char * filename)729 static char *make_filename_safe(const char *filename)
730 {
731 	if (!filename) {
732 		return NULL;
733 	}
734 	if (*filename && strncasecmp(filename, "file:", 5) == 0) {
735 		if (PG(open_basedir) && *PG(open_basedir)) {
736 			return NULL;
737 		}
738 		return estrdup(filename);
739 	}
740 	if (*filename && strcmp(filename, ":memory:")) {
741 		char *fullpath = expand_filepath(filename, NULL);
742 
743 		if (!fullpath) {
744 			return NULL;
745 		}
746 
747 		if (php_check_open_basedir(fullpath)) {
748 			efree(fullpath);
749 			return NULL;
750 		}
751 		return fullpath;
752 	}
753 	return estrdup(filename);
754 }
755 
authorizer(void * autharg,int access_type,const char * arg3,const char * arg4,const char * arg5,const char * arg6)756 static int authorizer(void *autharg, int access_type, const char *arg3, const char *arg4,
757 		const char *arg5, const char *arg6)
758 {
759 	char *filename;
760 	switch (access_type) {
761 		case SQLITE_ATTACH: {
762 			filename = make_filename_safe(arg3);
763 			if (!filename) {
764 				return SQLITE_DENY;
765 			}
766 			efree(filename);
767 			return SQLITE_OK;
768 		}
769 
770 		default:
771 			/* access allowed */
772 			return SQLITE_OK;
773 	}
774 }
775 
pdo_sqlite_handle_factory(pdo_dbh_t * dbh,zval * driver_options)776 static int pdo_sqlite_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ */
777 {
778 	pdo_sqlite_db_handle *H;
779 	int i, ret = 0;
780 	zend_long timeout = 60, flags;
781 	char *filename;
782 
783 	H = pecalloc(1, sizeof(pdo_sqlite_db_handle), dbh->is_persistent);
784 
785 	H->einfo.errcode = 0;
786 	H->einfo.errmsg = NULL;
787 	dbh->driver_data = H;
788 
789 	/* skip all but this one param event */
790 	dbh->skip_param_evt = 0x7F ^ (1 << PDO_PARAM_EVT_EXEC_PRE);
791 
792 	filename = make_filename_safe(dbh->data_source);
793 
794 	if (!filename) {
795 		zend_throw_exception_ex(php_pdo_get_exception(), 0,
796 			"open_basedir prohibits opening %s",
797 			dbh->data_source);
798 		goto cleanup;
799 	}
800 
801 	flags = pdo_attr_lval(driver_options, PDO_SQLITE_ATTR_OPEN_FLAGS, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
802 
803 	if (!(PG(open_basedir) && *PG(open_basedir))) {
804 		flags |= SQLITE_OPEN_URI;
805 	}
806 	i = sqlite3_open_v2(filename, &H->db, flags, NULL);
807 
808 	efree(filename);
809 
810 	if (i != SQLITE_OK) {
811 		pdo_sqlite_error(dbh);
812 		goto cleanup;
813 	}
814 
815 	if (PG(open_basedir) && *PG(open_basedir)) {
816 		sqlite3_set_authorizer(H->db, authorizer, NULL);
817 	}
818 
819 	if (driver_options) {
820 		timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, timeout);
821 	}
822 	sqlite3_busy_timeout(H->db, timeout * 1000);
823 
824 	dbh->alloc_own_columns = 1;
825 	dbh->max_escaped_char_length = 2;
826 
827 	ret = 1;
828 
829 cleanup:
830 	dbh->methods = &sqlite_methods;
831 
832 	return ret;
833 }
834 /* }}} */
835 
836 const pdo_driver_t pdo_sqlite_driver = {
837 	PDO_DRIVER_HEADER(sqlite),
838 	pdo_sqlite_handle_factory
839 };
840