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
87 changes: 47 additions & 40 deletions ext/date/php_date.c
Original file line number Diff line number Diff line change
Expand Up @@ -795,13 +795,24 @@ static zend_string *date_format(const char *format, size_t format_len, const tim
case TIMELIB_ZONETYPE_ABBR:
length = slprintf(buffer, sizeof(buffer), "%s", offset->abbr);
break;
case TIMELIB_ZONETYPE_OFFSET:
length = slprintf(buffer, sizeof(buffer), "%c%02d:%02d",
((offset->offset < 0) ? '-' : '+'),
abs(offset->offset / 3600),
abs((offset->offset % 3600) / 60)
);
case TIMELIB_ZONETYPE_OFFSET: {
int seconds = offset->offset % 60;
if (seconds == 0) {
length = slprintf(buffer, sizeof(buffer), "%c%02d:%02d",
((offset->offset < 0) ? '-' : '+'),
abs(offset->offset / 3600),
abs((offset->offset % 3600) / 60)
);
} else {
length = slprintf(buffer, sizeof(buffer), "%c%02d:%02d:%02d",
((offset->offset < 0) ? '-' : '+'),
abs(offset->offset / 3600),
abs((offset->offset % 3600) / 60),
abs(seconds)
);
}
break;
}
}
}
break;
Expand Down Expand Up @@ -1892,6 +1903,32 @@ static HashTable *date_object_get_gc_timezone(zend_object *object, zval **table,
return zend_std_get_properties(object);
} /* }}} */

static zend_string *date_create_tz_offset_str(timelib_sll offset)
{
int seconds = offset % 60;
size_t size;
const char *format;

if (seconds == 0) {
size = sizeof("+05:00");
format = "%c%02d:%02d";
} else {
size = sizeof("+05:00:01");
format = "%c%02d:%02d:%02d";
}

zend_string *tmpstr = zend_string_alloc(size - 1, 0);

/* Note: if seconds == 0, the seconds argument will be excessive and therefore ignored. */
ZSTR_LEN(tmpstr) = snprintf(ZSTR_VAL(tmpstr), size, format,
offset < 0 ? '-' : '+',
abs((int)(offset / 3600)),
abs((int)(offset % 3600) / 60),
abs(seconds));

return tmpstr;
}

static void date_object_to_hash(php_date_obj *dateobj, HashTable *props)
{
zval zv;
Expand All @@ -1909,17 +1946,8 @@ static void date_object_to_hash(php_date_obj *dateobj, HashTable *props)
case TIMELIB_ZONETYPE_ID:
ZVAL_STRING(&zv, dateobj->time->tz_info->name);
break;
case TIMELIB_ZONETYPE_OFFSET: {
zend_string *tmpstr = zend_string_alloc(sizeof("UTC+05:00")-1, 0);
int utc_offset = dateobj->time->z;

ZSTR_LEN(tmpstr) = snprintf(ZSTR_VAL(tmpstr), sizeof("+05:00"), "%c%02d:%02d",
utc_offset < 0 ? '-' : '+',
abs(utc_offset / 3600),
abs(((utc_offset % 3600) / 60)));

ZVAL_NEW_STR(&zv, tmpstr);
}
case TIMELIB_ZONETYPE_OFFSET:
ZVAL_NEW_STR(&zv, date_create_tz_offset_str(dateobj->time->z));
break;
case TIMELIB_ZONETYPE_ABBR:
ZVAL_STRING(&zv, dateobj->time->tz_abbr);
Expand Down Expand Up @@ -2031,29 +2059,8 @@ static void php_timezone_to_string(php_timezone_obj *tzobj, zval *zv)
case TIMELIB_ZONETYPE_ID:
ZVAL_STRING(zv, tzobj->tzi.tz->name);
break;
case TIMELIB_ZONETYPE_OFFSET: {
timelib_sll utc_offset = tzobj->tzi.utc_offset;
int seconds = utc_offset % 60;
size_t size;
const char *format;
if (seconds == 0) {
size = sizeof("+05:00");
format = "%c%02d:%02d";
} else {
size = sizeof("+05:00:01");
format = "%c%02d:%02d:%02d";
}
zend_string *tmpstr = zend_string_alloc(size - 1, 0);

/* Note: if seconds == 0, the seconds argument will be excessive and therefore ignored. */
ZSTR_LEN(tmpstr) = snprintf(ZSTR_VAL(tmpstr), size, format,
utc_offset < 0 ? '-' : '+',
abs((int)(utc_offset / 3600)),
abs((int)(utc_offset % 3600) / 60),
abs(seconds));

ZVAL_NEW_STR(zv, tmpstr);
}
case TIMELIB_ZONETYPE_OFFSET:
ZVAL_NEW_STR(zv, date_create_tz_offset_str(tzobj->tzi.utc_offset));
break;
case TIMELIB_ZONETYPE_ABBR:
ZVAL_STRING(zv, tzobj->tzi.z.abbr);
Expand Down
2 changes: 1 addition & 1 deletion ext/date/tests/bug81565.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ echo "\n", (new DatetimeZone('+01:45:30'))->getName();
\DateTime::__set_state(array(
'date' => '0021-08-21 00:00:00.000000',
'timezone_type' => 1,
'timezone' => '+00:49',
'timezone' => '+00:49:56',
))
+01:45:30
53 changes: 53 additions & 0 deletions ext/date/tests/gh20764.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
--TEST--
GH-20764 (Timezone offset with seconds loses precision)
--FILE--
<?php

$timezones = [
'+03:00:30',
'-03:00:30',
];

foreach ($timezones as $timezone) {
echo "--- Testing timezone $timezone ---\n";
$tz = new DateTimeZone($timezone);
$dt = new DateTimeImmutable('2025-04-01', $tz);
var_dump($dt->format('e'));
var_dump($dt);
var_dump(unserialize(serialize($dt))->getTimezone());
}

?>
--EXPECTF--
--- Testing timezone +03:00:30 ---
string(9) "+03:00:30"
object(DateTimeImmutable)#%d (3) {
["date"]=>
string(26) "2025-04-01 00:00:00.000000"
["timezone_type"]=>
int(1)
["timezone"]=>
string(9) "+03:00:30"
}
object(DateTimeZone)#%d (2) {
["timezone_type"]=>
int(1)
["timezone"]=>
string(9) "+03:00:30"
}
--- Testing timezone -03:00:30 ---
string(9) "-03:00:30"
object(DateTimeImmutable)#%d (3) {
["date"]=>
string(26) "2025-04-01 00:00:00.000000"
["timezone_type"]=>
int(1)
["timezone"]=>
string(9) "-03:00:30"
}
object(DateTimeZone)#%d (2) {
["timezone_type"]=>
int(1)
["timezone"]=>
string(9) "-03:00:30"
}
6 changes: 1 addition & 5 deletions ext/dom/element.c
Original file line number Diff line number Diff line change
Expand Up @@ -1326,11 +1326,7 @@ PHP_METHOD(DOMElement, hasAttribute)
DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);

