Merge branch 'master' of git.php.net:php-src

* 'master' of git.php.net:php-src: (150 commits)
  Fix Bug #74386Phar::__construct(): wrong number of parameters by reflection
  Fix Bug #74386 Phar::__construct(): wrong number of parameters by reflection
  Fixed typo
  fix typo
  fix resetting cursor data if dba_firstkey failed
  fix wrong define
  fix c/p issue
  enable ext/dba on AppVeyor
  implement support for LMDB in ext/dba
  fix identiation
  Bugfix #74556 stream_socket_get_name() returns empty string
  Fix abstract name handling to be binary safe
  Added more EXIF MAKERNOTE formats:  - AGFA,  - Kyocera  - Ricoh  - Epson
  Replace slow generic sha3 implementation by https://github.com/gvanas/KeccakCodePackage
  Bugfix #74598 ftp:// ignores context
  Improve conditions and visibility
  [ci skip] update NEWS
  Fix test
  Fixed bug #72885 flatfile: dba_fetch() fails to read replaced entry
  Update NEWS
  ...
This commit is contained in:
Remi Collet 2017-05-29 09:54:29 +02:00
commit 7bb6b6b6d2
220 changed files with 19800 additions and 1790 deletions

View File

@ -24,7 +24,7 @@ environment:
PHP_BUILD_CACHE_BASE_DIR: c:\build-cache
PHP_BUILD_OBJ_DIR: c:\obj
PHP_BUILD_CACHE_SDK_DIR: c:\build-cache\sdk
PHP_BUILD_SDK_BRANCH: php-sdk-2.0.1
PHP_BUILD_SDK_BRANCH: php-sdk-2.0.4
PHP_BUILD_CRT: vc15
# ext and env setup for tests
#MYSQL_TEST_PASSWD: Password12!
@ -44,7 +44,7 @@ environment:
services:
# the setup scripts have to be touched, once some other db version is used
- mysql
- postgresql95
- postgresql96
platform:
- x64

View File

@ -60,7 +60,7 @@ before_script:
# Run PHPs run-tests.php
script:
- ./sapi/cli/php run-tests.php -p `pwd`/sapi/cli/php $(if [ $ENABLE_DEBUG == 1 ]; then echo "-d opcache.enable_cli=1 -d zend_extension=`pwd`/modules/opcache.so"; fi) -g "FAIL,XFAIL,BORK,WARN,LEAK,SKIP" --offline --show-diff --set-timeout 120
- ./sapi/cli/php run-tests.php -p `pwd`/sapi/cli/php $(if [ $ENABLE_DEBUG == 1 ]; then echo "-d opcache.enable_cli=1 -d zend_extension=`pwd`/modules/opcache.so"; fi) -g "FAIL,XFAIL,BORK,WARN,LEAK,SKIP" --offline --show-diff --show-slow 1000 --set-timeout 120
after_success:
- ccache --show-stats

29
NEWS
View File

@ -3,6 +3,11 @@ PHP NEWS
?? ??? ????, PHP 7.2
- Core:
. Added ZEND_COUNT, ZEND_GET_CLASS, ZEND_GET_CALLED_CLASS, ZEND_GET_TYPE
instructions, to implement corresponding builtin functions. (Dmitry)
. "Countable" interface is moved from SPL to Core. (Dmitry)
. Added ZEND_IN_ARRAY instruction, implementing optimized in_array() builtin
function, through hash lookup in flipped array. (Dmitry)
. Removed IS_TYPE_IMMUTABLE (it's the same as COPYABLE & !REFCOUNTED). (Dmitry)
. Removed the sql.safe_mode directive. (Kalle)
. Removed support for Netware. (Kalle)
@ -39,6 +44,15 @@ PHP NEWS
. Fixed bug #74149 (static embed SAPI linkage error). (krakjoe)
. Fixed bug #72359, bug #72451, bug #73706, bug #71115 and others related
to interned strings handling in TS builds. (Anatol, Dmitry)
. Implemented "Trailing Commas In List Syntax" RFC for group use lists only.
(Sammy Kaye Powers)
. Fixed bug #74269 (It's possible to override trait property with different
loosely-equal value). (pmmaga)
. Fixed bug #61970 (Restraining __construct() access level in subclass gives
a fatal error). (pmmaga)
. Fixed bug #63384 (Cannot override an abstract method with an abstract
method). (pmmaga, wes)
. Fixed misparsing of abstract unix domain socket names. (Sara)
- BCMath:
. Fixed bug #46564 (bcmod truncates fractionals). (liborm85)
@ -52,6 +66,10 @@ PHP NEWS
(krakjoe)
. Fixed bug #74080 (add constant for RFC7231 format datetime). (duncan3dc)
- Dba:
. Fixed bug #72885 (flatfile: dba_fetch() fails to read replaced entry).
(Anatol)
- DOM:
. Fixed bug #67474 (getElementsByTagNameNS filter on default ns). (aboks)
. Fixed bug #54382 (getAttributeNodeNS doesn't get xmlns* attributes).
@ -61,7 +79,8 @@ PHP NEWS
- EXIF:
. Added support for vendor specific tags for the following formats:
Samsung, DJI, Panasonic, Sony, Pentax, Minolta & Sigma/Foveon. (Kalle)
Samsung, DJI, Panasonic, Sony, Pentax, Minolta, Sigma/Foveon, AGFA,
Kyocera, Ricoh & Epson. (Kalle)
. Fixed bug #72682 (exif_read_data() fails to read all data for some
images). (Kalle)
. Fixed bug #71534 (Type confusion in exif_read_data() leading to heap
@ -79,6 +98,7 @@ PHP NEWS
(Mike)
- FTP:
. Fixed bug #74598 (ftp:// wrapper ignores context arg). (Sara)
. Implement MLSD for structured listing of directories. (blar)
- GD:
@ -97,6 +117,8 @@ PHP NEWS
- intl:
. Fixed bug #74433 (wrong reflection for Normalizer methods). (villfa)
. Fixed bug #74439 (wrong reflection for Locale methods). (villfa)
. Fixed bug #74468 (wrong reflection on Collator::sortWithSortKeys). (villfa)
. Fixed bug #63790 (test using Spoofchecker which may be unavailable). (Sara)
- Mbstring:
. Implemented request #66024 (mb_chr() and mb_ord()). (Masakielastic, Yasuo)
@ -150,6 +172,7 @@ PHP NEWS
(mhagstrand)
. Fixed bug #74196 (phar does not correctly handle names containing dots).
(mhagstrand)
. Fixed bug #74386 (Phar::__construct reflection incorrect). (villfa)
- PHPDBG
. Added extended_value to opcode dump output. (Sara)
@ -181,11 +204,15 @@ PHP NEWS
. Fixed bug #72979 (money_format stores wrong length AIX). (matthieu.sarter)
. Fixed bug #74300 (unserialize accepts two plus/minus signs for float number exponent part).
(xKerman)
. Fixed bug #74556 (stream_socket_get_name() returns '\0'). (Sara)
- XML:
. Moved utf8_encode() and utf8_decode() to the Standard extension. (Andrea)
. Fixed bug #72135 (malformed XML causes fault) (edgarsandi)
- xmlreader:
. Fixed bug #74457 (Wrong reflection on XMLReader::expand). (villfa)
- XMLRPC:
. Use Zend MM for allocation in bundled libxmlrpc (Joe)

View File

@ -322,4 +322,15 @@ New Release Manager Checklist
1. Email systems@ to get setup for access to downloads.php.net
2. Create a GPG key for your @php.net address and publish it by editing `include/gpg-keys.inc`
in the `web-php` repository, adding the output of `gpg --fingerprint "$USER@php.net"`
in the `web-php` repository, adding the output of `gpg --fingerprint "$USER@php.net"`. Let
one or more of the previous RMs sign your key.
3. Request karma to eding main/php_version.h. Possibly karma for other restricted parts of
php-src might come in question.
4. Request karma for web/qa.git and web/php.git for publishing release announcements.
5. Request moderation access to announce@php.net and primary-qa-tester@lists.php.net lists, to
be able to moderate your release announcements. All the announcements should be sent from
the @php.net alias.

View File

@ -107,33 +107,30 @@ TSRM_API void tsrm_win32_shutdown(void)
#endif
}
char * tsrm_win32_get_path_sid_key(const char *pathname)
char * tsrm_win32_get_path_sid_key(const char *pathname, size_t pathname_len, size_t *key_len)
{
PSID pSid = TWG(impersonation_token_sid);
TCHAR *ptcSid = NULL;
char *ptcSid = NULL;
char *bucket_key = NULL;
size_t ptc_sid_len, pathname_len;
pathname_len = strlen(pathname);
size_t ptc_sid_len;
if (!pSid) {
bucket_key = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pathname_len + 1);
if (!bucket_key) {
return NULL;
}
memcpy(bucket_key, pathname, pathname_len);
return bucket_key;
*key_len = pathname_len;
return pathname;
}
if (!ConvertSidToStringSid(pSid, &ptcSid)) {
*key_len = 0;
return NULL;
}
ptc_sid_len = strlen(ptcSid);
bucket_key = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pathname_len + ptc_sid_len + 1);
*key_len = pathname_len + ptc_sid_len;
bucket_key = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *key_len + 1);
if (!bucket_key) {
LocalFree(ptcSid);
*key_len = 0;
return NULL;
}

View File

@ -95,7 +95,7 @@ TSRMLS_CACHE_EXTERN()
#define SHM_RND FILE_MAP_WRITE
#define SHM_REMAP FILE_MAP_COPY
char * tsrm_win32_get_path_sid_key(const char *pathname );
char * tsrm_win32_get_path_sid_key(const char *pathname, size_t pathname_len, size_t *key_len);
TSRM_API void tsrm_win32_startup(void);
TSRM_API void tsrm_win32_shutdown(void);

View File

