Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 34 additions & 18 deletions Zend/zend_string.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,33 +71,49 @@ END_EXTERN_C()

/*---*/

#define ZSTR_IS_INTERNED(s) (GC_FLAGS(s) & IS_STR_INTERNED)
#define ZSTR_IS_VALID_UTF8(s) (GC_FLAGS(s) & IS_STR_VALID_UTF8)
static zend_always_inline bool ZSTR_IS_INTERNED(const zend_string *s) {
return GC_FLAGS(s) & IS_STR_INTERNED;
}

static inline bool ZSTR_IS_VALID_UTF8(const zend_string *s) {
return GC_FLAGS(s) & IS_STR_VALID_UTF8;
}

/* These are properties, encoded as flags, that will hold on the resulting string
* after concatenating two strings that have these property.
* Example: concatenating two UTF-8 strings yields another UTF-8 string. */
#define ZSTR_COPYABLE_CONCAT_PROPERTIES (IS_STR_VALID_UTF8)

#define ZSTR_GET_COPYABLE_CONCAT_PROPERTIES(s) (GC_FLAGS(s) & ZSTR_COPYABLE_CONCAT_PROPERTIES)
/* This macro returns the copyable concat properties which hold on both strings. */
#define ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(s1, s2) (GC_FLAGS(s1) & GC_FLAGS(s2) & ZSTR_COPYABLE_CONCAT_PROPERTIES)
static inline uint32_t ZSTR_GET_COPYABLE_CONCAT_PROPERTIES(const zend_string *s) {
return GC_FLAGS(s) & ZSTR_COPYABLE_CONCAT_PROPERTIES;
}

#define ZSTR_COPY_CONCAT_PROPERTIES(out, in) do { \
zend_string *_out = (out); \
uint32_t properties = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES((in)); \
GC_ADD_FLAGS(_out, properties); \
} while (0)
/* This function returns the copyable concat properties which hold on both strings. */
static inline uint32_t ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(const zend_string *s1, const zend_string *s2) {
return ZSTR_GET_COPYABLE_CONCAT_PROPERTIES(s1) & ZSTR_GET_COPYABLE_CONCAT_PROPERTIES(s2);
}

#define ZSTR_COPY_CONCAT_PROPERTIES_BOTH(out, in1, in2) do { \
zend_string *_out = (out); \
uint32_t properties = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH((in1), (in2)); \
GC_ADD_FLAGS(_out, properties); \
} while (0)
static inline void ZSTR_COPY_CONCAT_PROPERTIES(zend_string *out, const zend_string *in) {
uint32_t properties = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES(in);
GC_ADD_FLAGS(out, properties);
}

#define ZSTR_EMPTY_ALLOC() zend_empty_string
#define ZSTR_CHAR(c) zend_one_char_string[c]
#define ZSTR_KNOWN(idx) zend_known_strings[idx]
static inline void ZSTR_COPY_CONCAT_PROPERTIES_BOTH(zend_string *out, const zend_string *in1, const zend_string *in2) {
uint32_t properties = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(in1, in2);
GC_ADD_FLAGS(out, properties);
}

static zend_always_inline zend_string *ZSTR_EMPTY_ALLOC(void) {
return zend_empty_string;
}

static zend_always_inline zend_string *ZSTR_CHAR(unsigned char c) {
return zend_one_char_string[c];
}

static zend_always_inline zend_string *ZSTR_KNOWN(size_t idx) {
return zend_known_strings[idx];
}

#define _ZSTR_HEADER_SIZE XtOffsetOf(zend_string, val)

Expand Down
4 changes: 4 additions & 0 deletions ext/pdo/pdo_stmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -1628,6 +1628,10 @@ bool pdo_stmt_setup_fetch_mode(pdo_stmt_t *stmt, zend_long mode, uint32_t mode_a

flags = mode & PDO_FETCH_FLAGS;

if ((mode & ~PDO_FETCH_FLAGS) == PDO_FETCH_USE_DEFAULT) {
mode = stmt->dbh->default_fetch_type | flags;
}

if (!pdo_verify_fetch_mode(stmt->default_fetch_type, mode, mode_arg_num, false)) {
return false;
}
Expand Down
64 changes: 64 additions & 0 deletions ext/pdo/tests/gh20214.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
--TEST--
GH-20214 (PDO::FETCH_DEFAULT unexpected behavior with PDOStatement::setFetchMode)
--EXTENSIONS--
pdo
--SKIPIF--
<?php
$dir = getenv('REDIR_TEST_DIR');
if (false == $dir) die('skip no driver');
require_once $dir . 'pdo_test.inc';
PDOTest::skip();
?>
--FILE--
<?php
if (getenv('REDIR_TEST_DIR') === false) putenv('REDIR_TEST_DIR='.__DIR__ . '/../../pdo/tests/');
require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
$db = PDOTest::factory();

$db->exec('CREATE TABLE gh20214 (c1 VARCHAR(10), c2 VARCHAR(10))');
$db->exec("INSERT INTO gh20214 VALUES ('v1', 'v2')");

$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);

