Skip to content

Commit

Permalink
Fixed the SEGV bug with TimecopDateTime::__construct() when its 1st a…
Browse files Browse the repository at this point in the history
…rgument is null
  • Loading branch information
hnw committed Mar 11, 2013
1 parent f7a0f00 commit 93118d8
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 49 deletions.
63 changes: 63 additions & 0 deletions tests/010.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
--TEST--
Check for TimecopDateTime::__construct
--SKIPIF--
<?php
extension_loaded('timecop') or die('skip timecop not available');
$required_class = array("timecopdatetime", "datetime");
foreach ($required_class as $class_name) {
if (!class_exists($class_name)) {
die("skip $class_name class is not available.");
}
}
--INI--
date.timezone=America/Los_Angeles
timecop.func_override=0
--FILE--
<?php
$strs = array(
"2005-07-14 22:30:41",
"2005-07-14 22:30:41 GMT",
"@1121373041",
"@1121373041 CEST",
'1 Monday December 2008',
'2 Monday December 2008',
'3 Monday December 2008',
'first Monday December 2008',
'second Monday December 2008',
'third Monday December 2008',
'2013-03-13 03:00:00 -1sec',
'0',
);
foreach ($strs as $str) {
try {
$dt1 = new DateTime($str);
$e1 = null;
} catch (Exception $e) {
$dt1 = null;
$e1 = $e;
}
try {
$dt2 = new TimecopDateTime($str);
$e2 = null;
} catch (Exception $e) {
$dt2 = null;
$e2 = $e;
}
if ($dt1 === null && $dt2 === null) {
if ($e1->getmessage() !== $e2->getmessage()) {
printf("Exception message is differ for str=%s: %s !== %s\n",
$str, $e1->getmessage(), $e2->getmessage());
}
}
if ($dt1 && $dt2) {
if ($dt1->format("c") !== $dt2->format("c")) {
printf("TimecopDatetime::format is differ from Datetime::format for str=%s: %s !== %s\n",
$str, $dt1->format("c"), $dt2->format("c"));
}
if ($dt1->format("U") != $dt2->getTimestamp()) {
printf("TimecopDatetime::getTimestamp is differ from Datetime::getTimestamp for str=%s: %s !== %s\n",
$str, $dt1->format("U"), $dt2->getTimestamp());
}
}
}
--EXPECT--
44 changes: 26 additions & 18 deletions tests/overload_13.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -25,33 +25,41 @@ timecop_freeze(timecop_orig_strtotime("2012-02-29 01:23:45"));
$dt0 = new DateTime();
var_dump(get_class($dt0));

// constuctor with 0 argument
$dt1 = new DateTime();
var_dump($dt1->format("c"));
$dts = array(
// constuctor with 0 argument
new DateTime(),

// constuctor with 1 argument(absolute format)
$dt2 = new DateTime("2012-03-31 12:34:56");
var_dump($dt2->format("c"));
// constuctor with 1 argument(null)
new DateTime(""),

// constuctor with 1 argument(relative format)
$dt3 = new DateTime("+3days");
var_dump($dt3->format("c"));
// constuctor with 1 argument(empty string)
new DateTime(""),

// constuctor with 1 argument(including timezone info)
$dt4 = new DateTime("1970-01-01 19:00:00 EST");
var_dump($dt4->format("c"));
// constuctor with 1 argument(absolute format)
new DateTime("2012-03-31 12:34:56"),

// constuctor with 1 argument(unix time)
$dt5 = new DateTime("@86400");
var_dump($dt5->format("c"));
// constuctor with 1 argument(relative format)
new DateTime("+3days"),

// constuctor with 2 argument
$dt6 = new DateTime("now", new DateTimezone("Asia/Tokyo"));
var_dump($dt6->format("c"));
// constuctor with 1 argument(including timezone info)
new DateTime("1970-01-01 19:00:00 EST"),

// constuctor with 1 argument(unix time)
new DateTime("@86400"),

// constuctor with 2 argument
new DateTime("now", new DateTimezone("Asia/Tokyo")),
);

foreach ($dts as $dt) {
var_dump($dt->format("c"));
}

--EXPECT--
string(15) "TimecopDateTime"
string(25) "2012-02-29T01:23:45-08:00"
string(25) "2012-02-29T01:23:45-08:00"
string(25) "2012-02-29T01:23:45-08:00"
string(25) "2012-03-31T12:34:56-07:00"
string(25) "2012-03-03T01:23:45-08:00"
string(25) "1970-01-01T19:00:00-05:00"
Expand Down
44 changes: 26 additions & 18 deletions tests/overload_14.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -25,33 +25,41 @@ timecop_freeze(timecop_orig_strtotime("2012-02-29 01:23:45"));
$dt0 = new DateTime();
var_dump(get_class($dt0));