attr = dom_get_attribute_or_nsdecl(intern, nodep, BAD_CAST name, name_len);
if (attr == NULL) {
RETURN_FALSE;
} else {
RETURN_TRUE;
}
RETURN_BOOL(attr != NULL);
}
/* }}} end dom_element_has_attribute */

Expand Down
8 changes: 4 additions & 4 deletions ext/gd/gd.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ static void php_image_filter_scatter(INTERNAL_FUNCTION_PARAMETERS);
/* End Section filters declarations */
static gdImagePtr _php_image_create_from_string(zend_string *Data, const char *tn, gdImagePtr (*ioctx_func_p)(gdIOCtxPtr));
static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type, const char *tn, gdImagePtr (*func_p)(FILE *), gdImagePtr (*ioctx_func_p)(gdIOCtxPtr));
static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, const char *tn);
static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type);
static gdIOCtx *create_stream_context(php_stream *stream, int close_stream);
static gdIOCtx *create_output_context(zval *to_zval, uint32_t arg_num);
static int _php_image_type(zend_string *data);
Expand Down Expand Up @@ -1729,7 +1729,7 @@ PHP_FUNCTION(imagecreatefromtga)
/* }}} */

/* {{{ _php_image_output */
static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, const char *tn)
static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type)
{
zval *imgind;
char *file = NULL;
Expand Down Expand Up @@ -2102,14 +2102,14 @@ PHP_FUNCTION(imagewbmp)
/* {{{ Output GD image to browser or file */
PHP_FUNCTION(imagegd)
{
_php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GD, "GD");
_php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GD);
}
/* }}} */

/* {{{ Output GD2 image to browser or file */
PHP_FUNCTION(imagegd2)
{
_php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GD2, "GD2");
_php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GD2);
}
/* }}} */

Expand Down
16 changes: 4 additions & 12 deletions ext/readline/readline.c
Original file line number Diff line number Diff line change
Expand Up @@ -393,13 +393,9 @@ PHP_FUNCTION(readline_read_history)
RETURN_FALSE;
}

/* XXX from & to NYI */
if (read_history(arg)) {
/* If filename is NULL, then read from `~/.history' */
RETURN_FALSE;
} else {
RETURN_TRUE;
}
/* XXX from & to NYI
If filename is NULL, then read from `~/.history' */
RETURN_BOOL(!read_history(arg));
}

/* }}} */
Expand All @@ -417,11 +413,7 @@ PHP_FUNCTION(readline_write_history)
RETURN_FALSE;
}

if (write_history(arg)) {
RETURN_FALSE;
} else {
RETURN_TRUE;
}
RETURN_BOOL(!write_history(arg));
}

/* }}} */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ Felix De Vliegher <felix.devliegher@gmail.com>
$standard = new ReflectionExtension('standard');
var_dump($standard->getDependencies());
?>
--EXPECTF--
array(%d) {
--EXPECT--
array(3) {
["random"]=>
string(8) "Required"
["uri"]=>
%s(8) "Required"
string(8) "Required"
["session"]=>
%s(8) "Optional"
string(8) "Optional"
}
1 change: 1 addition & 0 deletions ext/standard/basic_functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ static void user_shutdown_function_dtor(zval *zv);
static void user_tick_function_dtor(user_tick_function_entry *tick_function_entry);

static const zend_module_dep standard_deps[] = { /* {{{ */
ZEND_MOD_REQUIRED("random")
ZEND_MOD_REQUIRED("uri")
ZEND_MOD_OPTIONAL("session")
ZEND_MOD_END
Expand Down