// setFetchMode with FETCH_DEFAULT should use connection default (FETCH_OBJ)
$stmt = $db->query('SELECT c1, c2 FROM gh20214');
$stmt->setFetchMode(PDO::FETCH_DEFAULT);
$row = $stmt->fetch();
var_dump($row instanceof stdClass);
var_dump($row->c1);

// fetch with FETCH_DEFAULT should also use connection default
$stmt = $db->query('SELECT c1, c2 FROM gh20214');
$row = $stmt->fetch(PDO::FETCH_DEFAULT);
var_dump($row instanceof stdClass);

// fetchAll with FETCH_DEFAULT should also use connection default
$stmt = $db->query('SELECT c1, c2 FROM gh20214');
$rows = $stmt->fetchAll(PDO::FETCH_DEFAULT);
var_dump($rows[0] instanceof stdClass);

// setFetchMode then fetch without argument
$stmt = $db->query('SELECT c1, c2 FROM gh20214');
$stmt->setFetchMode(PDO::FETCH_DEFAULT);
$row = $stmt->fetch();
var_dump($row instanceof stdClass);

// query() with FETCH_DEFAULT as second argument
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_NUM);
$stmt = $db->query('SELECT c1, c2 FROM gh20214', PDO::FETCH_DEFAULT);
$row = $stmt->fetch();
var_dump(is_array($row) && isset($row[0]));
?>
--CLEAN--
<?php
require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
$db = PDOTest::factory();
PDOTest::dropTableIfExists($db, "gh20214");
?>
--EXPECT--
bool(true)
string(2) "v1"
bool(true)
bool(true)
bool(true)
bool(true)
4 changes: 0 additions & 4 deletions ext/phar/dirstream.c
Original file line number Diff line number Diff line change
Expand Up @@ -287,10 +287,6 @@ php_stream *phar_wrapper_open_dir(php_stream_wrapper *wrapper, const char *path,
return NULL;
}

if (error) {
efree(error);
}

if (zend_string_equals(resource->path, ZSTR_CHAR('/'))) {
/* root directory requested */
php_url_free(resource);
Expand Down
11 changes: 0 additions & 11 deletions ext/phar/phar_object.c
Original file line number Diff line number Diff line change
Expand Up @@ -1655,9 +1655,6 @@ static int phar_build(zend_object_iterator *iter, void *puser) /* {{{ */
return ZEND_HASH_APPLY_STOP;

} else {
if (error) {
efree(error);
}
/* convert to PHAR_UFP */
if (data->internal_file->fp_type == PHAR_MOD) {
php_stream_close(data->internal_file->fp);
Expand Down Expand Up @@ -3603,10 +3600,6 @@ static void phar_add_file(phar_archive_data **pphar, zend_string *file_name, con
}
goto finish;
} else {
if (error) {
efree(error);
}

if (!data->internal_file->is_dir) {
size_t contents_len = 0;
if (content) {
Expand Down Expand Up @@ -3683,10 +3676,6 @@ static void phar_mkdir(phar_archive_data **pphar, zend_string *dir_name)

return;
} else {
if (error) {
efree(error);
}

/* check for copy on write */
if (data->phar != *pphar) {
*pphar = data->phar;
Expand Down
6 changes: 0 additions & 6 deletions ext/phar/stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,9 +200,6 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, const cha
php_url_free(resource);
return NULL;
}
if (error) {
efree(error);
}
fpf = php_stream_alloc(&phar_ops, idata, NULL, mode);
php_url_free(resource);
efree(internal_file);
Expand Down Expand Up @@ -706,9 +703,6 @@ static int phar_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int
php_url_free(resource);
return 0;
}
if (error) {
efree(error);
}
if (idata->internal_file->fp_refcount > 1) {
/* more than just our fp resource is open for this file */
php_stream_wrapper_log_error(wrapper, options, "phar error: \"%s\" in phar \"%s\", has open file pointers, cannot unlink", internal_file, ZSTR_VAL(resource->host));
Expand Down
Loading
Loading