// constuctor with 0 argument
$dt1 = date_create();
var_dump($dt1->format("c"));
$dts = array(
// constuctor with 0 argument
date_create(),

// constuctor with 1 argument(absolute format)
$dt2 = date_create("2012-03-31 12:34:56");
var_dump($dt2->format("c"));
// constuctor with 1 argument(null)
date_create(null),

// constuctor with 1 argument(relative format)
$dt3 = date_create("+3days");
var_dump($dt3->format("c"));
// constuctor with 1 argument(empty string)
date_create(""),

// constuctor with 1 argument(including timezone info)
$dt4 = date_create("1970-01-01 19:00:00 EST");
var_dump($dt4->format("c"));
// constuctor with 1 argument(absolute format)
date_create("2012-03-31 12:34:56"),

// constuctor with 1 argument(unix time)
$dt5 = date_create("@86400");
var_dump($dt5->format("c"));
// constuctor with 1 argument(relative format)
date_create("+3days"),

// constuctor with 2 argument
$dt6 = date_create("now", new DateTimezone("Asia/Tokyo"));
var_dump($dt6->format("c"));
// constuctor with 1 argument(including timezone info)
date_create("1970-01-01 19:00:00 EST"),

// constuctor with 1 argument(unix time)
date_create("@86400"),

// constuctor with 2 argument
date_create("now", new DateTimezone("Asia/Tokyo")),
);

foreach ($dts as $dt) {
var_dump($dt->format("c"));
}

--EXPECT--
string(15) "TimecopDateTime"
string(25) "2012-02-29T01:23:45-08:00"
string(25) "2012-02-29T01:23:45-08:00"
string(25) "2012-02-29T01:23:45-08:00"
string(25) "2012-03-31T12:34:56-07:00"
string(25) "2012-03-03T01:23:45-08:00"
string(25) "1970-01-01T19:00:00-05:00"
Expand Down
41 changes: 28 additions & 13 deletions timecop.c
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ static int restore_request_time(TSRMLS_D);
static long timecop_current_timestamp(TSRMLS_D);

static int fill_mktime_params(zval ***params, const char *date_function_name, int from TSRMLS_DC);
static int fix_datetime_timestamp(zval **datetime_obj, zval *time_str TSRMLS_DC);
static int fix_datetime_timestamp(zval **datetime_obj, zval *time TSRMLS_DC);

static void _timecop_call_function(INTERNAL_FUNCTION_PARAMETERS, const char *function_name, zval **retval_ptr_ptr, int index_to_fill_timestamp);
static void _timecop_call_mktime(INTERNAL_FUNCTION_PARAMETERS, const char *mktime_function_name, const char *date_function_name, zval **retval_ptr_ptr);
Expand Down Expand Up @@ -589,21 +589,34 @@ static int fill_mktime_params(zval ***params, const char *date_function_name, in
return MKTIME_NUM_ARGS;
}

static int fix_datetime_timestamp(zval **datetime_obj, zval *time_str TSRMLS_DC)
static int fix_datetime_timestamp(zval **datetime_obj, zval *time TSRMLS_DC)
{
zval *orig_timestamp, *fixed_timestamp;
zval now;

if (time_str == NULL) {
INIT_ZVAL(now);
ZVAL_STRING(&now, "now", 0);
time_str = &now;
INIT_ZVAL(now);
ZVAL_STRING(&now, "now", 0);

if (time == NULL) {
time = &now;
} else {
zval time_str;
time_str = *time;
zval_copy_ctor(&time_str);
convert_to_string(&time_str);
if (Z_STRLEN(time_str) == 0) {
time = &now;
}
zval_dtor(&time_str);
}

zend_call_method_with_0_params(datetime_obj, Z_OBJCE_PP(datetime_obj), NULL, "gettimestamp", &orig_timestamp);
zend_call_method_with_1_params(NULL, NULL, NULL, "timecop_strtotime", &fixed_timestamp, time_str);
zend_call_method_with_1_params(NULL, NULL, NULL, "timecop_strtotime", &fixed_timestamp, time);

if (Z_LVAL_P(orig_timestamp) != Z_LVAL_P(fixed_timestamp)) {
if (Z_TYPE_P(fixed_timestamp) == IS_BOOL && Z_BVAL_P(fixed_timestamp) == 0) {
// timecop_strtotime($time) === false
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse time string '%s'", Z_STRVAL_P(time));
} else if (Z_LVAL_P(orig_timestamp) != Z_LVAL_P(fixed_timestamp)) {
zend_call_method_with_1_params(datetime_obj, Z_OBJCE_PP(datetime_obj), NULL, "settimestamp", NULL, fixed_timestamp);
}

Expand Down Expand Up @@ -850,7 +863,7 @@ PHP_FUNCTION(timecop_unixtojd)
*/
PHP_FUNCTION(timecop_date_create)
{
zval ***params, *datetime_obj, *time_str = NULL;
zval ***params, *datetime_obj, *time = NULL;

params = (zval ***) safe_emalloc(ZEND_NUM_ARGS(), sizeof(zval **), 0);

Expand All @@ -875,7 +888,7 @@ PHP_METHOD(TimecopDateTime, __construct)
{
zval ***params;
zval *obj = getThis();
zval *time_str = NULL;
zval *time = NULL;
zend_class_entry *datetime_ce;

params = (zval ***) safe_emalloc(ZEND_NUM_ARGS(), sizeof(zval **), 0);
Expand All @@ -888,10 +901,12 @@ PHP_METHOD(TimecopDateTime, __construct)
/* call DateTime::__constuctor() */
call_constructor(&obj, TIMECOP_G(ce_DateTime), params, ZEND_NUM_ARGS() TSRMLS_CC);

if (ZEND_NUM_ARGS() >= 1) {
time_str = *params[0];
if (!EG(exception)) {
if (ZEND_NUM_ARGS() >= 1) {
time = *params[0];
}
fix_datetime_timestamp(&obj, time TSRMLS_CC);
}
fix_datetime_timestamp(&obj, time_str TSRMLS_CC);

efree(params);
}
Expand Down

0 comments on commit 93118d8

Please sign in to comment.