diff --git a/ext/dba/dba.c b/ext/dba/dba.c index 86b99ad4bb6f0..107541bd2efa3 100644 --- a/ext/dba/dba.c +++ b/ext/dba/dba.c @@ -262,9 +262,10 @@ static void dba_close(dba_info *info) if (info->hnd) { info->hnd->close(info); } - if (info->path) { - pefree(info->path, info->flags&DBA_PERSISTENT); - } + ZEND_ASSERT(info->path); + zend_string_release_ex(info->path, info->flags&DBA_PERSISTENT); + info->path = NULL; + if (info->fp && info->fp != info->lock.fp) { if (info->flags & DBA_PERSISTENT) { php_stream_pclose(info->fp); @@ -431,7 +432,7 @@ static void php_dba_update(INTERNAL_FUNCTION_PARAMETERS, int mode) /* }}} */ /* {{{ php_find_dbm */ -static dba_info *php_dba_find(const char* path) +static dba_info *php_dba_find(const zend_string *path) { zend_resource *le; dba_info *info; @@ -444,7 +445,7 @@ static dba_info *php_dba_find(const char* path) } if (le->type == le_db || le->type == le_pdb) { info = (dba_info *)(le->ptr); - if (!strcmp(info->path, path)) { + if (zend_string_equals(path, info->path)) { return (dba_info *)(le->ptr); } } @@ -454,6 +455,20 @@ static dba_info *php_dba_find(const char* path) } /* }}} */ +static zend_always_inline zend_string *php_dba_zend_string_dup_safe(zend_string *s, bool persistent) +{ + if (ZSTR_IS_INTERNED(s) && !persistent) { + return s; + } else { + zend_string *duplicated_str = zend_string_init(ZSTR_VAL(s), ZSTR_LEN(s), persistent); + if (persistent) { + GC_MAKE_PERSISTENT_LOCAL(duplicated_str); + } + return duplicated_str; + } +} + + #define FREE_PERSISTENT_RESOURCE_KEY() if (persistent_resource_key) {zend_string_release_ex(persistent_resource_key, false);} /* {{{ php_dba_open */ @@ -467,7 +482,6 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent) const char *file_mode; const char *lock_file_mode = NULL; int persistent_flag = persistent ? STREAM_OPEN_PERSISTENT : 0; - zend_string *opened_path = NULL; char *lock_name; #ifdef PHP_WIN32 bool restarted = 0; @@ -724,7 +738,7 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent) info = pemalloc(sizeof(dba_info), persistent); memset(info, 0, sizeof(dba_info)); - info->path = pestrdup(ZSTR_VAL(path), persistent); + info->path = php_dba_zend_string_dup_safe(path, persistent); info->mode = modenr; info->file_permission = permission; info->map_size = map_size; @@ -753,8 +767,9 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent) if (is_db_lock) { lock_name = ZSTR_VAL(path); } else { - spprintf(&lock_name, 0, "%s.lck", info->path); + spprintf(&lock_name, 0, "%s.lck", ZSTR_VAL(info->path)); if (!strcmp(file_mode, "r")) { + zend_string *opened_path = NULL; /* when in read only mode try to use existing .lck file first */ /* do not log errors for .lck file while in read only mode on .lck file */ lock_file_mode = "rb"; @@ -769,13 +784,17 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent) } } if (!info->lock.fp) { + zend_string *opened_path = NULL; info->lock.fp = php_stream_open_wrapper(lock_name, lock_file_mode, STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|persistent_flag, &opened_path); if (info->lock.fp) { if (is_db_lock) { + ZEND_ASSERT(opened_path); /* replace the path info with the real path of the opened file */ - pefree(info->path, persistent); - info->path = pestrndup(ZSTR_VAL(opened_path), ZSTR_LEN(opened_path), persistent); + zend_string_release(info->path); + info->path = php_dba_zend_string_dup_safe(opened_path, persistent); } + } + if (opened_path) { zend_string_release_ex(opened_path, 0); } } @@ -801,7 +820,7 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent) if (info->lock.fp && is_db_lock) { info->fp = info->lock.fp; /* use the same stream for locking and database access */ } else { - info->fp = php_stream_open_wrapper(info->path, file_mode, STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|persistent_flag, NULL); + info->fp = php_stream_open_wrapper(ZSTR_VAL(info->path), file_mode, STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|persistent_flag, NULL); } if (!info->fp) { dba_close(info); @@ -1207,7 +1226,7 @@ PHP_FUNCTION(dba_list) } if (le->type == le_db || le->type == le_pdb) { info = (dba_info *)(le->ptr); - add_index_string(return_value, i, info->path); + add_index_str(return_value, i, zend_string_copy(info->path)); } } } diff --git a/ext/dba/dba_cdb.c b/ext/dba/dba_cdb.c index 5af9121b565a6..d5af1b8cce249 100644 --- a/ext/dba/dba_cdb.c +++ b/ext/dba/dba_cdb.c @@ -73,7 +73,7 @@ DBA_OPEN_FUNC(cdb) make = 0; file = info->fp; #else - file = VCWD_OPEN(info->path, O_RDONLY); + file = VCWD_OPEN(ZSTR_VAL(info->path), O_RDONLY); if (file < 0) { *error = "Unable to open file"; return FAILURE; diff --git a/ext/dba/dba_db1.c b/ext/dba/dba_db1.c index 3a95cea460c14..57dfab38f13b7 100644 --- a/ext/dba/dba_db1.c +++ b/ext/dba/dba_db1.c @@ -61,7 +61,7 @@ DBA_OPEN_FUNC(db1) return FAILURE; /* not possible */ } - db = dbopen((char *)info->path, gmode, filemode, DB_HASH, NULL); + db = dbopen((char *)ZSTR_VAL(info->path), gmode, filemode, DB_HASH, NULL); if (db == NULL) { return FAILURE; diff --git a/ext/dba/dba_db2.c b/ext/dba/dba_db2.c index 8f6d47a9239c9..86306bd59a2b8 100644 --- a/ext/dba/dba_db2.c +++ b/ext/dba/dba_db2.c @@ -41,7 +41,7 @@ DBA_OPEN_FUNC(db2) int gmode = 0; int filemode = info->file_permission; struct stat check_stat; - int s = VCWD_STAT(info->path, &check_stat); + int s = VCWD_STAT(ZSTR_VAL(info->path), &check_stat); if (!s && !check_stat.st_size) { info->mode = DBA_TRUNC; /* force truncate */ @@ -61,7 +61,7 @@ DBA_OPEN_FUNC(db2) return FAILURE;/* not possible */ } - if (db_open(info->path, type, gmode, filemode, NULL, NULL, &dbp)) { + if (db_open(ZSTR_VAL(info->path), type, gmode, filemode, NULL, NULL, &dbp)) { return FAILURE; } diff --git a/ext/dba/dba_db3.c b/ext/dba/dba_db3.c index d9e948a623f50..5d36d86e00808 100644 --- a/ext/dba/dba_db3.c +++ b/ext/dba/dba_db3.c @@ -53,7 +53,7 @@ DBA_OPEN_FUNC(db3) int gmode = 0, err; int filemode = info->file_permission; struct stat check_stat; - int s = VCWD_STAT(info->path, &check_stat); + int s = VCWD_STAT(ZSTR_VAL(info->path), &check_stat); if (!s && !check_stat.st_size) { info->mode = DBA_TRUNC; /* force truncate */ @@ -81,9 +81,9 @@ DBA_OPEN_FUNC(db3) dbp->set_errcall(dbp, php_dba_db3_errcall_fcn); if( #if (DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)) - (err=dbp->open(dbp, 0, info->path, NULL, type, gmode, filemode)) == 0) { + (err=dbp->open(dbp, 0, ZSTR_VAL(info->path), NULL, type, gmode, filemode)) == 0) { #else - (err=dbp->open(dbp, info->path, NULL, type, gmode, filemode)) == 0) { + (err=dbp->open(dbp, ZSTR_VAL(info->path), NULL, type, gmode, filemode)) == 0) { #endif dba_db3_data *data; diff --git a/ext/dba/dba_db4.c b/ext/dba/dba_db4.c index 3de66a4274432..a2dbd5dafa1e2 100644 --- a/ext/dba/dba_db4.c +++ b/ext/dba/dba_db4.c @@ -67,7 +67,7 @@ DBA_OPEN_FUNC(db4) int gmode = 0, err; int filemode = info->file_permission; struct stat check_stat; - int s = VCWD_STAT(info->path, &check_stat); + int s = VCWD_STAT(ZSTR_VAL(info->path), &check_stat); #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR <= 7) /* Bug 51086 */ if (!s && !check_stat.st_size) { @@ -110,9 +110,9 @@ DBA_OPEN_FUNC(db4) dbp->set_errcall(dbp, php_dba_db4_errcall_fcn); if ( #if (DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)) - (err=dbp->open(dbp, 0, info->path, NULL, type, gmode, filemode)) == 0) { + (err=dbp->open(dbp, 0, ZSTR_VAL(info->path), NULL, type, gmode, filemode)) == 0) { #else - (err=dbp->open(dbp, info->path, NULL, type, gmode, filemode)) == 0) { + (err=dbp->open(dbp, ZSTR_VAL(info->path), NULL, type, gmode, filemode)) == 0) { #endif dba_db4_data *data; diff --git a/ext/dba/dba_dbm.c b/ext/dba/dba_dbm.c index afa645cb2fe70..88a8959082709 100644 --- a/ext/dba/dba_dbm.c +++ b/ext/dba/dba_dbm.c @@ -36,7 +36,7 @@ #include <fcntl.h> #define TRUNC_IT(extension, mode) \ - snprintf(buf, MAXPATHLEN, "%s" extension, info->path); \ + snprintf(buf, MAXPATHLEN, "%s" extension, ZSTR_VAL(info->path)); \ buf[MAXPATHLEN-1] = '\0'; \ if((fd = VCWD_OPEN_MODE(buf, O_CREAT | mode | O_WRONLY, filemode)) == -1) \ return FAILURE; \ @@ -67,7 +67,7 @@ DBA_OPEN_FUNC(dbm) TRUNC_IT(".dir", 0); } - if(dbminit((char *) info->path) == -1) { + if(dbminit((char *) ZSTR_VAL(info->path)) == -1) { return FAILURE; } diff --git a/ext/dba/dba_gdbm.c b/ext/dba/dba_gdbm.c index c3fbb5bf21e18..0781e1fb1a76f 100644 --- a/ext/dba/dba_gdbm.c +++ b/ext/dba/dba_gdbm.c @@ -46,7 +46,7 @@ DBA_OPEN_FUNC(gdbm) if(gmode == -1) return FAILURE; /* not possible */ - dbf = gdbm_open(info->path, /* int block_size */ 0, gmode, filemode, NULL); + dbf = gdbm_open(ZSTR_VAL(info->path), /* int block_size */ 0, gmode, filemode, NULL); if(dbf) { info->dbf = pemalloc(sizeof(dba_gdbm_data), info->flags&DBA_PERSISTENT); diff --git a/ext/dba/dba_lmdb.c b/ext/dba/dba_lmdb.c index 1645453324525..f147f4c810dee 100644 --- a/ext/dba/dba_lmdb.c +++ b/ext/dba/dba_lmdb.c @@ -81,7 +81,7 @@ DBA_OPEN_FUNC(lmdb) } } - rc = mdb_env_open(env, info->path, flags, mode); + rc = mdb_env_open(env, ZSTR_VAL(info->path), flags, mode); if (rc) { /* If this function [mdb_env_open()] fails, mdb_env_close() must be called to discard the MDB_env handle. * http://www.lmdb.tech/doc/group__mdb.html#ga32a193c6bf4d7d5c5d579e71f22e9340 */ diff --git a/ext/dba/dba_ndbm.c b/ext/dba/dba_ndbm.c index d872add48e6ab..758fcd1e77172 100644 --- a/ext/dba/dba_ndbm.c +++ b/ext/dba/dba_ndbm.c @@ -52,7 +52,7 @@ DBA_OPEN_FUNC(ndbm) return FAILURE; /* not possible */ } - dbf = dbm_open(info->path, gmode, filemode); + dbf = dbm_open(ZSTR_VAL(info->path), gmode, filemode); pinfo->dbf = dbf; return SUCCESS; diff --git a/ext/dba/dba_qdbm.c b/ext/dba/dba_qdbm.c index d06af20659909..d70885754bedd 100644 --- a/ext/dba/dba_qdbm.c +++ b/ext/dba/dba_qdbm.c @@ -37,16 +37,16 @@ DBA_OPEN_FUNC(qdbm) switch(info->mode) { case DBA_READER: - dbf = dpopen(info->path, DP_OREADER, 0); + dbf = dpopen(ZSTR_VAL(info->path), DP_OREADER, 0); break; case DBA_WRITER: - dbf = dpopen(info->path, DP_OWRITER, 0); + dbf = dpopen(ZSTR_VAL(info->path), DP_OWRITER, 0); break; case DBA_CREAT: - dbf = dpopen(info->path, DP_OWRITER | DP_OCREAT, 0); + dbf = dpopen(ZSTR_VAL(info->path), DP_OWRITER | DP_OCREAT, 0); break; case DBA_TRUNC: - dbf = dpopen(info->path, DP_OWRITER | DP_OCREAT | DP_OTRUNC, 0); + dbf = dpopen(ZSTR_VAL(info->path), DP_OWRITER | DP_OCREAT | DP_OTRUNC, 0); break; default: return FAILURE; diff --git a/ext/dba/dba_tcadb.c b/ext/dba/dba_tcadb.c index 23c9e2d1d363d..b085558a71133 100644 --- a/ext/dba/dba_tcadb.c +++ b/ext/dba/dba_tcadb.c @@ -39,16 +39,16 @@ DBA_OPEN_FUNC(tcadb) if (tcadb) { switch(info->mode) { case DBA_READER: - spprintf(&path_string, 0, "%s#mode=r", info->path); + spprintf(&path_string, 0, "%s#mode=r", ZSTR_VAL(info->path)); break; case DBA_WRITER: - spprintf(&path_string, 0, "%s#mode=w", info->path); + spprintf(&path_string, 0, "%s#mode=w", ZSTR_VAL(info->path)); break; case DBA_CREAT: - spprintf(&path_string, 0, "%s#mode=wc", info->path); + spprintf(&path_string, 0, "%s#mode=wc", ZSTR_VAL(info->path)); break; case DBA_TRUNC: - spprintf(&path_string, 0, "%s#mode=wct", info->path); + spprintf(&path_string, 0, "%s#mode=wct", ZSTR_VAL(info->path)); break; default: tcadbdel(tcadb); diff --git a/ext/dba/php_dba.h b/ext/dba/php_dba.h index d6a86f76b271d..30742661c3bba 100644 --- a/ext/dba/php_dba.h +++ b/ext/dba/php_dba.h @@ -38,7 +38,7 @@ typedef struct dba_lock { typedef struct dba_info { /* public */ void *dbf; /* ptr to private data or whatever */ - char *path; + zend_string *path; dba_mode_t mode; php_stream *fp; /* this is the database stream for builtin handlers */ int fd;