Skip to content

Commit 1f1aa34

Browse files
authored
Merge branch 'master' into phar-5
2 parents 9e6857c + 8b34389 commit 1f1aa34

File tree

9 files changed

+202
-153
lines changed

9 files changed

+202
-153
lines changed

ext/pdo_pgsql/pgsql_statement.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,12 @@ static int pgsql_stmt_fetch(pdo_stmt_t *stmt,
571571
}
572572

573573
S->result = PQgetResult(S->H->server);
574+
if (!S->result) {
575+
S->is_running_unbuffered = false;
576+
stmt->row_count = 0;
577+
S->current_row = 0;
578+
return 0;
579+
}
574580
status = PQresultStatus(S->result);
575581

576582
if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK && status != PGRES_SINGLE_TUPLE) {

ext/pdo_pgsql/tests/gh21683.phpt

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
--TEST--
2+
PDO PgSQL single-row mode (ATTR_PREFETCH=0) on empty result set
3+
--EXTENSIONS--
4+
pdo
5+
pdo_pgsql
6+
--SKIPIF--
7+
<?php
8+
require __DIR__ . '/config.inc';
9+
require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc';
10+
PDOTest::skip();
11+
?>
12+
--FILE--
13+
<?php
14+
15+
require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc';
16+
$pdo = PDOTest::test_factory(__DIR__ . '/common.phpt');
17+
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
18+
$pdo->setAttribute(PDO::ATTR_PREFETCH, 0);
19+
20+
$pdo->exec("CREATE TEMP TABLE empty_t (id int, val text)");
21+
22+
echo "=== query / fetch ===\n";
23+
$stmt = $pdo->query("SELECT * FROM empty_t");
24+
var_dump($stmt->fetch());
25+
26+
echo "=== prepare / fetchAll ===\n";
27+
$stmt = $pdo->prepare("SELECT * FROM empty_t");
28+
$stmt->execute();
29+
var_dump($stmt->fetchAll());
30+
31+
echo "=== connection still works ===\n";
32+
$stmt = $pdo->query("SELECT 1 AS alive");
33+
var_dump($stmt->fetch(PDO::FETCH_ASSOC));
34+
35+
echo "Done\n";
36+
?>
37+
--EXPECT--
38+
=== query / fetch ===
39+
bool(false)
40+
=== prepare / fetchAll ===
41+
array(0) {
42+
}
43+
=== connection still works ===
44+
array(1) {
45+
["alive"]=>
46+
string(1) "1"
47+
}
48+
Done

ext/phar/dirstream.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -345,21 +345,21 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mo
345345
{
346346
phar_entry_info entry, *e;
347347
phar_archive_data *phar = NULL;
348-
char *error, *arch;
349-
size_t arch_len;
348+
char *error;
350349
php_url *resource = NULL;
351350

352351
/* pre-readonly check, we need to know if this is a data phar */
353-
if (FAILURE == phar_split_fname(url_from, strlen(url_from), &arch, &arch_len, NULL, 2, 2)) {
352+
zend_string *arch = phar_split_fname(url_from, strlen(url_from), NULL, 2, 2);
353+
if (!arch) {
354354
php_stream_wrapper_log_error(wrapper, options, "phar error: cannot create directory \"%s\", no phar archive specified", url_from);
355355
return 0;
356356
}
357357

358-
if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, NULL)) {
358+
if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, 0, NULL)) {
359359
phar = NULL;
360360
}
361361

362-
efree(arch);
362+
zend_string_release_ex(arch, false);
363363

364364
if (PHAR_G(readonly) && (!phar || !phar->is_data)) {
365365
php_stream_wrapper_log_error(wrapper, options, "phar error: cannot create directory \"%s\", write operations disabled", url_from);
@@ -471,21 +471,21 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options
471471
{
472472
phar_entry_info *entry;
473473
phar_archive_data *phar = NULL;
474-
char *error, *arch;
475-
size_t arch_len;
474+
char *error;
476475
php_url *resource = NULL;
477476

478477
/* pre-readonly check, we need to know if this is a data phar */
479-
if (FAILURE == phar_split_fname(url, strlen(url), &arch, &arch_len, NULL, 2, 2)) {
478+
zend_string *arch = phar_split_fname(url, strlen(url), NULL, 2, 2);
479+
if (!arch) {
480480
php_stream_wrapper_log_error(wrapper, options, "phar error: cannot remove directory \"%s\", no phar archive specified, or phar archive does not exist", url);
481481
return 0;
482482
}
483483

484-
if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, NULL)) {
484+
if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, 0, NULL)) {
485485
phar = NULL;
486486
}
487487