@ -39,6 +39,8 @@ PHP 7.2 UPGRADE NOTES
of a notice. They will generate an Error in a future version of PHP.
(https://wiki.php.net/rfc/deprecate-bareword-strings)
. Minimum supported Windows versions are Windows 7/Server 2008 R2.
. Initial trait property value compatibility check will no longer perform
any casts. (Bug #74269)
- BCMath:
. The bcmod() function no longer truncates fractional numbers to integers. As
@ -99,6 +101,11 @@ PHP 7.2 UPGRADE NOTES
inherited method. This complies with contravariance of method argument types
under the Liskov Substitution Principle.
(https://wiki.php.net/rfc/parameter-no-type-variance)
. It is now allowed to override an abstract method with another abstract
method in a child class.
(https://wiki.php.net/rfc/allow-abstract-function-override)
. A trailing comma in group use statements is now allowed.
(https://wiki.php.net/rfc/list-syntax-trailing-commas)
- PCRE:
. Added `J` modifier for setting PCRE_DUPNAMES.
@ -183,6 +190,7 @@ See also: https://wiki.php.net/rfc/deprecations_php_7_2
. count() now raises a warning when an invalid parameter is passed.
Only arrays and objects implementing the Countable interface should be passed.
. pack() and unpack() now support float and double in both little and big endian.
. number_format() ensures zero values never contain a negative sign.
- XML:
. utf8_encode() and utf8_decode() have been moved to the Standard extension
@ -230,7 +238,8 @@ See also: https://wiki.php.net/rfc/deprecations_php_7_2
- EXIF:
. Added extended exif tag support for the following formats:
Samsung, DJI, Panasonic, Sony, Pentax, Minolta & Sigma/Foveon.
Samsung, DJI, Panasonic, Sony, Pentax, Minolta, Sigma/Foveon,
AGFA, Kyocera, Ricoh & Epson.
- GD:
. Removed --enable-gd-native-ttf configuration option which was unused as

View File

@ -0,0 +1,12 @@
--TEST--
Allow abstract function override
--FILE--
<?php
abstract class A { abstract function bar($x); }
abstract class B extends A { abstract function bar($x); }
echo "DONE";
?>
--EXPECT--
DONE

View File

@ -0,0 +1,12 @@
--TEST--
Allow abstract function override
--FILE--
<?php
abstract class A { abstract function bar($x); }
abstract class B extends A { abstract function bar($x, $y = 0); }
echo "DONE";
?>
--EXPECT--
DONE

View File

@ -0,0 +1,12 @@
--TEST--
Allow abstract function override
--FILE--
<?php
abstract class A { abstract function bar($x, $y = 0); }
abstract class B extends A { abstract function bar($x); }
echo "DONE";
?>
--EXPECTF--
Fatal error: Declaration of B::bar($x) must be compatible with A::bar($x, $y = 0) in %s

16
Zend/tests/bug61970.phpt Normal file
View File

@ -0,0 +1,16 @@
--TEST--
Bug #61970 (Restraining __construct() access level in subclass gives a fatal error)
--FILE--
<?php
class Foo {
public function __construct(){}
}
class Bar extends Foo {
protected function __construct(){}
}
echo 'DONE';
--EXPECT--
DONE

View File

@ -0,0 +1,15 @@
--TEST--
Bug #61970 (Restraining __construct() access level in subclass gives a fatal error - stays when implementing abstract)
--FILE--
<?php
abstract class Foo {
abstract public function __construct();
}
class Bar extends Foo {
protected function __construct(){}
}
--EXPECTF--
Fatal error: Access level to Bar::__construct() must be public (as in class Foo) in %s

View File

@ -0,0 +1,19 @@
--TEST--
Bug #61970 (Restraining __construct() access level in subclass gives a fatal error - stays when inheriting implemented abstract)
--FILE--
<?php
abstract class Foo {
abstract public function __construct();
}
class Bar extends Foo {
public function __construct(){}
}
class Baz extends Bar {
protected function __construct(){}
}
--EXPECTF--
Fatal error: Access level to Baz::__construct() must be public (as in class Bar) in %s

17
Zend/tests/bug74269.phpt Normal file
View File

@ -0,0 +1,17 @@
--TEST--
Bug #74269: It's possible to override trait property with different loosely-equal value
--FILE--
<?php
trait PropertiesTrait
{
public $same = true;
}
class PropertiesExample
{
use PropertiesTrait;
public $same = 2;
}
?>
--EXPECTF--
Fatal error: PropertiesExample and PropertiesTrait define the same property ($same) in the composition of PropertiesExample. However, the definition differs and is considered incompatible. Class was composed in %s

11
Zend/tests/bug74546.phpt Normal file
View File

@ -0,0 +1,11 @@
--TEST--
Bug #74546 (SIGILL in ZEND_FETCH_CLASS_CONSTANT_SPEC_CONST_CONST_HANDLER())
--FILE--
<?php
"000000"[0]::d;
?>
--EXPECTF--
Fatal error: Uncaught Error: Class '0' not found in %sbug74546.php:%d
Stack trace:
#0 {main}
thrown in %sbug74546.php on line %d

26
Zend/tests/bug74657.phpt Normal file
View File

@ -0,0 +1,26 @@
--TEST--
Bug #74657 (Undefined constants in array properties result in broken properties)
--FILE--
<?php
interface I {
}
class C {
const FOO = I::FOO;
public $options = [self::FOO => "bar"];
}
try {
var_dump((new C)->options);
} catch (Throwable $e) {}
var_dump((new C)->options);
?>
--EXPECTF--
Fatal error: Uncaught Error: Undefined class constant 'I::FOO' in %sbug74657.php:%d
Stack trace:
#0 {main}
thrown in %sbug74657.php on line %d

View File

@ -0,0 +1,29 @@
--TEST--
Bug #74606 (Segfault within try/catch/finally nesting in Generators)
--FILE--
<?php
function gen() {
$array = ["foo"];
$array[] = "bar";
foreach ($array as $item) {
try {
try {
yield;
} finally {
echo "fin $item\n";
}
} catch (\Exception $e) {
echo "catch\n";
continue;
}
}
}
gen()->throw(new Exception);
?>
--EXPECT--
fin foo
catch
fin bar

View File

@ -14,4 +14,4 @@ namespace Fiz\Biz\Buz {
}
?>
--EXPECTF--
Parse error: syntax error, unexpected '{', expecting ',' or '}' in %sns_088.php on line 5
Parse error: syntax error, unexpected '{', expecting '}' in %sns_088.php on line 5

View File

@ -12,4 +12,4 @@ use const Foo\Bar\{
};
--EXPECTF--
Parse error: syntax error, unexpected 'const' (T_CONST), expecting identifier (T_STRING) in %s on line 7
Parse error: syntax error, unexpected 'const' (T_CONST), expecting '}' in %s on line 7

View File

@ -0,0 +1,30 @@
--TEST--
Mixed group use declaration can contain trailing comma
--FILE--
<?php
namespace Foo {
const FOO_CONST = "Foo const\n";
function foo_func() {
echo "Foo func\n";
}
class FooClass {
function __construct() {
echo "Foo class\n";
}
}
}
namespace {
use Foo\{
const FOO_CONST,
function foo_func,
FooClass as BarClass,
};
echo FOO_CONST;
foo_func();
new BarClass;
}
?>
--EXPECT--
Foo const
Foo func
Foo class

View File

@ -0,0 +1,52 @@
--TEST--
Unmixed group use declaration can contain trailing comma
--FILE--
<?php
namespace Foo {
const FOO_CONST_1 = "Foo const 1\n";
const FOO_CONST_2 = "Foo const 2\n";
}
namespace Bar {
function foo_func_1() {
echo "Bar func 1\n";
}
function foo_func_2() {
echo "Bar func 2\n";
}
}
namespace Baz {
class BazFooClass {
function __construct() { echo "BazFoo class\n"; }
}
class BazBarClass {
function __construct() { echo "BazBar class\n"; }
}
}
namespace {
use const Foo\{
FOO_CONST_1,
FOO_CONST_2,
};
use function Bar\{
foo_func_1,
foo_func_2,
};
use Baz\{
BazFooClass,
BazBarClass,
};
echo FOO_CONST_1;
echo FOO_CONST_2;
foo_func_1();
foo_func_2();
new BazFooClass;
new BazBarClass;
}
?>
--EXPECT--
Foo const 1
Foo const 2
Bar func 1
Bar func 2
BazFoo class
BazBar class

View File

@ -0,0 +1,8 @@
--TEST--
Group use declarations mustn't be empty
--FILE--
<?php
use Baz\{};
?>
--EXPECTF--
Parse error: syntax error, unexpected '}', expecting identifier (T_STRING) or function (T_FUNCTION) or const (T_CONST) in %s on line %d

View File

@ -0,0 +1,8 @@
--TEST--
Group use declarations mustn't contain just a comma
--FILE--
<?php
use Baz\{,};
?>
--EXPECTF--
Parse error: syntax error, unexpected ',', expecting identifier (T_STRING) or function (T_FUNCTION) or const (T_CONST) in %s on line %d

View File

@ -0,0 +1,8 @@
--TEST--
Group use declarations mustn't allow more than one comma
--FILE--
<?php
use Baz\{Foo,,};
?>
--EXPECTF--
Parse error: syntax error, unexpected ',', expecting '}' in %s on line %d

View File

@ -0,0 +1,8 @@
--TEST--
Group use declarations mustn't begin with a comma
--FILE--
<?php
use Baz\{,Foo};
?>
--EXPECTF--
Parse error: syntax error, unexpected ',', expecting identifier (T_STRING) or function (T_FUNCTION) or const (T_CONST) in %s on line %d

View File

@ -0,0 +1,8 @@
--TEST--
Group use declarations mustn't contain two commas mid-list
--FILE--
<?php
use Baz\{Foo,,Bar};
?>
--EXPECTF--
Parse error: syntax error, unexpected ',', expecting '}' in %s on line %d

View File

@ -0,0 +1,8 @@
--TEST--
Unmixed group use declarations mustn't allow more than one comma
--FILE--
<?php
use const Baz\{Foo,,};
?>
--EXPECTF--
Parse error: syntax error, unexpected ',', expecting '}' in %s on line %d

View File

@ -0,0 +1,8 @@
--TEST--
Unmixed group use declarations mustn't begin with a comma
--FILE--
<?php
use function Baz\{,Foo};
?>
--EXPECTF--
Parse error: syntax error, unexpected ',', expecting identifier (T_STRING) in %s on line %d

View File

@ -0,0 +1,8 @@
--TEST--
Unmixed group use declarations mustn't contain two commas mid-list
--FILE--
<?php
use const Baz\{Foo,,Bar};
?>
--EXPECTF--
Parse error: syntax error, unexpected ',', expecting '}' in %s on line %d

View File

@ -202,6 +202,36 @@ ZEND_API char *zend_zval_type_name(const zval *arg) /* {{{ */
}
/* }}} */
ZEND_API zend_string *zend_zval_get_type(const zval *arg) /* {{{ */
{
switch (Z_TYPE_P(arg)) {
case IS_NULL:
return ZSTR_KNOWN(ZEND_STR_NULL);
case IS_FALSE:
case IS_TRUE:
return ZSTR_KNOWN(ZEND_STR_BOOLEAN);
case IS_LONG:
return ZSTR_KNOWN(ZEND_STR_INTEGER);
case IS_DOUBLE:
return ZSTR_KNOWN(ZEND_STR_DOUBLE);
case IS_STRING:
return ZSTR_KNOWN(ZEND_STR_STRING);
case IS_ARRAY:
return ZSTR_KNOWN(ZEND_STR_ARRAY);
case IS_OBJECT:
return ZSTR_KNOWN(ZEND_STR_OBJECT);
case IS_RESOURCE:
if (zend_rsrc_list_get_rsrc_type(Z_RES_P(arg))) {
return ZSTR_KNOWN(ZEND_STR_RESOURCE);
} else {
return ZSTR_KNOWN(ZEND_STR_CLOSED_RESOURCE);
}
default:
return NULL;
}
}
/* }}} */
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameters_count_error(zend_bool throw_, int num_args, int min_num_args, int max_num_args) /* {{{ */
{
zend_function *active_function = EG(current_execute_data)->func;
@ -1088,8 +1118,6 @@ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties) /* {{{ */
ZEND_API int zend_update_class_constants(zend_class_entry *class_type) /* {{{ */
{
if (!(class_type->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) {
class_type->ce_flags |= ZEND_ACC_CONSTANTS_UPDATED;
if (class_type->parent) {
if (UNEXPECTED(zend_update_class_constants(class_type->parent) != SUCCESS)) {
return FAILURE;
@ -1158,7 +1186,9 @@ ZEND_API int zend_update_class_constants(zend_class_entry *class_type) /* {{{ */
ce = ce->parent;
}
}
class_type->ce_flags |= ZEND_ACC_CONSTANTS_UPDATED;
}
return SUCCESS;
}
/* }}} */

View File

@ -268,6 +268,8 @@ ZEND_API int zend_copy_parameters_array(int param_count, zval *argument_array);
_zend_get_parameters_array_ex(param_count, argument_array)
#define zend_parse_parameters_none() \
(EXPECTED(ZEND_NUM_ARGS() == 0) ? SUCCESS : zend_parse_parameters(ZEND_NUM_ARGS(), ""))
#define zend_parse_parameters_none_throw() \
(EXPECTED(ZEND_NUM_ARGS() == 0) ? SUCCESS : zend_parse_parameters_throw(ZEND_NUM_ARGS(), ""))
/* Parameter parsing API -- andrei */
@ -277,6 +279,7 @@ ZEND_API int zend_parse_parameters(int num_args, const char *type_spec, ...);
ZEND_API int zend_parse_parameters_ex(int flags, int num_args, const char *type_spec, ...);
ZEND_API int zend_parse_parameters_throw(int num_args, const char *type_spec, ...);
ZEND_API char *zend_zval_type_name(const zval *arg);
ZEND_API zend_string *zend_zval_get_type(const zval *arg);
ZEND_API int zend_parse_method_parameters(int num_args, zval *this_ptr, const char *type_spec, ...);
ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args, zval *this_ptr, const char *type_spec, ...);

View File

@ -839,7 +839,7 @@ repeat:
RETURN_FALSE;
}
ZVAL_DUP(&c.value, val);
ZVAL_COPY(&c.value, val);
zval_ptr_dtor(&val_free);
register_constant:
c.flags = case_sensitive; /* non persistent */

View File

@ -87,6 +87,7 @@ ZEND_API zend_executor_globals executor_globals;
#endif
static zend_op *zend_emit_op(znode *result, zend_uchar opcode, znode *op1, znode *op2);
static zend_bool zend_try_ct_eval_array(zval *result, zend_ast *ast);
static void zend_destroy_property_info_internal(zval *zv) /* {{{ */
{
@ -184,7 +185,7 @@ static zend_bool zend_is_reserved_class_name(const zend_string *name) /* {{{ */
}
/* }}} */
ZEND_API void zend_assert_valid_class_name(const zend_string *name) /* {{{ */
void zend_assert_valid_class_name(const zend_string *name) /* {{{ */
{
if (zend_is_reserved_class_name(name)) {
zend_error_noreturn(E_COMPILE_ERROR,
@ -2224,6 +2225,7 @@ ZEND_API int zend_is_smart_branch(zend_op *opline) /* {{{ */
case ZEND_INSTANCEOF:
case ZEND_TYPE_CHECK:
case ZEND_DEFINED:
case ZEND_IN_ARRAY:
return 1;
default:
return 0;
@ -3635,6 +3637,149 @@ static int zend_compile_assert(znode *result, zend_ast_list *args, zend_string *
}
/* }}} */
static int zend_compile_func_in_array(znode *result, zend_ast_list *args) /* {{{ */
{
zend_bool strict = 0;
znode array, needly;
zend_op *opline;
if (args->children == 3) {
if (args->child[2]->kind == ZEND_AST_ZVAL) {
strict = zend_is_true(zend_ast_get_zval(args->child[2]));
} else if (args->child[2]->kind == ZEND_AST_CONST) {
zval value;
zend_ast *name_ast = args->child[2]->child[0];
zend_bool is_fully_qualified;
zend_string *resolved_name = zend_resolve_const_name(
zend_ast_get_str(name_ast), name_ast->attr, &is_fully_qualified);
if (!zend_try_ct_eval_const(&value, resolved_name, is_fully_qualified)) {
zend_string_release(resolved_name);
return FAILURE;
}
zend_string_release(resolved_name);
strict = zend_is_true(&value);
zval_ptr_dtor(&value);
} else {
return FAILURE;
}
} else if (args->children != 2) {
return FAILURE;
}
if (args->child[1]->kind != ZEND_AST_ARRAY
|| !zend_try_ct_eval_array(&array.u.constant, args->child[1])) {
return FAILURE;
}
if (zend_hash_num_elements(Z_ARRVAL(array.u.constant)) > 0) {
zend_bool ok = 1;
zval *val, tmp;
HashTable *src = Z_ARRVAL(array.u.constant);
HashTable *dst = emalloc(sizeof(HashTable));
zend_hash_init(dst, zend_hash_num_elements(src), NULL, ZVAL_PTR_DTOR, 0);
ZVAL_TRUE(&tmp);
if (strict) {
ZEND_HASH_FOREACH_VAL(src, val) {
if (Z_TYPE_P(val) == IS_STRING) {
zend_hash_add(dst, Z_STR_P(val), &tmp);
} else if (Z_TYPE_P(val) == IS_LONG) {
zend_hash_index_add(dst, Z_LVAL_P(val), &tmp);
} else {
zend_array_destroy(dst);
ok = 0;
break;
}
} ZEND_HASH_FOREACH_END();
} else {
ZEND_HASH_FOREACH_VAL(src, val) {
if (Z_TYPE_P(val) != IS_STRING
|| is_numeric_string(Z_STRVAL_P(val), Z_STRLEN_P(val), NULL, NULL, 0)) {
zend_array_destroy(dst);
ok = 0;
break;
}
zend_hash_add(dst, Z_STR_P(val), &tmp);
} ZEND_HASH_FOREACH_END();
}
zend_array_destroy(src);
if (!ok) {
return FAILURE;
}
Z_ARRVAL(array.u.constant) = dst;
}
array.op_type = IS_CONST;
zend_compile_expr(&needly, args->child[0]);
opline = zend_emit_op_tmp(result, ZEND_IN_ARRAY, &needly, &array);
opline->extended_value = strict;
return SUCCESS;
}
/* }}} */
int zend_compile_func_count(znode *result, zend_ast_list *args) /* {{{ */
{
znode arg_node;
if (args->children != 1 || args->child[0]->kind == ZEND_AST_UNPACK) {
return FAILURE;
}
zend_compile_expr(&arg_node, args->child[0]);
zend_emit_op_tmp(result, ZEND_COUNT, &arg_node, NULL);
return SUCCESS;
}
/* }}} */
int zend_compile_func_get_class(znode *result, zend_ast_list *args) /* {{{ */
{
if (args->children == 0) {
zend_emit_op_tmp(result, ZEND_GET_CLASS, NULL, NULL);
} else {
znode arg_node;
if (args->children != 1 || args->child[0]->kind == ZEND_AST_UNPACK) {
return FAILURE;
}
zend_compile_expr(&arg_node, args->child[0]);
zend_emit_op_tmp(result, ZEND_GET_CLASS, &arg_node, NULL);
}
return SUCCESS;
}
/* }}} */
int zend_compile_func_get_called_class(znode *result, zend_ast_list *args) /* {{{ */
{
if (args->children != 0) {
return FAILURE;
}
zend_emit_op_tmp(result, ZEND_GET_CALLED_CLASS, NULL, NULL);
return SUCCESS;
}
/* }}} */
int zend_compile_func_gettype(znode *result, zend_ast_list *args) /* {{{ */
{
znode arg_node;
if (args->children != 1 || args->child[0]->kind == ZEND_AST_UNPACK) {
return FAILURE;
}
zend_compile_expr(&arg_node, args->child[0]);
zend_emit_op_tmp(result, ZEND_GET_TYPE, &arg_node, NULL);
return SUCCESS;
}
/* }}} */
int zend_try_compile_special_func(znode *result, zend_string *lcname, zend_ast_list *args, zend_function *fbc, uint32_t type) /* {{{ */
{
if (fbc->internal_function.handler == ZEND_FN(display_disabled_function)) {
@ -3693,6 +3838,16 @@ int zend_try_compile_special_func(znode *result, zend_string *lcname, zend_ast_l
return zend_compile_func_cufa(result, args, lcname);
} else if (zend_string_equals_literal(lcname, "call_user_func")) {
return zend_compile_func_cuf(result, args, lcname);
} else if (zend_string_equals_literal(lcname, "in_array")) {
return zend_compile_func_in_array(result, args);
} else if (zend_string_equals_literal(lcname, "count")) {
return zend_compile_func_count(result, args);
} else if (zend_string_equals_literal(lcname, "get_class")) {
return zend_compile_func_get_class(result, args);
} else if (zend_string_equals_literal(lcname, "get_called_class")) {
return zend_compile_func_get_called_class(result, args);
} else if (zend_string_equals_literal(lcname, "gettype")) {
return zend_compile_func_gettype(result, args);
} else {
return FAILURE;
}
@ -6502,7 +6657,11 @@ static zend_bool zend_try_ct_eval_magic_const(zval *zv, zend_ast *ast) /* {{{ */
{
zend_string *filename = CG(compiled_filename);
zend_string *dirname = zend_string_init(ZSTR_VAL(filename), ZSTR_LEN(filename), 0);
zend_dirname(ZSTR_VAL(dirname), ZSTR_LEN(dirname));
#ifdef ZEND_WIN32
ZSTR_LEN(dirname) = php_win32_ioutil_dirname(ZSTR_VAL(dirname), ZSTR_LEN(dirname));
#else
ZSTR_LEN(dirname) = zend_dirname(ZSTR_VAL(dirname), ZSTR_LEN(dirname));
#endif
if (strcmp(ZSTR_VAL(dirname), ".") == 0) {
dirname = zend_string_extend(dirname, MAXPATHLEN, 0);
@ -6511,9 +6670,9 @@ static zend_bool zend_try_ct_eval_magic_const(zval *zv, zend_ast *ast) /* {{{ */
#elif HAVE_GETWD
ZEND_IGNORE_VALUE(VCWD_GETWD(ZSTR_VAL(dirname)));
#endif
ZSTR_LEN(dirname) = strlen(ZSTR_VAL(dirname));
}
ZSTR_LEN(dirname) = strlen(ZSTR_VAL(dirname));
ZVAL_STR(zv, dirname);
break;
}
@ -7294,6 +7453,9 @@ void zend_compile_array(znode *result, zend_ast *ast) /* {{{ */
return;
}
/* Empty arrays are handled at compile-time */
ZEND_ASSERT(list->children > 0);
for (i = 0; i < list->children; ++i) {
zend_ast *elem_ast = list->child[i];
zend_ast *value_ast, *key_ast;
@ -7337,11 +7499,6 @@ void zend_compile_array(znode *result, zend_ast *ast) /* {{{ */
}
}
/* Handle empty array */
if (!list->children) {
zend_emit_op_tmp(result, ZEND_INIT_ARRAY, NULL, NULL);
}
/* Add a flag to INIT_ARRAY if we know this array cannot be packed */
if (!packed) {
ZEND_ASSERT(opnum_init != (uint32_t)-1);
@ -7421,8 +7578,11 @@ void zend_compile_class_const(znode *result, zend_ast *ast) /* {{{ */
return;
}
zend_eval_const_expr(&class_ast);
zend_eval_const_expr(&const_ast);
zend_eval_const_expr(&ast->child[0]);
zend_eval_const_expr(&ast->child[1]);
class_ast = ast->child[0];
const_ast = ast->child[1];
if (class_ast->kind == ZEND_AST_ZVAL) {
zend_string *resolved_name;
@ -8356,8 +8516,11 @@ void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
break;
}
zend_eval_const_expr(&class_ast);
zend_eval_const_expr(&name_ast);
zend_eval_const_expr(&ast->child[0]);
zend_eval_const_expr(&ast->child[1]);
class_ast = ast->child[0];
name_ast = ast->child[1];
if (name_ast->kind == ZEND_AST_ZVAL && zend_string_equals_literal_ci(zend_ast_get_str(name_ast), "class")) {
zend_error_noreturn(E_COMPILE_ERROR,

View File

@ -827,7 +827,7 @@ int zendlex(zend_parser_stack_elem *elem);
int zend_add_literal(zend_op_array *op_array, zval *zv);
ZEND_API void zend_assert_valid_class_name(const zend_string *const_name);
void zend_assert_valid_class_name(const zend_string *const_name);
/* BEGIN: OPCODES */

View File

@ -1974,7 +1974,8 @@ static zend_always_inline zval* zend_fetch_static_property_address(zend_execute_
ce = Z_CE_P(EX_VAR(op2.var));
}
if (varname_type == IS_CONST &&
(retval = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(varname), ce)) != NULL) {
EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(varname)) == ce)) {
retval = CACHED_PTR(Z_CACHE_SLOT_P(varname) + sizeof(void*));
/* check if static properties were destoyed */
if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {

View File

@ -997,10 +997,8 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *k
}
/* Verify class name before passing it to __autoload() */
if (strspn(ZSTR_VAL(name), "0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377\\") != ZSTR_LEN(name)) {
if (!key) {
zend_string_release(lc_name);
}
if (!key && strspn(ZSTR_VAL(name), "0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377\\") != ZSTR_LEN(name)) {
zend_string_release(lc_name);
return NULL;
}

View File

@ -108,7 +108,7 @@ static void zend_generator_cleanup_unfinished_execution(
if (UNEXPECTED(generator->frozen_call_stack)) {
zend_generator_restore_call_stack(generator);
}
zend_cleanup_unfinished_execution(execute_data, op_num, 0);
zend_cleanup_unfinished_execution(execute_data, op_num, catch_op_num);
}
}
/* }}} */

View File

@ -23,7 +23,7 @@
#include "zend_execute.h"
#include "zend_inheritance.h"
#include "zend_smart_str.h"
#include "zend_inheritance.h"
#include "zend_operators.h"
static void overriden_ptr_dtor(zval *zv) /* {{{ */
{
@ -188,12 +188,14 @@ static int zend_do_perform_type_hint_check(const zend_function *fe, zend_arg_inf
if (ZEND_TYPE_IS_CLASS(fe_arg_info->type) && ZEND_TYPE_IS_CLASS(proto_arg_info->type)) {
zend_string *fe_class_name, *proto_class_name;
const char *class_name;
size_t class_name_len;
fe_class_name = ZEND_TYPE_NAME(fe_arg_info->type);
class_name = ZSTR_VAL(fe_class_name);
if (!strcasecmp(class_name, "parent") && proto->common.scope) {
class_name_len = ZSTR_LEN(fe_class_name);
if (class_name_len == sizeof("parent")-1 && !strcasecmp(class_name, "parent") && proto->common.scope) {
fe_class_name = zend_string_copy(proto->common.scope->name);
} else if (!strcasecmp(class_name, "self") && fe->common.scope) {
} else if (class_name_len == sizeof("self")-1 && !strcasecmp(class_name, "self") && fe->common.scope) {
fe_class_name = zend_string_copy(fe->common.scope->name);
} else {
zend_string_addref(fe_class_name);
@ -201,15 +203,16 @@ static int zend_do_perform_type_hint_check(const zend_function *fe, zend_arg_inf
proto_class_name = ZEND_TYPE_NAME(proto_arg_info->type);
class_name = ZSTR_VAL(proto_class_name);
if (!strcasecmp(class_name, "parent") && proto->common.scope && proto->common.scope->parent) {
class_name_len = ZSTR_LEN(proto_class_name);
if (class_name_len == sizeof("parent")-1 && !strcasecmp(class_name, "parent") && proto->common.scope && proto->common.scope->parent) {
proto_class_name = zend_string_copy(proto->common.scope->parent->name);
} else if (!strcasecmp(class_name, "self") && proto->common.scope) {
} else if (class_name_len == sizeof("self")-1 && !strcasecmp(class_name, "self") && proto->common.scope) {
proto_class_name = zend_string_copy(proto->common.scope->name);
} else {
zend_string_addref(proto_class_name);
}
if (strcasecmp(ZSTR_VAL(fe_class_name), ZSTR_VAL(proto_class_name)) != 0) {
if (fe_class_name != proto_class_name && strcasecmp(ZSTR_VAL(fe_class_name), ZSTR_VAL(proto_class_name)) != 0) {
if (fe->common.type != ZEND_USER_FUNCTION) {
zend_string_release(proto_class_name);
zend_string_release(fe_class_name);
@ -548,16 +551,6 @@ static void do_inheritance_check_on_method(zend_function *child, zend_function *
uint32_t child_flags;
uint32_t parent_flags = parent->common.fn_flags;
if ((parent->common.scope->ce_flags & ZEND_ACC_INTERFACE) == 0
&& parent->common.fn_flags & ZEND_ACC_ABSTRACT
&& parent->common.scope != (child->common.prototype ? child->common.prototype->common.scope : child->common.scope)
&& child->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_IMPLEMENTED_ABSTRACT)) {
zend_error_noreturn(E_COMPILE_ERROR, "Can't inherit abstract function %s::%s() (previously declared abstract in %s)",
ZSTR_VAL(parent->common.scope->name),
ZSTR_VAL(child->common.function_name),
child->common.prototype ? ZSTR_VAL(child->common.prototype->common.scope->name) : ZSTR_VAL(child->common.scope->name));
}
if (UNEXPECTED(parent_flags & ZEND_ACC_FINAL)) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot override final method %s::%s()", ZEND_FN_SCOPE_NAME(parent), ZSTR_VAL(child->common.function_name));
}
@ -578,8 +571,9 @@ static void do_inheritance_check_on_method(zend_function *child, zend_function *
zend_error_noreturn(E_COMPILE_ERROR, "Cannot make non abstract method %s::%s() abstract in class %s", ZEND_FN_SCOPE_NAME(parent), ZSTR_VAL(child->common.function_name), ZEND_FN_SCOPE_NAME(child));
}
/* Prevent derived classes from restricting access that was available in parent classes */
if (UNEXPECTED((child_flags & ZEND_ACC_PPP_MASK) > (parent_flags & ZEND_ACC_PPP_MASK))) {
/* Prevent derived classes from restricting access that was available in parent classes (except deriving from non-abstract ctors) */
if (UNEXPECTED((!(child_flags & ZEND_ACC_CTOR) || (parent_flags & (ZEND_ACC_ABSTRACT | ZEND_ACC_IMPLEMENTED_ABSTRACT))) &&
(child_flags & ZEND_ACC_PPP_MASK) > (parent_flags & ZEND_ACC_PPP_MASK))) {
zend_error_noreturn(E_COMPILE_ERROR, "Access level to %s::%s() must be %s (as in class %s)%s", ZEND_FN_SCOPE_NAME(child), ZSTR_VAL(child->common.function_name), zend_visibility_string(parent_flags), ZEND_FN_SCOPE_NAME(parent), (parent_flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
}
@ -1531,7 +1525,6 @@ static void zend_do_traits_property_binding(zend_class_entry *ce) /* {{{ */
size_t i;
zend_property_info *property_info;
zend_property_info *coliding_prop;
zval compare_result;
zend_string* prop_name;
const char* class_name_unused;
zend_bool not_compatible;
@ -1576,15 +1569,11 @@ static void zend_do_traits_property_binding(zend_class_entry *ce) /* {{{ */
== (flags & (ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC))) {
/* flags are identical, now the value needs to be checked */
if (flags & ZEND_ACC_STATIC) {
not_compatible = (FAILURE == compare_function(&compare_result,
&ce->default_static_members_table[coliding_prop->offset],
&ce->traits[i]->default_static_members_table[property_info->offset]))
|| (Z_LVAL(compare_result) != 0);
not_compatible = fast_is_not_identical_function(&ce->default_static_members_table[coliding_prop->offset],
&ce->traits[i]->default_static_members_table[property_info->offset]);
} else {
not_compatible = (FAILURE == compare_function(&compare_result,
&ce->default_properties_table[OBJ_PROP_TO_NUM(coliding_prop->offset)],
&ce->traits[i]->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)]))
|| (Z_LVAL(compare_result) != 0);
not_compatible = fast_is_not_identical_function(&ce->default_properties_table[OBJ_PROP_TO_NUM(coliding_prop->offset)],
&ce->traits[i]->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)]);
}
} else {
/* the flags are not identical, thus, we assume properties are not compatible */

View File

@ -28,6 +28,7 @@ ZEND_API zend_class_entry *zend_ce_aggregate;
ZEND_API zend_class_entry *zend_ce_iterator;
ZEND_API zend_class_entry *zend_ce_arrayaccess;
ZEND_API zend_class_entry *zend_ce_serializable;
ZEND_API zend_class_entry *zend_ce_countable;
/* {{{ zend_call_method
Only returns the returned zval if retval_ptr != NULL */
@ -470,6 +471,13 @@ static int zend_implement_serializable(zend_class_entry *interface, zend_class_e
}
/* }}}*/
/* {{{ zend_implement_countable */
static int zend_implement_countable(zend_class_entry *interface, zend_class_entry *class_type)
{
return SUCCESS;
}
/* }}}*/
/* {{{ function tables */
const zend_function_entry zend_funcs_aggregate[] = {
ZEND_ABSTRACT_ME(iterator, getIterator, NULL)
@ -517,6 +525,14 @@ const zend_function_entry zend_funcs_serializable[] = {
ZEND_FENTRY(unserialize, NULL, arginfo_serializable_serialize, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT|ZEND_ACC_CTOR)
ZEND_FE_END
};
ZEND_BEGIN_ARG_INFO(arginfo_countable_count, 0)
ZEND_END_ARG_INFO()
const zend_function_entry zend_funcs_countable[] = {
ZEND_ABSTRACT_ME(Countable, count, arginfo_countable_count)
ZEND_FE_END
};
/* }}} */
/* {{{ zend_register_interfaces */
@ -533,6 +549,8 @@ ZEND_API void zend_register_interfaces(void)
REGISTER_MAGIC_INTERFACE(arrayaccess, ArrayAccess);
REGISTER_MAGIC_INTERFACE(serializable, Serializable);
REGISTER_MAGIC_INTERFACE(countable, Countable);
}
/* }}} */

View File

@ -31,6 +31,7 @@ extern ZEND_API zend_class_entry *zend_ce_aggregate;
extern ZEND_API zend_class_entry *zend_ce_iterator;
extern ZEND_API zend_class_entry *zend_ce_arrayaccess;
extern ZEND_API zend_class_entry *zend_ce_serializable;
extern ZEND_API zend_class_entry *zend_ce_countable;
typedef struct _zend_user_iterator {
zend_object_iterator it;

View File

@ -338,19 +338,24 @@ use_type:
;
group_use_declaration:
namespace_name T_NS_SEPARATOR '{' unprefixed_use_declarations '}'
namespace_name T_NS_SEPARATOR '{' unprefixed_use_declarations possible_comma '}'
{ $$ = zend_ast_create(ZEND_AST_GROUP_USE, $1, $4); }
| T_NS_SEPARATOR namespace_name T_NS_SEPARATOR '{' unprefixed_use_declarations '}'
| T_NS_SEPARATOR namespace_name T_NS_SEPARATOR '{' unprefixed_use_declarations possible_comma '}'
{ $$ = zend_ast_create(ZEND_AST_GROUP_USE, $2, $5); }
;
mixed_group_use_declaration:
namespace_name T_NS_SEPARATOR '{' inline_use_declarations '}'
namespace_name T_NS_SEPARATOR '{' inline_use_declarations possible_comma '}'
{ $$ = zend_ast_create(ZEND_AST_GROUP_USE, $1, $4);}
| T_NS_SEPARATOR namespace_name T_NS_SEPARATOR '{' inline_use_declarations '}'
| T_NS_SEPARATOR namespace_name T_NS_SEPARATOR '{' inline_use_declarations possible_comma '}'
{ $$ = zend_ast_create(ZEND_AST_GROUP_USE, $2, $5); }
;
possible_comma:
/* empty */
| ','
;
inline_use_declarations:
inline_use_declarations ',' inline_use_declaration
{ $$ = zend_ast_list_add($1, $3); }

View File

@ -29,24 +29,14 @@
ZEND_API void zend_object_std_init(zend_object *object, zend_class_entry *ce)
{
zval *p, *end;
GC_REFCOUNT(object) = 1;
GC_TYPE_INFO(object) = IS_OBJECT | (GC_COLLECTABLE << GC_FLAGS_SHIFT);
object->ce = ce;
object->properties = NULL;
zend_objects_store_put(object);
p = object->properties_table;
if (EXPECTED(ce->default_properties_count != 0)) {
end = p + ce->default_properties_count;
do {
ZVAL_UNDEF(p);
p++;
} while (p != end);
}
if (UNEXPECTED(ce->ce_flags & ZEND_ACC_USE_GUARDS)) {
GC_FLAGS(object) |= IS_OBJ_USE_GUARDS;
ZVAL_UNDEF(p);
ZVAL_UNDEF(object->properties_table + object->ce->default_properties_count);
}
}
@ -252,6 +242,16 @@ ZEND_API zend_object *zend_objects_clone_obj(zval *zobject)
old_object = Z_OBJ_P(zobject);
new_object = zend_objects_new(old_object->ce);
/* zend_objects_clone_members() expect the properties to be initialized. */
if (new_object->ce->default_properties_count) {
zval *p = new_object->properties_table;
zval *end = p + new_object->ce->default_properties_count;
do {
ZVAL_UNDEF(p);
p++;
} while (p != end);
}
zend_objects_clone_members(new_object, old_object);
return new_object;

View File

@ -152,18 +152,12 @@ ZEND_API void zend_objects_store_del(zend_object *object) /* {{{ */
if (EG(objects_store).object_buckets &&
IS_OBJ_VALID(EG(objects_store).object_buckets[object->handle])) {
if (GC_REFCOUNT(object) == 0) {
int failure = 0;
if (!(GC_FLAGS(object) & IS_OBJ_DESTRUCTOR_CALLED)) {
GC_FLAGS(object) |= IS_OBJ_DESTRUCTOR_CALLED;
if (object->handlers->dtor_obj) {
GC_REFCOUNT(object)++;
zend_try {
object->handlers->dtor_obj(object);
} zend_catch {
failure = 1;
} zend_end_try();
object->handlers->dtor_obj(object);
GC_REFCOUNT(object)--;
}
}
@ -176,13 +170,9 @@ ZEND_API void zend_objects_store_del(zend_object *object) /* {{{ */
if (!(GC_FLAGS(object) & IS_OBJ_FREE_CALLED)) {
GC_FLAGS(object) |= IS_OBJ_FREE_CALLED;
if (object->handlers->free_obj) {
zend_try {
GC_REFCOUNT(object)++;
object->handlers->free_obj(object);
GC_REFCOUNT(object)--;
} zend_catch {
failure = 1;
} zend_end_try();
GC_REFCOUNT(object)++;
object->handlers->free_obj(object);
GC_REFCOUNT(object)--;
}
}
ptr = ((char*)object) - object->handlers->offset;
@ -190,10 +180,6 @@ ZEND_API void zend_objects_store_del(zend_object *object) /* {{{ */
efree(ptr);
ZEND_OBJECTS_STORE_ADD_TO_FREE_LIST(handle);
}
if (failure) {
zend_bailout();
}
} else {
GC_REFCOUNT(object)--;
}

View File

@ -537,7 +537,7 @@ try_again:
break;
}
case IS_LONG: {
ZVAL_NEW_STR(op, zend_long_to_str(Z_LVAL_P(op)));
ZVAL_STR(op, zend_long_to_str(Z_LVAL_P(op)));
break;
}
case IS_DOUBLE: {
@ -2856,9 +2856,13 @@ ZEND_API void ZEND_FASTCALL zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_D
ZEND_API zend_string* ZEND_FASTCALL zend_long_to_str(zend_long num) /* {{{ */
{
char buf[MAX_LENGTH_OF_LONG + 1];
char *res = zend_print_long_to_buf(buf + sizeof(buf) - 1, num);
return zend_string_init(res, buf + sizeof(buf) - 1 - res, 0);
if ((zend_ulong)num <= 9) {
return ZSTR_CHAR((zend_uchar)'0' + (zend_uchar)num);
} else {
char buf[MAX_LENGTH_OF_LONG + 1];
char *res = zend_print_long_to_buf(buf + sizeof(buf) - 1, num);
return zend_string_init(res, buf + sizeof(buf) - 1 - res, 0);
}
}
/* }}} */

View File

@ -408,6 +408,21 @@ EMPTY_SWITCH_DEFAULT_CASE()
_(ZEND_STR_SEVERITY, "severity") \
_(ZEND_STR_STRING, "string") \
_(ZEND_STR_TRACE, "trace") \
_(ZEND_STR_SCHEME, "scheme") \
_(ZEND_STR_HOST, "host") \
_(ZEND_STR_PORT, "port") \
_(ZEND_STR_USER, "user") \
_(ZEND_STR_PASS, "pass") \
_(ZEND_STR_PATH, "path") \
_(ZEND_STR_QUERY, "query") \
_(ZEND_STR_FRAGMENT, "fragment") \
_(ZEND_STR_NULL, "NULL") \
_(ZEND_STR_BOOLEAN, "boolean") \
_(ZEND_STR_INTEGER, "integer") \
_(ZEND_STR_DOUBLE, "double") \
_(ZEND_STR_ARRAY, "array") \
_(ZEND_STR_RESOURCE, "resource") \
_(ZEND_STR_CLOSED_RESOURCE, "resource (closed)") \
typedef enum _zend_known_string_id {

View File

@ -535,6 +535,12 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) {
#define Z_COPYABLE(zval) ((Z_TYPE_FLAGS(zval) & IS_TYPE_COPYABLE) != 0)
#define Z_COPYABLE_P(zval_p) Z_COPYABLE(*(zval_p))
/* deprecated: (IMMUTABLE is the same as COPYABLE && !REFCOUED) */
#define Z_IMMUTABLE(zval) ((Z_TYPE_FLAGS(zval) & (IS_TYPE_REFCOUNTED|IS_TYPE_COPYABLE)) == IS_TYPE_COPYABLE)
#define Z_IMMUTABLE_P(zval_p) Z_IMMUTABLE(*(zval_p))
#define Z_OPT_IMMUTABLE(zval) Z_IMMUTABLE(zval_p)
#define Z_OPT_IMMUTABLE_P(zval_p) Z_IMMUTABLE(*(zval_p))
/* the following Z_OPT_* macros make better code when Z_TYPE_INFO accessed before */
#define Z_OPT_TYPE(zval) (Z_TYPE_INFO(zval) & Z_TYPE_MASK)
#define Z_OPT_TYPE_P(zval_p) Z_OPT_TYPE(*(zval_p))

View File

@ -525,7 +525,8 @@ CWD_API char *virtual_getcwd(char *buf, size_t size) /* {{{ */
static inline zend_ulong realpath_cache_key(const char *path, size_t path_len) /* {{{ */
{
register zend_ulong h;
char *bucket_key_start = tsrm_win32_get_path_sid_key(path);
size_t bucket_key_len;
char *bucket_key_start = tsrm_win32_get_path_sid_key(path, path_len, &bucket_key_len);
char *bucket_key = (char *)bucket_key_start;
const char *e;
@ -533,12 +534,14 @@ static inline zend_ulong realpath_cache_key(const char *path, size_t path_len) /
return 0;
}
e = bucket_key + strlen(bucket_key);
e = bucket_key + bucket_key_len;
for (h = Z_UL(2166136261); bucket_key < e;) {
h *= Z_UL(16777619);
h ^= *bucket_key++;
}
HeapFree(GetProcessHeap(), 0, (LPVOID)bucket_key_start);
if (bucket_key_start != path) {
HeapFree(GetProcessHeap(), 0, (LPVOID)bucket_key_start);
}
return h;
}
/* }}} */

View File

@ -28,7 +28,10 @@ ZEND_API void zend_vm_set_opcode_handler(zend_op* opcode);
ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* opcode, uint32_t op1_info, uint32_t op2_info, uint32_t res_info);
ZEND_API void zend_serialize_opcode_handler(zend_op *op);
ZEND_API void zend_deserialize_opcode_handler(zend_op *op);
ZEND_API const void *zend_get_opcode_handler_func(const zend_op *op);
ZEND_API const zend_op *zend_get_halt_op(void);
ZEND_API int zend_vm_call_opcode_handler(zend_execute_data *ex);
ZEND_API int zend_vm_kind(void);
END_EXTERN_C()

View File

@ -2478,7 +2478,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
}
}
ZEND_VM_HANDLER(42, ZEND_JMP, JMP_ADDR, ANY)
ZEND_VM_HOT_HANDLER(42, ZEND_JMP, JMP_ADDR, ANY)
{
USE_OPLINE
@ -2486,7 +2486,7 @@ ZEND_VM_HANDLER(42, ZEND_JMP, JMP_ADDR, ANY)
ZEND_VM_CONTINUE();
}
ZEND_VM_HANDLER(43, ZEND_JMPZ, CONST|TMPVAR|CV, JMP_ADDR)
ZEND_VM_HOT_HANDLER(43, ZEND_JMPZ, CONST|TMPVAR|CV, JMP_ADDR)
{
USE_OPLINE
zend_free_op free_op1;
@ -2518,7 +2518,7 @@ ZEND_VM_HANDLER(43, ZEND_JMPZ, CONST|TMPVAR|CV, JMP_ADDR)
ZEND_VM_JMP(opline);
}
ZEND_VM_HANDLER(44, ZEND_JMPNZ, CONST|TMPVAR|CV, JMP_ADDR)
ZEND_VM_HOT_HANDLER(44, ZEND_JMPNZ, CONST|TMPVAR|CV, JMP_ADDR)
{
USE_OPLINE
zend_free_op free_op1;
@ -2549,7 +2549,7 @@ ZEND_VM_HANDLER(44, ZEND_JMPNZ, CONST|TMPVAR|CV, JMP_ADDR)
ZEND_VM_JMP(opline);
}
ZEND_VM_HANDLER(45, ZEND_JMPZNZ, CONST|TMPVAR|CV, JMP_ADDR, JMP_ADDR)
ZEND_VM_HOT_HANDLER(45, ZEND_JMPZNZ, CONST|TMPVAR|CV, JMP_ADDR, JMP_ADDR)
{
USE_OPLINE
zend_free_op free_op1;
@ -2980,8 +2980,10 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|THIS|CV, CONST|T
obj = Z_OBJ_P(object);
called_scope = obj->ce;
if (OP2_TYPE != IS_CONST ||
UNEXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) {
if (OP2_TYPE == IS_CONST &&
EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(function_name)) == called_scope)) {
fbc = CACHED_PTR(Z_CACHE_SLOT_P(function_name) + sizeof(void*));
} else {
zend_object *orig_obj = obj;
if (UNEXPECTED(obj->handlers->get_method == NULL)) {
@ -3075,8 +3077,8 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR,
/* nothing to do */
} else if (OP1_TYPE != IS_CONST &&
OP2_TYPE == IS_CONST &&
(fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce))) {
/* do nothing */
EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))) == ce)) {
fbc = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)) + sizeof(void*));
} else if (OP2_TYPE != IS_UNUSED) {
zend_free_op free_op2;
@ -3191,7 +3193,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR,
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST, NUM)
ZEND_VM_HOT_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST, NUM)
{
USE_OPLINE
zend_function *fbc;
@ -3391,7 +3393,7 @@ ZEND_VM_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST, NUM)
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(61, ZEND_INIT_FCALL, NUM, CONST, NUM)
ZEND_VM_HOT_HANDLER(61, ZEND_INIT_FCALL, NUM, CONST, NUM)
{
USE_OPLINE
zend_free_op free_op2;
@ -3424,7 +3426,7 @@ ZEND_VM_HANDLER(61, ZEND_INIT_FCALL, NUM, CONST, NUM)
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL))
ZEND_VM_HOT_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL))
{
USE_OPLINE
zend_execute_data *call = EX(call);
@ -3468,7 +3470,7 @@ ZEND_VM_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL))
ZEND_VM_CONTINUE();
}
ZEND_VM_HANDLER(130, ZEND_DO_UCALL, ANY, ANY, SPEC(RETVAL))
ZEND_VM_HOT_HANDLER(130, ZEND_DO_UCALL, ANY, ANY, SPEC(RETVAL))
{
USE_OPLINE
zend_execute_data *call = EX(call);
@ -3490,7 +3492,7 @@ ZEND_VM_HANDLER(130, ZEND_DO_UCALL, ANY, ANY, SPEC(RETVAL))
ZEND_VM_ENTER();
}
ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL))
ZEND_VM_HOT_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL))
{
USE_OPLINE
zend_execute_data *call = EX(call);
@ -3568,7 +3570,7 @@ ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL))
ZEND_VM_CONTINUE();
}
ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL))
ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL))
{
USE_OPLINE
zend_execute_data *call = EX(call);
@ -3743,7 +3745,7 @@ ZEND_VM_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV, UNUSED)
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
ZEND_VM_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY)
ZEND_VM_HOT_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY)
{
USE_OPLINE
zval *retval_ptr;
@ -4082,7 +4084,7 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV, JMP_ADDR)
}
}
ZEND_VM_HANDLER(65, ZEND_SEND_VAL, CONST|TMPVAR, NUM)
ZEND_VM_HOT_HANDLER(65, ZEND_SEND_VAL, CONST|TMPVAR, NUM)
{
USE_OPLINE
zval *value, *arg;
@ -4099,7 +4101,7 @@ ZEND_VM_HANDLER(65, ZEND_SEND_VAL, CONST|TMPVAR, NUM)
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(116, ZEND_SEND_VAL_EX, CONST|TMP, NUM, SPEC(QUICK_ARG))
ZEND_VM_HOT_HANDLER(116, ZEND_SEND_VAL_EX, CONST|TMP, NUM, SPEC(QUICK_ARG))
{
USE_OPLINE
zval *value, *arg;
@ -4130,7 +4132,7 @@ ZEND_VM_C_LABEL(send_val_by_ref):
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(117, ZEND_SEND_VAR, VAR|CV, NUM)
ZEND_VM_HOT_HANDLER(117, ZEND_SEND_VAR, VAR|CV, NUM)
{
USE_OPLINE
zval *varptr, *arg;
@ -4257,7 +4259,7 @@ ZEND_VM_HANDLER(67, ZEND_SEND_REF, VAR|CV, NUM)
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(66, ZEND_SEND_VAR_EX, VAR|CV, NUM, SPEC(QUICK_ARG))
ZEND_VM_HOT_HANDLER(66, ZEND_SEND_VAR_EX, VAR|CV, NUM, SPEC(QUICK_ARG))
{
USE_OPLINE
zval *varptr, *arg;
@ -4574,7 +4576,7 @@ ZEND_VM_HANDLER(63, ZEND_RECV, NUM, ANY)
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(64, ZEND_RECV_INIT, NUM, CONST)
ZEND_VM_HOT_HANDLER(64, ZEND_RECV_INIT, NUM, CONST)
{
USE_OPLINE
uint32_t arg_num;
@ -4976,7 +4978,8 @@ ZEND_VM_HANDLER(181, ZEND_FETCH_CLASS_CONSTANT, VAR|CONST|UNUSED|CLASS_FETCH, CO
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
}
if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce)) != NULL) {
if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))) == ce)) {
value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)) + sizeof(void*));
break;
}
}
@ -5116,7 +5119,7 @@ ZEND_VM_C_LABEL(num_index):
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
ZEND_VM_HANDLER(71, ZEND_INIT_ARRAY, CONST|TMP|VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|NEXT|CV, ARRAY_INIT|REF)
ZEND_VM_HANDLER(71, ZEND_INIT_ARRAY, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV, ARRAY_INIT|REF)
{
zval *array;
uint32_t size;
@ -5138,13 +5141,7 @@ ZEND_VM_HANDLER(71, ZEND_INIT_ARRAY, CONST|TMP|VAR|UNUSED|CV, CONST|TMPVAR|UNUSE
}
}
if (OP1_TYPE == IS_UNUSED) {
ZEND_VM_NEXT_OPCODE();
#if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED)
} else {
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_ADD_ARRAY_ELEMENT);
#endif
}
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_ADD_ARRAY_ELEMENT);
}
ZEND_VM_HANDLER(21, ZEND_CAST, CONST|TMP|VAR|CV, ANY, TYPE)
@ -6320,7 +6317,9 @@ ZEND_VM_HANDLER(180, ZEND_ISSET_ISEMPTY_STATIC_PROP, CONST|TMPVAR|CV, UNUSED|CLA
ce = Z_CE_P(EX_VAR(opline->op2.var));
}
if (OP1_TYPE == IS_CONST &&
(value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))) == ce)) {
value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
/* check if static properties were destoyed */
if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
@ -6699,7 +6698,7 @@ ZEND_VM_HANDLER(169, ZEND_COALESCE, CONST|TMP|VAR|CV, JMP_ADDR)
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(22, ZEND_QM_ASSIGN, CONST|TMP|VAR|CV, ANY)
ZEND_VM_HOT_HANDLER(22, ZEND_QM_ASSIGN, CONST|TMP|VAR|CV, ANY)
{
USE_OPLINE
zend_free_op free_op1;
@ -7528,7 +7527,7 @@ ZEND_VM_HANDLER(163, ZEND_FAST_RET, ANY, TRY_CATCH)
ZEND_VM_DISPATCH_TO_HELPER(zend_dispatch_try_catch_finally_helper, try_catch_offset, current_try_catch_offset, op_num, current_op_num);
}
ZEND_VM_HANDLER(168, ZEND_BIND_GLOBAL, CV, CONST)
ZEND_VM_HOT_HANDLER(168, ZEND_BIND_GLOBAL, CV, CONST)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
@ -7784,6 +7783,8 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY)
zend_execute_data *call;
USE_OPLINE
SAVE_OPLINE();
args = emalloc(sizeof(zend_array));
zend_hash_init(args, num_args, NULL, ZVAL_PTR_DTOR, 0);
if (num_args) {
@ -7799,7 +7800,6 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY)
} ZEND_HASH_FILL_END();
}
SAVE_OPLINE();
call = execute_data;
execute_data = EG(current_execute_data) = EX(prev_execute_data);
@ -8102,7 +8102,162 @@ ZEND_VM_HANDLER(188, ZEND_SWITCH_STRING, CONST|TMPVAR|CV, CONST, JMP_ADDR)
}
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_ADD, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_ADD_LONG_NO_OVERFLOW, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST,COMMUTATIVE))
ZEND_VM_HANDLER(189, ZEND_IN_ARRAY, CONST|TMP|VAR|CV, CONST, NUM)
{
USE_OPLINE
zend_free_op free_op1;
zval *op1;
HashTable *ht = Z_ARRVAL_P(EX_CONSTANT(opline->op2));
int result;
SAVE_OPLINE();
op1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
result = zend_hash_exists(ht, Z_STR_P(op1));
} else if (opline->extended_value) {
if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
result = zend_hash_index_exists(ht, Z_LVAL_P(op1));
} else {
result = 0;
}
} else if (Z_TYPE_P(op1) <= IS_FALSE) {
result = zend_hash_exists(ht, ZSTR_EMPTY_ALLOC());
} else {
zend_string *key;
zval tmp;
result = 0;
ZEND_HASH_FOREACH_STR_KEY(ht, key) {
ZVAL_STR(&tmp, key);
compare_function(&tmp, op1, &tmp);
if (Z_LVAL(tmp) == 0) {
result = 1;
break;
}
} ZEND_HASH_FOREACH_END();
}
FREE_OP1();
ZEND_VM_SMART_BRANCH(result, 1);
ZVAL_BOOL(EX_VAR(opline->result.var), result);
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
ZEND_VM_HANDLER(190, ZEND_COUNT, CONST|TMP|VAR|CV, UNUSED)
{
USE_OPLINE
zend_free_op free_op1;
zval *op1;
zend_long count;
SAVE_OPLINE();
op1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
do {
if (Z_TYPE_P(op1) == IS_ARRAY) {
count = zend_array_count(Z_ARRVAL_P(op1));
break;
} else if (Z_TYPE_P(op1) == IS_OBJECT) {
/* first, we check if the handler is defined */
if (Z_OBJ_HT_P(op1)->count_elements) {
if (SUCCESS == Z_OBJ_HT_P(op1)->count_elements(op1, &count)) {
break;
}
}
/* if not and the object implements Countable we call its count() method */
if (instanceof_function(Z_OBJCE_P(op1), zend_ce_countable)) {
zval retval;
zend_call_method_with_0_params(op1, NULL, NULL, "count", &retval);
count = zval_get_long(&retval);
zval_ptr_dtor(&retval);
break;
}
/* If There's no handler and it doesn't implement Countable then add a warning */
count = 1;
} else if (Z_TYPE_P(op1) == IS_NULL) {
count = 0;
} else {
count = 1;
}
zend_error(E_WARNING, "count(): Parameter must be an array or an object that implements Countable");
} while (0);
ZVAL_LONG(EX_VAR(opline->result.var), count);
FREE_OP1();
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
ZEND_VM_HANDLER(191, ZEND_GET_CLASS, UNUSED|CONST|TMP|VAR|CV, UNUSED)
{
USE_OPLINE
if (OP1_TYPE == IS_UNUSED) {
if (UNEXPECTED(!EX(func)->common.scope)) {
SAVE_OPLINE();
zend_error(E_WARNING, "get_class() called without object from outside a class");
ZVAL_FALSE(EX_VAR(opline->result.var));
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
} else {
ZVAL_STR_COPY(EX_VAR(opline->result.var), EX(func)->common.scope->name);
ZEND_VM_NEXT_OPCODE();
}
} else {
zend_free_op free_op1;
zval *op1;
SAVE_OPLINE();
op1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
if (Z_TYPE_P(op1) == IS_OBJECT) {
ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE_P(op1)->name);
} else {
zend_error(E_WARNING, "get_class() expects parameter 1 to be object, %s given", zend_get_type_by_const(Z_TYPE_P(op1)));
ZVAL_FALSE(EX_VAR(opline->result.var));
}
FREE_OP1();
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
}
ZEND_VM_HANDLER(192, ZEND_GET_CALLED_CLASS, UNUSED, UNUSED)
{
USE_OPLINE
if (Z_TYPE(EX(This)) == IS_OBJECT) {
ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE(EX(This))->name);
} else if (Z_CE(EX(This))) {
ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_CE(EX(This))->name);
} else {
ZVAL_FALSE(EX_VAR(opline->result.var));
if (UNEXPECTED(!EX(func)->common.scope)) {
SAVE_OPLINE();
zend_error(E_WARNING, "get_called_class() called from outside a class");
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
}
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(193, ZEND_GET_TYPE, CONST|TMP|VAR|CV, UNUSED)
{
USE_OPLINE
zend_free_op free_op1;
zval *op1;
zend_string *type;
SAVE_OPLINE();
op1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
type = zend_zval_get_type(op1);
if (EXPECTED(type)) {
ZVAL_INTERNED_STR(EX_VAR(opline->result.var), type);
} else {
ZVAL_STRING(EX_VAR(opline->result.var), "unknown type");
}
FREE_OP1();
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_ADD, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_ADD_LONG_NO_OVERFLOW, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST,COMMUTATIVE))
{
USE_OPLINE
zval *op1, *op2, *result;
@ -8114,7 +8269,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_ADD, (res_info == MAY_BE_LONG && op1_info == MAY_
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_ADD, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_ADD_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST,COMMUTATIVE))
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_ADD, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_ADD_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST,COMMUTATIVE))
{
USE_OPLINE
zval *op1, *op2, *result;
@ -8126,7 +8281,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_ADD, (op1_info == MAY_BE_LONG && op2_info == MAY_
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_ADD, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_ADD_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST,COMMUTATIVE))
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_ADD, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_ADD_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST,COMMUTATIVE))
{
USE_OPLINE
zval *op1, *op2, *result;
@ -8138,7 +8293,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_ADD, (op1_info == MAY_BE_DOUBLE && op2_info == MA
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_SUB, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_SUB_LONG_NO_OVERFLOW, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST))
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_SUB, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_SUB_LONG_NO_OVERFLOW, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST))
{
USE_OPLINE
zval *op1, *op2, *result;
@ -8150,7 +8305,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_SUB, (res_info == MAY_BE_LONG && op1_info == MAY_
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_SUB, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_SUB_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST))
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_SUB, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_SUB_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST))
{
USE_OPLINE
zval *op1, *op2, *result;
@ -8162,7 +8317,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_SUB, (op1_info == MAY_BE_LONG && op2_info == MAY_
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_SUB, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_SUB_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST))
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_SUB, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_SUB_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST))
{
USE_OPLINE
zval *op1, *op2, *result;
@ -8174,7 +8329,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_SUB, (op1_info == MAY_BE_DOUBLE && op2_info == MA
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_MUL, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_MUL_LONG_NO_OVERFLOW, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST,COMMUTATIVE))
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_MUL, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_MUL_LONG_NO_OVERFLOW, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST,COMMUTATIVE))
{
USE_OPLINE
zval *op1, *op2, *result;
@ -8186,7 +8341,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_MUL, (res_info == MAY_BE_LONG && op1_info == MAY_
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_MUL, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_MUL_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST,COMMUTATIVE))
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_MUL, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_MUL_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST,COMMUTATIVE))
{
USE_OPLINE
zval *op1, *op2, *result;
@ -8200,7 +8355,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_MUL, (op1_info == MAY_BE_LONG && op2_info == MAY_
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_MUL, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_MUL_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST,COMMUTATIVE))
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_MUL, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_MUL_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST,COMMUTATIVE))
{
USE_OPLINE
zval *op1, *op2, *result;
@ -8212,7 +8367,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_MUL, (op1_info == MAY_BE_DOUBLE && op2_info == MA
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_EQUAL, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_IS_EQUAL_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE))
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_EQUAL, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_IS_EQUAL_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE))
{
USE_OPLINE
zval *op1, *op2;
@ -8226,7 +8381,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_EQUAL, (op1_info == MAY_BE_LONG && op2_info ==
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_EQUAL, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_IS_EQUAL_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE))
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_EQUAL, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_IS_EQUAL_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE))
{
USE_OPLINE
zval *op1, *op2;
@ -8240,7 +8395,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_EQUAL, (op1_info == MAY_BE_DOUBLE && op2_info
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_NOT_EQUAL, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_IS_NOT_EQUAL_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE))
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_NOT_EQUAL, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_IS_NOT_EQUAL_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE))
{
USE_OPLINE
zval *op1, *op2;
@ -8254,7 +8409,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_NOT_EQUAL, (op1_info == MAY_BE_LONG && op2_inf
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_NOT_EQUAL, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_IS_NOT_EQUAL_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE))
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_NOT_EQUAL, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_IS_NOT_EQUAL_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE))
{
USE_OPLINE
zval *op1, *op2;
@ -8268,7 +8423,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_NOT_EQUAL, (op1_info == MAY_BE_DOUBLE && op2_i
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_IS_SMALLER_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST))
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_IS_SMALLER_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST))
{
USE_OPLINE
zval *op1, *op2;
@ -8282,7 +8437,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER, (op1_info == MAY_BE_LONG && op2_info
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_IS_SMALLER_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST))
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_IS_SMALLER_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST))
{
USE_OPLINE
zval *op1, *op2;
@ -8296,7 +8451,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER, (op1_info == MAY_BE_DOUBLE && op2_inf
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER_OR_EQUAL, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_IS_SMALLER_OR_EQUAL_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST))
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER_OR_EQUAL, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_IS_SMALLER_OR_EQUAL_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST))
{
USE_OPLINE
zval *op1, *op2;
@ -8310,7 +8465,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER_OR_EQUAL, (op1_info == MAY_BE_LONG &&
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER_OR_EQUAL, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_IS_SMALLER_OR_EQUAL_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST))
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER_OR_EQUAL, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_IS_SMALLER_OR_EQUAL_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST))
{
USE_OPLINE
zval *op1, *op2;
@ -8324,7 +8479,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER_OR_EQUAL, (op1_info == MAY_BE_DOUBLE &
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_PRE_INC, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG), ZEND_PRE_INC_LONG_NO_OVERFLOW, TMPVARCV, ANY, SPEC(RETVAL))
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_PRE_INC, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG), ZEND_PRE_INC_LONG_NO_OVERFLOW, TMPVARCV, ANY, SPEC(RETVAL))
{
USE_OPLINE
zval *var_ptr;
@ -8337,7 +8492,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_PRE_INC, (res_info == MAY_BE_LONG && op1_info ==
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_PRE_INC, (op1_info == MAY_BE_LONG), ZEND_PRE_INC_LONG, TMPVARCV, ANY, SPEC(RETVAL))
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_PRE_INC, (op1_info == MAY_BE_LONG), ZEND_PRE_INC_LONG, TMPVARCV, ANY, SPEC(RETVAL))
{
USE_OPLINE
zval *var_ptr;
@ -8350,7 +8505,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_PRE_INC, (op1_info == MAY_BE_LONG), ZEND_PRE_INC_
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_PRE_INC, (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)), ZEND_PRE_INC_LONG_OR_DOUBLE, TMPVARCV, ANY, SPEC(RETVAL))
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_PRE_INC, (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)), ZEND_PRE_INC_LONG_OR_DOUBLE, TMPVARCV, ANY, SPEC(RETVAL))
{
USE_OPLINE
zval *var_ptr;
@ -8367,7 +8522,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_PRE_INC, (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_PRE_DEC, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG), ZEND_PRE_DEC_LONG_NO_OVERFLOW, TMPVARCV, ANY, SPEC(RETVAL))
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_PRE_DEC, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG), ZEND_PRE_DEC_LONG_NO_OVERFLOW, TMPVARCV, ANY, SPEC(RETVAL))
{
USE_OPLINE
zval *var_ptr;
@ -8380,7 +8535,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_PRE_DEC, (res_info == MAY_BE_LONG && op1_info ==
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_PRE_DEC, (op1_info == MAY_BE_LONG), ZEND_PRE_DEC_LONG, TMPVARCV, ANY, SPEC(RETVAL))
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_PRE_DEC, (op1_info == MAY_BE_LONG), ZEND_PRE_DEC_LONG, TMPVARCV, ANY, SPEC(RETVAL))
{
USE_OPLINE
zval *var_ptr;
@ -8393,7 +8548,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_PRE_DEC, (op1_info == MAY_BE_LONG), ZEND_PRE_DEC_
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_PRE_DEC, (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)), ZEND_PRE_DEC_LONG_OR_DOUBLE, TMPVARCV, ANY, SPEC(RETVAL))
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_PRE_DEC, (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)), ZEND_PRE_DEC_LONG_OR_DOUBLE, TMPVARCV, ANY, SPEC(RETVAL))
{
USE_OPLINE
zval *var_ptr;
@ -8410,7 +8565,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_PRE_DEC, (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_POST_INC, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG), ZEND_POST_INC_LONG_NO_OVERFLOW, TMPVARCV, ANY)
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_POST_INC, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG), ZEND_POST_INC_LONG_NO_OVERFLOW, TMPVARCV, ANY)
{
USE_OPLINE
zval *var_ptr;
@ -8421,7 +8576,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_POST_INC, (res_info == MAY_BE_LONG && op1_info ==
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_POST_INC, (op1_info == MAY_BE_LONG), ZEND_POST_INC_LONG, TMPVARCV, ANY)
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_POST_INC, (op1_info == MAY_BE_LONG), ZEND_POST_INC_LONG, TMPVARCV, ANY)
{
USE_OPLINE
zval *var_ptr;
@ -8432,7 +8587,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_POST_INC, (op1_info == MAY_BE_LONG), ZEND_POST_IN
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_POST_INC, (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)), ZEND_POST_INC_LONG_OR_DOUBLE, TMPVARCV, ANY)
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_POST_INC, (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)), ZEND_POST_INC_LONG_OR_DOUBLE, TMPVARCV, ANY)
{
USE_OPLINE
zval *var_ptr;
@ -8447,7 +8602,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_POST_INC, (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_POST_DEC, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG), ZEND_POST_DEC_LONG_NO_OVERFLOW, TMPVARCV, ANY)
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_POST_DEC, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG), ZEND_POST_DEC_LONG_NO_OVERFLOW, TMPVARCV, ANY)
{
USE_OPLINE
zval *var_ptr;
@ -8458,7 +8613,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_POST_DEC, (res_info == MAY_BE_LONG && op1_info ==
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_POST_DEC, (op1_info == MAY_BE_LONG), ZEND_POST_DEC_LONG, TMPVARCV, ANY)
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_POST_DEC, (op1_info == MAY_BE_LONG), ZEND_POST_DEC_LONG, TMPVARCV, ANY)
{
USE_OPLINE
zval *var_ptr;
@ -8469,7 +8624,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_POST_DEC, (op1_info == MAY_BE_LONG), ZEND_POST_DE
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_POST_DEC, (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)), ZEND_POST_DEC_LONG_OR_DOUBLE, TMPVARCV, ANY)
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_POST_DEC, (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)), ZEND_POST_DEC_LONG_OR_DOUBLE, TMPVARCV, ANY)
{
USE_OPLINE
zval *var_ptr;
@ -8484,7 +8639,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_POST_DEC, (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_QM_ASSIGN, (op1_info == MAY_BE_DOUBLE), ZEND_QM_ASSIGN_DOUBLE, CONST|TMPVARCV, ANY)
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_QM_ASSIGN, (op1_info == MAY_BE_DOUBLE), ZEND_QM_ASSIGN_DOUBLE, CONST|TMPVARCV, ANY)
{
USE_OPLINE
zend_free_op free_op1;
@ -8495,7 +8650,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_QM_ASSIGN, (op1_info == MAY_BE_DOUBLE), ZEND_QM_A
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_QM_ASSIGN, (!(op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE)))), ZEND_QM_ASSIGN_NOREF, CONST|TMPVARCV, ANY)
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_QM_ASSIGN, (!(op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE)))), ZEND_QM_ASSIGN_NOREF, CONST|TMPVARCV, ANY)
{
USE_OPLINE
zend_free_op free_op1;
@ -8506,7 +8661,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_QM_ASSIGN, (!(op1_info & ((MAY_BE_ANY|MAY_BE_UNDE
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_FETCH_DIM_R, (!(op2_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF))), ZEND_FETCH_DIM_R_INDEX, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_FETCH_DIM_R, (!(op2_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF))), ZEND_FETCH_DIM_R_INDEX, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
@ -8554,7 +8709,7 @@ ZEND_VM_C_LABEL(fetch_dim_r_index_undef):
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_SEND_VAR, (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0, ZEND_SEND_VAR_SIMPLE, CV|VAR, NUM)
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_SEND_VAR, (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0, ZEND_SEND_VAR_SIMPLE, CV|VAR, NUM)
{
USE_OPLINE
zval *varptr, *arg;
@ -8572,7 +8727,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_SEND_VAR, (op1_info & (MAY_BE_UNDEF|MAY_BE_REF))
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_SEND_VAR_EX, (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0, ZEND_SEND_VAR_EX_SIMPLE, CV|VAR, NUM, SPEC(QUICK_ARG))
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_SEND_VAR_EX, (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0, ZEND_SEND_VAR_EX_SIMPLE, CV|VAR, NUM, SPEC(QUICK_ARG))
{
USE_OPLINE
zval *varptr, *arg;

File diff suppressed because it is too large Load Diff

View File

@ -83,3 +83,35 @@ ZEND_API void zend_deserialize_opcode_handler(zend_op *op)
op->handler = zend_opcode_handlers[(zend_uintptr_t)op->handler];
}
ZEND_API const void *zend_get_opcode_handler_func(const zend_op *op)
{
#if ZEND_VM_KIND == ZEND_VM_KIND_CALL
return op->handler;
#elif ZEND_VM_KIND == ZEND_VM_KIND_HYBRID
zval *zv;
if (!zend_handlers_table) {
init_opcode_serialiser();
}
zv = zend_hash_index_find(zend_handlers_table, (zend_long)(zend_uintptr_t)op->handler);
ZEND_ASSERT(zv != NULL);
return zend_opcode_handler_funcs[Z_LVAL_P(zv)];
#else
return NULL;
#endif
}
ZEND_API const zend_op *zend_get_halt_op(void)
{
#if ZEND_VM_KIND == ZEND_VM_KIND_HYBRID
return &hybrid_halt_op;
#else
return NULL;
#endif
}
ZEND_API int zend_vm_kind(void)
{
return ZEND_VM_KIND;
}

View File

@ -53,6 +53,7 @@ error_reporting(E_ALL);
const ZEND_VM_KIND_CALL = 1;
const ZEND_VM_KIND_SWITCH = 2;
const ZEND_VM_KIND_GOTO = 3;
const ZEND_VM_KIND_HYBRID = 4;
$vm_op_flags = array(
"ZEND_VM_OP_SPEC" => 1<<0,
@ -134,6 +135,7 @@ $vm_kind_name = array(
ZEND_VM_KIND_CALL => "ZEND_VM_KIND_CALL",
ZEND_VM_KIND_SWITCH => "ZEND_VM_KIND_SWITCH",
ZEND_VM_KIND_GOTO => "ZEND_VM_KIND_GOTO",
ZEND_VM_KIND_HYBRID => "ZEND_VM_KIND_HYBRID",
);
$op_types = array(
@ -885,7 +887,7 @@ function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name, $extra_sp
if (strncasecmp($matches[0], "EXECUTE_DATA", strlen("EXECUTE_DATA")) == 0) {
return "execute_data";
} else if (strncasecmp($matches[0], "ZEND_VM_DISPATCH_TO_HANDLER", strlen("ZEND_VM_DISPATCH_TO_HANDLER")) == 0) {
return "goto " . opcode_name($matches[1], $spec, $op1, $op2) . "_HANDLER";
return "goto " . opcode_name($matches[1], $spec, $op1, $op2) . "_LABEL";
} else {
// ZEND_VM_DISPATCH_TO_HELPER
if (isset($matches[2])) {
@ -973,7 +975,7 @@ function skip_extra_spec_function($op1, $op2, $extra_spec) {
}
// Generates opcode handler
function gen_handler($f, $spec, $kind, $name, $op1, $op2, $use, $code, $lineno, $extra_spec = null, &$switch_labels = array()) {
function gen_handler($f, $spec, $kind, $name, $op1, $op2, $use, $code, $lineno, $opcode, $extra_spec = null, &$switch_labels = array()) {
global $definition_file, $prefix, $typecode, $opnames;
if ($spec && skip_extra_spec_function($op1, $op2, $extra_spec)) {
@ -987,8 +989,17 @@ function gen_handler($f, $spec, $kind, $name, $op1, $op2, $use, $code, $lineno,
// Generate opcode handler's entry point according to selected threading model
$spec_name = $name.($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2].($spec?extra_spec_name($extra_spec):"");
switch($kind) {
case ZEND_VM_KIND_HYBRID:
out($f,"\t\t\tHYBRID_CASE({$spec_name}):\n");
out($f,"\t\t\t\t{$spec_name}_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n");
out($f,"\t\t\t\tHYBRID_BREAK();\n");
return;
case ZEND_VM_KIND_CALL:
out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL {$spec_name}_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n");
if ($opcode["hot"] && ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) {
out($f,"static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL {$spec_name}_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n");
} else {
out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL {$spec_name}_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n");
}
break;
case ZEND_VM_KIND_SWITCH:
if ($spec) {
@ -1006,7 +1017,7 @@ function gen_handler($f, $spec, $kind, $name, $op1, $op2, $use, $code, $lineno,
}
break;
case ZEND_VM_KIND_GOTO:
out($f,"{$spec_name}_HANDLER: ZEND_VM_GUARD($spec_name);\n");
out($f,"{$spec_name}_LABEL: ZEND_VM_GUARD($spec_name);\n");
break;
}
@ -1018,6 +1029,10 @@ function gen_handler($f, $spec, $kind, $name, $op1, $op2, $use, $code, $lineno,
function gen_helper($f, $spec, $kind, $name, $op1, $op2, $param, $code, $lineno, $inline, $extra_spec = null) {
global $definition_file, $prefix;
if ($kind == ZEND_VM_KIND_HYBRID) {
return;
}
if ($spec && skip_extra_spec_function($op1, $op2, $extra_spec)) {
return;
}
@ -1068,7 +1083,7 @@ function gen_null_label($f, $kind, $prolog) {
out($f,$prolog."(void*)(uintptr_t)-1,\n");
break;
case ZEND_VM_KIND_GOTO:
out($f,$prolog."(void*)&&ZEND_NULL_HANDLER,\n");
out($f,$prolog."(void*)&&ZEND_NULL_LABEL,\n");
break;
}
}
@ -1219,7 +1234,7 @@ function gen_labels($f, $spec, $kind, $prolog, &$specs, $switch_labels = array()
$label++;
break;
case ZEND_VM_KIND_GOTO:
out($f,$prolog."(void*)&&{$spec_name}_HANDLER,\n");
out($f,$prolog."(void*)&&{$spec_name}_LABEL,\n");
$label++;
break;
}
@ -1265,7 +1280,7 @@ function gen_labels($f, $spec, $kind, $prolog, &$specs, $switch_labels = array()
out($f,$prolog."(void*)(uintptr_t)-1,\n");
break;
case ZEND_VM_KIND_GOTO:
out($f,$prolog."(void*)&&ZEND_NULL_HANDLER,\n");
out($f,$prolog."(void*)&&ZEND_NULL_LABEL,\n");
break;
}
$next++;
@ -1286,7 +1301,7 @@ function gen_labels($f, $spec, $kind, $prolog, &$specs, $switch_labels = array()
out($f,$prolog."(void*)(uintptr_t)".((string)$num).",\n");
break;
case ZEND_VM_KIND_GOTO:
out($f,$prolog."(void*)&&".$dsc["op"]."_HANDLER,\n");
out($f,$prolog."(void*)&&".$dsc["op"]."_LABEL,\n");
break;
}
} else {
@ -1298,7 +1313,7 @@ function gen_labels($f, $spec, $kind, $prolog, &$specs, $switch_labels = array()
out($f,$prolog."(void*)(uintptr_t)-1,\n");
break;
case ZEND_VM_KIND_GOTO:
out($f,$prolog."(void*)&&ZEND_NULL_HANDLER,\n");
out($f,$prolog."(void*)&&ZEND_NULL_LABEL,\n");
break;
}
}
@ -1314,14 +1329,14 @@ function gen_labels($f, $spec, $kind, $prolog, &$specs, $switch_labels = array()
out($f,$prolog."(void*)(uintptr_t)-1\n");
break;
case ZEND_VM_KIND_GOTO:
out($f,$prolog."(void*)&&ZEND_NULL_HANDLER\n");
out($f,$prolog."(void*)&&ZEND_NULL_LABEL\n");
break;
}
$specs[$num + 1] = "$label";
}
// Generates specialized offsets
function gen_specs($f, $spec, $kind, $prolog, $specs) {
function gen_specs($f, $prolog, $specs) {
$lastdef = array_pop($specs);
$last = 0;
foreach ($specs as $num => $def) {
@ -1462,7 +1477,7 @@ function gen_executor_code($f, $spec, $kind, $prolog, &$switch_labels = array())
if (isset($opcodes[$num]["op1"][$op1]) &&
isset($opcodes[$num]["op2"][$op2])) {
// Generate handler code
gen_handler($f, 1, $kind, $opcodes[$num]["op"], $op1, $op2, isset($opcodes[$num]["use"]), $opcodes[$num]["code"], $lineno, $extra_spec, $switch_labels);
gen_handler($f, 1, $kind, $opcodes[$num]["op"], $op1, $op2, isset($opcodes[$num]["use"]), $opcodes[$num]["code"], $lineno, $opcodes[$num], $extra_spec, $switch_labels);
}
}
} else if (isset($dsc["helper"])) {
@ -1491,7 +1506,7 @@ function gen_executor_code($f, $spec, $kind, $prolog, &$switch_labels = array())
$num = $dsc["handler"];
// Generate handler code
if ($num < 256) {
gen_handler($f, 0, $kind, $opcodes[$num]["op"], "ANY", "ANY", isset($opcodes[$num]["use"]), $opcodes[$num]["code"], $lineno);
gen_handler($f, 0, $kind, $opcodes[$num]["op"], "ANY", "ANY", isset($opcodes[$num]["use"]), $opcodes[$num]["code"], $lineno, $opcodes[$num]);
}
} else if (isset($dsc["helper"])) {
$num = $dsc["helper"];
@ -1520,10 +1535,19 @@ function gen_executor_code($f, $spec, $kind, $prolog, &$switch_labels = array())
out($f,"\tZEND_VM_NEXT_OPCODE(); /* Never reached */\n");
break;
case ZEND_VM_KIND_GOTO:
out($f,"ZEND_NULL_HANDLER:\n");
out($f,"ZEND_NULL_LABEL:\n");
out($f,"\tzend_error_noreturn(E_ERROR, \"Invalid opcode %d/%d/%d.\", OPLINE->opcode, OPLINE->op1_type, OPLINE->op2_type);\n");
out($f,"\tZEND_VM_NEXT_OPCODE(); /* Never reached */\n");
break;
case ZEND_VM_KIND_HYBRID:
out($f,"\t\t\tHYBRID_CASE(HYBRID_HALT):\n");
out($f,"\t\t\t\texecute_data = orig_execute_data;\n");
out($f,"\t\t\t\topline = orig_opline;\n");
out($f,"\t\t\t\treturn;\n");
out($f,"\t\t\tHYBRID_DEFAULT:\n");
out($f,"\t\t\t\tzend_error_noreturn(E_ERROR, \"Invalid opcode %d/%d/%d.\", OPLINE->opcode, OPLINE->op1_type, OPLINE->op2_type);\n");
out($f,"\t\t\t\tHYBRID_BREAK(); /* Never reached */\n");
break;
}
}
@ -1557,8 +1581,29 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
out($f,"static const uint32_t *zend_spec_handlers;\n");
out($f,"static const void **zend_opcode_handlers;\n");
out($f,"static int zend_handlers_count;\n");
if ($kind == ZEND_VM_KIND_HYBRID) {
out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
out($f,"static const void **zend_opcode_handler_funcs;\n");
out($f,"static zend_op hybrid_halt_op;\n");
out($f,"#endif\n");
}
out($f,"static const void *zend_vm_get_opcode_handler(zend_uchar opcode, const zend_op* op);\n\n");
if ($kind == ZEND_VM_KIND_HYBRID) {
out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
out($f,"static const void *zend_vm_get_opcode_handler_func(zend_uchar opcode, const zend_op* op);\n");
out($f,"#else\n");
out($f,"# define zend_vm_get_opcode_handler_func zend_vm_get_opcode_handler\n");
out($f,"#endif\n\n");
}
switch ($kind) {
case ZEND_VM_KIND_HYBRID:
out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
out($f,"#define HYBRID_NEXT() goto *(void**)(OPLINE->handler)\n");
out($f,"#define HYBRID_SWITCH() HYBRID_NEXT();\n");
out($f,"#define HYBRID_CASE(op) op ## _LABEL\n");
out($f,"#define HYBRID_BREAK() HYBRID_NEXT()\n");
out($f,"#define HYBRID_DEFAULT ZEND_NULL_LABEL\n");
out($f,"#endif\n");
case ZEND_VM_KIND_CALL:
out($f,"\n");
out($f,"#ifdef ZEND_VM_FP_GLOBAL_REG\n");
@ -1593,12 +1638,25 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
out($f,"# else\n");
out($f,"# define ZEND_VM_CONTINUE() return\n");
out($f,"# endif\n");
out($f,"# define ZEND_VM_RETURN() opline = NULL; return\n");
if ($kind == ZEND_VM_KIND_HYBRID) {
out($f,"# if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
out($f,"# define ZEND_VM_RETURN() opline = &hybrid_halt_op; return\n");
out($f,"# define ZEND_VM_HOT zend_always_inline\n");
out($f,"# else\n");
out($f,"# define ZEND_VM_RETURN() opline = NULL; return\n");
out($f,"# define ZEND_VM_HOT\n");
out($f,"# endif\n");
} else {
out($f,"# define ZEND_VM_RETURN() opline = NULL; return\n");
}
out($f,"#else\n");
out($f,"# define ZEND_OPCODE_HANDLER_RET int\n");
out($f,"# define ZEND_VM_TAIL_CALL(call) return call\n");
out($f,"# define ZEND_VM_CONTINUE() return 0\n");
out($f,"# define ZEND_VM_RETURN() return -1\n");
if ($kind == ZEND_VM_KIND_HYBRID) {
out($f,"# define ZEND_VM_HOT\n");
}
out($f,"#endif\n");
out($f,"\n");
out($f,"typedef ZEND_OPCODE_HANDLER_RET (ZEND_FASTCALL *opcode_handler_t) (ZEND_OPCODE_HANDLER_ARGS);\n");
@ -1639,7 +1697,11 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
out($f,"#endif\n");
out($f,"#define ZEND_VM_INTERRUPT() ZEND_VM_TAIL_CALL(zend_interrupt_helper".($spec?"_SPEC":"")."(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));\n");
out($f,"#define ZEND_VM_LOOP_INTERRUPT() zend_interrupt_helper".($spec?"_SPEC":"")."(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n");
out($f,"#define ZEND_VM_DISPATCH(opcode, opline) ZEND_VM_TAIL_CALL(((opcode_handler_t)zend_vm_get_opcode_handler(opcode, opline))(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));\n");
if ($kind == ZEND_VM_KIND_HYBRID) {
out($f,"#define ZEND_VM_DISPATCH(opcode, opline) ZEND_VM_TAIL_CALL(((opcode_handler_t)zend_vm_get_opcode_handler_func(opcode, opline))(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));\n");
} else {
out($f,"#define ZEND_VM_DISPATCH(opcode, opline) ZEND_VM_TAIL_CALL(((opcode_handler_t)zend_vm_get_opcode_handler(opcode, opline))(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));\n");
}
out($f,"\n");
out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_interrupt_helper".($spec?"_SPEC":"")."(ZEND_OPCODE_HANDLER_ARGS);");
out($f,"\n");
@ -1696,11 +1758,11 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
out($f,"#undef HANDLE_EXCEPTION\n");
out($f,"#undef HANDLE_EXCEPTION_LEAVE\n");
if (ZEND_VM_SPEC) {
out($f,"#define HANDLE_EXCEPTION() goto ZEND_HANDLE_EXCEPTION_SPEC_HANDLER\n");
out($f,"#define HANDLE_EXCEPTION_LEAVE() goto ZEND_HANDLE_EXCEPTION_SPEC_HANDLER\n");
out($f,"#define HANDLE_EXCEPTION() goto ZEND_HANDLE_EXCEPTION_SPEC_LABEL\n");
out($f,"#define HANDLE_EXCEPTION_LEAVE() goto ZEND_HANDLE_EXCEPTION_SPEC_LABEL\n");
} else {
out($f,"#define HANDLE_EXCEPTION() goto ZEND_HANDLE_EXCEPTION_HANDLER\n");
out($f,"#define HANDLE_EXCEPTION_LEAVE() goto ZEND_HANDLE_EXCEPTION_HANDLER\n");
out($f,"#define HANDLE_EXCEPTION() goto ZEND_HANDLE_EXCEPTION_LABEL\n");
out($f,"#define HANDLE_EXCEPTION_LEAVE() goto ZEND_HANDLE_EXCEPTION_LABEL\n");
}
out($f,"#define ZEND_VM_CONTINUE() goto *(void**)(OPLINE->handler)\n");
out($f,"#define ZEND_VM_RETURN() return\n");
@ -1712,12 +1774,15 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
out($f,"\n");
break;
}
if ($kind == ZEND_VM_KIND_HYBRID) {
gen_executor_code($f, $spec, ZEND_VM_KIND_CALL, $m[1]);
}
break;
case "EXECUTOR_NAME":
out($f, $m[1].$executor_name.$m[3]."\n");
break;
case "HELPER_VARS":
if ($kind != ZEND_VM_KIND_CALL) {
if ($kind != ZEND_VM_KIND_CALL && $kind != ZEND_VM_KIND_HYBRID) {
if ($kind == ZEND_VM_KIND_SWITCH) {
out($f,$m[1]."const void *dispatch_handler;\n");
}
@ -1743,28 +1808,36 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
}
break;
case "INTERNAL_LABELS":
if ($kind == ZEND_VM_KIND_GOTO) {
if ($kind == ZEND_VM_KIND_GOTO || $kind == ZEND_VM_KIND_HYBRID) {
// Emit array of labels of opcode handlers and code for
// zend_opcode_handlers initialization
if ($kind == ZEND_VM_KIND_HYBRID) {
out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
}
$prolog = $m[1];
out($f,$prolog."if (UNEXPECTED(execute_data == NULL)) {\n");
out($f,$prolog."\tstatic const void* labels[] = {\n");
gen_labels($f, $spec, $kind, $prolog."\t\t", $specs);
gen_labels($f, $spec, ZEND_VM_KIND_GOTO, $prolog."\t\t", $specs);
out($f,$prolog."\t};\n");
out($f,$prolog."static const uint32_t specs[] = {\n");
gen_specs($f, $spec, $kind, $prolog."\t", $specs);
out($f,$prolog."};\n");
out($f,$prolog."\tzend_opcode_handlers = (const void **) labels;\n");
out($f,$prolog."\tzend_handlers_count = sizeof(labels) / sizeof(void*);\n");
out($f,$prolog."\tzend_spec_handlers = (const uint32_t *) specs;\n");
out($f,$prolog."\treturn;\n");
if ($kind == ZEND_VM_KIND_HYBRID) {
out($f,$prolog."\tmemset(&hybrid_halt_op, 0, sizeof(hybrid_halt_op));\n");
out($f,$prolog."\thybrid_halt_op.handler = (void*)&&HYBRID_HALT_LABEL;\n");
out($f,$prolog."\tgoto HYBRID_HALT_LABEL;\n");
} else {
out($f,$prolog."\treturn;\n");
}
out($f,$prolog."}\n");
if ($kind == ZEND_VM_KIND_HYBRID) {
out($f,"#endif\n");
}
} else {
skip_blanks($f, $m[1], $m[3]);
}
break;
case "ZEND_VM_CONTINUE_LABEL":
if ($kind == ZEND_VM_KIND_CALL) {
if ($kind == ZEND_VM_KIND_CALL || $kind == ZEND_VM_KIND_HYBRID) {
// Only SWITCH dispatch method use it
out($f,"#if !defined(ZEND_VM_FP_GLOBAL_REG) || !defined(ZEND_VM_IP_GLOBAL_REG)\n");
out($f,$m[1]."\tint ret;".$m[3]."\n");
@ -1779,6 +1852,16 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
case "ZEND_VM_DISPATCH":
// Emit code that dispatches to opcode handler
switch ($kind) {
case ZEND_VM_KIND_SWITCH:
out($f, $m[1]."dispatch_handler = OPLINE->handler;\nzend_vm_dispatch:\n".$m[1]."switch ((int)(uintptr_t)dispatch_handler)".$m[3]."\n");
break;
case ZEND_VM_KIND_GOTO:
out($f, $m[1]."goto *(void**)(OPLINE->handler);".$m[3]."\n");
break;
case ZEND_VM_KIND_HYBRID:
out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
out($f, $m[1]."HYBRID_SWITCH()".$m[3]."\n");
out($f,"#else\n");
case ZEND_VM_KIND_CALL:
out($f,"#if defined(ZEND_VM_FP_GLOBAL_REG) && defined(ZEND_VM_IP_GLOBAL_REG)\n");
out($f, $m[1]."((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n");
@ -1786,18 +1869,25 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
out($f,"#else\n");
out($f, $m[1]."if (UNEXPECTED((ret = ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)) != 0))".$m[3]."\n");
out($f,"#endif\n");
break;
case ZEND_VM_KIND_SWITCH:
out($f, $m[1]."dispatch_handler = OPLINE->handler;\nzend_vm_dispatch:\n".$m[1]."switch ((int)(uintptr_t)dispatch_handler)".$m[3]."\n");
break;
case ZEND_VM_KIND_GOTO:
out($f, $m[1]."goto *(void**)(OPLINE->handler);".$m[3]."\n");
if ($kind == ZEND_VM_KIND_HYBRID) {
out($f,"#endif\n");
}
break;
}
break;
case "INTERNAL_EXECUTOR":
if ($kind == ZEND_VM_KIND_CALL) {
// Executor is defined as a set of functions
if ($kind != ZEND_VM_KIND_CALL) {
// Emit executor code
if ($kind == ZEND_VM_KIND_HYBRID) {
out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
}
gen_executor_code($f, $spec, $kind, $m[1], $switch_labels);
}
if ($kind == ZEND_VM_KIND_CALL || $kind == ZEND_VM_KIND_HYBRID) {
// Executor is defined as a set of functions
if ($kind == ZEND_VM_KIND_HYBRID) {
out($f,"#else\n");
}
out($f,
"#ifdef ZEND_VM_FP_GLOBAL_REG\n" .
$m[1]."execute_data = orig_execute_data;\n" .
@ -1816,9 +1906,9 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
$m[1]."\treturn;\n".
$m[1]."}\n".
"#endif\n");
} else {
// Emit executor code
gen_executor_code($f, $spec, $kind, $m[1], $switch_labels);
if ($kind == ZEND_VM_KIND_HYBRID) {
out($f,"#endif\n");
}
}
break;
case "EXTERNAL_EXECUTOR":
@ -1835,18 +1925,31 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
if ($kind == ZEND_VM_KIND_GOTO) {
// Labels are defined in the executor itself, so we call it
// with execute_data NULL and it sets zend_opcode_handlers array
out($f,$prolog."");
out($f,$prolog."static const uint32_t specs[] = {\n");
gen_specs($f, $prolog."\t", $specs);
out($f,$prolog."};\n");
out($f,$prolog."zend_spec_handlers = specs;\n");
out($f,$prolog.$executor_name."_ex(NULL);\n");
} else {
out($f,$prolog."static const void *labels[] = {\n");
gen_labels($f, $spec, $kind, $prolog."\t", $specs, $switch_labels);
gen_labels($f, $spec, ZEND_VM_KIND_CALL, $prolog."\t", $specs, $switch_labels);
out($f,$prolog."};\n");
out($f,$prolog."static const uint32_t specs[] = {\n");
gen_specs($f, $spec, $kind, $prolog."\t", $specs);
gen_specs($f, $prolog."\t", $specs);
out($f,$prolog."};\n");
if ($kind == ZEND_VM_KIND_HYBRID) {
out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
out($f,$prolog."zend_opcode_handler_funcs = labels;\n");
out($f,$prolog."zend_spec_handlers = specs;\n");
out($f,$prolog.$executor_name."_ex(NULL);\n");
out($f,"#else\n");
}
out($f,$prolog."zend_opcode_handlers = labels;\n");
out($f,$prolog."zend_handlers_count = sizeof(labels) / sizeof(void*);\n");
out($f,$prolog."zend_spec_handlers = specs;\n");
if ($kind == ZEND_VM_KIND_HYBRID) {
out($f,"#endif\n");
}
}
break;
default:
@ -1973,22 +2076,24 @@ function gen_vm($def, $skel) {
$export = array();
foreach ($in as $line) {
++$lineno;
if (strpos($line,"ZEND_VM_HANDLER(") === 0) {
if (strpos($line,"ZEND_VM_HANDLER(") === 0 ||
strpos($line,"ZEND_VM_HOT_HANDLER(") === 0) {
// Parsing opcode handler's definition
if (preg_match(
"/^ZEND_VM_HANDLER\(\s*([0-9]+)\s*,\s*([A-Z_]+)\s*,\s*([A-Z_|]+)\s*,\s*([A-Z_|]+)\s*(,\s*([A-Z_|]+)\s*)?(,\s*SPEC\(([A-Z_|=,]+)\)\s*)?\)/",
"/^ZEND_VM_(HOT_)?HANDLER\(\s*([0-9]+)\s*,\s*([A-Z_]+)\s*,\s*([A-Z_|]+)\s*,\s*([A-Z_|]+)\s*(,\s*([A-Z_|]+)\s*)?(,\s*SPEC\(([A-Z_|=,]+)\)\s*)?\)/",
$line,
$m) == 0) {
die("ERROR ($def:$lineno): Invalid ZEND_VM_HANDLER definition.\n");
}
$code = (int)$m[1];
$op = $m[2];
$hot = !empty($m[1]);
$code = (int)$m[2];
$op = $m[3];
$len = strlen($op);
$op1 = parse_operand_spec($def, $lineno, $m[3], $flags1);
$op2 = parse_operand_spec($def, $lineno, $m[4], $flags2);
$op1 = parse_operand_spec($def, $lineno, $m[4], $flags1);
$op2 = parse_operand_spec($def, $lineno, $m[5], $flags2);
$flags = $flags1 | ($flags2 << 8);
if (!empty($m[6])) {
$flags |= parse_ext_spec($def, $lineno, $m[6]);
if (!empty($m[7])) {
$flags |= parse_ext_spec($def, $lineno, $m[7]);
}
if ($len > $max_opcode_len) {
@ -2003,9 +2108,9 @@ function gen_vm($def, $skel) {
if (isset($opnames[$op])) {
die("ERROR ($def:$lineno): Opcode with name '$op' is already defined.\n");
}
$opcodes[$code] = array("op"=>$op,"op1"=>$op1,"op2"=>$op2,"code"=>"","flags"=>$flags);
if (isset($m[8])) {
$opcodes[$code]["spec"] = parse_spec_rules($def, $lineno, $m[8]);
$opcodes[$code] = array("op"=>$op,"op1"=>$op1,"op2"=>$op2,"code"=>"","flags"=>$flags,"hot"=>$hot);
if (isset($m[9])) {
$opcodes[$code]["spec"] = parse_spec_rules($def, $lineno, $m[9]);
if (isset($opcodes[$code]["spec"]["NO_CONST_CONST"])) {
$opcodes[$code]["flags"] |= $vm_op_flags["ZEND_VM_NO_CONST_CONST"];
}
@ -2017,27 +2122,29 @@ function gen_vm($def, $skel) {
$handler = $code;
$helper = null;
$list[$lineno] = array("handler"=>$handler);
} else if (strpos($line,"ZEND_VM_TYPE_SPEC_HANDLER(") === 0) {
} else if (strpos($line,"ZEND_VM_TYPE_SPEC_HANDLER(") === 0 ||
strpos($line,"ZEND_VM_HOT_TYPE_SPEC_HANDLER(") === 0) {
// Parsing opcode handler's definition
if (preg_match(
"/^ZEND_VM_TYPE_SPEC_HANDLER\(\s*([A-Z_]+)\s*,\s*([^,]+),\s*([A-Za-z_]+)\s*,\s*([A-Z_|]+)\s*,\s*([A-Z_|]+)\s*(,\s*([A-Z_|]+)\s*)?(,\s*SPEC\(([A-Z_|=,]+)\)\s*)?\)/",
"/^ZEND_VM_(HOT_)?TYPE_SPEC_HANDLER\(\s*([A-Z_]+)\s*,\s*([^,]+),\s*([A-Za-z_]+)\s*,\s*([A-Z_|]+)\s*,\s*([A-Z_|]+)\s*(,\s*([A-Z_|]+)\s*)?(,\s*SPEC\(([A-Z_|=,]+)\)\s*)?\)/",
$line,
$m) == 0) {
die("ERROR ($def:$lineno): Invalid ZEND_VM_TYPE_HANDLER_HANDLER definition.\n");
}
$orig_op = $m[1];
$hot = !empty($m[1]);
$orig_op = $m[2];
if (!isset($opnames[$orig_op])) {
die("ERROR ($def:$lineno): Opcode with name '$orig_op' is not defined.\n");
}
$orig_code = $opnames[$orig_op];
$condition = $m[2];
$condition = $m[3];
$code = $extra_num++;
$op = $m[3];
$op1 = parse_operand_spec($def, $lineno, $m[4], $flags1);
$op2 = parse_operand_spec($def, $lineno, $m[5], $flags2);
$op = $m[4];
$op1 = parse_operand_spec($def, $lineno, $m[5], $flags1);
$op2 = parse_operand_spec($def, $lineno, $m[6], $flags2);
$flags = $flags1 | ($flags2 << 8);
if (!empty($m[7])) {
$flags |= parse_ext_spec($def, $lineno, $m[7]);
if (!empty($m[8])) {
$flags |= parse_ext_spec($def, $lineno, $m[8]);
}
if (isset($opcodes[$code])) {
@ -2045,9 +2152,9 @@ function gen_vm($def, $skel) {
}
$opcodes[$orig_code]['type_spec'][$code] = $condition;
$used_extra_spec["TYPE"] = 1;
$opcodes[$code] = array("op"=>$op,"op1"=>$op1,"op2"=>$op2,"code"=>"","flags"=>$flags);
if (isset($m[9])) {
$opcodes[$code]["spec"] = parse_spec_rules($def, $lineno, $m[9]);
$opcodes[$code] = array("op"=>$op,"op1"=>$op1,"op2"=>$op2,"code"=>"","flags"=>$flags,"hot"=>$hot);
if (isset($m[10])) {
$opcodes[$code]["spec"] = parse_spec_rules($def, $lineno, $m[10]);
if (isset($opcodes[$code]["spec"]["NO_CONST_CONST"])) {
$opcodes[$code]["flags"] |= $vm_op_flags["ZEND_VM_NO_CONST_CONST"];
}
@ -2174,7 +2281,17 @@ function gen_vm($def, $skel) {
fputs($f, "#define ZEND_VM_KIND_CALL\t" . ZEND_VM_KIND_CALL . "\n");
fputs($f, "#define ZEND_VM_KIND_SWITCH\t" . ZEND_VM_KIND_SWITCH . "\n");
fputs($f, "#define ZEND_VM_KIND_GOTO\t" . ZEND_VM_KIND_GOTO . "\n");
fputs($f, "#define ZEND_VM_KIND\t\t" . $GLOBALS["vm_kind_name"][ZEND_VM_KIND] . "\n");
fputs($f, "#define ZEND_VM_KIND_HYBRID\t" . ZEND_VM_KIND_HYBRID . "\n");
if ($GLOBALS["vm_kind_name"][ZEND_VM_KIND] === "ZEND_VM_KIND_HYBRID") {
fputs($f, "/* HYBRID requires support for computed GOTO and global register variables*/\n");
fputs($f, "#if (defined(__GNUC__) && defined(HAVE_GCC_GLOBAL_REGS))\n");
fputs($f, "# define ZEND_VM_KIND\t\tZEND_VM_KIND_HYBRID\n");
fputs($f, "#else\n");
fputs($f, "# define ZEND_VM_KIND\t\tZEND_VM_KIND_CALL\n");
fputs($f, "#endif\n");
} else {
fputs($f, "#define ZEND_VM_KIND\t\t" . $GLOBALS["vm_kind_name"][ZEND_VM_KIND] . "\n");
}
fputs($f, "\n");
foreach($vm_op_flags as $name => $val) {
fprintf($f, "#define %-24s 0x%08x\n", $name, $val);
@ -2348,6 +2465,72 @@ function gen_vm($def, $skel) {
}
out($f, "}\n\n");
if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) {
// Generate zend_vm_get_opcode_handler_func() function
out($f, "#if ZEND_VM_KIND == ZEND_VM_KIND_HYBRID\n");
out($f,"static const void *zend_vm_get_opcode_handler_func(zend_uchar opcode, const zend_op* op)\n");
out($f, "{\n");
out($f, "\tuint32_t spec = zend_spec_handlers[opcode];\n");
if (!ZEND_VM_SPEC) {
out($f, "\treturn zend_opcode_handler_funcs[spec];\n");
} else {
out($f, "\tstatic const int zend_vm_decode[] = {\n");
out($f, "\t\t_UNUSED_CODE, /* 0 */\n");
out($f, "\t\t_CONST_CODE, /* 1 = IS_CONST */\n");
out($f, "\t\t_TMP_CODE, /* 2 = IS_TMP_VAR */\n");
out($f, "\t\t_UNUSED_CODE, /* 3 */\n");
out($f, "\t\t_VAR_CODE, /* 4 = IS_VAR */\n");
out($f, "\t\t_UNUSED_CODE, /* 5 */\n");
out($f, "\t\t_UNUSED_CODE, /* 6 */\n");
out($f, "\t\t_UNUSED_CODE, /* 7 */\n");
out($f, "\t\t_UNUSED_CODE, /* 8 = IS_UNUSED */\n");
out($f, "\t\t_UNUSED_CODE, /* 9 */\n");
out($f, "\t\t_UNUSED_CODE, /* 10 */\n");
out($f, "\t\t_UNUSED_CODE, /* 11 */\n");
out($f, "\t\t_UNUSED_CODE, /* 12 */\n");
out($f, "\t\t_UNUSED_CODE, /* 13 */\n");
out($f, "\t\t_UNUSED_CODE, /* 14 */\n");
out($f, "\t\t_UNUSED_CODE, /* 15 */\n");
out($f, "\t\t_CV_CODE /* 16 = IS_CV */\n");
out($f, "\t};\n");
out($f, "\tuint32_t offset = 0;\n");
out($f, "\tif (spec & SPEC_RULE_OP1) offset = offset * 5 + zend_vm_decode[op->op1_type];\n");
out($f, "\tif (spec & SPEC_RULE_OP2) offset = offset * 5 + zend_vm_decode[op->op2_type];\n");
if (isset($used_extra_spec["OP_DATA"])) {
out($f, "\tif (spec & SPEC_RULE_OP_DATA) offset = offset * 5 + zend_vm_decode[(op + 1)->op1_type];\n");
}
if (isset($used_extra_spec["RETVAL"])) {
out($f, "\tif (spec & SPEC_RULE_RETVAL) offset = offset * 2 + (op->result_type != IS_UNUSED);\n");
}
if (isset($used_extra_spec["QUICK_ARG"])) {
out($f, "\tif (spec & SPEC_RULE_QUICK_ARG) offset = offset * 2 + (op->op2.num < MAX_ARG_FLAG_NUM);\n");
}
if (isset($used_extra_spec["SMART_BRANCH"])) {
out($f, "\tif (spec & SPEC_RULE_SMART_BRANCH) {\n");
out($f, "\t\toffset = offset * 3;\n");
out($f, "\t\tif ((op+1)->opcode == ZEND_JMPZ) {\n");
out($f, "\t\t\toffset += 1;\n");
out($f, "\t\t} else if ((op+1)->opcode == ZEND_JMPNZ) {\n");
out($f, "\t\t\toffset += 2;\n");
out($f, "\t\t}\n");
out($f, "\t}\n");
}
if (isset($used_extra_spec["DIM_OBJ"])) {
out($f, "\tif (spec & SPEC_RULE_DIM_OBJ) {\n");
out($f, "\t\toffset = offset * 3;\n");
out($f, "\t\tif (op->extended_value == ZEND_ASSIGN_DIM) {\n");
out($f, "\t\t\toffset += 1;\n");
out($f, "\t\t} else if (op->extended_value == ZEND_ASSIGN_OBJ) {\n");
out($f, "\t\t\toffset += 2;\n");
out($f, "\t\t}\n");
out($f, "\t}\n");
}
out($f, "\treturn zend_opcode_handler_funcs[(spec & SPEC_START_MASK) + offset];\n");
}
out($f, "}\n\n");
out($f, "#endif\n\n");
}
// Generate zend_vm_get_opcode_handler() function
out($f, "ZEND_API void zend_vm_set_opcode_handler(zend_op* op)\n");
out($f, "{\n");
@ -2405,9 +2588,14 @@ function gen_vm($def, $skel) {
out($f, "}\n\n");
// Generate zend_vm_call_opcode_handler() function
if (ZEND_VM_KIND == ZEND_VM_KIND_CALL) {
if (ZEND_VM_KIND == ZEND_VM_KIND_CALL || ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) {
out($f, "ZEND_API int zend_vm_call_opcode_handler(zend_execute_data* ex)\n");
out($f, "{\n");
if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) {
out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
out($f, "\topcode_handler_t handler;\n");
out($f,"#endif\n");
}
out($f, "\tint ret;\n");
out($f, "#ifdef ZEND_VM_IP_GLOBAL_REG\n");
out($f, "\tconst zend_op *orig_opline = opline;\n");
@ -2421,8 +2609,20 @@ function gen_vm($def, $skel) {
out($f, "\n");
out($f, "\tLOAD_OPLINE();\n");
out($f,"#if defined(ZEND_VM_FP_GLOBAL_REG) && defined(ZEND_VM_IP_GLOBAL_REG)\n");
if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) {
out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
out($f, "\thandler = (opcode_handler_t)zend_vm_get_opcode_handler_func(opline->opcode, opline);\n");
out($f, "\thandler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n");
out($f, "\tif (EXPECTED(opline != &hybrid_halt_op)) {\n");
out($f,"#else\n");
}
out($f, "\t((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n");
out($f, "\tif (EXPECTED(opline)) {\n");
if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) {
out($f, "\tif (EXPECTED(opline)) {\n");
out($f,"#endif\n");
} else {
out($f, "\tif (EXPECTED(opline)) {\n");
}
out($f, "\t\tret = execute_data != ex ? (int)(execute_data->prev_execute_data != ex) + 1 : 0;\n");
out($f, "\t\tSAVE_OPLINE();\n");
out($f, "\t} else {\n");
@ -2523,9 +2723,9 @@ function gen_vm($def, $skel) {
function usage() {
echo("\nUsage: php zend_vm_gen.php [options]\n".
"\nOptions:".
"\n --with-vm-kind=CALL|SWITCH|GOTO - select threading model (default is CALL)".
"\n --without-specializer - disable executor specialization".
"\n --with-lines - enable #line directives".
"\n --with-vm-kind=CALL|SWITCH|GOTO|HYBRID - select threading model (default is HYBRID)".
"\n --without-specializer - disable executor specialization".
"\n --with-lines - enable #line directives".
"\n\n");
}
@ -2543,6 +2743,9 @@ for ($i = 1; $i < $argc; $i++) {
case "GOTO":
define("ZEND_VM_KIND", ZEND_VM_KIND_GOTO);
break;
case "HYBRID":
define("ZEND_VM_KIND", ZEND_VM_KIND_HYBRID);
break;
default:
echo("ERROR: Invalid vm kind '$kind'\n");
usage();
@ -2567,7 +2770,7 @@ for ($i = 1; $i < $argc; $i++) {
// Using defaults
if (!defined("ZEND_VM_KIND")) {
// Using CALL threading by default
define("ZEND_VM_KIND", ZEND_VM_KIND_CALL);
define("ZEND_VM_KIND", ZEND_VM_KIND_HYBRID);
}
if (!defined("ZEND_VM_SPEC")) {
// Using specialized executor by default

View File

@ -21,7 +21,7 @@
#include <stdio.h>
#include <zend.h>
static const char *zend_vm_opcodes_names[189] = {
static const char *zend_vm_opcodes_names[194] = {
"ZEND_NOP",
"ZEND_ADD",
"ZEND_SUB",
@ -211,9 +211,14 @@ static const char *zend_vm_opcodes_names[189] = {
"ZEND_ISSET_ISEMPTY_THIS",
"ZEND_SWITCH_LONG",
"ZEND_SWITCH_STRING",
"ZEND_IN_ARRAY",
"ZEND_COUNT",
"ZEND_GET_CLASS",
"ZEND_GET_CALLED_CLASS",
"ZEND_GET_TYPE",
};
static uint32_t zend_vm_opcodes_flags[189] = {
static uint32_t zend_vm_opcodes_flags[194] = {
0x00000000,
0x00000707,
0x00000707,
@ -403,6 +408,11 @@ static uint32_t zend_vm_opcodes_flags[189] = {
0x00000101,
0x03000307,
0x03000307,
0x01000303,
0x00000103,
0x00000103,
0x00000101,
0x00000103,
};
ZEND_API const char* zend_get_opcode_name(zend_uchar opcode) {

View File

@ -26,7 +26,13 @@
#define ZEND_VM_KIND_CALL 1
#define ZEND_VM_KIND_SWITCH 2
#define ZEND_VM_KIND_GOTO 3
#define ZEND_VM_KIND ZEND_VM_KIND_CALL
#define ZEND_VM_KIND_HYBRID 4
/* HYBRID requires support for computed GOTO and global register variables*/
#if (defined(__GNUC__) && defined(HAVE_GCC_GLOBAL_REGS))
# define ZEND_VM_KIND ZEND_VM_KIND_HYBRID
#else
# define ZEND_VM_KIND ZEND_VM_KIND_CALL
#endif
#define ZEND_VM_OP_SPEC 0x00000001
#define ZEND_VM_OP_CONST 0x00000002
@ -254,7 +260,12 @@ END_EXTERN_C()
#define ZEND_ISSET_ISEMPTY_THIS 186
#define ZEND_SWITCH_LONG 187
#define ZEND_SWITCH_STRING 188
#define ZEND_IN_ARRAY 189
#define ZEND_COUNT 190
#define ZEND_GET_CLASS 191
#define ZEND_GET_CALLED_CLASS 192
#define ZEND_GET_TYPE 193
#define ZEND_VM_LAST_OPCODE 188
#define ZEND_VM_LAST_OPCODE 193
#endif

View File

@ -27,7 +27,7 @@ if %errorlevel% neq 0 exit /b 3
if "%THREAD_SAFE%" equ "0" set ADD_CONF=--disable-zts
set EXT_EXCLUDE_FROM_TEST=snmp,oci8_12c,pdo_oci,pdo_odbc,odbc,pdo_firebird,interbase,ldap,imap,dba
set EXT_EXCLUDE_FROM_TEST=snmp,oci8_12c,pdo_oci,pdo_odbc,odbc,pdo_firebird,interbase,ldap,imap
if "%OPCACHE%" equ "0" set EXT_EXCLUDE_FROM_TEST=%EXT_EXCLUDE_FROM_TEST%,opcache
call configure.bat ^

View File

@ -71,5 +71,5 @@ copy %PHP_BUILD_CACHE_ENCHANT_DICT_DIR%\* %USERPROFILE%\enchant\myspell
mkdir c:\tests_tmp
cd "%APPVEYOR_BUILD_FOLDER%"
nmake test TESTS="%OPCACHE_OPTS% -q --offline --show-diff --set-timeout 120 -g FAIL,XFAIL,BORK,WARN,LEAK,SKIP --temp-source c:\tests_tmp --temp-target c:\tests_tmp"
nmake test TESTS="%OPCACHE_OPTS% -q --offline --show-diff --show-slow 1000 --set-timeout 120 -g FAIL,XFAIL,BORK,WARN,LEAK,SKIP --temp-source c:\tests_tmp --temp-target c:\tests_tmp"

View File

@ -461,6 +461,7 @@ limits.h \
locale.h \
monetary.h \
netdb.h \
poll.h \
pwd.h \
resolv.h \
signal.h \

View File

@ -0,0 +1,30 @@
--TEST--
Test for bug #74652: Incomplete dates
--INI--
date.timezone=UTC
--FILE--
<?php
$formats = [
'2017-03-25 10:52:09',
'2017-03-25 10:52',
'2017-03-25 10am',
'2017-03-25',
'2017-03',
'2017.042',
'2017043',
];
foreach ( $formats as $format )
{
$dt = new DateTimeImmutable( $format );
echo $dt->format( 'Y-m-d H:i:s' ), "\n";
}
?>
--EXPECT--
2017-03-25 10:52:09
2017-03-25 10:52:00
2017-03-25 10:00:00
2017-03-25 00:00:00
2017-03-01 00:00:00
2017-02-11 00:00:00
2017-02-12 00:00:00

View File

@ -100,6 +100,9 @@ PHP_ARG_WITH(dbm,,
PHP_ARG_WITH(tcadb,,
[ --with-tcadb[=DIR] DBA: Tokyo Cabinet abstract DB support], no, no)
PHP_ARG_WITH(lmdb,,
[ --with-lmdb[=DIR] DBA: Lightning memory-mapped database support], no, no)
dnl
dnl Library checks
@ -228,6 +231,37 @@ if test "$PHP_TCADB" != "no"; then
fi
PHP_DBA_STD_RESULT(tcadb)
dnl LMDB
if test "$PHP_LMDB" != "no"; then
PHP_DBA_STD_BEGIN
for i in $PHP_LMDB /usr/local /usr; do
if test -f "$i/include/lmdb.h"; then
THIS_PREFIX=$i
PHP_ADD_INCLUDE($THIS_PREFIX/include)
THIS_INCLUDE=$i/include/lmdb.h
break
fi
done
if test -n "$THIS_INCLUDE"; then
for LIB in lmdb; do
PHP_CHECK_LIBRARY($LIB, mdb_env_open, [
AC_DEFINE_UNQUOTED(LMDB_INCLUDE_FILE, "$THIS_INCLUDE", [ ])
AC_DEFINE(DBA_LMDB, 1, [ ])
THIS_LIBS=$LIB
], [], [-L$THIS_PREFIX/$PHP_LIBDIR])
if test -n "$THIS_LIBS"; then
break
fi
done
fi
PHP_DBA_STD_ASSIGN
PHP_DBA_STD_CHECK
PHP_DBA_STD_ATTACH
fi
PHP_DBA_STD_RESULT(lmdb)
dnl Berkeley specific (library and version test)
dnl parameters(version, library list, function)
AC_DEFUN([PHP_DBA_DB_CHECK],[
@ -629,7 +663,7 @@ if test "$HAVE_DBA" = "1"; then
AC_MSG_RESULT([yes])
fi
AC_DEFINE(HAVE_DBA, 1, [ ])
PHP_NEW_EXTENSION(dba, dba.c dba_cdb.c dba_dbm.c dba_gdbm.c dba_ndbm.c dba_db1.c dba_db2.c dba_db3.c dba_db4.c dba_flatfile.c dba_inifile.c dba_qdbm.c dba_tcadb.c $cdb_sources $flat_sources $ini_sources, $ext_shared)
PHP_NEW_EXTENSION(dba, dba.c dba_cdb.c dba_dbm.c dba_gdbm.c dba_ndbm.c dba_db1.c dba_db2.c dba_db3.c dba_db4.c dba_flatfile.c dba_inifile.c dba_qdbm.c dba_tcadb.c dba_lmdb.c $cdb_sources $flat_sources $ini_sources, $ext_shared)
PHP_ADD_BUILD_DIR($ext_builddir/libinifile)
PHP_ADD_BUILD_DIR($ext_builddir/libcdb)
PHP_ADD_BUILD_DIR($ext_builddir/libflatfile)

View File

@ -4,6 +4,7 @@
ARG_WITH("dba", "DBA support", "no");
ARG_WITH("qdbm", "DBA: QDBM support", "no");
ARG_WITH("db", "DBA: Berkeley DB support", "no");
ARG_WITH("lmdb", "DBA: Lightning memory-mapped database support", "no");
if (PHP_DBA != "no") {
EXTENSION("dba", "dba.c dba_cdb.c dba_db1.c dba_db2.c dba_db3.c dba_dbm.c dba_flatfile.c dba_gdbm.c dba_ndbm.c dba_inifile.c");
@ -32,4 +33,16 @@ if (PHP_DBA != "no") {
WARNING("dba: qdbm handlers not enabled; libraries and headers not found");
}
}
if (PHP_LMDB != "no") {
if (CHECK_LIB("liblmdb_a.lib", "dba", PHP_DBA) &&
CHECK_HEADER_ADD_INCLUDE("lmdb.h", "CFLAGS_DBA") &&
CHECK_LIB("ntdll.lib", "dba", PHP_DBA)) {
ADD_SOURCES("ext/dba", "dba_lmdb.c", "dba");
AC_DEFINE("LMDB_INCLUDE_FILE", "<lmdb.h>", "", false);
AC_DEFINE("DBA_LMDB", 1, "");
} else {
WARNING("dba: lmdb handlers not enabled; libraries and headers not found");
}
}
}

View File

@ -51,6 +51,7 @@
#include "php_inifile.h"
#include "php_qdbm.h"
#include "php_tcadb.h"
#include "php_lmdb.h"
/* {{{ arginfo */
ZEND_BEGIN_ARG_INFO_EX(arginfo_dba_popen, 0, 0, 2)
@ -362,6 +363,9 @@ static dba_handler handler[] = {
#endif
#if DBA_TCADB
DBA_HND(tcadb, DBA_LOCK_ALL)
#endif
#if DBA_LMDB
DBA_HND(lmdb, DBA_LOCK_EXT)
#endif
{ NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};
@ -386,6 +390,8 @@ static dba_handler handler[] = {
#define DBA_DEFAULT "qdbm"
#elif DBA_TCADB
#define DBA_DEFAULT "tcadb"
#elif DBA_LMDB
#define DBA_DEFAULT "lmdb"
#else
#define DBA_DEFAULT ""
#endif
@ -644,6 +650,10 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
int persistent_flag = persistent ? STREAM_OPEN_PERSISTENT : 0;
zend_string *opened_path = NULL;
char *lock_name;
#ifdef PHP_WIN32
zend_bool restarted = 0;
zend_bool need_creation = 0;
#endif
if (ac < 2) {
WRONG_PARAM_COUNT;
@ -762,7 +772,13 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
lock_mode = (lock_flag & DBA_LOCK_WRITER) ? LOCK_EX : 0;
file_mode = "r+b";
break;
case 'c':
case 'c': {
#ifdef PHP_WIN32
if (hptr->flags & (DBA_NO_APPEND|DBA_CAST_AS_FD)) {
php_stream_statbuf ssb;
need_creation = (SUCCESS != php_stream_stat_path(Z_STRVAL(args[0]), &ssb));
}
#endif
modenr = DBA_CREAT;
lock_mode = (lock_flag & DBA_LOCK_CREAT) ? LOCK_EX : 0;
if (lock_mode) {
@ -771,18 +787,34 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
* when the lib opens the file it is already created
*/
file_mode = "r+b"; /* read & write, seek 0 */
#ifdef PHP_WIN32
if (!need_creation) {
lock_file_mode = "r+b";
} else
#endif
lock_file_mode = "a+b"; /* append */
} else {
#ifdef PHP_WIN32
if (!need_creation) {
file_mode = "r+b";
} else
#endif
file_mode = "a+b"; /* append */
lock_file_mode = "w+b"; /* create/truncate */
}
} else {
#ifdef PHP_WIN32
if (!need_creation) {
file_mode = "r+b";
} else
#endif
file_mode = "a+b";
}
/* In case of the 'a+b' append mode, the handler is responsible
* to handle any rewind problems (see flatfile handler).
*/
break;
}
case 'n':
modenr = DBA_TRUNC;
lock_mode = (lock_flag & DBA_LOCK_TRUNC) ? LOCK_EX : 0;
@ -849,6 +881,9 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
}
}
#ifdef PHP_WIN32
restart:
#endif
if (!error && lock_mode) {
if (lock_dbf) {
lock_name = Z_STRVAL(args[0]);
@ -926,9 +961,27 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
} else if (modenr == DBA_CREAT) {
int flags = fcntl(info->fd, F_GETFL);
fcntl(info->fd, F_SETFL, flags & ~O_APPEND);
#elif defined(PHP_WIN32)
} else if (modenr == DBA_CREAT && need_creation && !restarted) {
zend_bool close_both;
close_both = (info->fp != info->lock.fp);
php_stream_close(info->lock.fp);
if (close_both) {
php_stream_close(info->fp);
}
info->fp = NULL;
info->lock.fp = NULL;
info->fd = -1;
pefree(info->lock.name, persistent);
lock_file_mode = "r+b";
restarted = 1;
goto restart;
#endif
}
}
}

354
ext/dba/dba_lmdb.c Normal file
View File

@ -0,0 +1,354 @@
/*
+----------------------------------------------------------------------+
| PHP Version 7 |
+----------------------------------------------------------------------+
| Copyright (c) 2017 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Anatol Belski <ab@php.net> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#if DBA_LMDB
#include "php_lmdb.h"
#ifdef LMDB_INCLUDE_FILE
#include LMDB_INCLUDE_FILE
#endif
struct php_lmdb_info {
MDB_env *env;
MDB_txn *txn;
MDB_dbi dbi;
MDB_cursor *cur;
};
#define LMDB_IT(it) (((struct php_lmdb_info *)info->dbf)->it)
DBA_OPEN_FUNC(lmdb)
{
MDB_env *env;
MDB_txn *txn;
int rc, mode = 0644, flags = MDB_NOSUBDIR;
if(info->argc > 0) {
convert_to_long_ex(&info->argv[0]);
mode = Z_LVAL(info->argv[0]);
/* TODO implement handling of the additional flags. */
}
rc = mdb_env_create(&env);
if (rc) {
*error = mdb_strerror(rc);
return FAILURE;
}
rc = mdb_env_open(env, info->path, flags, mode);
if (rc) {
*error = mdb_strerror(rc);
return FAILURE;
}
rc = mdb_txn_begin(env, NULL, 0, &txn);
if (rc) {
mdb_env_close(env);
*error = mdb_strerror(rc);
return FAILURE;
}
info->dbf = pemalloc(sizeof(struct php_lmdb_info), info->flags & DBA_PERSISTENT);
if (!info->dbf) {
*error = "Failed to allocate php_lmdb_info.";
return FAILURE;
}
memset(info->dbf, 0, sizeof(struct php_lmdb_info));
rc = mdb_dbi_open(txn, NULL, 0, &LMDB_IT(dbi));
if (rc) {
mdb_env_close(env);
pefree(info->dbf, info->flags & DBA_PERSISTENT);
*error = mdb_strerror(rc);
return FAILURE;
}
LMDB_IT(env) = env;
LMDB_IT(txn) = txn;
mdb_txn_abort(LMDB_IT(txn));
return SUCCESS;
}
DBA_CLOSE_FUNC(lmdb)
{
mdb_dbi_close(LMDB_IT(env), LMDB_IT(dbi));
mdb_env_close(LMDB_IT(env));
pefree(info->dbf, info->flags & DBA_PERSISTENT);
}
DBA_FETCH_FUNC(lmdb)
{
int rc;
MDB_val k, v;
char *ret = NULL;
if (LMDB_IT(cur)) {
rc = mdb_txn_renew(LMDB_IT(txn));
} else {
rc = mdb_txn_begin(LMDB_IT(env), NULL, MDB_RDONLY, &LMDB_IT(txn));
}
if (rc) {
php_error_docref1(NULL, key, E_WARNING, "%s", mdb_strerror(rc));
return NULL;
}
k.mv_size = keylen;
k.mv_data = key;
rc = mdb_get(LMDB_IT(txn), LMDB_IT(dbi), &k, &v);
if (rc) {
if (MDB_NOTFOUND != rc) {
php_error_docref1(NULL, key, E_WARNING, "%s", mdb_strerror(rc));
}
mdb_txn_abort(LMDB_IT(txn));
return NULL;
}
if (v.mv_data) {
if(newlen) *newlen = v.mv_size;
ret = estrndup(v.mv_data, v.mv_size);
}
if (LMDB_IT(cur)) {
mdb_txn_reset(LMDB_IT(txn));
} else {
mdb_txn_abort(LMDB_IT(txn));
}
return ret;
}
DBA_UPDATE_FUNC(lmdb)
{
int rc;
MDB_val k, v;
rc = mdb_txn_begin(LMDB_IT(env), NULL, 0, &LMDB_IT(txn));
if (rc) {
php_error_docref2(NULL, key, val, E_WARNING, "%s", mdb_strerror(rc));
return FAILURE;
}
k.mv_size = keylen;
k.mv_data = key;
v.mv_size = vallen;
v.mv_data = val;
rc = mdb_put(LMDB_IT(txn), LMDB_IT(dbi), &k, &v, mode == 1 ? MDB_NOOVERWRITE : 0);
if (rc) {
if (MDB_KEYEXIST != rc) {
php_error_docref2(NULL, key, val, E_WARNING, "%s", mdb_strerror(rc));
}
mdb_txn_abort(LMDB_IT(txn));
return FAILURE;
}
rc = mdb_txn_commit(LMDB_IT(txn));
if (rc) {
php_error_docref2(NULL, key, val, E_WARNING, "%s", mdb_strerror(rc));
mdb_txn_abort(LMDB_IT(txn));
return FAILURE;
}
return SUCCESS;
}
DBA_EXISTS_FUNC(lmdb)
{
int rc;
MDB_val k, v;
if (LMDB_IT(cur)) {
rc = mdb_txn_renew(LMDB_IT(txn));
} else {
rc = mdb_txn_begin(LMDB_IT(env), NULL, MDB_RDONLY, &LMDB_IT(txn));
}
if (rc) {
php_error_docref1(NULL, key, E_WARNING, "%s", mdb_strerror(rc));
return FAILURE;
}
k.mv_size = keylen;
k.mv_data = key;
rc = mdb_get(LMDB_IT(txn), LMDB_IT(dbi), &k, &v);
if (rc) {
if (MDB_NOTFOUND != rc) {
php_error_docref1(NULL, key, E_WARNING, "%s", mdb_strerror(rc));
}
mdb_txn_abort(LMDB_IT(txn));
return FAILURE;
}
if (LMDB_IT(cur)) {
mdb_txn_reset(LMDB_IT(txn));
} else {
mdb_txn_abort(LMDB_IT(txn));
}
return SUCCESS;
}
DBA_DELETE_FUNC(lmdb)
{
int rc;
MDB_val k;
rc = mdb_txn_begin(LMDB_IT(env), NULL, 0, &LMDB_IT(txn));
if (rc) {
php_error_docref1(NULL, key, E_WARNING, "%s", mdb_strerror(rc));
return FAILURE;
}
k.mv_size = keylen;
k.mv_data = key;
rc = mdb_del(LMDB_IT(txn), LMDB_IT(dbi), &k, NULL);
if (!rc) {
rc = mdb_txn_commit(LMDB_IT(txn));
if (rc) {
php_error_docref1(NULL, key, E_WARNING, "%s", mdb_strerror(rc));
mdb_txn_abort(LMDB_IT(txn));
return FAILURE;
}
return SUCCESS;
}
php_error_docref1(NULL, key, E_WARNING, "%s", mdb_strerror(rc));
return FAILURE;
}
DBA_FIRSTKEY_FUNC(lmdb)
{
int rc;
MDB_val k, v;
char *ret = NULL;
rc = mdb_txn_begin(LMDB_IT(env), NULL, MDB_RDONLY, &LMDB_IT(txn));
if (rc) {
php_error_docref0(NULL, E_WARNING, "%s", mdb_strerror(rc));
return NULL;
}
rc = mdb_cursor_open(LMDB_IT(txn), LMDB_IT(dbi), &LMDB_IT(cur));
if (rc) {
mdb_txn_abort(LMDB_IT(txn));
php_error_docref0(NULL, E_WARNING, "%s", mdb_strerror(rc));
return NULL;
}
rc = mdb_cursor_get(LMDB_IT(cur), &k, &v, MDB_FIRST);
if (rc) {
mdb_txn_abort(LMDB_IT(txn));
mdb_cursor_close(LMDB_IT(cur));
LMDB_IT(cur) = NULL;
if (MDB_NOTFOUND != rc) {
php_error_docref0(NULL, E_WARNING, "%s", mdb_strerror(rc));
}
return NULL;
}
if(k.mv_data) {
if(newlen) *newlen = k.mv_size;
ret = estrndup(k.mv_data, k.mv_size);
}
mdb_txn_reset(LMDB_IT(txn));
return ret;
}
DBA_NEXTKEY_FUNC(lmdb)
{
int rc;
MDB_val k, v;
char *ret = NULL;
rc = mdb_txn_renew(LMDB_IT(txn));
if (rc) {
php_error_docref0(NULL, E_WARNING, "%s", mdb_strerror(rc));
return NULL;
}
rc = mdb_cursor_get(LMDB_IT(cur), &k, &v, MDB_NEXT);
if (rc) {
mdb_txn_abort(LMDB_IT(txn));
mdb_cursor_close(LMDB_IT(cur));
LMDB_IT(cur) = NULL;
if (MDB_NOTFOUND != rc) {
php_error_docref0(NULL, E_WARNING, "%s", mdb_strerror(rc));
}
return NULL;
}
if(k.mv_data) {
if(newlen) *newlen = k.mv_size;
ret = estrndup(k.mv_data, k.mv_size);
}
mdb_txn_reset(LMDB_IT(txn));
return ret;
}
DBA_OPTIMIZE_FUNC(lmdb)
{
return SUCCESS;
}
DBA_SYNC_FUNC(lmdb)
{
int rc;
rc = mdb_env_sync(LMDB_IT(env), 1);
if (rc) {
php_error_docref0(NULL, E_WARNING, "%s", mdb_strerror(rc));
return FAILURE;
}
return SUCCESS;
}
DBA_INFO_FUNC(lmdb)
{
return estrdup(MDB_VERSION_STRING);
}
#endif
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: sw=4 ts=4 fdm=marker
* vim<600: sw=4 ts=4
*/

12
ext/dba/php_lmdb.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef PHP_LMDB_H
#define PHP_LMDB_H
#if DBA_LMDB
#include "php_dba.h"
DBA_FUNCS(lmdb);
#endif
#endif

View File

@ -0,0 +1,28 @@
--TEST--
Bug #72885 flatfile: dba_fetch() fails to read replaced entry
--SKIPIF--
<?php
$handler = "flatfile";
require_once(dirname(__FILE__) .'/skipif.inc');
?>
--FILE--
<?php
require_once(dirname(__FILE__) .'/test.inc');
$db = dba_open($db_filename, 'c', 'flatfile');
dba_insert('foo', 'bar', $db);
var_dump(dba_replace('foo', 'baz', $db));
var_dump(dba_fetch('foo', $db));
dba_close($db);
?>
===DONE===
--CLEAN--
<?php
require_once(dirname(__FILE__) .'/clean.inc');
?>
--EXPECT--
bool(true)
string(3) "baz"
===DONE===

View File

@ -2,4 +2,5 @@
$db_filename = dirname(__FILE__) .'/test0.dbm'; // see test.inc
@unlink($db_filename);
@unlink($db_filename.'.lck');
@unlink($db_filename.'-lock');
?>

View File

@ -0,0 +1,38 @@
--TEST--
DBA LMDB handler test
--SKIPIF--
<?php
$handler = 'lmdb';
require_once dirname(__FILE__) .'/skipif.inc';
?>
--FILE--
<?php
$handler = 'lmdb';
require_once dirname(__FILE__) .'/test.inc';
$lock_flag = ''; // lock in library
require_once dirname(__FILE__) .'/dba_handler.inc';
?>
===DONE===
--CLEAN--
<?php
require_once dirname(__FILE__) .'/clean.inc';
?>
--EXPECTF--
database handler: lmdb
3NYNYY
Content String 2
Content 2 replaced
Read during write:%sallowed
"key number 6" written
Failed to write "key number 6" 2nd time
Content 2 replaced 2nd time
The 6th value
array(3) {
["key number 6"]=>
string(13) "The 6th value"
["key2"]=>
string(27) "Content 2 replaced 2nd time"
["key5"]=>
string(23) "The last content string"
}
===DONE===

View File

@ -31,6 +31,4 @@ array(3) {
["key5"]=>
string(23) "The last content string"
}
Warning: dba_popen(%stest0.dbm,r-): Locking cannot be disabled for handler qdbm in %sdba_handler.inc on line %d
===DONE===

View File

@ -144,9 +144,9 @@ PHP_MINFO_FUNCTION(exif)
php_info_print_table_row(2, "Multibyte decoding support using mbstring", "disabled");
}
php_info_print_table_row(2, "Extended EXIF tag formats", "Canon, Casio, Fujifilm, Nikon, Olympus, Samsung, Panasonic, DJI, Sony, Pentax, Minolta, Sigma, Foveon");
php_info_print_table_row(2, "Extended EXIF tag formats", "Canon, Casio, Fujifilm, Nikon, Olympus, Samsung, Panasonic, DJI, Sony, Pentax, Minolta, Sigma, Foveon, Kyocera, Ricoh, AGFA, Epson");
php_info_print_table_end();
DISPLAY_INI_ENTRIES();
}
/* }}} */
@ -1318,6 +1318,20 @@ static tag_info_array tag_table_VND_SIGMA = {
TAG_TABLE_END
};
static tag_info_array tag_table_VND_KYOCERA = {
{ 0x0001, "FormatThumbnail"},
{ 0x0E00, "PrintImageMatchingInfo"},
TAG_TABLE_END
};
static tag_info_array tag_table_VND_RICOH = {
{ 0x0001, "MakerNoteDataType"},
{ 0x0002, "Version"},
{ 0x0E00, "PrintImageMatchingInfo"},
{ 0x2001, "RicohCameraInfoMakerNoteSubIFD"},
TAG_TABLE_END
};
typedef enum mn_byte_order_t {
MN_ORDER_INTEL = 0,
MN_ORDER_MOTOROLA = 1,
@ -1343,20 +1357,27 @@ typedef struct {
/* Remember to update PHP_MINFO if updated */
static const maker_note_type maker_note_array[] = {
{ tag_table_VND_CANON, "Canon", NULL, NULL, 0, 0, MN_ORDER_INTEL, MN_OFFSET_GUESS},
{ tag_table_VND_CASIO, "CASIO", NULL, NULL, 0, 0, MN_ORDER_MOTOROLA, MN_OFFSET_NORMAL},
{ tag_table_VND_FUJI, "FUJIFILM", NULL, "FUJIFILM\x0C\x00\x00\x00", 12, 12, MN_ORDER_INTEL, MN_OFFSET_MAKER},
{ tag_table_VND_NIKON, "NIKON", NULL, "Nikon\x00\x01\x00", 8, 8, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
{ tag_table_VND_NIKON_990, "NIKON", NULL, NULL, 0, 0, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
{ tag_table_VND_OLYMPUS, "OLYMPUS OPTICAL CO.,LTD", NULL, "OLYMP\x00\x01\x00", 8, 8, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
{ tag_table_VND_SAMSUNG, "SAMSUNG", NULL, NULL, 0, 0, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
{ tag_table_VND_PANASONIC, "Panasonic", NULL, "Panasonic\x00\x00\x00", 12, 12, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
{ tag_table_VND_DJI, "DJI", NULL, NULL, 0, 0, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
{ tag_table_VND_SONY, "SONY", NULL, "SONY DSC \x00\x00\x00", 12, 12, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
{ tag_table_VND_PENTAX, "PENTAX", NULL, "AOC\x00", 6, 6, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
{ tag_table_VND_MINOLTA, "Minolta, KONICA MINOLTA", NULL, NULL, 0, 0, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
{ tag_table_VND_SIGMA, "SIGMA, FOVEON", NULL, "SIGMA\x00\x00\x00", 10, 10, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
{ tag_table_VND_SIGMA, "SIGMA, FOVEON", NULL, "FOVEON\x00\x00\x00", 10, 10, MN_ORDER_NORMAL, MN_OFFSET_NORMAL}
{ tag_table_VND_CANON, "Canon", NULL, NULL, 0, 0, MN_ORDER_INTEL, MN_OFFSET_GUESS},
{ tag_table_VND_CASIO, "CASIO", NULL, NULL, 0, 0, MN_ORDER_MOTOROLA, MN_OFFSET_NORMAL},
{ tag_table_VND_FUJI, "FUJIFILM", NULL, "FUJIFILM\x0C\x00\x00\x00", 12, 12, MN_ORDER_INTEL, MN_OFFSET_MAKER},
{ tag_table_VND_NIKON, "NIKON", NULL, "Nikon\x00\x01\x00", 8, 8, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
{ tag_table_VND_NIKON_990, "NIKON", NULL, NULL, 0, 0, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
{ tag_table_VND_OLYMPUS, "OLYMPUS OPTICAL CO.,LTD", NULL, "OLYMP\x00\x01\x00", 8, 8, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
{ tag_table_VND_SAMSUNG, "SAMSUNG", NULL, NULL, 0, 0, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
{ tag_table_VND_PANASONIC, "Panasonic", NULL, "Panasonic\x00\x00\x00", 12, 12, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
{ tag_table_VND_DJI, "DJI", NULL, NULL, 0, 0, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
{ tag_table_VND_SONY, "SONY", NULL, "SONY DSC \x00\x00\x00", 12, 12, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
{ tag_table_VND_PENTAX, "PENTAX", NULL, "AOC\x00", 6, 6, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
{ tag_table_VND_MINOLTA, "Minolta, KONICA MINOLTA", NULL, NULL, 0, 0, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
{ tag_table_VND_SIGMA, "SIGMA, FOVEON", NULL, "SIGMA\x00\x00\x00", 10, 10, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
{ tag_table_VND_SIGMA, "SIGMA, FOVEON", NULL, "FOVEON\x00\x00\x00", 10, 10, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
{ tag_table_VND_KYOCERA, "KYOCERA, CONTAX", NULL, "KYOCERA \x00\x00\x00", 22, 22, MN_ORDER_NORMAL, MN_OFFSET_MAKER},
{ tag_table_VND_RICOH, "RICOH", NULL, "Ricoh", 5, 5, MN_ORDER_MOTOROLA, MN_OFFSET_NORMAL},
{ tag_table_VND_RICOH, "RICOH", NULL, "RICOH", 5, 5, MN_ORDER_MOTOROLA, MN_OFFSET_NORMAL},
/* These re-uses existing formats */
{ tag_table_VND_OLYMPUS, "AGFA", NULL, "AGFA \x00\x01", 8, 8, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
{ tag_table_VND_OLYMPUS, "EPSON", NULL, "EPSON\x00\x01\x00", 8, 8, MN_ORDER_NORMAL, MN_OFFSET_NORMAL}
};
/* }}} */

View File

@ -25,15 +25,24 @@ if test "$PHP_HASH" != "no"; then
AC_CHECK_SIZEOF(long, 4)
AC_CHECK_SIZEOF(long long, 8)
PHP_CHECK_64BIT([
SHA3_DIR="sha3/generic32lc"
SHA3_OPT_SRC="$SHA3_DIR/KeccakP-1600-inplace32BI.c"
],[
SHA3_DIR="sha3/generic64lc"
SHA3_OPT_SRC="$SHA3_DIR/KeccakP-1600-opt64.c"
])
EXT_HASH_SHA3_SOURCES="$SHA3_OPT_SRC $SHA3_DIR/KeccakHash.c $SHA3_DIR/KeccakSponge.c"
PHP_HASH_CFLAGS="-I@ext_srcdir@/$SHA3_DIR -DKeccakP200_excluded -DKeccakP400_excluded -DKeccakP800_excluded"
EXT_HASH_SOURCES="hash.c hash_md.c hash_sha.c hash_ripemd.c hash_haval.c \
hash_tiger.c hash_gost.c hash_snefru.c hash_whirlpool.c hash_adler32.c \
hash_crc32.c hash_fnv.c hash_joaat.c hash_sha3.c"
hash_crc32.c hash_fnv.c hash_joaat.c hash_sha3.c $EXT_HASH_SHA3_SOURCES"
EXT_HASH_HEADERS="php_hash.h php_hash_md.h php_hash_sha.h php_hash_ripemd.h \
php_hash_haval.h php_hash_tiger.h php_hash_gost.h php_hash_snefru.h \
php_hash_whirlpool.h php_hash_adler32.h php_hash_crc32.h \
php_hash_fnv.h php_hash_joaat.h php_hash_sha3.h"
PHP_NEW_EXTENSION(hash, $EXT_HASH_SOURCES, $ext_shared)
PHP_NEW_EXTENSION(hash, $EXT_HASH_SOURCES, $ext_shared,,$PHP_HASH_CFLAGS)
ifdef([PHP_INSTALL_HEADERS], [
PHP_INSTALL_HEADERS(ext/hash, $EXT_HASH_HEADERS)
])

View File

@ -12,13 +12,24 @@ if (PHP_MHASH != "no") {
}
if (PHP_HASH != "no") {
AC_DEFINE('HAVE_HASH_EXT', 1);
EXTENSION("hash", "hash.c hash_md.c hash_sha.c hash_ripemd.c hash_haval.c "
+ "hash_tiger.c hash_gost.c hash_snefru.c hash_whirlpool.c "
+ "hash_adler32.c hash_crc32.c hash_joaat.c hash_fnv.c hash_sha3.c");
var sha3_arch_dir = "sha3/" + (X64 ? "generic64lc" : "generic32lc");
var sha3_dir = "ext/hash/" + sha3_arch_dir;
if (CHECK_HEADER_ADD_INCLUDE("KeccakHash.h", "CFLAGS_HASH", PHP_HASH + ";" + sha3_dir)) {
AC_DEFINE('HAVE_HASH_EXT', 1);
EXTENSION("hash", "hash.c hash_md.c hash_sha.c hash_ripemd.c hash_haval.c "
+ "hash_tiger.c hash_gost.c hash_snefru.c hash_whirlpool.c "
+ "hash_adler32.c hash_crc32.c hash_joaat.c hash_fnv.c hash_sha3.c");
ADD_SOURCES(sha3_dir, "KeccakHash.c KeccakSponge.c " + (X64 ? "KeccakP-1600-opt64.c" : "KeccakP-1600-inplace32BI.c"),
"hash");
ADD_FLAG("CFLAGS_HASH", "/DKeccakP200_excluded /DKeccakP400_excluded /DKeccakP800_excluded");
PHP_INSTALL_HEADERS("ext/hash/", "php_hash.h php_hash_md.h php_hash_sha.h php_hash_ripemd.h " +
"php_hash_haval.h php_hash_tiger.h php_hash_gost.h php_hash_snefru.h " +
"php_hash_whirlpool.h php_hash_adler32.h php_hash_crc32.h php_hash_sha3.h");
"php_hash_whirlpool.h php_hash_adler32.h php_hash_crc32.h php_hash_sha3.h ");
} else {
WARNING("hash not enabled; libraries and headers not found");
}
}

View File

@ -19,204 +19,41 @@
#include "php_hash.h"
#include "php_hash_sha3.h"
#if (defined(__APPLE__) || defined(__APPLE_CC__)) && \
(defined(__BIG_ENDIAN__) || defined(__LITTLE_ENDIAN__))
# if defined(__LITTLE_ENDIAN__)
# undef WORDS_BIGENDIAN
# else
# if defined(__BIG_ENDIAN__)
# define WORDS_BIGENDIAN
# endif
# endif
#endif
#define SUCCESS SHA3_SUCCESS /* Avoid conflict between KeccacHash.h and zend_types.h */
#include "KeccakHash.h"
static inline uint64_t rol64(uint64_t v, unsigned char b) {
return (v << b) | (v >> (64 - b));
}
static inline unsigned char idx(unsigned char x, unsigned char y) {
return x + (5 * y);
}
#ifdef WORDS_BIGENDIAN
static inline uint64_t load64(const unsigned char* x) {
char i;
uint64_t ret = 0;
for (i = 7; i >= 0; --i) {
ret <<= 8;
ret |= x[i];
}
return ret;
}
static inline void store64(unsigned char* x, uint64_t val) {
char i;
for (i = 0; i < 8; ++i) {
x[i] = val & 0xFF;
val >>= 8;
}
}
static inline void xor64(unsigned char* x, uint64_t val) {
char i;
for (i = 0; i < 8; ++i) {
x[i] ^= val & 0xFF;
val >>= 8;
}
}
# define readLane(x, y) load64(ctx->state+sizeof(uint64_t)*idx(x, y))
# define writeLane(x, y, v) store64(ctx->state+sizeof(uint64_t)*idx(x, y), v)
# define XORLane(x, y, v) xor64(ctx->state+sizeof(uint64_t)*idx(x, y), v)
#else
# define readLane(x, y) (((uint64_t*)ctx->state)[idx(x,y)])
# define writeLane(x, y, v) (((uint64_t*)ctx->state)[idx(x,y)] = v)
# define XORLane(x, y, v) (((uint64_t*)ctx->state)[idx(x,y)] ^= v)
#endif
// ==========================================================================
static inline char LFSR86540(unsigned char* pLFSR)
static int hash_sha3_copy(const void *ops, void *orig_context, void *dest_context)
{
unsigned char LFSR = *pLFSR;
char result = LFSR & 0x01;
if (LFSR & 0x80) {
// Primitive polynomial over GF(2): x^8+x^6+x^5+x^4+1
LFSR = (LFSR << 1) ^ 0x71;
} else {
LFSR <<= 1;
}
*pLFSR = LFSR;
return result;
PHP_SHA3_CTX* orig = (PHP_SHA3_CTX*)orig_context;
PHP_SHA3_CTX* dest = (PHP_SHA3_CTX*)dest_context;
memcpy(dest->hashinstance, orig->hashinstance, sizeof(Keccak_HashInstance));
return SUCCESS;
}
static void permute(PHP_SHA3_CTX* ctx) {
unsigned char LFSRstate = 0x01;
unsigned char round;
for (round = 0; round < 24; ++round) {
{ // Theta step (see [Keccak Reference, Section 2.3.2])
uint64_t C[5], D;
unsigned char x, y;
for (x = 0; x < 5; ++x) {
C[x] = readLane(x, 0) ^ readLane(x, 1) ^
readLane(x, 2) ^ readLane(x, 3) ^ readLane(x, 4);
}
for (x = 0; x < 5; ++x) {
D = C[(x+4)%5] ^ rol64(C[(x+1)%5], 1);
for (y = 0; y < 5; ++y) {
XORLane(x, y, D);
}
}
}
{ // p and Pi steps (see [Keccak Reference, Sections 2.3.3 and 2.3.4])
unsigned char x = 1, y = 0, t;
uint64_t current = readLane(x, y);
for (t = 0; t < 24; ++t) {
unsigned char r = ((t + 1) * (t + 2) / 2) % 64;
unsigned char Y = (2*x + 3*y) % 5;
uint64_t temp;
x = y;
y = Y;
temp = readLane(x, y);
writeLane(x, y, rol64(current, r));
current = temp;
}
}
{ // X step (see [Keccak Reference, Section 2.3.1])
unsigned char x, y;
for (y = 0; y < 5; ++y) {
uint64_t temp[5];
for (x = 0; x < 5; ++x) {
temp[x] = readLane(x, y);
}
for (x = 0; x < 5; ++x) {
writeLane(x, y, temp[x] ^((~temp[(x+1)%5]) & temp[(x+2)%5]));
}
}
}
{ // i step (see [Keccak Reference, Section 2.3.5])
unsigned char j;
for (j = 0; j < 7; ++j) {
if (LFSR86540(&LFSRstate)) {
uint64_t bitPos = (1<<j) - 1;
XORLane(0, 0, (uint64_t)1 << bitPos);
}
}
}
}
}
// ==========================================================================
static void PHP_SHA3_Init(PHP_SHA3_CTX* ctx,
int bits) {
memset(ctx, 0, sizeof(PHP_SHA3_CTX));
}
static void PHP_SHA3_Update(PHP_SHA3_CTX* ctx,
const unsigned char* buf,
unsigned int count,
size_t block_size) {
while (count > 0) {
unsigned int len = block_size - ctx->pos;
if (len > count) len = count;
count -= len;
while (len-- > 0) {
ctx->state[ctx->pos++] ^= *(buf++);
}
if (ctx->pos >= block_size) {
permute(ctx);
ctx->pos = 0;
}
}
}
static void PHP_SHA3_Final(unsigned char* digest,
PHP_SHA3_CTX* ctx,
int block_size,
int digest_size) {
int len = digest_size;
// Pad state to finalize
ctx->state[ctx->pos++] ^= 0x06;
ctx->state[block_size-1] ^= 0x80;
permute(ctx);
// Square output for digest
for(;;) {
int bs = (len < block_size) ? len : block_size;
memcpy(digest, ctx->state, bs);
digest += bs;
len -= bs;
if (!len) break;
permute(ctx);
}
// Zero out context
memset(ctx, 0, sizeof(PHP_SHA3_CTX));
}
// ==========================================================================
#define DECLARE_SHA3_OPS(bits) \
void PHP_SHA3##bits##Init(PHP_SHA3_##bits##_CTX* ctx) { \
PHP_SHA3_Init(ctx, bits); \
ctx->hashinstance = emalloc(sizeof(Keccak_HashInstance)); \
Keccak_HashInitialize_SHA3_##bits((Keccak_HashInstance *)ctx->hashinstance); \
} \
void PHP_SHA3##bits##Update(PHP_SHA3_##bits##_CTX* ctx, \
const unsigned char* input, \
unsigned int inputLen) { \
PHP_SHA3_Update(ctx, input, inputLen, \
(1600 - (2 * bits)) >> 3); \
Keccak_HashUpdate((Keccak_HashInstance *)ctx->hashinstance, input, inputLen * 8); \
} \
void PHP_SHA3##bits##Final(unsigned char* digest, \
PHP_SHA3_##bits##_CTX* ctx) { \
PHP_SHA3_Final(digest, ctx, \
(1600 - (2 * bits)) >> 3, \
bits >> 3); \
Keccak_HashFinal((Keccak_HashInstance *)ctx->hashinstance, digest); \
efree(ctx->hashinstance); \
ctx->hashinstance = NULL; \
} \
const php_hash_ops php_hash_sha3_##bits##_ops = { \
(php_hash_init_func_t) PHP_SHA3##bits##Init, \
(php_hash_update_func_t) PHP_SHA3##bits##Update, \
(php_hash_final_func_t) PHP_SHA3##bits##Final, \
php_hash_copy, \
hash_sha3_copy, \
bits >> 3, \
(1600 - (2 * bits)) >> 3, \
sizeof(PHP_SHA3_##bits##_CTX), \

View File

@ -22,8 +22,7 @@
#include "php.h"
typedef struct {
unsigned char state[200]; // 5 * 5 * sizeof(uint64)
uint32_t pos;
void *hashinstance;
} PHP_SHA3_CTX;
typedef PHP_SHA3_CTX PHP_SHA3_224_CTX;

View File

@ -0,0 +1,80 @@
/*
Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,
Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby
denoted as "the implementer".
For more information, feedback or questions, please refer to our websites:
http://keccak.noekeon.org/
http://keyak.noekeon.org/
http://ketje.noekeon.org/
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#include <string.h>
#include "KeccakHash.h"
/* ---------------------------------------------------------------- */
HashReturn Keccak_HashInitialize(Keccak_HashInstance *instance, unsigned int rate, unsigned int capacity, unsigned int hashbitlen, unsigned char delimitedSuffix)
{
HashReturn result;
if (delimitedSuffix == 0)
return FAIL;
result = (HashReturn)KeccakWidth1600_SpongeInitialize(&instance->sponge, rate, capacity);
if (result != SUCCESS)
return result;
instance->fixedOutputLength = hashbitlen;
instance->delimitedSuffix = delimitedSuffix;
return SUCCESS;
}
/* ---------------------------------------------------------------- */
HashReturn Keccak_HashUpdate(Keccak_HashInstance *instance, const BitSequence *data, DataLength databitlen)
{
if ((databitlen % 8) == 0)
return (HashReturn)KeccakWidth1600_SpongeAbsorb(&instance->sponge, data, databitlen/8);
else {
HashReturn ret = (HashReturn)KeccakWidth1600_SpongeAbsorb(&instance->sponge, data, databitlen/8);
if (ret == SUCCESS) {
/* The last partial byte is assumed to be aligned on the least significant bits */
unsigned char lastByte = data[databitlen/8];
/* Concatenate the last few bits provided here with those of the suffix */
unsigned short delimitedLastBytes = (unsigned short)((unsigned short)lastByte | ((unsigned short)instance->delimitedSuffix << (databitlen % 8)));
if ((delimitedLastBytes & 0xFF00) == 0x0000) {
instance->delimitedSuffix = delimitedLastBytes & 0xFF;
}
else {
unsigned char oneByte[1];
oneByte[0] = delimitedLastBytes & 0xFF;
ret = (HashReturn)KeccakWidth1600_SpongeAbsorb(&instance->sponge, oneByte, 1);
instance->delimitedSuffix = (delimitedLastBytes >> 8) & 0xFF;
}
}
return ret;
}
}
/* ---------------------------------------------------------------- */
HashReturn Keccak_HashFinal(Keccak_HashInstance *instance, BitSequence *hashval)
{
HashReturn ret = (HashReturn)KeccakWidth1600_SpongeAbsorbLastFewBits(&instance->sponge, instance->delimitedSuffix);
if (ret == SUCCESS)
return (HashReturn)KeccakWidth1600_SpongeSqueeze(&instance->sponge, hashval, instance->fixedOutputLength/8);
else
return ret;
}
/* ---------------------------------------------------------------- */
HashReturn Keccak_HashSqueeze(Keccak_HashInstance *instance, BitSequence *data, DataLength databitlen)
{
if ((databitlen % 8) != 0)
return FAIL;
return (HashReturn)KeccakWidth1600_SpongeSqueeze(&instance->sponge, data, databitlen/8);
}

View File

@ -0,0 +1,113 @@
/*
Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,
Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby
denoted as "the implementer".
For more information, feedback or questions, please refer to our websites:
http://keccak.noekeon.org/
http://keyak.noekeon.org/
http://ketje.noekeon.org/
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#ifndef _KeccakHashInterface_h_
#define _KeccakHashInterface_h_
#ifndef KeccakP1600_excluded
#include "KeccakSponge.h"
#include <string.h>
typedef unsigned char BitSequence;
typedef size_t DataLength;
typedef enum { SUCCESS = 0, FAIL = 1, BAD_HASHLEN = 2 } HashReturn;
typedef struct {
KeccakWidth1600_SpongeInstance sponge;
unsigned int fixedOutputLength;
unsigned char delimitedSuffix;
} Keccak_HashInstance;
/**
* Function to initialize the Keccak[r, c] sponge function instance used in sequential hashing mode.
* @param hashInstance Pointer to the hash instance to be initialized.
* @param rate The value of the rate r.
* @param capacity The value of the capacity c.
* @param hashbitlen The desired number of output bits,
* or 0 for an arbitrarily-long output.
* @param delimitedSuffix Bits that will be automatically appended to the end
* of the input message, as in domain separation.
* This is a byte containing from 0 to 7 bits
* formatted like the @a delimitedData parameter of
* the Keccak_SpongeAbsorbLastFewBits() function.
* @pre One must have r+c=1600 and the rate a multiple of 8 bits in this implementation.
* @return SUCCESS if successful, FAIL otherwise.
*/
HashReturn Keccak_HashInitialize(Keccak_HashInstance *hashInstance, unsigned int rate, unsigned int capacity, unsigned int hashbitlen, unsigned char delimitedSuffix);
/** Macro to initialize a SHAKE128 instance as specified in the FIPS 202 standard.
*/
#define Keccak_HashInitialize_SHAKE128(hashInstance) Keccak_HashInitialize(hashInstance, 1344, 256, 0, 0x1F)
/** Macro to initialize a SHAKE256 instance as specified in the FIPS 202 standard.
*/
#define Keccak_HashInitialize_SHAKE256(hashInstance) Keccak_HashInitialize(hashInstance, 1088, 512, 0, 0x1F)
/** Macro to initialize a SHA3-224 instance as specified in the FIPS 202 standard.
*/
#define Keccak_HashInitialize_SHA3_224(hashInstance) Keccak_HashInitialize(hashInstance, 1152, 448, 224, 0x06)
/** Macro to initialize a SHA3-256 instance as specified in the FIPS 202 standard.
*/
#define Keccak_HashInitialize_SHA3_256(hashInstance) Keccak_HashInitialize(hashInstance, 1088, 512, 256, 0x06)
/** Macro to initialize a SHA3-384 instance as specified in the FIPS 202 standard.
*/
#define Keccak_HashInitialize_SHA3_384(hashInstance) Keccak_HashInitialize(hashInstance, 832, 768, 384, 0x06)
/** Macro to initialize a SHA3-512 instance as specified in the FIPS 202 standard.
*/
#define Keccak_HashInitialize_SHA3_512(hashInstance) Keccak_HashInitialize(hashInstance, 576, 1024, 512, 0x06)
/**
* Function to give input data to be absorbed.
* @param hashInstance Pointer to the hash instance initialized by Keccak_HashInitialize().
* @param data Pointer to the input data.
* When @a databitLen is not a multiple of 8, the last bits of data must be
* in the least significant bits of the last byte (little-endian convention).
* @param databitLen The number of input bits provided in the input data.
* @pre In the previous call to Keccak_HashUpdate(), databitlen was a multiple of 8.
* @return SUCCESS if successful, FAIL otherwise.
*/
HashReturn Keccak_HashUpdate(Keccak_HashInstance *hashInstance, const BitSequence *data, DataLength databitlen);
/**
* Function to call after all input blocks have been input and to get
* output bits if the length was specified when calling Keccak_HashInitialize().
* @param hashInstance Pointer to the hash instance initialized by Keccak_HashInitialize().
* If @a hashbitlen was not 0 in the call to Keccak_HashInitialize(), the number of
* output bits is equal to @a hashbitlen.
* If @a hashbitlen was 0 in the call to Keccak_HashInitialize(), the output bits
* must be extracted using the Keccak_HashSqueeze() function.
* @param hashval Pointer to the buffer where to store the output data.
* @return SUCCESS if successful, FAIL otherwise.
*/
HashReturn Keccak_HashFinal(Keccak_HashInstance *hashInstance, BitSequence *hashval);
/**
* Function to squeeze output data.
* @param hashInstance Pointer to the hash instance initialized by Keccak_HashInitialize().
* @param data Pointer to the buffer where to store the output data.
* @param databitlen The number of output bits desired (must be a multiple of 8).
* @pre Keccak_HashFinal() must have been already called.
* @pre @a databitlen is a multiple of 8.
* @return SUCCESS if successful, FAIL otherwise.
*/
HashReturn Keccak_HashSqueeze(Keccak_HashInstance *hashInstance, BitSequence *data, DataLength databitlen);
#endif
#endif

View File

@ -0,0 +1,38 @@
/*
Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,
Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby
denoted as "the implementer".
For more information, feedback or questions, please refer to our websites:
http://keccak.noekeon.org/
http://keyak.noekeon.org/
http://ketje.noekeon.org/
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#ifndef _KeccakP_1600_SnP_h_
#define _KeccakP_1600_SnP_h_
/** For the documentation, see SnP-documentation.h.
*/
#define KeccakP1600_implementation "in-place 32-bit optimized implementation"
#define KeccakP1600_stateSizeInBytes 200
#define KeccakP1600_stateAlignment 8
#define KeccakP1600_StaticInitialize()
void KeccakP1600_Initialize(void *state);
void KeccakP1600_AddByte(void *state, unsigned char data, unsigned int offset);
void KeccakP1600_AddBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length);
void KeccakP1600_OverwriteBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length);
void KeccakP1600_OverwriteWithZeroes(void *state, unsigned int byteCount);
void KeccakP1600_Permute_Nrounds(void *state, unsigned int nrounds);
void KeccakP1600_Permute_12rounds(void *state);
void KeccakP1600_Permute_24rounds(void *state);
void KeccakP1600_ExtractBytes(const void *state, unsigned char *data, unsigned int offset, unsigned int length);
void KeccakP1600_ExtractAndAddBytes(const void *state, const unsigned char *input, unsigned char *output, unsigned int offset, unsigned int length);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,110 @@
/*
Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,
Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby
denoted as "the implementer".
For more information, feedback or questions, please refer to our websites:
http://keccak.noekeon.org/
http://keyak.noekeon.org/
http://ketje.noekeon.org/
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#include "KeccakSponge.h"
#ifdef KeccakReference
#include "displayIntermediateValues.h"
#endif
#ifndef KeccakP200_excluded
#include "KeccakP-200-SnP.h"
#define prefix KeccakWidth200
#define SnP KeccakP200
#define SnP_width 200
#define SnP_Permute KeccakP200_Permute_18rounds
#if defined(KeccakF200_FastLoop_supported)
#define SnP_FastLoop_Absorb KeccakF200_FastLoop_Absorb
#endif
#include "KeccakSponge.inc"
#undef prefix
#undef SnP
#undef SnP_width
#undef SnP_Permute
#undef SnP_FastLoop_Absorb
#endif
#ifndef KeccakP400_excluded
#include "KeccakP-400-SnP.h"
#define prefix KeccakWidth400
#define SnP KeccakP400
#define SnP_width 400
#define SnP_Permute KeccakP400_Permute_20rounds
#if defined(KeccakF400_FastLoop_supported)
#define SnP_FastLoop_Absorb KeccakF400_FastLoop_Absorb
#endif
#include "KeccakSponge.inc"
#undef prefix
#undef SnP
#undef SnP_width
#undef SnP_Permute
#undef SnP_FastLoop_Absorb
#endif
#ifndef KeccakP800_excluded
#include "KeccakP-800-SnP.h"
#define prefix KeccakWidth800
#define SnP KeccakP800
#define SnP_width 800
#define SnP_Permute KeccakP800_Permute_22rounds
#if defined(KeccakF800_FastLoop_supported)
#define SnP_FastLoop_Absorb KeccakF800_FastLoop_Absorb
#endif
#include "KeccakSponge.inc"
#undef prefix
#undef SnP
#undef SnP_width
#undef SnP_Permute
#undef SnP_FastLoop_Absorb
#endif
#ifndef KeccakP1600_excluded
#include "KeccakP-1600-SnP.h"
#define prefix KeccakWidth1600
#define SnP KeccakP1600
#define SnP_width 1600
#define SnP_Permute KeccakP1600_Permute_24rounds
#if defined(KeccakF1600_FastLoop_supported)
#define SnP_FastLoop_Absorb KeccakF1600_FastLoop_Absorb
#endif
#include "KeccakSponge.inc"
#undef prefix
#undef SnP
#undef SnP_width
#undef SnP_Permute
#undef SnP_FastLoop_Absorb
#endif
#ifndef KeccakP1600_excluded
#include "KeccakP-1600-SnP.h"
#define prefix KeccakWidth1600_12rounds
#define SnP KeccakP1600
#define SnP_width 1600
#define SnP_Permute KeccakP1600_Permute_12rounds
#if defined(KeccakP1600_12rounds_FastLoop_supported)
#define SnP_FastLoop_Absorb KeccakP1600_12rounds_FastLoop_Absorb
#endif
#include "KeccakSponge.inc"
#undef prefix
#undef SnP
#undef SnP_width
#undef SnP_Permute
#undef SnP_FastLoop_Absorb
#endif

View File

@ -0,0 +1,178 @@
/*
Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,
Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby
denoted as "the implementer".
For more information, feedback or questions, please refer to our websites:
http://keccak.noekeon.org/
http://keyak.noekeon.org/
http://ketje.noekeon.org/
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#ifndef _KeccakSponge_h_
#define _KeccakSponge_h_
/** General information
*
* The following type and functions are not actually implemented. Their
* documentation is generic, with the prefix Prefix replaced by
* - KeccakWidth200 for a sponge function based on Keccak-f[200]
* - KeccakWidth400 for a sponge function based on Keccak-f[400]
* - KeccakWidth800 for a sponge function based on Keccak-f[800]
* - KeccakWidth1600 for a sponge function based on Keccak-f[1600]
*
* In all these functions, the rate and capacity must sum to the width of the
* chosen permutation. For instance, to use the sponge function
* Keccak[r=1344, c=256], one must use KeccakWidth1600_Sponge() or a combination
* of KeccakWidth1600_SpongeInitialize(), KeccakWidth1600_SpongeAbsorb(),
* KeccakWidth1600_SpongeAbsorbLastFewBits() and
* KeccakWidth1600_SpongeSqueeze().
*
* The Prefix_SpongeInstance contains the sponge instance attributes for use
* with the Prefix_Sponge* functions.
* It gathers the state processed by the permutation as well as the rate,
* the position of input/output bytes in the state and the phase
* (absorbing or squeezing).
*/
#ifdef DontReallyInclude_DocumentationOnly
/** Function to evaluate the sponge function Keccak[r, c] in a single call.
* @param rate The value of the rate r.
* @param capacity The value of the capacity c.
* @param input Pointer to the input message (before the suffix).
* @param inputByteLen The length of the input message in bytes.
* @param suffix Byte containing from 0 to 7 suffix bits
* that must be absorbed after @a input.
* These <i>n</i> bits must be in the least significant bit positions.
* These bits must be delimited with a bit 1 at position <i>n</i>
* (counting from 0=LSB to 7=MSB) and followed by bits 0
* from position <i>n</i>+1 to position 7.
* Some examples:
* - If no bits are to be absorbed, then @a suffix must be 0x01.
* - If the 2-bit sequence 0,0 is to be absorbed, @a suffix must be 0x04.
* - If the 5-bit sequence 0,1,0,0,1 is to be absorbed, @a suffix must be 0x32.
* - If the 7-bit sequence 1,1,0,1,0,0,0 is to be absorbed, @a suffix must be 0x8B.
* .
* @param output Pointer to the output buffer.
* @param outputByteLen The desired number of output bytes.
* @pre One must have r+c equal to the supported width of this implementation
* and the rate a multiple of 8 bits (one byte) in this implementation.
* @pre @a suffix 0x00
* @return Zero if successful, 1 otherwise.
*/
int Prefix_Sponge(unsigned int rate, unsigned int capacity, const unsigned char *input, size_t inputByteLen, unsigned char suffix, unsigned char *output, size_t outputByteLen);
/**
* Function to initialize the state of the Keccak[r, c] sponge function.
* The phase of the sponge function is set to absorbing.
* @param spongeInstance Pointer to the sponge instance to be initialized.
* @param rate The value of the rate r.
* @param capacity The value of the capacity c.
* @pre One must have r+c equal to the supported width of this implementation
* and the rate a multiple of 8 bits (one byte) in this implementation.
* @return Zero if successful, 1 otherwise.
*/
int Prefix_SpongeInitialize(Prefix_SpongeInstance *spongeInstance, unsigned int rate, unsigned int capacity);
/**
* Function to give input data bytes for the sponge function to absorb.
* @param spongeInstance Pointer to the sponge instance initialized by Prefix_SpongeInitialize().
* @param data Pointer to the input data.
* @param dataByteLen The number of input bytes provided in the input data.
* @pre The sponge function must be in the absorbing phase,
* i.e., Prefix_SpongeSqueeze() or Prefix_SpongeAbsorbLastFewBits()
* must not have been called before.
* @return Zero if successful, 1 otherwise.
*/
int Prefix_SpongeAbsorb(Prefix_SpongeInstance *spongeInstance, const unsigned char *data, size_t dataByteLen);
/**
* Function to give input data bits for the sponge function to absorb
* and then to switch to the squeezing phase.
* @param spongeInstance Pointer to the sponge instance initialized by Prefix_SpongeInitialize().
* @param delimitedData Byte containing from 0 to 7 trailing bits
* that must be absorbed.
* These <i>n</i> bits must be in the least significant bit positions.
* These bits must be delimited with a bit 1 at position <i>n</i>
* (counting from 0=LSB to 7=MSB) and followed by bits 0
* from position <i>n</i>+1 to position 7.
* Some examples:
* - If no bits are to be absorbed, then @a delimitedData must be 0x01.
* - If the 2-bit sequence 0,0 is to be absorbed, @a delimitedData must be 0x04.
* - If the 5-bit sequence 0,1,0,0,1 is to be absorbed, @a delimitedData must be 0x32.
* - If the 7-bit sequence 1,1,0,1,0,0,0 is to be absorbed, @a delimitedData must be 0x8B.
* .
* @pre The sponge function must be in the absorbing phase,
* i.e., Prefix_SpongeSqueeze() or Prefix_SpongeAbsorbLastFewBits()
* must not have been called before.
* @pre @a delimitedData 0x00
* @return Zero if successful, 1 otherwise.
*/
int Prefix_SpongeAbsorbLastFewBits(Prefix_SpongeInstance *spongeInstance, unsigned char delimitedData);
/**
* Function to squeeze output data from the sponge function.
* If the sponge function was in the absorbing phase, this function
* switches it to the squeezing phase
* as if Prefix_SpongeAbsorbLastFewBits(spongeInstance, 0x01) was called.
* @param spongeInstance Pointer to the sponge instance initialized by Prefix_SpongeInitialize().
* @param data Pointer to the buffer where to store the output data.
* @param dataByteLen The number of output bytes desired.
* @return Zero if successful, 1 otherwise.
*/
int Prefix_SpongeSqueeze(Prefix_SpongeInstance *spongeInstance, unsigned char *data, size_t dataByteLen);
#endif
#include <string.h>
#include "align.h"
#define KCP_DeclareSpongeStructure(prefix, size, alignment) \
ALIGN(alignment) typedef struct prefix##_SpongeInstanceStruct { \
unsigned char state[size]; \
unsigned int rate; \
unsigned int byteIOIndex; \
int squeezing; \
} prefix##_SpongeInstance;
#define KCP_DeclareSpongeFunctions(prefix) \
int prefix##_Sponge(unsigned int rate, unsigned int capacity, const unsigned char *input, size_t inputByteLen, unsigned char suffix, unsigned char *output, size_t outputByteLen); \
int prefix##_SpongeInitialize(prefix##_SpongeInstance *spongeInstance, unsigned int rate, unsigned int capacity); \
int prefix##_SpongeAbsorb(prefix##_SpongeInstance *spongeInstance, const unsigned char *data, size_t dataByteLen); \
int prefix##_SpongeAbsorbLastFewBits(prefix##_SpongeInstance *spongeInstance, unsigned char delimitedData); \
int prefix##_SpongeSqueeze(prefix##_SpongeInstance *spongeInstance, unsigned char *data, size_t dataByteLen);
#ifndef KeccakP200_excluded
#include "KeccakP-200-SnP.h"
KCP_DeclareSpongeStructure(KeccakWidth200, KeccakP200_stateSizeInBytes, KeccakP200_stateAlignment)
KCP_DeclareSpongeFunctions(KeccakWidth200)
#endif
#ifndef KeccakP400_excluded
#include "KeccakP-400-SnP.h"
KCP_DeclareSpongeStructure(KeccakWidth400, KeccakP400_stateSizeInBytes, KeccakP400_stateAlignment)
KCP_DeclareSpongeFunctions(KeccakWidth400)
#endif
#ifndef KeccakP800_excluded
#include "KeccakP-800-SnP.h"
KCP_DeclareSpongeStructure(KeccakWidth800, KeccakP800_stateSizeInBytes, KeccakP800_stateAlignment)
KCP_DeclareSpongeFunctions(KeccakWidth800)
#endif
#ifndef KeccakP1600_excluded
#include "KeccakP-1600-SnP.h"
KCP_DeclareSpongeStructure(KeccakWidth1600, KeccakP1600_stateSizeInBytes, KeccakP1600_stateAlignment)
KCP_DeclareSpongeFunctions(KeccakWidth1600)
#endif
#ifndef KeccakP1600_excluded
#include "KeccakP-1600-SnP.h"
KCP_DeclareSpongeStructure(KeccakWidth1600_12rounds, KeccakP1600_stateSizeInBytes, KeccakP1600_stateAlignment)
KCP_DeclareSpongeFunctions(KeccakWidth1600_12rounds)
#endif
#endif

View File

@ -0,0 +1,313 @@
/*
Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,
Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby
denoted as "the implementer".
For more information, feedback or questions, please refer to our websites:
http://keccak.noekeon.org/
http://keyak.noekeon.org/
http://ketje.noekeon.org/
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#define JOIN0(a, b) a ## b
#define JOIN(a, b) JOIN0(a, b)
#define Sponge JOIN(prefix, _Sponge)
#define SpongeInstance JOIN(prefix, _SpongeInstance)
#define SpongeInitialize JOIN(prefix, _SpongeInitialize)
#define SpongeAbsorb JOIN(prefix, _SpongeAbsorb)
#define SpongeAbsorbLastFewBits JOIN(prefix, _SpongeAbsorbLastFewBits)
#define SpongeSqueeze JOIN(prefix, _SpongeSqueeze)
#define SnP_stateSizeInBytes JOIN(SnP, _stateSizeInBytes)
#define SnP_stateAlignment JOIN(SnP, _stateAlignment)
#define SnP_StaticInitialize JOIN(SnP, _StaticInitialize)
#define SnP_Initialize JOIN(SnP, _Initialize)
#define SnP_AddByte JOIN(SnP, _AddByte)
#define SnP_AddBytes JOIN(SnP, _AddBytes)
#define SnP_ExtractBytes JOIN(SnP, _ExtractBytes)
int Sponge(unsigned int rate, unsigned int capacity, const unsigned char *input, size_t inputByteLen, unsigned char suffix, unsigned char *output, size_t outputByteLen)
{
ALIGN(SnP_stateAlignment) unsigned char state[SnP_stateSizeInBytes];
unsigned int partialBlock;
const unsigned char *curInput = input;
unsigned char *curOutput = output;
unsigned int rateInBytes = rate/8;
if (rate+capacity != SnP_width)
return 1;
if ((rate <= 0) || (rate > SnP_width) || ((rate % 8) != 0))
return 1;
if (suffix == 0)
return 1;
/* Initialize the state */
SnP_StaticInitialize();
SnP_Initialize(state);
/* First, absorb whole blocks */
#ifdef SnP_FastLoop_Absorb
if (((rateInBytes % (SnP_width/200)) == 0) && (inputByteLen >= rateInBytes)) {
/* fast lane: whole lane rate */
size_t j;
j = SnP_FastLoop_Absorb(state, rateInBytes/(SnP_width/200), curInput, inputByteLen);
curInput += j;
inputByteLen -= j;
}
#endif
while(inputByteLen >= (size_t)rateInBytes) {
#ifdef KeccakReference
displayBytes(1, "Block to be absorbed", curInput, rateInBytes);
#endif
SnP_AddBytes(state, curInput, 0, rateInBytes);
SnP_Permute(state);
curInput += rateInBytes;
inputByteLen -= rateInBytes;
}
/* Then, absorb what remains */
partialBlock = (unsigned int)inputByteLen;
#ifdef KeccakReference
displayBytes(1, "Block to be absorbed (part)", curInput, partialBlock);
#endif
SnP_AddBytes(state, curInput, 0, partialBlock);
/* Finally, absorb the suffix */
#ifdef KeccakReference
{
unsigned char delimitedData1[1];
delimitedData1[0] = suffix;
displayBytes(1, "Block to be absorbed (last few bits + first bit of padding)", delimitedData1, 1);
}
#endif
/* Last few bits, whose delimiter coincides with first bit of padding */
SnP_AddByte(state, suffix, partialBlock);
/* If the first bit of padding is at position rate-1, we need a whole new block for the second bit of padding */
if ((suffix >= 0x80) && (partialBlock == (rateInBytes-1)))
SnP_Permute(state);
/* Second bit of padding */
SnP_AddByte(state, 0x80, rateInBytes-1);
#ifdef KeccakReference
{
unsigned char block[SnP_width/8];
memset(block, 0, SnP_width/8);
block[rateInBytes-1] = 0x80;
displayBytes(1, "Second bit of padding", block, rateInBytes);
}
#endif
SnP_Permute(state);
#ifdef KeccakReference
displayText(1, "--- Switching to squeezing phase ---");
#endif
/* First, output whole blocks */
while(outputByteLen > (size_t)rateInBytes) {
SnP_ExtractBytes(state, curOutput, 0, rateInBytes);
SnP_Permute(state);
#ifdef KeccakReference
displayBytes(1, "Squeezed block", curOutput, rateInBytes);
#endif
curOutput += rateInBytes;
outputByteLen -= rateInBytes;
}
/* Finally, output what remains */
partialBlock = (unsigned int)outputByteLen;
SnP_ExtractBytes(state, curOutput, 0, partialBlock);
#ifdef KeccakReference
displayBytes(1, "Squeezed block (part)", curOutput, partialBlock);
#endif
return 0;
}
/* ---------------------------------------------------------------- */
/* ---------------------------------------------------------------- */
/* ---------------------------------------------------------------- */
int SpongeInitialize(SpongeInstance *instance, unsigned int rate, unsigned int capacity)
{
if (rate+capacity != SnP_width)
return 1;
if ((rate <= 0) || (rate > SnP_width) || ((rate % 8) != 0))
return 1;
SnP_StaticInitialize();
SnP_Initialize(instance->state);
instance->rate = rate;
instance->byteIOIndex = 0;
instance->squeezing = 0;
return 0;
}
/* ---------------------------------------------------------------- */
int SpongeAbsorb(SpongeInstance *instance, const unsigned char *data, size_t dataByteLen)
{
size_t i, j;
unsigned int partialBlock;
const unsigned char *curData;
unsigned int rateInBytes = instance->rate/8;
if (instance->squeezing)
return 1; /* Too late for additional input */
i = 0;
curData = data;
while(i < dataByteLen) {
if ((instance->byteIOIndex == 0) && (dataByteLen >= (i + rateInBytes))) {
#ifdef SnP_FastLoop_Absorb
/* processing full blocks first */
if ((rateInBytes % (SnP_width/200)) == 0) {
/* fast lane: whole lane rate */
j = SnP_FastLoop_Absorb(instance->state, rateInBytes/(SnP_width/200), curData, dataByteLen - i);
i += j;
curData += j;
}
else {
#endif
for(j=dataByteLen-i; j>=rateInBytes; j-=rateInBytes) {
#ifdef KeccakReference
displayBytes(1, "Block to be absorbed", curData, rateInBytes);
#endif
SnP_AddBytes(instance->state, curData, 0, rateInBytes);
SnP_Permute(instance->state);
curData+=rateInBytes;
}
i = dataByteLen - j;
#ifdef SnP_FastLoop_Absorb
}
#endif
}
else {
/* normal lane: using the message queue */
partialBlock = (unsigned int)(dataByteLen - i);
if (partialBlock+instance->byteIOIndex > rateInBytes)
partialBlock = rateInBytes-instance->byteIOIndex;
#ifdef KeccakReference
displayBytes(1, "Block to be absorbed (part)", curData, partialBlock);
#endif
i += partialBlock;
SnP_AddBytes(instance->state, curData, instance->byteIOIndex, partialBlock);
curData += partialBlock;
instance->byteIOIndex += partialBlock;
if (instance->byteIOIndex == rateInBytes) {
SnP_Permute(instance->state);
instance->byteIOIndex = 0;
}
}
}
return 0;
}
/* ---------------------------------------------------------------- */
int SpongeAbsorbLastFewBits(SpongeInstance *instance, unsigned char delimitedData)
{
unsigned int rateInBytes = instance->rate/8;
if (delimitedData == 0)
return 1;
if (instance->squeezing)
return 1; /* Too late for additional input */
#ifdef KeccakReference
{
unsigned char delimitedData1[1];
delimitedData1[0] = delimitedData;
displayBytes(1, "Block to be absorbed (last few bits + first bit of padding)", delimitedData1, 1);
}
#endif
/* Last few bits, whose delimiter coincides with first bit of padding */
SnP_AddByte(instance->state, delimitedData, instance->byteIOIndex);
/* If the first bit of padding is at position rate-1, we need a whole new block for the second bit of padding */
if ((delimitedData >= 0x80) && (instance->byteIOIndex == (rateInBytes-1)))
SnP_Permute(instance->state);
/* Second bit of padding */
SnP_AddByte(instance->state, 0x80, rateInBytes-1);
#ifdef KeccakReference
{
unsigned char block[SnP_width/8];
memset(block, 0, SnP_width/8);
block[rateInBytes-1] = 0x80;
displayBytes(1, "Second bit of padding", block, rateInBytes);
}
#endif
SnP_Permute(instance->state);
instance->byteIOIndex = 0;
instance->squeezing = 1;
#ifdef KeccakReference
displayText(1, "--- Switching to squeezing phase ---");
#endif
return 0;
}
/* ---------------------------------------------------------------- */
int SpongeSqueeze(SpongeInstance *instance, unsigned char *data, size_t dataByteLen)
{
size_t i, j;
unsigned int partialBlock;
unsigned int rateInBytes = instance->rate/8;
unsigned char *curData;
if (!instance->squeezing)
SpongeAbsorbLastFewBits(instance, 0x01);
i = 0;
curData = data;
while(i < dataByteLen) {
if ((instance->byteIOIndex == rateInBytes) && (dataByteLen >= (i + rateInBytes))) {
for(j=dataByteLen-i; j>=rateInBytes; j-=rateInBytes) {
SnP_Permute(instance->state);
SnP_ExtractBytes(instance->state, curData, 0, rateInBytes);
#ifdef KeccakReference
displayBytes(1, "Squeezed block", curData, rateInBytes);
#endif
curData+=rateInBytes;
}
i = dataByteLen - j;
}
else {
/* normal lane: using the message queue */
if (instance->byteIOIndex == rateInBytes) {
SnP_Permute(instance->state);
instance->byteIOIndex = 0;
}
partialBlock = (unsigned int)(dataByteLen - i);
if (partialBlock+instance->byteIOIndex > rateInBytes)
partialBlock = rateInBytes-instance->byteIOIndex;
i += partialBlock;
SnP_ExtractBytes(instance->state, curData, instance->byteIOIndex, partialBlock);
#ifdef KeccakReference
displayBytes(1, "Squeezed block (part)", curData, partialBlock);
#endif
curData += partialBlock;
instance->byteIOIndex += partialBlock;
}
}
return 0;
}
/* ---------------------------------------------------------------- */
#undef Sponge
#undef SpongeInstance
#undef SpongeInitialize
#undef SpongeAbsorb
#undef SpongeAbsorbLastFewBits
#undef SpongeSqueeze
#undef SnP_stateSizeInBytes
#undef SnP_stateAlignment
#undef SnP_StaticInitialize
#undef SnP_Initialize
#undef SnP_AddByte
#undef SnP_AddBytes
#undef SnP_ExtractBytes

View File

@ -0,0 +1,134 @@
/*
Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,
Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby
denoted as "the implementer".
For more information, feedback or questions, please refer to our websites:
http://keccak.noekeon.org/
http://keyak.noekeon.org/
http://ketje.noekeon.org/
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#ifndef _SnP_Relaned_h_
#define _SnP_Relaned_h_
#define SnP_AddBytes(state, data, offset, length, SnP_AddLanes, SnP_AddBytesInLane, SnP_laneLengthInBytes) \
{ \
if ((offset) == 0) { \
SnP_AddLanes(state, data, (length)/SnP_laneLengthInBytes); \
SnP_AddBytesInLane(state, \
(length)/SnP_laneLengthInBytes, \
(data)+((length)/SnP_laneLengthInBytes)*SnP_laneLengthInBytes, \
0, \
(length)%SnP_laneLengthInBytes); \
} \
else { \
unsigned int _sizeLeft = (length); \
unsigned int _lanePosition = (offset)/SnP_laneLengthInBytes; \
unsigned int _offsetInLane = (offset)%SnP_laneLengthInBytes; \
const unsigned char *_curData = (data); \
while(_sizeLeft > 0) { \
unsigned int _bytesInLane = SnP_laneLengthInBytes - _offsetInLane; \
if (_bytesInLane > _sizeLeft) \
_bytesInLane = _sizeLeft; \
SnP_AddBytesInLane(state, _lanePosition, _curData, _offsetInLane, _bytesInLane); \
_sizeLeft -= _bytesInLane; \
_lanePosition++; \
_offsetInLane = 0; \
_curData += _bytesInLane; \
} \
} \
}
#define SnP_OverwriteBytes(state, data, offset, length, SnP_OverwriteLanes, SnP_OverwriteBytesInLane, SnP_laneLengthInBytes) \
{ \
if ((offset) == 0) { \
SnP_OverwriteLanes(state, data, (length)/SnP_laneLengthInBytes); \
SnP_OverwriteBytesInLane(state, \
(length)/SnP_laneLengthInBytes, \
(data)+((length)/SnP_laneLengthInBytes)*SnP_laneLengthInBytes, \
0, \
(length)%SnP_laneLengthInBytes); \
} \
else { \
unsigned int _sizeLeft = (length); \
unsigned int _lanePosition = (offset)/SnP_laneLengthInBytes; \
unsigned int _offsetInLane = (offset)%SnP_laneLengthInBytes; \
const unsigned char *_curData = (data); \
while(_sizeLeft > 0) { \
unsigned int _bytesInLane = SnP_laneLengthInBytes - _offsetInLane; \
if (_bytesInLane > _sizeLeft) \
_bytesInLane = _sizeLeft; \
SnP_OverwriteBytesInLane(state, _lanePosition, _curData, _offsetInLane, _bytesInLane); \
_sizeLeft -= _bytesInLane; \
_lanePosition++; \
_offsetInLane = 0; \
_curData += _bytesInLane; \
} \
} \
}
#define SnP_ExtractBytes(state, data, offset, length, SnP_ExtractLanes, SnP_ExtractBytesInLane, SnP_laneLengthInBytes) \
{ \
if ((offset) == 0) { \
SnP_ExtractLanes(state, data, (length)/SnP_laneLengthInBytes); \
SnP_ExtractBytesInLane(state, \
(length)/SnP_laneLengthInBytes, \
(data)+((length)/SnP_laneLengthInBytes)*SnP_laneLengthInBytes, \
0, \
(length)%SnP_laneLengthInBytes); \
} \
else { \
unsigned int _sizeLeft = (length); \
unsigned int _lanePosition = (offset)/SnP_laneLengthInBytes; \
unsigned int _offsetInLane = (offset)%SnP_laneLengthInBytes; \
unsigned char *_curData = (data); \
while(_sizeLeft > 0) { \
unsigned int _bytesInLane = SnP_laneLengthInBytes - _offsetInLane; \
if (_bytesInLane > _sizeLeft) \
_bytesInLane = _sizeLeft; \
SnP_ExtractBytesInLane(state, _lanePosition, _curData, _offsetInLane, _bytesInLane); \
_sizeLeft -= _bytesInLane; \
_lanePosition++; \
_offsetInLane = 0; \
_curData += _bytesInLane; \
} \
} \
}
#define SnP_ExtractAndAddBytes(state, input, output, offset, length, SnP_ExtractAndAddLanes, SnP_ExtractAndAddBytesInLane, SnP_laneLengthInBytes) \
{ \
if ((offset) == 0) { \
SnP_ExtractAndAddLanes(state, input, output, (length)/SnP_laneLengthInBytes); \
SnP_ExtractAndAddBytesInLane(state, \
(length)/SnP_laneLengthInBytes, \
(input)+((length)/SnP_laneLengthInBytes)*SnP_laneLengthInBytes, \
(output)+((length)/SnP_laneLengthInBytes)*SnP_laneLengthInBytes, \
0, \
(length)%SnP_laneLengthInBytes); \
} \
else { \
unsigned int _sizeLeft = (length); \
unsigned int _lanePosition = (offset)/SnP_laneLengthInBytes; \
unsigned int _offsetInLane = (offset)%SnP_laneLengthInBytes; \
const unsigned char *_curInput = (input); \
unsigned char *_curOutput = (output); \
while(_sizeLeft > 0) { \
unsigned int _bytesInLane = SnP_laneLengthInBytes - _offsetInLane; \
if (_bytesInLane > _sizeLeft) \
_bytesInLane = _sizeLeft; \
SnP_ExtractAndAddBytesInLane(state, _lanePosition, _curInput, _curOutput, _offsetInLane, _bytesInLane); \
_sizeLeft -= _bytesInLane; \
_lanePosition++; \
_offsetInLane = 0; \
_curInput += _bytesInLane; \
_curOutput += _bytesInLane; \
} \
} \
}
#endif

View File

@ -0,0 +1,34 @@
/*
Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,
Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby
denoted as "the implementer".
For more information, feedback or questions, please refer to our websites:
http://keccak.noekeon.org/
http://keyak.noekeon.org/
http://ketje.noekeon.org/
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#ifndef _align_h_
#define _align_h_
/* on Mac OS-X and possibly others, ALIGN(x) is defined in param.h, and -Werror chokes on the redef. */
#ifdef ALIGN
#undef ALIGN
#endif
#if defined(__GNUC__)
#define ALIGN(x) __attribute__ ((aligned(x)))
#elif defined(_MSC_VER)
#define ALIGN(x) __declspec(align(x))
#elif defined(__ARMCC_VERSION)
#define ALIGN(x) __align(x)
#else
#define ALIGN(x)
#endif
#endif

View File

@ -0,0 +1,142 @@
/*
---------------------------------------------------------------------------
Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
LICENSE TERMS
The redistribution and use of this software (with or without changes)
is allowed without the payment of fees or royalties provided that:
1. source code distributions include the above copyright notice, this
list of conditions and the following disclaimer;
2. binary distributions include the above copyright notice, this list
of conditions and the following disclaimer in their documentation;
3. the name of the copyright holder is not used to endorse products
built using this software without specific written permission.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 20/12/2007
Changes for ARM 9/9/2010
*/
#ifndef _BRG_ENDIAN_H
#define _BRG_ENDIAN_H
#define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */
#define IS_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */
#if 0
/* Include files where endian defines and byteswap functions may reside */
#if defined( __sun )
# include <sys/isa_defs.h>
#elif defined( __FreeBSD__ ) || defined( __OpenBSD__ ) || defined( __NetBSD__ )
# include <sys/endian.h>
#elif defined( BSD ) && ( BSD >= 199103 ) || defined( __APPLE__ ) || \
defined( __CYGWIN32__ ) || defined( __DJGPP__ ) || defined( __osf__ )
# include <machine/endian.h>
#elif defined( __linux__ ) || defined( __GNUC__ ) || defined( __GNU_LIBRARY__ )
# if !defined( __MINGW32__ ) && !defined( _AIX )
# include <endian.h>
# if !defined( __BEOS__ )
# include <byteswap.h>
# endif
# endif
#endif
#endif
/* Now attempt to set the define for platform byte order using any */
/* of the four forms SYMBOL, _SYMBOL, __SYMBOL & __SYMBOL__, which */
/* seem to encompass most endian symbol definitions */
#if defined( BIG_ENDIAN ) && defined( LITTLE_ENDIAN )
# if defined( BYTE_ORDER ) && BYTE_ORDER == BIG_ENDIAN
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# elif defined( BYTE_ORDER ) && BYTE_ORDER == LITTLE_ENDIAN
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif defined( BIG_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined( LITTLE_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif
#if defined( _BIG_ENDIAN ) && defined( _LITTLE_ENDIAN )
# if defined( _BYTE_ORDER ) && _BYTE_ORDER == _BIG_ENDIAN
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# elif defined( _BYTE_ORDER ) && _BYTE_ORDER == _LITTLE_ENDIAN
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif defined( _BIG_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined( _LITTLE_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif
#if defined( __BIG_ENDIAN ) && defined( __LITTLE_ENDIAN )
# if defined( __BYTE_ORDER ) && __BYTE_ORDER == __BIG_ENDIAN
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# elif defined( __BYTE_ORDER ) && __BYTE_ORDER == __LITTLE_ENDIAN
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif defined( __BIG_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined( __LITTLE_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif
#if defined( __BIG_ENDIAN__ ) && defined( __LITTLE_ENDIAN__ )
# if defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __BIG_ENDIAN__
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# elif defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __LITTLE_ENDIAN__
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif defined( __BIG_ENDIAN__ )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined( __LITTLE_ENDIAN__ )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif
/* if the platform byte order could not be determined, then try to */
/* set this define using common machine defines */
#if !defined(PLATFORM_BYTE_ORDER)
#if defined( __alpha__ ) || defined( __alpha ) || defined( i386 ) || \
defined( __i386__ ) || defined( _M_I86 ) || defined( _M_IX86 ) || \
defined( __OS2__ ) || defined( sun386 ) || defined( __TURBOC__ ) || \
defined( vax ) || defined( vms ) || defined( VMS ) || \
defined( __VMS ) || defined( _M_X64 )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#elif defined( AMIGA ) || defined( applec ) || defined( __AS400__ ) || \
defined( _CRAY ) || defined( __hppa ) || defined( __hp9000 ) || \
defined( ibm370 ) || defined( mc68000 ) || defined( m68k ) || \
defined( __MRC__ ) || defined( __MVS__ ) || defined( __MWERKS__ ) || \
defined( sparc ) || defined( __sparc) || defined( SYMANTEC_C ) || \
defined( __VOS__ ) || defined( __TIGCC__ ) || defined( __TANDEM ) || \
defined( THINK_C ) || defined( __VMCMS__ ) || defined( _AIX )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined(__arm__)
# ifdef __BIG_ENDIAN
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# else
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif 1 /* **** EDIT HERE IF NECESSARY **** */
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#elif 0 /* **** EDIT HERE IF NECESSARY **** */
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#else
# error Please edit lines 132 or 134 in brg_endian.h to set the platform byte order
#endif
#endif
#endif

View File

@ -0,0 +1,80 @@
/*
Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,
Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby
denoted as "the implementer".
For more information, feedback or questions, please refer to our websites:
http://keccak.noekeon.org/
http://keyak.noekeon.org/
http://ketje.noekeon.org/
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#include <string.h>
#include "KeccakHash.h"
/* ---------------------------------------------------------------- */
HashReturn Keccak_HashInitialize(Keccak_HashInstance *instance, unsigned int rate, unsigned int capacity, unsigned int hashbitlen, unsigned char delimitedSuffix)
{
HashReturn result;
if (delimitedSuffix == 0)
return FAIL;
result = (HashReturn)KeccakWidth1600_SpongeInitialize(&instance->sponge, rate, capacity);
if (result != SUCCESS)
return result;
instance->fixedOutputLength = hashbitlen;
instance->delimitedSuffix = delimitedSuffix;
return SUCCESS;
}
/* ---------------------------------------------------------------- */
HashReturn Keccak_HashUpdate(Keccak_HashInstance *instance, const BitSequence *data, DataLength databitlen)
{
if ((databitlen % 8) == 0)
return (HashReturn)KeccakWidth1600_SpongeAbsorb(&instance->sponge, data, databitlen/8);
else {
HashReturn ret = (HashReturn)KeccakWidth1600_SpongeAbsorb(&instance->sponge, data, databitlen/8);
if (ret == SUCCESS) {
/* The last partial byte is assumed to be aligned on the least significant bits */
unsigned char lastByte = data[databitlen/8];
/* Concatenate the last few bits provided here with those of the suffix */
unsigned short delimitedLastBytes = (unsigned short)((unsigned short)lastByte | ((unsigned short)instance->delimitedSuffix << (databitlen % 8)));
if ((delimitedLastBytes & 0xFF00) == 0x0000) {
instance->delimitedSuffix = delimitedLastBytes & 0xFF;
}
else {
unsigned char oneByte[1];
oneByte[0] = delimitedLastBytes & 0xFF;
ret = (HashReturn)KeccakWidth1600_SpongeAbsorb(&instance->sponge, oneByte, 1);
instance->delimitedSuffix = (delimitedLastBytes >> 8) & 0xFF;
}
}
return ret;
}
}
/* ---------------------------------------------------------------- */
HashReturn Keccak_HashFinal(Keccak_HashInstance *instance, BitSequence *hashval)
{
HashReturn ret = (HashReturn)KeccakWidth1600_SpongeAbsorbLastFewBits(&instance->sponge, instance->delimitedSuffix);
if (ret == SUCCESS)
return (HashReturn)KeccakWidth1600_SpongeSqueeze(&instance->sponge, hashval, instance->fixedOutputLength/8);
else
return ret;
}
/* ---------------------------------------------------------------- */
HashReturn Keccak_HashSqueeze(Keccak_HashInstance *instance, BitSequence *data, DataLength databitlen)
{
if ((databitlen % 8) != 0)
return FAIL;
return (HashReturn)KeccakWidth1600_SpongeSqueeze(&instance->sponge, data, databitlen/8);
}

View File

@ -0,0 +1,113 @@
/*
Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,
Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby
denoted as "the implementer".
For more information, feedback or questions, please refer to our websites:
http://keccak.noekeon.org/
http://keyak.noekeon.org/
http://ketje.noekeon.org/
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#ifndef _KeccakHashInterface_h_
#define _KeccakHashInterface_h_
#ifndef KeccakP1600_excluded
#include "KeccakSponge.h"
#include <string.h>
typedef unsigned char BitSequence;
typedef size_t DataLength;
typedef enum { SUCCESS = 0, FAIL = 1, BAD_HASHLEN = 2 } HashReturn;
typedef struct {
KeccakWidth1600_SpongeInstance sponge;
unsigned int fixedOutputLength;
unsigned char delimitedSuffix;
} Keccak_HashInstance;
/**
* Function to initialize the Keccak[r, c] sponge function instance used in sequential hashing mode.
* @param hashInstance Pointer to the hash instance to be initialized.
* @param rate The value of the rate r.
* @param capacity The value of the capacity c.
* @param hashbitlen The desired number of output bits,
* or 0 for an arbitrarily-long output.
* @param delimitedSuffix Bits that will be automatically appended to the end
* of the input message, as in domain separation.
* This is a byte containing from 0 to 7 bits
* formatted like the @a delimitedData parameter of
* the Keccak_SpongeAbsorbLastFewBits() function.
* @pre One must have r+c=1600 and the rate a multiple of 8 bits in this implementation.
* @return SUCCESS if successful, FAIL otherwise.
*/
HashReturn Keccak_HashInitialize(Keccak_HashInstance *hashInstance, unsigned int rate, unsigned int capacity, unsigned int hashbitlen, unsigned char delimitedSuffix);
/** Macro to initialize a SHAKE128 instance as specified in the FIPS 202 standard.
*/
#define Keccak_HashInitialize_SHAKE128(hashInstance) Keccak_HashInitialize(hashInstance, 1344, 256, 0, 0x1F)
/** Macro to initialize a SHAKE256 instance as specified in the FIPS 202 standard.
*/
#define Keccak_HashInitialize_SHAKE256(hashInstance) Keccak_HashInitialize(hashInstance, 1088, 512, 0, 0x1F)
/** Macro to initialize a SHA3-224 instance as specified in the FIPS 202 standard.
*/
#define Keccak_HashInitialize_SHA3_224(hashInstance) Keccak_HashInitialize(hashInstance, 1152, 448, 224, 0x06)
/** Macro to initialize a SHA3-256 instance as specified in the FIPS 202 standard.
*/
#define Keccak_HashInitialize_SHA3_256(hashInstance) Keccak_HashInitialize(hashInstance, 1088, 512, 256, 0x06)
/** Macro to initialize a SHA3-384 instance as specified in the FIPS 202 standard.
*/
#define Keccak_HashInitialize_SHA3_384(hashInstance) Keccak_HashInitialize(hashInstance, 832, 768, 384, 0x06)
/** Macro to initialize a SHA3-512 instance as specified in the FIPS 202 standard.
*/
#define Keccak_HashInitialize_SHA3_512(hashInstance) Keccak_HashInitialize(hashInstance, 576, 1024, 512, 0x06)
/**
* Function to give input data to be absorbed.
* @param hashInstance Pointer to the hash instance initialized by Keccak_HashInitialize().
* @param data Pointer to the input data.
* When @a databitLen is not a multiple of 8, the last bits of data must be
* in the least significant bits of the last byte (little-endian convention).
* @param databitLen The number of input bits provided in the input data.
* @pre In the previous call to Keccak_HashUpdate(), databitlen was a multiple of 8.
* @return SUCCESS if successful, FAIL otherwise.
*/
HashReturn Keccak_HashUpdate(Keccak_HashInstance *hashInstance, const BitSequence *data, DataLength databitlen);
/**
* Function to call after all input blocks have been input and to get
* output bits if the length was specified when calling Keccak_HashInitialize().
* @param hashInstance Pointer to the hash instance initialized by Keccak_HashInitialize().
* If @a hashbitlen was not 0 in the call to Keccak_HashInitialize(), the number of
* output bits is equal to @a hashbitlen.
* If @a hashbitlen was 0 in the call to Keccak_HashInitialize(), the output bits
* must be extracted using the Keccak_HashSqueeze() function.
* @param hashval Pointer to the buffer where to store the output data.
* @return SUCCESS if successful, FAIL otherwise.
*/
HashReturn Keccak_HashFinal(Keccak_HashInstance *hashInstance, BitSequence *hashval);
/**
* Function to squeeze output data.
* @param hashInstance Pointer to the hash instance initialized by Keccak_HashInitialize().
* @param data Pointer to the buffer where to store the output data.
* @param databitlen The number of output bits desired (must be a multiple of 8).
* @pre Keccak_HashFinal() must have been already called.
* @pre @a databitlen is a multiple of 8.
* @return SUCCESS if successful, FAIL otherwise.
*/
HashReturn Keccak_HashSqueeze(Keccak_HashInstance *hashInstance, BitSequence *data, DataLength databitlen);
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,50 @@
/*
Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,
Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby
denoted as "the implementer".
For more information, feedback or questions, please refer to our websites:
http://keccak.noekeon.org/
http://keyak.noekeon.org/
http://ketje.noekeon.org/
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#ifndef _KeccakP_1600_SnP_h_
#define _KeccakP_1600_SnP_h_
/** For the documentation, see SnP-documentation.h.
*/
#include "brg_endian.h"
#include "KeccakP-1600-opt64-config.h"
#define KeccakP1600_implementation "generic 64-bit optimized implementation (" KeccakP1600_implementation_config ")"
#define KeccakP1600_stateSizeInBytes 200
#define KeccakP1600_stateAlignment 8
#define KeccakF1600_FastLoop_supported
#include <stddef.h>
#define KeccakP1600_StaticInitialize()
void KeccakP1600_Initialize(void *state);
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
#define KeccakP1600_AddByte(state, byte, offset) \
((unsigned char*)(state))[(offset)] ^= (byte)
#else
void KeccakP1600_AddByte(void *state, unsigned char data, unsigned int offset);
#endif
void KeccakP1600_AddBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length);
void KeccakP1600_OverwriteBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length);
void KeccakP1600_OverwriteWithZeroes(void *state, unsigned int byteCount);
void KeccakP1600_Permute_Nrounds(void *state, unsigned int nrounds);
void KeccakP1600_Permute_12rounds(void *state);
void KeccakP1600_Permute_24rounds(void *state);
void KeccakP1600_ExtractBytes(const void *state, unsigned char *data, unsigned int offset, unsigned int length);
void KeccakP1600_ExtractAndAddBytes(const void *state, const unsigned char *input, unsigned char *output, unsigned int offset, unsigned int length);
size_t KeccakF1600_FastLoop_Absorb(void *state, unsigned int laneCount, const unsigned char *data, size_t dataByteLen);
#endif

View File

@ -0,0 +1,3 @@
#define KeccakP1600_implementation_config "lane complementing, all rounds unrolled"
#define KeccakP1600_fullUnrolling
#define KeccakP1600_useLaneComplementing

View File

@ -0,0 +1,484 @@
/*
Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,
Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby
denoted as "the implementer".
For more information, feedback or questions, please refer to our websites:
http://keccak.noekeon.org/
http://keyak.noekeon.org/
http://ketje.noekeon.org/
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#include <string.h>
#include <stdlib.h>
#include "brg_endian.h"
#include "KeccakP-1600-opt64-config.h"
typedef unsigned char UINT8;
typedef unsigned long long int UINT64;
#if defined(KeccakP1600_useLaneComplementing)
#define UseBebigokimisa
#endif
#if defined(_MSC_VER)
#define ROL64(a, offset) _rotl64(a, offset)
#elif defined(KeccakP1600_useSHLD)
#define ROL64(x,N) ({ \
register UINT64 __out; \
register UINT64 __in = x; \
__asm__ ("shld %2,%0,%0" : "=r"(__out) : "0"(__in), "i"(N)); \
__out; \
})
#else
#define ROL64(a, offset) ((((UINT64)a) << offset) ^ (((UINT64)a) >> (64-offset)))
#endif
#include "KeccakP-1600-64.macros"
#ifdef KeccakP1600_fullUnrolling
#define FullUnrolling
#else
#define Unrolling KeccakP1600_unrolling
#endif
#include "KeccakP-1600-unrolling.macros"
#include "SnP-Relaned.h"
static const UINT64 KeccakF1600RoundConstants[24] = {
0x0000000000000001ULL,
0x0000000000008082ULL,
0x800000000000808aULL,
0x8000000080008000ULL,
0x000000000000808bULL,
0x0000000080000001ULL,
0x8000000080008081ULL,
0x8000000000008009ULL,
0x000000000000008aULL,
0x0000000000000088ULL,
0x0000000080008009ULL,
0x000000008000000aULL,
0x000000008000808bULL,
0x800000000000008bULL,
0x8000000000008089ULL,
0x8000000000008003ULL,
0x8000000000008002ULL,
0x8000000000000080ULL,
0x000000000000800aULL,
0x800000008000000aULL,
0x8000000080008081ULL,
0x8000000000008080ULL,
0x0000000080000001ULL,
0x8000000080008008ULL };
/* ---------------------------------------------------------------- */
void KeccakP1600_Initialize(void *state)
{
memset(state, 0, 200);
#ifdef KeccakP1600_useLaneComplementing
((UINT64*)state)[ 1] = ~(UINT64)0;
((UINT64*)state)[ 2] = ~(UINT64)0;
((UINT64*)state)[ 8] = ~(UINT64)0;
((UINT64*)state)[12] = ~(UINT64)0;
((UINT64*)state)[17] = ~(UINT64)0;
((UINT64*)state)[20] = ~(UINT64)0;
#endif
}
/* ---------------------------------------------------------------- */
void KeccakP1600_AddBytesInLane(void *state, unsigned int lanePosition, const unsigned char *data, unsigned int offset, unsigned int length)
{
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
UINT64 lane;
if (length == 0)
return;
if (length == 1)
lane = data[0];
else {
lane = 0;
memcpy(&lane, data, length);
}
lane <<= offset*8;
#else
UINT64 lane = 0;
unsigned int i;
for(i=0; i<length; i++)
lane |= ((UINT64)data[i]) << ((i+offset)*8);
#endif
((UINT64*)state)[lanePosition] ^= lane;
}
/* ---------------------------------------------------------------- */
void KeccakP1600_AddLanes(void *state, const unsigned char *data, unsigned int laneCount)
{
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
unsigned int i = 0;
#ifdef NO_MISALIGNED_ACCESSES
/* If either pointer is misaligned, fall back to byte-wise xor. */
if (((((uintptr_t)state) & 7) != 0) || ((((uintptr_t)data) & 7) != 0)) {
for (i = 0; i < laneCount * 8; i++) {
((unsigned char*)state)[i] ^= data[i];
}
}
else
#endif
{
/* Otherwise... */
for( ; (i+8)<=laneCount; i+=8) {
((UINT64*)state)[i+0] ^= ((UINT64*)data)[i+0];
((UINT64*)state)[i+1] ^= ((UINT64*)data)[i+1];
((UINT64*)state)[i+2] ^= ((UINT64*)data)[i+2];
((UINT64*)state)[i+3] ^= ((UINT64*)data)[i+3];
((UINT64*)state)[i+4] ^= ((UINT64*)data)[i+4];
((UINT64*)state)[i+5] ^= ((UINT64*)data)[i+5];
((UINT64*)state)[i+6] ^= ((UINT64*)data)[i+6];
((UINT64*)state)[i+7] ^= ((UINT64*)data)[i+7];
}
for( ; (i+4)<=laneCount; i+=4) {
((UINT64*)state)[i+0] ^= ((UINT64*)data)[i+0];
((UINT64*)state)[i+1] ^= ((UINT64*)data)[i+1];
((UINT64*)state)[i+2] ^= ((UINT64*)data)[i+2];
((UINT64*)state)[i+3] ^= ((UINT64*)data)[i+3];
}
for( ; (i+2)<=laneCount; i+=2) {
((UINT64*)state)[i+0] ^= ((UINT64*)data)[i+0];
((UINT64*)state)[i+1] ^= ((UINT64*)data)[i+1];
}
if (i<laneCount) {
((UINT64*)state)[i+0] ^= ((UINT64*)data)[i+0];
}
}
#else
unsigned int i;
UINT8 *curData = data;
for(i=0; i<laneCount; i++, curData+=8) {
UINT64 lane = (UINT64)curData[0]
| ((UINT64)curData[1] << 8)
| ((UINT64)curData[2] << 16)
| ((UINT64)curData[3] << 24)
| ((UINT64)curData[4] <<32)
| ((UINT64)curData[5] << 40)
| ((UINT64)curData[6] << 48)
| ((UINT64)curData[7] << 56);
((UINT64*)state)[i] ^= lane;
}
#endif
}
/* ---------------------------------------------------------------- */
#if (PLATFORM_BYTE_ORDER != IS_LITTLE_ENDIAN)
void KeccakP1600_AddByte(void *state, unsigned char byte, unsigned int offset)
{
UINT64 lane = byte;
lane <<= (offset%8)*8;
((UINT64*)state)[offset/8] ^= lane;
}
#endif
/* ---------------------------------------------------------------- */
void KeccakP1600_AddBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length)
{
SnP_AddBytes(state, data, offset, length, KeccakP1600_AddLanes, KeccakP1600_AddBytesInLane, 8);
}
/* ---------------------------------------------------------------- */
void KeccakP1600_OverwriteBytesInLane(void *state, unsigned int lanePosition, const unsigned char *data, unsigned int offset, unsigned int length)
{
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
#ifdef KeccakP1600_useLaneComplementing
if ((lanePosition == 1) || (lanePosition == 2) || (lanePosition == 8) || (lanePosition == 12) || (lanePosition == 17) || (lanePosition == 20)) {
unsigned int i;
for(i=0; i<length; i++)
((unsigned char*)state)[lanePosition*8+offset+i] = ~data[i];
}
else
#endif
{
memcpy((unsigned char*)state+lanePosition*8+offset, data, length);
}
#else
#error "Not yet implemented"
#endif
}
/* ---------------------------------------------------------------- */
void KeccakP1600_OverwriteLanes(void *state, const unsigned char *data, unsigned int laneCount)
{
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
#ifdef KeccakP1600_useLaneComplementing
unsigned int lanePosition;
for(lanePosition=0; lanePosition<laneCount; lanePosition++)
if ((lanePosition == 1) || (lanePosition == 2) || (lanePosition == 8) || (lanePosition == 12) || (lanePosition == 17) || (lanePosition == 20))
((UINT64*)state)[lanePosition] = ~((const UINT64*)data)[lanePosition];
else
((UINT64*)state)[lanePosition] = ((const UINT64*)data)[lanePosition];
#else
memcpy(state, data, laneCount*8);
#endif
#else
#error "Not yet implemented"
#endif
}
/* ---------------------------------------------------------------- */
void KeccakP1600_OverwriteBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length)
{
SnP_OverwriteBytes(state, data, offset, length, KeccakP1600_OverwriteLanes, KeccakP1600_OverwriteBytesInLane, 8);
}
/* ---------------------------------------------------------------- */
void KeccakP1600_OverwriteWithZeroes(void *state, unsigned int byteCount)
{
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
#ifdef KeccakP1600_useLaneComplementing
unsigned int lanePosition;
for(lanePosition=0; lanePosition<byteCount/8; lanePosition++)
if ((lanePosition == 1) || (lanePosition == 2) || (lanePosition == 8) || (lanePosition == 12) || (lanePosition == 17) || (lanePosition == 20))
((UINT64*)state)[lanePosition] = ~0;
else
((UINT64*)state)[lanePosition] = 0;
if (byteCount%8 != 0) {
lanePosition = byteCount/8;
if ((lanePosition == 1) || (lanePosition == 2) || (lanePosition == 8) || (lanePosition == 12) || (lanePosition == 17) || (lanePosition == 20))
memset((unsigned char*)state+lanePosition*8, 0xFF, byteCount%8);
else
memset((unsigned char*)state+lanePosition*8, 0, byteCount%8);
}
#else
memset(state, 0, byteCount);
#endif
#else
#error "Not yet implemented"
#endif
}
/* ---------------------------------------------------------------- */
void KeccakP1600_Permute_Nrounds(void *state, unsigned int nr)
{
declareABCDE
unsigned int i;
UINT64 *stateAsLanes = (UINT64*)state;
copyFromState(A, stateAsLanes)
roundsN(nr)
copyToState(stateAsLanes, A)
}
/* ---------------------------------------------------------------- */
void KeccakP1600_Permute_24rounds(void *state)
{
declareABCDE
#ifndef KeccakP1600_fullUnrolling
unsigned int i;
#endif
UINT64 *stateAsLanes = (UINT64*)state;
copyFromState(A, stateAsLanes)
rounds24
copyToState(stateAsLanes, A)
}
/* ---------------------------------------------------------------- */
void KeccakP1600_Permute_12rounds(void *state)
{
declareABCDE
#ifndef KeccakP1600_fullUnrolling
unsigned int i;
#endif
UINT64 *stateAsLanes = (UINT64*)state;
copyFromState(A, stateAsLanes)
rounds12
copyToState(stateAsLanes, A)
}
/* ---------------------------------------------------------------- */
void KeccakP1600_ExtractBytesInLane(const void *state, unsigned int lanePosition, unsigned char *data, unsigned int offset, unsigned int length)
{
UINT64 lane = ((UINT64*)state)[lanePosition];
#ifdef KeccakP1600_useLaneComplementing
if ((lanePosition == 1) || (lanePosition == 2) || (lanePosition == 8) || (lanePosition == 12) || (lanePosition == 17) || (lanePosition == 20))
lane = ~lane;
#endif
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
{
UINT64 lane1[1];
lane1[0] = lane;
memcpy(data, (UINT8*)lane1+offset, length);
}
#else
unsigned int i;
lane >>= offset*8;
for(i=0; i<length; i++) {
data[i] = lane & 0xFF;
lane >>= 8;
}
#endif
}
/* ---------------------------------------------------------------- */
#if (PLATFORM_BYTE_ORDER != IS_LITTLE_ENDIAN)
void fromWordToBytes(UINT8 *bytes, const UINT64 word)
{
unsigned int i;
for(i=0; i<(64/8); i++)
bytes[i] = (word >> (8*i)) & 0xFF;
}
#endif
void KeccakP1600_ExtractLanes(const void *state, unsigned char *data, unsigned int laneCount)
{
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
memcpy(data, state, laneCount*8);
#else
unsigned int i;
for(i=0; i<laneCount; i++)
fromWordToBytes(data+(i*8), ((const UINT64*)state)[i]);
#endif
#ifdef KeccakP1600_useLaneComplementing
if (laneCount > 1) {
((UINT64*)data)[ 1] = ~((UINT64*)data)[ 1];
if (laneCount > 2) {
((UINT64*)data)[ 2] = ~((UINT64*)data)[ 2];
if (laneCount > 8) {
((UINT64*)data)[ 8] = ~((UINT64*)data)[ 8];
if (laneCount > 12) {
((UINT64*)data)[12] = ~((UINT64*)data)[12];
if (laneCount > 17) {
((UINT64*)data)[17] = ~((UINT64*)data)[17];
if (laneCount > 20) {
((UINT64*)data)[20] = ~((UINT64*)data)[20];
}
}
}
}
}
}
#endif
}
/* ---------------------------------------------------------------- */
void KeccakP1600_ExtractBytes(const void *state, unsigned char *data, unsigned int offset, unsigned int length)
{
SnP_ExtractBytes(state, data, offset, length, KeccakP1600_ExtractLanes, KeccakP1600_ExtractBytesInLane, 8);
}
/* ---------------------------------------------------------------- */
void KeccakP1600_ExtractAndAddBytesInLane(const void *state, unsigned int lanePosition, const unsigned char *input, unsigned char *output, unsigned int offset, unsigned int length)
{
UINT64 lane = ((UINT64*)state)[lanePosition];
#ifdef KeccakP1600_useLaneComplementing
if ((lanePosition == 1) || (lanePosition == 2) || (lanePosition == 8) || (lanePosition == 12) || (lanePosition == 17) || (lanePosition == 20))
lane = ~lane;
#endif
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
{
unsigned int i;
UINT64 lane1[1];
lane1[0] = lane;
for(i=0; i<length; i++)
output[i] = input[i] ^ ((UINT8*)lane1)[offset+i];
}
#else
unsigned int i;
lane >>= offset*8;
for(i=0; i<length; i++) {
output[i] = input[i] ^ (lane & 0xFF);
lane >>= 8;
}
#endif
}
/* ---------------------------------------------------------------- */
void KeccakP1600_ExtractAndAddLanes(const void *state, const unsigned char *input, unsigned char *output, unsigned int laneCount)
{
unsigned int i;
#if (PLATFORM_BYTE_ORDER != IS_LITTLE_ENDIAN)
unsigned char temp[8];
unsigned int j;
#endif
for(i=0; i<laneCount; i++) {
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
((UINT64*)output)[i] = ((UINT64*)input)[i] ^ ((const UINT64*)state)[i];
#else
fromWordToBytes(temp, ((const UINT64*)state)[i]);
for(j=0; j<8; j++)
output[i*8+j] = input[i*8+j] ^ temp[j];
#endif
}
#ifdef KeccakP1600_useLaneComplementing
if (laneCount > 1) {
((UINT64*)output)[ 1] = ~((UINT64*)output)[ 1];
if (laneCount > 2) {
((UINT64*)output)[ 2] = ~((UINT64*)output)[ 2];
if (laneCount > 8) {
((UINT64*)output)[ 8] = ~((UINT64*)output)[ 8];
if (laneCount > 12) {
((UINT64*)output)[12] = ~((UINT64*)output)[12];
if (laneCount > 17) {
((UINT64*)output)[17] = ~((UINT64*)output)[17];
if (laneCount > 20) {
((UINT64*)output)[20] = ~((UINT64*)output)[20];
}
}
}
}
}
}
#endif
}
/* ---------------------------------------------------------------- */
void KeccakP1600_ExtractAndAddBytes(const void *state, const unsigned char *input, unsigned char *output, unsigned int offset, unsigned int length)
{
SnP_ExtractAndAddBytes(state, input, output, offset, length, KeccakP1600_ExtractAndAddLanes, KeccakP1600_ExtractAndAddBytesInLane, 8);
}
/* ---------------------------------------------------------------- */
size_t KeccakF1600_FastLoop_Absorb(void *state, unsigned int laneCount, const unsigned char *data, size_t dataByteLen)
{
size_t originalDataByteLen = dataByteLen;
declareABCDE
#ifndef KeccakP1600_fullUnrolling
unsigned int i;
#endif
UINT64 *stateAsLanes = (UINT64*)state;
UINT64 *inDataAsLanes = (UINT64*)data;
copyFromState(A, stateAsLanes)
while(dataByteLen >= laneCount*8) {
addInput(A, inDataAsLanes, laneCount)
rounds24
inDataAsLanes += laneCount;
dataByteLen -= laneCount*8;
}
copyToState(stateAsLanes, A)
return originalDataByteLen - dataByteLen;
}

View File

@ -0,0 +1,198 @@
/*
Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,
Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby
denoted as "the implementer".
For more information, feedback or questions, please refer to our websites:
http://keccak.noekeon.org/
http://keyak.noekeon.org/
http://ketje.noekeon.org/
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#if (defined(FullUnrolling))
#define rounds24 \
prepareTheta \
thetaRhoPiChiIotaPrepareTheta( 0, A, E) \
thetaRhoPiChiIotaPrepareTheta( 1, E, A) \
thetaRhoPiChiIotaPrepareTheta( 2, A, E) \
thetaRhoPiChiIotaPrepareTheta( 3, E, A) \
thetaRhoPiChiIotaPrepareTheta( 4, A, E) \
thetaRhoPiChiIotaPrepareTheta( 5, E, A) \
thetaRhoPiChiIotaPrepareTheta( 6, A, E) \
thetaRhoPiChiIotaPrepareTheta( 7, E, A) \
thetaRhoPiChiIotaPrepareTheta( 8, A, E) \
thetaRhoPiChiIotaPrepareTheta( 9, E, A) \
thetaRhoPiChiIotaPrepareTheta(10, A, E) \
thetaRhoPiChiIotaPrepareTheta(11, E, A) \
thetaRhoPiChiIotaPrepareTheta(12, A, E) \
thetaRhoPiChiIotaPrepareTheta(13, E, A) \
thetaRhoPiChiIotaPrepareTheta(14, A, E) \
thetaRhoPiChiIotaPrepareTheta(15, E, A) \
thetaRhoPiChiIotaPrepareTheta(16, A, E) \
thetaRhoPiChiIotaPrepareTheta(17, E, A) \
thetaRhoPiChiIotaPrepareTheta(18, A, E) \
thetaRhoPiChiIotaPrepareTheta(19, E, A) \
thetaRhoPiChiIotaPrepareTheta(20, A, E) \
thetaRhoPiChiIotaPrepareTheta(21, E, A) \
thetaRhoPiChiIotaPrepareTheta(22, A, E) \
thetaRhoPiChiIota(23, E, A) \
#define rounds12 \
prepareTheta \
thetaRhoPiChiIotaPrepareTheta(12, A, E) \
thetaRhoPiChiIotaPrepareTheta(13, E, A) \
thetaRhoPiChiIotaPrepareTheta(14, A, E) \
thetaRhoPiChiIotaPrepareTheta(15, E, A) \
thetaRhoPiChiIotaPrepareTheta(16, A, E) \
thetaRhoPiChiIotaPrepareTheta(17, E, A) \
thetaRhoPiChiIotaPrepareTheta(18, A, E) \
thetaRhoPiChiIotaPrepareTheta(19, E, A) \
thetaRhoPiChiIotaPrepareTheta(20, A, E) \
thetaRhoPiChiIotaPrepareTheta(21, E, A) \
thetaRhoPiChiIotaPrepareTheta(22, A, E) \
thetaRhoPiChiIota(23, E, A) \
#elif (Unrolling == 12)
#define rounds24 \
prepareTheta \
for(i=0; i<24; i+=12) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
thetaRhoPiChiIotaPrepareTheta(i+ 1, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+ 2, A, E) \
thetaRhoPiChiIotaPrepareTheta(i+ 3, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+ 4, A, E) \
thetaRhoPiChiIotaPrepareTheta(i+ 5, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+ 6, A, E) \
thetaRhoPiChiIotaPrepareTheta(i+ 7, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+ 8, A, E) \
thetaRhoPiChiIotaPrepareTheta(i+ 9, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+10, A, E) \
thetaRhoPiChiIotaPrepareTheta(i+11, E, A) \
} \
#define rounds12 \
prepareTheta \
thetaRhoPiChiIotaPrepareTheta(12, A, E) \
thetaRhoPiChiIotaPrepareTheta(13, E, A) \
thetaRhoPiChiIotaPrepareTheta(14, A, E) \
thetaRhoPiChiIotaPrepareTheta(15, E, A) \
thetaRhoPiChiIotaPrepareTheta(16, A, E) \
thetaRhoPiChiIotaPrepareTheta(17, E, A) \
thetaRhoPiChiIotaPrepareTheta(18, A, E) \
thetaRhoPiChiIotaPrepareTheta(19, E, A) \
thetaRhoPiChiIotaPrepareTheta(20, A, E) \
thetaRhoPiChiIotaPrepareTheta(21, E, A) \
thetaRhoPiChiIotaPrepareTheta(22, A, E) \
thetaRhoPiChiIota(23, E, A) \
#elif (Unrolling == 6)
#define rounds24 \
prepareTheta \
for(i=0; i<24; i+=6) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+4, A, E) \
thetaRhoPiChiIotaPrepareTheta(i+5, E, A) \
} \
#define rounds12 \
prepareTheta \
for(i=12; i<24; i+=6) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+4, A, E) \
thetaRhoPiChiIotaPrepareTheta(i+5, E, A) \
} \
#elif (Unrolling == 4)
#define rounds24 \
prepareTheta \
for(i=0; i<24; i+=4) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \
} \
#define rounds12 \
prepareTheta \
for(i=12; i<24; i+=4) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \
} \
#elif (Unrolling == 3)
#define rounds24 \
prepareTheta \
for(i=0; i<24; i+=3) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
copyStateVariables(A, E) \
} \
#define rounds12 \
prepareTheta \
for(i=12; i<24; i+=3) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
copyStateVariables(A, E) \
} \
#elif (Unrolling == 2)
#define rounds24 \
prepareTheta \
for(i=0; i<24; i+=2) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
} \
#define rounds12 \
prepareTheta \
for(i=12; i<24; i+=2) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
} \
#elif (Unrolling == 1)
#define rounds24 \
prepareTheta \
for(i=0; i<24; i++) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
copyStateVariables(A, E) \
} \
#define rounds12 \
prepareTheta \
for(i=12; i<24; i++) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
copyStateVariables(A, E) \
} \
#else
#error "Unrolling is not correctly specified!"
#endif
#define roundsN(__nrounds) \
prepareTheta \
i = 24 - (__nrounds); \
if ((i&1) != 0) { \
thetaRhoPiChiIotaPrepareTheta(i, A, E) \
copyStateVariables(A, E) \
++i; \
} \
for( /* empty */; i<24; i+=2) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
}

View File

@ -0,0 +1,110 @@
/*
Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,
Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby
denoted as "the implementer".
For more information, feedback or questions, please refer to our websites:
http://keccak.noekeon.org/
http://keyak.noekeon.org/
http://ketje.noekeon.org/
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#include "KeccakSponge.h"
#ifdef KeccakReference
#include "displayIntermediateValues.h"
#endif
#ifndef KeccakP200_excluded
#include "KeccakP-200-SnP.h"
#define prefix KeccakWidth200
#define SnP KeccakP200
#define SnP_width 200
#define SnP_Permute KeccakP200_Permute_18rounds
#if defined(KeccakF200_FastLoop_supported)
#define SnP_FastLoop_Absorb KeccakF200_FastLoop_Absorb
#endif
#include "KeccakSponge.inc"
#undef prefix
#undef SnP
#undef SnP_width
#undef SnP_Permute
#undef SnP_FastLoop_Absorb
#endif
#ifndef KeccakP400_excluded
#include "KeccakP-400-SnP.h"
#define prefix KeccakWidth400
#define SnP KeccakP400
#define SnP_width 400
#define SnP_Permute KeccakP400_Permute_20rounds
#if defined(KeccakF400_FastLoop_supported)
#define SnP_FastLoop_Absorb KeccakF400_FastLoop_Absorb
#endif
#include "KeccakSponge.inc"
#undef prefix
#undef SnP
#undef SnP_width
#undef SnP_Permute
#undef SnP_FastLoop_Absorb
#endif
#ifndef KeccakP800_excluded
#include "KeccakP-800-SnP.h"
#define prefix KeccakWidth800
#define SnP KeccakP800
#define SnP_width 800
#define SnP_Permute KeccakP800_Permute_22rounds
#if defined(KeccakF800_FastLoop_supported)
#define SnP_FastLoop_Absorb KeccakF800_FastLoop_Absorb
#endif
#include "KeccakSponge.inc"
#undef prefix
#undef SnP
#undef SnP_width
#undef SnP_Permute
#undef SnP_FastLoop_Absorb
#endif
#ifndef KeccakP1600_excluded
#include "KeccakP-1600-SnP.h"
#define prefix KeccakWidth1600
#define SnP KeccakP1600
#define SnP_width 1600
#define SnP_Permute KeccakP1600_Permute_24rounds
#if defined(KeccakF1600_FastLoop_supported)
#define SnP_FastLoop_Absorb KeccakF1600_FastLoop_Absorb
#endif
#include "KeccakSponge.inc"
#undef prefix
#undef SnP
#undef SnP_width
#undef SnP_Permute
#undef SnP_FastLoop_Absorb
#endif
#ifndef KeccakP1600_excluded
#include "KeccakP-1600-SnP.h"
#define prefix KeccakWidth1600_12rounds
#define SnP KeccakP1600
#define SnP_width 1600
#define SnP_Permute KeccakP1600_Permute_12rounds
#if defined(KeccakP1600_12rounds_FastLoop_supported)
#define SnP_FastLoop_Absorb KeccakP1600_12rounds_FastLoop_Absorb
#endif
#include "KeccakSponge.inc"
#undef prefix
#undef SnP
#undef SnP_width
#undef SnP_Permute
#undef SnP_FastLoop_Absorb
#endif

View File

@ -0,0 +1,178 @@
/*
Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,
Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby
denoted as "the implementer".
For more information, feedback or questions, please refer to our websites:
http://keccak.noekeon.org/
http://keyak.noekeon.org/
http://ketje.noekeon.org/
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#ifndef _KeccakSponge_h_
#define _KeccakSponge_h_
/** General information
*
* The following type and functions are not actually implemented. Their
* documentation is generic, with the prefix Prefix replaced by
* - KeccakWidth200 for a sponge function based on Keccak-f[200]
* - KeccakWidth400 for a sponge function based on Keccak-f[400]
* - KeccakWidth800 for a sponge function based on Keccak-f[800]
* - KeccakWidth1600 for a sponge function based on Keccak-f[1600]
*
* In all these functions, the rate and capacity must sum to the width of the
* chosen permutation. For instance, to use the sponge function
* Keccak[r=1344, c=256], one must use KeccakWidth1600_Sponge() or a combination
* of KeccakWidth1600_SpongeInitialize(), KeccakWidth1600_SpongeAbsorb(),
* KeccakWidth1600_SpongeAbsorbLastFewBits() and
* KeccakWidth1600_SpongeSqueeze().
*
* The Prefix_SpongeInstance contains the sponge instance attributes for use
* with the Prefix_Sponge* functions.
* It gathers the state processed by the permutation as well as the rate,
* the position of input/output bytes in the state and the phase
* (absorbing or squeezing).
*/
#ifdef DontReallyInclude_DocumentationOnly
/** Function to evaluate the sponge function Keccak[r, c] in a single call.
* @param rate The value of the rate r.
* @param capacity The value of the capacity c.
* @param input Pointer to the input message (before the suffix).
* @param inputByteLen The length of the input message in bytes.
* @param suffix Byte containing from 0 to 7 suffix bits
* that must be absorbed after @a input.
* These <i>n</i> bits must be in the least significant bit positions.
* These bits must be delimited with a bit 1 at position <i>n</i>
* (counting from 0=LSB to 7=MSB) and followed by bits 0
* from position <i>n</i>+1 to position 7.
* Some examples:
* - If no bits are to be absorbed, then @a suffix must be 0x01.
* - If the 2-bit sequence 0,0 is to be absorbed, @a suffix must be 0x04.
* - If the 5-bit sequence 0,1,0,0,1 is to be absorbed, @a suffix must be 0x32.
* - If the 7-bit sequence 1,1,0,1,0,0,0 is to be absorbed, @a suffix must be 0x8B.
* .
* @param output Pointer to the output buffer.
* @param outputByteLen The desired number of output bytes.
* @pre One must have r+c equal to the supported width of this implementation
* and the rate a multiple of 8 bits (one byte) in this implementation.
* @pre @a suffix 0x00
* @return Zero if successful, 1 otherwise.
*/
int Prefix_Sponge(unsigned int rate, unsigned int capacity, const unsigned char *input, size_t inputByteLen, unsigned char suffix, unsigned char *output, size_t outputByteLen);
/**
* Function to initialize the state of the Keccak[r, c] sponge function.
* The phase of the sponge function is set to absorbing.
* @param spongeInstance Pointer to the sponge instance to be initialized.
* @param rate The value of the rate r.
* @param capacity The value of the capacity c.
* @pre One must have r+c equal to the supported width of this implementation
* and the rate a multiple of 8 bits (one byte) in this implementation.
* @return Zero if successful, 1 otherwise.
*/
int Prefix_SpongeInitialize(Prefix_SpongeInstance *spongeInstance, unsigned int rate, unsigned int capacity);
/**
* Function to give input data bytes for the sponge function to absorb.
* @param spongeInstance Pointer to the sponge instance initialized by Prefix_SpongeInitialize().
* @param data Pointer to the input data.
* @param dataByteLen The number of input bytes provided in the input data.
* @pre The sponge function must be in the absorbing phase,
* i.e., Prefix_SpongeSqueeze() or Prefix_SpongeAbsorbLastFewBits()
* must not have been called before.
* @return Zero if successful, 1 otherwise.
*/
int Prefix_SpongeAbsorb(Prefix_SpongeInstance *spongeInstance, const unsigned char *data, size_t dataByteLen);
/**
* Function to give input data bits for the sponge function to absorb
* and then to switch to the squeezing phase.
* @param spongeInstance Pointer to the sponge instance initialized by Prefix_SpongeInitialize().
* @param delimitedData Byte containing from 0 to 7 trailing bits
* that must be absorbed.
* These <i>n</i> bits must be in the least significant bit positions.
* These bits must be delimited with a bit 1 at position <i>n</i>
* (counting from 0=LSB to 7=MSB) and followed by bits 0
* from position <i>n</i>+1 to position 7.
* Some examples:
* - If no bits are to be absorbed, then @a delimitedData must be 0x01.
* - If the 2-bit sequence 0,0 is to be absorbed, @a delimitedData must be 0x04.
* - If the 5-bit sequence 0,1,0,0,1 is to be absorbed, @a delimitedData must be 0x32.
* - If the 7-bit sequence 1,1,0,1,0,0,0 is to be absorbed, @a delimitedData must be 0x8B.
* .
* @pre The sponge function must be in the absorbing phase,
* i.e., Prefix_SpongeSqueeze() or Prefix_SpongeAbsorbLastFewBits()
* must not have been called before.
* @pre @a delimitedData 0x00
* @return Zero if successful, 1 otherwise.
*/
int Prefix_SpongeAbsorbLastFewBits(Prefix_SpongeInstance *spongeInstance, unsigned char delimitedData);
/**
* Function to squeeze output data from the sponge function.
* If the sponge function was in the absorbing phase, this function
* switches it to the squeezing phase
* as if Prefix_SpongeAbsorbLastFewBits(spongeInstance, 0x01) was called.
* @param spongeInstance Pointer to the sponge instance initialized by Prefix_SpongeInitialize().
* @param data Pointer to the buffer where to store the output data.
* @param dataByteLen The number of output bytes desired.
* @return Zero if successful, 1 otherwise.
*/
int Prefix_SpongeSqueeze(Prefix_SpongeInstance *spongeInstance, unsigned char *data, size_t dataByteLen);
#endif
#include <string.h>
#include "align.h"
#define KCP_DeclareSpongeStructure(prefix, size, alignment) \
ALIGN(alignment) typedef struct prefix##_SpongeInstanceStruct { \
unsigned char state[size]; \
unsigned int rate; \
unsigned int byteIOIndex; \
int squeezing; \
} prefix##_SpongeInstance;
#define KCP_DeclareSpongeFunctions(prefix) \
int prefix##_Sponge(unsigned int rate, unsigned int capacity, const unsigned char *input, size_t inputByteLen, unsigned char suffix, unsigned char *output, size_t outputByteLen); \
int prefix##_SpongeInitialize(prefix##_SpongeInstance *spongeInstance, unsigned int rate, unsigned int capacity); \
int prefix##_SpongeAbsorb(prefix##_SpongeInstance *spongeInstance, const unsigned char *data, size_t dataByteLen); \
int prefix##_SpongeAbsorbLastFewBits(prefix##_SpongeInstance *spongeInstance, unsigned char delimitedData); \
int prefix##_SpongeSqueeze(prefix##_SpongeInstance *spongeInstance, unsigned char *data, size_t dataByteLen);
#ifndef KeccakP200_excluded
#include "KeccakP-200-SnP.h"
KCP_DeclareSpongeStructure(KeccakWidth200, KeccakP200_stateSizeInBytes, KeccakP200_stateAlignment)
KCP_DeclareSpongeFunctions(KeccakWidth200)
#endif
#ifndef KeccakP400_excluded
#include "KeccakP-400-SnP.h"
KCP_DeclareSpongeStructure(KeccakWidth400, KeccakP400_stateSizeInBytes, KeccakP400_stateAlignment)
KCP_DeclareSpongeFunctions(KeccakWidth400)
#endif
#ifndef KeccakP800_excluded
#include "KeccakP-800-SnP.h"
KCP_DeclareSpongeStructure(KeccakWidth800, KeccakP800_stateSizeInBytes, KeccakP800_stateAlignment)
KCP_DeclareSpongeFunctions(KeccakWidth800)
#endif
#ifndef KeccakP1600_excluded
#include "KeccakP-1600-SnP.h"
KCP_DeclareSpongeStructure(KeccakWidth1600, KeccakP1600_stateSizeInBytes, KeccakP1600_stateAlignment)
KCP_DeclareSpongeFunctions(KeccakWidth1600)
#endif
#ifndef KeccakP1600_excluded
#include "KeccakP-1600-SnP.h"
KCP_DeclareSpongeStructure(KeccakWidth1600_12rounds, KeccakP1600_stateSizeInBytes, KeccakP1600_stateAlignment)
KCP_DeclareSpongeFunctions(KeccakWidth1600_12rounds)
#endif
#endif

View File

@ -0,0 +1,313 @@
/*
Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,
Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby
denoted as "the implementer".
For more information, feedback or questions, please refer to our websites:
http://keccak.noekeon.org/
http://keyak.noekeon.org/
http://ketje.noekeon.org/
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#define JOIN0(a, b) a ## b
#define JOIN(a, b) JOIN0(a, b)
#define Sponge JOIN(prefix, _Sponge)
#define SpongeInstance JOIN(prefix, _SpongeInstance)
#define SpongeInitialize JOIN(prefix, _SpongeInitialize)
#define SpongeAbsorb JOIN(prefix, _SpongeAbsorb)
#define SpongeAbsorbLastFewBits JOIN(prefix, _SpongeAbsorbLastFewBits)
#define SpongeSqueeze JOIN(prefix, _SpongeSqueeze)
#define SnP_stateSizeInBytes JOIN(SnP, _stateSizeInBytes)
#define SnP_stateAlignment JOIN(SnP, _stateAlignment)
#define SnP_StaticInitialize JOIN(SnP, _StaticInitialize)
#define SnP_Initialize JOIN(SnP, _Initialize)
#define SnP_AddByte JOIN(SnP, _AddByte)
#define SnP_AddBytes JOIN(SnP, _AddBytes)
#define SnP_ExtractBytes JOIN(SnP, _ExtractBytes)
int Sponge(unsigned int rate, unsigned int capacity, const unsigned char *input, size_t inputByteLen, unsigned char suffix, unsigned char *output, size_t outputByteLen)
{
ALIGN(SnP_stateAlignment) unsigned char state[SnP_stateSizeInBytes];
unsigned int partialBlock;
const unsigned char *curInput = input;
unsigned char *curOutput = output;
unsigned int rateInBytes = rate/8;
if (rate+capacity != SnP_width)
return 1;
if ((rate <= 0) || (rate > SnP_width) || ((rate % 8) != 0))
return 1;
if (suffix == 0)
return 1;
/* Initialize the state */
SnP_StaticInitialize();
SnP_Initialize(state);
/* First, absorb whole blocks */
#ifdef SnP_FastLoop_Absorb
if (((rateInBytes % (SnP_width/200)) == 0) && (inputByteLen >= rateInBytes)) {
/* fast lane: whole lane rate */
size_t j;
j = SnP_FastLoop_Absorb(state, rateInBytes/(SnP_width/200), curInput, inputByteLen);
curInput += j;
inputByteLen -= j;
}
#endif
while(inputByteLen >= (size_t)rateInBytes) {
#ifdef KeccakReference
displayBytes(1, "Block to be absorbed", curInput, rateInBytes);
#endif
SnP_AddBytes(state, curInput, 0, rateInBytes);
SnP_Permute(state);
curInput += rateInBytes;
inputByteLen -= rateInBytes;
}
/* Then, absorb what remains */
partialBlock = (unsigned int)inputByteLen;
#ifdef KeccakReference
displayBytes(1, "Block to be absorbed (part)", curInput, partialBlock);
#endif
SnP_AddBytes(state, curInput, 0, partialBlock);
/* Finally, absorb the suffix */
#ifdef KeccakReference
{
unsigned char delimitedData1[1];
delimitedData1[0] = suffix;
displayBytes(1, "Block to be absorbed (last few bits + first bit of padding)", delimitedData1, 1);
}
#endif
/* Last few bits, whose delimiter coincides with first bit of padding */
SnP_AddByte(state, suffix, partialBlock);
/* If the first bit of padding is at position rate-1, we need a whole new block for the second bit of padding */
if ((suffix >= 0x80) && (partialBlock == (rateInBytes-1)))
SnP_Permute(state);
/* Second bit of padding */
SnP_AddByte(state, 0x80, rateInBytes-1);
#ifdef KeccakReference
{
unsigned char block[SnP_width/8];
memset(block, 0, SnP_width/8);
block[rateInBytes-1] = 0x80;
displayBytes(1, "Second bit of padding", block, rateInBytes);
}
#endif
SnP_Permute(state);
#ifdef KeccakReference
displayText(1, "--- Switching to squeezing phase ---");
#endif
/* First, output whole blocks */
while(outputByteLen > (size_t)rateInBytes) {
SnP_ExtractBytes(state, curOutput, 0, rateInBytes);
SnP_Permute(state);
#ifdef KeccakReference
displayBytes(1, "Squeezed block", curOutput, rateInBytes);
#endif
curOutput += rateInBytes;
outputByteLen -= rateInBytes;
}
/* Finally, output what remains */
partialBlock = (unsigned int)outputByteLen;
SnP_ExtractBytes(state, curOutput, 0, partialBlock);
#ifdef KeccakReference
displayBytes(1, "Squeezed block (part)", curOutput, partialBlock);
#endif
return 0;
}
/* ---------------------------------------------------------------- */
/* ---------------------------------------------------------------- */
/* ---------------------------------------------------------------- */
int SpongeInitialize(SpongeInstance *instance, unsigned int rate, unsigned int capacity)
{
if (rate+capacity != SnP_width)
return 1;
if ((rate <= 0) || (rate > SnP_width) || ((rate % 8) != 0))
return 1;
SnP_StaticInitialize();
SnP_Initialize(instance->state);
instance->rate = rate;
instance->byteIOIndex = 0;
instance->squeezing = 0;
return 0;
}
/* ---------------------------------------------------------------- */
int SpongeAbsorb(SpongeInstance *instance, const unsigned char *data, size_t dataByteLen)
{
size_t i, j;
unsigned int partialBlock;
const unsigned char *curData;
unsigned int rateInBytes = instance->rate/8;
if (instance->squeezing)
return 1; /* Too late for additional input */
i = 0;
curData = data;
while(i < dataByteLen) {
if ((instance->byteIOIndex == 0) && (dataByteLen >= (i + rateInBytes))) {
#ifdef SnP_FastLoop_Absorb
/* processing full blocks first */
if ((rateInBytes % (SnP_width/200)) == 0) {
/* fast lane: whole lane rate */
j = SnP_FastLoop_Absorb(instance->state, rateInBytes/(SnP_width/200), curData, dataByteLen - i);
i += j;
curData += j;
}
else {
#endif
for(j=dataByteLen-i; j>=rateInBytes; j-=rateInBytes) {
#ifdef KeccakReference
displayBytes(1, "Block to be absorbed", curData, rateInBytes);
#endif
SnP_AddBytes(instance->state, curData, 0, rateInBytes);
SnP_Permute(instance->state);
curData+=rateInBytes;
}
i = dataByteLen - j;
#ifdef SnP_FastLoop_Absorb
}
#endif
}
else {
/* normal lane: using the message queue */
partialBlock = (unsigned int)(dataByteLen - i);
if (partialBlock+instance->byteIOIndex > rateInBytes)
partialBlock = rateInBytes-instance->byteIOIndex;
#ifdef KeccakReference
displayBytes(1, "Block to be absorbed (part)", curData, partialBlock);
#endif
i += partialBlock;
SnP_AddBytes(instance->state, curData, instance->byteIOIndex, partialBlock);
curData += partialBlock;
instance->byteIOIndex += partialBlock;
if (instance->byteIOIndex == rateInBytes) {
SnP_Permute(instance->state);
instance->byteIOIndex = 0;
}
}
}
return 0;
}
/* ---------------------------------------------------------------- */
int SpongeAbsorbLastFewBits(SpongeInstance *instance, unsigned char delimitedData)
{
unsigned int rateInBytes = instance->rate/8;
if (delimitedData == 0)
return 1;
if (instance->squeezing)
return 1; /* Too late for additional input */
#ifdef KeccakReference
{
unsigned char delimitedData1[1];
delimitedData1[0] = delimitedData;
displayBytes(1, "Block to be absorbed (last few bits + first bit of padding)", delimitedData1, 1);
}
#endif
/* Last few bits, whose delimiter coincides with first bit of padding */
SnP_AddByte(instance->state, delimitedData, instance->byteIOIndex);
/* If the first bit of padding is at position rate-1, we need a whole new block for the second bit of padding */
if ((delimitedData >= 0x80) && (instance->byteIOIndex == (rateInBytes-1)))
SnP_Permute(instance->state);
/* Second bit of padding */
SnP_AddByte(instance->state, 0x80, rateInBytes-1);
#ifdef KeccakReference
{
unsigned char block[SnP_width/8];
memset(block, 0, SnP_width/8);
block[rateInBytes-1] = 0x80;
displayBytes(1, "Second bit of padding", block, rateInBytes);
}
#endif
SnP_Permute(instance->state);
instance->byteIOIndex = 0;
instance->squeezing = 1;
#ifdef KeccakReference
displayText(1, "--- Switching to squeezing phase ---");
#endif
return 0;
}
/* ---------------------------------------------------------------- */
int SpongeSqueeze(SpongeInstance *instance, unsigned char *data, size_t dataByteLen)
{
size_t i, j;
unsigned int partialBlock;
unsigned int rateInBytes = instance->rate/8;
unsigned char *curData;
if (!instance->squeezing)
SpongeAbsorbLastFewBits(instance, 0x01);
i = 0;
curData = data;
while(i < dataByteLen) {
if ((instance->byteIOIndex == rateInBytes) && (dataByteLen >= (i + rateInBytes))) {
for(j=dataByteLen-i; j>=rateInBytes; j-=rateInBytes) {
SnP_Permute(instance->state);
SnP_ExtractBytes(instance->state, curData, 0, rateInBytes);
#ifdef KeccakReference
displayBytes(1, "Squeezed block", curData, rateInBytes);
#endif
curData+=rateInBytes;
}
i = dataByteLen - j;
}
else {
/* normal lane: using the message queue */
if (instance->byteIOIndex == rateInBytes) {
SnP_Permute(instance->state);
instance->byteIOIndex = 0;
}
partialBlock = (unsigned int)(dataByteLen - i);
if (partialBlock+instance->byteIOIndex > rateInBytes)
partialBlock = rateInBytes-instance->byteIOIndex;
i += partialBlock;
SnP_ExtractBytes(instance->state, curData, instance->byteIOIndex, partialBlock);
#ifdef KeccakReference
displayBytes(1, "Squeezed block (part)", curData, partialBlock);
#endif
curData += partialBlock;
instance->byteIOIndex += partialBlock;
}
}
return 0;
}
/* ---------------------------------------------------------------- */
#undef Sponge
#undef SpongeInstance
#undef SpongeInitialize
#undef SpongeAbsorb
#undef SpongeAbsorbLastFewBits
#undef SpongeSqueeze
#undef SnP_stateSizeInBytes
#undef SnP_stateAlignment
#undef SnP_StaticInitialize
#undef SnP_Initialize
#undef SnP_AddByte
#undef SnP_AddBytes
#undef SnP_ExtractBytes

View File

@ -0,0 +1,134 @@
/*
Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,
Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby
denoted as "the implementer".
For more information, feedback or questions, please refer to our websites:
http://keccak.noekeon.org/
http://keyak.noekeon.org/
http://ketje.noekeon.org/
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#ifndef _SnP_Relaned_h_
#define _SnP_Relaned_h_
#define SnP_AddBytes(state, data, offset, length, SnP_AddLanes, SnP_AddBytesInLane, SnP_laneLengthInBytes) \
{ \
if ((offset) == 0) { \
SnP_AddLanes(state, data, (length)/SnP_laneLengthInBytes); \
SnP_AddBytesInLane(state, \
(length)/SnP_laneLengthInBytes, \
(data)+((length)/SnP_laneLengthInBytes)*SnP_laneLengthInBytes, \
0, \
(length)%SnP_laneLengthInBytes); \
} \
else { \
unsigned int _sizeLeft = (length); \
unsigned int _lanePosition = (offset)/SnP_laneLengthInBytes; \
unsigned int _offsetInLane = (offset)%SnP_laneLengthInBytes; \
const unsigned char *_curData = (data); \
while(_sizeLeft > 0) { \
unsigned int _bytesInLane = SnP_laneLengthInBytes - _offsetInLane; \
if (_bytesInLane > _sizeLeft) \
_bytesInLane = _sizeLeft; \
SnP_AddBytesInLane(state, _lanePosition, _curData, _offsetInLane, _bytesInLane); \
_sizeLeft -= _bytesInLane; \
_lanePosition++; \
_offsetInLane = 0; \
_curData += _bytesInLane; \
} \
} \
}
#define SnP_OverwriteBytes(state, data, offset, length, SnP_OverwriteLanes, SnP_OverwriteBytesInLane, SnP_laneLengthInBytes) \
{ \
if ((offset) == 0) { \
SnP_OverwriteLanes(state, data, (length)/SnP_laneLengthInBytes); \
SnP_OverwriteBytesInLane(state, \
(length)/SnP_laneLengthInBytes, \
(data)+((length)/SnP_laneLengthInBytes)*SnP_laneLengthInBytes, \
0, \
(length)%SnP_laneLengthInBytes); \
} \
else { \
unsigned int _sizeLeft = (length); \
unsigned int _lanePosition = (offset)/SnP_laneLengthInBytes; \
unsigned int _offsetInLane = (offset)%SnP_laneLengthInBytes; \
const unsigned char *_curData = (data); \
while(_sizeLeft > 0) { \
unsigned int _bytesInLane = SnP_laneLengthInBytes - _offsetInLane; \
if (_bytesInLane > _sizeLeft) \
_bytesInLane = _sizeLeft; \
SnP_OverwriteBytesInLane(state, _lanePosition, _curData, _offsetInLane, _bytesInLane); \
_sizeLeft -= _bytesInLane; \
_lanePosition++; \
_offsetInLane = 0; \
_curData += _bytesInLane; \
} \
} \
}
#define SnP_ExtractBytes(state, data, offset, length, SnP_ExtractLanes, SnP_ExtractBytesInLane, SnP_laneLengthInBytes) \
{ \
if ((offset) == 0) { \
SnP_ExtractLanes(state, data, (length)/SnP_laneLengthInBytes); \
SnP_ExtractBytesInLane(state, \
(length)/SnP_laneLengthInBytes, \
(data)+((length)/SnP_laneLengthInBytes)*SnP_laneLengthInBytes, \
0, \
(length)%SnP_laneLengthInBytes); \
} \
else { \
unsigned int _sizeLeft = (length); \
unsigned int _lanePosition = (offset)/SnP_laneLengthInBytes; \
unsigned int _offsetInLane = (offset)%SnP_laneLengthInBytes; \
unsigned char *_curData = (data); \
while(_sizeLeft > 0) { \
unsigned int _bytesInLane = SnP_laneLengthInBytes - _offsetInLane; \
if (_bytesInLane > _sizeLeft) \
_bytesInLane = _sizeLeft; \
SnP_ExtractBytesInLane(state, _lanePosition, _curData, _offsetInLane, _bytesInLane); \
_sizeLeft -= _bytesInLane; \
_lanePosition++; \
_offsetInLane = 0; \
_curData += _bytesInLane; \
} \
} \
}
#define SnP_ExtractAndAddBytes(state, input, output, offset, length, SnP_ExtractAndAddLanes, SnP_ExtractAndAddBytesInLane, SnP_laneLengthInBytes) \
{ \
if ((offset) == 0) { \
SnP_ExtractAndAddLanes(state, input, output, (length)/SnP_laneLengthInBytes); \
SnP_ExtractAndAddBytesInLane(state, \
(length)/SnP_laneLengthInBytes, \
(input)+((length)/SnP_laneLengthInBytes)*SnP_laneLengthInBytes, \
(output)+((length)/SnP_laneLengthInBytes)*SnP_laneLengthInBytes, \
0, \
(length)%SnP_laneLengthInBytes); \
} \
else { \
unsigned int _sizeLeft = (length); \
unsigned int _lanePosition = (offset)/SnP_laneLengthInBytes; \
unsigned int _offsetInLane = (offset)%SnP_laneLengthInBytes; \
const unsigned char *_curInput = (input); \
unsigned char *_curOutput = (output); \
while(_sizeLeft > 0) { \
unsigned int _bytesInLane = SnP_laneLengthInBytes - _offsetInLane; \
if (_bytesInLane > _sizeLeft) \
_bytesInLane = _sizeLeft; \
SnP_ExtractAndAddBytesInLane(state, _lanePosition, _curInput, _curOutput, _offsetInLane, _bytesInLane); \
_sizeLeft -= _bytesInLane; \
_lanePosition++; \
_offsetInLane = 0; \
_curInput += _bytesInLane; \
_curOutput += _bytesInLane; \
} \
} \
}
#endif

View File

@ -0,0 +1,34 @@
/*
Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,
Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby
denoted as "the implementer".
For more information, feedback or questions, please refer to our websites:
http://keccak.noekeon.org/
http://keyak.noekeon.org/
http://ketje.noekeon.org/
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#ifndef _align_h_
#define _align_h_
/* on Mac OS-X and possibly others, ALIGN(x) is defined in param.h, and -Werror chokes on the redef. */
#ifdef ALIGN
#undef ALIGN
#endif
#if defined(__GNUC__)
#define ALIGN(x) __attribute__ ((aligned(x)))
#elif defined(_MSC_VER)
#define ALIGN(x) __declspec(align(x))
#elif defined(__ARMCC_VERSION)
#define ALIGN(x) __align(x)
#else
#define ALIGN(x)
#endif
#endif

View File

@ -0,0 +1,142 @@
/*
---------------------------------------------------------------------------
Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
LICENSE TERMS
The redistribution and use of this software (with or without changes)
is allowed without the payment of fees or royalties provided that:
1. source code distributions include the above copyright notice, this
list of conditions and the following disclaimer;
2. binary distributions include the above copyright notice, this list
of conditions and the following disclaimer in their documentation;
3. the name of the copyright holder is not used to endorse products
built using this software without specific written permission.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 20/12/2007
Changes for ARM 9/9/2010
*/
#ifndef _BRG_ENDIAN_H
#define _BRG_ENDIAN_H
#define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */
#define IS_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */
#if 0
/* Include files where endian defines and byteswap functions may reside */
#if defined( __sun )
# include <sys/isa_defs.h>
#elif defined( __FreeBSD__ ) || defined( __OpenBSD__ ) || defined( __NetBSD__ )
# include <sys/endian.h>
#elif defined( BSD ) && ( BSD >= 199103 ) || defined( __APPLE__ ) || \
defined( __CYGWIN32__ ) || defined( __DJGPP__ ) || defined( __osf__ )
# include <machine/endian.h>
#elif defined( __linux__ ) || defined( __GNUC__ ) || defined( __GNU_LIBRARY__ )
# if !defined( __MINGW32__ ) && !defined( _AIX )
# include <endian.h>
# if !defined( __BEOS__ )
# include <byteswap.h>
# endif
# endif
#endif
#endif
/* Now attempt to set the define for platform byte order using any */
/* of the four forms SYMBOL, _SYMBOL, __SYMBOL & __SYMBOL__, which */
/* seem to encompass most endian symbol definitions */
#if defined( BIG_ENDIAN ) && defined( LITTLE_ENDIAN )
# if defined( BYTE_ORDER ) && BYTE_ORDER == BIG_ENDIAN
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# elif defined( BYTE_ORDER ) && BYTE_ORDER == LITTLE_ENDIAN
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif defined( BIG_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined( LITTLE_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif
#if defined( _BIG_ENDIAN ) && defined( _LITTLE_ENDIAN )
# if defined( _BYTE_ORDER ) && _BYTE_ORDER == _BIG_ENDIAN
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# elif defined( _BYTE_ORDER ) && _BYTE_ORDER == _LITTLE_ENDIAN
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif defined( _BIG_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined( _LITTLE_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif
#if defined( __BIG_ENDIAN ) && defined( __LITTLE_ENDIAN )
# if defined( __BYTE_ORDER ) && __BYTE_ORDER == __BIG_ENDIAN
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# elif defined( __BYTE_ORDER ) && __BYTE_ORDER == __LITTLE_ENDIAN
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif defined( __BIG_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined( __LITTLE_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif
#if defined( __BIG_ENDIAN__ ) && defined( __LITTLE_ENDIAN__ )
# if defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __BIG_ENDIAN__
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# elif defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __LITTLE_ENDIAN__
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif defined( __BIG_ENDIAN__ )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined( __LITTLE_ENDIAN__ )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif
/* if the platform byte order could not be determined, then try to */
/* set this define using common machine defines */
#if !defined(PLATFORM_BYTE_ORDER)
#if defined( __alpha__ ) || defined( __alpha ) || defined( i386 ) || \
defined( __i386__ ) || defined( _M_I86 ) || defined( _M_IX86 ) || \
defined( __OS2__ ) || defined( sun386 ) || defined( __TURBOC__ ) || \
defined( vax ) || defined( vms ) || defined( VMS ) || \
defined( __VMS ) || defined( _M_X64 )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#elif defined( AMIGA ) || defined( applec ) || defined( __AS400__ ) || \
defined( _CRAY ) || defined( __hppa ) || defined( __hp9000 ) || \
defined( ibm370 ) || defined( mc68000 ) || defined( m68k ) || \
defined( __MRC__ ) || defined( __MVS__ ) || defined( __MWERKS__ ) || \
defined( sparc ) || defined( __sparc) || defined( SYMANTEC_C ) || \
defined( __VOS__ ) || defined( __TIGCC__ ) || defined( __TANDEM ) || \
defined( THINK_C ) || defined( __VMCMS__ ) || defined( _AIX )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined(__arm__)
# ifdef __BIG_ENDIAN
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# else
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif 1 /* **** EDIT HERE IF NECESSARY **** */
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#elif 0 /* **** EDIT HERE IF NECESSARY **** */
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#else
# error Please edit lines 132 or 134 in brg_endian.h to set the platform byte order
#endif
#endif
#endif

View File

@ -88,6 +88,10 @@ ZEND_BEGIN_ARG_INFO_EX( collator_sort_args, 0, 0, 1 )
ZEND_ARG_INFO( 0, flags )
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX( collator_sort_with_sort_keys_args, 0, 0, 1 )
ZEND_ARG_ARRAY_INFO( 1, arr, 0 )
ZEND_END_ARG_INFO()
/* }}} */
/* {{{ Collator_class_functions
@ -99,7 +103,7 @@ zend_function_entry Collator_class_functions[] = {
ZEND_FENTRY( create, ZEND_FN( collator_create ), collator_1_arg, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
PHP_NAMED_FE( compare, ZEND_FN( collator_compare ), collator_2_args )
PHP_NAMED_FE( sort, ZEND_FN( collator_sort ), collator_sort_args )
PHP_NAMED_FE( sortWithSortKeys, ZEND_FN( collator_sort_with_sort_keys ), collator_sort_args )
PHP_NAMED_FE( sortWithSortKeys, ZEND_FN( collator_sort_with_sort_keys ), collator_sort_with_sort_keys_args )
PHP_NAMED_FE( asort, ZEND_FN( collator_asort ), collator_sort_args )
PHP_NAMED_FE( getAttribute, ZEND_FN( collator_get_attribute ), collator_1_arg )
PHP_NAMED_FE( setAttribute, ZEND_FN( collator_set_attribute ), collator_2_args )

View File

@ -154,6 +154,11 @@ ZEND_BEGIN_ARG_INFO_EX(collator_sort_args, 0, 0, 2)
ZEND_ARG_INFO(0, sort_flags)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(collator_sort_with_sort_keys_args, 0, 0, 2)
ZEND_ARG_OBJ_INFO(0, coll, Collator, 0)
ZEND_ARG_ARRAY_INFO(1, arr, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(numfmt_parse_arginfo, 0, 0, 2)
ZEND_ARG_INFO(0, formatter)
ZEND_ARG_INFO(0, string)
@ -629,7 +634,7 @@ zend_function_entry intl_functions[] = {
PHP_FE( collator_get_strength, collator_0_args )
PHP_FE( collator_set_strength, collator_1_arg )
PHP_FE( collator_sort, collator_sort_args )
PHP_FE( collator_sort_with_sort_keys, collator_sort_args )
PHP_FE( collator_sort_with_sort_keys, collator_sort_with_sort_keys_args )
PHP_FE( collator_asort, collator_sort_args )
PHP_FE( collator_get_locale, collator_1_arg )
PHP_FE( collator_get_error_code, collator_0_args )

View File

@ -4,6 +4,8 @@ Bug #62915: cloning of several classes is defective
<?php
if (!extension_loaded('intl'))
die('skip intl extension not enabled');
if (!class_exists('Spoofchecker'))
die('skip intl extension does not have spoof checker');
--FILE--
<?php
class A extends IntlDateFormatter {

View File

@ -0,0 +1,22 @@
--TEST--
Bug #74468 Wrong reflection on Collator::sortWithSortKeys
--SKIPIF--
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
<?php if (version_compare(INTL_ICU_VERSION, '51.2') >= 0) die('skip for ICU < 51.2'); ?>
--FILE--
<?php
$rm = new ReflectionMethod(Collator::class, 'sortWithSortKeys');
var_dump($rm->getNumberOfParameters());
var_dump($rm->getNumberOfRequiredParameters());
$rf = new ReflectionFunction('collator_sort_with_sort_keys');
var_dump($rf->getNumberOfParameters());
var_dump($rf->getNumberOfRequiredParameters());
?>
===DONE===
--EXPECT--
int(1)
int(1)
int(2)
int(2)
===DONE===

View File

@ -19,8 +19,8 @@ var_dump($lsb->getDisplayName(false, IntlTimeZone::DISPLAY_LONG, 'pt_PT'));
?>
==DONE==
--EXPECT--
--EXPECTF--
string(30) "Western European Standard Time"
string(30) "Western European Standard Time"
string(32) "Hora Padrão da Europa Ocidental"
string(32) "Hora %cadrão da Europa Ocidental"
==DONE==

Some files were not shown because too many files have changed in this diff Show More