mirror of
https://github.com/php/php-src.git
synced 2025-01-15 16:24:37 +08:00
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:
commit
7bb6b6b6d2
@ -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
|
||||
|
@ -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
29
NEWS
@ -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)
|
||||
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
11
UPGRADING
11
UPGRADING
@ -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
|
||||
|
12
Zend/tests/abstract_inheritance_001.phpt
Normal file
12
Zend/tests/abstract_inheritance_001.phpt
Normal 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
|
12
Zend/tests/abstract_inheritance_002.phpt
Normal file
12
Zend/tests/abstract_inheritance_002.phpt
Normal 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
|
12
Zend/tests/abstract_inheritance_003.phpt
Normal file
12
Zend/tests/abstract_inheritance_003.phpt
Normal 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
16
Zend/tests/bug61970.phpt
Normal 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
|
15
Zend/tests/bug61970_1.phpt
Normal file
15
Zend/tests/bug61970_1.phpt
Normal 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
|
19
Zend/tests/bug61970_2.phpt
Normal file
19
Zend/tests/bug61970_2.phpt
Normal 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
17
Zend/tests/bug74269.phpt
Normal 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
11
Zend/tests/bug74546.phpt
Normal 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
26
Zend/tests/bug74657.phpt
Normal 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
|
||||
|
29
Zend/tests/generators/bug74606.phpt
Normal file
29
Zend/tests/generators/bug74606.phpt
Normal 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
|
@ -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
|
||||
|
@ -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
|
||||
|
30
Zend/tests/ns_trailing_comma_01.phpt
Normal file
30
Zend/tests/ns_trailing_comma_01.phpt
Normal 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
|
52
Zend/tests/ns_trailing_comma_02.phpt
Normal file
52
Zend/tests/ns_trailing_comma_02.phpt
Normal 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
|
8
Zend/tests/ns_trailing_comma_error_01.phpt
Normal file
8
Zend/tests/ns_trailing_comma_error_01.phpt
Normal 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
|
8
Zend/tests/ns_trailing_comma_error_02.phpt
Normal file
8
Zend/tests/ns_trailing_comma_error_02.phpt
Normal 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
|
8
Zend/tests/ns_trailing_comma_error_03.phpt
Normal file
8
Zend/tests/ns_trailing_comma_error_03.phpt
Normal 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
|
8
Zend/tests/ns_trailing_comma_error_04.phpt
Normal file
8
Zend/tests/ns_trailing_comma_error_04.phpt
Normal 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
|
8
Zend/tests/ns_trailing_comma_error_05.phpt
Normal file
8
Zend/tests/ns_trailing_comma_error_05.phpt
Normal 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
|
8
Zend/tests/ns_trailing_comma_error_06.phpt
Normal file
8
Zend/tests/ns_trailing_comma_error_06.phpt
Normal 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
|
8
Zend/tests/ns_trailing_comma_error_07.phpt
Normal file
8
Zend/tests/ns_trailing_comma_error_07.phpt
Normal 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
|
8
Zend/tests/ns_trailing_comma_error_08.phpt
Normal file
8
Zend/tests/ns_trailing_comma_error_08.phpt
Normal 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
|
@ -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;
|
||||
}
|
||||
/* }}} */
|
||||
|
@ -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, ...);
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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)) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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); }
|
||||
|
@ -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;
|
||||
|
@ -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)--;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
}
|
||||
/* }}} */
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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;
|
||||
|
10579
Zend/zend_vm_execute.h
10579
Zend/zend_vm_execute.h
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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 ^
|
||||
|
@ -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"
|
||||
|
||||
|
@ -461,6 +461,7 @@ limits.h \
|
||||
locale.h \
|
||||
monetary.h \
|
||||
netdb.h \
|
||||
poll.h \
|
||||
pwd.h \
|
||||
resolv.h \
|
||||
signal.h \
|
||||
|
30
ext/date/tests/bug74652.phpt
Normal file
30
ext/date/tests/bug74652.phpt
Normal 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
|
@ -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)
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
354
ext/dba/dba_lmdb.c
Normal 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
12
ext/dba/php_lmdb.h
Normal 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
|
28
ext/dba/tests/bug72885.phpt
Normal file
28
ext/dba/tests/bug72885.phpt
Normal 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===
|
@ -2,4 +2,5 @@
|
||||
$db_filename = dirname(__FILE__) .'/test0.dbm'; // see test.inc
|
||||
@unlink($db_filename);
|
||||
@unlink($db_filename.'.lck');
|
||||
@unlink($db_filename.'-lock');
|
||||
?>
|
||||
|
38
ext/dba/tests/dba_lmdb.phpt
Normal file
38
ext/dba/tests/dba_lmdb.phpt
Normal 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===
|
@ -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===
|
||||
|
@ -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}
|
||||
};
|
||||
/* }}} */
|
||||
|
||||
|
@ -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)
|
||||
])
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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), \
|
||||
|
@ -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;
|
||||
|
80
ext/hash/sha3/generic32lc/KeccakHash.c
Normal file
80
ext/hash/sha3/generic32lc/KeccakHash.c
Normal 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);
|
||||
}
|
113
ext/hash/sha3/generic32lc/KeccakHash.h
Normal file
113
ext/hash/sha3/generic32lc/KeccakHash.h
Normal 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
|
38
ext/hash/sha3/generic32lc/KeccakP-1600-SnP.h
Normal file
38
ext/hash/sha3/generic32lc/KeccakP-1600-SnP.h
Normal 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
|
1158
ext/hash/sha3/generic32lc/KeccakP-1600-inplace32BI.c
Normal file
1158
ext/hash/sha3/generic32lc/KeccakP-1600-inplace32BI.c
Normal file
File diff suppressed because it is too large
Load Diff
110
ext/hash/sha3/generic32lc/KeccakSponge.c
Normal file
110
ext/hash/sha3/generic32lc/KeccakSponge.c
Normal 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
|
178
ext/hash/sha3/generic32lc/KeccakSponge.h
Normal file
178
ext/hash/sha3/generic32lc/KeccakSponge.h
Normal 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
|
313
ext/hash/sha3/generic32lc/KeccakSponge.inc
Normal file
313
ext/hash/sha3/generic32lc/KeccakSponge.inc
Normal 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
|
134
ext/hash/sha3/generic32lc/SnP-Relaned.h
Normal file
134
ext/hash/sha3/generic32lc/SnP-Relaned.h
Normal 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
|
34
ext/hash/sha3/generic32lc/align.h
Normal file
34
ext/hash/sha3/generic32lc/align.h
Normal 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
|
142
ext/hash/sha3/generic32lc/brg_endian.h
Normal file
142
ext/hash/sha3/generic32lc/brg_endian.h
Normal 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
|
80
ext/hash/sha3/generic64lc/KeccakHash.c
Normal file
80
ext/hash/sha3/generic64lc/KeccakHash.c
Normal 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);
|
||||
}
|
113
ext/hash/sha3/generic64lc/KeccakHash.h
Normal file
113
ext/hash/sha3/generic64lc/KeccakHash.h
Normal 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
|
2197
ext/hash/sha3/generic64lc/KeccakP-1600-64.macros
Normal file
2197
ext/hash/sha3/generic64lc/KeccakP-1600-64.macros
Normal file
File diff suppressed because it is too large
Load Diff
50
ext/hash/sha3/generic64lc/KeccakP-1600-SnP.h
Normal file
50
ext/hash/sha3/generic64lc/KeccakP-1600-SnP.h
Normal 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
|
3
ext/hash/sha3/generic64lc/KeccakP-1600-opt64-config.h
Normal file
3
ext/hash/sha3/generic64lc/KeccakP-1600-opt64-config.h
Normal file
@ -0,0 +1,3 @@
|
||||
#define KeccakP1600_implementation_config "lane complementing, all rounds unrolled"
|
||||
#define KeccakP1600_fullUnrolling
|
||||
#define KeccakP1600_useLaneComplementing
|
484
ext/hash/sha3/generic64lc/KeccakP-1600-opt64.c
Normal file
484
ext/hash/sha3/generic64lc/KeccakP-1600-opt64.c
Normal 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;
|
||||
}
|
198
ext/hash/sha3/generic64lc/KeccakP-1600-unrolling.macros
Normal file
198
ext/hash/sha3/generic64lc/KeccakP-1600-unrolling.macros
Normal 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) \
|
||||
}
|
110
ext/hash/sha3/generic64lc/KeccakSponge.c
Normal file
110
ext/hash/sha3/generic64lc/KeccakSponge.c
Normal 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
|
178
ext/hash/sha3/generic64lc/KeccakSponge.h
Normal file
178
ext/hash/sha3/generic64lc/KeccakSponge.h
Normal 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
|
313
ext/hash/sha3/generic64lc/KeccakSponge.inc
Normal file
313
ext/hash/sha3/generic64lc/KeccakSponge.inc
Normal 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
|
134
ext/hash/sha3/generic64lc/SnP-Relaned.h
Normal file
134
ext/hash/sha3/generic64lc/SnP-Relaned.h
Normal 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
|
34
ext/hash/sha3/generic64lc/align.h
Normal file
34
ext/hash/sha3/generic64lc/align.h
Normal 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
|
142
ext/hash/sha3/generic64lc/brg_endian.h
Normal file
142
ext/hash/sha3/generic64lc/brg_endian.h
Normal 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
|
@ -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 )
|
||||
|
@ -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 )
|
||||
|
@ -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 {
|
||||
|
22
ext/intl/tests/bug74468.phpt
Normal file
22
ext/intl/tests/bug74468.phpt
Normal 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===
|
@ -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
Loading…
Reference in New Issue
Block a user