488-
efree(arch);
488+
zend_string_release_ex(arch, false);
489489

490490
if (PHAR_G(readonly) && (!phar || !phar->is_data)) {
491491
php_stream_wrapper_log_error(wrapper, options, "phar error: cannot rmdir directory \"%s\", write operations disabled", url);

ext/phar/func_interceptors.c

Lines changed: 30 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ PHP_FUNCTION(phar_opendir) /* {{{ */
3838
}
3939

4040
if (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://")) {
41-
char *arch;
42-
size_t arch_len;
4341
zend_string *fname = zend_get_executed_filename_ex();
4442

4543
/* we are checking for existence of a file within the relative path. Chances are good that this is
@@ -48,7 +46,8 @@ PHP_FUNCTION(phar_opendir) /* {{{ */
4846
goto skip_phar;
4947
}
5048

51-
if (SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, 2, 0)) {
49+
zend_string *arch = phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), NULL, 2, 0);
50+
if (arch) {
5251
php_stream_context *context = NULL;
5352
php_stream *stream;
5453
char *name;
@@ -58,12 +57,12 @@ PHP_FUNCTION(phar_opendir) /* {{{ */
5857
zend_string *entry = phar_fix_filepath(filename, filename_len, true);
5958

6059
if (ZSTR_VAL(entry)[0] == '/') {
61-
spprintf(&name, 4096, "phar://%s%s", arch, ZSTR_VAL(entry));
60+
spprintf(&name, 4096, "phar://%s%s", ZSTR_VAL(arch), ZSTR_VAL(entry));
6261
} else {
63-
spprintf(&name, 4096, "phar://%s/%s", arch, ZSTR_VAL(entry));
62+
spprintf(&name, 4096, "phar://%s/%s", ZSTR_VAL(arch), ZSTR_VAL(entry));
6463
}
6564
zend_string_release_ex(entry, false);
66-
efree(arch);
65+
zend_string_release_ex(arch, false);
6766
if (zcontext) {
6867
context = php_stream_context_from_zval(zcontext, 0);
6968
}
@@ -84,8 +83,6 @@ PHP_FUNCTION(phar_opendir) /* {{{ */
8483

8584
static zend_string* phar_get_name_for_relative_paths(zend_string *filename, bool using_include_path)
8685
{
87-
char *arch;
88-
size_t arch_len;
8986
zend_string *fname = zend_get_executed_filename_ex();
9087

9188
/* we are checking for existence of a file within the relative path. Chances are good that this is
@@ -94,23 +91,24 @@ static zend_string* phar_get_name_for_relative_paths(zend_string *filename, bool
9491
return NULL;
9592
}
9693

97-
if (FAILURE == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, 2, 0)) {
94+
zend_string *arch = phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), NULL, 2, 0);
95+
if (!arch) {
9896
return NULL;
9997
}
10098

10199
/* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
102100
/* retrieving a file defaults to within the current directory, so use this if possible */
103101
phar_archive_data *phar;
104-
if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, NULL)) {
105-
efree(arch);
102+
if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, 0, NULL)) {
103+
zend_string_release_ex(arch, false);
106104
return NULL;
107105
}
108106

