Skip to content

Commit 12d9cfe

Browse files
authored
Merge branch 'master' into phar-5
2 parents 3a623c6 + 8b34389 commit 12d9cfe

File tree

16 files changed

+330
-149
lines changed

16 files changed

+330
-149
lines changed

build/gen_stub.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2375,8 +2375,8 @@ protected function getTypeCode(string $variableLikeName, string &$code): string
23752375
$code .= "\t{$variableLikeType}_{$variableLikeName}_type_list->num_types = $classTypeCount;\n";
23762376

23772377
foreach ($arginfoType->classTypes as $k => $classType) {
2378-
$escapedClassName = $classType->toEscapedName();
2379-
$code .= "\t{$variableLikeType}_{$variableLikeName}_type_list->types[$k] = (zend_type) ZEND_TYPE_INIT_CLASS({$variableLikeType}_{$variableLikeName}_class_{$escapedClassName}, 0, 0);\n";
2378+
$varEscapedClassName = $classType->toVarEscapedName();
2379+
$code .= "\t{$variableLikeType}_{$variableLikeName}_type_list->types[$k] = (zend_type) ZEND_TYPE_INIT_CLASS({$variableLikeType}_{$variableLikeName}_class_{$varEscapedClassName}, 0, 0);\n";
23802380
}
23812381

23822382
$typeMaskCode = $this->type->toArginfoType()->toTypeMask();
@@ -4261,6 +4261,11 @@ private function handleStatements(array $stmts, PrettyPrinterAbstract $prettyPri
42614261
continue;
42624262
}
42634263

4264+
if ($stmt instanceof Stmt\Use_ || $stmt instanceof Stmt\GroupUse) {
4265+
// use statements are resolved by NameResolver before this point
4266+
continue;
4267+
}
4268+
42644269
if ($stmt instanceof Stmt\Const_) {
42654270
foreach ($stmt->consts as $const) {
42664271
$this->constInfos[] = parseConstLike(

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: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -345,12 +345,12 @@ 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
}
@@ -359,7 +359,7 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mo
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,12 +471,12 @@ 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
}
@@ -485,7 +485,7 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options
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: 20 additions & 28 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,7 +91,8 @@ 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

@@ -110,7 +108,7 @@ static zend_string* phar_get_name_for_relative_paths(zend_string *filename, bool
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,9 +490,9 @@ 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>/ */
499497
zend_result has_archive = phar_get_archive(&phar, arch, arch_len, NULL, NULL);
500498
efree(arch);
@@ -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,7 +727,8 @@ 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>/ */
@@ -747,12 +744,10 @@ PHP_FUNCTION(phar_is_file) /* {{{ */
747744
}
748745
zend_string_release_ex(entry, false);
749746
if (etemp) {
750-
efree(arch);
751747
RETURN_BOOL(!etemp->is_dir);
752748
}
753749
/* this file is not in the current directory, use the original path */
754750
}
755-
efree(arch);
756751
RETURN_FALSE;
757752
}
758753
}
@@ -779,8 +774,6 @@ PHP_FUNCTION(phar_is_link) /* {{{ */
779774
goto skip_phar;
780775
}
781776
if (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://")) {
782-
char *arch;
783-
size_t arch_len;
784777
zend_string *fname = zend_get_executed_filename_ex();
785778

786779
/* we are checking for existence of a file within the relative path. Chances are good that this is
@@ -789,7 +782,8 @@ PHP_FUNCTION(phar_is_link) /* {{{ */
789782
goto skip_phar;
790783
}
791784

792-
if (SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, 2, 0)) {
785+
zend_string *arch = phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), NULL, 2, 0);
786+
if (arch) {
793787
phar_archive_data *phar;
794788

795789
/* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
@@ -805,11 +799,9 @@ PHP_FUNCTION(phar_is_link) /* {{{ */
805799
}
806800
zend_string_release_ex(entry, false);
807801
if (etemp) {
808-
efree(arch);
809802
RETURN_BOOL(etemp->link);
810803
}
811804
}
812-
efree(arch);
813805
RETURN_FALSE;
814806
}
815807
}

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

ext/phar/phar_internal.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,8 @@ ZEND_ATTRIBUTE_NONNULL zend_result phar_get_entry_data(phar_entry_data **ret, co
473473
ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_flush_ex(phar_archive_data *archive, zend_string *user_stub, bool is_default_stub, char **error);
474474
ZEND_ATTRIBUTE_NONNULL int phar_flush(phar_archive_data *archive, char **error);
475475
zend_result phar_detect_phar_fname_ext(const char *filename, size_t filename_len, const char **ext_str, size_t *ext_len, int executable, int for_create, bool is_complete);
476-
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);
476+
zend_string* phar_split_fname_ex(const char *filename, size_t filename_len, zend_string **entry, int executable, int for_create, const char **error);
477+
zend_string* phar_split_fname(const char *filename, size_t filename_len, zend_string **entry, int executable, int for_create);
477478

478479
typedef enum {
479480
pcr_use_query,

0 commit comments

Comments
 (0)