109107
zend_string *name = NULL;
110108
if (using_include_path) {
111109
if (!(name = phar_find_in_include_path(filename, NULL))) {
112110
/* this file is not in the phar, use the original path */
113-
efree(arch);
111+
zend_string_release_ex(arch, false);
114112
return NULL;
115113
}
116114
} else {
@@ -124,24 +122,24 @@ static zend_string* phar_get_name_for_relative_paths(zend_string *filename, bool
124122
/* this file is not in the phar, use the original path */
125123
if (!is_in_phar) {
126124
zend_string_release_ex(entry, false);
127-
efree(arch);
125+
zend_string_release_ex(arch, false);
128126
return NULL;
129127
}
130128
/* auto-convert to phar:// */
131129
if (ZSTR_VAL(entry)[0] == '/') {
132-
ZEND_ASSERT(strlen("phar://") + arch_len + ZSTR_LEN(entry) < 4096);
130+
ZEND_ASSERT(strlen("phar://") + ZSTR_LEN(arch) + ZSTR_LEN(entry) < 4096);
133131
name = zend_string_concat3(
134132
"phar://", strlen("phar://"),
135-
arch, arch_len,
133+
ZSTR_VAL(arch), ZSTR_LEN(arch),
136134
ZSTR_VAL(entry), ZSTR_LEN(entry)
137135
);
138136
} else {
139-
name = strpprintf(4096, "phar://%s/%s", arch, ZSTR_VAL(entry));
137+
name = strpprintf(4096, "phar://%s/%s", ZSTR_VAL(arch), ZSTR_VAL(entry));
140138
}
141139
zend_string_release_ex(entry, false);
142140
}
143141

144-
efree(arch);
142+
zend_string_release_ex(arch, false);
145143
return name;
146144
}
147145

@@ -492,12 +490,12 @@ static void phar_file_stat(const char *filename, size_t filename_length, int typ
492490
phar = PHAR_G(last_phar);
493491
goto splitted;
494492
}
495-
char *arch;
496-
size_t arch_len;
497-
if (SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, 2, 0)) {
493+
494+
zend_string *arch = phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), NULL, 2, 0);
495+
if (arch) {
498496
/* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
499-
zend_result has_archive = phar_get_archive(&phar, arch, arch_len, NULL, NULL);
500-
efree(arch);
497+
zend_result has_archive = phar_get_archive(&phar, ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, 0, NULL);
498+
zend_string_release_ex(arch, false);
501499
if (FAILURE == has_archive) {
502500
goto skip_phar;
503501
}
@@ -721,8 +719,6 @@ PHP_FUNCTION(phar_is_file) /* {{{ */
721719
goto skip_phar;
722720
}
723721
if (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://")) {
724-
char *arch;
725-
size_t arch_len;
726722
zend_string *fname = zend_get_executed_filename_ex();
727723

728724
/* we are checking for existence of a file within the relative path. Chances are good that this is
@@ -731,12 +727,15 @@ PHP_FUNCTION(phar_is_file) /* {{{ */
731727
goto skip_phar;
732728
}
733729

734-
if (SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, 2, 0)) {
730+
zend_string *arch = phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), NULL, 2, 0);
731+
if (arch) {
735732
phar_archive_data *phar;
736733

737734
/* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
738735
/* retrieving a file within the current directory, so use this if possible */
739-
if (SUCCESS == phar_get_archive(&phar, arch, arch_len, NULL, NULL)) {
736+
zend_result has_archive = phar_get_archive(&phar, ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, 0, NULL);
737+
zend_string_release_ex(arch, false);
738+
if (has_archive == SUCCESS) {
740739
phar_entry_info *etemp;
741740

742741
zend_string *entry = phar_fix_filepath(filename, filename_len, true);
@@ -747,12 +746,10 @@ PHP_FUNCTION(phar_is_file) /* {{{ */
747746
}
748747
zend_string_release_ex(entry, false);
749748
if (etemp) {
750-
efree(arch);
751749
RETURN_BOOL(!etemp->is_dir);
752750
}
753751
/* this file is not in the current directory, use the original path */
754752
}
755-
efree(arch);
756753
RETURN_FALSE;
757754
}
758755
}
@@ -779,8 +776,6 @@ PHP_FUNCTION(phar_is_link) /* {{{ */
779776
goto skip_phar;
780777
}
781778
if (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://")) {
782-
char *arch;
783-
size_t arch_len;
784779
zend_string *fname = zend_get_executed_filename_ex();
785780

786781
/* we are checking for existence of a file within the relative path. Chances are good that this is
@@ -789,12 +784,15 @@ PHP_FUNCTION(phar_is_link) /* {{{ */
789784
goto skip_phar;
790785
}
791786

792-
if (SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, 2, 0)) {
787+
zend_string *arch = phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), NULL, 2, 0);
788+
if (arch) {
793789
phar_archive_data *phar;
794790

795791
/* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
796792
/* retrieving a file within the current directory, so use this if possible */
797-
if (SUCCESS == phar_get_archive(&phar, arch, arch_len, NULL, NULL)) {
793+
zend_result has_archive = phar_get_archive(&phar, ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, 0, NULL);
794+
zend_string_release_ex(arch, false);
795+
if (has_archive == SUCCESS) {
798796
phar_entry_info *etemp;
799797

800798
zend_string *entry = phar_fix_filepath(filename, filename_len, true);
@@ -805,11 +803,9 @@ PHP_FUNCTION(phar_is_link) /* {{{ */
805803
}
806804
zend_string_release_ex(entry, false);
807805
if (etemp) {
808-
efree(arch);
809806
RETURN_BOOL(etemp->link);
810807
}
811808
}
812-
efree(arch);
813809
RETURN_FALSE;
814810
}
815811
}

ext/phar/phar.c

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2171,16 +2171,19 @@ zend_string* phar_fix_filepath(const char *path, size_t path_length, bool use_cw
21712171
*
21722172
* This is used by phar_parse_url()
21732173
*/
2174-
zend_result phar_split_fname(const char *filename, size_t filename_len, char **arch, size_t *arch_len, zend_string **entry, int executable, int for_create) /* {{{ */
2174+
zend_string* phar_split_fname_ex(const char *filename, size_t filename_len, zend_string **entry, int executable, int for_create, const char **error) /* {{{ */
21752175
{
21762176
const char *ext_str;
21772177
#ifdef PHP_WIN32
21782178
char *save;
21792179
#endif
21802180
size_t ext_len;
21812181

2182+
if (error) {
2183+
*error = NULL;
2184+
}
21822185
if (zend_char_has_nul_byte(filename, filename_len)) {
2183-
return FAILURE;
2186+
return NULL;
21842187
}
21852188

21862189
if (!strncasecmp(filename, "phar://", 7)) {
@@ -2198,12 +2201,12 @@ zend_result phar_split_fname(const char *filename, size_t filename_len, char **a
21982201
#endif
21992202
if (phar_detect_phar_fname_ext(filename, filename_len, &ext_str, &ext_len, executable, for_create, false) == FAILURE) {
22002203
if (ext_len != -1) {
2201-
if (!ext_str) {
2204+
if (!ext_str && error) {
22022205
/* no / detected, restore arch for error message */
22032206
#ifdef PHP_WIN32
2204-
*arch = save;
2207+
*error = save;
22052208
#else
2206-
*arch = (char*)filename;
2209+
*error = filename;
22072210
#endif
22082211
}
22092212

@@ -2212,19 +2215,19 @@ zend_result phar_split_fname(const char *filename, size_t filename_len, char **a
22122215
efree((char *)filename);
22132216
}
22142217
#endif
2215-
return FAILURE;
2218+
return NULL;
22162219
}
22172220

22182221
ext_len = 0;
22192222
/* no extension detected - instead we are dealing with an alias */
22202223
}
22212224

2222-
*arch_len = ext_str - filename + ext_len;
2223-
*arch = estrndup(filename, *arch_len);
2225+
size_t arch_len = ext_str - filename + ext_len;
2226+
zend_string *arch = zend_string_init(filename, arch_len, false);
22242227

22252228
if (entry) {
22262229
if (ext_str[ext_len]) {
2227-
size_t computed_entry_len = filename_len - *arch_len;
2230+
size_t computed_entry_len = filename_len - arch_len;
22282231
/* We don't need to unixify the path on Windows,
22292232
* as ext_str is derived from filename that was already unixify */
22302233
*entry = phar_fix_filepath(ext_str+ext_len, computed_entry_len, false);
@@ -2239,10 +2242,14 @@ zend_result phar_split_fname(const char *filename, size_t filename_len, char **a
22392242
}
22402243
#endif
22412244

2242-
return SUCCESS;
2245+
return arch;
22432246
}
22442247
/* }}} */
22452248

2249+
zend_string* phar_split_fname(const char *filename, size_t filename_len, zend_string **entry, int executable, int for_create) {
2250+
return phar_split_fname_ex(filename, filename_len, entry, executable, for_create, NULL);
2251+
}
2252+
22462253
/**
22472254
* Invoked when a user calls Phar::mapPhar() from within an executing .phar
22482255
* to set up its manifest directly

0 commit comments

Comments
 (0)