mirror of
https://github.com/bdnugget/php-src.git
synced 2026-11-13 04:00:50 +00:00
Compare commits
87
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
24324791c2 | ||
|
|
1922c650ba | ||
|
|
7ceb0e3a18 | ||
|
|
48cfd1160b | ||
|
|
7c31203935 | ||
|
|
1390a5812b | ||
|
|
906f19f136 | ||
|
|
c8f07ad477 | ||
|
|
259057b2a4 | ||
|
|
f06a069c46 | ||
|
|
e8429400d4 | ||
|
|
e201f01ac1 | ||
|
|
f9c2bf73ad | ||
|
|
ce2c67c8e8 | ||
|
|
03964892c0 | ||
|
|
64043cb9e5 | ||
|
|
df4bf28f9f | ||
|
|
1744be2d17 | ||
|
|
9ff3334397 | ||
|
|
dc72378ff0 | ||
|
|
b221df5549 | ||
|
|
da5321013c | ||
|
|
f1acac154a | ||
|
|
0a21b5d970 | ||
|
|
ee61c7175f | ||
|
|
51f9a00b47 | ||
|
|
dda81f0505 | ||
|
|
0e09009753 | ||
|
|
4d2278143a | ||
|
|
863bf294fe | ||
|
|
7381b6accc | ||
|
|
c7d3c027d5 | ||
|
|
c2e197e4ef | ||
|
|
7fc04937f5 | ||
|
|
8f1baa6e1c | ||
|
|
16023f3e3b | ||
|
|
7a4584d3f6 | ||
|
|
b7fa67742c | ||
|
|
e488690d95 | ||
|
|
c96d08b272 | ||
|
|
496f291f3d | ||
|
|
885edfef0a | ||
|
|
c8157619ef | ||
|
|
97aa752fee | ||
|
|
6dedeb40db | ||
|
|
bf58162ddf | ||
|
|
29533ae528 | ||
|
|
cd9c39d77c | ||
|
|
921544cad9 | ||
|
|
a621781fdb | ||
|
|
fdb580a5ad | ||
|
|
d263ecd864 | ||
|
|
dacea3f6fb | ||
|
|
cc7194dd10 | ||
|
|
5f67caad54 | ||
|
|
7f4e1a0eef | ||
|
|
f1ffb4b1ad | ||
|
|
9d168b863e | ||
|
|
eee8b6c33f | ||
|
|
539738c438 | ||
|
|
8036758491 | ||
|
|
f7d7befae8 | ||
|
|
531c306fe6 | ||
|
|
78d1228ef6 | ||
|
|
33a9f01d36 | ||
|
|
7ced40e24e | ||
|
|
4cc46b2a99 | ||
|
|
90a8ea9827 | ||
|
|
0765623d69 | ||
|
|
f38ca75a3c | ||
|
|
88aab478bf | ||
|
|
593c4b9b00 | ||
|
|
3ee3066bd0 | ||
|
|
f93d24aa67 | ||
|
|
4ceb7b46ad | ||
|
|
f473ea5464 | ||
|
|
2f83797a0c | ||
|
|
9c0813fd48 | ||
|
|
634aa0a2db | ||
|
|
ba1d9cc4b7 | ||
|
|
e2bbf0a2df | ||
|
|
c591f022f8 | ||
|
|
be9b2a95ad | ||
|
|
4605d536d2 | ||
|
|
c27f012b7a | ||
|
|
ac28329354 | ||
|
|
95fa727992 |
No files matched your search
@@ -19,6 +19,8 @@
|
||||
*.tgz
|
||||
*.tar.gz
|
||||
*.tar.bz2
|
||||
*.tar.gz.asc
|
||||
*.tar.bz2.asc
|
||||
.FBCIndex
|
||||
.FBCLockFolder
|
||||
.deps
|
||||
|
||||
@@ -1,15 +1,145 @@
|
||||
PHP NEWS
|
||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
?? ??? 2015 PHP 5.4.41
|
||||
03 Sep 2015 PHP 5.4.45
|
||||
|
||||
- Core:
|
||||
. Fixed bug #70172 (Use After Free Vulnerability in unserialize()). (Stas)
|
||||
. Fixed bug #70219 (Use after free vulnerability in session deserializer).
|
||||
(taoguangchen at icloud dot com)
|
||||
|
||||
- EXIF:
|
||||
. Fixed bug #70385 (Buffer over-read in exif_read_data with TIFF IFD tag byte
|
||||
value of 32 bytes). (Stas)
|
||||
|
||||
- hash:
|
||||
. Fixed bug #70312 (HAVAL gives wrong hashes in specific cases). (letsgolee
|
||||
at naver dot com)
|
||||
|
||||
- PCRE:
|
||||
. Fixed bug #70345 (Multiple vulnerabilities related to PCRE functions).
|
||||
(Anatol Belski)
|
||||
|
||||
- SOAP:
|
||||
. Fixed bug #70388 (SOAP serialize_function_call() type confusion / RCE).
|
||||
(Stas)
|
||||
|
||||
- SPL:
|
||||
. Fixed bug #70365 (Use-after-free vulnerability in unserialize() with
|
||||
SplObjectStorage). (taoguangchen at icloud dot com)
|
||||
. Fixed bug #70366 (Use-after-free vulnerability in unserialize() with
|
||||
SplDoublyLinkedList). (taoguangchen at icloud dot com)
|
||||
|
||||
- XSLT:
|
||||
. Fixed bug #69782 (NULL pointer dereference). (Stas)
|
||||
|
||||
- ZIP:
|
||||
. Fixed bug #70350 (ZipArchive::extractTo allows for directory traversal when
|
||||
creating directories). (neal at fb dot com)
|
||||
|
||||
06 Aug 2015 PHP 5.4.44
|
||||
|
||||
- Core:
|
||||
. Fixed bug #69793 (Remotely triggerable stack exhaustion via recursive
|
||||
method calls). (Stas)
|
||||
. Fixed bug #69892 (Different arrays compare indentical due to integer key
|
||||
truncation). (Nikita)
|
||||
. Fixed bug #70121 (unserialize() could lead to unexpected methods execution
|
||||
/ NULL pointer deref). (Stas)
|
||||
|
||||
- OpenSSL:
|
||||
. Fixed bug #70014 (openssl_random_pseudo_bytes() is not cryptographically
|
||||
secure). (Stas)
|
||||
|
||||
- Phar:
|
||||
. Improved fix for bug #69441. (Anatol Belski)
|
||||
. Fixed bug #70019 (Files extracted from archive may be placed outside of
|
||||
destination directory). (Anatol Belski)
|
||||
|
||||
- SOAP:
|
||||
. Fixed bug #70081 (SoapClient info leak / null pointer dereference via
|
||||
multiple type confusions). (Stas)
|
||||
|
||||
- SPL:
|
||||
. Fixed bug #70068 (Dangling pointer in the unserialization of ArrayObject
|
||||
items). (sean.heelan)
|
||||
. Fixed bug #70166 (Use After Free Vulnerability in unserialize() with
|
||||
SPLArrayObject). (taoguangchen at icloud dot com)
|
||||
. Fixed bug #70168 (Use After Free Vulnerability in unserialize() with
|
||||
SplObjectStorage). (taoguangchen at icloud dot com)
|
||||
. Fixed bug #70169 (Use After Free Vulnerability in unserialize() with
|
||||
SplDoublyLinkedList). (taoguangchen at icloud dot com)
|
||||
|
||||
09 Jul 2015 PHP 5.4.43
|
||||
|
||||
- Core:
|
||||
. Fixed bug #69768 (escapeshell*() doesn't cater to !). (cmb)
|
||||
. Fixed bug #69874 (Can't set empty additional_headers for mail()), regression
|
||||
from fix to bug #68776. (Yasuo)
|
||||
|
||||
- Mysqlnd:
|
||||
. Fixed bug #69669 (mysqlnd is vulnerable to BACKRONYM). (CVE-2015-3152)
|
||||
(Andrey)
|
||||
|
||||
- Phar:
|
||||
. Fixed bug #69958 (Segfault in Phar::convertToData on invalid file).
|
||||
(CVE-2015-5589) (Stas)
|
||||
. Fixed bug #69923 (Buffer overflow and stack smashing error in
|
||||
phar_fix_filepath). (CVE-2015-5590) (Stas)
|
||||
|
||||
11 Jun 2015 PHP 5.4.42
|
||||
|
||||
- Core:
|
||||
. Imroved fix for bug #69545 (Integer overflow in ftp_genlist() resulting in
|
||||
heap overflow). (CVE-2015-4643) (Max Spelsberg)
|
||||
. Fixed bug #69646 (OS command injection vulnerability in escapeshellarg).
|
||||
(CVE-2015-4642) (Anatol Belski)
|
||||
. Fixed bug #69719 (Incorrect handling of paths with NULs). (Stas)
|
||||
|
||||
- Litespeed SAPI:
|
||||
. Fixed bug #68812 (Unchecked return value). (George Wang)
|
||||
|
||||
- Mail:
|
||||
. Fixed bug #68776 (mail() does not have mail header injection prevention for
|
||||
additional headers). (Yasuo)
|
||||
|
||||
- Postgres:
|
||||
. Fixed bug #69667 (segfault in php_pgsql_meta_data). (CVE-2015-4644) (Remi)
|
||||
|
||||
- Sqlite3:
|
||||
. Upgrade bundled sqlite to 3.8.10.2. (CVE-2015-3414, CVE-2015-3415,
|
||||
CVE-2015-3416) (Kaplan)
|
||||
|
||||
14 May 2015 PHP 5.4.41
|
||||
|
||||
- Core:
|
||||
. Fixed bug #69364 (PHP Multipart/form-data remote dos Vulnerability).
|
||||
(CVE-2015-4024) (Stas)
|
||||
. Fixed bug #69403 (str_repeat() sign mismatch based memory corruption).
|
||||
(Stas)
|
||||
. Fixed bug #69418 (CVE-2006-7243 fix regressions in 5.4+). (CVE-2015-4025)
|
||||
(Stas)
|
||||
. Fixed bug #69522 (heap buffer overflow in unpack()). (Stas)
|
||||
|
||||
- FTP:
|
||||
. Fixed bug #69545 (Integer overflow in ftp_genlist() resulting in heap
|
||||
overflow). (CVE-2015-4022) (Stas)
|
||||
|
||||
- PCNTL:
|
||||
. Fixed bug #68598 (pcntl_exec() should not allow null char). (CVE-2015-4026)
|
||||
(Stas)
|
||||
|
||||
- PCRE
|
||||
. Upgraded pcrelib to 8.36.
|
||||
. Upgraded pcrelib to 8.37. (CVE-2015-2325, CVE-2015-2326)
|
||||
|
||||
- Phar:
|
||||
. Fixed bug #69453 (Memory Corruption in phar_parse_tarfile when entry
|
||||
filename starts with null). (CVE-2015-4021) (Stas)
|
||||
|
||||
16 Apr 2015 PHP 5.4.40
|
||||
|
||||
- Apache2handler:
|
||||
. Fixed bug #69218 (potential remote code execution with apache 2.4
|
||||
apache2handler). (Gerrit Venema)
|
||||
apache2handler). (CVE-2015-3330) (Gerrit Venema)
|
||||
|
||||
- Core:
|
||||
. Additional fix for bug #69152 (Type confusion vulnerability in
|
||||
@@ -31,13 +161,16 @@ PHP NEWS
|
||||
segfault). (Anatol Belski)
|
||||
|
||||
- GD:
|
||||
. Fixed bug #68601 (buffer read overflow in gd_gif_in.c). (Remi)
|
||||
. Fixed bug #68601 (buffer read overflow in gd_gif_in.c). (CVE-2014-9709)
|
||||
(Remi)
|
||||
|
||||
- Phar:
|
||||
. Fixed bug #68901 (use after free). (bugreports at internot dot info)
|
||||
. Fixed bug #69324 (Buffer Over-read in unserialize when parsing Phar). (Stas)
|
||||
. Fixed bug #68901 (use after free). (CVE-2015-2301) (bugreports at internot
|
||||
dot info)
|
||||
. Fixed bug #69324 (Buffer Over-read in unserialize when parsing Phar).
|
||||
(CVE-2015-2783) (Stas)
|
||||
. Fixed bug #69441 (Buffer Overflow when parsing tar/zip/phar in
|
||||
phar_set_inode). (Stas)
|
||||
phar_set_inode). (CVE-2015-3329) (Stas)
|
||||
|
||||
- Postgres:
|
||||
. Fixed bug #68741 (Null pointer deference) (CVE-2015-1352). (Xinchen Hui)
|
||||
@@ -56,7 +189,8 @@ PHP NEWS
|
||||
(CVE-2015-2787). (Stas)
|
||||
. Fixed bug #69134 (Per Directory Values overrides PHP_INI_SYSTEM
|
||||
configuration options). (Anatol Belski)
|
||||
. Fixed bug #69207 (move_uploaded_file allows nulls in path). (Stas)
|
||||
. Fixed bug #69207 (move_uploaded_file allows nulls in path). (CVE-2015-2348)
|
||||
(Stas)
|
||||
|
||||
- Ereg:
|
||||
. Fixed bug #69248 (heap overflow vulnerability in regcomp.c) (CVE-2015-2305).
|
||||
@@ -64,7 +198,7 @@ PHP NEWS
|
||||
|
||||
- SOAP:
|
||||
. Fixed bug #69085 (SoapClient's __call() type confusion through
|
||||
unserialize()). (Dmitry)
|
||||
unserialize()). (CVE-2015-4147, CVE-2015-4148) (Dmitry)
|
||||
|
||||
- ZIP:
|
||||
. Fixed bug #69253 (ZIP Integer Overflow leads to writing past heap
|
||||
|
||||
+6
-6
@@ -12,7 +12,7 @@ Collaboration is a Good Thing(tm), and Git lets us do this. Thus, following
|
||||
some basic rules with regards to Git usage will::
|
||||
|
||||
a. Make everybody happier, especially those responsible for maintaining
|
||||
Git itself.
|
||||
PHP itself.
|
||||
|
||||
b. Keep the changes consistently well documented and easily trackable.
|
||||
|
||||
@@ -48,11 +48,11 @@ Currently we have the following branches in use::
|
||||
PHP-5.6 Is used to release the PHP 5.6.x series. This is a current
|
||||
stable version and is open for bugfixes only.
|
||||
|
||||
PHP-5.5 Is used to release the PHP 5.5.x series. This is a current
|
||||
stable version and is open for bugfixes only.
|
||||
PHP-5.5 Is used to release the PHP 5.5.x series. This is an old
|
||||
stable version and is open for security fixes only.
|
||||
|
||||
PHP-5.4 Is used to release the PHP 5.4.x series. This is a current
|
||||
stable version and is open for bugfixes only.
|
||||
PHP-5.4 Is used to release the PHP 5.4.x series. This is an old
|
||||
stable version and is open for security fixes only.
|
||||
|
||||
PHP-5.3 This branch is closed.
|
||||
|
||||
@@ -67,7 +67,7 @@ Currently we have the following branches in use::
|
||||
|
||||
The next few rules are more of a technical nature::
|
||||
|
||||
1. All changes should first go to the lowest branch (i.e. 5.4) and then
|
||||
1. All changes should first go to the lowest branch (i.e. 5.6) and then
|
||||
get merged up to all other branches. If a change is not needed for
|
||||
later branches (i.e. fixes for features which where dropped from later
|
||||
branches) an empty merge should be done.
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
--TEST--
|
||||
Bug #69892: Different arrays compare indentical due to integer key truncation
|
||||
--SKIPIF--
|
||||
<?php if (PHP_INT_SIZE != 8) die("skip this test is for 64bit platforms only"); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
var_dump([0 => 0] === [0x100000000 => 0]);
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(false)
|
||||
@@ -0,0 +1,9 @@
|
||||
--TEST--
|
||||
Bug #70121 (unserialize() could lead to unexpected methods execution / NULL pointer deref)
|
||||
--FILE--
|
||||
<?php
|
||||
unserialize('O:12:"DateInterval":1:{s:4:"days";O:9:"Exception":7:{s:10:"'."\0".'*'."\0".'message";s:1:"x";s:17:"'."\0".'Exception'."\0".'string";s:1:"A";s:7:"'."\0".'*'."\0".'code";i:0;s:7:"'."\0".'*'."\0".'file";s:1:"a";s:7:"'."\0".'*'."\0".'line";i:1337;s:16:"'."\0".'Exception'."\0".'trace";a:0:{}s:19:"'."\0".'Exception'."\0".'previous";O:8:"stdClass":0:{}}}');
|
||||
?>
|
||||
OK
|
||||
--EXPECT--
|
||||
OK
|
||||
+11
-11
@@ -980,7 +980,7 @@ static void zend_mm_random(unsigned char *buf, size_t size) /* {{{ */
|
||||
int has_context = 0;
|
||||
|
||||
if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)) {
|
||||
/* Could mean that the key container does not exist, let try
|
||||
/* Could mean that the key container does not exist, let try
|
||||
again by asking for a new one */
|
||||
if (GetLastError() == NTE_BAD_KEYSET) {
|
||||
if (CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) {
|
||||
@@ -1344,7 +1344,7 @@ static int zend_mm_check_ptr(zend_mm_heap *heap, void *ptr, int silent ZEND_FILE
|
||||
}
|
||||
if (!silent) {
|
||||
TSRMLS_FETCH();
|
||||
|
||||
|
||||
zend_message_dispatcher(ZMSG_LOG_SCRIPT_NAME, NULL TSRMLS_CC);
|
||||
zend_debug_alloc_output("---------------------------------------\n");
|
||||
zend_debug_alloc_output("%s(%d) : Block "PTR_FMT" status:\n" ZEND_FILE_LINE_RELAY_CC, ptr);
|
||||
@@ -2171,7 +2171,7 @@ static void *_zend_mm_realloc_int(zend_mm_heap *heap, void *p, size_t size ZEND_
|
||||
#if ZEND_MM_CACHE
|
||||
if (ZEND_MM_SMALL_SIZE(true_size)) {
|
||||
size_t index = ZEND_MM_BUCKET_INDEX(true_size);
|
||||
|
||||
|
||||
if (heap->cache[index] != NULL) {
|
||||
zend_mm_free_block *best_fit;
|
||||
zend_mm_free_block **cache;
|
||||
@@ -2184,7 +2184,7 @@ static void *_zend_mm_realloc_int(zend_mm_heap *heap, void *p, size_t size ZEND_
|
||||
heap->cache[index] = best_fit->prev_free_block;
|
||||
ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_CACHED);
|
||||
ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 0);
|
||||
|
||||
|
||||
ptr = ZEND_MM_DATA_OF(best_fit);
|
||||
|
||||
#if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
|
||||
@@ -2466,7 +2466,7 @@ static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
|
||||
: "%0"(res),
|
||||
"rm"(size),
|
||||
"rm"(offset));
|
||||
|
||||
|
||||
if (UNEXPECTED(overflow)) {
|
||||
zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
|
||||
return 0;
|
||||
@@ -2575,7 +2575,7 @@ ZEND_API void *_ecalloc(size_t nmemb, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LI
|
||||
|
||||
ZEND_API char *_estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
|
||||
{
|
||||
int length;
|
||||
size_t length;
|
||||
char *p;
|
||||
#ifdef ZEND_SIGNALS
|
||||
TSRMLS_FETCH();
|
||||
@@ -2583,13 +2583,13 @@ ZEND_API char *_estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
|
||||
|
||||
HANDLE_BLOCK_INTERRUPTIONS();
|
||||
|
||||
length = strlen(s)+1;
|
||||
p = (char *) _emalloc(length ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
|
||||
length = strlen(s);
|
||||
p = (char *) _emalloc(safe_address(length, 1, 1) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
|
||||
if (UNEXPECTED(p == NULL)) {
|
||||
HANDLE_UNBLOCK_INTERRUPTIONS();
|
||||
return p;
|
||||
}
|
||||
memcpy(p, s, length);
|
||||
memcpy(p, s, length+1);
|
||||
HANDLE_UNBLOCK_INTERRUPTIONS();
|
||||
return p;
|
||||
}
|
||||
@@ -2603,7 +2603,7 @@ ZEND_API char *_estrndup(const char *s, uint length ZEND_FILE_LINE_DC ZEND_FILE_
|
||||
|
||||
HANDLE_BLOCK_INTERRUPTIONS();
|
||||
|
||||
p = (char *) _emalloc(length+1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
|
||||
p = (char *) _emalloc(safe_address(length, 1, 1) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
|
||||
if (UNEXPECTED(p == NULL)) {
|
||||
HANDLE_UNBLOCK_INTERRUPTIONS();
|
||||
return p;
|
||||
@@ -2624,7 +2624,7 @@ ZEND_API char *zend_strndup(const char *s, uint length)
|
||||
|
||||
HANDLE_BLOCK_INTERRUPTIONS();
|
||||
|
||||
p = (char *) malloc(length+1);
|
||||
p = (char *) malloc(safe_address(length, 1, 1));
|
||||
if (UNEXPECTED(p == NULL)) {
|
||||
HANDLE_UNBLOCK_INTERRUPTIONS();
|
||||
return p;
|
||||
|
||||
+37
-8
@@ -41,7 +41,7 @@ void zend_exception_set_previous(zval *exception, zval *add_previous TSRMLS_DC)
|
||||
if (exception == add_previous || !add_previous || !exception) {
|
||||
return;
|
||||
}
|
||||
if (Z_TYPE_P(add_previous) != IS_OBJECT && !instanceof_function(Z_OBJCE_P(add_previous), default_exception_ce TSRMLS_CC)) {
|
||||
if (Z_TYPE_P(add_previous) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(add_previous), default_exception_ce TSRMLS_CC)) {
|
||||
zend_error(E_ERROR, "Cannot set non exception as previous exception");
|
||||
return;
|
||||
}
|
||||
@@ -218,6 +218,33 @@ ZEND_METHOD(exception, __construct)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto Exception::__wakeup()
|
||||
Exception unserialize checks */
|
||||
#define CHECK_EXC_TYPE(name, type) \
|
||||
value = zend_read_property(default_exception_ce, object, name, sizeof(name)-1, 0 TSRMLS_CC); \
|
||||
if(value && Z_TYPE_P(value) != type) { \
|
||||
zval *tmp; \
|
||||
MAKE_STD_ZVAL(tmp); \
|
||||
ZVAL_STRINGL(tmp, name, sizeof(name)-1, 1); \
|
||||
Z_OBJ_HANDLER_P(object, unset_property)(object, tmp, 0 TSRMLS_CC); \
|
||||
zval_ptr_dtor(&tmp); \
|
||||
}
|
||||
|
||||
ZEND_METHOD(exception, __wakeup)
|
||||
{
|
||||
zval *value;
|
||||
zval *object = getThis();
|
||||
HashTable *intern_ht = zend_std_get_properties(getThis() TSRMLS_CC);
|
||||
CHECK_EXC_TYPE("message", IS_STRING);
|
||||
CHECK_EXC_TYPE("string", IS_STRING);
|
||||
CHECK_EXC_TYPE("code", IS_LONG);
|
||||
CHECK_EXC_TYPE("file", IS_STRING);
|
||||
CHECK_EXC_TYPE("line", IS_LONG);
|
||||
CHECK_EXC_TYPE("trace", IS_ARRAY);
|
||||
CHECK_EXC_TYPE("previous", IS_OBJECT);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto ErrorException::__construct(string message, int code, int severity [, string filename [, int lineno [, Exception previous]]])
|
||||
ErrorException constructor */
|
||||
ZEND_METHOD(error_exception, __construct)
|
||||
@@ -586,7 +613,7 @@ ZEND_METHOD(exception, getTraceAsString)
|
||||
int res_len = 0, *len = &res_len, num = 0;
|
||||
|
||||
DEFAULT_0_PARAMS;
|
||||
|
||||
|
||||
trace = zend_read_property(default_exception_ce, getThis(), "trace", sizeof("trace")-1, 1 TSRMLS_CC);
|
||||
if(Z_TYPE_P(trace) != IS_ARRAY) {
|
||||
RETURN_FALSE;
|
||||
@@ -602,8 +629,8 @@ ZEND_METHOD(exception, getTraceAsString)
|
||||
TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
|
||||
efree(s_tmp);
|
||||
|
||||
res[res_len] = '\0';
|
||||
RETURN_STRINGL(res, res_len, 0);
|
||||
res[res_len] = '\0';
|
||||
RETURN_STRINGL(res, res_len, 0);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -640,15 +667,15 @@ ZEND_METHOD(exception, __toString)
|
||||
int len = 0;
|
||||
zend_fcall_info fci;
|
||||
zval fname;
|
||||
|
||||
|
||||
DEFAULT_0_PARAMS;
|
||||
|
||||
|
||||
str = estrndup("", 0);
|
||||
|
||||
exception = getThis();
|
||||
ZVAL_STRINGL(&fname, "gettraceasstring", sizeof("gettraceasstring")-1, 1);
|
||||
|
||||
while (exception && Z_TYPE_P(exception) == IS_OBJECT) {
|
||||
while (exception && Z_TYPE_P(exception) == IS_OBJECT && instanceof_function(Z_OBJCE_P(exception), default_exception_ce TSRMLS_CC)) {
|
||||
prev_str = str;
|
||||
_default_exception_get_entry(exception, "message", sizeof("message")-1, &message TSRMLS_CC);
|
||||
_default_exception_get_entry(exception, "file", sizeof("file")-1, &file TSRMLS_CC);
|
||||
@@ -658,6 +685,7 @@ ZEND_METHOD(exception, __toString)
|
||||
convert_to_string(&file);
|
||||
convert_to_long(&line);
|
||||
|
||||
trace = NULL;
|
||||
fci.size = sizeof(fci);
|
||||
fci.function_table = &Z_OBJCE_P(exception)->function_table;
|
||||
fci.function_name = &fname;
|
||||
@@ -670,7 +698,7 @@ ZEND_METHOD(exception, __toString)
|
||||
|
||||
zend_call_function(&fci, NULL TSRMLS_CC);
|
||||
|
||||
if (Z_TYPE_P(trace) != IS_STRING) {
|
||||
if (trace && Z_TYPE_P(trace) != IS_STRING) {
|
||||
zval_ptr_dtor(&trace);
|
||||
trace = NULL;
|
||||
}
|
||||
@@ -727,6 +755,7 @@ ZEND_END_ARG_INFO()
|
||||
const static zend_function_entry default_exception_functions[] = {
|
||||
ZEND_ME(exception, __clone, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
|
||||
ZEND_ME(exception, __construct, arginfo_exception___construct, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(exception, __wakeup, NULL, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(exception, getMessage, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
|
||||
ZEND_ME(exception, getCode, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
|
||||
ZEND_ME(exception, getFile, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
|
||||
|
||||
+2
-3
@@ -1513,11 +1513,10 @@ ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t co
|
||||
}
|
||||
if (ordered) {
|
||||
if (p1->nKeyLength==0 && p2->nKeyLength==0) { /* numeric indices */
|
||||
result = p1->h - p2->h;
|
||||
if (result!=0) {
|
||||
if (p1->h != p2->h) {
|
||||
HASH_UNPROTECT_RECURSION(ht1);
|
||||
HASH_UNPROTECT_RECURSION(ht2);
|
||||
return result;
|
||||
return p1->h > p2->h ? 1 : -1;
|
||||
}
|
||||
} else { /* string indices */
|
||||
result = p1->nKeyLength - p2->nKeyLength;
|
||||
|
||||
@@ -1264,14 +1264,19 @@ ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{
|
||||
zend_error(E_ERROR, "String size overflow");
|
||||
}
|
||||
|
||||
Z_STRVAL_P(result) = erealloc(Z_STRVAL_P(result), res_len+1);
|
||||
Z_STRVAL_P(result) = safe_erealloc(Z_STRVAL_P(result), res_len, 1, 1);
|
||||
|
||||
memcpy(Z_STRVAL_P(result)+Z_STRLEN_P(result), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
|
||||
Z_STRVAL_P(result)[res_len]=0;
|
||||
Z_STRLEN_P(result) = res_len;
|
||||
} else {
|
||||
int length = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);
|
||||
char *buf = (char *) emalloc(length + 1);
|
||||
char *buf;
|
||||
|
||||
if (Z_STRLEN_P(op1) < 0 || Z_STRLEN_P(op2) < 0 || (int) (Z_STRLEN_P(op1) + Z_STRLEN_P(op2)) < 0) {
|
||||
zend_error(E_ERROR, "String size overflow");
|
||||
}
|
||||
buf = (char *) safe_emalloc(length, 1, 1);
|
||||
|
||||
memcpy(buf, Z_STRVAL_P(op1), Z_STRLEN_P(op1));
|
||||
memcpy(buf + Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
|
||||
@@ -2067,7 +2072,7 @@ ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2) /* {{{ */
|
||||
} else if (ret2!=IS_DOUBLE) {
|
||||
if (oflow1) {
|
||||
ZVAL_LONG(result, oflow1);
|
||||
return;
|
||||
return;
|
||||
}
|
||||
dval2 = (double) lval2;
|
||||
} else if (dval1 == dval2 && !zend_finite(dval1)) {
|
||||
|
||||
+2
-2
@@ -119,8 +119,8 @@ int zend_sprintf(char *buffer, const char *format, ...);
|
||||
|
||||
PHP_MAJOR_VERSION=5
|
||||
PHP_MINOR_VERSION=4
|
||||
PHP_RELEASE_VERSION=41
|
||||
PHP_EXTRA_VERSION="-dev"
|
||||
PHP_RELEASE_VERSION=45
|
||||
PHP_EXTRA_VERSION=""
|
||||
PHP_VERSION="$PHP_MAJOR_VERSION.$PHP_MINOR_VERSION.$PHP_RELEASE_VERSION$PHP_EXTRA_VERSION"
|
||||
PHP_VERSION_ID=`expr [$]PHP_MAJOR_VERSION \* 10000 + [$]PHP_MINOR_VERSION \* 100 + [$]PHP_RELEASE_VERSION`
|
||||
|
||||
|
||||
+73
-67
@@ -548,7 +548,7 @@ static zend_object_handlers date_object_handlers_period;
|
||||
#define DATE_SET_CONTEXT \
|
||||
zval *object; \
|
||||
object = getThis(); \
|
||||
|
||||
|
||||
#define DATE_FETCH_OBJECT \
|
||||
php_date_obj *obj; \
|
||||
DATE_SET_CONTEXT; \
|
||||
@@ -715,7 +715,7 @@ PHP_RSHUTDOWN_FUNCTION(date)
|
||||
* RFC2822, Section 3.3: http://www.ietf.org/rfc/rfc2822.txt
|
||||
* FWS = ([*WSP CRLF] 1*WSP) / ; Folding white space
|
||||
* CFWS = *([FWS] comment) (([FWS] comment) / FWS)
|
||||
*
|
||||
*
|
||||
* date-time = [ day-of-week "," ] date FWS time [CFWS]
|
||||
* day-of-week = ([FWS] day-name)
|
||||
* day-name = "Mon" / "Tue" / "Wed" / "Thu" / "Fri" / "Sat" / "Sun"
|
||||
@@ -737,19 +737,19 @@ PHP_RSHUTDOWN_FUNCTION(date)
|
||||
* date-fullyear = 4DIGIT
|
||||
* date-month = 2DIGIT ; 01-12
|
||||
* date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31 based on month/year
|
||||
*
|
||||
*
|
||||
* time-hour = 2DIGIT ; 00-23
|
||||
* time-minute = 2DIGIT ; 00-59
|
||||
* time-second = 2DIGIT ; 00-58, 00-59, 00-60 based on leap second rules
|
||||
*
|
||||
*
|
||||
* time-secfrac = "." 1*DIGIT
|
||||
* time-numoffset = ("+" / "-") time-hour ":" time-minute
|
||||
* time-offset = "Z" / time-numoffset
|
||||
*
|
||||
*
|
||||
* partial-time = time-hour ":" time-minute ":" time-second [time-secfrac]
|
||||
* full-date = date-fullyear "-" date-month "-" date-mday
|
||||
* full-time = partial-time time-offset
|
||||
*
|
||||
*
|
||||
* date-time = full-date "T" full-time
|
||||
*/
|
||||
#define DATE_FORMAT_RFC3339 "Y-m-d\\TH:i:sP"
|
||||
@@ -839,7 +839,7 @@ PHP_MSHUTDOWN_FUNCTION(date)
|
||||
PHP_MINFO_FUNCTION(date)
|
||||
{
|
||||
const timelib_tzdb *tzdb = DATE_TIMEZONEDB;
|
||||
|
||||
|
||||
php_info_print_table_start();
|
||||
php_info_print_table_row(2, "date/time support", "enabled");
|
||||
php_info_print_table_row(2, "\"Olson\" Timezone Database Version", tzdb->version);
|
||||
@@ -991,8 +991,8 @@ char *php_date_full_day_name(timelib_sll y, timelib_sll m, timelib_sll d)
|
||||
timelib_sll day_of_week = timelib_day_of_week(y, m, d);
|
||||
if (day_of_week < 0) {
|
||||
return "Unknown";
|
||||
}
|
||||
return day_full_names[day_of_week];
|
||||
}
|
||||
return day_full_names[day_of_week];
|
||||
}
|
||||
|
||||
char *php_date_short_day_name(timelib_sll y, timelib_sll m, timelib_sll d)
|
||||
@@ -1000,8 +1000,8 @@ char *php_date_short_day_name(timelib_sll y, timelib_sll m, timelib_sll d)
|
||||
timelib_sll day_of_week = timelib_day_of_week(y, m, d);
|
||||
if (day_of_week < 0) {
|
||||
return "Unknown";
|
||||
}
|
||||
return day_short_names[day_of_week];
|
||||
}
|
||||
return day_short_names[day_of_week];
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -1033,7 +1033,7 @@ static char *date_format(char *format, int format_len, timelib_time *t, int loca
|
||||
offset->leap_secs = 0;
|
||||
offset->is_dst = 0;
|
||||
offset->abbr = malloc(9); /* GMT�xxxx\0 */
|
||||
snprintf(offset->abbr, 9, "GMT%c%02d%02d",
|
||||
snprintf(offset->abbr, 9, "GMT%c%02d%02d",
|
||||
localtime ? ((offset->offset < 0) ? '-' : '+') : '+',
|
||||
localtime ? abs(offset->offset / 3600) : 0,
|
||||
localtime ? abs((offset->offset % 3600) / 60) : 0 );
|
||||
@@ -1079,7 +1079,7 @@ static char *date_format(char *format, int format_len, timelib_time *t, int loca
|
||||
case 'a': length = slprintf(buffer, 32, "%s", t->h >= 12 ? "pm" : "am"); break;
|
||||
case 'A': length = slprintf(buffer, 32, "%s", t->h >= 12 ? "PM" : "AM"); break;
|
||||
case 'B': {
|
||||
int retval = (((((long)t->sse)-(((long)t->sse) - ((((long)t->sse) % 86400) + 3600))) * 10) / 864);
|
||||
int retval = (((((long)t->sse)-(((long)t->sse) - ((((long)t->sse) % 86400) + 3600))) * 10) / 864);
|
||||
while (retval < 0) {
|
||||
retval += 1000;
|
||||
}
|
||||
@@ -1179,7 +1179,7 @@ static void php_date(INTERNAL_FUNCTION_PARAMETERS, int localtime)
|
||||
}
|
||||
|
||||
string = php_format_date(format, format_len, ts, localtime TSRMLS_CC);
|
||||
|
||||
|
||||
RETVAL_STRING(string, 0);
|
||||
}
|
||||
/* }}} */
|
||||
@@ -1203,7 +1203,7 @@ PHPAPI char *php_format_date(char *format, int format_len, time_t ts, int localt
|
||||
}
|
||||
|
||||
string = date_format(format, format_len, t, localtime);
|
||||
|
||||
|
||||
timelib_time_dtor(t);
|
||||
return string;
|
||||
}
|
||||
@@ -1244,7 +1244,7 @@ PHPAPI int php_idate(char format, time_t ts, int localtime TSRMLS_DC)
|
||||
offset->leap_secs = 0;
|
||||
offset->is_dst = t->dst;
|
||||
offset->abbr = malloc(9); /* GMT�xxxx\0 */
|
||||
snprintf(offset->abbr, 9, "GMT%c%02d%02d",
|
||||
snprintf(offset->abbr, 9, "GMT%c%02d%02d",
|
||||
!localtime ? ((offset->offset < 0) ? '-' : '+') : '+',
|
||||
!localtime ? abs(offset->offset / 3600) : 0,
|
||||
!localtime ? abs((offset->offset % 3600) / 60) : 0 );
|
||||
@@ -1276,7 +1276,7 @@ PHPAPI int php_idate(char format, time_t ts, int localtime TSRMLS_DC)
|
||||
|
||||
/* Swatch Beat a.k.a. Internet Time */
|
||||
case 'B':
|
||||
retval = (((((long)t->sse)-(((long)t->sse) - ((((long)t->sse) % 86400) + 3600))) * 10) / 864);
|
||||
retval = (((((long)t->sse)-(((long)t->sse) - ((((long)t->sse) % 86400) + 3600))) * 10) / 864);
|
||||
while (retval < 0) {
|
||||
retval += 1000;
|
||||
}
|
||||
@@ -1328,7 +1328,7 @@ PHP_FUNCTION(idate)
|
||||
char *format;
|
||||
int format_len;
|
||||
long ts = 0;
|
||||
int ret;
|
||||
int ret;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &format, &format_len, &ts) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
@@ -1356,7 +1356,7 @@ PHP_FUNCTION(idate)
|
||||
PHPAPI void php_date_set_tzdb(timelib_tzdb *tzdb)
|
||||
{
|
||||
const timelib_tzdb *builtin = timelib_builtin_db();
|
||||
|
||||
|
||||
if (php_version_compare(tzdb->version, builtin->version) > 0) {
|
||||
php_date_global_timezone_db = tzdb;
|
||||
php_date_global_timezone_db_enabled = 1;
|
||||
@@ -1428,7 +1428,7 @@ PHP_FUNCTION(strtotime)
|
||||
}
|
||||
|
||||
if (!time_len) {
|
||||
timelib_time_dtor(now);
|
||||
timelib_time_dtor(now);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
@@ -1869,7 +1869,7 @@ static void date_period_it_current_data(zend_object_iterator *iter, zval ***data
|
||||
if (it_time->tz_info) {
|
||||
newdateobj->time->tz_info = it_time->tz_info;
|
||||
}
|
||||
|
||||
|
||||
*data = &iterator->current;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -2037,13 +2037,13 @@ static inline zend_object_value date_object_new_date_ex(zend_class_entry *class_
|
||||
if (ptr) {
|
||||
*ptr = intern;
|
||||
}
|
||||
|
||||
|
||||
zend_object_std_init(&intern->std, class_type TSRMLS_CC);
|
||||
object_properties_init(&intern->std, class_type);
|
||||
|
||||
|
||||
retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_date, NULL TSRMLS_CC);
|
||||
retval.handlers = &date_object_handlers_date;
|
||||
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -2057,12 +2057,12 @@ static zend_object_value date_object_clone_date(zval *this_ptr TSRMLS_DC)
|
||||
php_date_obj *new_obj = NULL;
|
||||
php_date_obj *old_obj = (php_date_obj *) zend_object_store_get_object(this_ptr TSRMLS_CC);
|
||||
zend_object_value new_ov = date_object_new_date_ex(old_obj->std.ce, &new_obj TSRMLS_CC);
|
||||
|
||||
|
||||
zend_objects_clone_members(&new_obj->std, new_ov, &old_obj->std, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC);
|
||||
if (!old_obj->time) {
|
||||
return new_ov;
|
||||
}
|
||||
|
||||
|
||||
/* this should probably moved to a new `timelib_time *timelime_time_clone(timelib_time *)` */
|
||||
new_obj->time = timelib_time_ctor();
|
||||
*new_obj->time = *old_obj->time;
|
||||
@@ -2072,7 +2072,7 @@ static zend_object_value date_object_clone_date(zval *this_ptr TSRMLS_DC)
|
||||
if (old_obj->time->tz_info) {
|
||||
new_obj->time->tz_info = old_obj->time->tz_info;
|
||||
}
|
||||
|
||||
|
||||
return new_ov;
|
||||
}
|
||||
|
||||
@@ -2094,10 +2094,10 @@ static int date_object_compare_date(zval *d1, zval *d2 TSRMLS_DC)
|
||||
if (!o2->time->sse_uptodate) {
|
||||
timelib_update_ts(o2->time, o2->time->tz_info);
|
||||
}
|
||||
|
||||
|
||||
return (o1->time->sse == o2->time->sse) ? 0 : ((o1->time->sse < o2->time->sse) ? -1 : 1);
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -2174,10 +2174,10 @@ static inline zend_object_value date_object_new_timezone_ex(zend_class_entry *cl
|
||||
|
||||
zend_object_std_init(&intern->std, class_type TSRMLS_CC);
|
||||
object_properties_init(&intern->std, class_type);
|
||||
|
||||
|
||||
retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_timezone, NULL TSRMLS_CC);
|
||||
retval.handlers = &date_object_handlers_timezone;
|
||||
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -2191,12 +2191,12 @@ static zend_object_value date_object_clone_timezone(zval *this_ptr TSRMLS_DC)
|
||||
php_timezone_obj *new_obj = NULL;
|
||||
php_timezone_obj *old_obj = (php_timezone_obj *) zend_object_store_get_object(this_ptr TSRMLS_CC);
|
||||
zend_object_value new_ov = date_object_new_timezone_ex(old_obj->std.ce, &new_obj TSRMLS_CC);
|
||||
|
||||
|
||||
zend_objects_clone_members(&new_obj->std, new_ov, &old_obj->std, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC);
|
||||
if (!old_obj->initialized) {
|
||||
return new_ov;
|
||||
}
|
||||
|
||||
|
||||
new_obj->type = old_obj->type;
|
||||
new_obj->initialized = 1;
|
||||
switch (new_obj->type) {
|
||||
@@ -2212,7 +2212,7 @@ static zend_object_value date_object_clone_timezone(zval *this_ptr TSRMLS_DC)
|
||||
new_obj->tzi.z.abbr = old_obj->tzi.z.abbr;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return new_ov;
|
||||
}
|
||||
|
||||
@@ -2229,10 +2229,10 @@ static inline zend_object_value date_object_new_interval_ex(zend_class_entry *cl
|
||||
|
||||
zend_object_std_init(&intern->std, class_type TSRMLS_CC);
|
||||
object_properties_init(&intern->std, class_type);
|
||||
|
||||
|
||||
retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_interval, NULL TSRMLS_CC);
|
||||
retval.handlers = &date_object_handlers_interval;
|
||||
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -2246,7 +2246,7 @@ static zend_object_value date_object_clone_interval(zval *this_ptr TSRMLS_DC)
|
||||
php_interval_obj *new_obj = NULL;
|
||||
php_interval_obj *old_obj = (php_interval_obj *) zend_object_store_get_object(this_ptr TSRMLS_CC);
|
||||
zend_object_value new_ov = date_object_new_interval_ex(old_obj->std.ce, &new_obj TSRMLS_CC);
|
||||
|
||||
|
||||
zend_objects_clone_members(&new_obj->std, new_ov, &old_obj->std, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC);
|
||||
|
||||
/** FIX ME ADD CLONE STUFF **/
|
||||
@@ -2318,10 +2318,10 @@ static inline zend_object_value date_object_new_period_ex(zend_class_entry *clas
|
||||
|
||||
zend_object_std_init(&intern->std, class_type TSRMLS_CC);
|
||||
object_properties_init(&intern->std, class_type);
|
||||
|
||||
|
||||
retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_period, NULL TSRMLS_CC);
|
||||
retval.handlers = &date_object_handlers_period;
|
||||
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -2335,7 +2335,7 @@ static zend_object_value date_object_clone_period(zval *this_ptr TSRMLS_DC)
|
||||
php_period_obj *new_obj = NULL;
|
||||
php_period_obj *old_obj = (php_period_obj *) zend_object_store_get_object(this_ptr TSRMLS_CC);
|
||||
zend_object_value new_ov = date_object_new_period_ex(old_obj->std.ce, &new_obj TSRMLS_CC);
|
||||
|
||||
|
||||
zend_objects_clone_members(&new_obj->std, new_ov, &old_obj->std, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC);
|
||||
|
||||
/** FIX ME ADD CLONE STUFF **/
|
||||
@@ -2421,7 +2421,7 @@ PHPAPI int php_date_initialize(php_date_obj *dateobj, /*const*/ char *time_str,
|
||||
int type = TIMELIB_ZONETYPE_ID, new_dst = 0;
|
||||
char *new_abbr = NULL;
|
||||
timelib_sll new_offset;
|
||||
|
||||
|
||||
if (dateobj->time) {
|
||||
timelib_time_dtor(dateobj->time);
|
||||
}
|
||||
@@ -2710,7 +2710,7 @@ void php_date_do_return_parsed_time(INTERNAL_FUNCTION_PARAMETERS, timelib_time *
|
||||
PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(hour, h);
|
||||
PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(minute, i);
|
||||
PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(second, s);
|
||||
|
||||
|
||||
if (parsed_time->f == -99999) {
|
||||
add_assoc_bool(return_value, "fraction", 0);
|
||||
} else {
|
||||
@@ -2777,7 +2777,7 @@ PHP_FUNCTION(date_parse)
|
||||
int date_len;
|
||||
struct timelib_error_container *error;
|
||||
timelib_time *parsed_time;
|
||||
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &date, &date_len) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
@@ -2796,7 +2796,7 @@ PHP_FUNCTION(date_parse_from_format)
|
||||
int date_len, format_len;
|
||||
struct timelib_error_container *error;
|
||||
timelib_time *parsed_time;
|
||||
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &format, &format_len, &date, &date_len) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
@@ -3123,7 +3123,7 @@ PHP_FUNCTION(date_isodate_set)
|
||||
memset(&dateobj->time->relative, 0, sizeof(dateobj->time->relative));
|
||||
dateobj->time->relative.d = timelib_daynr_from_weeknr(y, w, d);
|
||||
dateobj->time->have_relative = 1;
|
||||
|
||||
|
||||
timelib_update_ts(dateobj->time, NULL);
|
||||
|
||||
RETURN_ZVAL(object, 1, 0);
|
||||
@@ -3210,15 +3210,15 @@ PHP_FUNCTION(date_diff)
|
||||
static int timezone_initialize(timelib_tzinfo **tzi, /*const*/ char *tz TSRMLS_DC)
|
||||
{
|
||||
char *tzid;
|
||||
|
||||
|
||||
*tzi = NULL;
|
||||
|
||||
|
||||
if ((tzid = timelib_timezone_id_from_abbr(tz, -1, 0))) {
|
||||
*tzi = php_date_parse_tzfile(tzid, DATE_TIMEZONEDB TSRMLS_CC);
|
||||
} else {
|
||||
*tzi = php_date_parse_tzfile(tz, DATE_TIMEZONEDB TSRMLS_CC);
|
||||
}
|
||||
|
||||
|
||||
if (*tzi) {
|
||||
return SUCCESS;
|
||||
} else {
|
||||
@@ -3260,7 +3260,7 @@ PHP_METHOD(DateTimeZone, __construct)
|
||||
timelib_tzinfo *tzi = NULL;
|
||||
php_timezone_obj *tzobj;
|
||||
zend_error_handling error_handling;
|
||||
|
||||
|
||||
zend_replace_error_handling(EH_THROW, NULL, &error_handling TSRMLS_CC);
|
||||
if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &tz, &tz_len)) {
|
||||
if (SUCCESS == timezone_initialize(&tzi, tz TSRMLS_CC)) {
|
||||
@@ -3487,7 +3487,7 @@ static int date_interval_initialize(timelib_rel_time **rt, /*const*/ char *forma
|
||||
struct timelib_error_container *errors;
|
||||
|
||||
timelib_strtointerval(format, format_length, &b, &e, &p, &r, &errors);
|
||||
|
||||
|
||||
if (errors->error_count > 0) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown or bad format (%s)", format);
|
||||
retval = FAILURE;
|
||||
@@ -3646,7 +3646,7 @@ PHP_METHOD(DateInterval, __construct)
|
||||
php_interval_obj *diobj;
|
||||
timelib_rel_time *reltime;
|
||||
zend_error_handling error_handling;
|
||||
|
||||
|
||||
zend_replace_error_handling(EH_THROW, NULL, &error_handling TSRMLS_CC);
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &interval_string, &interval_string_length) == SUCCESS) {
|
||||
if (date_interval_initialize(&reltime, interval_string, interval_string_length TSRMLS_CC) == SUCCESS) {
|
||||
@@ -3669,8 +3669,7 @@ static int php_date_interval_initialize_from_hash(zval **return_value, php_inter
|
||||
#define PHP_DATE_INTERVAL_READ_PROPERTY(element, member, itype, def) \
|
||||
do { \
|
||||
zval **z_arg = NULL; \
|
||||
if (zend_hash_find(myht, element, strlen(element) + 1, (void**) &z_arg) == SUCCESS) { \
|
||||
convert_to_long(*z_arg); \
|
||||
if (zend_hash_find(myht, element, strlen(element) + 1, (void**) &z_arg) == SUCCESS && Z_TYPE_PP(z_arg) == IS_LONG) { \
|
||||
(*intobj)->diff->member = (itype)Z_LVAL_PP(z_arg); \
|
||||
} else { \
|
||||
(*intobj)->diff->member = (itype)def; \
|
||||
@@ -3681,8 +3680,15 @@ static int php_date_interval_initialize_from_hash(zval **return_value, php_inter
|
||||
do { \
|
||||
zval **z_arg = NULL; \
|
||||
if (zend_hash_find(myht, element, strlen(element) + 1, (void**) &z_arg) == SUCCESS) { \
|
||||
convert_to_string(*z_arg); \
|
||||
DATE_A64I((*intobj)->diff->member, Z_STRVAL_PP(z_arg)); \
|
||||
if (Z_TYPE_PP(z_arg) == IS_STRING) { \
|
||||
DATE_A64I((*intobj)->diff->member, Z_STRVAL_PP(z_arg)); \
|
||||
} else if (Z_TYPE_PP(z_arg) == IS_LONG || Z_TYPE_PP(z_arg) == IS_BOOL) { \
|
||||
(*intobj)->diff->member = (timelib_sll)Z_LVAL_PP(z_arg); \
|
||||
} else if (Z_TYPE_PP(z_arg) == IS_DOUBLE) { \
|
||||
(*intobj)->diff->member = (timelib_sll)Z_DVAL_PP(z_arg); \
|
||||
} else { \
|
||||
(*intobj)->diff->member = -1LL; \
|
||||
} \
|
||||
} else { \
|
||||
(*intobj)->diff->member = -1LL; \
|
||||
} \
|
||||
@@ -3860,7 +3866,7 @@ static int date_period_initialize(timelib_time **st, timelib_time **et, timelib_
|
||||
struct timelib_error_container *errors;
|
||||
|
||||
timelib_strtointerval(format, format_length, &b, &e, &p, &r, &errors);
|
||||
|
||||
|
||||
if (errors->error_count > 0) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown or bad format (%s)", format);
|
||||
retval = FAILURE;
|
||||
@@ -3889,7 +3895,7 @@ PHP_METHOD(DatePeriod, __construct)
|
||||
int isostr_len = 0;
|
||||
timelib_time *clone;
|
||||
zend_error_handling error_handling;
|
||||
|
||||
|
||||
zend_replace_error_handling(EH_THROW, NULL, &error_handling TSRMLS_CC);
|
||||
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "OOl|l", &start, date_ce_date, &interval, date_ce_interval, &recurrences, &options) == FAILURE) {
|
||||
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "OOO|l", &start, date_ce_date, &interval, date_ce_interval, &end, date_ce_date, &options) == FAILURE) {
|
||||
@@ -4002,7 +4008,7 @@ PHP_FUNCTION(timezone_identifiers_list)
|
||||
tzdb = DATE_TIMEZONEDB;
|
||||
item_count = tzdb->index_size;
|
||||
table = tzdb->index;
|
||||
|
||||
|
||||
array_init(return_value);
|
||||
|
||||
for (i = 0; i < item_count; ++i) {
|
||||
@@ -4036,7 +4042,7 @@ PHP_FUNCTION(timezone_abbreviations_list)
|
||||
{
|
||||
const timelib_tz_lookup_table *table, *entry;
|
||||
zval *element, **abbr_array_pp, *abbr_array;
|
||||
|
||||
|
||||
table = timelib_timezone_abbreviations_list();
|
||||
array_init(return_value);
|
||||
entry = table;
|
||||
@@ -4112,11 +4118,11 @@ static void php_do_date_sunrise_sunset(INTERNAL_FUNCTION_PARAMETERS, int calc_su
|
||||
timelib_time *t;
|
||||
timelib_tzinfo *tzi;
|
||||
char *retstr;
|
||||
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|ldddd", &time, &retformat, &latitude, &longitude, &zenith, &gmt_offset) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
|
||||
switch (ZEND_NUM_ARGS()) {
|
||||
case 1:
|
||||
retformat = SUNFUNCS_RET_STRING;
|
||||
@@ -4160,7 +4166,7 @@ static void php_do_date_sunrise_sunset(INTERNAL_FUNCTION_PARAMETERS, int calc_su
|
||||
timelib_unixtime2local(t, time);
|
||||
rs = timelib_astro_rise_set_altitude(t, longitude, latitude, altitude, 1, &h_rise, &h_set, &rise, &set, &transit);
|
||||
timelib_time_dtor(t);
|
||||
|
||||
|
||||
if (rs != 0) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
@@ -4214,7 +4220,7 @@ PHP_FUNCTION(date_sun_info)
|
||||
timelib_sll rise, set, transit;
|
||||
int dummy;
|
||||
double ddummy;
|
||||
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ldd", &time, &latitude, &longitude) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
@@ -4228,7 +4234,7 @@ PHP_FUNCTION(date_sun_info)
|
||||
/* Setup */
|
||||
t2 = timelib_time_ctor();
|
||||
array_init(return_value);
|
||||
|
||||
|
||||
/* Get sun up/down and transit */
|
||||
rs = timelib_astro_rise_set_altitude(t, longitude, latitude, -35.0/60, 1, &ddummy, &ddummy, &rise, &set, &transit);
|
||||
switch (rs) {
|
||||
@@ -4372,7 +4378,7 @@ static HashTable *date_object_get_properties_period(zval *object TSRMLS_DC)
|
||||
ZVAL_NULL(zv);
|
||||
}
|
||||
zend_hash_update(props, "interval", sizeof("interval"), &zv, sizeof(zv), NULL);
|
||||
|
||||
|
||||
/* converted to larger type (int->long); must check when unserializing */
|
||||
MAKE_STD_ZVAL(zv);
|
||||
ZVAL_LONG(zv, (long) period_obj->recurrences);
|
||||
@@ -4454,7 +4460,7 @@ static int php_date_period_initialize_from_hash(php_period_obj *period_obj, Hash
|
||||
}
|
||||
|
||||
period_obj->initialized = 1;
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -4471,7 +4477,7 @@ PHP_METHOD(DatePeriod, __set_state)
|
||||
}
|
||||
|
||||
myht = Z_ARRVAL_P(array);
|
||||
|
||||
|
||||
object_init_ex(return_value, date_ce_period);
|
||||
period_obj = zend_object_store_get_object(return_value TSRMLS_CC);
|
||||
if (!php_date_period_initialize_from_hash(period_obj, myht TSRMLS_CC)) {
|
||||
|
||||
@@ -14,17 +14,17 @@ var_dump($di);
|
||||
--EXPECTF--
|
||||
object(DateInterval)#%d (15) {
|
||||
["y"]=>
|
||||
int(2)
|
||||
int(-1)
|
||||
["m"]=>
|
||||
int(0)
|
||||
int(-1)
|
||||
["d"]=>
|
||||
int(0)
|
||||
int(-1)
|
||||
["h"]=>
|
||||
int(6)
|
||||
int(-1)
|
||||
["i"]=>
|
||||
int(8)
|
||||
int(-1)
|
||||
["s"]=>
|
||||
int(0)
|
||||
int(-1)
|
||||
["weekday"]=>
|
||||
int(10)
|
||||
["weekday_behavior"]=>
|
||||
|
||||
@@ -14,17 +14,17 @@ var_dump($di);
|
||||
--EXPECTF--
|
||||
object(DateInterval)#%d (15) {
|
||||
["y"]=>
|
||||
int(2)
|
||||
int(-1)
|
||||
["m"]=>
|
||||
int(0)
|
||||
int(-1)
|
||||
["d"]=>
|
||||
int(0)
|
||||
int(-1)
|
||||
["h"]=>
|
||||
int(6)
|
||||
int(-1)
|
||||
["i"]=>
|
||||
int(8)
|
||||
int(-1)
|
||||
["s"]=>
|
||||
int(0)
|
||||
int(-1)
|
||||
["weekday"]=>
|
||||
int(10)
|
||||
["weekday_behavior"]=>
|
||||
|
||||
+17
-5
@@ -1761,7 +1761,7 @@ PHP_FUNCTION(dom_document_save)
|
||||
char *file;
|
||||
long options = 0;
|
||||
|
||||
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os|l", &id, dom_document_class_entry, &file, &file_len, &options) == FAILURE) {
|
||||
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Op|l", &id, dom_document_class_entry, &file, &file_len, &options) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1990,7 +1990,7 @@ static void _dom_document_schema_validate(INTERNAL_FUNCTION_PARAMETERS, int type
|
||||
int is_valid;
|
||||
char resolved_path[MAXPATHLEN + 1];
|
||||
|
||||
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Op", &id, dom_document_class_entry, &source, &source_len) == FAILURE) {
|
||||
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &id, dom_document_class_entry, &source, &source_len) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2003,6 +2003,10 @@ static void _dom_document_schema_validate(INTERNAL_FUNCTION_PARAMETERS, int type
|
||||
|
||||
switch (type) {
|
||||
case DOM_LOAD_FILE:
|
||||
if (CHECK_NULL_PATH(source, source_len)) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Schema file source");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
valid_file = _dom_get_valid_file_path(source, resolved_path, MAXPATHLEN TSRMLS_CC);
|
||||
if (!valid_file) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Schema file source");
|
||||
@@ -2079,7 +2083,7 @@ static void _dom_document_relaxNG_validate(INTERNAL_FUNCTION_PARAMETERS, int typ
|
||||
int is_valid;
|
||||
char resolved_path[MAXPATHLEN + 1];
|
||||
|
||||
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Op", &id, dom_document_class_entry, &source, &source_len) == FAILURE) {
|
||||
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &id, dom_document_class_entry, &source, &source_len) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2092,6 +2096,10 @@ static void _dom_document_relaxNG_validate(INTERNAL_FUNCTION_PARAMETERS, int typ
|
||||
|
||||
switch (type) {
|
||||
case DOM_LOAD_FILE:
|
||||
if (CHECK_NULL_PATH(source, source_len)) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid RelaxNG file source");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
valid_file = _dom_get_valid_file_path(source, resolved_path, MAXPATHLEN TSRMLS_CC);
|
||||
if (!valid_file) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid RelaxNG file source");
|
||||
@@ -2172,7 +2180,7 @@ static void dom_load_html(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */
|
||||
|
||||
id = getThis();
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|l", &source, &source_len, &options) == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &source, &source_len, &options) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2182,6 +2190,10 @@ static void dom_load_html(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */
|
||||
}
|
||||
|
||||
if (mode == DOM_LOAD_FILE) {
|
||||
if (CHECK_NULL_PATH(source, source_len)) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid file source");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
ctxt = htmlCreateFileParserCtxt(source, NULL);
|
||||
} else {
|
||||
source_len = xmlStrlen(source);
|
||||
@@ -2270,7 +2282,7 @@ PHP_FUNCTION(dom_document_save_html_file)
|
||||
char *file;
|
||||
const char *encoding;
|
||||
|
||||
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &id, dom_document_class_entry, &file, &file_len) == FAILURE) {
|
||||
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Op", &id, dom_document_class_entry, &file, &file_len) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,9 +15,9 @@ $result = $doc->loadHTMLFile("");
|
||||
assert('$result === false');
|
||||
$doc = new DOMDocument();
|
||||
$result = $doc->loadHTMLFile("text.html\0something");
|
||||
assert('$result === null');
|
||||
assert('$result === false');
|
||||
?>
|
||||
--EXPECTF--
|
||||
%r(PHP ){0,1}%rWarning: DOMDocument::loadHTMLFile(): Empty string supplied as input %s
|
||||
|
||||
%r(PHP ){0,1}%rWarning: DOMDocument::loadHTMLFile() expects parameter 1 to be a valid path, string given %s
|
||||
%r(PHP ){0,1}%rWarning: DOMDocument::loadHTMLFile(): Invalid file source %s
|
||||
+106
-106
@@ -74,7 +74,7 @@
|
||||
#include "php_ini.h"
|
||||
#include "ext/standard/php_string.h"
|
||||
#include "ext/standard/php_image.h"
|
||||
#include "ext/standard/info.h"
|
||||
#include "ext/standard/info.h"
|
||||
|
||||
/* needed for ssize_t definition */
|
||||
#include <sys/types.h>
|
||||
@@ -161,7 +161,7 @@ ZEND_BEGIN_MODULE_GLOBALS(exif)
|
||||
char * encode_jis;
|
||||
char * decode_jis_be;
|
||||
char * decode_jis_le;
|
||||
ZEND_END_MODULE_GLOBALS(exif)
|
||||
ZEND_END_MODULE_GLOBALS(exif)
|
||||
|
||||
ZEND_DECLARE_MODULE_GLOBALS(exif)
|
||||
|
||||
@@ -170,7 +170,7 @@ ZEND_DECLARE_MODULE_GLOBALS(exif)
|
||||
#else
|
||||
#define EXIF_G(v) (exif_globals.v)
|
||||
#endif
|
||||
|
||||
|
||||
/* {{{ PHP_INI
|
||||
*/
|
||||
|
||||
@@ -213,7 +213,7 @@ PHP_INI_BEGIN()
|
||||
STD_PHP_INI_ENTRY("exif.decode_jis_intel", "JIS", PHP_INI_ALL, OnUpdateDecode, decode_jis_le, zend_exif_globals, exif_globals)
|
||||
PHP_INI_END()
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ PHP_GINIT_FUNCTION
|
||||
*/
|
||||
static PHP_GINIT_FUNCTION(exif)
|
||||
@@ -233,9 +233,9 @@ PHP_MINIT_FUNCTION(exif)
|
||||
{
|
||||
REGISTER_INI_ENTRIES();
|
||||
if (zend_hash_exists(&module_registry, "mbstring", sizeof("mbstring"))) {
|
||||
REGISTER_LONG_CONSTANT("EXIF_USE_MBSTRING", 1, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("EXIF_USE_MBSTRING", 1, CONST_CS | CONST_PERSISTENT);
|
||||
} else {
|
||||
REGISTER_LONG_CONSTANT("EXIF_USE_MBSTRING", 0, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("EXIF_USE_MBSTRING", 0, CONST_CS | CONST_PERSISTENT);
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
@@ -265,7 +265,7 @@ zend_module_entry exif_module_entry = {
|
||||
exif_module_deps,
|
||||
"exif",
|
||||
exif_functions,
|
||||
PHP_MINIT(exif),
|
||||
PHP_MINIT(exif),
|
||||
PHP_MSHUTDOWN(exif),
|
||||
NULL, NULL,
|
||||
PHP_MINFO(exif),
|
||||
@@ -278,7 +278,7 @@ zend_module_entry exif_module_entry = {
|
||||
NULL,
|
||||
NULL,
|
||||
STANDARD_MODULE_PROPERTIES_EX
|
||||
#else
|
||||
#else
|
||||
STANDARD_MODULE_PROPERTIES
|
||||
#endif
|
||||
};
|
||||
@@ -667,73 +667,73 @@ static tag_info_array tag_table_IFD = {
|
||||
{ 0x0213, "YCbCrPositioning"},
|
||||
{ 0x0214, "ReferenceBlackWhite"},
|
||||
{ 0x02BC, "ExtensibleMetadataPlatform"}, /* XAP: Extensible Authoring Publishing, obsoleted by XMP: Extensible Metadata Platform */
|
||||
{ 0x0301, "Gamma"},
|
||||
{ 0x0302, "ICCProfileDescriptor"},
|
||||
{ 0x0303, "SRGBRenderingIntent"},
|
||||
{ 0x0320, "ImageTitle"},
|
||||
{ 0x5001, "ResolutionXUnit"},
|
||||
{ 0x5002, "ResolutionYUnit"},
|
||||
{ 0x5003, "ResolutionXLengthUnit"},
|
||||
{ 0x5004, "ResolutionYLengthUnit"},
|
||||
{ 0x5005, "PrintFlags"},
|
||||
{ 0x5006, "PrintFlagsVersion"},
|
||||
{ 0x5007, "PrintFlagsCrop"},
|
||||
{ 0x5008, "PrintFlagsBleedWidth"},
|
||||
{ 0x5009, "PrintFlagsBleedWidthScale"},
|
||||
{ 0x500A, "HalftoneLPI"},
|
||||
{ 0x500B, "HalftoneLPIUnit"},
|
||||
{ 0x500C, "HalftoneDegree"},
|
||||
{ 0x500D, "HalftoneShape"},
|
||||
{ 0x500E, "HalftoneMisc"},
|
||||
{ 0x500F, "HalftoneScreen"},
|
||||
{ 0x5010, "JPEGQuality"},
|
||||
{ 0x5011, "GridSize"},
|
||||
{ 0x5012, "ThumbnailFormat"},
|
||||
{ 0x5013, "ThumbnailWidth"},
|
||||
{ 0x5014, "ThumbnailHeight"},
|
||||
{ 0x5015, "ThumbnailColorDepth"},
|
||||
{ 0x5016, "ThumbnailPlanes"},
|
||||
{ 0x5017, "ThumbnailRawBytes"},
|
||||
{ 0x5018, "ThumbnailSize"},
|
||||
{ 0x5019, "ThumbnailCompressedSize"},
|
||||
{ 0x501A, "ColorTransferFunction"},
|
||||
{ 0x501B, "ThumbnailData"},
|
||||
{ 0x5020, "ThumbnailImageWidth"},
|
||||
{ 0x5021, "ThumbnailImageHeight"},
|
||||
{ 0x5022, "ThumbnailBitsPerSample"},
|
||||
{ 0x5023, "ThumbnailCompression"},
|
||||
{ 0x5024, "ThumbnailPhotometricInterp"},
|
||||
{ 0x5025, "ThumbnailImageDescription"},
|
||||
{ 0x5026, "ThumbnailEquipMake"},
|
||||
{ 0x5027, "ThumbnailEquipModel"},
|
||||
{ 0x5028, "ThumbnailStripOffsets"},
|
||||
{ 0x5029, "ThumbnailOrientation"},
|
||||
{ 0x502A, "ThumbnailSamplesPerPixel"},
|
||||
{ 0x502B, "ThumbnailRowsPerStrip"},
|
||||
{ 0x502C, "ThumbnailStripBytesCount"},
|
||||
{ 0x502D, "ThumbnailResolutionX"},
|
||||
{ 0x502E, "ThumbnailResolutionY"},
|
||||
{ 0x502F, "ThumbnailPlanarConfig"},
|
||||
{ 0x5030, "ThumbnailResolutionUnit"},
|
||||
{ 0x5031, "ThumbnailTransferFunction"},
|
||||
{ 0x5032, "ThumbnailSoftwareUsed"},
|
||||
{ 0x5033, "ThumbnailDateTime"},
|
||||
{ 0x5034, "ThumbnailArtist"},
|
||||
{ 0x5035, "ThumbnailWhitePoint"},
|
||||
{ 0x5036, "ThumbnailPrimaryChromaticities"},
|
||||
{ 0x5037, "ThumbnailYCbCrCoefficients"},
|
||||
{ 0x5038, "ThumbnailYCbCrSubsampling"},
|
||||
{ 0x5039, "ThumbnailYCbCrPositioning"},
|
||||
{ 0x503A, "ThumbnailRefBlackWhite"},
|
||||
{ 0x503B, "ThumbnailCopyRight"},
|
||||
{ 0x5090, "LuminanceTable"},
|
||||
{ 0x5091, "ChrominanceTable"},
|
||||
{ 0x5100, "FrameDelay"},
|
||||
{ 0x5101, "LoopCount"},
|
||||
{ 0x5110, "PixelUnit"},
|
||||
{ 0x5111, "PixelPerUnitX"},
|
||||
{ 0x5112, "PixelPerUnitY"},
|
||||
{ 0x5113, "PaletteHistogram"},
|
||||
{ 0x0301, "Gamma"},
|
||||
{ 0x0302, "ICCProfileDescriptor"},
|
||||
{ 0x0303, "SRGBRenderingIntent"},
|
||||
{ 0x0320, "ImageTitle"},
|
||||
{ 0x5001, "ResolutionXUnit"},
|
||||
{ 0x5002, "ResolutionYUnit"},
|
||||
{ 0x5003, "ResolutionXLengthUnit"},
|
||||
{ 0x5004, "ResolutionYLengthUnit"},
|
||||
{ 0x5005, "PrintFlags"},
|
||||
{ 0x5006, "PrintFlagsVersion"},
|
||||
{ 0x5007, "PrintFlagsCrop"},
|
||||
{ 0x5008, "PrintFlagsBleedWidth"},
|
||||
{ 0x5009, "PrintFlagsBleedWidthScale"},
|
||||
{ 0x500A, "HalftoneLPI"},
|
||||
{ 0x500B, "HalftoneLPIUnit"},
|
||||
{ 0x500C, "HalftoneDegree"},
|
||||
{ 0x500D, "HalftoneShape"},
|
||||
{ 0x500E, "HalftoneMisc"},
|
||||
{ 0x500F, "HalftoneScreen"},
|
||||
{ 0x5010, "JPEGQuality"},
|
||||
{ 0x5011, "GridSize"},
|
||||
{ 0x5012, "ThumbnailFormat"},
|
||||
{ 0x5013, "ThumbnailWidth"},
|
||||
{ 0x5014, "ThumbnailHeight"},
|
||||
{ 0x5015, "ThumbnailColorDepth"},
|
||||
{ 0x5016, "ThumbnailPlanes"},
|
||||
{ 0x5017, "ThumbnailRawBytes"},
|
||||
{ 0x5018, "ThumbnailSize"},
|
||||
{ 0x5019, "ThumbnailCompressedSize"},
|
||||
{ 0x501A, "ColorTransferFunction"},
|
||||
{ 0x501B, "ThumbnailData"},
|
||||
{ 0x5020, "ThumbnailImageWidth"},
|
||||
{ 0x5021, "ThumbnailImageHeight"},
|
||||
{ 0x5022, "ThumbnailBitsPerSample"},
|
||||
{ 0x5023, "ThumbnailCompression"},
|
||||
{ 0x5024, "ThumbnailPhotometricInterp"},
|
||||
{ 0x5025, "ThumbnailImageDescription"},
|
||||
{ 0x5026, "ThumbnailEquipMake"},
|
||||
{ 0x5027, "ThumbnailEquipModel"},
|
||||
{ 0x5028, "ThumbnailStripOffsets"},
|
||||
{ 0x5029, "ThumbnailOrientation"},
|
||||
{ 0x502A, "ThumbnailSamplesPerPixel"},
|
||||
{ 0x502B, "ThumbnailRowsPerStrip"},
|
||||
{ 0x502C, "ThumbnailStripBytesCount"},
|
||||
{ 0x502D, "ThumbnailResolutionX"},
|
||||
{ 0x502E, "ThumbnailResolutionY"},
|
||||
{ 0x502F, "ThumbnailPlanarConfig"},
|
||||
{ 0x5030, "ThumbnailResolutionUnit"},
|
||||
{ 0x5031, "ThumbnailTransferFunction"},
|
||||
{ 0x5032, "ThumbnailSoftwareUsed"},
|
||||
{ 0x5033, "ThumbnailDateTime"},
|
||||
{ 0x5034, "ThumbnailArtist"},
|
||||
{ 0x5035, "ThumbnailWhitePoint"},
|
||||
{ 0x5036, "ThumbnailPrimaryChromaticities"},
|
||||
{ 0x5037, "ThumbnailYCbCrCoefficients"},
|
||||
{ 0x5038, "ThumbnailYCbCrSubsampling"},
|
||||
{ 0x5039, "ThumbnailYCbCrPositioning"},
|
||||
{ 0x503A, "ThumbnailRefBlackWhite"},
|
||||
{ 0x503B, "ThumbnailCopyRight"},
|
||||
{ 0x5090, "LuminanceTable"},
|
||||
{ 0x5091, "ChrominanceTable"},
|
||||
{ 0x5100, "FrameDelay"},
|
||||
{ 0x5101, "LoopCount"},
|
||||
{ 0x5110, "PixelUnit"},
|
||||
{ 0x5111, "PixelPerUnitX"},
|
||||
{ 0x5112, "PixelPerUnitY"},
|
||||
{ 0x5113, "PaletteHistogram"},
|
||||
{ 0x1000, "RelatedImageFileFormat"},
|
||||
{ 0x800D, "ImageID"},
|
||||
{ 0x80E3, "Matteing"}, /* obsoleted by ExtraSamples */
|
||||
@@ -939,7 +939,7 @@ static tag_info_array tag_table_VND_NIKON = {
|
||||
{ 0x000b, "Converter"},
|
||||
TAG_TABLE_END
|
||||
};
|
||||
|
||||
|
||||
static tag_info_array tag_table_VND_NIKON_990 = {
|
||||
{ 0x0001, "Version"},
|
||||
{ 0x0002, "ISOSetting"},
|
||||
@@ -958,7 +958,7 @@ static tag_info_array tag_table_VND_NIKON_990 = {
|
||||
{ 0x0010, "DataDump"},
|
||||
TAG_TABLE_END
|
||||
};
|
||||
|
||||
|
||||
static tag_info_array tag_table_VND_OLYMPUS = {
|
||||
{ 0x0200, "SpecialMode"},
|
||||
{ 0x0201, "JPEGQuality"},
|
||||
@@ -1224,7 +1224,7 @@ char * exif_dump_data(int *dump_free, int format, int components, int length, in
|
||||
if (components > 0) {
|
||||
dump = erealloc(dump, len + 2 + 1);
|
||||
snprintf(dump + len, 2 + 1, ", ");
|
||||
len += 2;
|
||||
len += 2;
|
||||
components--;
|
||||
} else{
|
||||
break;
|
||||
@@ -1574,7 +1574,7 @@ typedef struct {
|
||||
static void exif_error_docref(const char *docref EXIFERR_DC, const image_info_type *ImageInfo, int type, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
|
||||
va_start(args, format);
|
||||
#ifdef EXIF_DEBUG
|
||||
{
|
||||
@@ -2627,7 +2627,7 @@ static int exif_process_user_comment(image_info_type *ImageInfo, char **pszInfoP
|
||||
*pszEncoding = estrdup((const char*)szValuePtr);
|
||||
szValuePtr = szValuePtr+8;
|
||||
ByteCount -= 8;
|
||||
/* First try to detect BOM: ZERO WIDTH NOBREAK SPACE (FEFF 16)
|
||||
/* First try to detect BOM: ZERO WIDTH NOBREAK SPACE (FEFF 16)
|
||||
* since we have no encoding support for the BOM yet we skip that.
|
||||
*/
|
||||
if (!memcmp(szValuePtr, "\xFE\xFF", 2)) {
|
||||
@@ -2645,8 +2645,8 @@ static int exif_process_user_comment(image_info_type *ImageInfo, char **pszInfoP
|
||||
}
|
||||
/* XXX this will fail again if encoding_converter returns on error something different than SIZE_MAX */
|
||||
if (zend_multibyte_encoding_converter(
|
||||
(unsigned char**)pszInfoPtr,
|
||||
&len,
|
||||
(unsigned char**)pszInfoPtr,
|
||||
&len,
|
||||
(unsigned char*)szValuePtr,
|
||||
ByteCount,
|
||||
zend_multibyte_fetch_encoding(ImageInfo->encode_unicode TSRMLS_CC),
|
||||
@@ -2666,8 +2666,8 @@ static int exif_process_user_comment(image_info_type *ImageInfo, char **pszInfoP
|
||||
ByteCount -= 8;
|
||||
/* XXX this will fail again if encoding_converter returns on error something different than SIZE_MAX */
|
||||
if (zend_multibyte_encoding_converter(
|
||||
(unsigned char**)pszInfoPtr,
|
||||
&len,
|
||||
(unsigned char**)pszInfoPtr,
|
||||
&len,
|
||||
(unsigned char*)szValuePtr,
|
||||
ByteCount,
|
||||
zend_multibyte_fetch_encoding(ImageInfo->encode_jis TSRMLS_CC),
|
||||
@@ -2701,12 +2701,12 @@ static int exif_process_user_comment(image_info_type *ImageInfo, char **pszInfoP
|
||||
* Process unicode field in IFD. */
|
||||
static int exif_process_unicode(image_info_type *ImageInfo, xp_field_type *xp_field, int tag, char *szValuePtr, int ByteCount TSRMLS_DC)
|
||||
{
|
||||
xp_field->tag = tag;
|
||||
xp_field->tag = tag;
|
||||
xp_field->value = NULL;
|
||||
/* XXX this will fail again if encoding_converter returns on error something different than SIZE_MAX */
|
||||
if (zend_multibyte_encoding_converter(
|
||||
(unsigned char**)&xp_field->value,
|
||||
&xp_field->size,
|
||||
(unsigned char**)&xp_field->value,
|
||||
&xp_field->size,
|
||||
(unsigned char*)szValuePtr,
|
||||
ByteCount,
|
||||
zend_multibyte_fetch_encoding(ImageInfo->encode_unicode TSRMLS_CC),
|
||||
@@ -2731,7 +2731,7 @@ static int exif_process_IFD_in_MAKERNOTE(image_info_type *ImageInfo, char * valu
|
||||
if (i==sizeof(maker_note_array)/sizeof(maker_note_type))
|
||||
return FALSE;
|
||||
maker_note = maker_note_array+i;
|
||||
|
||||
|
||||
/*exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_NOTICE, "check (%s,%s)", maker_note->make?maker_note->make:"", maker_note->model?maker_note->model:"");*/
|
||||
if (maker_note->make && (!ImageInfo->make || strcmp(maker_note->make, ImageInfo->make)))
|
||||
continue;
|
||||
@@ -2852,9 +2852,9 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, cha
|
||||
offset_val = php_ifd_get32u(dir_entry+8, ImageInfo->motorola_intel);
|
||||
/* If its bigger than 4 bytes, the dir entry contains an offset. */
|
||||
value_ptr = offset_base+offset_val;
|
||||
/*
|
||||
/*
|
||||
dir_entry is ImageInfo->file.list[sn].data+2+i*12
|
||||
offset_base is ImageInfo->file.list[sn].data-dir_offset
|
||||
offset_base is ImageInfo->file.list[sn].data-dir_offset
|
||||
dir_entry - offset_base is dir_offset+2+i*12
|
||||
*/
|
||||
if (byte_count > IFDlength || offset_val > IFDlength-byte_count || value_ptr < dir_entry || offset_val < (size_t)(dir_entry-offset_base)) {
|
||||
@@ -2925,18 +2925,18 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, cha
|
||||
case TAG_COMP_IMAGE_WIDTH:
|
||||
ImageInfo->Thumbnail.width = exif_convert_any_to_int(value_ptr, format, ImageInfo->motorola_intel TSRMLS_CC);
|
||||
break;
|
||||
|
||||
|
||||
case TAG_IMAGEHEIGHT:
|
||||
case TAG_COMP_IMAGE_HEIGHT:
|
||||
ImageInfo->Thumbnail.height = exif_convert_any_to_int(value_ptr, format, ImageInfo->motorola_intel TSRMLS_CC);
|
||||
break;
|
||||
|
||||
|
||||
case TAG_STRIP_OFFSETS:
|
||||
case TAG_JPEG_INTERCHANGE_FORMAT:
|
||||
/* accept both formats */
|
||||
ImageInfo->Thumbnail.offset = exif_convert_any_to_int(value_ptr, format, ImageInfo->motorola_intel TSRMLS_CC);
|
||||
break;
|
||||
|
||||
|
||||
case TAG_STRIP_BYTE_COUNTS:
|
||||
if (ImageInfo->FileType == IMAGE_FILETYPE_TIFF_II || ImageInfo->FileType == IMAGE_FILETYPE_TIFF_MM) {
|
||||
ImageInfo->Thumbnail.filetype = ImageInfo->FileType;
|
||||
@@ -2946,7 +2946,7 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, cha
|
||||
}
|
||||
ImageInfo->Thumbnail.size = exif_convert_any_to_int(value_ptr, format, ImageInfo->motorola_intel TSRMLS_CC);
|
||||
break;
|
||||
|
||||
|
||||
case TAG_JPEG_INTERCHANGE_FORMAT_LEN:
|
||||
if (ImageInfo->Thumbnail.filetype == IMAGE_FILETYPE_UNKNOWN) {
|
||||
ImageInfo->Thumbnail.filetype = IMAGE_FILETYPE_JPEG;
|
||||
@@ -2964,16 +2964,16 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, cha
|
||||
if (length<byte_count-1) {
|
||||
/* When there are any characters after the first NUL */
|
||||
ImageInfo->CopyrightPhotographer = estrdup(value_ptr);
|
||||
ImageInfo->CopyrightEditor = estrdup(value_ptr+length+1);
|
||||
ImageInfo->CopyrightEditor = estrndup(value_ptr+length+1, byte_count-length-1);
|
||||
spprintf(&ImageInfo->Copyright, 0, "%s, %s", value_ptr, value_ptr+length+1);
|
||||
/* format = TAG_FMT_UNDEFINED; this musn't be ASCII */
|
||||
/* but we are not supposed to change this */
|
||||
/* keep in mind that image_info does not store editor value */
|
||||
} else {
|
||||
ImageInfo->Copyright = estrdup(value_ptr);
|
||||
ImageInfo->Copyright = estrndup(value_ptr, byte_count);
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case TAG_USERCOMMENT:
|
||||
ImageInfo->UserCommentLength = exif_process_user_comment(ImageInfo, &(ImageInfo->UserComment), &(ImageInfo->UserCommentEncoding), value_ptr, byte_count TSRMLS_CC);
|
||||
@@ -3061,10 +3061,10 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, cha
|
||||
break;
|
||||
|
||||
case TAG_MAKE:
|
||||
ImageInfo->make = estrdup(value_ptr);
|
||||
ImageInfo->make = estrndup(value_ptr, byte_count);
|
||||
break;
|
||||
case TAG_MODEL:
|
||||
ImageInfo->model = estrdup(value_ptr);
|
||||
ImageInfo->model = estrndup(value_ptr, byte_count);
|
||||
break;
|
||||
|
||||
case TAG_MAKER_NOTE:
|
||||
@@ -3414,7 +3414,7 @@ static int exif_scan_JPEG_header(image_info_type *ImageInfo TSRMLS_DC)
|
||||
if ((itemlen - 2) < 6) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
exif_process_SOFn(Data, marker, &sof_info);
|
||||
ImageInfo->Width = sof_info.width;
|
||||
ImageInfo->Height = sof_info.height;
|
||||
@@ -3459,21 +3459,21 @@ static int exif_scan_thumbnail(image_info_type *ImageInfo TSRMLS_DC)
|
||||
}
|
||||
for (;;) {
|
||||
pos += length;
|
||||
if (pos>=ImageInfo->Thumbnail.size)
|
||||
if (pos>=ImageInfo->Thumbnail.size)
|
||||
return FALSE;
|
||||
c = data[pos++];
|
||||
if (pos>=ImageInfo->Thumbnail.size)
|
||||
if (pos>=ImageInfo->Thumbnail.size)
|
||||
return FALSE;
|
||||
if (c != 0xFF) {
|
||||
return FALSE;
|
||||
}
|
||||
n = 8;
|
||||
while ((c = data[pos++]) == 0xFF && n--) {
|
||||
if (pos+3>=ImageInfo->Thumbnail.size)
|
||||
if (pos+3>=ImageInfo->Thumbnail.size)
|
||||
return FALSE;
|
||||
/* +3 = pos++ of next check when reaching marker + 2 bytes for length */
|
||||
}
|
||||
if (c == 0xFF)
|
||||
if (c == 0xFF)
|
||||
return FALSE;
|
||||
marker = c;
|
||||
length = php_jpg_get16(data+pos);
|
||||
@@ -3787,7 +3787,7 @@ static int exif_scan_FILE_header(image_info_type *ImageInfo TSRMLS_DC)
|
||||
exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_NOTICE, "File has TIFF/II format");
|
||||
#endif
|
||||
ImageInfo->sections_found |= FOUND_IFD0;
|
||||
if (exif_process_IFD_in_TIFF(ImageInfo,
|
||||
if (exif_process_IFD_in_TIFF(ImageInfo,
|
||||
php_ifd_get32u(file_header + 4, ImageInfo->motorola_intel),
|
||||
SECTION_IFD0 TSRMLS_CC)) {
|
||||
ret = TRUE;
|
||||
@@ -3967,7 +3967,7 @@ PHP_FUNCTION(exif_read_data)
|
||||
sections_str = exif_get_sectionlist(ImageInfo.sections_found TSRMLS_CC);
|
||||
|
||||
#ifdef EXIF_DEBUG
|
||||
if (sections_str)
|
||||
if (sections_str)
|
||||
exif_error_docref(NULL EXIFERR_CC, &ImageInfo, E_NOTICE, "Sections found: %s", sections_str[0] ? sections_str : "None");
|
||||
#endif
|
||||
|
||||
|
||||
+41
-43
@@ -188,9 +188,9 @@ ftp_close(ftpbuf_t *ftp)
|
||||
SSL_shutdown(ftp->ssl_handle);
|
||||
SSL_free(ftp->ssl_handle);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
closesocket(ftp->fd);
|
||||
}
|
||||
}
|
||||
ftp_gc(ftp);
|
||||
efree(ftp);
|
||||
return NULL;
|
||||
@@ -262,7 +262,7 @@ ftp_login(ftpbuf_t *ftp, const char *user, const char *pass TSRMLS_DC)
|
||||
if (!ftp_getresp(ftp)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (ftp->resp != 234) {
|
||||
if (!ftp_putcmd(ftp, "AUTH", "SSL")) {
|
||||
return 0;
|
||||
@@ -270,7 +270,7 @@ ftp_login(ftpbuf_t *ftp, const char *user, const char *pass TSRMLS_DC)
|
||||
if (!ftp_getresp(ftp)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (ftp->resp != 334) {
|
||||
return 0;
|
||||
} else {
|
||||
@@ -278,7 +278,7 @@ ftp_login(ftpbuf_t *ftp, const char *user, const char *pass TSRMLS_DC)
|
||||
ftp->use_ssl_for_data = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ctx = SSL_CTX_new(SSLv23_client_method());
|
||||
if (ctx == NULL) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to create the SSL context");
|
||||
@@ -325,8 +325,8 @@ ftp_login(ftpbuf_t *ftp, const char *user, const char *pass TSRMLS_DC)
|
||||
if (!ftp_getresp(ftp)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ftp->use_ssl_for_data = (ftp->resp >= 200 && ftp->resp <=299);
|
||||
|
||||
ftp->use_ssl_for_data = (ftp->resp >= 200 && ftp->resp <=299);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -360,7 +360,7 @@ ftp_reinit(ftpbuf_t *ftp)
|
||||
{
|
||||
if (ftp == NULL) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ftp_gc(ftp);
|
||||
|
||||
@@ -395,7 +395,7 @@ ftp_syst(ftpbuf_t *ftp)
|
||||
if (!ftp_putcmd(ftp, "SYST", NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
if (!ftp_getresp(ftp) || ftp->resp != 215) {
|
||||
if (!ftp_getresp(ftp) || ftp->resp != 215) {
|
||||
return NULL;
|
||||
}
|
||||
syst = ftp->inbuf;
|
||||
@@ -431,14 +431,14 @@ ftp_pwd(ftpbuf_t *ftp)
|
||||
if (!ftp_putcmd(ftp, "PWD", NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
if (!ftp_getresp(ftp) || ftp->resp != 257) {
|
||||
if (!ftp_getresp(ftp) || ftp->resp != 257) {
|
||||
return NULL;
|
||||
}
|
||||
/* copy out the pwd from response */
|
||||
if ((pwd = strchr(ftp->inbuf, '"')) == NULL) {
|
||||
if ((pwd = strchr(ftp->inbuf, '"')) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if ((end = strrchr(++pwd, '"')) == NULL) {
|
||||
if ((end = strrchr(++pwd, '"')) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ftp->pwd = estrndup(pwd, end - pwd);
|
||||
@@ -608,7 +608,7 @@ ftp_chmod(ftpbuf_t *ftp, const int mode, const char *filename, const int filenam
|
||||
if (!ftp_getresp(ftp) || ftp->resp != 200) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -625,7 +625,7 @@ ftp_alloc(ftpbuf_t *ftp, const long size, char **response)
|
||||
}
|
||||
|
||||
snprintf(buffer, sizeof(buffer) - 1, "%ld", size);
|
||||
|
||||
|
||||
if (!ftp_putcmd(ftp, "ALLO", buffer)) {
|
||||
return 0;
|
||||
}
|
||||
@@ -642,7 +642,7 @@ ftp_alloc(ftpbuf_t *ftp, const long size, char **response)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -674,7 +674,7 @@ ftp_type(ftpbuf_t *ftp, ftptype_t type)
|
||||
if (ftp == NULL) {
|
||||
return 0;
|
||||
}
|
||||
if (type == ftp->type) {
|
||||
if (type == ftp->type) {
|
||||
return 1;
|
||||
}
|
||||
if (type == FTPTYPE_ASCII) {
|
||||
@@ -765,7 +765,7 @@ ftp_pasv(ftpbuf_t *ftp, int pasv)
|
||||
if (!ftp_putcmd(ftp, "PASV", NULL)) {
|
||||
return 0;
|
||||
}
|
||||
if (!ftp_getresp(ftp) || ftp->resp != 227) {
|
||||
if (!ftp_getresp(ftp) || ftp->resp != 227) {
|
||||
return 0;
|
||||
}
|
||||
/* parse out the IP and port */
|
||||
@@ -808,7 +808,7 @@ ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t type,
|
||||
if ((data = ftp_getdata(ftp TSRMLS_CC)) == NULL) {
|
||||
goto bail;
|
||||
}
|
||||
|
||||
|
||||
ftp->data = data;
|
||||
|
||||
if (resumepos > 0) {
|
||||
@@ -902,7 +902,7 @@ ftp_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type, l
|
||||
if ((data = ftp_getdata(ftp TSRMLS_CC)) == NULL) {
|
||||
goto bail;
|
||||
}
|
||||
ftp->data = data;
|
||||
ftp->data = data;
|
||||
|
||||
if (startpos > 0) {
|
||||
snprintf(arg, sizeof(arg), "%ld", startpos);
|
||||
@@ -1103,7 +1103,7 @@ ftp_putcmd(ftpbuf_t *ftp, const char *cmd, const char *args)
|
||||
|
||||
if (strpbrk(cmd, "\r\n")) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* build the output buffer */
|
||||
if (args && args[0]) {
|
||||
/* "cmd args\r\n\0" */
|
||||
@@ -1252,7 +1252,7 @@ my_send(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len)
|
||||
#if HAVE_OPENSSL_EXT
|
||||
if (ftp->use_ssl && ftp->fd == s && ftp->ssl_active) {
|
||||
sent = SSL_write(ftp->ssl_handle, buf, size);
|
||||
} else if (ftp->use_ssl && ftp->fd != s && ftp->use_ssl_for_data && ftp->data->ssl_active) {
|
||||
} else if (ftp->use_ssl && ftp->fd != s && ftp->use_ssl_for_data && ftp->data->ssl_active) {
|
||||
sent = SSL_write(ftp->data->ssl_handle, buf, size);
|
||||
} else {
|
||||
#endif
|
||||
@@ -1292,14 +1292,14 @@ my_recv(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len)
|
||||
#if HAVE_OPENSSL_EXT
|
||||
if (ftp->use_ssl && ftp->fd == s && ftp->ssl_active) {
|
||||
nr_bytes = SSL_read(ftp->ssl_handle, buf, len);
|
||||
} else if (ftp->use_ssl && ftp->fd != s && ftp->use_ssl_for_data && ftp->data->ssl_active) {
|
||||
} else if (ftp->use_ssl && ftp->fd != s && ftp->use_ssl_for_data && ftp->data->ssl_active) {
|
||||
nr_bytes = SSL_read(ftp->data->ssl_handle, buf, len);
|
||||
} else {
|
||||
#endif
|
||||
nr_bytes = recv(s, buf, len, 0);
|
||||
#if HAVE_OPENSSL_EXT
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return (nr_bytes);
|
||||
}
|
||||
/* }}} */
|
||||
@@ -1516,7 +1516,7 @@ data_accept(databuf_t *data, ftpbuf_t *ftp TSRMLS_DC)
|
||||
|
||||
data_accepted:
|
||||
#if HAVE_OPENSSL_EXT
|
||||
|
||||
|
||||
/* now enable ssl if we need to */
|
||||
if (ftp->use_ssl && ftp->use_ssl_for_data) {
|
||||
ctx = SSL_CTX_new(SSLv23_client_method());
|
||||
@@ -1536,23 +1536,23 @@ data_accepted:
|
||||
SSL_CTX_free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
SSL_set_fd(data->ssl_handle, data->fd);
|
||||
|
||||
if (ftp->old_ssl) {
|
||||
SSL_copy_session_id(data->ssl_handle, ftp->ssl_handle);
|
||||
}
|
||||
|
||||
|
||||
if (SSL_connect(data->ssl_handle) <= 0) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_accept: SSL/TLS handshake failed");
|
||||
SSL_shutdown(data->ssl_handle);
|
||||
SSL_free(data->ssl_handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
data->ssl_active = 1;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1567,14 +1567,14 @@ data_close(ftpbuf_t *ftp, databuf_t *data)
|
||||
{
|
||||
#if HAVE_OPENSSL_EXT
|
||||
SSL_CTX *ctx;
|
||||
#endif
|
||||
#endif
|
||||
if (data == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (data->listener != -1) {
|
||||
#if HAVE_OPENSSL_EXT
|
||||
if (data->ssl_active) {
|
||||
|
||||
|
||||
ctx = SSL_get_SSL_CTX(data->ssl_handle);
|
||||
SSL_CTX_free(ctx);
|
||||
|
||||
@@ -1582,9 +1582,9 @@ data_close(ftpbuf_t *ftp, databuf_t *data)
|
||||
SSL_free(data->ssl_handle);
|
||||
data->ssl_active = 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
closesocket(data->listener);
|
||||
}
|
||||
}
|
||||
if (data->fd != -1) {
|
||||
#if HAVE_OPENSSL_EXT
|
||||
if (data->ssl_active) {
|
||||
@@ -1595,9 +1595,9 @@ data_close(ftpbuf_t *ftp, databuf_t *data)
|
||||
SSL_free(data->ssl_handle);
|
||||
data->ssl_active = 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
closesocket(data->fd);
|
||||
}
|
||||
}
|
||||
if (ftp) {
|
||||
ftp->data = NULL;
|
||||
}
|
||||
@@ -1615,8 +1615,8 @@ ftp_genlist(ftpbuf_t *ftp, const char *cmd, const char *path TSRMLS_DC)
|
||||
databuf_t *data = NULL;
|
||||
char *ptr;
|
||||
int ch, lastch;
|
||||
int size, rcvd;
|
||||
int lines;
|
||||
size_t size, rcvd;
|
||||
size_t lines;
|
||||
char **ret = NULL;
|
||||
char **entry;
|
||||
char *text;
|
||||
@@ -1634,7 +1634,7 @@ ftp_genlist(ftpbuf_t *ftp, const char *cmd, const char *path TSRMLS_DC)
|
||||
if ((data = ftp_getdata(ftp TSRMLS_CC)) == NULL) {
|
||||
goto bail;
|
||||
}
|
||||
ftp->data = data;
|
||||
ftp->data = data;
|
||||
|
||||
if (!ftp_putcmd(ftp, cmd, path)) {
|
||||
goto bail;
|
||||
@@ -1658,7 +1658,7 @@ ftp_genlist(ftpbuf_t *ftp, const char *cmd, const char *path TSRMLS_DC)
|
||||
lines = 0;
|
||||
lastch = 0;
|
||||
while ((rcvd = my_recv(ftp, data->fd, data->buf, FTP_BUFSIZE))) {
|
||||
if (rcvd == -1) {
|
||||
if (rcvd == -1 || rcvd > ((size_t)(-1))-size) {
|
||||
goto bail;
|
||||
}
|
||||
|
||||
@@ -1668,8 +1668,6 @@ ftp_genlist(ftpbuf_t *ftp, const char *cmd, const char *path TSRMLS_DC)
|
||||
for (ptr = data->buf; rcvd; rcvd--, ptr++) {
|
||||
if (*ptr == '\n' && lastch == '\r') {
|
||||
lines++;
|
||||
} else {
|
||||
size++;
|
||||
}
|
||||
lastch = *ptr;
|
||||
}
|
||||
@@ -1863,7 +1861,7 @@ ftp_nb_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type
|
||||
if (!ftp_getresp(ftp) || (ftp->resp != 150 && ftp->resp != 125)) {
|
||||
goto bail;
|
||||
}
|
||||
if ((data = data_accept(data, ftp TSRMLS_CC)) == NULL) {
|
||||
if ((data = data_accept(data, ftp TSRMLS_CC)) == NULL) {
|
||||
goto bail;
|
||||
}
|
||||
ftp->data = data;
|
||||
@@ -1919,7 +1917,7 @@ ftp_nb_continue_write(ftpbuf_t *ftp TSRMLS_DC)
|
||||
goto bail;
|
||||
}
|
||||
ftp->data = data_close(ftp, ftp->data);
|
||||
|
||||
|
||||
if (!ftp_getresp(ftp) || (ftp->resp != 226 && ftp->resp != 250)) {
|
||||
goto bail;
|
||||
}
|
||||
|
||||
+8
-8
@@ -1790,7 +1790,7 @@ PHP_FUNCTION(imagefilledarc)
|
||||
long cx, cy, w, h, ST, E, col, style;
|
||||
gdImagePtr im;
|
||||
int e, st;
|
||||
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rllllllll", &IM, &cx, &cy, &w, &h, &ST, &E, &col, &style) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -2033,7 +2033,7 @@ PHP_FUNCTION(imagegrabwindow)
|
||||
if ( handle == 0 ) {
|
||||
goto clean;
|
||||
}
|
||||
pPrintWindow = (tPrintWindow) GetProcAddress(handle, "PrintWindow");
|
||||
pPrintWindow = (tPrintWindow) GetProcAddress(handle, "PrintWindow");
|
||||
|
||||
if ( pPrintWindow ) {
|
||||
pPrintWindow(window, memDC, (UINT) client_area);
|
||||
@@ -3984,7 +3984,7 @@ static void php_imagettftext_common(INTERNAL_FUNCTION_PARAMETERS, int mode, int
|
||||
if (zend_hash_get_current_data_ex(HASH_OF(EXT), (void **) &item, &pos) == FAILURE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (strcmp("linespacing", key) == 0) {
|
||||
convert_to_double_ex(item);
|
||||
strex.flags |= gdFTEX_LINESPACE;
|
||||
@@ -4006,7 +4006,7 @@ static void php_imagettftext_common(INTERNAL_FUNCTION_PARAMETERS, int mode, int
|
||||
#endif
|
||||
|
||||
PHP_GD_CHECK_OPEN_BASEDIR(fontname, "Invalid font filename");
|
||||
|
||||
|
||||
#ifdef USE_GD_IMGSTRTTF
|
||||
# if HAVE_GD_STRINGFTEX
|
||||
if (extended) {
|
||||
@@ -4071,7 +4071,7 @@ PHP_FUNCTION(imagepsloadfont)
|
||||
struct stat st;
|
||||
#endif
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &file, &file_len) == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &file, &file_len) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4411,11 +4411,11 @@ PHP_FUNCTION(imagepsbbox)
|
||||
if (argc != 3 && argc != 6) {
|
||||
ZEND_WRONG_PARAM_COUNT();
|
||||
}
|
||||
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "srl|lld", &str, &str_len, &fnt, &sz, &sp, &wd, &angle) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (argc == 6) {
|
||||
space = sp;
|
||||
add_width = wd;
|
||||
@@ -4600,7 +4600,7 @@ static void _php_image_convert(INTERNAL_FUNCTION_PARAMETERS, int image_type )
|
||||
#ifdef HAVE_GD_JPG
|
||||
long ignore_warning;
|
||||
#endif
|
||||
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pplll", &f_org, &f_org_len, &f_dest, &f_dest_len, &height, &width, &threshold) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -336,7 +336,7 @@ PHP_HASH_API void PHP_HAVAL128Final(unsigned char *digest, PHP_HAVAL_CTX * conte
|
||||
|
||||
/* Pad out to 118 mod 128.
|
||||
*/
|
||||
index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
|
||||
index = (unsigned int) ((context->count[0] >> 3) & 0x7f);
|
||||
padLen = (index < 118) ? (118 - index) : (246 - index);
|
||||
PHP_HAVALUpdate(context, PADDING, padLen);
|
||||
|
||||
@@ -390,7 +390,7 @@ PHP_HASH_API void PHP_HAVAL160Final(unsigned char *digest, PHP_HAVAL_CTX * conte
|
||||
|
||||
/* Pad out to 118 mod 128.
|
||||
*/
|
||||
index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
|
||||
index = (unsigned int) ((context->count[0] >> 3) & 0x7f);
|
||||
padLen = (index < 118) ? (118 - index) : (246 - index);
|
||||
PHP_HAVALUpdate(context, PADDING, padLen);
|
||||
|
||||
@@ -444,7 +444,7 @@ PHP_HASH_API void PHP_HAVAL192Final(unsigned char *digest, PHP_HAVAL_CTX * conte
|
||||
|
||||
/* Pad out to 118 mod 128.
|
||||
*/
|
||||
index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
|
||||
index = (unsigned int) ((context->count[0] >> 3) & 0x7f);
|
||||
padLen = (index < 118) ? (118 - index) : (246 - index);
|
||||
PHP_HAVALUpdate(context, PADDING, padLen);
|
||||
|
||||
@@ -484,7 +484,7 @@ PHP_HASH_API void PHP_HAVAL224Final(unsigned char *digest, PHP_HAVAL_CTX * conte
|
||||
|
||||
/* Pad out to 118 mod 128.
|
||||
*/
|
||||
index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
|
||||
index = (unsigned int) ((context->count[0] >> 3) & 0x7f);
|
||||
padLen = (index < 118) ? (118 - index) : (246 - index);
|
||||
PHP_HAVALUpdate(context, PADDING, padLen);
|
||||
|
||||
@@ -525,7 +525,7 @@ PHP_HASH_API void PHP_HAVAL256Final(unsigned char *digest, PHP_HAVAL_CTX * conte
|
||||
|
||||
/* Pad out to 118 mod 128.
|
||||
*/
|
||||
index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
|
||||
index = (unsigned int) ((context->count[0] >> 3) & 0x7f);
|
||||
padLen = (index < 118) ? (118 - index) : (246 - index);
|
||||
PHP_HAVALUpdate(context, PADDING, padLen);
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
--TEST--
|
||||
Bug #70312 HAVAL gives wrong hashes in specific cases
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("hash")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
var_dump(hash('haval128,5', '1234567890123456789012345678901234567890123456789012345678901234'));
|
||||
var_dump(hash('haval160,5', '1234567890123456789012345678901234567890123456789012345678901234'));
|
||||
var_dump(hash('haval192,5', '1234567890123456789012345678901234567890123456789012345678901234'));
|
||||
var_dump(hash('haval224,5', '1234567890123456789012345678901234567890123456789012345678901234'));
|
||||
var_dump(hash('haval256,5', '1234567890123456789012345678901234567890123456789012345678901234'));
|
||||
?>
|
||||
--EXPECTF--
|
||||
string(32) "f3f0d23819b87228b4b70ee350afaa9d"
|
||||
string(40) "aded6485e137f11d7292212ba3fa961714df0564"
|
||||
string(48) "e53da2b16269fe732e9a898a96707a9f28404d7333b02286"
|
||||
string(56) "c574fb307f0817b514b9bb2e7c4bfaffb7ad667aca3c8b523fefcf10"
|
||||
string(64) "fb73c19300b14d5cb393d929bf005e6c2d459a4c9c009e9813af1d2d3637ee8f"
|
||||
@@ -64,7 +64,7 @@ unlink($file);
|
||||
adler32: ff87222e
|
||||
crc32: 61664d33
|
||||
gost: d9e65f0c0c2ef944e4f8a01f4a46365c4f33a2853756878182a7f03e1490a4cd
|
||||
haval128,3: 8bb81269aca8b7f87829020d76a4e841
|
||||
haval128,3: c25962b13383c3ed9f13817c8f2ae7d6
|
||||
md2: 70f791c0d8fa9edd7d08e32fcba8c354
|
||||
md4: a9d034b16bb290c57a645afd6f14cd3b
|
||||
md5: 704bf818448f5bbb94061332d2c889aa
|
||||
|
||||
@@ -45,7 +45,7 @@ echo "sha256(raw): " . bin2hex(hash_hmac('sha256', $content, $key, TRUE)) . "\n"
|
||||
adler32: 12c803f7
|
||||
crc32: 96859101
|
||||
gost: a4a3c80bdf3f8665bf07376a34dc9c1b11af7c813f4928f62e39f0c0dc564dad
|
||||
haval128,3: 82cd0f4bd36729b5c80c33efa8c13ac5
|
||||
haval128,3: 4d1318607f0406bd1b7bd50907772672
|
||||
md2: 6d111dab563025e4cb5f4425c991fa12
|
||||
md4: 10cdbfe843000c623f8b8da0d5d20b0b
|
||||
md5: 2a632783e2812cf23de100d7d6a463ae
|
||||
|
||||
@@ -73,7 +73,7 @@ unlink($file);
|
||||
adler32: 0f8c02f9
|
||||
crc32: f2a60b9c
|
||||
gost: 94c39a40d5db852a8dc3d24e37eebf2d53e3d711457c59cd02b614f792a9d918
|
||||
haval128,3: e8fcff647f1a675acb429130fb94a17e
|
||||
haval128,3: f1cea637451097d790354a86de3f54a3
|
||||
md2: a685475e600314bb549ab4f33c3b27cb
|
||||
md4: cbc6bff781f48f57378d3effa27553e4
|
||||
md5: 8bddf39dd1c566c27acc7fa85ec36acf
|
||||
|
||||
+40
-25
@@ -378,7 +378,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, set_server_option)(MYSQLND_CONN_DATA * const c
|
||||
|
||||
int2store(buffer, (unsigned int) option);
|
||||
ret = conn->m->simple_command(conn, COM_SET_OPTION, buffer, sizeof(buffer), PROT_EOF_PACKET, FALSE, TRUE TSRMLS_CC);
|
||||
|
||||
|
||||
conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
|
||||
}
|
||||
DBG_RETURN(ret);
|
||||
@@ -446,26 +446,41 @@ mysqlnd_switch_to_ssl_if_needed(
|
||||
}
|
||||
|
||||
#ifdef MYSQLND_SSL_SUPPORTED
|
||||
if ((greet_packet->server_capabilities & CLIENT_SSL) && (mysql_flags & CLIENT_SSL)) {
|
||||
zend_bool verify = mysql_flags & CLIENT_SSL_VERIFY_SERVER_CERT? TRUE:FALSE;
|
||||
DBG_INF("Switching to SSL");
|
||||
if (!PACKET_WRITE(auth_packet, conn)) {
|
||||
CONN_SET_STATE(conn, CONN_QUIT_SENT);
|
||||
SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
|
||||
goto end;
|
||||
}
|
||||
if (mysql_flags & CLIENT_SSL) {
|
||||
zend_bool server_has_ssl = (greet_packet->server_capabilities & CLIENT_SSL)? TRUE:FALSE;
|
||||
if (server_has_ssl == FALSE) {
|
||||
goto close_conn;
|
||||
} else {
|
||||
zend_bool verify = mysql_flags & CLIENT_SSL_VERIFY_SERVER_CERT? TRUE:FALSE;
|
||||
DBG_INF("Switching to SSL");
|
||||
if (!PACKET_WRITE(auth_packet, conn)) {
|
||||
goto close_conn;
|
||||
}
|
||||
|
||||
conn->net->m.set_client_option(conn->net, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (const char *) &verify TSRMLS_CC);
|
||||
conn->net->m.set_client_option(conn->net, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (const char *) &verify TSRMLS_CC);
|
||||
|
||||
if (FAIL == conn->net->m.enable_ssl(conn->net TSRMLS_CC)) {
|
||||
goto end;
|
||||
if (FAIL == conn->net->m.enable_ssl(conn->net TSRMLS_CC)) {
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
auth_packet->client_flags &= ~CLIENT_SSL;
|
||||
if (!PACKET_WRITE(auth_packet, conn)) {
|
||||
goto close_conn;
|
||||
}
|
||||
#endif
|
||||
ret = PASS;
|
||||
end:
|
||||
PACKET_FREE(auth_packet);
|
||||
DBG_RETURN(ret);
|
||||
|
||||
close_conn:
|
||||
CONN_SET_STATE(conn, CONN_QUIT_SENT);
|
||||
conn->m->send_close(conn TSRMLS_CC);
|
||||
SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
|
||||
PACKET_FREE(auth_packet);
|
||||
DBG_RETURN(ret);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -587,7 +602,7 @@ mysqlnd_connect_run_authentication(
|
||||
if (plugin_data) {
|
||||
mnd_efree(plugin_data);
|
||||
}
|
||||
|
||||
|
||||
if (ret == PASS) {
|
||||
DBG_INF_FMT("saving requested_protocol=%s", requested_protocol);
|
||||
conn->m->set_client_option(conn, MYSQLND_OPT_AUTH_PROTOCOL, requested_protocol TSRMLS_CC);
|
||||
@@ -1438,7 +1453,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, sqlstate)(const MYSQLND_CONN_DATA * const conn
|
||||
|
||||
|
||||
/* {{{ mysqlnd_old_escape_string */
|
||||
PHPAPI ulong
|
||||
PHPAPI ulong
|
||||
mysqlnd_old_escape_string(char * newstr, const char * escapestr, size_t escapestr_len TSRMLS_DC)
|
||||
{
|
||||
DBG_ENTER("mysqlnd_old_escape_string");
|
||||
@@ -1599,7 +1614,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, statistic)(MYSQLND_CONN_DATA * conn, char **me
|
||||
|
||||
if (PASS == (ret = PACKET_READ(stats_header, conn))) {
|
||||
/* will be freed by Zend, thus don't use the mnd_ allocator */
|
||||
*message = estrndup(stats_header->message, stats_header->message_len);
|
||||
*message = estrndup(stats_header->message, stats_header->message_len);
|
||||
*message_len = stats_header->message_len;
|
||||
DBG_INF(*message);
|
||||
}
|
||||
@@ -1724,7 +1739,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, shutdown)(MYSQLND_CONN_DATA * const conn, uint
|
||||
|
||||
conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
|
||||
}
|
||||
DBG_RETURN(ret);
|
||||
DBG_RETURN(ret);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -2243,7 +2258,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, change_user)(MYSQLND_CONN_DATA * const conn,
|
||||
*/
|
||||
end:
|
||||
if (TRUE == local_tx_started) {
|
||||
conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
|
||||
conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
|
||||
}
|
||||
DBG_INF(ret == PASS? "PASS":"FAIL");
|
||||
DBG_RETURN(ret);
|
||||
@@ -2335,7 +2350,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, set_client_option)(MYSQLND_CONN_DATA * const c
|
||||
ret = FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
new_charset_name = mnd_pestrdup(value, conn->persistent);
|
||||
if (!new_charset_name) {
|
||||
goto oom;
|
||||
@@ -2401,11 +2416,11 @@ MYSQLND_METHOD(mysqlnd_conn_data, set_client_option)(MYSQLND_CONN_DATA * const c
|
||||
default:
|
||||
ret = FAIL;
|
||||
}
|
||||
conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
|
||||
conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
|
||||
DBG_RETURN(ret);
|
||||
oom:
|
||||
SET_OOM_ERROR(*conn->error_info);
|
||||
conn->m->local_tx_end(conn, this_func, FAIL TSRMLS_CC);
|
||||
conn->m->local_tx_end(conn, this_func, FAIL TSRMLS_CC);
|
||||
end:
|
||||
DBG_RETURN(FAIL);
|
||||
}
|
||||
@@ -2446,7 +2461,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, use_result)(MYSQLND_CONN_DATA * const conn TSR
|
||||
conn->current_result = NULL;
|
||||
} while (0);
|
||||
|
||||
conn->m->local_tx_end(conn, this_func, result == NULL? FAIL:PASS TSRMLS_CC);
|
||||
conn->m->local_tx_end(conn, this_func, result == NULL? FAIL:PASS TSRMLS_CC);
|
||||
}
|
||||
|
||||
DBG_RETURN(result);
|
||||
@@ -2486,7 +2501,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, store_result)(MYSQLND_CONN_DATA * const conn T
|
||||
conn->current_result = NULL;
|
||||
} while (0);
|
||||
|
||||
conn->m->local_tx_end(conn, this_func, result == NULL? FAIL:PASS TSRMLS_CC);
|
||||
conn->m->local_tx_end(conn, this_func, result == NULL? FAIL:PASS TSRMLS_CC);
|
||||
}
|
||||
DBG_RETURN(result);
|
||||
}
|
||||
@@ -2515,7 +2530,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, set_autocommit)(MYSQLND_CONN_DATA * conn, unsi
|
||||
|
||||
if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
|
||||
ret = conn->m->query(conn, (mode) ? "SET AUTOCOMMIT=1":"SET AUTOCOMMIT=0", sizeof("SET AUTOCOMMIT=1") - 1 TSRMLS_CC);
|
||||
conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
|
||||
conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
|
||||
}
|
||||
|
||||
DBG_RETURN(ret);
|
||||
@@ -2533,7 +2548,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, tx_commit)(MYSQLND_CONN_DATA * conn TSRMLS_DC)
|
||||
|
||||
if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
|
||||
ret = conn->m->query(conn, "COMMIT", sizeof("COMMIT") - 1 TSRMLS_CC);
|
||||
conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
|
||||
conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
|
||||
}
|
||||
|
||||
DBG_RETURN(ret);
|
||||
@@ -2551,7 +2566,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, tx_rollback)(MYSQLND_CONN_DATA * conn TSRMLS_D
|
||||
|
||||
if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
|
||||
ret = conn->m->query(conn, "ROLLBACK", sizeof("ROLLBACK") - 1 TSRMLS_CC);
|
||||
conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
|
||||
conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
|
||||
}
|
||||
|
||||
DBG_RETURN(ret);
|
||||
|
||||
@@ -5070,7 +5070,6 @@ PHP_FUNCTION(openssl_random_pseudo_bytes)
|
||||
long buffer_length;
|
||||
unsigned char *buffer = NULL;
|
||||
zval *zstrong_result_returned = NULL;
|
||||
int strong_result = 0;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|z", &buffer_length, &zstrong_result_returned) == FAILURE) {
|
||||
return;
|
||||
@@ -5088,7 +5087,6 @@ PHP_FUNCTION(openssl_random_pseudo_bytes)
|
||||
buffer = emalloc(buffer_length + 1);
|
||||
|
||||
#ifdef PHP_WIN32
|
||||
strong_result = 1;
|
||||
/* random/urandom equivalent on Windows */
|
||||
if (php_win32_get_random_bytes(buffer, (size_t) buffer_length) == FAILURE) {
|
||||
efree(buffer);
|
||||
@@ -5098,7 +5096,7 @@ PHP_FUNCTION(openssl_random_pseudo_bytes)
|
||||
RETURN_FALSE;
|
||||
}
|
||||
#else
|
||||
if ((strong_result = RAND_pseudo_bytes(buffer, buffer_length)) < 0) {
|
||||
if (RAND_bytes(buffer, buffer_length) <= 0) {
|
||||
efree(buffer);
|
||||
if (zstrong_result_returned) {
|
||||
ZVAL_BOOL(zstrong_result_returned, 0);
|
||||
@@ -5111,7 +5109,7 @@ PHP_FUNCTION(openssl_random_pseudo_bytes)
|
||||
RETVAL_STRINGL((char *)buffer, buffer_length, 0);
|
||||
|
||||
if (zstrong_result_returned) {
|
||||
ZVAL_BOOL(zstrong_result_returned, strong_result);
|
||||
ZVAL_BOOL(zstrong_result_returned, 1);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
+37
-37
@@ -198,7 +198,7 @@ ZEND_GET_MODULE(pcntl)
|
||||
|
||||
static void pcntl_signal_handler(int);
|
||||
static void pcntl_signal_dispatch();
|
||||
|
||||
|
||||
void php_register_signal_constants(INIT_FUNC_ARGS)
|
||||
{
|
||||
|
||||
@@ -234,7 +234,7 @@ void php_register_signal_constants(INIT_FUNC_ARGS)
|
||||
REGISTER_LONG_CONSTANT("SIGTERM", (long) SIGTERM, CONST_CS | CONST_PERSISTENT);
|
||||
#ifdef SIGSTKFLT
|
||||
REGISTER_LONG_CONSTANT("SIGSTKFLT",(long) SIGSTKFLT, CONST_CS | CONST_PERSISTENT);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef SIGCLD
|
||||
REGISTER_LONG_CONSTANT("SIGCLD", (long) SIGCLD, CONST_CS | CONST_PERSISTENT);
|
||||
#endif
|
||||
@@ -484,7 +484,7 @@ static void php_pcntl_register_errno_constants(INIT_FUNC_ARGS)
|
||||
}
|
||||
|
||||
static PHP_GINIT_FUNCTION(pcntl)
|
||||
{
|
||||
{
|
||||
memset(pcntl_globals, 0, sizeof(*pcntl_globals));
|
||||
}
|
||||
|
||||
@@ -547,7 +547,7 @@ PHP_FUNCTION(pcntl_fork)
|
||||
PCNTL_G(last_error) = errno;
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d", errno);
|
||||
}
|
||||
|
||||
|
||||
RETURN_LONG((long) id);
|
||||
}
|
||||
/* }}} */
|
||||
@@ -560,7 +560,7 @@ PHP_FUNCTION(pcntl_alarm)
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &seconds) == FAILURE)
|
||||
return;
|
||||
|
||||
|
||||
RETURN_LONG ((long) alarm(seconds));
|
||||
}
|
||||
/* }}} */
|
||||
@@ -576,7 +576,7 @@ PHP_FUNCTION(pcntl_waitpid)
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz|l", &pid, &z_status, &options) == FAILURE)
|
||||
return;
|
||||
|
||||
|
||||
convert_to_long_ex(&z_status);
|
||||
|
||||
status = Z_LVAL_P(z_status);
|
||||
@@ -604,7 +604,7 @@ PHP_FUNCTION(pcntl_wait)
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", &z_status, &options) == FAILURE)
|
||||
return;
|
||||
|
||||
|
||||
convert_to_long_ex(&z_status);
|
||||
|
||||
status = Z_LVAL_P(z_status);
|
||||
@@ -628,7 +628,7 @@ PHP_FUNCTION(pcntl_wait)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto bool pcntl_wifexited(int status)
|
||||
/* {{{ proto bool pcntl_wifexited(int status)
|
||||
Returns true if the child status code represents a successful exit */
|
||||
PHP_FUNCTION(pcntl_wifexited)
|
||||
{
|
||||
@@ -646,7 +646,7 @@ PHP_FUNCTION(pcntl_wifexited)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto bool pcntl_wifstopped(int status)
|
||||
/* {{{ proto bool pcntl_wifstopped(int status)
|
||||
Returns true if the child status code represents a stopped process (WUNTRACED must have been used with waitpid) */
|
||||
PHP_FUNCTION(pcntl_wifstopped)
|
||||
{
|
||||
@@ -664,7 +664,7 @@ PHP_FUNCTION(pcntl_wifstopped)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto bool pcntl_wifsignaled(int status)
|
||||
/* {{{ proto bool pcntl_wifsignaled(int status)
|
||||
Returns true if the child status code represents a process that was terminated due to a signal */
|
||||
PHP_FUNCTION(pcntl_wifsignaled)
|
||||
{
|
||||
@@ -682,7 +682,7 @@ PHP_FUNCTION(pcntl_wifsignaled)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int pcntl_wexitstatus(int status)
|
||||
/* {{{ proto int pcntl_wexitstatus(int status)
|
||||
Returns the status code of a child's exit */
|
||||
PHP_FUNCTION(pcntl_wexitstatus)
|
||||
{
|
||||
@@ -700,7 +700,7 @@ PHP_FUNCTION(pcntl_wexitstatus)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int pcntl_wtermsig(int status)
|
||||
/* {{{ proto int pcntl_wtermsig(int status)
|
||||
Returns the number of the signal that terminated the process who's status code is passed */
|
||||
PHP_FUNCTION(pcntl_wtermsig)
|
||||
{
|
||||
@@ -718,7 +718,7 @@ PHP_FUNCTION(pcntl_wtermsig)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int pcntl_wstopsig(int status)
|
||||
/* {{{ proto int pcntl_wstopsig(int status)
|
||||
Returns the number of the signal that caused the process to stop who's status code is passed */
|
||||
PHP_FUNCTION(pcntl_wstopsig)
|
||||
{
|
||||
@@ -754,19 +754,19 @@ PHP_FUNCTION(pcntl_exec)
|
||||
char *path;
|
||||
int path_len;
|
||||
ulong key_num;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|aa", &path, &path_len, &args, &envs) == FAILURE) {
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|aa", &path, &path_len, &args, &envs) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (ZEND_NUM_ARGS() > 1) {
|
||||
/* Build argument list */
|
||||
args_hash = HASH_OF(args);
|
||||
argc = zend_hash_num_elements(args_hash);
|
||||
|
||||
|
||||
argv = safe_emalloc((argc + 2), sizeof(char *), 0);
|
||||
*argv = path;
|
||||
for ( zend_hash_internal_pointer_reset(args_hash), current_arg = argv+1;
|
||||
for ( zend_hash_internal_pointer_reset(args_hash), current_arg = argv+1;
|
||||
(argi < argc && (zend_hash_get_current_data(args_hash, (void **) &element) == SUCCESS));
|
||||
(argi++, current_arg++, zend_hash_move_forward(args_hash)) ) {
|
||||
|
||||
@@ -784,9 +784,9 @@ PHP_FUNCTION(pcntl_exec)
|
||||
/* Build environment pair list */
|
||||
envs_hash = HASH_OF(envs);
|
||||
envc = zend_hash_num_elements(envs_hash);
|
||||
|
||||
|
||||
envp = safe_emalloc((envc + 1), sizeof(char *), 0);
|
||||
for ( zend_hash_internal_pointer_reset(envs_hash), pair = envp;
|
||||
for ( zend_hash_internal_pointer_reset(envs_hash), pair = envp;
|
||||
(envi < envc && (zend_hash_get_current_data(envs_hash, (void **) &element) == SUCCESS));
|
||||
(envi++, pair++, zend_hash_move_forward(envs_hash)) ) {
|
||||
switch (return_val = zend_hash_get_current_key_ex(envs_hash, &key, &key_length, &key_num, 0, NULL)) {
|
||||
@@ -802,13 +802,13 @@ PHP_FUNCTION(pcntl_exec)
|
||||
|
||||
convert_to_string_ex(element);
|
||||
|
||||
/* Length of element + equal sign + length of key + null */
|
||||
/* Length of element + equal sign + length of key + null */
|
||||
pair_length = Z_STRLEN_PP(element) + key_length + 2;
|
||||
*pair = emalloc(pair_length);
|
||||
strlcpy(*pair, key, key_length);
|
||||
strlcpy(*pair, key, key_length);
|
||||
strlcat(*pair, "=", pair_length);
|
||||
strlcat(*pair, Z_STRVAL_PP(element), pair_length);
|
||||
|
||||
|
||||
/* Cleanup */
|
||||
if (return_val == HASH_KEY_IS_LONG) efree(key);
|
||||
}
|
||||
@@ -818,7 +818,7 @@ PHP_FUNCTION(pcntl_exec)
|
||||
PCNTL_G(last_error) = errno;
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error has occurred: (errno %d) %s", errno, strerror(errno));
|
||||
}
|
||||
|
||||
|
||||
/* Cleanup */
|
||||
for (pair = envp; *pair != NULL; pair++) efree(*pair);
|
||||
efree(envp);
|
||||
@@ -831,7 +831,7 @@ PHP_FUNCTION(pcntl_exec)
|
||||
}
|
||||
|
||||
efree(argv);
|
||||
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -880,7 +880,7 @@ PHP_FUNCTION(pcntl_signal)
|
||||
}
|
||||
RETURN_TRUE;
|
||||
}
|
||||
|
||||
|
||||
if (!zend_is_callable(handle, 0, &func_name TSRMLS_CC)) {
|
||||
PCNTL_G(last_error) = EINVAL;
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s is not a callable function name error", func_name);
|
||||
@@ -888,11 +888,11 @@ PHP_FUNCTION(pcntl_signal)
|
||||
RETURN_FALSE;
|
||||
}
|
||||
efree(func_name);
|
||||
|
||||
|
||||
/* Add the function name to our signal table */
|
||||
zend_hash_index_update(&PCNTL_G(php_signal_table), signo, (void **) &handle, sizeof(zval *), (void **) &dest_handle);
|
||||
if (dest_handle) zval_add_ref(dest_handle);
|
||||
|
||||
|
||||
if (php_signal4(signo, pcntl_signal_handler, (int) restart_syscalls, 1) == SIG_ERR) {
|
||||
PCNTL_G(last_error) = errno;
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error assigning signal");
|
||||
@@ -1029,7 +1029,7 @@ static void pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAMETERS, int timedwait) /* {{
|
||||
}
|
||||
|
||||
/*
|
||||
* sigtimedwait and sigwaitinfo can return 0 on success on some
|
||||
* sigtimedwait and sigwaitinfo can return 0 on success on some
|
||||
* platforms, e.g. NetBSD
|
||||
*/
|
||||
if (!signo && siginfo.si_signo) {
|
||||
@@ -1077,7 +1077,7 @@ static void pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAMETERS, int timedwait) /* {{
|
||||
EMPTY_SWITCH_DEFAULT_CASE();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RETURN_LONG(signo);
|
||||
}
|
||||
/* }}} */
|
||||
@@ -1107,12 +1107,12 @@ PHP_FUNCTION(pcntl_getpriority)
|
||||
long who = PRIO_PROCESS;
|
||||
long pid = getpid();
|
||||
int pri;
|
||||
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ll", &pid, &who) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
/* needs to be cleared, since any returned value is valid */
|
||||
/* needs to be cleared, since any returned value is valid */
|
||||
errno = 0;
|
||||
|
||||
pri = getpriority(who, pid);
|
||||
@@ -1172,7 +1172,7 @@ PHP_FUNCTION(pcntl_setpriority)
|
||||
}
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
|
||||
RETURN_TRUE;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -1205,7 +1205,7 @@ static void pcntl_signal_handler(int signo)
|
||||
{
|
||||
struct php_pcntl_pending_signal *psig;
|
||||
TSRMLS_FETCH();
|
||||
|
||||
|
||||
psig = PCNTL_G(spares);
|
||||
if (!psig) {
|
||||
/* oops, too many signals for us to track, so we'll forget about this one */
|
||||
@@ -1233,7 +1233,7 @@ void pcntl_signal_dispatch()
|
||||
sigset_t mask;
|
||||
sigset_t old_mask;
|
||||
TSRMLS_FETCH();
|
||||
|
||||
|
||||
/* Mask all signals */
|
||||
sigfillset(&mask);
|
||||
sigprocmask(SIG_BLOCK, &mask, &old_mask);
|
||||
@@ -1249,7 +1249,7 @@ void pcntl_signal_dispatch()
|
||||
|
||||
queue = PCNTL_G(head);
|
||||
PCNTL_G(head) = NULL; /* simple stores are atomic */
|
||||
|
||||
|
||||
/* Allocate */
|
||||
|
||||
while (queue) {
|
||||
@@ -1274,7 +1274,7 @@ void pcntl_signal_dispatch()
|
||||
|
||||
/* Re-enable queue */
|
||||
PCNTL_G(processing_signal_queue) = 0;
|
||||
|
||||
|
||||
/* return signal mask to previous state */
|
||||
sigprocmask(SIG_SETMASK, &old_mask, NULL);
|
||||
}
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
|
||||
EXTENSION("pcre", "php_pcre.c", false /* never shared */,
|
||||
"-Iext/pcre/pcrelib");
|
||||
ADD_SOURCES("ext/pcre/pcrelib", "pcre_chartables.c pcre_ucd.c pcre_compile.c pcre_config.c pcre_exec.c pcre_fullinfo.c pcre_get.c pcre_globals.c pcre_maketables.c pcre_newline.c pcre_ord2utf8.c pcre_refcount.c pcre_study.c pcre_tables.c pcre_valid_utf8.c pcre_version.c pcre_xclass.c", "pcre");
|
||||
ADD_SOURCES("ext/pcre/pcrelib", "pcre_chartables.c pcre_ucd.c pcre_compile.c pcre_config.c pcre_exec.c pcre_fullinfo.c pcre_get.c pcre_globals.c pcre_maketables.c pcre_newline.c pcre_ord2utf8.c pcre_refcount.c pcre_study.c pcre_tables.c pcre_valid_utf8.c pcre_version.c pcre_xclass.c pcre_jit_compile.c", "pcre");
|
||||
ADD_DEF_FILE("ext\\pcre\\php_pcre.def");
|
||||
|
||||
AC_DEFINE('HAVE_BUNDLED_PCRE', 1, 'Using bundled PCRE library');
|
||||
|
||||
+2
-1
@@ -58,7 +58,8 @@ PHP_ARG_WITH(pcre-regex,,
|
||||
pcrelib/pcre_maketables.c pcrelib/pcre_newline.c \
|
||||
pcrelib/pcre_ord2utf8.c pcrelib/pcre_refcount.c pcrelib/pcre_study.c \
|
||||
pcrelib/pcre_tables.c pcrelib/pcre_valid_utf8.c \
|
||||
pcrelib/pcre_version.c pcrelib/pcre_xclass.c"
|
||||
pcrelib/pcre_version.c pcrelib/pcre_xclass.c \
|
||||
pcrelib/pcre_jit_compile.c"
|
||||
PHP_PCRE_CFLAGS="-DHAVE_CONFIG_H -I@ext_srcdir@/pcrelib"
|
||||
PHP_NEW_EXTENSION(pcre, $pcrelib_sources php_pcre.c, no,,$PHP_PCRE_CFLAGS)
|
||||
PHP_ADD_BUILD_DIR($ext_builddir/pcrelib)
|
||||
|
||||
@@ -8,7 +8,7 @@ Email domain: cam.ac.uk
|
||||
University of Cambridge Computing Service,
|
||||
Cambridge, England.
|
||||
|
||||
Copyright (c) 1997-2014 University of Cambridge
|
||||
Copyright (c) 1997-2015 University of Cambridge
|
||||
All rights reserved
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ Written by: Zoltan Herczeg
|
||||
Email local part: hzmester
|
||||
Emain domain: freemail.hu
|
||||
|
||||
Copyright(c) 2010-2014 Zoltan Herczeg
|
||||
Copyright(c) 2010-2015 Zoltan Herczeg
|
||||
All rights reserved.
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ Written by: Zoltan Herczeg
|
||||
Email local part: hzmester
|
||||
Emain domain: freemail.hu
|
||||
|
||||
Copyright(c) 2009-2014 Zoltan Herczeg
|
||||
Copyright(c) 2009-2015 Zoltan Herczeg
|
||||
All rights reserved.
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,173 @@
|
||||
ChangeLog for PCRE
|
||||
------------------
|
||||
|
||||
Version 8.37 28-April-2015
|
||||
--------------------------
|
||||
|
||||
1. When an (*ACCEPT) is triggered inside capturing parentheses, it arranges
|
||||
for those parentheses to be closed with whatever has been captured so far.
|
||||
However, it was failing to mark any other groups between the hightest
|
||||
capture so far and the currrent group as "unset". Thus, the ovector for
|
||||
those groups contained whatever was previously there. An example is the
|
||||
pattern /(x)|((*ACCEPT))/ when matched against "abcd".
|
||||
|
||||
2. If an assertion condition was quantified with a minimum of zero (an odd
|
||||
thing to do, but it happened), SIGSEGV or other misbehaviour could occur.
|
||||
|
||||
3. If a pattern in pcretest input had the P (POSIX) modifier followed by an
|
||||
unrecognized modifier, a crash could occur.
|
||||
|
||||
4. An attempt to do global matching in pcretest with a zero-length ovector
|
||||
caused a crash.
|
||||
|
||||
5. Fixed a memory leak during matching that could occur for a subpattern
|
||||
subroutine call (recursive or otherwise) if the number of captured groups
|
||||
that had to be saved was greater than ten.
|
||||
|
||||
6. Catch a bad opcode during auto-possessification after compiling a bad UTF
|
||||
string with NO_UTF_CHECK. This is a tidyup, not a bug fix, as passing bad
|
||||
UTF with NO_UTF_CHECK is documented as having an undefined outcome.
|
||||
|
||||
7. A UTF pattern containing a "not" match of a non-ASCII character and a
|
||||
subroutine reference could loop at compile time. Example: /[^\xff]((?1))/.
|
||||
|
||||
8. When a pattern is compiled, it remembers the highest back reference so that
|
||||
when matching, if the ovector is too small, extra memory can be obtained to
|
||||
use instead. A conditional subpattern whose condition is a check on a
|
||||
capture having happened, such as, for example in the pattern
|
||||
/^(?:(a)|b)(?(1)A|B)/, is another kind of back reference, but it was not
|
||||
setting the highest backreference number. This mattered only if pcre_exec()
|
||||
was called with an ovector that was too small to hold the capture, and there
|
||||
was no other kind of back reference (a situation which is probably quite
|
||||
rare). The effect of the bug was that the condition was always treated as
|
||||
FALSE when the capture could not be consulted, leading to a incorrect
|
||||
behaviour by pcre_exec(). This bug has been fixed.
|
||||
|
||||
9. A reference to a duplicated named group (either a back reference or a test
|
||||
for being set in a conditional) that occurred in a part of the pattern where
|
||||
PCRE_DUPNAMES was not set caused the amount of memory needed for the pattern
|
||||
to be incorrectly calculated, leading to overwriting.
|
||||
|
||||
10. A mutually recursive set of back references such as (\2)(\1) caused a
|
||||
segfault at study time (while trying to find the minimum matching length).
|
||||
The infinite loop is now broken (with the minimum length unset, that is,
|
||||
zero).
|
||||
|
||||
11. If an assertion that was used as a condition was quantified with a minimum
|
||||
of zero, matching went wrong. In particular, if the whole group had
|
||||
unlimited repetition and could match an empty string, a segfault was
|
||||
likely. The pattern (?(?=0)?)+ is an example that caused this. Perl allows
|
||||
assertions to be quantified, but not if they are being used as conditions,
|
||||
so the above pattern is faulted by Perl. PCRE has now been changed so that
|
||||
it also rejects such patterns.
|
||||
|
||||
12. A possessive capturing group such as (a)*+ with a minimum repeat of zero
|
||||
failed to allow the zero-repeat case if pcre2_exec() was called with an
|
||||
ovector too small to capture the group.
|
||||
|
||||
13. Fixed two bugs in pcretest that were discovered by fuzzing and reported by
|
||||
Red Hat Product Security:
|
||||
|
||||
(a) A crash if /K and /F were both set with the option to save the compiled
|
||||
pattern.
|
||||
|
||||
(b) Another crash if the option to print captured substrings in a callout
|
||||
was combined with setting a null ovector, for example \O\C+ as a subject
|
||||
string.
|
||||
|
||||
14. A pattern such as "((?2){0,1999}())?", which has a group containing a
|
||||
forward reference repeated a large (but limited) number of times within a
|
||||
repeated outer group that has a zero minimum quantifier, caused incorrect
|
||||
code to be compiled, leading to the error "internal error:
|
||||
previously-checked referenced subpattern not found" when an incorrect
|
||||
memory address was read. This bug was reported as "heap overflow",
|
||||
discovered by Kai Lu of Fortinet's FortiGuard Labs and given the CVE number
|
||||
CVE-2015-2325.
|
||||
|
||||
23. A pattern such as "((?+1)(\1))/" containing a forward reference subroutine
|
||||
call within a group that also contained a recursive back reference caused
|
||||
incorrect code to be compiled. This bug was reported as "heap overflow",
|
||||
discovered by Kai Lu of Fortinet's FortiGuard Labs, and given the CVE
|
||||
number CVE-2015-2326.
|
||||
|
||||
24. Computing the size of the JIT read-only data in advance has been a source
|
||||
of various issues, and new ones are still appear unfortunately. To fix
|
||||
existing and future issues, size computation is eliminated from the code,
|
||||
and replaced by on-demand memory allocation.
|
||||
|
||||
25. A pattern such as /(?i)[A-`]/, where characters in the other case are
|
||||
adjacent to the end of the range, and the range contained characters with
|
||||
more than one other case, caused incorrect behaviour when compiled in UTF
|
||||
mode. In that example, the range a-j was left out of the class.
|
||||
|
||||
26. Fix JIT compilation of conditional blocks, which assertion
|
||||
is converted to (*FAIL). E.g: /(?(?!))/.
|
||||
|
||||
27. The pattern /(?(?!)^)/ caused references to random memory. This bug was
|
||||
discovered by the LLVM fuzzer.
|
||||
|
||||
28. The assertion (?!) is optimized to (*FAIL). This was not handled correctly
|
||||
when this assertion was used as a condition, for example (?(?!)a|b). In
|
||||
pcre2_match() it worked by luck; in pcre2_dfa_match() it gave an incorrect
|
||||
error about an unsupported item.
|
||||
|
||||
29. For some types of pattern, for example /Z*(|d*){216}/, the auto-
|
||||
possessification code could take exponential time to complete. A recursion
|
||||
depth limit of 1000 has been imposed to limit the resources used by this
|
||||
optimization.
|
||||
|
||||
30. A pattern such as /(*UTF)[\S\V\H]/, which contains a negated special class
|
||||
such as \S in non-UCP mode, explicit wide characters (> 255) can be ignored
|
||||
because \S ensures they are all in the class. The code for doing this was
|
||||
interacting badly with the code for computing the amount of space needed to
|
||||
compile the pattern, leading to a buffer overflow. This bug was discovered
|
||||
by the LLVM fuzzer.
|
||||
|
||||
31. A pattern such as /((?2)+)((?1))/ which has mutual recursion nested inside
|
||||
other kinds of group caused stack overflow at compile time. This bug was
|
||||
discovered by the LLVM fuzzer.
|
||||
|
||||
32. A pattern such as /(?1)(?#?'){8}(a)/ which had a parenthesized comment
|
||||
between a subroutine call and its quantifier was incorrectly compiled,
|
||||
leading to buffer overflow or other errors. This bug was discovered by the
|
||||
LLVM fuzzer.
|
||||
|
||||
33. The illegal pattern /(?(?<E>.*!.*)?)/ was not being diagnosed as missing an
|
||||
assertion after (?(. The code was failing to check the character after
|
||||
(?(?< for the ! or = that would indicate a lookbehind assertion. This bug
|
||||
was discovered by the LLVM fuzzer.
|
||||
|
||||
34. A pattern such as /X((?2)()*+){2}+/ which has a possessive quantifier with
|
||||
a fixed maximum following a group that contains a subroutine reference was
|
||||
incorrectly compiled and could trigger buffer overflow. This bug was
|
||||
discovered by the LLVM fuzzer.
|
||||
|
||||
35. A mutual recursion within a lookbehind assertion such as (?<=((?2))((?1)))
|
||||
caused a stack overflow instead of the diagnosis of a non-fixed length
|
||||
lookbehind assertion. This bug was discovered by the LLVM fuzzer.
|
||||
|
||||
36. The use of \K in a positive lookbehind assertion in a non-anchored pattern
|
||||
(e.g. /(?<=\Ka)/) could make pcregrep loop.
|
||||
|
||||
37. There was a similar problem to 36 in pcretest for global matches.
|
||||
|
||||
38. If a greedy quantified \X was preceded by \C in UTF mode (e.g. \C\X*),
|
||||
and a subsequent item in the pattern caused a non-match, backtracking over
|
||||
the repeated \X did not stop, but carried on past the start of the subject,
|
||||
causing reference to random memory and/or a segfault. There were also some
|
||||
other cases where backtracking after \C could crash. This set of bugs was
|
||||
discovered by the LLVM fuzzer.
|
||||
|
||||
39. The function for finding the minimum length of a matching string could take
|
||||
a very long time if mutual recursion was present many times in a pattern,
|
||||
for example, /((?2){73}(?2))((?1))/. A better mutual recursion detection
|
||||
method has been implemented. This infelicity was discovered by the LLVM
|
||||
fuzzer.
|
||||
|
||||
40. Static linking against the PCRE library using the pkg-config module was
|
||||
failing on missing pthread symbols.
|
||||
|
||||
|
||||
Version 8.36 26-September-2014
|
||||
------------------------------
|
||||
|
||||
|
||||
@@ -6,7 +6,8 @@ and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Release 8 of PCRE is distributed under the terms of the "BSD" licence, as
|
||||
specified below. The documentation for PCRE, supplied in the "doc"
|
||||
directory, is distributed under the same terms as the software itself.
|
||||
directory, is distributed under the same terms as the software itself. The data
|
||||
in the testdata directory is not copyrighted and is in the public domain.
|
||||
|
||||
The basic library functions are written in C and are freestanding. Also
|
||||
included in the distribution is a set of C++ wrapper functions, and a
|
||||
@@ -24,7 +25,7 @@ Email domain: cam.ac.uk
|
||||
University of Cambridge Computing Service,
|
||||
Cambridge, England.
|
||||
|
||||
Copyright (c) 1997-2014 University of Cambridge
|
||||
Copyright (c) 1997-2015 University of Cambridge
|
||||
All rights reserved.
|
||||
|
||||
|
||||
@@ -35,7 +36,7 @@ Written by: Zoltan Herczeg
|
||||
Email local part: hzmester
|
||||
Emain domain: freemail.hu
|
||||
|
||||
Copyright(c) 2010-2014 Zoltan Herczeg
|
||||
Copyright(c) 2010-2015 Zoltan Herczeg
|
||||
All rights reserved.
|
||||
|
||||
|
||||
@@ -46,7 +47,7 @@ Written by: Zoltan Herczeg
|
||||
Email local part: hzmester
|
||||
Emain domain: freemail.hu
|
||||
|
||||
Copyright(c) 2009-2014 Zoltan Herczeg
|
||||
Copyright(c) 2009-2015 Zoltan Herczeg
|
||||
All rights reserved.
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
News about PCRE releases
|
||||
------------------------
|
||||
|
||||
Release 8.37 28-April-2015
|
||||
--------------------------
|
||||
|
||||
This is bug-fix release. Note that this library (now called PCRE1) is now being
|
||||
maintained for bug fixes only. New projects are advised to use the new PCRE2
|
||||
libraries.
|
||||
|
||||
|
||||
Release 8.36 26-September-2014
|
||||
------------------------------
|
||||
|
||||
|
||||
+11
-2
@@ -1,7 +1,16 @@
|
||||
README file for PCRE (Perl-compatible regular expression library)
|
||||
-----------------------------------------------------------------
|
||||
|
||||
The latest release of PCRE is always available in three alternative formats
|
||||
NOTE: This set of files relates to PCRE releases that use the original API,
|
||||
with library names libpcre, libpcre16, and libpcre32. January 2015 saw the
|
||||
first release of a new API, known as PCRE2, with release numbers starting at
|
||||
10.00 and library names libpcre2-8, libpcre2-16, and libpcre2-32. The old
|
||||
libraries (now called PCRE1) are still being maintained for bug fixes, but
|
||||
there will be no new development. New projects are advised to use the new PCRE2
|
||||
libraries.
|
||||
|
||||
|
||||
The latest release of PCRE1 is always available in three alternative formats
|
||||
from:
|
||||
|
||||
ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-xxx.tar.gz
|
||||
@@ -990,4 +999,4 @@ pcre_xxx, one with the name pcre16_xx, and a third with the name pcre32_xxx.
|
||||
Philip Hazel
|
||||
Email local part: ph10
|
||||
Email domain: cam.ac.uk
|
||||
Last updated: 24 October 2014
|
||||
Last updated: 10 February 2015
|
||||
@@ -312,7 +312,7 @@ them both to 0; an emulation function will be used. */
|
||||
#define PACKAGE_NAME "PCRE"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "PCRE 8.36"
|
||||
#define PACKAGE_STRING "PCRE 8.37"
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME "pcre"
|
||||
@@ -321,7 +321,7 @@ them both to 0; an emulation function will be used. */
|
||||
#define PACKAGE_URL ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "8.36"
|
||||
#define PACKAGE_VERSION "8.37"
|
||||
|
||||
/* to make a symbol visible */
|
||||
/* #undef PCRECPP_EXP_DECL */
|
||||
@@ -395,7 +395,7 @@ them both to 0; an emulation function will be used. */
|
||||
#undef SUPPORT_GCOV
|
||||
|
||||
/* Define to any value to enable support for Just-In-Time compiling. */
|
||||
#undef SUPPORT_JIT
|
||||
#define SUPPORT_JIT
|
||||
|
||||
/* Define to any value to allow pcregrep to be linked with libbz2, so that it
|
||||
is able to handle .bz2 files. */
|
||||
@@ -437,7 +437,7 @@ them both to 0; an emulation function will be used. */
|
||||
|
||||
/* Version number of package */
|
||||
#ifndef VERSION
|
||||
#define VERSION "8.36"
|
||||
#define VERSION "8.37"
|
||||
#endif
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
|
||||
@@ -42,9 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
/* The current PCRE version information. */
|
||||
|
||||
#define PCRE_MAJOR 8
|
||||
#define PCRE_MINOR 36
|
||||
#define PCRE_MINOR 37
|
||||
#define PCRE_PRERELEASE
|
||||
#define PCRE_DATE 2014-09-26
|
||||
#define PCRE_DATE 2015-04-28
|
||||
|
||||
/* When an application links to a PCRE DLL in Windows, the symbols that are
|
||||
imported have to be identified as such. When building PCRE, the appropriate
|
||||
|
||||
+165
-84
@@ -1704,6 +1704,7 @@ Arguments:
|
||||
utf TRUE in UTF-8 / UTF-16 / UTF-32 mode
|
||||
atend TRUE if called when the pattern is complete
|
||||
cd the "compile data" structure
|
||||
recurses chain of recurse_check to catch mutual recursion
|
||||
|
||||
Returns: the fixed length,
|
||||
or -1 if there is no fixed length,
|
||||
@@ -1713,10 +1714,11 @@ Returns: the fixed length,
|
||||
*/
|
||||
|
||||
static int
|
||||
find_fixedlength(pcre_uchar *code, BOOL utf, BOOL atend, compile_data *cd)
|
||||
find_fixedlength(pcre_uchar *code, BOOL utf, BOOL atend, compile_data *cd,
|
||||
recurse_check *recurses)
|
||||
{
|
||||
int length = -1;
|
||||
|
||||
recurse_check this_recurse;
|
||||
register int branchlength = 0;
|
||||
register pcre_uchar *cc = code + 1 + LINK_SIZE;
|
||||
|
||||
@@ -1741,7 +1743,8 @@ for (;;)
|
||||
case OP_ONCE:
|
||||
case OP_ONCE_NC:
|
||||
case OP_COND:
|
||||
d = find_fixedlength(cc + ((op == OP_CBRA)? IMM2_SIZE : 0), utf, atend, cd);
|
||||
d = find_fixedlength(cc + ((op == OP_CBRA)? IMM2_SIZE : 0), utf, atend, cd,
|
||||
recurses);
|
||||
if (d < 0) return d;
|
||||
branchlength += d;
|
||||
do cc += GET(cc, 1); while (*cc == OP_ALT);
|
||||
@@ -1775,7 +1778,15 @@ for (;;)
|
||||
cs = ce = (pcre_uchar *)cd->start_code + GET(cc, 1); /* Start subpattern */
|
||||
do ce += GET(ce, 1); while (*ce == OP_ALT); /* End subpattern */
|
||||
if (cc > cs && cc < ce) return -1; /* Recursion */
|
||||
d = find_fixedlength(cs + IMM2_SIZE, utf, atend, cd);
|
||||
else /* Check for mutual recursion */
|
||||
{
|
||||
recurse_check *r = recurses;
|
||||
for (r = recurses; r != NULL; r = r->prev) if (r->group == cs) break;
|
||||
if (r != NULL) return -1; /* Mutual recursion */
|
||||
}
|
||||
this_recurse.prev = recurses;
|
||||
this_recurse.group = cs;
|
||||
d = find_fixedlength(cs + IMM2_SIZE, utf, atend, cd, &this_recurse);
|
||||
if (d < 0) return d;
|
||||
branchlength += d;
|
||||
cc += 1 + LINK_SIZE;
|
||||
@@ -2129,32 +2140,60 @@ for (;;)
|
||||
{
|
||||
case OP_CHAR:
|
||||
case OP_CHARI:
|
||||
case OP_NOT:
|
||||
case OP_NOTI:
|
||||
case OP_EXACT:
|
||||
case OP_EXACTI:
|
||||
case OP_NOTEXACT:
|
||||
case OP_NOTEXACTI:
|
||||
case OP_UPTO:
|
||||
case OP_UPTOI:
|
||||
case OP_NOTUPTO:
|
||||
case OP_NOTUPTOI:
|
||||
case OP_MINUPTO:
|
||||
case OP_MINUPTOI:
|
||||
case OP_NOTMINUPTO:
|
||||
case OP_NOTMINUPTOI:
|
||||
case OP_POSUPTO:
|
||||
case OP_POSUPTOI:
|
||||
case OP_NOTPOSUPTO:
|
||||
case OP_NOTPOSUPTOI:
|
||||
case OP_STAR:
|
||||
case OP_STARI:
|
||||
case OP_NOTSTAR:
|
||||
case OP_NOTSTARI:
|
||||
case OP_MINSTAR:
|
||||
case OP_MINSTARI:
|
||||
case OP_NOTMINSTAR:
|
||||
case OP_NOTMINSTARI:
|
||||
case OP_POSSTAR:
|
||||
case OP_POSSTARI:
|
||||
case OP_NOTPOSSTAR:
|
||||
case OP_NOTPOSSTARI:
|
||||
case OP_PLUS:
|
||||
case OP_PLUSI:
|
||||
case OP_NOTPLUS:
|
||||
case OP_NOTPLUSI:
|
||||
case OP_MINPLUS:
|
||||
case OP_MINPLUSI:
|
||||
case OP_NOTMINPLUS:
|
||||
case OP_NOTMINPLUSI:
|
||||
case OP_POSPLUS:
|
||||
case OP_POSPLUSI:
|
||||
case OP_NOTPOSPLUS:
|
||||
case OP_NOTPOSPLUSI:
|
||||
case OP_QUERY:
|
||||
case OP_QUERYI:
|
||||
case OP_NOTQUERY:
|
||||
case OP_NOTQUERYI:
|
||||
case OP_MINQUERY:
|
||||
case OP_MINQUERYI:
|
||||
case OP_NOTMINQUERY:
|
||||
case OP_NOTMINQUERYI:
|
||||
case OP_POSQUERY:
|
||||
case OP_POSQUERYI:
|
||||
case OP_NOTPOSQUERY:
|
||||
case OP_NOTPOSQUERYI:
|
||||
if (HAS_EXTRALEN(code[-1])) code += GET_EXTRALEN(code[-1]);
|
||||
break;
|
||||
}
|
||||
@@ -2334,11 +2373,6 @@ Arguments:
|
||||
Returns: TRUE if what is matched could be empty
|
||||
*/
|
||||
|
||||
typedef struct recurse_check {
|
||||
struct recurse_check *prev;
|
||||
const pcre_uchar *group;
|
||||
} recurse_check;
|
||||
|
||||
static BOOL
|
||||
could_be_empty_branch(const pcre_uchar *code, const pcre_uchar *endcode,
|
||||
BOOL utf, compile_data *cd, recurse_check *recurses)
|
||||
@@ -2469,8 +2503,8 @@ for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE);
|
||||
empty_branch = FALSE;
|
||||
do
|
||||
{
|
||||
if (!empty_branch && could_be_empty_branch(code, endcode, utf, cd, NULL))
|
||||
empty_branch = TRUE;
|
||||
if (!empty_branch && could_be_empty_branch(code, endcode, utf, cd,
|
||||
recurses)) empty_branch = TRUE;
|
||||
code += GET(code, 1);
|
||||
}
|
||||
while (*code == OP_ALT);
|
||||
@@ -3065,7 +3099,7 @@ Returns: TRUE if the auto-possessification is possible
|
||||
|
||||
static BOOL
|
||||
compare_opcodes(const pcre_uchar *code, BOOL utf, const compile_data *cd,
|
||||
const pcre_uint32 *base_list, const pcre_uchar *base_end)
|
||||
const pcre_uint32 *base_list, const pcre_uchar *base_end, int *rec_limit)
|
||||
{
|
||||
pcre_uchar c;
|
||||
pcre_uint32 list[8];
|
||||
@@ -3082,6 +3116,9 @@ pcre_uint32 chr;
|
||||
BOOL accepted, invert_bits;
|
||||
BOOL entered_a_group = FALSE;
|
||||
|
||||
if (*rec_limit == 0) return FALSE;
|
||||
--(*rec_limit);
|
||||
|
||||
/* Note: the base_list[1] contains whether the current opcode has greedy
|
||||
(represented by a non-zero value) quantifier. This is a different from
|
||||
other character type lists, which stores here that the character iterator
|
||||
@@ -3152,7 +3189,8 @@ for(;;)
|
||||
|
||||
while (*next_code == OP_ALT)
|
||||
{
|
||||
if (!compare_opcodes(code, utf, cd, base_list, base_end)) return FALSE;
|
||||
if (!compare_opcodes(code, utf, cd, base_list, base_end, rec_limit))
|
||||
return FALSE;
|
||||
code = next_code + 1 + LINK_SIZE;
|
||||
next_code += GET(next_code, 1);
|
||||
}
|
||||
@@ -3172,7 +3210,7 @@ for(;;)
|
||||
/* The bracket content will be checked by the
|
||||
OP_BRA/OP_CBRA case above. */
|
||||
next_code += 1 + LINK_SIZE;
|
||||
if (!compare_opcodes(next_code, utf, cd, base_list, base_end))
|
||||
if (!compare_opcodes(next_code, utf, cd, base_list, base_end, rec_limit))
|
||||
return FALSE;
|
||||
|
||||
code += PRIV(OP_lengths)[c];
|
||||
@@ -3605,11 +3643,20 @@ register pcre_uchar c;
|
||||
const pcre_uchar *end;
|
||||
pcre_uchar *repeat_opcode;
|
||||
pcre_uint32 list[8];
|
||||
int rec_limit;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
c = *code;
|
||||
|
||||
/* When a pattern with bad UTF-8 encoding is compiled with NO_UTF_CHECK,
|
||||
it may compile without complaining, but may get into a loop here if the code
|
||||
pointer points to a bad value. This is, of course a documentated possibility,
|
||||
when NO_UTF_CHECK is set, so it isn't a bug, but we can detect this case and
|
||||
just give up on this optimization. */
|
||||
|
||||
if (c >= OP_TABLE_LENGTH) return;
|
||||
|
||||
if (c >= OP_STAR && c <= OP_TYPEPOSUPTO)
|
||||
{
|
||||
c -= get_repeat_base(c) - OP_STAR;
|
||||
@@ -3617,7 +3664,8 @@ for (;;)
|
||||
get_chr_property_list(code, utf, cd->fcc, list) : NULL;
|
||||
list[1] = c == OP_STAR || c == OP_PLUS || c == OP_QUERY || c == OP_UPTO;
|
||||
|
||||
if (end != NULL && compare_opcodes(end, utf, cd, list, end))
|
||||
rec_limit = 1000;
|
||||
if (end != NULL && compare_opcodes(end, utf, cd, list, end, &rec_limit))
|
||||
{
|
||||
switch(c)
|
||||
{
|
||||
@@ -3673,7 +3721,8 @@ for (;;)
|
||||
|
||||
list[1] = (c & 1) == 0;
|
||||
|
||||
if (compare_opcodes(end, utf, cd, list, end))
|
||||
rec_limit = 1000;
|
||||
if (compare_opcodes(end, utf, cd, list, end, &rec_limit))
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
@@ -3947,14 +3996,14 @@ Arguments:
|
||||
adjust the amount by which the group is to be moved
|
||||
utf TRUE in UTF-8 / UTF-16 / UTF-32 mode
|
||||
cd contains pointers to tables etc.
|
||||
save_hwm the hwm forward reference pointer at the start of the group
|
||||
save_hwm_offset the hwm forward reference offset at the start of the group
|
||||
|
||||
Returns: nothing
|
||||
*/
|
||||
|
||||
static void
|
||||
adjust_recurse(pcre_uchar *group, int adjust, BOOL utf, compile_data *cd,
|
||||
pcre_uchar *save_hwm)
|
||||
size_t save_hwm_offset)
|
||||
{
|
||||
pcre_uchar *ptr = group;
|
||||
|
||||
@@ -3966,7 +4015,8 @@ while ((ptr = (pcre_uchar *)find_recurse(ptr, utf)) != NULL)
|
||||
/* See if this recursion is on the forward reference list. If so, adjust the
|
||||
reference. */
|
||||
|
||||
for (hc = save_hwm; hc < cd->hwm; hc += LINK_SIZE)
|
||||
for (hc = (pcre_uchar *)cd->start_workspace + save_hwm_offset; hc < cd->hwm;
|
||||
hc += LINK_SIZE)
|
||||
{
|
||||
offset = (int)GET(hc, 0);
|
||||
if (cd->start_code + offset == ptr + 1)
|
||||
@@ -4171,7 +4221,11 @@ if ((options & PCRE_CASELESS) != 0)
|
||||
range. Otherwise, use a recursive call to add the additional range. */
|
||||
|
||||
else if (oc < start && od >= start - 1) start = oc; /* Extend downwards */
|
||||
else if (od > end && oc <= end + 1) end = od; /* Extend upwards */
|
||||
else if (od > end && oc <= end + 1)
|
||||
{
|
||||
end = od; /* Extend upwards */
|
||||
if (end > classbits_end) classbits_end = (end <= 0xff ? end : 0xff);
|
||||
}
|
||||
else n8 += add_to_class(classbits, uchardptr, options, cd, oc, od);
|
||||
}
|
||||
}
|
||||
@@ -4411,7 +4465,7 @@ const pcre_uchar *tempptr;
|
||||
const pcre_uchar *nestptr = NULL;
|
||||
pcre_uchar *previous = NULL;
|
||||
pcre_uchar *previous_callout = NULL;
|
||||
pcre_uchar *save_hwm = NULL;
|
||||
size_t save_hwm_offset = 0;
|
||||
pcre_uint8 classbits[32];
|
||||
|
||||
/* We can fish out the UTF-8 setting once and for all into a BOOL, but we
|
||||
@@ -5470,6 +5524,12 @@ for (;; ptr++)
|
||||
PUT(previous, 1, (int)(code - previous));
|
||||
break; /* End of class handling */
|
||||
}
|
||||
|
||||
/* Even though any XCLASS list is now discarded, we must allow for
|
||||
its memory. */
|
||||
|
||||
if (lengthptr != NULL)
|
||||
*lengthptr += (int)(class_uchardata - class_uchardata_base);
|
||||
#endif
|
||||
|
||||
/* If there are no characters > 255, or they are all to be included or
|
||||
@@ -5870,6 +5930,7 @@ for (;; ptr++)
|
||||
{
|
||||
register int i;
|
||||
int len = (int)(code - previous);
|
||||
size_t base_hwm_offset = save_hwm_offset;
|
||||
pcre_uchar *bralink = NULL;
|
||||
pcre_uchar *brazeroptr = NULL;
|
||||
|
||||
@@ -5924,7 +5985,7 @@ for (;; ptr++)
|
||||
if (repeat_max <= 1) /* Covers 0, 1, and unlimited */
|
||||
{
|
||||
*code = OP_END;
|
||||
adjust_recurse(previous, 1, utf, cd, save_hwm);
|
||||
adjust_recurse(previous, 1, utf, cd, save_hwm_offset);
|
||||
memmove(previous + 1, previous, IN_UCHARS(len));
|
||||
code++;
|
||||
if (repeat_max == 0)
|
||||
@@ -5948,7 +6009,7 @@ for (;; ptr++)
|
||||
{
|
||||
int offset;
|
||||
*code = OP_END;
|
||||
adjust_recurse(previous, 2 + LINK_SIZE, utf, cd, save_hwm);
|
||||
adjust_recurse(previous, 2 + LINK_SIZE, utf, cd, save_hwm_offset);
|
||||
memmove(previous + 2 + LINK_SIZE, previous, IN_UCHARS(len));
|
||||
code += 2 + LINK_SIZE;
|
||||
*previous++ = OP_BRAZERO + repeat_type;
|
||||
@@ -6011,26 +6072,25 @@ for (;; ptr++)
|
||||
for (i = 1; i < repeat_min; i++)
|
||||
{
|
||||
pcre_uchar *hc;
|
||||
pcre_uchar *this_hwm = cd->hwm;
|
||||
size_t this_hwm_offset = cd->hwm - cd->start_workspace;
|
||||
memcpy(code, previous, IN_UCHARS(len));
|
||||
|
||||
while (cd->hwm > cd->start_workspace + cd->workspace_size -
|
||||
WORK_SIZE_SAFETY_MARGIN - (this_hwm - save_hwm))
|
||||
WORK_SIZE_SAFETY_MARGIN -
|
||||
(this_hwm_offset - base_hwm_offset))
|
||||
{
|
||||
size_t save_offset = save_hwm - cd->start_workspace;
|
||||
size_t this_offset = this_hwm - cd->start_workspace;
|
||||
*errorcodeptr = expand_workspace(cd);
|
||||
if (*errorcodeptr != 0) goto FAILED;
|
||||
save_hwm = (pcre_uchar *)cd->start_workspace + save_offset;
|
||||
this_hwm = (pcre_uchar *)cd->start_workspace + this_offset;
|
||||
}
|
||||
|
||||
for (hc = save_hwm; hc < this_hwm; hc += LINK_SIZE)
|
||||
for (hc = (pcre_uchar *)cd->start_workspace + base_hwm_offset;
|
||||
hc < (pcre_uchar *)cd->start_workspace + this_hwm_offset;
|
||||
hc += LINK_SIZE)
|
||||
{
|
||||
PUT(cd->hwm, 0, GET(hc, 0) + len);
|
||||
cd->hwm += LINK_SIZE;
|
||||
}
|
||||
save_hwm = this_hwm;
|
||||
base_hwm_offset = this_hwm_offset;
|
||||
code += len;
|
||||
}
|
||||
}
|
||||
@@ -6075,7 +6135,7 @@ for (;; ptr++)
|
||||
else for (i = repeat_max - 1; i >= 0; i--)
|
||||
{
|
||||
pcre_uchar *hc;
|
||||
pcre_uchar *this_hwm = cd->hwm;
|
||||
size_t this_hwm_offset = cd->hwm - cd->start_workspace;
|
||||
|
||||
*code++ = OP_BRAZERO + repeat_type;
|
||||
|
||||
@@ -6097,22 +6157,21 @@ for (;; ptr++)
|
||||
copying them. */
|
||||
|
||||
while (cd->hwm > cd->start_workspace + cd->workspace_size -
|
||||
WORK_SIZE_SAFETY_MARGIN - (this_hwm - save_hwm))
|
||||
WORK_SIZE_SAFETY_MARGIN -
|
||||
(this_hwm_offset - base_hwm_offset))
|
||||
{
|
||||
size_t save_offset = save_hwm - cd->start_workspace;
|
||||
size_t this_offset = this_hwm - cd->start_workspace;
|
||||
*errorcodeptr = expand_workspace(cd);
|
||||
if (*errorcodeptr != 0) goto FAILED;
|
||||
save_hwm = (pcre_uchar *)cd->start_workspace + save_offset;
|
||||
this_hwm = (pcre_uchar *)cd->start_workspace + this_offset;
|
||||
}
|
||||
|
||||
for (hc = save_hwm; hc < this_hwm; hc += LINK_SIZE)
|
||||
for (hc = (pcre_uchar *)cd->start_workspace + base_hwm_offset;
|
||||
hc < (pcre_uchar *)cd->start_workspace + this_hwm_offset;
|
||||
hc += LINK_SIZE)
|
||||
{
|
||||
PUT(cd->hwm, 0, GET(hc, 0) + len + ((i != 0)? 2+LINK_SIZE : 1));
|
||||
cd->hwm += LINK_SIZE;
|
||||
}
|
||||
save_hwm = this_hwm;
|
||||
base_hwm_offset = this_hwm_offset;
|
||||
code += len;
|
||||
}
|
||||
|
||||
@@ -6208,7 +6267,7 @@ for (;; ptr++)
|
||||
{
|
||||
int nlen = (int)(code - bracode);
|
||||
*code = OP_END;
|
||||
adjust_recurse(bracode, 1 + LINK_SIZE, utf, cd, save_hwm);
|
||||
adjust_recurse(bracode, 1 + LINK_SIZE, utf, cd, save_hwm_offset);
|
||||
memmove(bracode + 1 + LINK_SIZE, bracode, IN_UCHARS(nlen));
|
||||
code += 1 + LINK_SIZE;
|
||||
nlen += 1 + LINK_SIZE;
|
||||
@@ -6342,7 +6401,7 @@ for (;; ptr++)
|
||||
else
|
||||
{
|
||||
*code = OP_END;
|
||||
adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, save_hwm);
|
||||
adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, save_hwm_offset);
|
||||
memmove(tempcode + 1 + LINK_SIZE, tempcode, IN_UCHARS(len));
|
||||
code += 1 + LINK_SIZE;
|
||||
len += 1 + LINK_SIZE;
|
||||
@@ -6391,7 +6450,7 @@ for (;; ptr++)
|
||||
|
||||
default:
|
||||
*code = OP_END;
|
||||
adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, save_hwm);
|
||||
adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, save_hwm_offset);
|
||||
memmove(tempcode + 1 + LINK_SIZE, tempcode, IN_UCHARS(len));
|
||||
code += 1 + LINK_SIZE;
|
||||
len += 1 + LINK_SIZE;
|
||||
@@ -6420,15 +6479,25 @@ for (;; ptr++)
|
||||
parenthesis forms. */
|
||||
|
||||
case CHAR_LEFT_PARENTHESIS:
|
||||
newoptions = options;
|
||||
skipbytes = 0;
|
||||
bravalue = OP_CBRA;
|
||||
save_hwm = cd->hwm;
|
||||
reset_bracount = FALSE;
|
||||
|
||||
/* First deal with various "verbs" that can be introduced by '*'. */
|
||||
|
||||
ptr++;
|
||||
|
||||
/* First deal with comments. Putting this code right at the start ensures
|
||||
that comments have no bad side effects. */
|
||||
|
||||
if (ptr[0] == CHAR_QUESTION_MARK && ptr[1] == CHAR_NUMBER_SIGN)
|
||||
{
|
||||
ptr += 2;
|
||||
while (*ptr != CHAR_NULL && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++;
|
||||
if (*ptr == CHAR_NULL)
|
||||
{
|
||||
*errorcodeptr = ERR18;
|
||||
goto FAILED;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Now deal with various "verbs" that can be introduced by '*'. */
|
||||
|
||||
if (ptr[0] == CHAR_ASTERISK && (ptr[1] == ':'
|
||||
|| (MAX_255(ptr[1]) && ((cd->ctypes[ptr[1]] & ctype_letter) != 0))))
|
||||
{
|
||||
@@ -6549,10 +6618,18 @@ for (;; ptr++)
|
||||
goto FAILED;
|
||||
}
|
||||
|
||||
/* Initialize for "real" parentheses */
|
||||
|
||||
newoptions = options;
|
||||
skipbytes = 0;
|
||||
bravalue = OP_CBRA;
|
||||
save_hwm_offset = cd->hwm - cd->start_workspace;
|
||||
reset_bracount = FALSE;
|
||||
|
||||
/* Deal with the extended parentheses; all are introduced by '?', and the
|
||||
appearance of any of them means that this is not a capturing group. */
|
||||
|
||||
else if (*ptr == CHAR_QUESTION_MARK)
|
||||
if (*ptr == CHAR_QUESTION_MARK)
|
||||
{
|
||||
int i, set, unset, namelen;
|
||||
int *optset;
|
||||
@@ -6561,17 +6638,6 @@ for (;; ptr++)
|
||||
|
||||
switch (*(++ptr))
|
||||
{
|
||||
case CHAR_NUMBER_SIGN: /* Comment; skip to ket */
|
||||
ptr++;
|
||||
while (*ptr != CHAR_NULL && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++;
|
||||
if (*ptr == CHAR_NULL)
|
||||
{
|
||||
*errorcodeptr = ERR18;
|
||||
goto FAILED;
|
||||
}
|
||||
continue;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
case CHAR_VERTICAL_LINE: /* Reset capture count for each branch */
|
||||
reset_bracount = TRUE;
|
||||
@@ -6620,8 +6686,13 @@ for (;; ptr++)
|
||||
if (tempptr[1] == CHAR_QUESTION_MARK &&
|
||||
(tempptr[2] == CHAR_EQUALS_SIGN ||
|
||||
tempptr[2] == CHAR_EXCLAMATION_MARK ||
|
||||
tempptr[2] == CHAR_LESS_THAN_SIGN))
|
||||
(tempptr[2] == CHAR_LESS_THAN_SIGN &&
|
||||
(tempptr[3] == CHAR_EQUALS_SIGN ||
|
||||
tempptr[3] == CHAR_EXCLAMATION_MARK))))
|
||||
{
|
||||
cd->iscondassert = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Other conditions use OP_CREF/OP_DNCREF/OP_RREF/OP_DNRREF, and all
|
||||
need to skip at least 1+IMM2_SIZE bytes at the start of the group. */
|
||||
@@ -6698,8 +6769,7 @@ for (;; ptr++)
|
||||
ptr++;
|
||||
}
|
||||
namelen = (int)(ptr - name);
|
||||
if (lengthptr != NULL && (options & PCRE_DUPNAMES) != 0)
|
||||
*lengthptr += IMM2_SIZE;
|
||||
if (lengthptr != NULL) *lengthptr += IMM2_SIZE;
|
||||
}
|
||||
|
||||
/* Check the terminator */
|
||||
@@ -6735,6 +6805,7 @@ for (;; ptr++)
|
||||
goto FAILED;
|
||||
}
|
||||
PUT2(code, 2+LINK_SIZE, recno);
|
||||
if (recno > cd->top_backref) cd->top_backref = recno;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -6757,6 +6828,7 @@ for (;; ptr++)
|
||||
int offset = i++;
|
||||
int count = 1;
|
||||
recno = GET2(slot, 0); /* Number from first found */
|
||||
if (recno > cd->top_backref) cd->top_backref = recno;
|
||||
for (; i < cd->names_found; i++)
|
||||
{
|
||||
slot += cd->name_entry_size;
|
||||
@@ -7114,11 +7186,11 @@ for (;; ptr++)
|
||||
|
||||
if (!is_recurse) cd->namedrefcount++;
|
||||
|
||||
/* If duplicate names are permitted, we have to allow for a named
|
||||
reference to a duplicated name (this cannot be determined until the
|
||||
second pass). This needs an extra 16-bit data item. */
|
||||
/* We have to allow for a named reference to a duplicated name (this
|
||||
cannot be determined until the second pass). This needs an extra
|
||||
16-bit data item. */
|
||||
|
||||
if ((options & PCRE_DUPNAMES) != 0) *lengthptr += IMM2_SIZE;
|
||||
*lengthptr += IMM2_SIZE;
|
||||
}
|
||||
|
||||
/* In the real compile, search the name table. We check the name
|
||||
@@ -7475,12 +7547,22 @@ for (;; ptr++)
|
||||
goto FAILED;
|
||||
}
|
||||
|
||||
/* Assertions used not to be repeatable, but this was changed for Perl
|
||||
compatibility, so all kinds can now be repeated. We copy code into a
|
||||
/* All assertions used not to be repeatable, but this was changed for Perl
|
||||
compatibility. All kinds can now be repeated except for assertions that are
|
||||
conditions (Perl also forbids these to be repeated). We copy code into a
|
||||
non-register variable (tempcode) in order to be able to pass its address
|
||||
because some compilers complain otherwise. */
|
||||
because some compilers complain otherwise. At the start of a conditional
|
||||
group whose condition is an assertion, cd->iscondassert is set. We unset it
|
||||
here so as to allow assertions later in the group to be quantified. */
|
||||
|
||||
if (bravalue >= OP_ASSERT && bravalue <= OP_ASSERTBACK_NOT &&
|
||||
cd->iscondassert)
|
||||
{
|
||||
previous = NULL;
|
||||
cd->iscondassert = FALSE;
|
||||
}
|
||||
else previous = code;
|
||||
|
||||
previous = code; /* For handling repetition */
|
||||
*code = bravalue;
|
||||
tempcode = code;
|
||||
tempreqvary = cd->req_varyopt; /* Save value before bracket */
|
||||
@@ -7727,7 +7809,7 @@ for (;; ptr++)
|
||||
const pcre_uchar *p;
|
||||
pcre_uint32 cf;
|
||||
|
||||
save_hwm = cd->hwm; /* Normally this is set when '(' is read */
|
||||
save_hwm_offset = cd->hwm - cd->start_workspace; /* Normally this is set when '(' is read */
|
||||
terminator = (*(++ptr) == CHAR_LESS_THAN_SIGN)?
|
||||
CHAR_GREATER_THAN_SIGN : CHAR_APOSTROPHE;
|
||||
|
||||
@@ -8054,6 +8136,7 @@ int length;
|
||||
unsigned int orig_bracount;
|
||||
unsigned int max_bracount;
|
||||
branch_chain bc;
|
||||
size_t save_hwm_offset;
|
||||
|
||||
/* If set, call the external function that checks for stack availability. */
|
||||
|
||||
@@ -8071,6 +8154,8 @@ bc.current_branch = code;
|
||||
firstchar = reqchar = 0;
|
||||
firstcharflags = reqcharflags = REQ_UNSET;
|
||||
|
||||
save_hwm_offset = cd->hwm - cd->start_workspace;
|
||||
|
||||
/* Accumulate the length for use in the pre-compile phase. Start with the
|
||||
length of the BRA and KET and any extra bytes that are required at the
|
||||
beginning. We accumulate in a local variable to save frequent testing of
|
||||
@@ -8212,7 +8297,7 @@ for (;;)
|
||||
int fixed_length;
|
||||
*code = OP_END;
|
||||
fixed_length = find_fixedlength(last_branch, (options & PCRE_UTF8) != 0,
|
||||
FALSE, cd);
|
||||
FALSE, cd, NULL);
|
||||
DPRINTF(("fixed length = %d\n", fixed_length));
|
||||
if (fixed_length == -3)
|
||||
{
|
||||
@@ -8273,7 +8358,7 @@ for (;;)
|
||||
{
|
||||
*code = OP_END;
|
||||
adjust_recurse(start_bracket, 1 + LINK_SIZE,
|
||||
(options & PCRE_UTF8) != 0, cd, cd->hwm);
|
||||
(options & PCRE_UTF8) != 0, cd, save_hwm_offset);
|
||||
memmove(start_bracket + 1 + LINK_SIZE, start_bracket,
|
||||
IN_UCHARS(code - start_bracket));
|
||||
*start_bracket = OP_ONCE;
|
||||
@@ -8497,6 +8582,7 @@ do {
|
||||
case OP_RREF:
|
||||
case OP_DNRREF:
|
||||
case OP_DEF:
|
||||
case OP_FAIL:
|
||||
return FALSE;
|
||||
|
||||
default: /* Assertion */
|
||||
@@ -9081,6 +9167,7 @@ cd->dupnames = FALSE;
|
||||
cd->namedrefcount = 0;
|
||||
cd->start_code = cworkspace;
|
||||
cd->hwm = cworkspace;
|
||||
cd->iscondassert = FALSE;
|
||||
cd->start_workspace = cworkspace;
|
||||
cd->workspace_size = COMPILE_WORK_SIZE;
|
||||
cd->named_groups = named_groups;
|
||||
@@ -9118,13 +9205,6 @@ if (length > MAX_PATTERN_SIZE)
|
||||
goto PCRE_EARLY_ERROR_RETURN;
|
||||
}
|
||||
|
||||
/* If there are groups with duplicate names and there are also references by
|
||||
name, we must allow for the possibility of named references to duplicated
|
||||
groups. These require an extra data item each. */
|
||||
|
||||
if (cd->dupnames && cd->namedrefcount > 0)
|
||||
length += cd->namedrefcount * IMM2_SIZE * sizeof(pcre_uchar);
|
||||
|
||||
/* Compute the size of the data block for storing the compiled pattern. Integer
|
||||
overflow should no longer be possible because nowadays we limit the maximum
|
||||
value of cd->names_found and cd->name_entry_size. */
|
||||
@@ -9183,6 +9263,7 @@ cd->name_table = (pcre_uchar *)re + re->name_table_offset;
|
||||
codestart = cd->name_table + re->name_entry_size * re->name_count;
|
||||
cd->start_code = codestart;
|
||||
cd->hwm = (pcre_uchar *)(cd->start_workspace);
|
||||
cd->iscondassert = FALSE;
|
||||
cd->req_varyopt = 0;
|
||||
cd->had_accept = FALSE;
|
||||
cd->had_pruneorskip = FALSE;
|
||||
@@ -9319,7 +9400,7 @@ if (cd->check_lookbehind)
|
||||
int end_op = *be;
|
||||
*be = OP_END;
|
||||
fixed_length = find_fixedlength(cc, (re->options & PCRE_UTF8) != 0, TRUE,
|
||||
cd);
|
||||
cd, NULL);
|
||||
*be = end_op;
|
||||
DPRINTF(("fixed length = %d\n", fixed_length));
|
||||
if (fixed_length < 0)
|
||||
|
||||
@@ -1136,93 +1136,81 @@ for (;;)
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
if (offset < md->offset_max)
|
||||
if (offset >= md->offset_max) goto POSSESSIVE_NON_CAPTURE;
|
||||
|
||||
matched_once = FALSE;
|
||||
code_offset = (int)(ecode - md->start_code);
|
||||
|
||||
save_offset1 = md->offset_vector[offset];
|
||||
save_offset2 = md->offset_vector[offset+1];
|
||||
save_offset3 = md->offset_vector[md->offset_end - number];
|
||||
save_capture_last = md->capture_last;
|
||||
|
||||
DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3));
|
||||
|
||||
/* Each time round the loop, save the current subject position for use
|
||||
when the group matches. For MATCH_MATCH, the group has matched, so we
|
||||
restart it with a new subject starting position, remembering that we had
|
||||
at least one match. For MATCH_NOMATCH, carry on with the alternatives, as
|
||||
usual. If we haven't matched any alternatives in any iteration, check to
|
||||
see if a previous iteration matched. If so, the group has matched;
|
||||
continue from afterwards. Otherwise it has failed; restore the previous
|
||||
capture values before returning NOMATCH. */
|
||||
|
||||
for (;;)
|
||||
{
|
||||
matched_once = FALSE;
|
||||
code_offset = (int)(ecode - md->start_code);
|
||||
|
||||
save_offset1 = md->offset_vector[offset];
|
||||
save_offset2 = md->offset_vector[offset+1];
|
||||
save_offset3 = md->offset_vector[md->offset_end - number];
|
||||
save_capture_last = md->capture_last;
|
||||
|
||||
DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3));
|
||||
|
||||
/* Each time round the loop, save the current subject position for use
|
||||
when the group matches. For MATCH_MATCH, the group has matched, so we
|
||||
restart it with a new subject starting position, remembering that we had
|
||||
at least one match. For MATCH_NOMATCH, carry on with the alternatives, as
|
||||
usual. If we haven't matched any alternatives in any iteration, check to
|
||||
see if a previous iteration matched. If so, the group has matched;
|
||||
continue from afterwards. Otherwise it has failed; restore the previous
|
||||
capture values before returning NOMATCH. */
|
||||
|
||||
for (;;)
|
||||
md->offset_vector[md->offset_end - number] =
|
||||
(int)(eptr - md->start_subject);
|
||||
if (op >= OP_SBRA) md->match_function_type = MATCH_CBEGROUP;
|
||||
RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
|
||||
eptrb, RM63);
|
||||
if (rrc == MATCH_KETRPOS)
|
||||
{
|
||||
md->offset_vector[md->offset_end - number] =
|
||||
(int)(eptr - md->start_subject);
|
||||
if (op >= OP_SBRA) md->match_function_type = MATCH_CBEGROUP;
|
||||
RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
|
||||
eptrb, RM63);
|
||||
if (rrc == MATCH_KETRPOS)
|
||||
offset_top = md->end_offset_top;
|
||||
ecode = md->start_code + code_offset;
|
||||
save_capture_last = md->capture_last;
|
||||
matched_once = TRUE;
|
||||
mstart = md->start_match_ptr; /* In case \K changed it */
|
||||
if (eptr == md->end_match_ptr) /* Matched an empty string */
|
||||
{
|
||||
offset_top = md->end_offset_top;
|
||||
ecode = md->start_code + code_offset;
|
||||
save_capture_last = md->capture_last;
|
||||
matched_once = TRUE;
|
||||
mstart = md->start_match_ptr; /* In case \K changed it */
|
||||
if (eptr == md->end_match_ptr) /* Matched an empty string */
|
||||
{
|
||||
do ecode += GET(ecode, 1); while (*ecode == OP_ALT);
|
||||
break;
|
||||
}
|
||||
eptr = md->end_match_ptr;
|
||||
continue;
|
||||
do ecode += GET(ecode, 1); while (*ecode == OP_ALT);
|
||||
break;
|
||||
}
|
||||
|
||||
/* See comment in the code for capturing groups above about handling
|
||||
THEN. */
|
||||
|
||||
if (rrc == MATCH_THEN)
|
||||
{
|
||||
next = ecode + GET(ecode,1);
|
||||
if (md->start_match_ptr < next &&
|
||||
(*ecode == OP_ALT || *next == OP_ALT))
|
||||
rrc = MATCH_NOMATCH;
|
||||
}
|
||||
|
||||
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
|
||||
md->capture_last = save_capture_last;
|
||||
ecode += GET(ecode, 1);
|
||||
if (*ecode != OP_ALT) break;
|
||||
eptr = md->end_match_ptr;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!matched_once)
|
||||
/* See comment in the code for capturing groups above about handling
|
||||
THEN. */
|
||||
|
||||
if (rrc == MATCH_THEN)
|
||||
{
|
||||
md->offset_vector[offset] = save_offset1;
|
||||
md->offset_vector[offset+1] = save_offset2;
|
||||
md->offset_vector[md->offset_end - number] = save_offset3;
|
||||
next = ecode + GET(ecode,1);
|
||||
if (md->start_match_ptr < next &&
|
||||
(*ecode == OP_ALT || *next == OP_ALT))
|
||||
rrc = MATCH_NOMATCH;
|
||||
}
|
||||
|
||||
if (allow_zero || matched_once)
|
||||
{
|
||||
ecode += 1 + LINK_SIZE;
|
||||
break;
|
||||
}
|
||||
|
||||
RRETURN(MATCH_NOMATCH);
|
||||
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
|
||||
md->capture_last = save_capture_last;
|
||||
ecode += GET(ecode, 1);
|
||||
if (*ecode != OP_ALT) break;
|
||||
}
|
||||
|
||||
/* FALL THROUGH ... Insufficient room for saving captured contents. Treat
|
||||
as a non-capturing bracket. */
|
||||
if (!matched_once)
|
||||
{
|
||||
md->offset_vector[offset] = save_offset1;
|
||||
md->offset_vector[offset+1] = save_offset2;
|
||||
md->offset_vector[md->offset_end - number] = save_offset3;
|
||||
}
|
||||
|
||||
/* VVVVVVVVVVVVVVVVVVVVVVVVV */
|
||||
/* VVVVVVVVVVVVVVVVVVVVVVVVV */
|
||||
if (allow_zero || matched_once)
|
||||
{
|
||||
ecode += 1 + LINK_SIZE;
|
||||
break;
|
||||
}
|
||||
|
||||
DPRINTF(("insufficient capture room: treat as non-capturing\n"));
|
||||
|
||||
/* VVVVVVVVVVVVVVVVVVVVVVVVV */
|
||||
/* VVVVVVVVVVVVVVVVVVVVVVVVV */
|
||||
RRETURN(MATCH_NOMATCH);
|
||||
|
||||
/* Non-capturing possessive bracket with unlimited repeat. We come here
|
||||
from BRAZERO with allow_zero = TRUE. The code is similar to the above,
|
||||
@@ -1388,6 +1376,7 @@ for (;;)
|
||||
break;
|
||||
|
||||
case OP_DEF: /* DEFINE - always false */
|
||||
case OP_FAIL: /* From optimized (?!) condition */
|
||||
break;
|
||||
|
||||
/* The condition is an assertion. Call match() to evaluate it - setting
|
||||
@@ -1404,8 +1393,11 @@ for (;;)
|
||||
condition = TRUE;
|
||||
|
||||
/* Advance ecode past the assertion to the start of the first branch,
|
||||
but adjust it so that the general choosing code below works. */
|
||||
but adjust it so that the general choosing code below works. If the
|
||||
assertion has a quantifier that allows zero repeats we must skip over
|
||||
the BRAZERO. This is a lunatic thing to do, but somebody did! */
|
||||
|
||||
if (*ecode == OP_BRAZERO) ecode++;
|
||||
ecode += GET(ecode, 1);
|
||||
while (*ecode == OP_ALT) ecode += GET(ecode, 1);
|
||||
ecode += 1 + LINK_SIZE - PRIV(OP_lengths)[condcode];
|
||||
@@ -1474,7 +1466,18 @@ for (;;)
|
||||
md->offset_vector[offset] =
|
||||
md->offset_vector[md->offset_end - number];
|
||||
md->offset_vector[offset+1] = (int)(eptr - md->start_subject);
|
||||
if (offset_top <= offset) offset_top = offset + 2;
|
||||
|
||||
/* If this group is at or above the current highwater mark, ensure that
|
||||
any groups between the current high water mark and this group are marked
|
||||
unset and then update the high water mark. */
|
||||
|
||||
if (offset >= offset_top)
|
||||
{
|
||||
register int *iptr = md->offset_vector + offset_top;
|
||||
register int *iend = md->offset_vector + offset;
|
||||
while (iptr < iend) *iptr++ = -1;
|
||||
offset_top = offset + 2;
|
||||
}
|
||||
}
|
||||
ecode += 1 + IMM2_SIZE;
|
||||
break;
|
||||
@@ -1826,7 +1829,11 @@ for (;;)
|
||||
are defined in a range that can be tested for. */
|
||||
|
||||
if (rrc >= MATCH_BACKTRACK_MIN && rrc <= MATCH_BACKTRACK_MAX)
|
||||
{
|
||||
if (new_recursive.offset_save != stacksave)
|
||||
(PUBL(free))(new_recursive.offset_save);
|
||||
RRETURN(MATCH_NOMATCH);
|
||||
}
|
||||
|
||||
/* Any return code other than NOMATCH is an error. */
|
||||
|
||||
@@ -3476,7 +3483,7 @@ for (;;)
|
||||
if (possessive) continue; /* No backtracking */
|
||||
for(;;)
|
||||
{
|
||||
if (eptr == pp) goto TAIL_RECURSE;
|
||||
if (eptr <= pp) goto TAIL_RECURSE;
|
||||
RMATCH(eptr, ecode, offset_top, md, eptrb, RM23);
|
||||
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
|
||||
#ifdef SUPPORT_UCP
|
||||
@@ -3897,7 +3904,7 @@ for (;;)
|
||||
if (possessive) continue; /* No backtracking */
|
||||
for(;;)
|
||||
{
|
||||
if (eptr == pp) goto TAIL_RECURSE;
|
||||
if (eptr <= pp) goto TAIL_RECURSE;
|
||||
RMATCH(eptr, ecode, offset_top, md, eptrb, RM30);
|
||||
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
|
||||
eptr--;
|
||||
@@ -4032,7 +4039,7 @@ for (;;)
|
||||
if (possessive) continue; /* No backtracking */
|
||||
for(;;)
|
||||
{
|
||||
if (eptr == pp) goto TAIL_RECURSE;
|
||||
if (eptr <= pp) goto TAIL_RECURSE;
|
||||
RMATCH(eptr, ecode, offset_top, md, eptrb, RM34);
|
||||
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
|
||||
eptr--;
|
||||
@@ -5603,7 +5610,7 @@ for (;;)
|
||||
if (possessive) continue; /* No backtracking */
|
||||
for(;;)
|
||||
{
|
||||
if (eptr == pp) goto TAIL_RECURSE;
|
||||
if (eptr <= pp) goto TAIL_RECURSE;
|
||||
RMATCH(eptr, ecode, offset_top, md, eptrb, RM44);
|
||||
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
|
||||
eptr--;
|
||||
@@ -5645,12 +5652,17 @@ for (;;)
|
||||
|
||||
if (possessive) continue; /* No backtracking */
|
||||
|
||||
/* We use <= pp rather than == pp to detect the start of the run while
|
||||
backtracking because the use of \C in UTF mode can cause BACKCHAR to
|
||||
move back past pp. This is just palliative; the use of \C in UTF mode
|
||||
is fraught with danger. */
|
||||
|
||||
for(;;)
|
||||
{
|
||||
int lgb, rgb;
|
||||
PCRE_PUCHAR fptr;
|
||||
|
||||
if (eptr == pp) goto TAIL_RECURSE; /* At start of char run */
|
||||
if (eptr <= pp) goto TAIL_RECURSE; /* At start of char run */
|
||||
RMATCH(eptr, ecode, offset_top, md, eptrb, RM45);
|
||||
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
|
||||
|
||||
@@ -5668,7 +5680,7 @@ for (;;)
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (eptr == pp) goto TAIL_RECURSE; /* At start of char run */
|
||||
if (eptr <= pp) goto TAIL_RECURSE; /* At start of char run */
|
||||
fptr = eptr - 1;
|
||||
if (!utf) c = *fptr; else
|
||||
{
|
||||
@@ -5918,7 +5930,7 @@ for (;;)
|
||||
if (possessive) continue; /* No backtracking */
|
||||
for(;;)
|
||||
{
|
||||
if (eptr == pp) goto TAIL_RECURSE;
|
||||
if (eptr <= pp) goto TAIL_RECURSE;
|
||||
RMATCH(eptr, ecode, offset_top, md, eptrb, RM46);
|
||||
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
|
||||
eptr--;
|
||||
|
||||
@@ -2450,6 +2450,7 @@ typedef struct compile_data {
|
||||
BOOL had_pruneorskip; /* (*PRUNE) or (*SKIP) encountered */
|
||||
BOOL check_lookbehind; /* Lookbehinds need later checking */
|
||||
BOOL dupnames; /* Duplicate names exist */
|
||||
BOOL iscondassert; /* Next assert is a condition */
|
||||
int nltype; /* Newline type */
|
||||
int nllen; /* Newline string length */
|
||||
pcre_uchar nl[4]; /* Newline string when fixed length */
|
||||
@@ -2463,6 +2464,13 @@ typedef struct branch_chain {
|
||||
pcre_uchar *current_branch;
|
||||
} branch_chain;
|
||||
|
||||
/* Structure for mutual recursion detection. */
|
||||
|
||||
typedef struct recurse_check {
|
||||
struct recurse_check *prev;
|
||||
const pcre_uchar *group;
|
||||
} recurse_check;
|
||||
|
||||
/* Structure for items in a linked list that represents an explicit recursive
|
||||
call within the pattern; used by pcre_exec(). */
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -70,7 +70,7 @@ Arguments:
|
||||
code pointer to start of group (the bracket)
|
||||
startcode pointer to start of the whole pattern's code
|
||||
options the compiling options
|
||||
int RECURSE depth
|
||||
recurses chain of recurse_check to catch mutual recursion
|
||||
|
||||
Returns: the minimum length
|
||||
-1 if \C in UTF-8 mode or (*ACCEPT) was encountered
|
||||
@@ -80,12 +80,13 @@ Returns: the minimum length
|
||||
|
||||
static int
|
||||
find_minlength(const REAL_PCRE *re, const pcre_uchar *code,
|
||||
const pcre_uchar *startcode, int options, int recurse_depth)
|
||||
const pcre_uchar *startcode, int options, recurse_check *recurses)
|
||||
{
|
||||
int length = -1;
|
||||
/* PCRE_UTF16 has the same value as PCRE_UTF8. */
|
||||
BOOL utf = (options & PCRE_UTF8) != 0;
|
||||
BOOL had_recurse = FALSE;
|
||||
recurse_check this_recurse;
|
||||
register int branchlength = 0;
|
||||
register pcre_uchar *cc = (pcre_uchar *)code + 1 + LINK_SIZE;
|
||||
|
||||
@@ -130,7 +131,7 @@ for (;;)
|
||||
case OP_SBRAPOS:
|
||||
case OP_ONCE:
|
||||
case OP_ONCE_NC:
|
||||
d = find_minlength(re, cc, startcode, options, recurse_depth);
|
||||
d = find_minlength(re, cc, startcode, options, recurses);
|
||||
if (d < 0) return d;
|
||||
branchlength += d;
|
||||
do cc += GET(cc, 1); while (*cc == OP_ALT);
|
||||
@@ -393,7 +394,7 @@ for (;;)
|
||||
ce = cs = (pcre_uchar *)PRIV(find_bracket)(startcode, utf, GET2(slot, 0));
|
||||
if (cs == NULL) return -2;
|
||||
do ce += GET(ce, 1); while (*ce == OP_ALT);
|
||||
if (cc > cs && cc < ce)
|
||||
if (cc > cs && cc < ce) /* Simple recursion */
|
||||
{
|
||||
d = 0;
|
||||
had_recurse = TRUE;
|
||||
@@ -401,8 +402,22 @@ for (;;)
|
||||
}
|
||||
else
|
||||
{
|
||||
int dd = find_minlength(re, cs, startcode, options, recurse_depth);
|
||||
if (dd < d) d = dd;
|
||||
recurse_check *r = recurses;
|
||||
for (r = recurses; r != NULL; r = r->prev) if (r->group == cs) break;
|
||||
if (r != NULL) /* Mutual recursion */
|
||||
{
|
||||
d = 0;
|
||||
had_recurse = TRUE;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
int dd;
|
||||
this_recurse.prev = recurses;
|
||||
this_recurse.group = cs;
|
||||
dd = find_minlength(re, cs, startcode, options, &this_recurse);
|
||||
if (dd < d) d = dd;
|
||||
}
|
||||
}
|
||||
slot += re->name_entry_size;
|
||||
}
|
||||
@@ -418,14 +433,26 @@ for (;;)
|
||||
ce = cs = (pcre_uchar *)PRIV(find_bracket)(startcode, utf, GET2(cc, 1));
|
||||
if (cs == NULL) return -2;
|
||||
do ce += GET(ce, 1); while (*ce == OP_ALT);
|
||||
if (cc > cs && cc < ce)
|
||||
if (cc > cs && cc < ce) /* Simple recursion */
|
||||
{
|
||||
d = 0;
|
||||
had_recurse = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
d = find_minlength(re, cs, startcode, options, recurse_depth);
|
||||
recurse_check *r = recurses;
|
||||
for (r = recurses; r != NULL; r = r->prev) if (r->group == cs) break;
|
||||
if (r != NULL) /* Mutual recursion */
|
||||
{
|
||||
d = 0;
|
||||
had_recurse = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
this_recurse.prev = recurses;
|
||||
this_recurse.group = cs;
|
||||
d = find_minlength(re, cs, startcode, options, &this_recurse);
|
||||
}
|
||||
}
|
||||
}
|
||||
else d = 0;
|
||||
@@ -474,12 +501,21 @@ for (;;)
|
||||
case OP_RECURSE:
|
||||
cs = ce = (pcre_uchar *)startcode + GET(cc, 1);
|
||||
do ce += GET(ce, 1); while (*ce == OP_ALT);
|
||||
if ((cc > cs && cc < ce) || recurse_depth > 10)
|
||||
if (cc > cs && cc < ce) /* Simple recursion */
|
||||
had_recurse = TRUE;
|
||||
else
|
||||
{
|
||||
branchlength += find_minlength(re, cs, startcode, options,
|
||||
recurse_depth + 1);
|
||||
recurse_check *r = recurses;
|
||||
for (r = recurses; r != NULL; r = r->prev) if (r->group == cs) break;
|
||||
if (r != NULL) /* Mutual recursion */
|
||||
had_recurse = TRUE;
|
||||
else
|
||||
{
|
||||
this_recurse.prev = recurses;
|
||||
this_recurse.group = cs;
|
||||
branchlength += find_minlength(re, cs, startcode, options,
|
||||
&this_recurse);
|
||||
}
|
||||
}
|
||||
cc += 1 + LINK_SIZE;
|
||||
break;
|
||||
@@ -1503,7 +1539,7 @@ if ((re->options & PCRE_ANCHORED) == 0 &&
|
||||
|
||||
/* Find the minimum length of subject string. */
|
||||
|
||||
switch(min = find_minlength(re, code, code, re->options, 0))
|
||||
switch(min = find_minlength(re, code, code, re->options, NULL))
|
||||
{
|
||||
case -2: *errorptr = "internal error: missing capturing bracket"; return NULL;
|
||||
case -3: *errorptr = "internal error: opcode not recognized"; return NULL;
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SLJIT_CONFIG_H_
|
||||
#define _SLJIT_CONFIG_H_
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Custom defines */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* Put your custom defines here. This empty section will never change
|
||||
which helps maintaining patches (with diff / patch utilities). */
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Architecture */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* Architecture selection. */
|
||||
/* #define SLJIT_CONFIG_X86_32 1 */
|
||||
/* #define SLJIT_CONFIG_X86_64 1 */
|
||||
/* #define SLJIT_CONFIG_ARM_V5 1 */
|
||||
/* #define SLJIT_CONFIG_ARM_V7 1 */
|
||||
/* #define SLJIT_CONFIG_ARM_THUMB2 1 */
|
||||
/* #define SLJIT_CONFIG_ARM_64 1 */
|
||||
/* #define SLJIT_CONFIG_PPC_32 1 */
|
||||
/* #define SLJIT_CONFIG_PPC_64 1 */
|
||||
/* #define SLJIT_CONFIG_MIPS_32 1 */
|
||||
/* #define SLJIT_CONFIG_MIPS_64 1 */
|
||||
/* #define SLJIT_CONFIG_SPARC_32 1 */
|
||||
/* #define SLJIT_CONFIG_TILEGX 1 */
|
||||
|
||||
/* #define SLJIT_CONFIG_AUTO 1 */
|
||||
/* #define SLJIT_CONFIG_UNSUPPORTED 1 */
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Utilities */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* Useful for thread-safe compiling of global functions. */
|
||||
#ifndef SLJIT_UTIL_GLOBAL_LOCK
|
||||
/* Enabled by default */
|
||||
#define SLJIT_UTIL_GLOBAL_LOCK 1
|
||||
#endif
|
||||
|
||||
/* Implements a stack like data structure (by using mmap / VirtualAlloc). */
|
||||
#ifndef SLJIT_UTIL_STACK
|
||||
/* Enabled by default */
|
||||
#define SLJIT_UTIL_STACK 1
|
||||
#endif
|
||||
|
||||
/* Single threaded application. Does not require any locks. */
|
||||
#ifndef SLJIT_SINGLE_THREADED
|
||||
/* Disabled by default. */
|
||||
#define SLJIT_SINGLE_THREADED 0
|
||||
#endif
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Configuration */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* If SLJIT_STD_MACROS_DEFINED is not defined, the application should
|
||||
define SLJIT_MALLOC, SLJIT_FREE, SLJIT_MEMMOVE, and NULL. */
|
||||
#ifndef SLJIT_STD_MACROS_DEFINED
|
||||
/* Disabled by default. */
|
||||
#define SLJIT_STD_MACROS_DEFINED 0
|
||||
#endif
|
||||
|
||||
/* Executable code allocation:
|
||||
If SLJIT_EXECUTABLE_ALLOCATOR is not defined, the application should
|
||||
define both SLJIT_MALLOC_EXEC and SLJIT_FREE_EXEC. */
|
||||
#ifndef SLJIT_EXECUTABLE_ALLOCATOR
|
||||
/* Enabled by default. */
|
||||
#define SLJIT_EXECUTABLE_ALLOCATOR 1
|
||||
#endif
|
||||
|
||||
/* Return with error when an invalid argument is passed. */
|
||||
#ifndef SLJIT_ARGUMENT_CHECKS
|
||||
/* Disabled by default */
|
||||
#define SLJIT_ARGUMENT_CHECKS 0
|
||||
#endif
|
||||
|
||||
/* Debug checks (assertions, etc.). */
|
||||
#ifndef SLJIT_DEBUG
|
||||
/* Enabled by default */
|
||||
#define SLJIT_DEBUG 1
|
||||
#endif
|
||||
|
||||
/* Verbose operations. */
|
||||
#ifndef SLJIT_VERBOSE
|
||||
/* Enabled by default */
|
||||
#define SLJIT_VERBOSE 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
SLJIT_IS_FPU_AVAILABLE
|
||||
The availability of the FPU can be controlled by SLJIT_IS_FPU_AVAILABLE.
|
||||
zero value - FPU is NOT present.
|
||||
nonzero value - FPU is present.
|
||||
*/
|
||||
|
||||
/* For further configurations, see the beginning of sljitConfigInternal.h */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,702 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SLJIT_CONFIG_INTERNAL_H_
|
||||
#define _SLJIT_CONFIG_INTERNAL_H_
|
||||
|
||||
/*
|
||||
SLJIT defines the following architecture dependent types and macros:
|
||||
|
||||
Types:
|
||||
sljit_sb, sljit_ub : signed and unsigned 8 bit byte
|
||||
sljit_sh, sljit_uh : signed and unsigned 16 bit half-word (short) type
|
||||
sljit_si, sljit_ui : signed and unsigned 32 bit integer type
|
||||
sljit_sw, sljit_uw : signed and unsigned machine word, enough to store a pointer
|
||||
sljit_p : unsgined pointer value (usually the same as sljit_uw, but
|
||||
some 64 bit ABIs may use 32 bit pointers)
|
||||
sljit_s : single precision floating point value
|
||||
sljit_d : double precision floating point value
|
||||
|
||||
Macros for feature detection (boolean):
|
||||
SLJIT_32BIT_ARCHITECTURE : 32 bit architecture
|
||||
SLJIT_64BIT_ARCHITECTURE : 64 bit architecture
|
||||
SLJIT_LITTLE_ENDIAN : little endian architecture
|
||||
SLJIT_BIG_ENDIAN : big endian architecture
|
||||
SLJIT_UNALIGNED : allows unaligned memory accesses for non-fpu operations (only!)
|
||||
SLJIT_INDIRECT_CALL : see SLJIT_FUNC_OFFSET() for more information
|
||||
|
||||
Constants:
|
||||
SLJIT_NUMBER_OF_REGISTERS : number of available registers
|
||||
SLJIT_NUMBER_OF_SCRATCH_REGISTERS : number of available scratch registers
|
||||
SLJIT_NUMBER_OF_SAVED_REGISTERS : number of available saved registers
|
||||
SLJIT_NUMBER_OF_FLOAT_REGISTERS : number of available floating point registers
|
||||
SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS : number of available floating point scratch registers
|
||||
SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS : number of available floating point saved registers
|
||||
SLJIT_WORD_SHIFT : the shift required to apply when accessing a sljit_sw/sljit_uw array by index
|
||||
SLJIT_DOUBLE_SHIFT : the shift required to apply when accessing
|
||||
a double precision floating point array by index
|
||||
SLJIT_SINGLE_SHIFT : the shift required to apply when accessing
|
||||
a single precision floating point array by index
|
||||
SLJIT_LOCALS_OFFSET : local space starting offset (SLJIT_SP + SLJIT_LOCALS_OFFSET)
|
||||
SLJIT_RETURN_ADDRESS_OFFSET : a return instruction always adds this offset to the return address
|
||||
|
||||
Other macros:
|
||||
SLJIT_CALL : C calling convention define for both calling JIT form C and C callbacks for JIT
|
||||
SLJIT_W(number) : defining 64 bit constants on 64 bit architectures (compiler independent helper)
|
||||
*/
|
||||
|
||||
/*****************/
|
||||
/* Sanity check. */
|
||||
/*****************/
|
||||
|
||||
#if !((defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \
|
||||
|| (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \
|
||||
|| (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) \
|
||||
|| (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \
|
||||
|| (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \
|
||||
|| (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
|
||||
|| (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \
|
||||
|| (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \
|
||||
|| (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \
|
||||
|| (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \
|
||||
|| (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \
|
||||
|| (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX) \
|
||||
|| (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \
|
||||
|| (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED))
|
||||
#error "An architecture must be selected"
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \
|
||||
+ (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \
|
||||
+ (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) \
|
||||
+ (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \
|
||||
+ (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \
|
||||
+ (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
|
||||
+ (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \
|
||||
+ (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \
|
||||
+ (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX) \
|
||||
+ (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \
|
||||
+ (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \
|
||||
+ (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \
|
||||
+ (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \
|
||||
+ (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) >= 2
|
||||
#error "Multiple architectures are selected"
|
||||
#endif
|
||||
|
||||
/********************************************************/
|
||||
/* Automatic CPU detection (requires compiler support). */
|
||||
/********************************************************/
|
||||
|
||||
#if (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO)
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#if defined(__i386__) || defined(__i386)
|
||||
#define SLJIT_CONFIG_X86_32 1
|
||||
#elif defined(__x86_64__)
|
||||
#define SLJIT_CONFIG_X86_64 1
|
||||
#elif defined(__arm__) || defined(__ARM__)
|
||||
#ifdef __thumb2__
|
||||
#define SLJIT_CONFIG_ARM_THUMB2 1
|
||||
#elif defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__)
|
||||
#define SLJIT_CONFIG_ARM_V7 1
|
||||
#else
|
||||
#define SLJIT_CONFIG_ARM_V5 1
|
||||
#endif
|
||||
#elif defined (__aarch64__)
|
||||
#define SLJIT_CONFIG_ARM_64 1
|
||||
#elif defined(__ppc64__) || defined(__powerpc64__) || defined(_ARCH_PPC64) || (defined(_POWER) && defined(__64BIT__))
|
||||
#define SLJIT_CONFIG_PPC_64 1
|
||||
#elif defined(__ppc__) || defined(__powerpc__) || defined(_ARCH_PPC) || defined(_ARCH_PWR) || defined(_ARCH_PWR2) || defined(_POWER)
|
||||
#define SLJIT_CONFIG_PPC_32 1
|
||||
#elif defined(__mips__) && !defined(_LP64)
|
||||
#define SLJIT_CONFIG_MIPS_32 1
|
||||
#elif defined(__mips64)
|
||||
#define SLJIT_CONFIG_MIPS_64 1
|
||||
#elif defined(__sparc__) || defined(__sparc)
|
||||
#define SLJIT_CONFIG_SPARC_32 1
|
||||
#elif defined(__tilegx__)
|
||||
#define SLJIT_CONFIG_TILEGX 1
|
||||
#else
|
||||
/* Unsupported architecture */
|
||||
#define SLJIT_CONFIG_UNSUPPORTED 1
|
||||
#endif
|
||||
|
||||
#else /* !_WIN32 */
|
||||
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
#define SLJIT_CONFIG_X86_64 1
|
||||
#elif defined(_ARM_)
|
||||
#define SLJIT_CONFIG_ARM_V5 1
|
||||
#else
|
||||
#define SLJIT_CONFIG_X86_32 1
|
||||
#endif
|
||||
|
||||
#endif /* !WIN32 */
|
||||
#endif /* SLJIT_CONFIG_AUTO */
|
||||
|
||||
#if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
|
||||
#undef SLJIT_EXECUTABLE_ALLOCATOR
|
||||
#endif
|
||||
|
||||
/******************************/
|
||||
/* CPU family type detection. */
|
||||
/******************************/
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \
|
||||
|| (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
|
||||
#define SLJIT_CONFIG_ARM_32 1
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
#define SLJIT_CONFIG_X86 1
|
||||
#elif (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) || (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
|
||||
#define SLJIT_CONFIG_ARM 1
|
||||
#elif (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
#define SLJIT_CONFIG_PPC 1
|
||||
#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) || (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||
#define SLJIT_CONFIG_MIPS 1
|
||||
#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) || (defined SLJIT_CONFIG_SPARC_64 && SLJIT_CONFIG_SPARC_64)
|
||||
#define SLJIT_CONFIG_SPARC 1
|
||||
#endif
|
||||
|
||||
/**********************************/
|
||||
/* External function definitions. */
|
||||
/**********************************/
|
||||
|
||||
#if !(defined SLJIT_STD_MACROS_DEFINED && SLJIT_STD_MACROS_DEFINED)
|
||||
|
||||
/* These libraries are needed for the macros below. */
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#endif /* SLJIT_STD_MACROS_DEFINED */
|
||||
|
||||
/* General macros:
|
||||
Note: SLJIT is designed to be independent from them as possible.
|
||||
|
||||
In release mode (SLJIT_DEBUG is not defined) only the following
|
||||
external functions are needed:
|
||||
*/
|
||||
|
||||
#ifndef SLJIT_MALLOC
|
||||
#define SLJIT_MALLOC(size, allocator_data) malloc(size)
|
||||
#endif
|
||||
|
||||
#ifndef SLJIT_FREE
|
||||
#define SLJIT_FREE(ptr, allocator_data) free(ptr)
|
||||
#endif
|
||||
|
||||
#ifndef SLJIT_MEMMOVE
|
||||
#define SLJIT_MEMMOVE(dest, src, len) memmove(dest, src, len)
|
||||
#endif
|
||||
|
||||
#ifndef SLJIT_ZEROMEM
|
||||
#define SLJIT_ZEROMEM(dest, len) memset(dest, 0, len)
|
||||
#endif
|
||||
|
||||
/***************************/
|
||||
/* Compiler helper macros. */
|
||||
/***************************/
|
||||
|
||||
#if !defined(SLJIT_LIKELY) && !defined(SLJIT_UNLIKELY)
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ >= 3)
|
||||
#define SLJIT_LIKELY(x) __builtin_expect((x), 1)
|
||||
#define SLJIT_UNLIKELY(x) __builtin_expect((x), 0)
|
||||
#else
|
||||
#define SLJIT_LIKELY(x) (x)
|
||||
#define SLJIT_UNLIKELY(x) (x)
|
||||
#endif
|
||||
|
||||
#endif /* !defined(SLJIT_LIKELY) && !defined(SLJIT_UNLIKELY) */
|
||||
|
||||
#ifndef SLJIT_INLINE
|
||||
/* Inline functions. Some old compilers do not support them. */
|
||||
#if defined(__SUNPRO_C) && __SUNPRO_C <= 0x510
|
||||
#define SLJIT_INLINE
|
||||
#else
|
||||
#define SLJIT_INLINE __inline
|
||||
#endif
|
||||
#endif /* !SLJIT_INLINE */
|
||||
|
||||
#ifndef SLJIT_NOINLINE
|
||||
/* Not inline functions. */
|
||||
#if defined(__GNUC__)
|
||||
#define SLJIT_NOINLINE __attribute__ ((noinline))
|
||||
#else
|
||||
#define SLJIT_NOINLINE
|
||||
#endif
|
||||
#endif /* !SLJIT_INLINE */
|
||||
|
||||
#ifndef SLJIT_CONST
|
||||
/* Const variables. */
|
||||
#define SLJIT_CONST const
|
||||
#endif
|
||||
|
||||
#ifndef SLJIT_UNUSED_ARG
|
||||
/* Unused arguments. */
|
||||
#define SLJIT_UNUSED_ARG(arg) (void)arg
|
||||
#endif
|
||||
|
||||
/*********************************/
|
||||
/* Type of public API functions. */
|
||||
/*********************************/
|
||||
|
||||
#if (defined SLJIT_CONFIG_STATIC && SLJIT_CONFIG_STATIC)
|
||||
/* Static ABI functions. For all-in-one programs. */
|
||||
|
||||
#if defined(__GNUC__)
|
||||
/* Disable unused warnings in gcc. */
|
||||
#define SLJIT_API_FUNC_ATTRIBUTE static __attribute__((unused))
|
||||
#else
|
||||
#define SLJIT_API_FUNC_ATTRIBUTE static
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define SLJIT_API_FUNC_ATTRIBUTE
|
||||
#endif /* (defined SLJIT_CONFIG_STATIC && SLJIT_CONFIG_STATIC) */
|
||||
|
||||
/****************************/
|
||||
/* Instruction cache flush. */
|
||||
/****************************/
|
||||
|
||||
#ifndef SLJIT_CACHE_FLUSH
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
|
||||
|
||||
/* Not required to implement on archs with unified caches. */
|
||||
#define SLJIT_CACHE_FLUSH(from, to)
|
||||
|
||||
#elif defined __APPLE__
|
||||
|
||||
/* Supported by all macs since Mac OS 10.5.
|
||||
However, it does not work on non-jailbroken iOS devices,
|
||||
although the compilation is successful. */
|
||||
|
||||
#define SLJIT_CACHE_FLUSH(from, to) \
|
||||
sys_icache_invalidate((char*)(from), (char*)(to) - (char*)(from))
|
||||
|
||||
#elif defined __ANDROID__
|
||||
|
||||
/* Android lacks __clear_cache; instead, cacheflush should be used. */
|
||||
|
||||
#define SLJIT_CACHE_FLUSH(from, to) \
|
||||
cacheflush((long)(from), (long)(to), 0)
|
||||
|
||||
#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
|
||||
|
||||
/* The __clear_cache() implementation of GCC is a dummy function on PowerPC. */
|
||||
#define SLJIT_CACHE_FLUSH(from, to) \
|
||||
ppc_cache_flush((from), (to))
|
||||
|
||||
#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
|
||||
|
||||
/* The __clear_cache() implementation of GCC is a dummy function on Sparc. */
|
||||
#define SLJIT_CACHE_FLUSH(from, to) \
|
||||
sparc_cache_flush((from), (to))
|
||||
|
||||
#else
|
||||
|
||||
/* Calls __ARM_NR_cacheflush on ARM-Linux. */
|
||||
#define SLJIT_CACHE_FLUSH(from, to) \
|
||||
__clear_cache((char*)(from), (char*)(to))
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* !SLJIT_CACHE_FLUSH */
|
||||
|
||||
/******************************************************/
|
||||
/* Byte/half/int/word/single/double type definitions. */
|
||||
/******************************************************/
|
||||
|
||||
/* 8 bit byte type. */
|
||||
typedef unsigned char sljit_ub;
|
||||
typedef signed char sljit_sb;
|
||||
|
||||
/* 16 bit half-word type. */
|
||||
typedef unsigned short int sljit_uh;
|
||||
typedef signed short int sljit_sh;
|
||||
|
||||
/* 32 bit integer type. */
|
||||
typedef unsigned int sljit_ui;
|
||||
typedef signed int sljit_si;
|
||||
|
||||
/* Machine word type. Enough for storing a pointer.
|
||||
32 bit for 32 bit machines.
|
||||
64 bit for 64 bit machines. */
|
||||
#if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
|
||||
/* Just to have something. */
|
||||
#define SLJIT_WORD_SHIFT 0
|
||||
typedef unsigned long int sljit_uw;
|
||||
typedef long int sljit_sw;
|
||||
#elif !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \
|
||||
&& !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
|
||||
&& !(defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \
|
||||
&& !(defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \
|
||||
&& !(defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX)
|
||||
#define SLJIT_32BIT_ARCHITECTURE 1
|
||||
#define SLJIT_WORD_SHIFT 2
|
||||
typedef unsigned int sljit_uw;
|
||||
typedef int sljit_sw;
|
||||
#else
|
||||
#define SLJIT_64BIT_ARCHITECTURE 1
|
||||
#define SLJIT_WORD_SHIFT 3
|
||||
#ifdef _WIN32
|
||||
typedef unsigned __int64 sljit_uw;
|
||||
typedef __int64 sljit_sw;
|
||||
#else
|
||||
typedef unsigned long int sljit_uw;
|
||||
typedef long int sljit_sw;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef sljit_uw sljit_p;
|
||||
|
||||
/* Floating point types. */
|
||||
typedef float sljit_s;
|
||||
typedef double sljit_d;
|
||||
|
||||
/* Shift for pointer sized data. */
|
||||
#define SLJIT_POINTER_SHIFT SLJIT_WORD_SHIFT
|
||||
|
||||
/* Shift for double precision sized data. */
|
||||
#define SLJIT_DOUBLE_SHIFT 3
|
||||
#define SLJIT_SINGLE_SHIFT 2
|
||||
|
||||
#ifndef SLJIT_W
|
||||
|
||||
/* Defining long constants. */
|
||||
#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
|
||||
#define SLJIT_W(w) (w##ll)
|
||||
#else
|
||||
#define SLJIT_W(w) (w)
|
||||
#endif
|
||||
|
||||
#endif /* !SLJIT_W */
|
||||
|
||||
/*************************/
|
||||
/* Endianness detection. */
|
||||
/*************************/
|
||||
|
||||
#if !defined(SLJIT_BIG_ENDIAN) && !defined(SLJIT_LITTLE_ENDIAN)
|
||||
|
||||
/* These macros are mostly useful for the applications. */
|
||||
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \
|
||||
|| (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
#define SLJIT_LITTLE_ENDIAN 1
|
||||
#else
|
||||
#define SLJIT_BIG_ENDIAN 1
|
||||
#endif
|
||||
|
||||
#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \
|
||||
|| (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||
|
||||
#ifdef __MIPSEL__
|
||||
#define SLJIT_LITTLE_ENDIAN 1
|
||||
#else
|
||||
#define SLJIT_BIG_ENDIAN 1
|
||||
#endif
|
||||
|
||||
#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
|
||||
|
||||
#define SLJIT_BIG_ENDIAN 1
|
||||
|
||||
#else
|
||||
#define SLJIT_LITTLE_ENDIAN 1
|
||||
#endif
|
||||
|
||||
#endif /* !defined(SLJIT_BIG_ENDIAN) && !defined(SLJIT_LITTLE_ENDIAN) */
|
||||
|
||||
/* Sanity check. */
|
||||
#if (defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN) && (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
|
||||
#error "Exactly one endianness must be selected"
|
||||
#endif
|
||||
|
||||
#if !(defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN) && !(defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
|
||||
#error "Exactly one endianness must be selected"
|
||||
#endif
|
||||
|
||||
#ifndef SLJIT_UNALIGNED
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \
|
||||
|| (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \
|
||||
|| (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \
|
||||
|| (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \
|
||||
|| (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
|
||||
|| (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \
|
||||
|| (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
#define SLJIT_UNALIGNED 1
|
||||
#endif
|
||||
|
||||
#endif /* !SLJIT_UNALIGNED */
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
/* Auto detect SSE2 support using CPUID.
|
||||
On 64 bit x86 cpus, sse2 must be present. */
|
||||
#define SLJIT_DETECT_SSE2 1
|
||||
#endif
|
||||
|
||||
/*****************************************************************************************/
|
||||
/* Calling convention of functions generated by SLJIT or called from the generated code. */
|
||||
/*****************************************************************************************/
|
||||
|
||||
#ifndef SLJIT_CALL
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
|
||||
#if defined(__GNUC__) && !defined(__APPLE__)
|
||||
|
||||
#define SLJIT_CALL __attribute__ ((fastcall))
|
||||
#define SLJIT_X86_32_FASTCALL 1
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
|
||||
#define SLJIT_CALL __fastcall
|
||||
#define SLJIT_X86_32_FASTCALL 1
|
||||
|
||||
#elif defined(__BORLANDC__)
|
||||
|
||||
#define SLJIT_CALL __msfastcall
|
||||
#define SLJIT_X86_32_FASTCALL 1
|
||||
|
||||
#else /* Unknown compiler. */
|
||||
|
||||
/* The cdecl attribute is the default. */
|
||||
#define SLJIT_CALL
|
||||
|
||||
#endif
|
||||
|
||||
#else /* Non x86-32 architectures. */
|
||||
|
||||
#define SLJIT_CALL
|
||||
|
||||
#endif /* SLJIT_CONFIG_X86_32 */
|
||||
|
||||
#endif /* !SLJIT_CALL */
|
||||
|
||||
#ifndef SLJIT_INDIRECT_CALL
|
||||
#if ((defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) && (defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN)) \
|
||||
|| ((defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) && defined _AIX)
|
||||
/* It seems certain ppc compilers use an indirect addressing for functions
|
||||
which makes things complicated. */
|
||||
#define SLJIT_INDIRECT_CALL 1
|
||||
#endif
|
||||
#endif /* SLJIT_INDIRECT_CALL */
|
||||
|
||||
/* The offset which needs to be substracted from the return address to
|
||||
determine the next executed instruction after return. */
|
||||
#ifndef SLJIT_RETURN_ADDRESS_OFFSET
|
||||
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
|
||||
#define SLJIT_RETURN_ADDRESS_OFFSET 8
|
||||
#else
|
||||
#define SLJIT_RETURN_ADDRESS_OFFSET 0
|
||||
#endif
|
||||
#endif /* SLJIT_RETURN_ADDRESS_OFFSET */
|
||||
|
||||
/***************************************************/
|
||||
/* Functions of the built-in executable allocator. */
|
||||
/***************************************************/
|
||||
|
||||
#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size);
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr);
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void);
|
||||
#define SLJIT_MALLOC_EXEC(size) sljit_malloc_exec(size)
|
||||
#define SLJIT_FREE_EXEC(ptr) sljit_free_exec(ptr)
|
||||
#endif
|
||||
|
||||
/**********************************************/
|
||||
/* Registers and locals offset determination. */
|
||||
/**********************************************/
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 10
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 7
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
#define SLJIT_LOCALS_OFFSET_BASE ((2 + 4) * sizeof(sljit_sw))
|
||||
#else
|
||||
/* Maximum 3 arguments are passed on the stack, +1 for double alignment. */
|
||||
#define SLJIT_LOCALS_OFFSET_BASE ((3 + 1 + 4) * sizeof(sljit_sw))
|
||||
#endif /* SLJIT_X86_32_FASTCALL */
|
||||
|
||||
#elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
|
||||
#ifndef _WIN64
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 12
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 6
|
||||
#define SLJIT_LOCALS_OFFSET_BASE (sizeof(sljit_sw))
|
||||
#else
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 12
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
|
||||
#define SLJIT_LOCALS_OFFSET_BASE ((4 + 2) * sizeof(sljit_sw))
|
||||
#endif /* _WIN64 */
|
||||
|
||||
#elif (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
|
||||
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 11
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
|
||||
#define SLJIT_LOCALS_OFFSET_BASE 0
|
||||
|
||||
#elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
|
||||
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 11
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 7
|
||||
#define SLJIT_LOCALS_OFFSET_BASE 0
|
||||
|
||||
#elif (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
|
||||
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 25
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 10
|
||||
#define SLJIT_LOCALS_OFFSET_BASE (2 * sizeof(sljit_sw))
|
||||
|
||||
#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
|
||||
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 22
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 17
|
||||
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) || (defined _AIX)
|
||||
#define SLJIT_LOCALS_OFFSET_BASE ((6 + 8) * sizeof(sljit_sw))
|
||||
#elif (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
|
||||
/* Add +1 for double alignment. */
|
||||
#define SLJIT_LOCALS_OFFSET_BASE ((3 + 1) * sizeof(sljit_sw))
|
||||
#else
|
||||
#define SLJIT_LOCALS_OFFSET_BASE (3 * sizeof(sljit_sw))
|
||||
#endif /* SLJIT_CONFIG_PPC_64 || _AIX */
|
||||
|
||||
#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
|
||||
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 17
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
#define SLJIT_LOCALS_OFFSET_BASE (4 * sizeof(sljit_sw))
|
||||
#else
|
||||
#define SLJIT_LOCALS_OFFSET_BASE 0
|
||||
#endif
|
||||
|
||||
#elif (defined SLJIT_CONFIG_SPARC && SLJIT_CONFIG_SPARC)
|
||||
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 18
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 14
|
||||
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
|
||||
/* Add +1 for double alignment. */
|
||||
#define SLJIT_LOCALS_OFFSET_BASE ((23 + 1) * sizeof(sljit_sw))
|
||||
#endif
|
||||
|
||||
#elif (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
|
||||
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 0
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 0
|
||||
#define SLJIT_LOCALS_OFFSET_BASE 0
|
||||
|
||||
#endif
|
||||
|
||||
#define SLJIT_LOCALS_OFFSET (SLJIT_LOCALS_OFFSET_BASE)
|
||||
|
||||
#define SLJIT_NUMBER_OF_SCRATCH_REGISTERS \
|
||||
(SLJIT_NUMBER_OF_REGISTERS - SLJIT_NUMBER_OF_SAVED_REGISTERS)
|
||||
|
||||
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 6
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && (defined _WIN64)
|
||||
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 1
|
||||
#else
|
||||
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0
|
||||
#endif
|
||||
|
||||
#define SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS \
|
||||
(SLJIT_NUMBER_OF_FLOAT_REGISTERS - SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS)
|
||||
|
||||
/*************************************/
|
||||
/* Debug and verbose related macros. */
|
||||
/*************************************/
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
|
||||
#if !defined(SLJIT_ASSERT) || !defined(SLJIT_ASSERT_STOP)
|
||||
|
||||
/* SLJIT_HALT_PROCESS must halt the process. */
|
||||
#ifndef SLJIT_HALT_PROCESS
|
||||
#include <stdlib.h>
|
||||
|
||||
#define SLJIT_HALT_PROCESS() \
|
||||
abort();
|
||||
#endif /* !SLJIT_HALT_PROCESS */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#endif /* !SLJIT_ASSERT || !SLJIT_ASSERT_STOP */
|
||||
|
||||
/* Feel free to redefine these two macros. */
|
||||
#ifndef SLJIT_ASSERT
|
||||
|
||||
#define SLJIT_ASSERT(x) \
|
||||
do { \
|
||||
if (SLJIT_UNLIKELY(!(x))) { \
|
||||
printf("Assertion failed at " __FILE__ ":%d\n", __LINE__); \
|
||||
SLJIT_HALT_PROCESS(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif /* !SLJIT_ASSERT */
|
||||
|
||||
#ifndef SLJIT_ASSERT_STOP
|
||||
|
||||
#define SLJIT_ASSERT_STOP() \
|
||||
do { \
|
||||
printf("Should never been reached " __FILE__ ":%d\n", __LINE__); \
|
||||
SLJIT_HALT_PROCESS(); \
|
||||
} while (0)
|
||||
|
||||
#endif /* !SLJIT_ASSERT_STOP */
|
||||
|
||||
#else /* (defined SLJIT_DEBUG && SLJIT_DEBUG) */
|
||||
|
||||
/* Forcing empty, but valid statements. */
|
||||
#undef SLJIT_ASSERT
|
||||
#undef SLJIT_ASSERT_STOP
|
||||
|
||||
#define SLJIT_ASSERT(x) \
|
||||
do { } while (0)
|
||||
#define SLJIT_ASSERT_STOP() \
|
||||
do { } while (0)
|
||||
|
||||
#endif /* (defined SLJIT_DEBUG && SLJIT_DEBUG) */
|
||||
|
||||
#ifndef SLJIT_COMPILE_ASSERT
|
||||
|
||||
/* Should be improved eventually. */
|
||||
#define SLJIT_COMPILE_ASSERT(x, description) \
|
||||
SLJIT_ASSERT(x)
|
||||
|
||||
#endif /* !SLJIT_COMPILE_ASSERT */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,312 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
This file contains a simple executable memory allocator
|
||||
|
||||
It is assumed, that executable code blocks are usually medium (or sometimes
|
||||
large) memory blocks, and the allocator is not too frequently called (less
|
||||
optimized than other allocators). Thus, using it as a generic allocator is
|
||||
not suggested.
|
||||
|
||||
How does it work:
|
||||
Memory is allocated in continuous memory areas called chunks by alloc_chunk()
|
||||
Chunk format:
|
||||
[ block ][ block ] ... [ block ][ block terminator ]
|
||||
|
||||
All blocks and the block terminator is started with block_header. The block
|
||||
header contains the size of the previous and the next block. These sizes
|
||||
can also contain special values.
|
||||
Block size:
|
||||
0 - The block is a free_block, with a different size member.
|
||||
1 - The block is a block terminator.
|
||||
n - The block is used at the moment, and the value contains its size.
|
||||
Previous block size:
|
||||
0 - This is the first block of the memory chunk.
|
||||
n - The size of the previous block.
|
||||
|
||||
Using these size values we can go forward or backward on the block chain.
|
||||
The unused blocks are stored in a chain list pointed by free_blocks. This
|
||||
list is useful if we need to find a suitable memory area when the allocator
|
||||
is called.
|
||||
|
||||
When a block is freed, the new free block is connected to its adjacent free
|
||||
blocks if possible.
|
||||
|
||||
[ free block ][ used block ][ free block ]
|
||||
and "used block" is freed, the three blocks are connected together:
|
||||
[ one big free block ]
|
||||
*/
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* System (OS) functions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* 64 KByte. */
|
||||
#define CHUNK_SIZE 0x10000
|
||||
|
||||
/*
|
||||
alloc_chunk / free_chunk :
|
||||
* allocate executable system memory chunks
|
||||
* the size is always divisible by CHUNK_SIZE
|
||||
allocator_grab_lock / allocator_release_lock :
|
||||
* make the allocator thread safe
|
||||
* can be empty if the OS (or the application) does not support threading
|
||||
* only the allocator requires this lock, sljit is fully thread safe
|
||||
as it only uses local variables
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
|
||||
{
|
||||
return VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void free_chunk(void* chunk, sljit_uw size)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(size);
|
||||
VirtualFree(chunk, 0, MEM_RELEASE);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
|
||||
{
|
||||
void* retval;
|
||||
|
||||
#ifdef MAP_ANON
|
||||
retval = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
#else
|
||||
if (dev_zero < 0) {
|
||||
if (open_dev_zero())
|
||||
return NULL;
|
||||
}
|
||||
retval = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, dev_zero, 0);
|
||||
#endif
|
||||
|
||||
return (retval != MAP_FAILED) ? retval : NULL;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void free_chunk(void* chunk, sljit_uw size)
|
||||
{
|
||||
munmap(chunk, size);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Common functions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
#define CHUNK_MASK (~(CHUNK_SIZE - 1))
|
||||
|
||||
struct block_header {
|
||||
sljit_uw size;
|
||||
sljit_uw prev_size;
|
||||
};
|
||||
|
||||
struct free_block {
|
||||
struct block_header header;
|
||||
struct free_block *next;
|
||||
struct free_block *prev;
|
||||
sljit_uw size;
|
||||
};
|
||||
|
||||
#define AS_BLOCK_HEADER(base, offset) \
|
||||
((struct block_header*)(((sljit_ub*)base) + offset))
|
||||
#define AS_FREE_BLOCK(base, offset) \
|
||||
((struct free_block*)(((sljit_ub*)base) + offset))
|
||||
#define MEM_START(base) ((void*)(((sljit_ub*)base) + sizeof(struct block_header)))
|
||||
#define ALIGN_SIZE(size) (((size) + sizeof(struct block_header) + 7) & ~7)
|
||||
|
||||
static struct free_block* free_blocks;
|
||||
static sljit_uw allocated_size;
|
||||
static sljit_uw total_size;
|
||||
|
||||
static SLJIT_INLINE void sljit_insert_free_block(struct free_block *free_block, sljit_uw size)
|
||||
{
|
||||
free_block->header.size = 0;
|
||||
free_block->size = size;
|
||||
|
||||
free_block->next = free_blocks;
|
||||
free_block->prev = 0;
|
||||
if (free_blocks)
|
||||
free_blocks->prev = free_block;
|
||||
free_blocks = free_block;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void sljit_remove_free_block(struct free_block *free_block)
|
||||
{
|
||||
if (free_block->next)
|
||||
free_block->next->prev = free_block->prev;
|
||||
|
||||
if (free_block->prev)
|
||||
free_block->prev->next = free_block->next;
|
||||
else {
|
||||
SLJIT_ASSERT(free_blocks == free_block);
|
||||
free_blocks = free_block->next;
|
||||
}
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)
|
||||
{
|
||||
struct block_header *header;
|
||||
struct block_header *next_header;
|
||||
struct free_block *free_block;
|
||||
sljit_uw chunk_size;
|
||||
|
||||
allocator_grab_lock();
|
||||
if (size < sizeof(struct free_block))
|
||||
size = sizeof(struct free_block);
|
||||
size = ALIGN_SIZE(size);
|
||||
|
||||
free_block = free_blocks;
|
||||
while (free_block) {
|
||||
if (free_block->size >= size) {
|
||||
chunk_size = free_block->size;
|
||||
if (chunk_size > size + 64) {
|
||||
/* We just cut a block from the end of the free block. */
|
||||
chunk_size -= size;
|
||||
free_block->size = chunk_size;
|
||||
header = AS_BLOCK_HEADER(free_block, chunk_size);
|
||||
header->prev_size = chunk_size;
|
||||
AS_BLOCK_HEADER(header, size)->prev_size = size;
|
||||
}
|
||||
else {
|
||||
sljit_remove_free_block(free_block);
|
||||
header = (struct block_header*)free_block;
|
||||
size = chunk_size;
|
||||
}
|
||||
allocated_size += size;
|
||||
header->size = size;
|
||||
allocator_release_lock();
|
||||
return MEM_START(header);
|
||||
}
|
||||
free_block = free_block->next;
|
||||
}
|
||||
|
||||
chunk_size = (size + sizeof(struct block_header) + CHUNK_SIZE - 1) & CHUNK_MASK;
|
||||
header = (struct block_header*)alloc_chunk(chunk_size);
|
||||
if (!header) {
|
||||
allocator_release_lock();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
chunk_size -= sizeof(struct block_header);
|
||||
total_size += chunk_size;
|
||||
|
||||
header->prev_size = 0;
|
||||
if (chunk_size > size + 64) {
|
||||
/* Cut the allocated space into a free and a used block. */
|
||||
allocated_size += size;
|
||||
header->size = size;
|
||||
chunk_size -= size;
|
||||
|
||||
free_block = AS_FREE_BLOCK(header, size);
|
||||
free_block->header.prev_size = size;
|
||||
sljit_insert_free_block(free_block, chunk_size);
|
||||
next_header = AS_BLOCK_HEADER(free_block, chunk_size);
|
||||
}
|
||||
else {
|
||||
/* All space belongs to this allocation. */
|
||||
allocated_size += chunk_size;
|
||||
header->size = chunk_size;
|
||||
next_header = AS_BLOCK_HEADER(header, chunk_size);
|
||||
}
|
||||
next_header->size = 1;
|
||||
next_header->prev_size = chunk_size;
|
||||
allocator_release_lock();
|
||||
return MEM_START(header);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)
|
||||
{
|
||||
struct block_header *header;
|
||||
struct free_block* free_block;
|
||||
|
||||
allocator_grab_lock();
|
||||
header = AS_BLOCK_HEADER(ptr, -(sljit_sw)sizeof(struct block_header));
|
||||
allocated_size -= header->size;
|
||||
|
||||
/* Connecting free blocks together if possible. */
|
||||
|
||||
/* If header->prev_size == 0, free_block will equal to header.
|
||||
In this case, free_block->header.size will be > 0. */
|
||||
free_block = AS_FREE_BLOCK(header, -(sljit_sw)header->prev_size);
|
||||
if (SLJIT_UNLIKELY(!free_block->header.size)) {
|
||||
free_block->size += header->size;
|
||||
header = AS_BLOCK_HEADER(free_block, free_block->size);
|
||||
header->prev_size = free_block->size;
|
||||
}
|
||||
else {
|
||||
free_block = (struct free_block*)header;
|
||||
sljit_insert_free_block(free_block, header->size);
|
||||
}
|
||||
|
||||
header = AS_BLOCK_HEADER(free_block, free_block->size);
|
||||
if (SLJIT_UNLIKELY(!header->size)) {
|
||||
free_block->size += ((struct free_block*)header)->size;
|
||||
sljit_remove_free_block((struct free_block*)header);
|
||||
header = AS_BLOCK_HEADER(free_block, free_block->size);
|
||||
header->prev_size = free_block->size;
|
||||
}
|
||||
|
||||
/* The whole chunk is free. */
|
||||
if (SLJIT_UNLIKELY(!free_block->header.prev_size && header->size == 1)) {
|
||||
/* If this block is freed, we still have (allocated_size / 2) free space. */
|
||||
if (total_size - free_block->size > (allocated_size * 3 / 2)) {
|
||||
total_size -= free_block->size;
|
||||
sljit_remove_free_block(free_block);
|
||||
free_chunk(free_block, free_block->size + sizeof(struct block_header));
|
||||
}
|
||||
}
|
||||
|
||||
allocator_release_lock();
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void)
|
||||
{
|
||||
struct free_block* free_block;
|
||||
struct free_block* next_free_block;
|
||||
|
||||
allocator_grab_lock();
|
||||
|
||||
free_block = free_blocks;
|
||||
while (free_block) {
|
||||
next_free_block = free_block->next;
|
||||
if (!free_block->header.prev_size &&
|
||||
AS_BLOCK_HEADER(free_block, free_block->size)->size == 1) {
|
||||
total_size -= free_block->size;
|
||||
sljit_remove_free_block(free_block);
|
||||
free_chunk(free_block, free_block->size + sizeof(struct block_header));
|
||||
}
|
||||
free_block = next_free_block;
|
||||
}
|
||||
|
||||
SLJIT_ASSERT((total_size && free_blocks) || (!total_size && !free_blocks));
|
||||
allocator_release_lock();
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,366 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* mips 32-bit arch dependent functions. */
|
||||
|
||||
static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst_ar, sljit_sw imm)
|
||||
{
|
||||
if (!(imm & ~0xffff))
|
||||
return push_inst(compiler, ORI | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
|
||||
|
||||
if (imm < 0 && imm >= SIMM_MIN)
|
||||
return push_inst(compiler, ADDIU | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
|
||||
|
||||
FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(imm >> 16), dst_ar));
|
||||
return (imm & 0xffff) ? push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar) : SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
#define EMIT_LOGICAL(op_imm, op_norm) \
|
||||
if (flags & SRC2_IMM) { \
|
||||
if (op & SLJIT_SET_E) \
|
||||
FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \
|
||||
if (CHECK_FLAGS(SLJIT_SET_E)) \
|
||||
FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \
|
||||
} \
|
||||
else { \
|
||||
if (op & SLJIT_SET_E) \
|
||||
FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
|
||||
if (CHECK_FLAGS(SLJIT_SET_E)) \
|
||||
FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | D(dst), DR(dst))); \
|
||||
}
|
||||
|
||||
#define EMIT_SHIFT(op_imm, op_v) \
|
||||
if (flags & SRC2_IMM) { \
|
||||
if (op & SLJIT_SET_E) \
|
||||
FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \
|
||||
if (CHECK_FLAGS(SLJIT_SET_E)) \
|
||||
FAIL_IF(push_inst(compiler, op_imm | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \
|
||||
} \
|
||||
else { \
|
||||
if (op & SLJIT_SET_E) \
|
||||
FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
|
||||
if (CHECK_FLAGS(SLJIT_SET_E)) \
|
||||
FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | D(dst), DR(dst))); \
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
|
||||
sljit_si dst, sljit_si src1, sljit_sw src2)
|
||||
{
|
||||
switch (GET_OPCODE(op)) {
|
||||
case SLJIT_MOV:
|
||||
case SLJIT_MOV_UI:
|
||||
case SLJIT_MOV_SI:
|
||||
case SLJIT_MOV_P:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if (dst != src2)
|
||||
return push_inst(compiler, ADDU | S(src2) | TA(0) | D(dst), DR(dst));
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UB:
|
||||
case SLJIT_MOV_SB:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SB) {
|
||||
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
|
||||
return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst));
|
||||
#else
|
||||
FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(24), DR(dst)));
|
||||
return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(24), DR(dst));
|
||||
#endif
|
||||
}
|
||||
return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));
|
||||
}
|
||||
else if (dst != src2)
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UH:
|
||||
case SLJIT_MOV_SH:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SH) {
|
||||
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
|
||||
return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst));
|
||||
#else
|
||||
FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(16), DR(dst)));
|
||||
return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(16), DR(dst));
|
||||
#endif
|
||||
}
|
||||
return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));
|
||||
}
|
||||
else if (dst != src2)
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_NOT:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst)));
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_CLZ:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, CLZ | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
FAIL_IF(push_inst(compiler, CLZ | S(src2) | T(dst) | D(dst), DR(dst)));
|
||||
#else
|
||||
if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) {
|
||||
FAIL_IF(push_inst(compiler, SRL | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG));
|
||||
return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG);
|
||||
}
|
||||
/* Nearly all instructions are unmovable in the following sequence. */
|
||||
FAIL_IF(push_inst(compiler, ADDU | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
|
||||
/* Check zero. */
|
||||
FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG1) | TA(0) | IMM(5), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM(32), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(dst) | IMM(-1), DR(dst)));
|
||||
/* Loop for searching the highest bit. */
|
||||
FAIL_IF(push_inst(compiler, ADDIU | S(dst) | T(dst) | IMM(1), DR(dst)));
|
||||
FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, SLL | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS));
|
||||
if (op & SLJIT_SET_E)
|
||||
return push_inst(compiler, ADDU | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG);
|
||||
#endif
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_ADD:
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_O) {
|
||||
if (src2 >= 0)
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
}
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
|
||||
if (op & (SLJIT_SET_C | SLJIT_SET_O)) {
|
||||
if (src2 >= 0)
|
||||
FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
|
||||
else {
|
||||
FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
}
|
||||
}
|
||||
/* dst may be the same as src1 or src2. */
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(src2), DR(dst)));
|
||||
}
|
||||
else {
|
||||
if (op & SLJIT_SET_O)
|
||||
FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (op & (SLJIT_SET_C | SLJIT_SET_O))
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
/* dst may be the same as src1 or src2. */
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | D(dst), DR(dst)));
|
||||
}
|
||||
|
||||
/* a + b >= a | b (otherwise, the carry should be set to 1). */
|
||||
if (op & (SLJIT_SET_C | SLJIT_SET_O))
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
if (!(op & SLJIT_SET_O))
|
||||
return SLJIT_SUCCESS;
|
||||
FAIL_IF(push_inst(compiler, SLL | TA(ULESS_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
return push_inst(compiler, SLL | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG);
|
||||
|
||||
case SLJIT_ADDC:
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_C) {
|
||||
if (src2 >= 0)
|
||||
FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG));
|
||||
else {
|
||||
FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
}
|
||||
}
|
||||
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(src2), DR(dst)));
|
||||
} else {
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
/* dst may be the same as src1 or src2. */
|
||||
FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | D(dst), DR(dst)));
|
||||
}
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
|
||||
FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst)));
|
||||
if (!(op & SLJIT_SET_C))
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
/* Set ULESS_FLAG (dst == 0) && (ULESS_FLAG == 1). */
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
/* Set carry flag. */
|
||||
return push_inst(compiler, OR | SA(ULESS_FLAG) | TA(OVERFLOW_FLAG) | DA(ULESS_FLAG), ULESS_FLAG);
|
||||
|
||||
case SLJIT_SUB:
|
||||
if ((flags & SRC2_IMM) && ((op & (SLJIT_SET_U | SLJIT_SET_S)) || src2 == SIMM_MIN)) {
|
||||
FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
|
||||
src2 = TMP_REG2;
|
||||
flags &= ~SRC2_IMM;
|
||||
}
|
||||
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_O) {
|
||||
if (src2 >= 0)
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
}
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
|
||||
if (op & (SLJIT_SET_C | SLJIT_SET_O))
|
||||
FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
|
||||
/* dst may be the same as src1 or src2. */
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst)));
|
||||
}
|
||||
else {
|
||||
if (op & SLJIT_SET_O)
|
||||
FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (op & (SLJIT_SET_U | SLJIT_SET_C | SLJIT_SET_O))
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
if (op & SLJIT_SET_U)
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(UGREATER_FLAG), UGREATER_FLAG));
|
||||
if (op & SLJIT_SET_S) {
|
||||
FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(LESS_FLAG), LESS_FLAG));
|
||||
FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(GREATER_FLAG), GREATER_FLAG));
|
||||
}
|
||||
/* dst may be the same as src1 or src2. */
|
||||
if (CHECK_FLAGS(SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_C))
|
||||
FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst)));
|
||||
}
|
||||
|
||||
if (!(op & SLJIT_SET_O))
|
||||
return SLJIT_SUCCESS;
|
||||
FAIL_IF(push_inst(compiler, SLL | TA(ULESS_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
return push_inst(compiler, SRL | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG);
|
||||
|
||||
case SLJIT_SUBC:
|
||||
if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
|
||||
FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
|
||||
src2 = TMP_REG2;
|
||||
flags &= ~SRC2_IMM;
|
||||
}
|
||||
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG));
|
||||
/* dst may be the same as src1 or src2. */
|
||||
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst)));
|
||||
}
|
||||
else {
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
/* dst may be the same as src1 or src2. */
|
||||
FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst)));
|
||||
}
|
||||
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(LESS_FLAG), LESS_FLAG));
|
||||
|
||||
FAIL_IF(push_inst(compiler, SUBU | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst)));
|
||||
return (op & SLJIT_SET_C) ? push_inst(compiler, OR | SA(OVERFLOW_FLAG) | TA(LESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG) : SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MUL:
|
||||
SLJIT_ASSERT(!(flags & SRC2_IMM));
|
||||
if (!(op & SLJIT_SET_O)) {
|
||||
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
|
||||
return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));
|
||||
#else
|
||||
FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS));
|
||||
return push_inst(compiler, MFLO | D(dst), DR(dst));
|
||||
#endif
|
||||
}
|
||||
FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, MFHI | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));
|
||||
FAIL_IF(push_inst(compiler, SRA | T(dst) | DA(UGREATER_FLAG) | SH_IMM(31), UGREATER_FLAG));
|
||||
return push_inst(compiler, SUBU | SA(ULESS_FLAG) | TA(UGREATER_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG);
|
||||
|
||||
case SLJIT_AND:
|
||||
EMIT_LOGICAL(ANDI, AND);
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_OR:
|
||||
EMIT_LOGICAL(ORI, OR);
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_XOR:
|
||||
EMIT_LOGICAL(XORI, XOR);
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_SHL:
|
||||
EMIT_SHIFT(SLL, SLLV);
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_LSHR:
|
||||
EMIT_SHIFT(SRL, SRLV);
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_ASHR:
|
||||
EMIT_SHIFT(SRA, SRAV);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw init_value)
|
||||
{
|
||||
FAIL_IF(push_inst(compiler, LUI | T(dst) | IMM(init_value >> 16), DR(dst)));
|
||||
return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst));
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins*)addr;
|
||||
|
||||
inst[0] = (inst[0] & 0xffff0000) | ((new_addr >> 16) & 0xffff);
|
||||
inst[1] = (inst[1] & 0xffff0000) | (new_addr & 0xffff);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 2);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins*)addr;
|
||||
|
||||
inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
|
||||
inst[1] = (inst[1] & 0xffff0000) | (new_constant & 0xffff);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 2);
|
||||
}
|
||||
@@ -0,0 +1,469 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* mips 64-bit arch dependent functions. */
|
||||
|
||||
static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst_ar, sljit_sw imm)
|
||||
{
|
||||
sljit_si shift = 32;
|
||||
sljit_si shift2;
|
||||
sljit_si inv = 0;
|
||||
sljit_ins ins;
|
||||
sljit_uw uimm;
|
||||
|
||||
if (!(imm & ~0xffff))
|
||||
return push_inst(compiler, ORI | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
|
||||
|
||||
if (imm < 0 && imm >= SIMM_MIN)
|
||||
return push_inst(compiler, ADDIU | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
|
||||
|
||||
if (imm <= 0x7fffffffl && imm >= -0x80000000l) {
|
||||
FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(imm >> 16), dst_ar));
|
||||
return (imm & 0xffff) ? push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar) : SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
/* Zero extended number. */
|
||||
uimm = imm;
|
||||
if (imm < 0) {
|
||||
uimm = ~imm;
|
||||
inv = 1;
|
||||
}
|
||||
|
||||
while (!(uimm & 0xff00000000000000l)) {
|
||||
shift -= 8;
|
||||
uimm <<= 8;
|
||||
}
|
||||
|
||||
if (!(uimm & 0xf000000000000000l)) {
|
||||
shift -= 4;
|
||||
uimm <<= 4;
|
||||
}
|
||||
|
||||
if (!(uimm & 0xc000000000000000l)) {
|
||||
shift -= 2;
|
||||
uimm <<= 2;
|
||||
}
|
||||
|
||||
if ((sljit_sw)uimm < 0) {
|
||||
uimm >>= 1;
|
||||
shift += 1;
|
||||
}
|
||||
SLJIT_ASSERT(((uimm & 0xc000000000000000l) == 0x4000000000000000l) && (shift > 0) && (shift <= 32));
|
||||
|
||||
if (inv)
|
||||
uimm = ~uimm;
|
||||
|
||||
FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(uimm >> 48), dst_ar));
|
||||
if (uimm & 0x0000ffff00000000l)
|
||||
FAIL_IF(push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(uimm >> 32), dst_ar));
|
||||
|
||||
imm &= (1l << shift) - 1;
|
||||
if (!(imm & ~0xffff)) {
|
||||
ins = (shift == 32) ? DSLL32 : DSLL;
|
||||
if (shift < 32)
|
||||
ins |= SH_IMM(shift);
|
||||
FAIL_IF(push_inst(compiler, ins | TA(dst_ar) | DA(dst_ar), dst_ar));
|
||||
return !(imm & 0xffff) ? SLJIT_SUCCESS : push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar);
|
||||
}
|
||||
|
||||
/* Double shifts needs to be performed. */
|
||||
uimm <<= 32;
|
||||
shift2 = shift - 16;
|
||||
|
||||
while (!(uimm & 0xf000000000000000l)) {
|
||||
shift2 -= 4;
|
||||
uimm <<= 4;
|
||||
}
|
||||
|
||||
if (!(uimm & 0xc000000000000000l)) {
|
||||
shift2 -= 2;
|
||||
uimm <<= 2;
|
||||
}
|
||||
|
||||
if (!(uimm & 0x8000000000000000l)) {
|
||||
shift2--;
|
||||
uimm <<= 1;
|
||||
}
|
||||
|
||||
SLJIT_ASSERT((uimm & 0x8000000000000000l) && (shift2 > 0) && (shift2 <= 16));
|
||||
|
||||
FAIL_IF(push_inst(compiler, DSLL | TA(dst_ar) | DA(dst_ar) | SH_IMM(shift - shift2), dst_ar));
|
||||
FAIL_IF(push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(uimm >> 48), dst_ar));
|
||||
FAIL_IF(push_inst(compiler, DSLL | TA(dst_ar) | DA(dst_ar) | SH_IMM(shift2), dst_ar));
|
||||
|
||||
imm &= (1l << shift2) - 1;
|
||||
return !(imm & 0xffff) ? SLJIT_SUCCESS : push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar);
|
||||
}
|
||||
|
||||
#define SELECT_OP(a, b) \
|
||||
(!(op & SLJIT_INT_OP) ? a : b)
|
||||
|
||||
#define EMIT_LOGICAL(op_imm, op_norm) \
|
||||
if (flags & SRC2_IMM) { \
|
||||
if (op & SLJIT_SET_E) \
|
||||
FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \
|
||||
if (CHECK_FLAGS(SLJIT_SET_E)) \
|
||||
FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \
|
||||
} \
|
||||
else { \
|
||||
if (op & SLJIT_SET_E) \
|
||||
FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
|
||||
if (CHECK_FLAGS(SLJIT_SET_E)) \
|
||||
FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | D(dst), DR(dst))); \
|
||||
}
|
||||
|
||||
#define EMIT_SHIFT(op_dimm, op_dimm32, op_imm, op_dv, op_v) \
|
||||
if (flags & SRC2_IMM) { \
|
||||
if (src2 >= 32) { \
|
||||
SLJIT_ASSERT(!(op & SLJIT_INT_OP)); \
|
||||
ins = op_dimm32; \
|
||||
src2 -= 32; \
|
||||
} \
|
||||
else \
|
||||
ins = (op & SLJIT_INT_OP) ? op_imm : op_dimm; \
|
||||
if (op & SLJIT_SET_E) \
|
||||
FAIL_IF(push_inst(compiler, ins | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \
|
||||
if (CHECK_FLAGS(SLJIT_SET_E)) \
|
||||
FAIL_IF(push_inst(compiler, ins | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \
|
||||
} \
|
||||
else { \
|
||||
ins = (op & SLJIT_INT_OP) ? op_v : op_dv; \
|
||||
if (op & SLJIT_SET_E) \
|
||||
FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
|
||||
if (CHECK_FLAGS(SLJIT_SET_E)) \
|
||||
FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | D(dst), DR(dst))); \
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
|
||||
sljit_si dst, sljit_si src1, sljit_sw src2)
|
||||
{
|
||||
sljit_ins ins;
|
||||
|
||||
switch (GET_OPCODE(op)) {
|
||||
case SLJIT_MOV:
|
||||
case SLJIT_MOV_P:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if (dst != src2)
|
||||
return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(dst), DR(dst));
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UB:
|
||||
case SLJIT_MOV_SB:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SB) {
|
||||
FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(24), DR(dst)));
|
||||
return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(24), DR(dst));
|
||||
}
|
||||
return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));
|
||||
}
|
||||
else if (dst != src2)
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UH:
|
||||
case SLJIT_MOV_SH:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SH) {
|
||||
FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(16), DR(dst)));
|
||||
return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(16), DR(dst));
|
||||
}
|
||||
return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));
|
||||
}
|
||||
else if (dst != src2)
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UI:
|
||||
SLJIT_ASSERT(!(op & SLJIT_INT_OP));
|
||||
FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(0), DR(dst)));
|
||||
return push_inst(compiler, DSRL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst));
|
||||
|
||||
case SLJIT_MOV_SI:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
return push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(0), DR(dst));
|
||||
|
||||
case SLJIT_NOT:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst)));
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_CLZ:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | T(dst) | D(dst), DR(dst)));
|
||||
#else
|
||||
if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) {
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG));
|
||||
return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG);
|
||||
}
|
||||
/* Nearly all instructions are unmovable in the following sequence. */
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
|
||||
/* Check zero. */
|
||||
FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG1) | TA(0) | IMM(5), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM((op & SLJIT_INT_OP) ? 32 : 64), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | T(dst) | IMM(-1), DR(dst)));
|
||||
/* Loop for searching the highest bit. */
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(dst) | T(dst) | IMM(1), DR(dst)));
|
||||
FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSLL, SLL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS));
|
||||
if (op & SLJIT_SET_E)
|
||||
return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG);
|
||||
#endif
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_ADD:
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_O) {
|
||||
if (src2 >= 0)
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
}
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
|
||||
if (op & (SLJIT_SET_C | SLJIT_SET_O)) {
|
||||
if (src2 >= 0)
|
||||
FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
|
||||
else {
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
}
|
||||
}
|
||||
/* dst may be the same as src1 or src2. */
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));
|
||||
}
|
||||
else {
|
||||
if (op & SLJIT_SET_O)
|
||||
FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (op & (SLJIT_SET_C | SLJIT_SET_O))
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
/* dst may be the same as src1 or src2. */
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));
|
||||
}
|
||||
|
||||
/* a + b >= a | b (otherwise, the carry should be set to 1). */
|
||||
if (op & (SLJIT_SET_C | SLJIT_SET_O))
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
if (!(op & SLJIT_SET_O))
|
||||
return SLJIT_SUCCESS;
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(ULESS_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
return push_inst(compiler, SELECT_OP(DSRL32, SLL) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG);
|
||||
|
||||
case SLJIT_ADDC:
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_C) {
|
||||
if (src2 >= 0)
|
||||
FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG));
|
||||
else {
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
}
|
||||
}
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));
|
||||
} else {
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
/* dst may be the same as src1 or src2. */
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));
|
||||
}
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst)));
|
||||
if (!(op & SLJIT_SET_C))
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
/* Set ULESS_FLAG (dst == 0) && (ULESS_FLAG == 1). */
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
/* Set carry flag. */
|
||||
return push_inst(compiler, OR | SA(ULESS_FLAG) | TA(OVERFLOW_FLAG) | DA(ULESS_FLAG), ULESS_FLAG);
|
||||
|
||||
case SLJIT_SUB:
|
||||
if ((flags & SRC2_IMM) && ((op & (SLJIT_SET_U | SLJIT_SET_S)) || src2 == SIMM_MIN)) {
|
||||
FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
|
||||
src2 = TMP_REG2;
|
||||
flags &= ~SRC2_IMM;
|
||||
}
|
||||
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_O) {
|
||||
if (src2 >= 0)
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
}
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
|
||||
if (op & (SLJIT_SET_C | SLJIT_SET_O))
|
||||
FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
|
||||
/* dst may be the same as src1 or src2. */
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));
|
||||
}
|
||||
else {
|
||||
if (op & SLJIT_SET_O)
|
||||
FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (op & (SLJIT_SET_U | SLJIT_SET_C | SLJIT_SET_O))
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
if (op & SLJIT_SET_U)
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(UGREATER_FLAG), UGREATER_FLAG));
|
||||
if (op & SLJIT_SET_S) {
|
||||
FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(LESS_FLAG), LESS_FLAG));
|
||||
FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(GREATER_FLAG), GREATER_FLAG));
|
||||
}
|
||||
/* dst may be the same as src1 or src2. */
|
||||
if (CHECK_FLAGS(SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_C))
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));
|
||||
}
|
||||
|
||||
if (!(op & SLJIT_SET_O))
|
||||
return SLJIT_SUCCESS;
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(ULESS_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
return push_inst(compiler, SELECT_OP(DSRL32, SRL) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG);
|
||||
|
||||
case SLJIT_SUBC:
|
||||
if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
|
||||
FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
|
||||
src2 = TMP_REG2;
|
||||
flags &= ~SRC2_IMM;
|
||||
}
|
||||
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG));
|
||||
/* dst may be the same as src1 or src2. */
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));
|
||||
}
|
||||
else {
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
/* dst may be the same as src1 or src2. */
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));
|
||||
}
|
||||
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(LESS_FLAG), LESS_FLAG));
|
||||
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst)));
|
||||
return (op & SLJIT_SET_C) ? push_inst(compiler, OR | SA(OVERFLOW_FLAG) | TA(LESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG) : SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MUL:
|
||||
SLJIT_ASSERT(!(flags & SRC2_IMM));
|
||||
if (!(op & SLJIT_SET_O)) {
|
||||
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
|
||||
if (op & SLJIT_INT_OP)
|
||||
return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));
|
||||
FAIL_IF(push_inst(compiler, DMULT | S(src1) | T(src2), MOVABLE_INS));
|
||||
return push_inst(compiler, MFLO | D(dst), DR(dst));
|
||||
#else
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));
|
||||
return push_inst(compiler, MFLO | D(dst), DR(dst));
|
||||
#endif
|
||||
}
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, MFHI | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSRA32, SRA) | T(dst) | DA(UGREATER_FLAG) | SH_IMM(31), UGREATER_FLAG));
|
||||
return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(ULESS_FLAG) | TA(UGREATER_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG);
|
||||
|
||||
case SLJIT_AND:
|
||||
EMIT_LOGICAL(ANDI, AND);
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_OR:
|
||||
EMIT_LOGICAL(ORI, OR);
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_XOR:
|
||||
EMIT_LOGICAL(XORI, XOR);
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_SHL:
|
||||
EMIT_SHIFT(DSLL, DSLL32, SLL, DSLLV, SLLV);
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_LSHR:
|
||||
EMIT_SHIFT(DSRL, DSRL32, SRL, DSRLV, SRLV);
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_ASHR:
|
||||
EMIT_SHIFT(DSRA, DSRA32, SRA, DSRAV, SRAV);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw init_value)
|
||||
{
|
||||
FAIL_IF(push_inst(compiler, LUI | T(dst) | IMM(init_value >> 48), DR(dst)));
|
||||
FAIL_IF(push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value >> 32), DR(dst)));
|
||||
FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst)));
|
||||
FAIL_IF(push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value >> 16), DR(dst)));
|
||||
FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst)));
|
||||
return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst));
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins*)addr;
|
||||
|
||||
inst[0] = (inst[0] & 0xffff0000) | ((new_addr >> 48) & 0xffff);
|
||||
inst[1] = (inst[1] & 0xffff0000) | ((new_addr >> 32) & 0xffff);
|
||||
inst[3] = (inst[3] & 0xffff0000) | ((new_addr >> 16) & 0xffff);
|
||||
inst[5] = (inst[5] & 0xffff0000) | (new_addr & 0xffff);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 6);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins*)addr;
|
||||
|
||||
inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 48) & 0xffff);
|
||||
inst[1] = (inst[1] & 0xffff0000) | ((new_constant >> 32) & 0xffff);
|
||||
inst[3] = (inst[3] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
|
||||
inst[5] = (inst[5] & 0xffff0000) | (new_constant & 0xffff);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 6);
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* ppc 32-bit arch dependent functions. */
|
||||
|
||||
static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si reg, sljit_sw imm)
|
||||
{
|
||||
if (imm <= SIMM_MAX && imm >= SIMM_MIN)
|
||||
return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));
|
||||
|
||||
if (!(imm & ~0xffff))
|
||||
return push_inst(compiler, ORI | S(TMP_ZERO) | A(reg) | IMM(imm));
|
||||
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16)));
|
||||
return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
#define INS_CLEAR_LEFT(dst, src, from) \
|
||||
(RLWINM | S(src) | A(dst) | ((from) << 6) | (31 << 1))
|
||||
|
||||
static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
|
||||
sljit_si dst, sljit_si src1, sljit_si src2)
|
||||
{
|
||||
switch (op) {
|
||||
case SLJIT_MOV:
|
||||
case SLJIT_MOV_UI:
|
||||
case SLJIT_MOV_SI:
|
||||
case SLJIT_MOV_P:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if (dst != src2)
|
||||
return push_inst(compiler, OR | S(src2) | A(dst) | B(src2));
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UB:
|
||||
case SLJIT_MOV_SB:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SB)
|
||||
return push_inst(compiler, EXTSB | S(src2) | A(dst));
|
||||
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 24));
|
||||
}
|
||||
else if ((flags & REG_DEST) && op == SLJIT_MOV_SB)
|
||||
return push_inst(compiler, EXTSB | S(src2) | A(dst));
|
||||
else {
|
||||
SLJIT_ASSERT(dst == src2);
|
||||
}
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UH:
|
||||
case SLJIT_MOV_SH:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SH)
|
||||
return push_inst(compiler, EXTSH | S(src2) | A(dst));
|
||||
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16));
|
||||
}
|
||||
else {
|
||||
SLJIT_ASSERT(dst == src2);
|
||||
}
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_NOT:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_NEG:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
return push_inst(compiler, NEG | OERC(flags) | D(dst) | A(src2));
|
||||
|
||||
case SLJIT_CLZ:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
return push_inst(compiler, CNTLZW | RC(flags) | S(src2) | A(dst));
|
||||
|
||||
case SLJIT_ADD:
|
||||
if (flags & ALT_FORM1) {
|
||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ADDI | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM2) {
|
||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM3) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM4) {
|
||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||
FAIL_IF(push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff)));
|
||||
return push_inst(compiler, ADDIS | D(dst) | A(dst) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1)));
|
||||
}
|
||||
if (!(flags & ALT_SET_FLAGS))
|
||||
return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));
|
||||
return push_inst(compiler, ADDC | OERC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
|
||||
|
||||
case SLJIT_ADDC:
|
||||
if (flags & ALT_FORM1) {
|
||||
FAIL_IF(push_inst(compiler, MFXER | D(0)));
|
||||
FAIL_IF(push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2)));
|
||||
return push_inst(compiler, MTXER | S(0));
|
||||
}
|
||||
return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2));
|
||||
|
||||
case SLJIT_SUB:
|
||||
if (flags & ALT_FORM1) {
|
||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
if (flags & (ALT_FORM2 | ALT_FORM3)) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
if (flags & ALT_FORM2)
|
||||
FAIL_IF(push_inst(compiler, CMPI | CRD(0) | A(src1) | compiler->imm));
|
||||
if (flags & ALT_FORM3)
|
||||
return push_inst(compiler, CMPLI | CRD(4) | A(src1) | compiler->imm);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
if (flags & (ALT_FORM4 | ALT_FORM5)) {
|
||||
if (flags & ALT_FORM4)
|
||||
FAIL_IF(push_inst(compiler, CMPL | CRD(4) | A(src1) | B(src2)));
|
||||
if (flags & ALT_FORM5)
|
||||
FAIL_IF(push_inst(compiler, CMP | CRD(0) | A(src1) | B(src2)));
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
if (!(flags & ALT_SET_FLAGS))
|
||||
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
|
||||
if (flags & ALT_FORM6)
|
||||
FAIL_IF(push_inst(compiler, CMPL | CRD(4) | A(src1) | B(src2)));
|
||||
return push_inst(compiler, SUBFC | OERC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
|
||||
|
||||
case SLJIT_SUBC:
|
||||
if (flags & ALT_FORM1) {
|
||||
FAIL_IF(push_inst(compiler, MFXER | D(0)));
|
||||
FAIL_IF(push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1)));
|
||||
return push_inst(compiler, MTXER | S(0));
|
||||
}
|
||||
return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1));
|
||||
|
||||
case SLJIT_MUL:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
return push_inst(compiler, MULLW | OERC(flags) | D(dst) | A(src2) | B(src1));
|
||||
|
||||
case SLJIT_AND:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ANDI | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM2) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ANDIS | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
return push_inst(compiler, AND | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_OR:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ORI | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM2) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ORIS | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM3) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(compiler->imm)));
|
||||
return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16));
|
||||
}
|
||||
return push_inst(compiler, OR | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_XOR:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, XORI | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM2) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, XORIS | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM3) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(compiler->imm)));
|
||||
return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16));
|
||||
}
|
||||
return push_inst(compiler, XOR | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_SHL:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
compiler->imm &= 0x1f;
|
||||
return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11) | ((31 - compiler->imm) << 1));
|
||||
}
|
||||
return push_inst(compiler, SLW | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_LSHR:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
compiler->imm &= 0x1f;
|
||||
return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (((32 - compiler->imm) & 0x1f) << 11) | (compiler->imm << 6) | (31 << 1));
|
||||
}
|
||||
return push_inst(compiler, SRW | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_ASHR:
|
||||
if (flags & ALT_FORM3)
|
||||
FAIL_IF(push_inst(compiler, MFXER | D(0)));
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
compiler->imm &= 0x1f;
|
||||
FAIL_IF(push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11)));
|
||||
}
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2)));
|
||||
return (flags & ALT_FORM3) ? push_inst(compiler, MTXER | S(0)) : SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_si reg, sljit_sw init_value)
|
||||
{
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 16)));
|
||||
return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value));
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins*)addr;
|
||||
|
||||
inst[0] = (inst[0] & 0xffff0000) | ((new_addr >> 16) & 0xffff);
|
||||
inst[1] = (inst[1] & 0xffff0000) | (new_addr & 0xffff);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 2);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins*)addr;
|
||||
|
||||
inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
|
||||
inst[1] = (inst[1] & 0xffff0000) | (new_constant & 0xffff);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 2);
|
||||
}
|
||||
@@ -0,0 +1,421 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* ppc 64-bit arch dependent functions. */
|
||||
|
||||
#if defined(__GNUC__) || (defined(__IBM_GCC_ASM) && __IBM_GCC_ASM)
|
||||
#define ASM_SLJIT_CLZ(src, dst) \
|
||||
__asm__ volatile ( "cntlzd %0, %1" : "=r"(dst) : "r"(src) )
|
||||
#elif defined(__xlc__)
|
||||
#error "Please enable GCC syntax for inline assembly statements"
|
||||
#else
|
||||
#error "Must implement count leading zeroes"
|
||||
#endif
|
||||
|
||||
#define RLDI(dst, src, sh, mb, type) \
|
||||
(HI(30) | S(src) | A(dst) | ((type) << 2) | (((sh) & 0x1f) << 11) | (((sh) & 0x20) >> 4) | (((mb) & 0x1f) << 6) | ((mb) & 0x20))
|
||||
|
||||
#define PUSH_RLDICR(reg, shift) \
|
||||
push_inst(compiler, RLDI(reg, reg, 63 - shift, shift, 1))
|
||||
|
||||
static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si reg, sljit_sw imm)
|
||||
{
|
||||
sljit_uw tmp;
|
||||
sljit_uw shift;
|
||||
sljit_uw tmp2;
|
||||
sljit_uw shift2;
|
||||
|
||||
if (imm <= SIMM_MAX && imm >= SIMM_MIN)
|
||||
return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));
|
||||
|
||||
if (!(imm & ~0xffff))
|
||||
return push_inst(compiler, ORI | S(TMP_ZERO) | A(reg) | IMM(imm));
|
||||
|
||||
if (imm <= 0x7fffffffl && imm >= -0x80000000l) {
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16)));
|
||||
return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
/* Count leading zeroes. */
|
||||
tmp = (imm >= 0) ? imm : ~imm;
|
||||
ASM_SLJIT_CLZ(tmp, shift);
|
||||
SLJIT_ASSERT(shift > 0);
|
||||
shift--;
|
||||
tmp = (imm << shift);
|
||||
|
||||
if ((tmp & ~0xffff000000000000ul) == 0) {
|
||||
FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48)));
|
||||
shift += 15;
|
||||
return PUSH_RLDICR(reg, shift);
|
||||
}
|
||||
|
||||
if ((tmp & ~0xffffffff00000000ul) == 0) {
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(tmp >> 48)));
|
||||
FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(tmp >> 32)));
|
||||
shift += 31;
|
||||
return PUSH_RLDICR(reg, shift);
|
||||
}
|
||||
|
||||
/* Cut out the 16 bit from immediate. */
|
||||
shift += 15;
|
||||
tmp2 = imm & ((1ul << (63 - shift)) - 1);
|
||||
|
||||
if (tmp2 <= 0xffff) {
|
||||
FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48)));
|
||||
FAIL_IF(PUSH_RLDICR(reg, shift));
|
||||
return push_inst(compiler, ORI | S(reg) | A(reg) | tmp2);
|
||||
}
|
||||
|
||||
if (tmp2 <= 0xffffffff) {
|
||||
FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48)));
|
||||
FAIL_IF(PUSH_RLDICR(reg, shift));
|
||||
FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | (tmp2 >> 16)));
|
||||
return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(tmp2)) : SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
ASM_SLJIT_CLZ(tmp2, shift2);
|
||||
tmp2 <<= shift2;
|
||||
|
||||
if ((tmp2 & ~0xffff000000000000ul) == 0) {
|
||||
FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48)));
|
||||
shift2 += 15;
|
||||
shift += (63 - shift2);
|
||||
FAIL_IF(PUSH_RLDICR(reg, shift));
|
||||
FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | (tmp2 >> 48)));
|
||||
return PUSH_RLDICR(reg, shift2);
|
||||
}
|
||||
|
||||
/* The general version. */
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 48)));
|
||||
FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm >> 32)));
|
||||
FAIL_IF(PUSH_RLDICR(reg, 31));
|
||||
FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | IMM(imm >> 16)));
|
||||
return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm));
|
||||
}
|
||||
|
||||
/* Simplified mnemonics: clrldi. */
|
||||
#define INS_CLEAR_LEFT(dst, src, from) \
|
||||
(RLDICL | S(src) | A(dst) | ((from) << 6) | (1 << 5))
|
||||
|
||||
/* Sign extension for integer operations. */
|
||||
#define UN_EXTS() \
|
||||
if ((flags & (ALT_SIGN_EXT | REG2_SOURCE)) == (ALT_SIGN_EXT | REG2_SOURCE)) { \
|
||||
FAIL_IF(push_inst(compiler, EXTSW | S(src2) | A(TMP_REG2))); \
|
||||
src2 = TMP_REG2; \
|
||||
}
|
||||
|
||||
#define BIN_EXTS() \
|
||||
if (flags & ALT_SIGN_EXT) { \
|
||||
if (flags & REG1_SOURCE) { \
|
||||
FAIL_IF(push_inst(compiler, EXTSW | S(src1) | A(TMP_REG1))); \
|
||||
src1 = TMP_REG1; \
|
||||
} \
|
||||
if (flags & REG2_SOURCE) { \
|
||||
FAIL_IF(push_inst(compiler, EXTSW | S(src2) | A(TMP_REG2))); \
|
||||
src2 = TMP_REG2; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define BIN_IMM_EXTS() \
|
||||
if ((flags & (ALT_SIGN_EXT | REG1_SOURCE)) == (ALT_SIGN_EXT | REG1_SOURCE)) { \
|
||||
FAIL_IF(push_inst(compiler, EXTSW | S(src1) | A(TMP_REG1))); \
|
||||
src1 = TMP_REG1; \
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
|
||||
sljit_si dst, sljit_si src1, sljit_si src2)
|
||||
{
|
||||
switch (op) {
|
||||
case SLJIT_MOV:
|
||||
case SLJIT_MOV_P:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if (dst != src2)
|
||||
return push_inst(compiler, OR | S(src2) | A(dst) | B(src2));
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UI:
|
||||
case SLJIT_MOV_SI:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SI)
|
||||
return push_inst(compiler, EXTSW | S(src2) | A(dst));
|
||||
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 0));
|
||||
}
|
||||
else {
|
||||
SLJIT_ASSERT(dst == src2);
|
||||
}
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UB:
|
||||
case SLJIT_MOV_SB:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SB)
|
||||
return push_inst(compiler, EXTSB | S(src2) | A(dst));
|
||||
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 24));
|
||||
}
|
||||
else if ((flags & REG_DEST) && op == SLJIT_MOV_SB)
|
||||
return push_inst(compiler, EXTSB | S(src2) | A(dst));
|
||||
else {
|
||||
SLJIT_ASSERT(dst == src2);
|
||||
}
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UH:
|
||||
case SLJIT_MOV_SH:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SH)
|
||||
return push_inst(compiler, EXTSH | S(src2) | A(dst));
|
||||
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16));
|
||||
}
|
||||
else {
|
||||
SLJIT_ASSERT(dst == src2);
|
||||
}
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_NOT:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
UN_EXTS();
|
||||
return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_NEG:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
UN_EXTS();
|
||||
return push_inst(compiler, NEG | OERC(flags) | D(dst) | A(src2));
|
||||
|
||||
case SLJIT_CLZ:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||
if (flags & ALT_FORM1)
|
||||
return push_inst(compiler, CNTLZW | RC(flags) | S(src2) | A(dst));
|
||||
return push_inst(compiler, CNTLZD | RC(flags) | S(src2) | A(dst));
|
||||
|
||||
case SLJIT_ADD:
|
||||
if (flags & ALT_FORM1) {
|
||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ADDI | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM2) {
|
||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM3) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
BIN_IMM_EXTS();
|
||||
return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM4) {
|
||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||
FAIL_IF(push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff)));
|
||||
return push_inst(compiler, ADDIS | D(dst) | A(dst) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1)));
|
||||
}
|
||||
if (!(flags & ALT_SET_FLAGS))
|
||||
return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));
|
||||
BIN_EXTS();
|
||||
return push_inst(compiler, ADDC | OERC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
|
||||
|
||||
case SLJIT_ADDC:
|
||||
if (flags & ALT_FORM1) {
|
||||
FAIL_IF(push_inst(compiler, MFXER | D(0)));
|
||||
FAIL_IF(push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2)));
|
||||
return push_inst(compiler, MTXER | S(0));
|
||||
}
|
||||
BIN_EXTS();
|
||||
return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2));
|
||||
|
||||
case SLJIT_SUB:
|
||||
if (flags & ALT_FORM1) {
|
||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
if (flags & (ALT_FORM2 | ALT_FORM3)) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
if (flags & ALT_FORM2)
|
||||
FAIL_IF(push_inst(compiler, CMPI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm));
|
||||
if (flags & ALT_FORM3)
|
||||
return push_inst(compiler, CMPLI | CRD(4 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
if (flags & (ALT_FORM4 | ALT_FORM5)) {
|
||||
if (flags & ALT_FORM4)
|
||||
FAIL_IF(push_inst(compiler, CMPL | CRD(4 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)));
|
||||
if (flags & ALT_FORM5)
|
||||
return push_inst(compiler, CMP | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2));
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
if (!(flags & ALT_SET_FLAGS))
|
||||
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
|
||||
BIN_EXTS();
|
||||
if (flags & ALT_FORM6)
|
||||
FAIL_IF(push_inst(compiler, CMPL | CRD(4 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)));
|
||||
return push_inst(compiler, SUBFC | OERC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
|
||||
|
||||
case SLJIT_SUBC:
|
||||
if (flags & ALT_FORM1) {
|
||||
FAIL_IF(push_inst(compiler, MFXER | D(0)));
|
||||
FAIL_IF(push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1)));
|
||||
return push_inst(compiler, MTXER | S(0));
|
||||
}
|
||||
BIN_EXTS();
|
||||
return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1));
|
||||
|
||||
case SLJIT_MUL:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm);
|
||||
}
|
||||
BIN_EXTS();
|
||||
if (flags & ALT_FORM2)
|
||||
return push_inst(compiler, MULLW | OERC(flags) | D(dst) | A(src2) | B(src1));
|
||||
return push_inst(compiler, MULLD | OERC(flags) | D(dst) | A(src2) | B(src1));
|
||||
|
||||
case SLJIT_AND:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ANDI | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM2) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ANDIS | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
return push_inst(compiler, AND | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_OR:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ORI | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM2) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, ORIS | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM3) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(compiler->imm)));
|
||||
return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16));
|
||||
}
|
||||
return push_inst(compiler, OR | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_XOR:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, XORI | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM2) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
return push_inst(compiler, XORIS | S(src1) | A(dst) | compiler->imm);
|
||||
}
|
||||
if (flags & ALT_FORM3) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(compiler->imm)));
|
||||
return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16));
|
||||
}
|
||||
return push_inst(compiler, XOR | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_SHL:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
if (flags & ALT_FORM2) {
|
||||
compiler->imm &= 0x1f;
|
||||
return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11) | ((31 - compiler->imm) << 1));
|
||||
}
|
||||
else {
|
||||
compiler->imm &= 0x3f;
|
||||
return push_inst(compiler, RLDI(dst, src1, compiler->imm, 63 - compiler->imm, 1) | RC(flags));
|
||||
}
|
||||
}
|
||||
return push_inst(compiler, ((flags & ALT_FORM2) ? SLW : SLD) | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_LSHR:
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
if (flags & ALT_FORM2) {
|
||||
compiler->imm &= 0x1f;
|
||||
return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (((32 - compiler->imm) & 0x1f) << 11) | (compiler->imm << 6) | (31 << 1));
|
||||
}
|
||||
else {
|
||||
compiler->imm &= 0x3f;
|
||||
return push_inst(compiler, RLDI(dst, src1, 64 - compiler->imm, compiler->imm, 0) | RC(flags));
|
||||
}
|
||||
}
|
||||
return push_inst(compiler, ((flags & ALT_FORM2) ? SRW : SRD) | RC(flags) | S(src1) | A(dst) | B(src2));
|
||||
|
||||
case SLJIT_ASHR:
|
||||
if (flags & ALT_FORM3)
|
||||
FAIL_IF(push_inst(compiler, MFXER | D(0)));
|
||||
if (flags & ALT_FORM1) {
|
||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||
if (flags & ALT_FORM2) {
|
||||
compiler->imm &= 0x1f;
|
||||
FAIL_IF(push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11)));
|
||||
}
|
||||
else {
|
||||
compiler->imm &= 0x3f;
|
||||
FAIL_IF(push_inst(compiler, SRADI | RC(flags) | S(src1) | A(dst) | ((compiler->imm & 0x1f) << 11) | ((compiler->imm & 0x20) >> 4)));
|
||||
}
|
||||
}
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, ((flags & ALT_FORM2) ? SRAW : SRAD) | RC(flags) | S(src1) | A(dst) | B(src2)));
|
||||
return (flags & ALT_FORM3) ? push_inst(compiler, MTXER | S(0)) : SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_si reg, sljit_sw init_value)
|
||||
{
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 48)));
|
||||
FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value >> 32)));
|
||||
FAIL_IF(PUSH_RLDICR(reg, 31));
|
||||
FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | IMM(init_value >> 16)));
|
||||
return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value));
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins*)addr;
|
||||
|
||||
inst[0] = (inst[0] & 0xffff0000) | ((new_addr >> 48) & 0xffff);
|
||||
inst[1] = (inst[1] & 0xffff0000) | ((new_addr >> 32) & 0xffff);
|
||||
inst[3] = (inst[3] & 0xffff0000) | ((new_addr >> 16) & 0xffff);
|
||||
inst[4] = (inst[4] & 0xffff0000) | (new_addr & 0xffff);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 5);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins*)addr;
|
||||
|
||||
inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 48) & 0xffff);
|
||||
inst[1] = (inst[1] & 0xffff0000) | ((new_constant >> 32) & 0xffff);
|
||||
inst[3] = (inst[3] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
|
||||
inst[4] = (inst[4] & 0xffff0000) | (new_constant & 0xffff);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 5);
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst, sljit_sw imm)
|
||||
{
|
||||
if (imm <= SIMM_MAX && imm >= SIMM_MIN)
|
||||
return push_inst(compiler, OR | D(dst) | S1(0) | IMM(imm), DR(dst));
|
||||
|
||||
FAIL_IF(push_inst(compiler, SETHI | D(dst) | ((imm >> 10) & 0x3fffff), DR(dst)));
|
||||
return (imm & 0x3ff) ? push_inst(compiler, OR | D(dst) | S1(dst) | IMM_ARG | (imm & 0x3ff), DR(dst)) : SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
#define ARG2(flags, src2) ((flags & SRC2_IMM) ? IMM(src2) : S2(src2))
|
||||
|
||||
static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
|
||||
sljit_si dst, sljit_si src1, sljit_sw src2)
|
||||
{
|
||||
SLJIT_COMPILE_ASSERT(ICC_IS_SET == SET_FLAGS, icc_is_set_and_set_flags_must_be_the_same);
|
||||
|
||||
switch (op) {
|
||||
case SLJIT_MOV:
|
||||
case SLJIT_MOV_UI:
|
||||
case SLJIT_MOV_SI:
|
||||
case SLJIT_MOV_P:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if (dst != src2)
|
||||
return push_inst(compiler, OR | D(dst) | S1(0) | S2(src2), DR(dst));
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UB:
|
||||
case SLJIT_MOV_SB:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_UB)
|
||||
return push_inst(compiler, AND | D(dst) | S1(src2) | IMM(0xff), DR(dst));
|
||||
FAIL_IF(push_inst(compiler, SLL | D(dst) | S1(src2) | IMM(24), DR(dst)));
|
||||
return push_inst(compiler, SRA | D(dst) | S1(dst) | IMM(24), DR(dst));
|
||||
}
|
||||
else if (dst != src2)
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UH:
|
||||
case SLJIT_MOV_SH:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
FAIL_IF(push_inst(compiler, SLL | D(dst) | S1(src2) | IMM(16), DR(dst)));
|
||||
return push_inst(compiler, (op == SLJIT_MOV_SH ? SRA : SRL) | D(dst) | S1(dst) | IMM(16), DR(dst));
|
||||
}
|
||||
else if (dst != src2)
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_NOT:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
return push_inst(compiler, XNOR | (flags & SET_FLAGS) | D(dst) | S1(0) | S2(src2), DR(dst) | (flags & SET_FLAGS));
|
||||
|
||||
case SLJIT_CLZ:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
/* sparc 32 does not support SLJIT_KEEP_FLAGS. Not sure I can fix this. */
|
||||
FAIL_IF(push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(src2) | S2(0), SET_FLAGS));
|
||||
FAIL_IF(push_inst(compiler, OR | D(TMP_REG1) | S1(0) | S2(src2), DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, BICC | DA(0x1) | (7 & DISP_MASK), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, OR | (flags & SET_FLAGS) | D(dst) | S1(0) | IMM(32), UNMOVABLE_INS | (flags & SET_FLAGS)));
|
||||
FAIL_IF(push_inst(compiler, OR | D(dst) | S1(0) | IMM(-1), DR(dst)));
|
||||
|
||||
/* Loop. */
|
||||
FAIL_IF(push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(TMP_REG1) | S2(0), SET_FLAGS));
|
||||
FAIL_IF(push_inst(compiler, SLL | D(TMP_REG1) | S1(TMP_REG1) | IMM(1), DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, BICC | DA(0xe) | (-2 & DISP_MASK), UNMOVABLE_INS));
|
||||
return push_inst(compiler, ADD | (flags & SET_FLAGS) | D(dst) | S1(dst) | IMM(1), UNMOVABLE_INS | (flags & SET_FLAGS));
|
||||
|
||||
case SLJIT_ADD:
|
||||
return push_inst(compiler, ADD | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
|
||||
|
||||
case SLJIT_ADDC:
|
||||
return push_inst(compiler, ADDC | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
|
||||
|
||||
case SLJIT_SUB:
|
||||
return push_inst(compiler, SUB | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
|
||||
|
||||
case SLJIT_SUBC:
|
||||
return push_inst(compiler, SUBC | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
|
||||
|
||||
case SLJIT_MUL:
|
||||
FAIL_IF(push_inst(compiler, SMUL | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst)));
|
||||
if (!(flags & SET_FLAGS))
|
||||
return SLJIT_SUCCESS;
|
||||
FAIL_IF(push_inst(compiler, SRA | D(TMP_REG1) | S1(dst) | IMM(31), DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, RDY | D(TMP_LINK), DR(TMP_LINK)));
|
||||
return push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(TMP_REG1) | S2(TMP_LINK), MOVABLE_INS | SET_FLAGS);
|
||||
|
||||
case SLJIT_AND:
|
||||
return push_inst(compiler, AND | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
|
||||
|
||||
case SLJIT_OR:
|
||||
return push_inst(compiler, OR | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
|
||||
|
||||
case SLJIT_XOR:
|
||||
return push_inst(compiler, XOR | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
|
||||
|
||||
case SLJIT_SHL:
|
||||
FAIL_IF(push_inst(compiler, SLL | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst)));
|
||||
return !(flags & SET_FLAGS) ? SLJIT_SUCCESS : push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(dst) | S2(0), SET_FLAGS);
|
||||
|
||||
case SLJIT_LSHR:
|
||||
FAIL_IF(push_inst(compiler, SRL | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst)));
|
||||
return !(flags & SET_FLAGS) ? SLJIT_SUCCESS : push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(dst) | S2(0), SET_FLAGS);
|
||||
|
||||
case SLJIT_ASHR:
|
||||
FAIL_IF(push_inst(compiler, SRA | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst)));
|
||||
return !(flags & SET_FLAGS) ? SLJIT_SUCCESS : push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(dst) | S2(0), SET_FLAGS);
|
||||
}
|
||||
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw init_value)
|
||||
{
|
||||
FAIL_IF(push_inst(compiler, SETHI | D(dst) | ((init_value >> 10) & 0x3fffff), DR(dst)));
|
||||
return push_inst(compiler, OR | D(dst) | S1(dst) | IMM_ARG | (init_value & 0x3ff), DR(dst));
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins*)addr;
|
||||
|
||||
inst[0] = (inst[0] & 0xffc00000) | ((new_addr >> 10) & 0x3fffff);
|
||||
inst[1] = (inst[1] & 0xfffffc00) | (new_addr & 0x3ff);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 2);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins*)addr;
|
||||
|
||||
inst[0] = (inst[0] & 0xffc00000) | ((new_constant >> 10) & 0x3fffff);
|
||||
inst[1] = (inst[1] & 0xfffffc00) | (new_constant & 0x3ff);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 2);
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,550 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* x86 32-bit arch dependent functions. */
|
||||
|
||||
static sljit_si emit_do_imm(struct sljit_compiler *compiler, sljit_ub opcode, sljit_sw imm)
|
||||
{
|
||||
sljit_ub *inst;
|
||||
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + sizeof(sljit_sw));
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(1 + sizeof(sljit_sw));
|
||||
*inst++ = opcode;
|
||||
*(sljit_sw*)inst = imm;
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, sljit_si type)
|
||||
{
|
||||
if (type == SLJIT_JUMP) {
|
||||
*code_ptr++ = JMP_i32;
|
||||
jump->addr++;
|
||||
}
|
||||
else if (type >= SLJIT_FAST_CALL) {
|
||||
*code_ptr++ = CALL_i32;
|
||||
jump->addr++;
|
||||
}
|
||||
else {
|
||||
*code_ptr++ = GROUP_0F;
|
||||
*code_ptr++ = get_jump_code(type);
|
||||
jump->addr += 2;
|
||||
}
|
||||
|
||||
if (jump->flags & JUMP_LABEL)
|
||||
jump->flags |= PATCH_MW;
|
||||
else
|
||||
*(sljit_sw*)code_ptr = jump->u.target - (jump->addr + 4);
|
||||
code_ptr += 4;
|
||||
|
||||
return code_ptr;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler,
|
||||
sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
|
||||
sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
|
||||
{
|
||||
sljit_si size;
|
||||
sljit_ub *inst;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
compiler->args = args;
|
||||
compiler->flags_saved = 0;
|
||||
|
||||
size = 1 + (scratches > 7 ? (scratches - 7) : 0) + (saveds <= 3 ? saveds : 3);
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
size += (args > 0 ? (args * 2) : 0) + (args > 2 ? 2 : 0);
|
||||
#else
|
||||
size += (args > 0 ? (2 + args * 3) : 0);
|
||||
#endif
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(size);
|
||||
PUSH_REG(reg_map[TMP_REG1]);
|
||||
#if !(defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
if (args > 0) {
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (reg_map[TMP_REG1] << 3) | 0x4 /* esp */;
|
||||
}
|
||||
#endif
|
||||
if (saveds > 2 || scratches > 7)
|
||||
PUSH_REG(reg_map[SLJIT_S2]);
|
||||
if (saveds > 1 || scratches > 8)
|
||||
PUSH_REG(reg_map[SLJIT_S1]);
|
||||
if (saveds > 0 || scratches > 9)
|
||||
PUSH_REG(reg_map[SLJIT_S0]);
|
||||
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
if (args > 0) {
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (reg_map[SLJIT_S0] << 3) | reg_map[SLJIT_R2];
|
||||
}
|
||||
if (args > 1) {
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (reg_map[SLJIT_S1] << 3) | reg_map[SLJIT_R1];
|
||||
}
|
||||
if (args > 2) {
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_S2] << 3) | 0x4 /* esp */;
|
||||
*inst++ = 0x24;
|
||||
*inst++ = sizeof(sljit_sw) * (3 + 2); /* saveds >= 3 as well. */
|
||||
}
|
||||
#else
|
||||
if (args > 0) {
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_S0] << 3) | reg_map[TMP_REG1];
|
||||
*inst++ = sizeof(sljit_sw) * 2;
|
||||
}
|
||||
if (args > 1) {
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_S1] << 3) | reg_map[TMP_REG1];
|
||||
*inst++ = sizeof(sljit_sw) * 3;
|
||||
}
|
||||
if (args > 2) {
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_S2] << 3) | reg_map[TMP_REG1];
|
||||
*inst++ = sizeof(sljit_sw) * 4;
|
||||
}
|
||||
#endif
|
||||
|
||||
SLJIT_COMPILE_ASSERT(SLJIT_LOCALS_OFFSET >= (2 + 4) * sizeof(sljit_uw), require_at_least_two_words);
|
||||
#if defined(__APPLE__)
|
||||
/* Ignore pushed registers and SLJIT_LOCALS_OFFSET when computing the aligned local size. */
|
||||
saveds = (2 + (scratches > 7 ? (scratches - 7) : 0) + (saveds <= 3 ? saveds : 3)) * sizeof(sljit_uw);
|
||||
local_size = ((SLJIT_LOCALS_OFFSET + saveds + local_size + 15) & ~15) - saveds;
|
||||
#else
|
||||
if (options & SLJIT_DOUBLE_ALIGNMENT) {
|
||||
local_size = SLJIT_LOCALS_OFFSET + ((local_size + 7) & ~7);
|
||||
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 17);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(17);
|
||||
inst[0] = MOV_r_rm;
|
||||
inst[1] = MOD_REG | (reg_map[TMP_REG1] << 3) | reg_map[SLJIT_SP];
|
||||
inst[2] = GROUP_F7;
|
||||
inst[3] = MOD_REG | (0 << 3) | reg_map[SLJIT_SP];
|
||||
*(sljit_sw*)(inst + 4) = 0x4;
|
||||
inst[8] = JNE_i8;
|
||||
inst[9] = 6;
|
||||
inst[10] = GROUP_BINARY_81;
|
||||
inst[11] = MOD_REG | (5 << 3) | reg_map[SLJIT_SP];
|
||||
*(sljit_sw*)(inst + 12) = 0x4;
|
||||
inst[16] = PUSH_r + reg_map[TMP_REG1];
|
||||
}
|
||||
else
|
||||
local_size = SLJIT_LOCALS_OFFSET + ((local_size + 3) & ~3);
|
||||
#endif
|
||||
|
||||
compiler->local_size = local_size;
|
||||
#ifdef _WIN32
|
||||
if (local_size > 1024) {
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
FAIL_IF(emit_do_imm(compiler, MOV_r_i32 + reg_map[SLJIT_R0], local_size));
|
||||
#else
|
||||
local_size -= SLJIT_LOCALS_OFFSET;
|
||||
FAIL_IF(emit_do_imm(compiler, MOV_r_i32 + reg_map[SLJIT_R0], local_size));
|
||||
FAIL_IF(emit_non_cum_binary(compiler, SUB_r_rm, SUB_rm_r, SUB, SUB_EAX_i32,
|
||||
SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, SLJIT_LOCALS_OFFSET));
|
||||
#endif
|
||||
FAIL_IF(sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_grow_stack)));
|
||||
}
|
||||
#endif
|
||||
|
||||
SLJIT_ASSERT(local_size > 0);
|
||||
return emit_non_cum_binary(compiler, SUB_r_rm, SUB_rm_r, SUB, SUB_EAX_i32,
|
||||
SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_set_context(struct sljit_compiler *compiler,
|
||||
sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
|
||||
sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
set_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
compiler->args = args;
|
||||
|
||||
#if defined(__APPLE__)
|
||||
saveds = (2 + (scratches > 7 ? (scratches - 7) : 0) + (saveds <= 3 ? saveds : 3)) * sizeof(sljit_uw);
|
||||
compiler->local_size = ((SLJIT_LOCALS_OFFSET + saveds + local_size + 15) & ~15) - saveds;
|
||||
#else
|
||||
if (options & SLJIT_DOUBLE_ALIGNMENT)
|
||||
compiler->local_size = SLJIT_LOCALS_OFFSET + ((local_size + 7) & ~7);
|
||||
else
|
||||
compiler->local_size = SLJIT_LOCALS_OFFSET + ((local_size + 3) & ~3);
|
||||
#endif
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
sljit_si size;
|
||||
sljit_ub *inst;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_return(compiler, op, src, srcw));
|
||||
SLJIT_ASSERT(compiler->args >= 0);
|
||||
|
||||
compiler->flags_saved = 0;
|
||||
FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
|
||||
|
||||
SLJIT_ASSERT(compiler->local_size > 0);
|
||||
FAIL_IF(emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
|
||||
SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, compiler->local_size));
|
||||
|
||||
#if !defined(__APPLE__)
|
||||
if (compiler->options & SLJIT_DOUBLE_ALIGNMENT) {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 3);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(3);
|
||||
inst[0] = MOV_r_rm;
|
||||
inst[1] = (reg_map[SLJIT_SP] << 3) | 0x4 /* SIB */;
|
||||
inst[2] = (4 << 3) | reg_map[SLJIT_SP];
|
||||
}
|
||||
#endif
|
||||
|
||||
size = 2 + (compiler->scratches > 7 ? (compiler->scratches - 7) : 0) +
|
||||
(compiler->saveds <= 3 ? compiler->saveds : 3);
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
if (compiler->args > 2)
|
||||
size += 2;
|
||||
#else
|
||||
if (compiler->args > 0)
|
||||
size += 2;
|
||||
#endif
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(size);
|
||||
|
||||
if (compiler->saveds > 0 || compiler->scratches > 9)
|
||||
POP_REG(reg_map[SLJIT_S0]);
|
||||
if (compiler->saveds > 1 || compiler->scratches > 8)
|
||||
POP_REG(reg_map[SLJIT_S1]);
|
||||
if (compiler->saveds > 2 || compiler->scratches > 7)
|
||||
POP_REG(reg_map[SLJIT_S2]);
|
||||
POP_REG(reg_map[TMP_REG1]);
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
if (compiler->args > 2)
|
||||
RET_I16(sizeof(sljit_sw));
|
||||
else
|
||||
RET();
|
||||
#else
|
||||
RET();
|
||||
#endif
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Operators */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* Size contains the flags as well. */
|
||||
static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si size,
|
||||
/* The register or immediate operand. */
|
||||
sljit_si a, sljit_sw imma,
|
||||
/* The general operand (not immediate). */
|
||||
sljit_si b, sljit_sw immb)
|
||||
{
|
||||
sljit_ub *inst;
|
||||
sljit_ub *buf_ptr;
|
||||
sljit_si flags = size & ~0xf;
|
||||
sljit_si inst_size;
|
||||
|
||||
/* Both cannot be switched on. */
|
||||
SLJIT_ASSERT((flags & (EX86_BIN_INS | EX86_SHIFT_INS)) != (EX86_BIN_INS | EX86_SHIFT_INS));
|
||||
/* Size flags not allowed for typed instructions. */
|
||||
SLJIT_ASSERT(!(flags & (EX86_BIN_INS | EX86_SHIFT_INS)) || (flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) == 0);
|
||||
/* Both size flags cannot be switched on. */
|
||||
SLJIT_ASSERT((flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) != (EX86_BYTE_ARG | EX86_HALF_ARG));
|
||||
/* SSE2 and immediate is not possible. */
|
||||
SLJIT_ASSERT(!(a & SLJIT_IMM) || !(flags & EX86_SSE2));
|
||||
SLJIT_ASSERT((flags & (EX86_PREF_F2 | EX86_PREF_F3)) != (EX86_PREF_F2 | EX86_PREF_F3)
|
||||
&& (flags & (EX86_PREF_F2 | EX86_PREF_66)) != (EX86_PREF_F2 | EX86_PREF_66)
|
||||
&& (flags & (EX86_PREF_F3 | EX86_PREF_66)) != (EX86_PREF_F3 | EX86_PREF_66));
|
||||
|
||||
size &= 0xf;
|
||||
inst_size = size;
|
||||
|
||||
if (flags & (EX86_PREF_F2 | EX86_PREF_F3))
|
||||
inst_size++;
|
||||
if (flags & EX86_PREF_66)
|
||||
inst_size++;
|
||||
|
||||
/* Calculate size of b. */
|
||||
inst_size += 1; /* mod r/m byte. */
|
||||
if (b & SLJIT_MEM) {
|
||||
if ((b & REG_MASK) == SLJIT_UNUSED)
|
||||
inst_size += sizeof(sljit_sw);
|
||||
else if (immb != 0 && !(b & OFFS_REG_MASK)) {
|
||||
/* Immediate operand. */
|
||||
if (immb <= 127 && immb >= -128)
|
||||
inst_size += sizeof(sljit_sb);
|
||||
else
|
||||
inst_size += sizeof(sljit_sw);
|
||||
}
|
||||
|
||||
if ((b & REG_MASK) == SLJIT_SP && !(b & OFFS_REG_MASK))
|
||||
b |= TO_OFFS_REG(SLJIT_SP);
|
||||
|
||||
if ((b & OFFS_REG_MASK) != SLJIT_UNUSED)
|
||||
inst_size += 1; /* SIB byte. */
|
||||
}
|
||||
|
||||
/* Calculate size of a. */
|
||||
if (a & SLJIT_IMM) {
|
||||
if (flags & EX86_BIN_INS) {
|
||||
if (imma <= 127 && imma >= -128) {
|
||||
inst_size += 1;
|
||||
flags |= EX86_BYTE_ARG;
|
||||
} else
|
||||
inst_size += 4;
|
||||
}
|
||||
else if (flags & EX86_SHIFT_INS) {
|
||||
imma &= 0x1f;
|
||||
if (imma != 1) {
|
||||
inst_size ++;
|
||||
flags |= EX86_BYTE_ARG;
|
||||
}
|
||||
} else if (flags & EX86_BYTE_ARG)
|
||||
inst_size++;
|
||||
else if (flags & EX86_HALF_ARG)
|
||||
inst_size += sizeof(short);
|
||||
else
|
||||
inst_size += sizeof(sljit_sw);
|
||||
}
|
||||
else
|
||||
SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG);
|
||||
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + inst_size);
|
||||
PTR_FAIL_IF(!inst);
|
||||
|
||||
/* Encoding the byte. */
|
||||
INC_SIZE(inst_size);
|
||||
if (flags & EX86_PREF_F2)
|
||||
*inst++ = 0xf2;
|
||||
if (flags & EX86_PREF_F3)
|
||||
*inst++ = 0xf3;
|
||||
if (flags & EX86_PREF_66)
|
||||
*inst++ = 0x66;
|
||||
|
||||
buf_ptr = inst + size;
|
||||
|
||||
/* Encode mod/rm byte. */
|
||||
if (!(flags & EX86_SHIFT_INS)) {
|
||||
if ((flags & EX86_BIN_INS) && (a & SLJIT_IMM))
|
||||
*inst = (flags & EX86_BYTE_ARG) ? GROUP_BINARY_83 : GROUP_BINARY_81;
|
||||
|
||||
if ((a & SLJIT_IMM) || (a == 0))
|
||||
*buf_ptr = 0;
|
||||
else if (!(flags & EX86_SSE2_OP1))
|
||||
*buf_ptr = reg_map[a] << 3;
|
||||
else
|
||||
*buf_ptr = a << 3;
|
||||
}
|
||||
else {
|
||||
if (a & SLJIT_IMM) {
|
||||
if (imma == 1)
|
||||
*inst = GROUP_SHIFT_1;
|
||||
else
|
||||
*inst = GROUP_SHIFT_N;
|
||||
} else
|
||||
*inst = GROUP_SHIFT_CL;
|
||||
*buf_ptr = 0;
|
||||
}
|
||||
|
||||
if (!(b & SLJIT_MEM))
|
||||
*buf_ptr++ |= MOD_REG + ((!(flags & EX86_SSE2_OP2)) ? reg_map[b] : b);
|
||||
else if ((b & REG_MASK) != SLJIT_UNUSED) {
|
||||
if ((b & OFFS_REG_MASK) == SLJIT_UNUSED || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP)) {
|
||||
if (immb != 0) {
|
||||
if (immb <= 127 && immb >= -128)
|
||||
*buf_ptr |= 0x40;
|
||||
else
|
||||
*buf_ptr |= 0x80;
|
||||
}
|
||||
|
||||
if ((b & OFFS_REG_MASK) == SLJIT_UNUSED)
|
||||
*buf_ptr++ |= reg_map[b & REG_MASK];
|
||||
else {
|
||||
*buf_ptr++ |= 0x04;
|
||||
*buf_ptr++ = reg_map[b & REG_MASK] | (reg_map[OFFS_REG(b)] << 3);
|
||||
}
|
||||
|
||||
if (immb != 0) {
|
||||
if (immb <= 127 && immb >= -128)
|
||||
*buf_ptr++ = immb; /* 8 bit displacement. */
|
||||
else {
|
||||
*(sljit_sw*)buf_ptr = immb; /* 32 bit displacement. */
|
||||
buf_ptr += sizeof(sljit_sw);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
*buf_ptr++ |= 0x04;
|
||||
*buf_ptr++ = reg_map[b & REG_MASK] | (reg_map[OFFS_REG(b)] << 3) | (immb << 6);
|
||||
}
|
||||
}
|
||||
else {
|
||||
*buf_ptr++ |= 0x05;
|
||||
*(sljit_sw*)buf_ptr = immb; /* 32 bit displacement. */
|
||||
buf_ptr += sizeof(sljit_sw);
|
||||
}
|
||||
|
||||
if (a & SLJIT_IMM) {
|
||||
if (flags & EX86_BYTE_ARG)
|
||||
*buf_ptr = imma;
|
||||
else if (flags & EX86_HALF_ARG)
|
||||
*(short*)buf_ptr = imma;
|
||||
else if (!(flags & EX86_SHIFT_INS))
|
||||
*(sljit_sw*)buf_ptr = imma;
|
||||
}
|
||||
|
||||
return !(flags & EX86_SHIFT_INS) ? inst : (inst + 1);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Call / return instructions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static SLJIT_INLINE sljit_si call_with_args(struct sljit_compiler *compiler, sljit_si type)
|
||||
{
|
||||
sljit_ub *inst;
|
||||
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
inst = (sljit_ub*)ensure_buf(compiler, type >= SLJIT_CALL3 ? 1 + 2 + 1 : 1 + 2);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(type >= SLJIT_CALL3 ? 2 + 1 : 2);
|
||||
|
||||
if (type >= SLJIT_CALL3)
|
||||
PUSH_REG(reg_map[SLJIT_R2]);
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (reg_map[SLJIT_R2] << 3) | reg_map[SLJIT_R0];
|
||||
#else
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 4 * (type - SLJIT_CALL0));
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(4 * (type - SLJIT_CALL0));
|
||||
|
||||
*inst++ = MOV_rm_r;
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_R0] << 3) | 0x4 /* SIB */;
|
||||
*inst++ = (0x4 /* none*/ << 3) | reg_map[SLJIT_SP];
|
||||
*inst++ = 0;
|
||||
if (type >= SLJIT_CALL2) {
|
||||
*inst++ = MOV_rm_r;
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_R1] << 3) | 0x4 /* SIB */;
|
||||
*inst++ = (0x4 /* none*/ << 3) | reg_map[SLJIT_SP];
|
||||
*inst++ = sizeof(sljit_sw);
|
||||
}
|
||||
if (type >= SLJIT_CALL3) {
|
||||
*inst++ = MOV_rm_r;
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_R2] << 3) | 0x4 /* SIB */;
|
||||
*inst++ = (0x4 /* none*/ << 3) | reg_map[SLJIT_SP];
|
||||
*inst++ = 2 * sizeof(sljit_sw);
|
||||
}
|
||||
#endif
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
|
||||
{
|
||||
sljit_ub *inst;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
|
||||
ADJUST_LOCAL_OFFSET(dst, dstw);
|
||||
|
||||
CHECK_EXTRA_REGS(dst, dstw, (void)0);
|
||||
|
||||
/* For UNUSED dst. Uncommon, but possible. */
|
||||
if (dst == SLJIT_UNUSED)
|
||||
dst = TMP_REG1;
|
||||
|
||||
if (FAST_IS_REG(dst)) {
|
||||
/* Unused dest is possible here. */
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(1);
|
||||
POP_REG(reg_map[dst]);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
/* Memory. */
|
||||
inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
|
||||
FAIL_IF(!inst);
|
||||
*inst++ = POP_rm;
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
sljit_ub *inst;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_fast_return(compiler, src, srcw));
|
||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
|
||||
CHECK_EXTRA_REGS(src, srcw, (void)0);
|
||||
|
||||
if (FAST_IS_REG(src)) {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 1);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(1 + 1);
|
||||
PUSH_REG(reg_map[src]);
|
||||
}
|
||||
else if (src & SLJIT_MEM) {
|
||||
inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
|
||||
FAIL_IF(!inst);
|
||||
*inst++ = GROUP_FF;
|
||||
*inst |= PUSH_rm;
|
||||
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(1);
|
||||
}
|
||||
else {
|
||||
/* SLJIT_IMM. */
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 5 + 1);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(5 + 1);
|
||||
*inst++ = PUSH_i32;
|
||||
*(sljit_sw*)inst = srcw;
|
||||
inst += sizeof(sljit_sw);
|
||||
}
|
||||
|
||||
RET();
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,747 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* x86 64-bit arch dependent functions. */
|
||||
|
||||
static sljit_si emit_load_imm64(struct sljit_compiler *compiler, sljit_si reg, sljit_sw imm)
|
||||
{
|
||||
sljit_ub *inst;
|
||||
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 2 + sizeof(sljit_sw));
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(2 + sizeof(sljit_sw));
|
||||
*inst++ = REX_W | ((reg_map[reg] <= 7) ? 0 : REX_B);
|
||||
*inst++ = MOV_r_i32 + (reg_map[reg] & 0x7);
|
||||
*(sljit_sw*)inst = imm;
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, sljit_si type)
|
||||
{
|
||||
if (type < SLJIT_JUMP) {
|
||||
/* Invert type. */
|
||||
*code_ptr++ = get_jump_code(type ^ 0x1) - 0x10;
|
||||
*code_ptr++ = 10 + 3;
|
||||
}
|
||||
|
||||
SLJIT_COMPILE_ASSERT(reg_map[TMP_REG3] == 9, tmp3_is_9_first);
|
||||
*code_ptr++ = REX_W | REX_B;
|
||||
*code_ptr++ = MOV_r_i32 + 1;
|
||||
jump->addr = (sljit_uw)code_ptr;
|
||||
|
||||
if (jump->flags & JUMP_LABEL)
|
||||
jump->flags |= PATCH_MD;
|
||||
else
|
||||
*(sljit_sw*)code_ptr = jump->u.target;
|
||||
|
||||
code_ptr += sizeof(sljit_sw);
|
||||
*code_ptr++ = REX_B;
|
||||
*code_ptr++ = GROUP_FF;
|
||||
*code_ptr++ = (type >= SLJIT_FAST_CALL) ? (MOD_REG | CALL_rm | 1) : (MOD_REG | JMP_rm | 1);
|
||||
|
||||
return code_ptr;
|
||||
}
|
||||
|
||||
static sljit_ub* generate_fixed_jump(sljit_ub *code_ptr, sljit_sw addr, sljit_si type)
|
||||
{
|
||||
sljit_sw delta = addr - ((sljit_sw)code_ptr + 1 + sizeof(sljit_si));
|
||||
|
||||
if (delta <= HALFWORD_MAX && delta >= HALFWORD_MIN) {
|
||||
*code_ptr++ = (type == 2) ? CALL_i32 : JMP_i32;
|
||||
*(sljit_sw*)code_ptr = delta;
|
||||
}
|
||||
else {
|
||||
SLJIT_COMPILE_ASSERT(reg_map[TMP_REG3] == 9, tmp3_is_9_second);
|
||||
*code_ptr++ = REX_W | REX_B;
|
||||
*code_ptr++ = MOV_r_i32 + 1;
|
||||
*(sljit_sw*)code_ptr = addr;
|
||||
code_ptr += sizeof(sljit_sw);
|
||||
*code_ptr++ = REX_B;
|
||||
*code_ptr++ = GROUP_FF;
|
||||
*code_ptr++ = (type == 2) ? (MOD_REG | CALL_rm | 1) : (MOD_REG | JMP_rm | 1);
|
||||
}
|
||||
|
||||
return code_ptr;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler,
|
||||
sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
|
||||
sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
|
||||
{
|
||||
sljit_si i, tmp, size, saved_register_size;
|
||||
sljit_ub *inst;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
compiler->flags_saved = 0;
|
||||
|
||||
/* Including the return address saved by the call instruction. */
|
||||
saved_register_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
|
||||
|
||||
tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
|
||||
for (i = SLJIT_S0; i >= tmp; i--) {
|
||||
size = reg_map[i] >= 8 ? 2 : 1;
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(size);
|
||||
if (reg_map[i] >= 8)
|
||||
*inst++ = REX_B;
|
||||
PUSH_REG(reg_lmap[i]);
|
||||
}
|
||||
|
||||
for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
|
||||
size = reg_map[i] >= 8 ? 2 : 1;
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(size);
|
||||
if (reg_map[i] >= 8)
|
||||
*inst++ = REX_B;
|
||||
PUSH_REG(reg_lmap[i]);
|
||||
}
|
||||
|
||||
if (args > 0) {
|
||||
size = args * 3;
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(size);
|
||||
|
||||
#ifndef _WIN64
|
||||
if (args > 0) {
|
||||
*inst++ = REX_W;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (reg_map[SLJIT_S0] << 3) | 0x7 /* rdi */;
|
||||
}
|
||||
if (args > 1) {
|
||||
*inst++ = REX_W | REX_R;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (reg_lmap[SLJIT_S1] << 3) | 0x6 /* rsi */;
|
||||
}
|
||||
if (args > 2) {
|
||||
*inst++ = REX_W | REX_R;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (reg_lmap[SLJIT_S2] << 3) | 0x2 /* rdx */;
|
||||
}
|
||||
#else
|
||||
if (args > 0) {
|
||||
*inst++ = REX_W;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (reg_map[SLJIT_S0] << 3) | 0x1 /* rcx */;
|
||||
}
|
||||
if (args > 1) {
|
||||
*inst++ = REX_W;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (reg_map[SLJIT_S1] << 3) | 0x2 /* rdx */;
|
||||
}
|
||||
if (args > 2) {
|
||||
*inst++ = REX_W | REX_B;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (reg_map[SLJIT_S2] << 3) | 0x0 /* r8 */;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
local_size = ((local_size + SLJIT_LOCALS_OFFSET + saved_register_size + 15) & ~15) - saved_register_size;
|
||||
compiler->local_size = local_size;
|
||||
|
||||
#ifdef _WIN64
|
||||
if (local_size > 1024) {
|
||||
/* Allocate stack for the callback, which grows the stack. */
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 4 + (3 + sizeof(sljit_si)));
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(4 + (3 + sizeof(sljit_si)));
|
||||
*inst++ = REX_W;
|
||||
*inst++ = GROUP_BINARY_83;
|
||||
*inst++ = MOD_REG | SUB | 4;
|
||||
/* Allocated size for registers must be divisible by 8. */
|
||||
SLJIT_ASSERT(!(saved_register_size & 0x7));
|
||||
/* Aligned to 16 byte. */
|
||||
if (saved_register_size & 0x8) {
|
||||
*inst++ = 5 * sizeof(sljit_sw);
|
||||
local_size -= 5 * sizeof(sljit_sw);
|
||||
} else {
|
||||
*inst++ = 4 * sizeof(sljit_sw);
|
||||
local_size -= 4 * sizeof(sljit_sw);
|
||||
}
|
||||
/* Second instruction */
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_R0] < 8, temporary_reg1_is_loreg);
|
||||
*inst++ = REX_W;
|
||||
*inst++ = MOV_rm_i32;
|
||||
*inst++ = MOD_REG | reg_lmap[SLJIT_R0];
|
||||
*(sljit_si*)inst = local_size;
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
FAIL_IF(sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_grow_stack)));
|
||||
}
|
||||
#endif
|
||||
|
||||
SLJIT_ASSERT(local_size > 0);
|
||||
if (local_size <= 127) {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 4);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(4);
|
||||
*inst++ = REX_W;
|
||||
*inst++ = GROUP_BINARY_83;
|
||||
*inst++ = MOD_REG | SUB | 4;
|
||||
*inst++ = local_size;
|
||||
}
|
||||
else {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 7);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(7);
|
||||
*inst++ = REX_W;
|
||||
*inst++ = GROUP_BINARY_81;
|
||||
*inst++ = MOD_REG | SUB | 4;
|
||||
*(sljit_si*)inst = local_size;
|
||||
inst += sizeof(sljit_si);
|
||||
}
|
||||
|
||||
#ifdef _WIN64
|
||||
/* Save xmm6 register: movaps [rsp + 0x20], xmm6 */
|
||||
if (fscratches >= 6 || fsaveds >= 1) {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 5);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(5);
|
||||
*inst++ = GROUP_0F;
|
||||
*(sljit_si*)inst = 0x20247429;
|
||||
}
|
||||
#endif
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_set_context(struct sljit_compiler *compiler,
|
||||
sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
|
||||
sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
|
||||
{
|
||||
sljit_si saved_register_size;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
set_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
/* Including the return address saved by the call instruction. */
|
||||
saved_register_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
|
||||
compiler->local_size = ((local_size + SLJIT_LOCALS_OFFSET + saved_register_size + 15) & ~15) - saved_register_size;
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
sljit_si i, tmp, size;
|
||||
sljit_ub *inst;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_return(compiler, op, src, srcw));
|
||||
|
||||
compiler->flags_saved = 0;
|
||||
FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
|
||||
|
||||
#ifdef _WIN64
|
||||
/* Restore xmm6 register: movaps xmm6, [rsp + 0x20] */
|
||||
if (compiler->fscratches >= 6 || compiler->fsaveds >= 1) {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 5);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(5);
|
||||
*inst++ = GROUP_0F;
|
||||
*(sljit_si*)inst = 0x20247428;
|
||||
}
|
||||
#endif
|
||||
|
||||
SLJIT_ASSERT(compiler->local_size > 0);
|
||||
if (compiler->local_size <= 127) {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 4);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(4);
|
||||
*inst++ = REX_W;
|
||||
*inst++ = GROUP_BINARY_83;
|
||||
*inst++ = MOD_REG | ADD | 4;
|
||||
*inst = compiler->local_size;
|
||||
}
|
||||
else {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 7);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(7);
|
||||
*inst++ = REX_W;
|
||||
*inst++ = GROUP_BINARY_81;
|
||||
*inst++ = MOD_REG | ADD | 4;
|
||||
*(sljit_si*)inst = compiler->local_size;
|
||||
}
|
||||
|
||||
tmp = compiler->scratches;
|
||||
for (i = SLJIT_FIRST_SAVED_REG; i <= tmp; i++) {
|
||||
size = reg_map[i] >= 8 ? 2 : 1;
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(size);
|
||||
if (reg_map[i] >= 8)
|
||||
*inst++ = REX_B;
|
||||
POP_REG(reg_lmap[i]);
|
||||
}
|
||||
|
||||
tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;
|
||||
for (i = tmp; i <= SLJIT_S0; i++) {
|
||||
size = reg_map[i] >= 8 ? 2 : 1;
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(size);
|
||||
if (reg_map[i] >= 8)
|
||||
*inst++ = REX_B;
|
||||
POP_REG(reg_lmap[i]);
|
||||
}
|
||||
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(1);
|
||||
RET();
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Operators */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static sljit_si emit_do_imm32(struct sljit_compiler *compiler, sljit_ub rex, sljit_ub opcode, sljit_sw imm)
|
||||
{
|
||||
sljit_ub *inst;
|
||||
sljit_si length = 1 + (rex ? 1 : 0) + sizeof(sljit_si);
|
||||
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + length);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(length);
|
||||
if (rex)
|
||||
*inst++ = rex;
|
||||
*inst++ = opcode;
|
||||
*(sljit_si*)inst = imm;
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si size,
|
||||
/* The register or immediate operand. */
|
||||
sljit_si a, sljit_sw imma,
|
||||
/* The general operand (not immediate). */
|
||||
sljit_si b, sljit_sw immb)
|
||||
{
|
||||
sljit_ub *inst;
|
||||
sljit_ub *buf_ptr;
|
||||
sljit_ub rex = 0;
|
||||
sljit_si flags = size & ~0xf;
|
||||
sljit_si inst_size;
|
||||
|
||||
/* The immediate operand must be 32 bit. */
|
||||
SLJIT_ASSERT(!(a & SLJIT_IMM) || compiler->mode32 || IS_HALFWORD(imma));
|
||||
/* Both cannot be switched on. */
|
||||
SLJIT_ASSERT((flags & (EX86_BIN_INS | EX86_SHIFT_INS)) != (EX86_BIN_INS | EX86_SHIFT_INS));
|
||||
/* Size flags not allowed for typed instructions. */
|
||||
SLJIT_ASSERT(!(flags & (EX86_BIN_INS | EX86_SHIFT_INS)) || (flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) == 0);
|
||||
/* Both size flags cannot be switched on. */
|
||||
SLJIT_ASSERT((flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) != (EX86_BYTE_ARG | EX86_HALF_ARG));
|
||||
/* SSE2 and immediate is not possible. */
|
||||
SLJIT_ASSERT(!(a & SLJIT_IMM) || !(flags & EX86_SSE2));
|
||||
SLJIT_ASSERT((flags & (EX86_PREF_F2 | EX86_PREF_F3)) != (EX86_PREF_F2 | EX86_PREF_F3)
|
||||
&& (flags & (EX86_PREF_F2 | EX86_PREF_66)) != (EX86_PREF_F2 | EX86_PREF_66)
|
||||
&& (flags & (EX86_PREF_F3 | EX86_PREF_66)) != (EX86_PREF_F3 | EX86_PREF_66));
|
||||
|
||||
size &= 0xf;
|
||||
inst_size = size;
|
||||
|
||||
if (!compiler->mode32 && !(flags & EX86_NO_REXW))
|
||||
rex |= REX_W;
|
||||
else if (flags & EX86_REX)
|
||||
rex |= REX;
|
||||
|
||||
if (flags & (EX86_PREF_F2 | EX86_PREF_F3))
|
||||
inst_size++;
|
||||
if (flags & EX86_PREF_66)
|
||||
inst_size++;
|
||||
|
||||
/* Calculate size of b. */
|
||||
inst_size += 1; /* mod r/m byte. */
|
||||
if (b & SLJIT_MEM) {
|
||||
if (!(b & OFFS_REG_MASK)) {
|
||||
if (NOT_HALFWORD(immb)) {
|
||||
if (emit_load_imm64(compiler, TMP_REG3, immb))
|
||||
return NULL;
|
||||
immb = 0;
|
||||
if (b & REG_MASK)
|
||||
b |= TO_OFFS_REG(TMP_REG3);
|
||||
else
|
||||
b |= TMP_REG3;
|
||||
}
|
||||
else if (reg_lmap[b & REG_MASK] == 4)
|
||||
b |= TO_OFFS_REG(SLJIT_SP);
|
||||
}
|
||||
|
||||
if ((b & REG_MASK) == SLJIT_UNUSED)
|
||||
inst_size += 1 + sizeof(sljit_si); /* SIB byte required to avoid RIP based addressing. */
|
||||
else {
|
||||
if (reg_map[b & REG_MASK] >= 8)
|
||||
rex |= REX_B;
|
||||
|
||||
if (immb != 0 && (!(b & OFFS_REG_MASK) || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP))) {
|
||||
/* Immediate operand. */
|
||||
if (immb <= 127 && immb >= -128)
|
||||
inst_size += sizeof(sljit_sb);
|
||||
else
|
||||
inst_size += sizeof(sljit_si);
|
||||
}
|
||||
else if (reg_lmap[b & REG_MASK] == 5)
|
||||
inst_size += sizeof(sljit_sb);
|
||||
|
||||
if ((b & OFFS_REG_MASK) != SLJIT_UNUSED) {
|
||||
inst_size += 1; /* SIB byte. */
|
||||
if (reg_map[OFFS_REG(b)] >= 8)
|
||||
rex |= REX_X;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!(flags & EX86_SSE2_OP2) && reg_map[b] >= 8)
|
||||
rex |= REX_B;
|
||||
|
||||
if (a & SLJIT_IMM) {
|
||||
if (flags & EX86_BIN_INS) {
|
||||
if (imma <= 127 && imma >= -128) {
|
||||
inst_size += 1;
|
||||
flags |= EX86_BYTE_ARG;
|
||||
} else
|
||||
inst_size += 4;
|
||||
}
|
||||
else if (flags & EX86_SHIFT_INS) {
|
||||
imma &= compiler->mode32 ? 0x1f : 0x3f;
|
||||
if (imma != 1) {
|
||||
inst_size ++;
|
||||
flags |= EX86_BYTE_ARG;
|
||||
}
|
||||
} else if (flags & EX86_BYTE_ARG)
|
||||
inst_size++;
|
||||
else if (flags & EX86_HALF_ARG)
|
||||
inst_size += sizeof(short);
|
||||
else
|
||||
inst_size += sizeof(sljit_si);
|
||||
}
|
||||
else {
|
||||
SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG);
|
||||
/* reg_map[SLJIT_PREF_SHIFT_REG] is less than 8. */
|
||||
if (!(flags & EX86_SSE2_OP1) && reg_map[a] >= 8)
|
||||
rex |= REX_R;
|
||||
}
|
||||
|
||||
if (rex)
|
||||
inst_size++;
|
||||
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + inst_size);
|
||||
PTR_FAIL_IF(!inst);
|
||||
|
||||
/* Encoding the byte. */
|
||||
INC_SIZE(inst_size);
|
||||
if (flags & EX86_PREF_F2)
|
||||
*inst++ = 0xf2;
|
||||
if (flags & EX86_PREF_F3)
|
||||
*inst++ = 0xf3;
|
||||
if (flags & EX86_PREF_66)
|
||||
*inst++ = 0x66;
|
||||
if (rex)
|
||||
*inst++ = rex;
|
||||
buf_ptr = inst + size;
|
||||
|
||||
/* Encode mod/rm byte. */
|
||||
if (!(flags & EX86_SHIFT_INS)) {
|
||||
if ((flags & EX86_BIN_INS) && (a & SLJIT_IMM))
|
||||
*inst = (flags & EX86_BYTE_ARG) ? GROUP_BINARY_83 : GROUP_BINARY_81;
|
||||
|
||||
if ((a & SLJIT_IMM) || (a == 0))
|
||||
*buf_ptr = 0;
|
||||
else if (!(flags & EX86_SSE2_OP1))
|
||||
*buf_ptr = reg_lmap[a] << 3;
|
||||
else
|
||||
*buf_ptr = a << 3;
|
||||
}
|
||||
else {
|
||||
if (a & SLJIT_IMM) {
|
||||
if (imma == 1)
|
||||
*inst = GROUP_SHIFT_1;
|
||||
else
|
||||
*inst = GROUP_SHIFT_N;
|
||||
} else
|
||||
*inst = GROUP_SHIFT_CL;
|
||||
*buf_ptr = 0;
|
||||
}
|
||||
|
||||
if (!(b & SLJIT_MEM))
|
||||
*buf_ptr++ |= MOD_REG + ((!(flags & EX86_SSE2_OP2)) ? reg_lmap[b] : b);
|
||||
else if ((b & REG_MASK) != SLJIT_UNUSED) {
|
||||
if ((b & OFFS_REG_MASK) == SLJIT_UNUSED || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP)) {
|
||||
if (immb != 0 || reg_lmap[b & REG_MASK] == 5) {
|
||||
if (immb <= 127 && immb >= -128)
|
||||
*buf_ptr |= 0x40;
|
||||
else
|
||||
*buf_ptr |= 0x80;
|
||||
}
|
||||
|
||||
if ((b & OFFS_REG_MASK) == SLJIT_UNUSED)
|
||||
*buf_ptr++ |= reg_lmap[b & REG_MASK];
|
||||
else {
|
||||
*buf_ptr++ |= 0x04;
|
||||
*buf_ptr++ = reg_lmap[b & REG_MASK] | (reg_lmap[OFFS_REG(b)] << 3);
|
||||
}
|
||||
|
||||
if (immb != 0 || reg_lmap[b & REG_MASK] == 5) {
|
||||
if (immb <= 127 && immb >= -128)
|
||||
*buf_ptr++ = immb; /* 8 bit displacement. */
|
||||
else {
|
||||
*(sljit_si*)buf_ptr = immb; /* 32 bit displacement. */
|
||||
buf_ptr += sizeof(sljit_si);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (reg_lmap[b & REG_MASK] == 5)
|
||||
*buf_ptr |= 0x40;
|
||||
*buf_ptr++ |= 0x04;
|
||||
*buf_ptr++ = reg_lmap[b & REG_MASK] | (reg_lmap[OFFS_REG(b)] << 3) | (immb << 6);
|
||||
if (reg_lmap[b & REG_MASK] == 5)
|
||||
*buf_ptr++ = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
*buf_ptr++ |= 0x04;
|
||||
*buf_ptr++ = 0x25;
|
||||
*(sljit_si*)buf_ptr = immb; /* 32 bit displacement. */
|
||||
buf_ptr += sizeof(sljit_si);
|
||||
}
|
||||
|
||||
if (a & SLJIT_IMM) {
|
||||
if (flags & EX86_BYTE_ARG)
|
||||
*buf_ptr = imma;
|
||||
else if (flags & EX86_HALF_ARG)
|
||||
*(short*)buf_ptr = imma;
|
||||
else if (!(flags & EX86_SHIFT_INS))
|
||||
*(sljit_si*)buf_ptr = imma;
|
||||
}
|
||||
|
||||
return !(flags & EX86_SHIFT_INS) ? inst : (inst + 1);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Call / return instructions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static SLJIT_INLINE sljit_si call_with_args(struct sljit_compiler *compiler, sljit_si type)
|
||||
{
|
||||
sljit_ub *inst;
|
||||
|
||||
#ifndef _WIN64
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_R1] == 6 && reg_map[SLJIT_R0] < 8 && reg_map[SLJIT_R2] < 8, args_registers);
|
||||
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE((type < SLJIT_CALL3) ? 3 : 6);
|
||||
if (type >= SLJIT_CALL3) {
|
||||
*inst++ = REX_W;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (0x2 /* rdx */ << 3) | reg_lmap[SLJIT_R2];
|
||||
}
|
||||
*inst++ = REX_W;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (0x7 /* rdi */ << 3) | reg_lmap[SLJIT_R0];
|
||||
#else
|
||||
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_R1] == 2 && reg_map[SLJIT_R0] < 8 && reg_map[SLJIT_R2] < 8, args_registers);
|
||||
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE((type < SLJIT_CALL3) ? 3 : 6);
|
||||
if (type >= SLJIT_CALL3) {
|
||||
*inst++ = REX_W | REX_R;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (0x0 /* r8 */ << 3) | reg_lmap[SLJIT_R2];
|
||||
}
|
||||
*inst++ = REX_W;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (0x1 /* rcx */ << 3) | reg_lmap[SLJIT_R0];
|
||||
#endif
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
|
||||
{
|
||||
sljit_ub *inst;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
|
||||
ADJUST_LOCAL_OFFSET(dst, dstw);
|
||||
|
||||
/* For UNUSED dst. Uncommon, but possible. */
|
||||
if (dst == SLJIT_UNUSED)
|
||||
dst = TMP_REG1;
|
||||
|
||||
if (FAST_IS_REG(dst)) {
|
||||
if (reg_map[dst] < 8) {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(1);
|
||||
POP_REG(reg_lmap[dst]);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 2);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(2);
|
||||
*inst++ = REX_B;
|
||||
POP_REG(reg_lmap[dst]);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
/* REX_W is not necessary (src is not immediate). */
|
||||
compiler->mode32 = 1;
|
||||
inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
|
||||
FAIL_IF(!inst);
|
||||
*inst++ = POP_rm;
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
sljit_ub *inst;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_fast_return(compiler, src, srcw));
|
||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
|
||||
if ((src & SLJIT_IMM) && NOT_HALFWORD(srcw)) {
|
||||
FAIL_IF(emit_load_imm64(compiler, TMP_REG1, srcw));
|
||||
src = TMP_REG1;
|
||||
}
|
||||
|
||||
if (FAST_IS_REG(src)) {
|
||||
if (reg_map[src] < 8) {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 1);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(1 + 1);
|
||||
PUSH_REG(reg_lmap[src]);
|
||||
}
|
||||
else {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 2 + 1);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(2 + 1);
|
||||
*inst++ = REX_B;
|
||||
PUSH_REG(reg_lmap[src]);
|
||||
}
|
||||
}
|
||||
else if (src & SLJIT_MEM) {
|
||||
/* REX_W is not necessary (src is not immediate). */
|
||||
compiler->mode32 = 1;
|
||||
inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
|
||||
FAIL_IF(!inst);
|
||||
*inst++ = GROUP_FF;
|
||||
*inst |= PUSH_rm;
|
||||
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(1);
|
||||
}
|
||||
else {
|
||||
SLJIT_ASSERT(IS_HALFWORD(srcw));
|
||||
/* SLJIT_IMM. */
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 5 + 1);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(5 + 1);
|
||||
*inst++ = PUSH_i32;
|
||||
*(sljit_si*)inst = srcw;
|
||||
inst += sizeof(sljit_si);
|
||||
}
|
||||
|
||||
RET();
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Extend input */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static sljit_si emit_mov_int(struct sljit_compiler *compiler, sljit_si sign,
|
||||
sljit_si dst, sljit_sw dstw,
|
||||
sljit_si src, sljit_sw srcw)
|
||||
{
|
||||
sljit_ub* inst;
|
||||
sljit_si dst_r;
|
||||
|
||||
compiler->mode32 = 0;
|
||||
|
||||
if (dst == SLJIT_UNUSED && !(src & SLJIT_MEM))
|
||||
return SLJIT_SUCCESS; /* Empty instruction. */
|
||||
|
||||
if (src & SLJIT_IMM) {
|
||||
if (FAST_IS_REG(dst)) {
|
||||
if (sign || ((sljit_uw)srcw <= 0x7fffffff)) {
|
||||
inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_si)srcw, dst, dstw);
|
||||
FAIL_IF(!inst);
|
||||
*inst = MOV_rm_i32;
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
return emit_load_imm64(compiler, dst, srcw);
|
||||
}
|
||||
compiler->mode32 = 1;
|
||||
inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_si)srcw, dst, dstw);
|
||||
FAIL_IF(!inst);
|
||||
*inst = MOV_rm_i32;
|
||||
compiler->mode32 = 0;
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
|
||||
|
||||
if ((dst & SLJIT_MEM) && FAST_IS_REG(src))
|
||||
dst_r = src;
|
||||
else {
|
||||
if (sign) {
|
||||
inst = emit_x86_instruction(compiler, 1, dst_r, 0, src, srcw);
|
||||
FAIL_IF(!inst);
|
||||
*inst++ = MOVSXD_r_rm;
|
||||
} else {
|
||||
compiler->mode32 = 1;
|
||||
FAIL_IF(emit_mov(compiler, dst_r, 0, src, srcw));
|
||||
compiler->mode32 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (dst & SLJIT_MEM) {
|
||||
compiler->mode32 = 1;
|
||||
inst = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw);
|
||||
FAIL_IF(!inst);
|
||||
*inst = MOV_rm_r;
|
||||
compiler->mode32 = 0;
|
||||
}
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,334 @@
|
||||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* Locks */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) || (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK)
|
||||
|
||||
#if (defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)
|
||||
|
||||
#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
|
||||
|
||||
static SLJIT_INLINE void allocator_grab_lock(void)
|
||||
{
|
||||
/* Always successful. */
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void allocator_release_lock(void)
|
||||
{
|
||||
/* Always successful. */
|
||||
}
|
||||
|
||||
#endif /* SLJIT_EXECUTABLE_ALLOCATOR */
|
||||
|
||||
#if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK)
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_grab_lock(void)
|
||||
{
|
||||
/* Always successful. */
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void)
|
||||
{
|
||||
/* Always successful. */
|
||||
}
|
||||
|
||||
#endif /* SLJIT_UTIL_GLOBAL_LOCK */
|
||||
|
||||
#elif defined(_WIN32) /* SLJIT_SINGLE_THREADED */
|
||||
|
||||
#include "windows.h"
|
||||
|
||||
#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
|
||||
|
||||
static HANDLE allocator_mutex = 0;
|
||||
|
||||
static SLJIT_INLINE void allocator_grab_lock(void)
|
||||
{
|
||||
/* No idea what to do if an error occures. Static mutexes should never fail... */
|
||||
if (!allocator_mutex)
|
||||
allocator_mutex = CreateMutex(NULL, TRUE, NULL);
|
||||
else
|
||||
WaitForSingleObject(allocator_mutex, INFINITE);
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void allocator_release_lock(void)
|
||||
{
|
||||
ReleaseMutex(allocator_mutex);
|
||||
}
|
||||
|
||||
#endif /* SLJIT_EXECUTABLE_ALLOCATOR */
|
||||
|
||||
#if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK)
|
||||
|
||||
static HANDLE global_mutex = 0;
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_grab_lock(void)
|
||||
{
|
||||
/* No idea what to do if an error occures. Static mutexes should never fail... */
|
||||
if (!global_mutex)
|
||||
global_mutex = CreateMutex(NULL, TRUE, NULL);
|
||||
else
|
||||
WaitForSingleObject(global_mutex, INFINITE);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void)
|
||||
{
|
||||
ReleaseMutex(global_mutex);
|
||||
}
|
||||
|
||||
#endif /* SLJIT_UTIL_GLOBAL_LOCK */
|
||||
|
||||
#else /* _WIN32 */
|
||||
|
||||
#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
static pthread_mutex_t allocator_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
static SLJIT_INLINE void allocator_grab_lock(void)
|
||||
{
|
||||
pthread_mutex_lock(&allocator_mutex);
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void allocator_release_lock(void)
|
||||
{
|
||||
pthread_mutex_unlock(&allocator_mutex);
|
||||
}
|
||||
|
||||
#endif /* SLJIT_EXECUTABLE_ALLOCATOR */
|
||||
|
||||
#if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK)
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
static pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_grab_lock(void)
|
||||
{
|
||||
pthread_mutex_lock(&global_mutex);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void)
|
||||
{
|
||||
pthread_mutex_unlock(&global_mutex);
|
||||
}
|
||||
|
||||
#endif /* SLJIT_UTIL_GLOBAL_LOCK */
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* Stack */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) || (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "windows.h"
|
||||
#else
|
||||
/* Provides mmap function. */
|
||||
#include <sys/mman.h>
|
||||
/* For detecting the page size. */
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef MAP_ANON
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
/* Some old systems does not have MAP_ANON. */
|
||||
static sljit_si dev_zero = -1;
|
||||
|
||||
#if (defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)
|
||||
|
||||
static SLJIT_INLINE sljit_si open_dev_zero(void)
|
||||
{
|
||||
dev_zero = open("/dev/zero", O_RDWR);
|
||||
return dev_zero < 0;
|
||||
}
|
||||
|
||||
#else /* SLJIT_SINGLE_THREADED */
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
static pthread_mutex_t dev_zero_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
static SLJIT_INLINE sljit_si open_dev_zero(void)
|
||||
{
|
||||
pthread_mutex_lock(&dev_zero_mutex);
|
||||
dev_zero = open("/dev/zero", O_RDWR);
|
||||
pthread_mutex_unlock(&dev_zero_mutex);
|
||||
return dev_zero < 0;
|
||||
}
|
||||
|
||||
#endif /* SLJIT_SINGLE_THREADED */
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* SLJIT_UTIL_STACK || SLJIT_EXECUTABLE_ALLOCATOR */
|
||||
|
||||
#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK)
|
||||
|
||||
/* Planning to make it even more clever in the future. */
|
||||
static sljit_sw sljit_page_align = 0;
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(sljit_uw limit, sljit_uw max_limit, void *allocator_data)
|
||||
{
|
||||
struct sljit_stack *stack;
|
||||
union {
|
||||
void *ptr;
|
||||
sljit_uw uw;
|
||||
} base;
|
||||
#ifdef _WIN32
|
||||
SYSTEM_INFO si;
|
||||
#endif
|
||||
|
||||
SLJIT_UNUSED_ARG(allocator_data);
|
||||
if (limit > max_limit || limit < 1)
|
||||
return NULL;
|
||||
|
||||
#ifdef _WIN32
|
||||
if (!sljit_page_align) {
|
||||
GetSystemInfo(&si);
|
||||
sljit_page_align = si.dwPageSize - 1;
|
||||
}
|
||||
#else
|
||||
if (!sljit_page_align) {
|
||||
sljit_page_align = sysconf(_SC_PAGESIZE);
|
||||
/* Should never happen. */
|
||||
if (sljit_page_align < 0)
|
||||
sljit_page_align = 4096;
|
||||
sljit_page_align--;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Align limit and max_limit. */
|
||||
max_limit = (max_limit + sljit_page_align) & ~sljit_page_align;
|
||||
|
||||
stack = (struct sljit_stack*)SLJIT_MALLOC(sizeof(struct sljit_stack), allocator_data);
|
||||
if (!stack)
|
||||
return NULL;
|
||||
|
||||
#ifdef _WIN32
|
||||
base.ptr = VirtualAlloc(NULL, max_limit, MEM_RESERVE, PAGE_READWRITE);
|
||||
if (!base.ptr) {
|
||||
SLJIT_FREE(stack, allocator_data);
|
||||
return NULL;
|
||||
}
|
||||
stack->base = base.uw;
|
||||
stack->limit = stack->base;
|
||||
stack->max_limit = stack->base + max_limit;
|
||||
if (sljit_stack_resize(stack, stack->base + limit)) {
|
||||
sljit_free_stack(stack, allocator_data);
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
#ifdef MAP_ANON
|
||||
base.ptr = mmap(NULL, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
#else
|
||||
if (dev_zero < 0) {
|
||||
if (open_dev_zero()) {
|
||||
SLJIT_FREE(stack, allocator_data);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
base.ptr = mmap(NULL, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE, dev_zero, 0);
|
||||
#endif
|
||||
if (base.ptr == MAP_FAILED) {
|
||||
SLJIT_FREE(stack, allocator_data);
|
||||
return NULL;
|
||||
}
|
||||
stack->base = base.uw;
|
||||
stack->limit = stack->base + limit;
|
||||
stack->max_limit = stack->base + max_limit;
|
||||
#endif
|
||||
stack->top = stack->base;
|
||||
return stack;
|
||||
}
|
||||
|
||||
#undef PAGE_ALIGN
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_free_stack(struct sljit_stack* stack, void *allocator_data)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(allocator_data);
|
||||
#ifdef _WIN32
|
||||
VirtualFree((void*)stack->base, 0, MEM_RELEASE);
|
||||
#else
|
||||
munmap((void*)stack->base, stack->max_limit - stack->base);
|
||||
#endif
|
||||
SLJIT_FREE(stack, allocator_data);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_sw SLJIT_CALL sljit_stack_resize(struct sljit_stack* stack, sljit_uw new_limit)
|
||||
{
|
||||
sljit_uw aligned_old_limit;
|
||||
sljit_uw aligned_new_limit;
|
||||
|
||||
if ((new_limit > stack->max_limit) || (new_limit < stack->base))
|
||||
return -1;
|
||||
#ifdef _WIN32
|
||||
aligned_new_limit = (new_limit + sljit_page_align) & ~sljit_page_align;
|
||||
aligned_old_limit = (stack->limit + sljit_page_align) & ~sljit_page_align;
|
||||
if (aligned_new_limit != aligned_old_limit) {
|
||||
if (aligned_new_limit > aligned_old_limit) {
|
||||
if (!VirtualAlloc((void*)aligned_old_limit, aligned_new_limit - aligned_old_limit, MEM_COMMIT, PAGE_READWRITE))
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
if (!VirtualFree((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, MEM_DECOMMIT))
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
stack->limit = new_limit;
|
||||
return 0;
|
||||
#else
|
||||
if (new_limit >= stack->limit) {
|
||||
stack->limit = new_limit;
|
||||
return 0;
|
||||
}
|
||||
aligned_new_limit = (new_limit + sljit_page_align) & ~sljit_page_align;
|
||||
aligned_old_limit = (stack->limit + sljit_page_align) & ~sljit_page_align;
|
||||
/* If madvise is available, we release the unnecessary space. */
|
||||
#if defined(MADV_DONTNEED)
|
||||
if (aligned_new_limit < aligned_old_limit)
|
||||
madvise((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, MADV_DONTNEED);
|
||||
#elif defined(POSIX_MADV_DONTNEED)
|
||||
if (aligned_new_limit < aligned_old_limit)
|
||||
posix_madvise((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, POSIX_MADV_DONTNEED);
|
||||
#endif
|
||||
stack->limit = new_limit;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* SLJIT_UTIL_STACK */
|
||||
|
||||
#endif
|
||||
+76
-76
@@ -136,7 +136,7 @@ static PHP_MINFO_FUNCTION(pcre)
|
||||
static PHP_MINIT_FUNCTION(pcre)
|
||||
{
|
||||
REGISTER_INI_ENTRIES();
|
||||
|
||||
|
||||
REGISTER_LONG_CONSTANT("PREG_PATTERN_ORDER", PREG_PATTERN_ORDER, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("PREG_SET_ORDER", PREG_SET_ORDER, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("PREG_OFFSET_CAPTURE", PREG_OFFSET_CAPTURE, CONST_CS | CONST_PERSISTENT);
|
||||
@@ -276,18 +276,18 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int regex_le
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
p = regex;
|
||||
|
||||
|
||||
/* Parse through the leading whitespace, and display a warning if we
|
||||
get to the end without encountering a delimiter. */
|
||||
while (isspace((int)*(unsigned char *)p)) p++;
|
||||
if (*p == 0) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING,
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING,
|
||||
p < regex + regex_len ? "Null byte in regex" : "Empty regular expression");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Get the delimiter and display a warning if it is alphanumeric
|
||||
or a backslash. */
|
||||
delimiter = *p++;
|
||||
@@ -340,7 +340,7 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int regex_le
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Make a copy of the actual pattern. */
|
||||
pattern = estrndup(p, pp-p);
|
||||
|
||||
@@ -348,7 +348,7 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int regex_le
|
||||
pp++;
|
||||
|
||||
/* Parse through the options, setting appropriate flags. Display
|
||||
a warning if we encounter an unknown modifier. */
|
||||
a warning if we encounter an unknown modifier. */
|
||||
while (pp < regex + regex_len) {
|
||||
switch (*pp++) {
|
||||
/* Perl compatible options */
|
||||
@@ -356,7 +356,7 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int regex_le
|
||||
case 'm': coptions |= PCRE_MULTILINE; break;
|
||||
case 's': coptions |= PCRE_DOTALL; break;
|
||||
case 'x': coptions |= PCRE_EXTENDED; break;
|
||||
|
||||
|
||||
/* PCRE specific options */
|
||||
case 'A': coptions |= PCRE_ANCHORED; break;
|
||||
case 'D': coptions |= PCRE_DOLLAR_ENDONLY;break;
|
||||
@@ -369,12 +369,12 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int regex_le
|
||||
the PCRE_UCP option. */
|
||||
#ifdef PCRE_UCP
|
||||
coptions |= PCRE_UCP;
|
||||
#endif
|
||||
#endif
|
||||
break;
|
||||
|
||||
/* Custom preg options */
|
||||
case 'e': poptions |= PREG_REPLACE_EVAL; break;
|
||||
|
||||
|
||||
case ' ':
|
||||
case '\n':
|
||||
break;
|
||||
@@ -453,7 +453,7 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int regex_le
|
||||
* at end of request. However PCRE_G(pcre_cache) must be consistent
|
||||
* on the next request as well. So we disable usage of interned strings
|
||||
* as hash keys especually for this table.
|
||||
* See bug #63180
|
||||
* See bug #63180
|
||||
*/
|
||||
if (IS_INTERNED(regex)) {
|
||||
regex = tmp = estrndup(regex, regex_len);
|
||||
@@ -482,7 +482,7 @@ PHPAPI pcre* pcre_get_compiled_regex(char *regex, pcre_extra **extra, int *preg_
|
||||
if (preg_options) {
|
||||
*preg_options = pce ? pce->preg_options : 0;
|
||||
}
|
||||
|
||||
|
||||
return pce ? pce->re : NULL;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -492,7 +492,7 @@ PHPAPI pcre* pcre_get_compiled_regex(char *regex, pcre_extra **extra, int *preg_
|
||||
PHPAPI pcre* pcre_get_compiled_regex_ex(char *regex, pcre_extra **extra, int *preg_options, int *compile_options TSRMLS_DC)
|
||||
{
|
||||
pcre_cache_entry * pce = pcre_get_compiled_regex_cache(regex, strlen(regex) TSRMLS_CC);
|
||||
|
||||
|
||||
if (extra) {
|
||||
*extra = pce ? pce->extra : NULL;
|
||||
}
|
||||
@@ -502,7 +502,7 @@ PHPAPI pcre* pcre_get_compiled_regex_ex(char *regex, pcre_extra **extra, int *pr
|
||||
if (compile_options) {
|
||||
*compile_options = pce ? pce->compile_options : 0;
|
||||
}
|
||||
|
||||
|
||||
return pce ? pce->re : NULL;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -519,7 +519,7 @@ static inline void add_offset_pair(zval *result, char *str, int len, int offset,
|
||||
/* Add (match, offset) to the return value */
|
||||
add_next_index_stringl(match_pair, str, len, 1);
|
||||
add_next_index_long(match_pair, offset);
|
||||
|
||||
|
||||
if (name) {
|
||||
zval_add_ref(&match_pair);
|
||||
zend_hash_update(Z_ARRVAL_P(result), name, strlen(name)+1, &match_pair, sizeof(zval *), NULL);
|
||||
@@ -544,13 +544,13 @@ static void php_do_pcre_match(INTERNAL_FUNCTION_PARAMETERS, int global) /* {{{ *
|
||||
&subject, &subject_len, &subpats, &flags, &start_offset) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* Compile regex or get it from cache. */
|
||||
if ((pce = pcre_get_compiled_regex_cache(regex, regex_len TSRMLS_CC)) == NULL) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
php_pcre_match_impl(pce, subject, subject_len, return_value, subpats,
|
||||
php_pcre_match_impl(pce, subject, subject_len, return_value, subpats,
|
||||
global, ZEND_NUM_ARGS() >= 4, flags, start_offset TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
@@ -653,7 +653,7 @@ PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, char *subject, int subjec
|
||||
|
||||
matched = 0;
|
||||
PCRE_G(error_code) = PHP_PCRE_NO_ERROR;
|
||||
|
||||
|
||||
do {
|
||||
/* Execute the regular expression. */
|
||||
count = pcre_exec(pce->re, extra, subject, subject_len, start_offset,
|
||||
@@ -675,7 +675,7 @@ PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, char *subject, int subjec
|
||||
/* If subpatterns array has been passed, fill it in with values. */
|
||||
if (subpats != NULL) {
|
||||
/* Try to get the list of substrings and display a warning if failed. */
|
||||
if (pcre_get_substring_list(subject, offsets, count, &stringlist) < 0) {
|
||||
if ((offsets[1] - offsets[0] < 0) || pcre_get_substring_list(subject, offsets, count, &stringlist) < 0) {
|
||||
efree(subpat_names);
|
||||
efree(offsets);
|
||||
if (match_sets) efree(match_sets);
|
||||
@@ -710,7 +710,7 @@ PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, char *subject, int subjec
|
||||
ALLOC_ZVAL(result_set);
|
||||
array_init(result_set);
|
||||
INIT_PZVAL(result_set);
|
||||
|
||||
|
||||
/* Add all the subpatterns to it */
|
||||
for (i = 0; i < count; i++) {
|
||||
if (offset_capture) {
|
||||
@@ -762,13 +762,13 @@ PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, char *subject, int subjec
|
||||
pcre_handle_exec_error(count TSRMLS_CC);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* If we have matched an empty string, mimic what Perl's /g options does.
|
||||
This turns out to be rather cunning. First we set PCRE_NOTEMPTY and try
|
||||
the match again at the same point. If this fails (picked up above) we
|
||||
advance to the next character. */
|
||||
g_notempty = (offsets[1] == offsets[0])? PCRE_NOTEMPTY | PCRE_ANCHORED : 0;
|
||||
|
||||
|
||||
/* Advance to the position right after the last full match */
|
||||
start_offset = offsets[1];
|
||||
} while (global);
|
||||
@@ -785,7 +785,7 @@ PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, char *subject, int subjec
|
||||
}
|
||||
efree(match_sets);
|
||||
}
|
||||
|
||||
|
||||
efree(offsets);
|
||||
efree(subpat_names);
|
||||
|
||||
@@ -835,7 +835,7 @@ static int preg_get_backref(char **str, int *backref)
|
||||
walk++;
|
||||
} else
|
||||
return 0;
|
||||
|
||||
|
||||
if (*walk && *walk >= '0' && *walk <= '9') {
|
||||
*backref = *backref * 10 + *walk - '0';
|
||||
walk++;
|
||||
@@ -847,9 +847,9 @@ static int preg_get_backref(char **str, int *backref)
|
||||
else
|
||||
walk++;
|
||||
}
|
||||
|
||||
|
||||
*str = walk;
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -859,7 +859,7 @@ static int preg_do_repl_func(zval *function, char *subject, int *offsets, char *
|
||||
{
|
||||
zval *retval_ptr; /* Function return value */
|
||||
zval **args[1]; /* Argument to pass to function */
|
||||
zval *subpats; /* Captured subpatterns */
|
||||
zval *subpats; /* Captured subpatterns */
|
||||
int result_len; /* Return value length */
|
||||
int i;
|
||||
|
||||
@@ -910,11 +910,11 @@ static int preg_do_eval(char *eval_str, int eval_str_len, char *subject,
|
||||
int backref; /* Current backref */
|
||||
char *compiled_string_description;
|
||||
smart_str code = {0};
|
||||
|
||||
|
||||
eval_str_end = eval_str + eval_str_len;
|
||||
walk = segment = eval_str;
|
||||
walk_last = 0;
|
||||
|
||||
|
||||
while (walk < eval_str_end) {
|
||||
/* If found a backreference.. */
|
||||
if ('\\' == *walk || '$' == *walk) {
|
||||
@@ -967,15 +967,15 @@ static int preg_do_eval(char *eval_str, int eval_str_len, char *subject,
|
||||
}
|
||||
efree(compiled_string_description);
|
||||
convert_to_string(&retval);
|
||||
|
||||
|
||||
/* Save the return value and its length */
|
||||
*result = estrndup(Z_STRVAL(retval), Z_STRLEN(retval));
|
||||
result_len = Z_STRLEN(retval);
|
||||
|
||||
|
||||
/* Clean up */
|
||||
zval_dtor(&retval);
|
||||
smart_str_free(&code);
|
||||
|
||||
|
||||
return result_len;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -994,13 +994,13 @@ PHPAPI char *php_pcre_replace(char *regex, int regex_len,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return php_pcre_replace_impl(pce, subject, subject_len, replace_val,
|
||||
return php_pcre_replace_impl(pce, subject, subject_len, replace_val,
|
||||
is_callable_replace, result_len, limit, replace_count TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ php_pcre_replace_impl() */
|
||||
PHPAPI char *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int subject_len, zval *replace_val,
|
||||
PHPAPI char *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int subject_len, zval *replace_val,
|
||||
int is_callable_replace, int *result_len, int limit, int *replace_count TSRMLS_DC)
|
||||
{
|
||||
pcre_extra *extra = pce->extra;/* Holds results of studying */
|
||||
@@ -1072,7 +1072,7 @@ PHPAPI char *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int sub
|
||||
}
|
||||
|
||||
offsets = (int *)safe_emalloc(size_offsets, sizeof(int), 0);
|
||||
|
||||
|
||||
alloc_len = 2 * subject_len + 1;
|
||||
result = safe_emalloc(alloc_len, sizeof(char), 0);
|
||||
|
||||
@@ -1081,7 +1081,7 @@ PHPAPI char *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int sub
|
||||
*result_len = 0;
|
||||
start_offset = 0;
|
||||
PCRE_G(error_code) = PHP_PCRE_NO_ERROR;
|
||||
|
||||
|
||||
while (1) {
|
||||
/* Execute the regular expression. */
|
||||
count = pcre_exec(pce->re, extra, subject, subject_len, start_offset,
|
||||
@@ -1098,7 +1098,7 @@ PHPAPI char *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int sub
|
||||
|
||||
piece = subject + start_offset;
|
||||
|
||||
if (count > 0 && (limit == -1 || limit > 0)) {
|
||||
if (count > 0 && (offsets[1] - offsets[0] >= 0) && (limit == -1 || limit > 0)) {
|
||||
if (replace_count) {
|
||||
++*replace_count;
|
||||
}
|
||||
@@ -1106,7 +1106,7 @@ PHPAPI char *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int sub
|
||||
match = subject + offsets[0];
|
||||
|
||||
new_len = *result_len + offsets[0] - start_offset; /* part before the match */
|
||||
|
||||
|
||||
/* If evaluating, do it and add the return string's length */
|
||||
if (eval) {
|
||||
eval_result_len = preg_do_eval(replace, replace_len, subject,
|
||||
@@ -1151,7 +1151,7 @@ PHPAPI char *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int sub
|
||||
|
||||
/* copy replacement and backrefs */
|
||||
walkbuf = result + *result_len;
|
||||
|
||||
|
||||
/* If evaluating or using custom function, copy result to the buffer
|
||||
* and clean up. */
|
||||
if (eval || is_callable_replace) {
|
||||
@@ -1219,13 +1219,13 @@ PHPAPI char *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int sub
|
||||
result = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* If we have matched an empty string, mimic what Perl's /g options does.
|
||||
This turns out to be rather cunning. First we set PCRE_NOTEMPTY and try
|
||||
the match again at the same point. If this fails (picked up above) we
|
||||
advance to the next character. */
|
||||
g_notempty = (offsets[1] == offsets[0])? PCRE_NOTEMPTY | PCRE_ANCHORED : 0;
|
||||
|
||||
|
||||
/* Advance to the next piece. */
|
||||
start_offset = offsets[1];
|
||||
}
|
||||
@@ -1249,18 +1249,18 @@ static char *php_replace_in_subject(zval *regex, zval *replace, zval **subject,
|
||||
*result;
|
||||
int subject_len;
|
||||
|
||||
/* Make sure we're dealing with strings. */
|
||||
/* Make sure we're dealing with strings. */
|
||||
convert_to_string_ex(subject);
|
||||
/* FIXME: This might need to be changed to STR_EMPTY_ALLOC(). Check if this zval could be dtor()'ed somehow */
|
||||
ZVAL_STRINGL(&empty_replace, "", 0, 0);
|
||||
|
||||
|
||||
/* If regex is an array */
|
||||
if (Z_TYPE_P(regex) == IS_ARRAY) {
|
||||
/* Duplicate subject string for repeated replacement */
|
||||
subject_value = estrndup(Z_STRVAL_PP(subject), Z_STRLEN_PP(subject));
|
||||
subject_len = Z_STRLEN_PP(subject);
|
||||
*result_len = subject_len;
|
||||
|
||||
|
||||
zend_hash_internal_pointer_reset(Z_ARRVAL_P(regex));
|
||||
|
||||
replace_value = replace;
|
||||
@@ -1269,9 +1269,9 @@ static char *php_replace_in_subject(zval *regex, zval *replace, zval **subject,
|
||||
|
||||
/* For each entry in the regex array, get the entry */
|
||||
while (zend_hash_get_current_data(Z_ARRVAL_P(regex), (void **)®ex_entry) == SUCCESS) {
|
||||
/* Make sure we're dealing with strings. */
|
||||
/* Make sure we're dealing with strings. */
|
||||
convert_to_string_ex(regex_entry);
|
||||
|
||||
|
||||
/* If replace is an array and not a callable construct */
|
||||
if (Z_TYPE_P(replace) == IS_ARRAY && !is_callable_replace) {
|
||||
/* Get current entry */
|
||||
@@ -1286,7 +1286,7 @@ static char *php_replace_in_subject(zval *regex, zval *replace, zval **subject,
|
||||
replace_value = &empty_replace;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Do the actual replacement and put the result back into subject_value
|
||||
for further replacements. */
|
||||
if ((result = php_pcre_replace(Z_STRVAL_PP(regex_entry),
|
||||
@@ -1342,12 +1342,12 @@ static void preg_replace_impl(INTERNAL_FUNCTION_PARAMETERS, int is_callable_repl
|
||||
ulong num_key;
|
||||
char *callback_name;
|
||||
int replace_count=0, old_replace_count;
|
||||
|
||||
|
||||
/* Get function parameters and do error-checking. */
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZZ|lZ", ®ex, &replace, &subject, &limit, &zcount) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!is_callable_replace && Z_TYPE_PP(replace) == IS_ARRAY && Z_TYPE_PP(regex) != IS_ARRAY) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Parameter mismatch, pattern is a string while replacement is an array");
|
||||
RETURN_FALSE;
|
||||
@@ -1373,10 +1373,10 @@ static void preg_replace_impl(INTERNAL_FUNCTION_PARAMETERS, int is_callable_repl
|
||||
if (ZEND_NUM_ARGS() > 3) {
|
||||
limit_val = limit;
|
||||
}
|
||||
|
||||
|
||||
if (Z_TYPE_PP(regex) != IS_ARRAY)
|
||||
convert_to_string_ex(regex);
|
||||
|
||||
|
||||
/* if subject is an array */
|
||||
if (Z_TYPE_PP(subject) == IS_ARRAY) {
|
||||
array_init(return_value);
|
||||
@@ -1404,7 +1404,7 @@ static void preg_replace_impl(INTERNAL_FUNCTION_PARAMETERS, int is_callable_repl
|
||||
efree(result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
zend_hash_move_forward(Z_ARRVAL_PP(subject));
|
||||
}
|
||||
} else { /* if subject is not an array */
|
||||
@@ -1421,7 +1421,7 @@ static void preg_replace_impl(INTERNAL_FUNCTION_PARAMETERS, int is_callable_repl
|
||||
zval_dtor(*zcount);
|
||||
ZVAL_LONG(*zcount, replace_count);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -1449,7 +1449,7 @@ static PHP_FUNCTION(preg_filter)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto array preg_split(string pattern, string subject [, int limit [, int flags]])
|
||||
/* {{{ proto array preg_split(string pattern, string subject [, int limit [, int flags]])
|
||||
Split string into an array using a perl-style regular expression as a delimiter */
|
||||
static PHP_FUNCTION(preg_split)
|
||||
{
|
||||
@@ -1461,12 +1461,12 @@ static PHP_FUNCTION(preg_split)
|
||||
long flags = 0; /* Match control flags */
|
||||
pcre_cache_entry *pce; /* Compiled regular expression */
|
||||
|
||||
/* Get function parameters and do error checking */
|
||||
/* Get function parameters and do error checking */
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ll", ®ex, ®ex_len,
|
||||
&subject, &subject_len, &limit_val, &flags) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* Compile regex or get it from cache. */
|
||||
if ((pce = pcre_get_compiled_regex_cache(regex, regex_len TSRMLS_CC)) == NULL) {
|
||||
RETURN_FALSE;
|
||||
@@ -1501,7 +1501,7 @@ PHPAPI void php_pcre_split_impl(pcre_cache_entry *pce, char *subject, int subjec
|
||||
no_empty = flags & PREG_SPLIT_NO_EMPTY;
|
||||
delim_capture = flags & PREG_SPLIT_DELIM_CAPTURE;
|
||||
offset_capture = flags & PREG_SPLIT_OFFSET_CAPTURE;
|
||||
|
||||
|
||||
if (limit_val == 0) {
|
||||
limit_val = -1;
|
||||
}
|
||||
@@ -1512,7 +1512,7 @@ PHPAPI void php_pcre_split_impl(pcre_cache_entry *pce, char *subject, int subjec
|
||||
}
|
||||
extra->match_limit = PCRE_G(backtrack_limit);
|
||||
extra->match_limit_recursion = PCRE_G(recursion_limit);
|
||||
|
||||
|
||||
/* Initialize return value */
|
||||
array_init(return_value);
|
||||
|
||||
@@ -1524,13 +1524,13 @@ PHPAPI void php_pcre_split_impl(pcre_cache_entry *pce, char *subject, int subjec
|
||||
}
|
||||
size_offsets = (size_offsets + 1) * 3;
|
||||
offsets = (int *)safe_emalloc(size_offsets, sizeof(int), 0);
|
||||
|
||||
|
||||
/* Start at the beginning of the string */
|
||||
start_offset = 0;
|
||||
next_offset = 0;
|
||||
last_match = subject;
|
||||
PCRE_G(error_code) = PHP_PCRE_NO_ERROR;
|
||||
|
||||
|
||||
/* Get next piece if no limit or limit not yet reached and something matched*/
|
||||
while ((limit_val == -1 || limit_val > 1)) {
|
||||
count = pcre_exec(pce->re, extra, subject,
|
||||
@@ -1545,9 +1545,9 @@ PHPAPI void php_pcre_split_impl(pcre_cache_entry *pce, char *subject, int subjec
|
||||
php_error_docref(NULL TSRMLS_CC,E_NOTICE, "Matched, but too many substrings");
|
||||
count = size_offsets/3;
|
||||
}
|
||||
|
||||
|
||||
/* If something matched */
|
||||
if (count > 0) {
|
||||
if (count > 0 && (offsets[1] - offsets[0] >= 0)) {
|
||||
if (!no_empty || &subject[offsets[0]] != last_match) {
|
||||
|
||||
if (offset_capture) {
|
||||
@@ -1563,7 +1563,7 @@ PHPAPI void php_pcre_split_impl(pcre_cache_entry *pce, char *subject, int subjec
|
||||
if (limit_val != -1)
|
||||
limit_val--;
|
||||
}
|
||||
|
||||
|
||||
last_match = &subject[offsets[1]];
|
||||
next_offset = offsets[1];
|
||||
|
||||
@@ -1620,7 +1620,7 @@ PHPAPI void php_pcre_split_impl(pcre_cache_entry *pce, char *subject, int subjec
|
||||
the match again at the same point. If this fails (picked up above) we
|
||||
advance to the next character. */
|
||||
g_notempty = (offsets[1] == offsets[0])? PCRE_NOTEMPTY | PCRE_ANCHORED : 0;
|
||||
|
||||
|
||||
/* Advance to the position right after the last full match */
|
||||
start_offset = offsets[1];
|
||||
}
|
||||
@@ -1639,7 +1639,7 @@ PHPAPI void php_pcre_split_impl(pcre_cache_entry *pce, char *subject, int subjec
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Clean up */
|
||||
efree(offsets);
|
||||
}
|
||||
@@ -1660,13 +1660,13 @@ static PHP_FUNCTION(preg_quote)
|
||||
delim_char=0, /* Delimiter character to be quoted */
|
||||
c; /* Current character */
|
||||
zend_bool quote_delim = 0; /* Whether to quote additional delim char */
|
||||
|
||||
|
||||
/* Get the arguments and check for errors */
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &in_str, &in_str_len,
|
||||
&delim, &delim_len) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
in_str_end = in_str + in_str_len;
|
||||
|
||||
/* Nothing to do if we got an empty string */
|
||||
@@ -1678,11 +1678,11 @@ static PHP_FUNCTION(preg_quote)
|
||||
delim_char = delim[0];
|
||||
quote_delim = 1;
|
||||
}
|
||||
|
||||
|
||||
/* Allocate enough memory so that even if each character
|
||||
is quoted, we won't run out of room */
|
||||
out_str = safe_emalloc(4, in_str_len, 1);
|
||||
|
||||
|
||||
/* Go through the string and quote necessary characters */
|
||||
for(p = in_str, q = out_str; p != in_str_end; p++) {
|
||||
c = *p;
|
||||
@@ -1726,7 +1726,7 @@ static PHP_FUNCTION(preg_quote)
|
||||
}
|
||||
}
|
||||
*q = '\0';
|
||||
|
||||
|
||||
/* Reallocate string and return it */
|
||||
RETVAL_STRINGL(erealloc(out_str, q - out_str + 1), q - out_str, 0);
|
||||
}
|
||||
@@ -1747,12 +1747,12 @@ static PHP_FUNCTION(preg_grep)
|
||||
&input, &flags) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Compile regex or get it from cache. */
|
||||
if ((pce = pcre_get_compiled_regex_cache(regex, regex_len TSRMLS_CC)) == NULL) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
|
||||
php_pcre_grep_impl(pce, input, return_value, flags TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
@@ -1770,9 +1770,9 @@ PHPAPI void php_pcre_grep_impl(pcre_cache_entry *pce, zval *input, zval *return
|
||||
zend_bool invert; /* Whether to return non-matching
|
||||
entries */
|
||||
int rc;
|
||||
|
||||
|
||||
invert = flags & PREG_GREP_INVERT ? 1 : 0;
|
||||
|
||||
|
||||
if (extra == NULL) {
|
||||
extra_data.flags = PCRE_EXTRA_MATCH_LIMIT | PCRE_EXTRA_MATCH_LIMIT_RECURSION;
|
||||
extra = &extra_data;
|
||||
@@ -1788,7 +1788,7 @@ PHPAPI void php_pcre_grep_impl(pcre_cache_entry *pce, zval *input, zval *return
|
||||
}
|
||||
size_offsets = (size_offsets + 1) * 3;
|
||||
offsets = (int *)safe_emalloc(size_offsets, sizeof(int), 0);
|
||||
|
||||
|
||||
/* Initialize return array */
|
||||
array_init(return_value);
|
||||
|
||||
@@ -1901,7 +1901,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_preg_split, 0, 0, 2)
|
||||
ZEND_ARG_INFO(0, pattern)
|
||||
ZEND_ARG_INFO(0, subject)
|
||||
ZEND_ARG_INFO(0, limit)
|
||||
ZEND_ARG_INFO(0, flags)
|
||||
ZEND_ARG_INFO(0, flags)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_preg_quote, 0, 0, 1)
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
--TEST--
|
||||
Bug #70345 (Multiple vulnerabilities related to PCRE functions)
|
||||
--FILE--
|
||||
<?php
|
||||
$regex = '/(?=xyz\K)/';
|
||||
$subject = "aaaaxyzaaaa";
|
||||
|
||||
$v = preg_split($regex, $subject);
|
||||
print_r($v);
|
||||
|
||||
$regex = '/(a(?=xyz\K))/';
|
||||
$subject = "aaaaxyzaaaa";
|
||||
preg_match($regex, $subject, $matches);
|
||||
|
||||
var_dump($matches);
|
||||
--EXPECTF--
|
||||
Array
|
||||
(
|
||||
[0] => aaaaxyzaaaa
|
||||
)
|
||||
|
||||
Warning: preg_match(): Get subpatterns list failed in %s on line %d
|
||||
array(0) {
|
||||
}
|
||||
+7
-2
@@ -5103,7 +5103,11 @@ PHP_PGSQL_API int php_pgsql_meta_data(PGconn *pg_link, const char *table_name, z
|
||||
|
||||
src = estrdup(table_name);
|
||||
tmp_name = php_strtok_r(src, ".", &tmp_name2);
|
||||
|
||||
if (!tmp_name) {
|
||||
efree(src);
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "The table name must be specified");
|
||||
return FAILURE;
|
||||
}
|
||||
if (!tmp_name2 || !*tmp_name2) {
|
||||
/* Default schema */
|
||||
tmp_name2 = tmp_name;
|
||||
@@ -6111,7 +6115,8 @@ static int do_exec(smart_str *querystr, int expect, PGconn *pg_link, ulong opt T
|
||||
|
||||
static inline void build_tablename(smart_str *querystr, PGconn *pg_link, const char *table)
|
||||
{
|
||||
char *table_copy, *escaped, *token, *tmp;
|
||||
char *table_copy, *escaped, *tmp;
|
||||
const char *token;
|
||||
size_t len;
|
||||
|
||||
/* schame.table should be "schame"."table" */
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
--TEST--
|
||||
PostgreSQL pg_insert() - test for CVE-2015-1532
|
||||
--SKIPIF--
|
||||
<?php include("skipif.inc"); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
include('config.inc');
|
||||
|
||||
$conn = pg_connect($conn_str);
|
||||
|
||||
foreach (array('', '.', '..') as $table) {
|
||||
var_dump(pg_insert($conn, $table, array('id' => 1, 'id2' => 1)));
|
||||
}
|
||||
?>
|
||||
Done
|
||||
--EXPECTF--
|
||||
|
||||
Warning: pg_insert(): The table name must be specified in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: pg_insert(): The table name must be specified in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: pg_insert(): The table name must be specified in %s on line %d
|
||||
bool(false)
|
||||
Done
|
||||
+8
-2
@@ -2142,7 +2142,7 @@ char *tsrm_strtok_r(char *s, const char *delim, char **last) /* {{{ */
|
||||
*/
|
||||
char *phar_fix_filepath(char *path, int *new_len, int use_cwd TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
char newpath[MAXPATHLEN];
|
||||
char *newpath;
|
||||
int newpath_len;
|
||||
char *ptr;
|
||||
char *tok;
|
||||
@@ -2150,8 +2150,10 @@ char *phar_fix_filepath(char *path, int *new_len, int use_cwd TSRMLS_DC) /* {{{
|
||||
|
||||
if (PHAR_G(cwd_len) && use_cwd && path_length > 2 && path[0] == '.' && path[1] == '/') {
|
||||
newpath_len = PHAR_G(cwd_len);
|
||||
newpath = emalloc(strlen(path) + newpath_len + 1);
|
||||
memcpy(newpath, PHAR_G(cwd), newpath_len);
|
||||
} else {
|
||||
newpath = emalloc(strlen(path) + 2);
|
||||
newpath[0] = '/';
|
||||
newpath_len = 1;
|
||||
}
|
||||
@@ -2174,6 +2176,7 @@ char *phar_fix_filepath(char *path, int *new_len, int use_cwd TSRMLS_DC) /* {{{
|
||||
if (*tok == '.') {
|
||||
efree(path);
|
||||
*new_len = 1;
|
||||
efree(newpath);
|
||||
return estrndup("/", 1);
|
||||
}
|
||||
break;
|
||||
@@ -2181,9 +2184,11 @@ char *phar_fix_filepath(char *path, int *new_len, int use_cwd TSRMLS_DC) /* {{{
|
||||
if (tok[0] == '.' && tok[1] == '.') {
|
||||
efree(path);
|
||||
*new_len = 1;
|
||||
efree(newpath);
|
||||
return estrndup("/", 1);
|
||||
}
|
||||
}
|
||||
efree(newpath);
|
||||
return path;
|
||||
}
|
||||
|
||||
@@ -2232,7 +2237,8 @@ last_time:
|
||||
|
||||
efree(path);
|
||||
*new_len = newpath_len;
|
||||
return estrndup(newpath, newpath_len);
|
||||
newpath[newpath_len] = '\0';
|
||||
return erealloc(newpath, newpath_len + 1);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
@@ -618,13 +618,16 @@ static inline void phar_set_inode(phar_entry_info *entry TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
char tmp[MAXPATHLEN];
|
||||
int tmp_len;
|
||||
size_t len;
|
||||
size_t len1, len2;
|
||||
|
||||
tmp_len = MIN(MAXPATHLEN, entry->filename_len + entry->phar->fname_len);
|
||||
len = MIN(entry->phar->fname_len, tmp_len);
|
||||
memcpy(tmp, entry->phar->fname, len);
|
||||
len = MIN(tmp_len - len, entry->filename_len);
|
||||
memcpy(tmp + entry->phar->fname_len, entry->filename, len);
|
||||
|
||||
len1 = MIN(entry->phar->fname_len, tmp_len);
|
||||
memcpy(tmp, entry->phar->fname, len1);
|
||||
|
||||
len2 = MIN(tmp_len - len1, entry->filename_len);
|
||||
memcpy(tmp + len1, entry->filename, len2);
|
||||
|
||||
entry->inode = (unsigned short)zend_get_hash_value(tmp, tmp_len);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
+93
-45
@@ -1269,7 +1269,7 @@ PHP_METHOD(Phar, __construct)
|
||||
INIT_PZVAL(&arg2);
|
||||
ZVAL_LONG(&arg2, flags);
|
||||
|
||||
zend_call_method_with_2_params(&zobj, Z_OBJCE_P(zobj),
|
||||
zend_call_method_with_2_params(&zobj, Z_OBJCE_P(zobj),
|
||||
&spl_ce_RecursiveDirectoryIterator->constructor, "__construct", NULL, &arg1, &arg2);
|
||||
|
||||
if (!phar_data->is_persistent) {
|
||||
@@ -1293,7 +1293,7 @@ PHP_METHOD(Phar, getSupportedSignatures)
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
array_init(return_value);
|
||||
|
||||
add_next_index_stringl(return_value, "MD5", 3, 1);
|
||||
@@ -1320,7 +1320,7 @@ PHP_METHOD(Phar, getSupportedCompression)
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
array_init(return_value);
|
||||
phar_request_initialize(TSRMLS_C);
|
||||
|
||||
@@ -1608,7 +1608,7 @@ phar_spl_fileinfo:
|
||||
}
|
||||
return ZEND_HASH_APPLY_STOP;
|
||||
}
|
||||
|
||||
|
||||
base = temp;
|
||||
base_len = strlen(base);
|
||||
|
||||
@@ -1805,7 +1805,7 @@ after_open_fp:
|
||||
/* {{{ proto array Phar::buildFromDirectory(string base_dir[, string regex])
|
||||
* Construct a phar archive from an existing directory, recursively.
|
||||
* Optional second parameter is a regular expression for filtering directory contents.
|
||||
*
|
||||
*
|
||||
* Return value is an array mapping phar index to actual files added.
|
||||
*/
|
||||
PHP_METHOD(Phar, buildFromDirectory)
|
||||
@@ -1845,7 +1845,7 @@ PHP_METHOD(Phar, buildFromDirectory)
|
||||
ZVAL_LONG(&arg2, SPL_FILE_DIR_SKIPDOTS|SPL_FILE_DIR_UNIXPATHS);
|
||||
#endif
|
||||
|
||||
zend_call_method_with_2_params(&iter, spl_ce_RecursiveDirectoryIterator,
|
||||
zend_call_method_with_2_params(&iter, spl_ce_RecursiveDirectoryIterator,
|
||||
&spl_ce_RecursiveDirectoryIterator->constructor, "__construct", NULL, &arg, &arg2);
|
||||
|
||||
if (EG(exception)) {
|
||||
@@ -1862,7 +1862,7 @@ PHP_METHOD(Phar, buildFromDirectory)
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
zend_call_method_with_1_params(&iteriter, spl_ce_RecursiveIteratorIterator,
|
||||
zend_call_method_with_1_params(&iteriter, spl_ce_RecursiveIteratorIterator,
|
||||
&spl_ce_RecursiveIteratorIterator->constructor, "__construct", NULL, iter);
|
||||
|
||||
if (EG(exception)) {
|
||||
@@ -1887,7 +1887,7 @@ PHP_METHOD(Phar, buildFromDirectory)
|
||||
INIT_PZVAL(&arg2);
|
||||
ZVAL_STRINGL(&arg2, regex, regex_len, 0);
|
||||
|
||||
zend_call_method_with_2_params(®exiter, spl_ce_RegexIterator,
|
||||
zend_call_method_with_2_params(®exiter, spl_ce_RegexIterator,
|
||||
&spl_ce_RegexIterator->constructor, "__construct", NULL, iteriter, &arg2);
|
||||
}
|
||||
|
||||
@@ -2008,7 +2008,7 @@ PHP_METHOD(Phar, buildFromIterator)
|
||||
PHP_METHOD(Phar, count)
|
||||
{
|
||||
PHAR_ARCHIVE_OBJECT();
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -2089,9 +2089,10 @@ static int phar_copy_file_contents(phar_entry_info *entry, php_stream *fp TSRMLS
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zval *phar_rename_archive(phar_archive_data *phar, char *ext, zend_bool compress TSRMLS_DC) /* {{{ */
|
||||
static zval *phar_rename_archive(phar_archive_data **sphar, char *ext, zend_bool compress TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
const char *oldname = NULL;
|
||||
phar_archive_data *phar = *sphar;
|
||||
char *oldpath = NULL;
|
||||
char *basename = NULL, *basepath = NULL;
|
||||
char *newname = NULL, *newpath = NULL;
|
||||
@@ -2173,7 +2174,7 @@ static zval *phar_rename_archive(phar_archive_data *phar, char *ext, zend_bool c
|
||||
spprintf(&newname, 0, "%s.%s", strtok(basename, "."), ext);
|
||||
efree(basename);
|
||||
|
||||
|
||||
|
||||
|
||||
basepath = estrndup(oldpath, (strlen(oldpath) - oldname_len));
|
||||
phar->fname_len = spprintf(&newpath, 0, "%s%s", basepath, newname);
|
||||
@@ -2199,6 +2200,7 @@ static zval *phar_rename_archive(phar_archive_data *phar, char *ext, zend_bool c
|
||||
phar->fp = NULL;
|
||||
phar_destroy_phar_data(phar TSRMLS_CC);
|
||||
phar = *pphar;
|
||||
*sphar = NULL;
|
||||
phar->refcount++;
|
||||
newpath = oldpath;
|
||||
goto its_ok;
|
||||
@@ -2413,15 +2415,19 @@ no_copy:
|
||||
phar_add_virtual_dirs(phar, newentry.filename, newentry.filename_len TSRMLS_CC);
|
||||
}
|
||||
|
||||
if ((ret = phar_rename_archive(phar, ext, 0 TSRMLS_CC))) {
|
||||
if ((ret = phar_rename_archive(&phar, ext, 0 TSRMLS_CC))) {
|
||||
return ret;
|
||||
} else {
|
||||
zend_hash_destroy(&(phar->manifest));
|
||||
zend_hash_destroy(&(phar->mounted_dirs));
|
||||
zend_hash_destroy(&(phar->virtual_dirs));
|
||||
php_stream_close(phar->fp);
|
||||
efree(phar->fname);
|
||||
efree(phar);
|
||||
if(phar != NULL) {
|
||||
zend_hash_destroy(&(phar->manifest));
|
||||
zend_hash_destroy(&(phar->mounted_dirs));
|
||||
zend_hash_destroy(&(phar->virtual_dirs));
|
||||
if (phar->fp) {
|
||||
php_stream_close(phar->fp);
|
||||
}
|
||||
efree(phar->fname);
|
||||
efree(phar);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -2639,7 +2645,7 @@ PHP_METHOD(Phar, convertToData)
|
||||
PHP_METHOD(Phar, isCompressed)
|
||||
{
|
||||
PHAR_ARCHIVE_OBJECT();
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -2663,7 +2669,7 @@ PHP_METHOD(Phar, isWritable)
|
||||
{
|
||||
php_stream_statbuf ssb;
|
||||
PHAR_ARCHIVE_OBJECT();
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -2741,7 +2747,7 @@ PHP_METHOD(Phar, delete)
|
||||
PHP_METHOD(Phar, getAlias)
|
||||
{
|
||||
PHAR_ARCHIVE_OBJECT();
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -2758,7 +2764,7 @@ PHP_METHOD(Phar, getAlias)
|
||||
PHP_METHOD(Phar, getPath)
|
||||
{
|
||||
PHAR_ARCHIVE_OBJECT();
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -2874,7 +2880,7 @@ valid_alias:
|
||||
PHP_METHOD(Phar, getVersion)
|
||||
{
|
||||
PHAR_ARCHIVE_OBJECT();
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -2889,7 +2895,7 @@ PHP_METHOD(Phar, getVersion)
|
||||
PHP_METHOD(Phar, startBuffering)
|
||||
{
|
||||
PHAR_ARCHIVE_OBJECT();
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -2904,7 +2910,7 @@ PHP_METHOD(Phar, startBuffering)
|
||||
PHP_METHOD(Phar, isBuffering)
|
||||
{
|
||||
PHAR_ARCHIVE_OBJECT();
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -2921,7 +2927,7 @@ PHP_METHOD(Phar, stopBuffering)
|
||||
char *error;
|
||||
|
||||
PHAR_ARCHIVE_OBJECT();
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -3156,7 +3162,7 @@ PHP_METHOD(Phar, setSignatureAlgorithm)
|
||||
PHP_METHOD(Phar, getSignature)
|
||||
{
|
||||
PHAR_ARCHIVE_OBJECT();
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -3200,7 +3206,7 @@ PHP_METHOD(Phar, getSignature)
|
||||
PHP_METHOD(Phar, getModified)
|
||||
{
|
||||
PHAR_ARCHIVE_OBJECT();
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -3462,7 +3468,7 @@ PHP_METHOD(Phar, decompressFiles)
|
||||
{
|
||||
char *error;
|
||||
PHAR_ARCHIVE_OBJECT();
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -3983,7 +3989,7 @@ PHP_METHOD(Phar, getStub)
|
||||
phar_entry_info *stub;
|
||||
|
||||
PHAR_ARCHIVE_OBJECT();
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -4086,7 +4092,7 @@ PHP_METHOD(Phar, hasMetadata)
|
||||
PHP_METHOD(Phar, getMetadata)
|
||||
{
|
||||
PHAR_ARCHIVE_OBJECT();
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -4194,6 +4200,9 @@ static int phar_extract_file(zend_bool overwrite, phar_entry_info *entry, char *
|
||||
char *fullpath;
|
||||
const char *slash;
|
||||
mode_t mode;
|
||||
cwd_state new_state;
|
||||
char *filename;
|
||||
size_t filename_len;
|
||||
|
||||
if (entry->is_mounted) {
|
||||
/* silently ignore mounted entries */
|
||||
@@ -4203,8 +4212,39 @@ static int phar_extract_file(zend_bool overwrite, phar_entry_info *entry, char *
|
||||
if (entry->filename_len >= sizeof(".phar")-1 && !memcmp(entry->filename, ".phar", sizeof(".phar")-1)) {
|
||||
return SUCCESS;
|
||||
}
|
||||
/* strip .. from path and restrict it to be under dest directory */
|
||||
new_state.cwd = (char*)malloc(2);
|
||||
new_state.cwd[0] = DEFAULT_SLASH;
|
||||
new_state.cwd[1] = '\0';
|
||||
new_state.cwd_length = 1;
|
||||
if (virtual_file_ex(&new_state, entry->filename, NULL, CWD_EXPAND TSRMLS_CC) != 0 ||
|
||||
new_state.cwd_length <= 1) {
|
||||
if (EINVAL == errno && entry->filename_len > 50) {
|
||||
char *tmp = estrndup(entry->filename, 50);
|
||||
spprintf(error, 4096, "Cannot extract \"%s...\" to \"%s...\", extracted filename is too long for filesystem", tmp, dest);
|
||||
efree(tmp);
|
||||
} else {
|
||||
spprintf(error, 4096, "Cannot extract \"%s\", internal error", entry->filename);
|
||||
}
|
||||
free(new_state.cwd);
|
||||
return FAILURE;
|
||||
}
|
||||
filename = new_state.cwd + 1;
|
||||
filename_len = new_state.cwd_length - 1;
|
||||
#ifdef PHP_WIN32
|
||||
/* unixify the path back, otherwise non zip formats might be broken */
|
||||
{
|
||||
int cnt = filename_len;
|
||||
|
||||
len = spprintf(&fullpath, 0, "%s/%s", dest, entry->filename);
|
||||
do {
|
||||
if ('\\' == filename[cnt]) {
|
||||
filename[cnt] = '/';
|
||||
}
|
||||
} while (cnt-- >= 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
len = spprintf(&fullpath, 0, "%s/%s", dest, filename);
|
||||
|
||||
if (len >= MAXPATHLEN) {
|
||||
char *tmp;
|
||||
@@ -4218,18 +4258,21 @@ static int phar_extract_file(zend_bool overwrite, phar_entry_info *entry, char *
|
||||
spprintf(error, 4096, "Cannot extract \"%s\" to \"%s...\", extracted filename is too long for filesystem", entry->filename, fullpath);
|
||||
}
|
||||
efree(fullpath);
|
||||
free(new_state.cwd);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (!len) {
|
||||
spprintf(error, 4096, "Cannot extract \"%s\", internal error", entry->filename);
|
||||
efree(fullpath);
|
||||
free(new_state.cwd);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (PHAR_OPENBASEDIR_CHECKPATH(fullpath)) {
|
||||
spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", openbasedir/safe mode restrictions in effect", entry->filename, fullpath);
|
||||
efree(fullpath);
|
||||
free(new_state.cwd);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
@@ -4237,14 +4280,15 @@ static int phar_extract_file(zend_bool overwrite, phar_entry_info *entry, char *
|
||||
if (!overwrite && SUCCESS == php_stream_stat_path(fullpath, &ssb)) {
|
||||
spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", path already exists", entry->filename, fullpath);
|
||||
efree(fullpath);
|
||||
free(new_state.cwd);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
/* perform dirname */
|
||||
slash = zend_memrchr(entry->filename, '/', entry->filename_len);
|
||||
slash = zend_memrchr(filename, '/', filename_len);
|
||||
|
||||
if (slash) {
|
||||
fullpath[dest_len + (slash - entry->filename) + 1] = '\0';
|
||||
fullpath[dest_len + (slash - filename) + 1] = '\0';
|
||||
} else {
|
||||
fullpath[dest_len] = '\0';
|
||||
}
|
||||
@@ -4254,23 +4298,27 @@ static int phar_extract_file(zend_bool overwrite, phar_entry_info *entry, char *
|
||||
if (!php_stream_mkdir(fullpath, entry->flags & PHAR_ENT_PERM_MASK, PHP_STREAM_MKDIR_RECURSIVE, NULL)) {
|
||||
spprintf(error, 4096, "Cannot extract \"%s\", could not create directory \"%s\"", entry->filename, fullpath);
|
||||
efree(fullpath);
|
||||
free(new_state.cwd);
|
||||
return FAILURE;
|
||||
}
|
||||
} else {
|
||||
if (!php_stream_mkdir(fullpath, 0777, PHP_STREAM_MKDIR_RECURSIVE, NULL)) {
|
||||
spprintf(error, 4096, "Cannot extract \"%s\", could not create directory \"%s\"", entry->filename, fullpath);
|
||||
efree(fullpath);
|
||||
free(new_state.cwd);
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (slash) {
|
||||
fullpath[dest_len + (slash - entry->filename) + 1] = '/';
|
||||
fullpath[dest_len + (slash - filename) + 1] = '/';
|
||||
} else {
|
||||
fullpath[dest_len] = '/';
|
||||
}
|
||||
|
||||
filename = NULL;
|
||||
free(new_state.cwd);
|
||||
/* it is a standalone directory, job done */
|
||||
if (entry->is_dir) {
|
||||
efree(fullpath);
|
||||
@@ -4544,7 +4592,7 @@ PHP_METHOD(PharFileInfo, __construct)
|
||||
INIT_PZVAL(&arg1);
|
||||
ZVAL_STRINGL(&arg1, fname, fname_len, 0);
|
||||
|
||||
zend_call_method_with_1_params(&zobj, Z_OBJCE_P(zobj),
|
||||
zend_call_method_with_1_params(&zobj, Z_OBJCE_P(zobj),
|
||||
&spl_ce_SplFileInfo->constructor, "__construct", NULL, &arg1);
|
||||
}
|
||||
/* }}} */
|
||||
@@ -4582,7 +4630,7 @@ PHP_METHOD(PharFileInfo, __destruct)
|
||||
PHP_METHOD(PharFileInfo, getCompressedSize)
|
||||
{
|
||||
PHAR_ENTRY_OBJECT();
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -4624,7 +4672,7 @@ PHP_METHOD(PharFileInfo, isCompressed)
|
||||
PHP_METHOD(PharFileInfo, getCRC32)
|
||||
{
|
||||
PHAR_ENTRY_OBJECT();
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -4650,7 +4698,7 @@ PHP_METHOD(PharFileInfo, getCRC32)
|
||||
PHP_METHOD(PharFileInfo, isCRCChecked)
|
||||
{
|
||||
PHAR_ENTRY_OBJECT();
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -4665,7 +4713,7 @@ PHP_METHOD(PharFileInfo, isCRCChecked)
|
||||
PHP_METHOD(PharFileInfo, getPharFlags)
|
||||
{
|
||||
PHAR_ENTRY_OBJECT();
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -4743,7 +4791,7 @@ PHP_METHOD(PharFileInfo, chmod)
|
||||
PHP_METHOD(PharFileInfo, hasMetadata)
|
||||
{
|
||||
PHAR_ENTRY_OBJECT();
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -4758,7 +4806,7 @@ PHP_METHOD(PharFileInfo, hasMetadata)
|
||||
PHP_METHOD(PharFileInfo, getMetadata)
|
||||
{
|
||||
PHAR_ENTRY_OBJECT();
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -4839,7 +4887,7 @@ PHP_METHOD(PharFileInfo, delMetadata)
|
||||
char *error;
|
||||
|
||||
PHAR_ENTRY_OBJECT();
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -4897,7 +4945,7 @@ PHP_METHOD(PharFileInfo, getContent)
|
||||
phar_entry_info *link;
|
||||
|
||||
PHAR_ENTRY_OBJECT();
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -5071,7 +5119,7 @@ PHP_METHOD(PharFileInfo, decompress)
|
||||
{
|
||||
char *error;
|
||||
PHAR_ENTRY_OBJECT();
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
+1
-1
@@ -425,7 +425,7 @@ bail:
|
||||
entry.filename_len = i;
|
||||
entry.filename = pestrndup(hdr->name, i, myphar->is_persistent);
|
||||
|
||||
if (entry.filename[entry.filename_len - 1] == '/') {
|
||||
if (i > 0 && entry.filename[entry.filename_len - 1] == '/') {
|
||||
/* some tar programs store directories with trailing slash */
|
||||
entry.filename[entry.filename_len - 1] = '\0';
|
||||
entry.filename_len--;
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
--TEST--
|
||||
Phar: bug #69453: Memory Corruption in phar_parse_tarfile when entry filename starts with null
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded("phar")) die("skip"); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$fname = dirname(__FILE__) . '/bug69453.tar.phar';
|
||||
try {
|
||||
$r = new Phar($fname, 0);
|
||||
} catch(UnexpectedValueException $e) {
|
||||
echo $e;
|
||||
}
|
||||
?>
|
||||
|
||||
==DONE==
|
||||
--EXPECTF--
|
||||
exception 'UnexpectedValueException' with message 'phar error: "%s/bug69453.tar.phar" is a corrupted tar file (checksum mismatch of file "")' in %s:%d
|
||||
Stack trace:
|
||||
#0 %s/bug69453.php(%d): Phar->__construct('%s', 0)
|
||||
#1 {main}
|
||||
==DONE==
|
||||
Binary file not shown.
@@ -0,0 +1,16 @@
|
||||
--TEST--
|
||||
Phar: bug #69958: Segfault in Phar::convertToData on invalid file
|
||||
--XFAIL--
|
||||
Still has memory leaks, see https://bugs.php.net/bug.php?id=70005
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded("phar")) die("skip"); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$tarphar = new PharData(__DIR__.'/bug69958.tar');
|
||||
$phar = $tarphar->convertToData(Phar::TAR);
|
||||
--EXPECTF--
|
||||
Fatal error: Uncaught exception 'BadMethodCallException' with message 'phar "%s/bug69958.tar" exists and must be unlinked prior to conversion' in %s/bug69958.php:%d
|
||||
Stack trace:
|
||||
#0 %s/bug69958.php(%d): PharData->convertToData(%d)
|
||||
#1 {main}
|
||||
thrown in %s/bug69958.php on line %d
|
||||
Binary file not shown.
@@ -0,0 +1,22 @@
|
||||
--TEST--
|
||||
Bug #70019 Files extracted from archive may be placed outside of destination directory
|
||||
--FILE--
|
||||
<?php
|
||||
$dir = __DIR__."/bug70019";
|
||||
$phar = new PharData(__DIR__."/bug70019.zip");
|
||||
if(!is_dir($dir)) {
|
||||
mkdir($dir);
|
||||
}
|
||||
$phar->extractTo($dir);
|
||||
var_dump(file_exists("$dir/ThisIsATestFile.txt"));
|
||||
?>
|
||||
===DONE===
|
||||
--CLEAN--
|
||||
<?php
|
||||
$dir = __DIR__."/bug70019";
|
||||
unlink("$dir/ThisIsATestFile.txt");
|
||||
rmdir($dir);
|
||||
?>
|
||||
--EXPECTF--
|
||||
bool(true)
|
||||
===DONE===
|
||||
Binary file not shown.
+22
-14
@@ -210,16 +210,18 @@ static char *php_session_encode(int *newlen TSRMLS_DC) /* {{{ */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void php_session_decode(const char *val, int vallen TSRMLS_DC) /* {{{ */
|
||||
static int php_session_decode(const char *val, int vallen TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
if (!PS(serializer)) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown session.serialize_handler. Failed to decode session object");
|
||||
return;
|
||||
return FAILURE;
|
||||
}
|
||||
if (PS(serializer)->decode(val, vallen TSRMLS_CC) == FAILURE) {
|
||||
php_session_destroy(TSRMLS_C);
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to decode session object. Session has been destroyed");
|
||||
return FAILURE;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -413,7 +415,7 @@ PHPAPI char *php_session_create_id(PS_CREATE_SID_ARGS) /* {{{ */
|
||||
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "The ini setting hash_bits_per_character is out of range (should be 4, 5, or 6) - using 4 for now");
|
||||
}
|
||||
|
||||
|
||||
outid = emalloc((size_t)((digest_len + 2) * ((8.0f / PS(hash_bits_per_character)) + 0.5)));
|
||||
j = (int) (bin_to_readable((char *)digest, digest_len, outid, (char)PS(hash_bits_per_character)) - outid);
|
||||
efree(digest);
|
||||
@@ -855,8 +857,11 @@ PS_SERIALIZER_DECODE_FUNC(php_binary) /* {{{ */
|
||||
ALLOC_INIT_ZVAL(current);
|
||||
if (php_var_unserialize(¤t, (const unsigned char **) &p, (const unsigned char *) endptr, &var_hash TSRMLS_CC)) {
|
||||
php_set_session_var(name, namelen, current, &var_hash TSRMLS_CC);
|
||||
} else {
|
||||
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
|
||||
return FAILURE;
|
||||
}
|
||||
zval_ptr_dtor(¤t);
|
||||
var_push_dtor_no_addref(&var_hash, ¤t);
|
||||
}
|
||||
PS_ADD_VARL(name, namelen);
|
||||
efree(name);
|
||||
@@ -947,8 +952,13 @@ PS_SERIALIZER_DECODE_FUNC(php) /* {{{ */
|
||||
ALLOC_INIT_ZVAL(current);
|
||||
if (php_var_unserialize(¤t, (const unsigned char **) &q, (const unsigned char *) endptr, &var_hash TSRMLS_CC)) {
|
||||
php_set_session_var(name, namelen, current, &var_hash TSRMLS_CC);
|
||||
} else {
|
||||
var_push_dtor_no_addref(&var_hash, ¤t);
|
||||
efree(name);
|
||||
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
|
||||
return FAILURE;
|
||||
}
|
||||
zval_ptr_dtor(¤t);
|
||||
var_push_dtor_no_addref(&var_hash, ¤t);
|
||||
}
|
||||
PS_ADD_VARL(name, namelen);
|
||||
skip:
|
||||
@@ -1744,7 +1754,7 @@ static PHP_FUNCTION(session_set_save_handler)
|
||||
}
|
||||
efree(name);
|
||||
}
|
||||
|
||||
|
||||
if (PS(mod) && PS(mod) != &ps_mod_user) {
|
||||
zend_alter_ini_entry("session.save_handler", sizeof("session.save_handler"), "user", sizeof("user")-1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
|
||||
}
|
||||
@@ -1922,9 +1932,7 @@ static PHP_FUNCTION(session_decode)
|
||||
return;
|
||||
}
|
||||
|
||||
php_session_decode(str, str_len TSRMLS_CC);
|
||||
|
||||
RETURN_TRUE;
|
||||
RETVAL_BOOL(php_session_decode(str, str_len TSRMLS_CC) == SUCCESS);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -2516,12 +2524,12 @@ static int php_session_rfc1867_callback(unsigned int event, void *event_data, vo
|
||||
case MULTIPART_EVENT_FILE_START: {
|
||||
multipart_event_file_start *data = (multipart_event_file_start *) event_data;
|
||||
|
||||
/* Do nothing when $_POST["PHP_SESSION_UPLOAD_PROGRESS"] is not set
|
||||
/* Do nothing when $_POST["PHP_SESSION_UPLOAD_PROGRESS"] is not set
|
||||
* or when we have no session id */
|
||||
if (!Z_TYPE(progress->sid) || !progress->key.c) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* First FILE_START event, initializing data */
|
||||
if (!progress->data) {
|
||||
|
||||
@@ -2571,7 +2579,7 @@ static int php_session_rfc1867_callback(unsigned int event, void *event_data, vo
|
||||
add_assoc_zval_ex(progress->current_file, "bytes_processed", sizeof("bytes_processed"), progress->current_file_bytes_processed);
|
||||
|
||||
add_next_index_zval(progress->files, progress->current_file);
|
||||
|
||||
|
||||
Z_LVAL_P(progress->post_bytes_processed) = data->post_bytes_processed;
|
||||
|
||||
php_session_rfc1867_update(progress, 0 TSRMLS_CC);
|
||||
@@ -2583,7 +2591,7 @@ static int php_session_rfc1867_callback(unsigned int event, void *event_data, vo
|
||||
if (!Z_TYPE(progress->sid) || !progress->key.c) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
Z_LVAL_P(progress->current_file_bytes_processed) = data->offset + data->length;
|
||||
Z_LVAL_P(progress->post_bytes_processed) = data->post_bytes_processed;
|
||||
|
||||
@@ -2596,7 +2604,7 @@ static int php_session_rfc1867_callback(unsigned int event, void *event_data, vo
|
||||
if (!Z_TYPE(progress->sid) || !progress->key.c) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (data->temp_filename) {
|
||||
add_assoc_string_ex(progress->current_file, "tmp_name", sizeof("tmp_name"), data->temp_filename, 1);
|
||||
}
|
||||
|
||||
@@ -53,563 +53,247 @@ array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 4 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 5 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 6 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 7 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 8 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 9 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 10 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 11 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 12 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 13 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 14 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 15 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 16 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 17 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 18 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 19 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 20 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 21 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 22 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 23 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 24 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 25 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 26 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 27 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 28 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 29 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 30 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 31 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 32 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 33 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 34 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 35 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 36 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 37 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 38 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 39 --
|
||||
bool(true)
|
||||
array(2) {
|
||||
["foo"]=>
|
||||
array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
["guff"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 40 --
|
||||
bool(true)
|
||||
array(2) {
|
||||
["foo"]=>
|
||||
array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
["guff"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 41 --
|
||||
bool(true)
|
||||
array(2) {
|
||||
["foo"]=>
|
||||
array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
["guff"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 42 --
|
||||
bool(true)
|
||||
array(2) {
|
||||
["foo"]=>
|
||||
array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
["guff"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 43 --
|
||||
bool(true)
|
||||
array(2) {
|
||||
["foo"]=>
|
||||
&array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
["guff"]=>
|
||||
&array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 44 --
|
||||
bool(true)
|
||||
array(2) {
|
||||
["foo"]=>
|
||||
&array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
["guff"]=>
|
||||
&array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 45 --
|
||||
bool(true)
|
||||
array(2) {
|
||||
["foo"]=>
|
||||
&array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
["guff"]=>
|
||||
&array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 46 --
|
||||
bool(true)
|
||||
array(2) {
|
||||
["foo"]=>
|
||||
&array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
["guff"]=>
|
||||
&array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 47 --
|
||||
bool(true)
|
||||
array(2) {
|
||||
["foo"]=>
|
||||
&array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
["guff"]=>
|
||||
&array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 48 --
|
||||
bool(true)
|
||||
array(3) {
|
||||
["foo"]=>
|
||||
&array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
["guff"]=>
|
||||
&array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
["blah"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 49 --
|
||||
bool(true)
|
||||
array(3) {
|
||||
["foo"]=>
|
||||
&array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
["guff"]=>
|
||||
&array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
["blah"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 50 --
|
||||
bool(true)
|
||||
array(3) {
|
||||
["foo"]=>
|
||||
&array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
["guff"]=>
|
||||
&array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
["blah"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 51 --
|
||||
bool(true)
|
||||
array(3) {
|
||||
["foo"]=>
|
||||
&array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
["guff"]=>
|
||||
&array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
["blah"]=>
|
||||
NULL
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
bool(true)
|
||||
Done
|
||||
|
||||
Warning: session_destroy(): Trying to destroy uninitialized session in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
Done
|
||||
@@ -49,7 +49,7 @@ array(3) {
|
||||
}
|
||||
|
||||
Warning: session_decode(): Unknown session.serialize_handler. Failed to decode session object in %s on line %d
|
||||
bool(true)
|
||||
bool(false)
|
||||
array(3) {
|
||||
["foo"]=>
|
||||
int(1234567890)
|
||||
|
||||
+13
-10
@@ -313,7 +313,7 @@ int make_http_soap_request(zval *this_ptr,
|
||||
int kind = Z_LVAL_PP(tmp) & SOAP_COMPRESSION_DEFLATE;
|
||||
|
||||
if (level > 9) {level = 9;}
|
||||
|
||||
|
||||
if ((Z_LVAL_PP(tmp) & SOAP_COMPRESSION_ACCEPT) != 0) {
|
||||
smart_str_append_const(&soap_headers_z,"Accept-Encoding: gzip, deflate\r\n");
|
||||
}
|
||||
@@ -372,7 +372,7 @@ int make_http_soap_request(zval *this_ptr,
|
||||
context = php_stream_context_from_zval(*tmp, 0);
|
||||
}
|
||||
|
||||
if (context &&
|
||||
if (context &&
|
||||
php_stream_context_get_option(context, "http", "max_redirects", &tmp) == SUCCESS) {
|
||||
if (Z_TYPE_PP(tmp) != IS_STRING || !is_numeric_string(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), &redirect_max, NULL, 1)) {
|
||||
if (Z_TYPE_PP(tmp) == IS_LONG)
|
||||
@@ -470,7 +470,7 @@ try_again:
|
||||
add_property_resource(this_ptr, "httpurl", ret);
|
||||
/*zend_list_addref(ret);*/
|
||||
|
||||
if (context &&
|
||||
if (context &&
|
||||
php_stream_context_get_option(context, "http", "protocol_version", &tmp) == SUCCESS &&
|
||||
Z_TYPE_PP(tmp) == IS_DOUBLE &&
|
||||
Z_DVAL_PP(tmp) == 1.0) {
|
||||
@@ -528,7 +528,7 @@ try_again:
|
||||
smart_str_appendl(&soap_headers, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
|
||||
smart_str_append_const(&soap_headers, "\r\n");
|
||||
}
|
||||
} else if (context &&
|
||||
} else if (context &&
|
||||
php_stream_context_get_option(context, "http", "user_agent", &tmp) == SUCCESS &&
|
||||
Z_TYPE_PP(tmp) == IS_STRING) {
|
||||
if (Z_STRLEN_PP(tmp) > 0) {
|
||||
@@ -670,7 +670,7 @@ try_again:
|
||||
PHP_MD5Update(&md5ctx, (unsigned char*)HA2, 32);
|
||||
PHP_MD5Final(hash, &md5ctx);
|
||||
make_digest(response, hash);
|
||||
|
||||
|
||||
smart_str_append_const(&soap_headers, "Authorization: Digest username=\"");
|
||||
smart_str_appendl(&soap_headers, Z_STRVAL_PP(login), Z_STRLEN_PP(login));
|
||||
if (zend_hash_find(Z_ARRVAL_PP(digest), "realm", sizeof("realm"), (void **)&tmp) == SUCCESS &&
|
||||
@@ -688,7 +688,7 @@ try_again:
|
||||
smart_str_appends(&soap_headers, phpurl->path);
|
||||
} else {
|
||||
smart_str_appendc(&soap_headers, '/');
|
||||
}
|
||||
}
|
||||
if (phpurl->query) {
|
||||
smart_str_appendc(&soap_headers, '?');
|
||||
smart_str_appends(&soap_headers, phpurl->query);
|
||||
@@ -759,18 +759,21 @@ try_again:
|
||||
zend_hash_internal_pointer_reset(Z_ARRVAL_PP(cookies));
|
||||
smart_str_append_const(&soap_headers, "Cookie: ");
|
||||
for (i = 0; i < n; i++) {
|
||||
ulong numindx;
|
||||
int res = zend_hash_get_current_key(Z_ARRVAL_PP(cookies), &key, &numindx, FALSE);
|
||||
zend_hash_get_current_data(Z_ARRVAL_PP(cookies), (void **)&data);
|
||||
zend_hash_get_current_key(Z_ARRVAL_PP(cookies), &key, NULL, FALSE);
|
||||
|
||||
if (Z_TYPE_PP(data) == IS_ARRAY) {
|
||||
if (res == HASH_KEY_IS_STRING && Z_TYPE_PP(data) == IS_ARRAY) {
|
||||
zval** value;
|
||||
|
||||
if (zend_hash_index_find(Z_ARRVAL_PP(data), 0, (void**)&value) == SUCCESS &&
|
||||
Z_TYPE_PP(value) == IS_STRING) {
|
||||
zval **tmp;
|
||||
if ((zend_hash_index_find(Z_ARRVAL_PP(data), 1, (void**)&tmp) == FAILURE ||
|
||||
Z_TYPE_PP(tmp) != IS_STRING ||
|
||||
strncmp(phpurl->path?phpurl->path:"/",Z_STRVAL_PP(tmp),Z_STRLEN_PP(tmp)) == 0) &&
|
||||
(zend_hash_index_find(Z_ARRVAL_PP(data), 2, (void**)&tmp) == FAILURE ||
|
||||
Z_TYPE_PP(tmp) != IS_STRING ||
|
||||
in_domain(phpurl->host,Z_STRVAL_PP(tmp))) &&
|
||||
(use_ssl || zend_hash_index_find(Z_ARRVAL_PP(data), 3, (void**)&tmp) == FAILURE)) {
|
||||
smart_str_appendl(&soap_headers, key, strlen(key));
|
||||
@@ -997,7 +1000,7 @@ try_again:
|
||||
efree(connection);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!get_http_body(stream, http_close, http_headers, &http_body, &http_body_size TSRMLS_CC)) {
|
||||
if (request != buf) {efree(request);}
|
||||
@@ -1048,7 +1051,7 @@ try_again:
|
||||
strcat(s, new_url->path);
|
||||
efree(new_url->path);
|
||||
new_url->path = s;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
char *s = emalloc(strlen(new_url->path) + 2);
|
||||
s[0] = '/'; s[1] = 0;
|
||||
|
||||
+52
-44
@@ -989,7 +989,7 @@ static HashTable* soap_create_typemap(sdlPtr sdl, HashTable *ht TSRMLS_DC)
|
||||
HashTable *ht2;
|
||||
HashPosition pos1, pos2;
|
||||
HashTable *typemap = NULL;
|
||||
|
||||
|
||||
zend_hash_internal_pointer_reset_ex(ht, &pos1);
|
||||
while (zend_hash_get_current_data_ex(ht, (void**)&tmp, &pos1) == SUCCESS) {
|
||||
char *type_name = NULL;
|
||||
@@ -1033,7 +1033,7 @@ static HashTable* soap_create_typemap(sdlPtr sdl, HashTable *ht TSRMLS_DC)
|
||||
}
|
||||
}
|
||||
zend_hash_move_forward_ex(ht2, &pos2);
|
||||
}
|
||||
}
|
||||
|
||||
if (type_name) {
|
||||
smart_str nscat = {0};
|
||||
@@ -1063,7 +1063,7 @@ static HashTable* soap_create_typemap(sdlPtr sdl, HashTable *ht TSRMLS_DC)
|
||||
new_enc->to_xml = enc->to_xml;
|
||||
new_enc->to_zval = enc->to_zval;
|
||||
new_enc->details.map = emalloc(sizeof(soapMapping));
|
||||
memset(new_enc->details.map, 0, sizeof(soapMapping));
|
||||
memset(new_enc->details.map, 0, sizeof(soapMapping));
|
||||
if (to_xml) {
|
||||
zval_add_ref(&to_xml);
|
||||
new_enc->details.map->to_xml = to_xml;
|
||||
@@ -1120,7 +1120,7 @@ PHP_METHOD(SoapServer, SoapServer)
|
||||
if (Z_TYPE_P(wsdl) != IS_STRING && Z_TYPE_P(wsdl) != IS_NULL) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters");
|
||||
}
|
||||
|
||||
|
||||
service = emalloc(sizeof(soapService));
|
||||
memset(service, 0, sizeof(soapService));
|
||||
service->send_errors = 1;
|
||||
@@ -1155,7 +1155,7 @@ PHP_METHOD(SoapServer, SoapServer)
|
||||
if (zend_hash_find(ht, "encoding", sizeof("encoding"), (void**)&tmp) == SUCCESS &&
|
||||
Z_TYPE_PP(tmp) == IS_STRING) {
|
||||
xmlCharEncodingHandlerPtr encoding;
|
||||
|
||||
|
||||
encoding = xmlFindCharEncodingHandler(Z_STRVAL_PP(tmp));
|
||||
if (encoding == NULL) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid 'encoding' option - '%s'", Z_STRVAL_PP(tmp));
|
||||
@@ -1215,7 +1215,7 @@ PHP_METHOD(SoapServer, SoapServer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (typemap_ht) {
|
||||
service->typemap = soap_create_typemap(service->sdl, typemap_ht TSRMLS_CC);
|
||||
}
|
||||
@@ -1345,7 +1345,7 @@ PHP_METHOD(SoapServer, getFunctions)
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
FETCH_THIS_SERVICE(service);
|
||||
|
||||
array_init(return_value);
|
||||
@@ -1505,7 +1505,7 @@ PHP_METHOD(SoapServer, handle)
|
||||
|
||||
FETCH_THIS_SERVICE(service);
|
||||
SOAP_GLOBAL(soap_version) = service->version;
|
||||
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &arg, &arg_len) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -1930,7 +1930,7 @@ PHP_METHOD(SoapServer, handle)
|
||||
|
||||
if (size == 0) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Dump memory failed");
|
||||
}
|
||||
}
|
||||
|
||||
if (soap_version == SOAP_1_2) {
|
||||
sapi_add_header("Content-Type: application/soap+xml; charset=utf-8", sizeof("Content-Type: application/soap+xml; charset=utf-8")-1, 1);
|
||||
@@ -2147,10 +2147,10 @@ static void soap_error_handler(int error_num, const char *error_filename, const
|
||||
use_exceptions = 1;
|
||||
}
|
||||
|
||||
if ((error_num == E_USER_ERROR ||
|
||||
error_num == E_COMPILE_ERROR ||
|
||||
if ((error_num == E_USER_ERROR ||
|
||||
error_num == E_COMPILE_ERROR ||
|
||||
error_num == E_CORE_ERROR ||
|
||||
error_num == E_ERROR ||
|
||||
error_num == E_ERROR ||
|
||||
error_num == E_PARSE) &&
|
||||
use_exceptions) {
|
||||
zval *fault, *exception;
|
||||
@@ -2219,10 +2219,10 @@ static void soap_error_handler(int error_num, const char *error_filename, const
|
||||
va_list argcopy;
|
||||
#endif
|
||||
|
||||
if (error_num == E_USER_ERROR ||
|
||||
error_num == E_COMPILE_ERROR ||
|
||||
if (error_num == E_USER_ERROR ||
|
||||
error_num == E_COMPILE_ERROR ||
|
||||
error_num == E_CORE_ERROR ||
|
||||
error_num == E_ERROR ||
|
||||
error_num == E_ERROR ||
|
||||
error_num == E_PARSE) {
|
||||
|
||||
char* code = SOAP_GLOBAL(error_code);
|
||||
@@ -2452,13 +2452,13 @@ PHP_METHOD(SoapClient, SoapClient)
|
||||
if (zend_hash_find(ht, "encoding", sizeof("encoding"), (void**)&tmp) == SUCCESS &&
|
||||
Z_TYPE_PP(tmp) == IS_STRING) {
|
||||
xmlCharEncodingHandlerPtr encoding;
|
||||
|
||||
|
||||
encoding = xmlFindCharEncodingHandler(Z_STRVAL_PP(tmp));
|
||||
if (encoding == NULL) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid 'encoding' option - '%s'", Z_STRVAL_PP(tmp));
|
||||
} else {
|
||||
xmlCharEncCloseFunc(encoding);
|
||||
add_property_stringl(this_ptr, "_encoding", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
|
||||
add_property_stringl(this_ptr, "_encoding", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
|
||||
}
|
||||
}
|
||||
if (zend_hash_find(ht, "classmap", sizeof("classmap"), (void**)&tmp) == SUCCESS &&
|
||||
@@ -2493,7 +2493,7 @@ PHP_METHOD(SoapClient, SoapClient)
|
||||
if (context) {
|
||||
add_property_resource(this_ptr, "_stream_context", context->rsrc_id);
|
||||
}
|
||||
|
||||
|
||||
if (zend_hash_find(ht, "cache_wsdl", sizeof("cache_wsdl"), (void**)&tmp) == SUCCESS &&
|
||||
Z_TYPE_PP(tmp) == IS_LONG) {
|
||||
cache_wsdl = Z_LVAL_PP(tmp);
|
||||
@@ -2503,7 +2503,7 @@ PHP_METHOD(SoapClient, SoapClient)
|
||||
Z_TYPE_PP(tmp) == IS_STRING) {
|
||||
add_property_stringl(this_ptr, "_user_agent", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
|
||||
}
|
||||
|
||||
|
||||
if (zend_hash_find(ht, "keep_alive", sizeof("keep_alive"), (void**)&tmp) == SUCCESS &&
|
||||
(Z_TYPE_PP(tmp) == IS_BOOL || Z_TYPE_PP(tmp) == IS_LONG) && Z_LVAL_PP(tmp) == 0) {
|
||||
add_property_long(this_ptr, "_keep_alive", 0);
|
||||
@@ -2606,7 +2606,7 @@ static int do_request(zval *this_ptr, xmlDoc *request, char *location, char *act
|
||||
xmlFree(buf);
|
||||
if (ret && zend_hash_find(Z_OBJPROP_P(this_ptr), "__soap_fault", sizeof("__soap_fault"), (void **) &fault) == SUCCESS) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2903,8 +2903,10 @@ PHP_METHOD(SoapClient, __call)
|
||||
}
|
||||
zend_hash_internal_pointer_reset(default_headers);
|
||||
while (zend_hash_get_current_data(default_headers, (void**)&tmp) == SUCCESS) {
|
||||
Z_ADDREF_PP(tmp);
|
||||
zend_hash_next_index_insert(soap_headers, tmp, sizeof(zval *), NULL);
|
||||
if(Z_TYPE_PP(tmp) == IS_OBJECT) {
|
||||
Z_ADDREF_PP(tmp);
|
||||
zend_hash_next_index_insert(soap_headers, tmp, sizeof(zval *), NULL);
|
||||
}
|
||||
zend_hash_move_forward(default_headers);
|
||||
}
|
||||
} else {
|
||||
@@ -2912,7 +2914,7 @@ PHP_METHOD(SoapClient, __call)
|
||||
free_soap_headers = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
arg_count = zend_hash_num_elements(Z_ARRVAL_P(args));
|
||||
|
||||
if (arg_count > 0) {
|
||||
@@ -2978,7 +2980,7 @@ PHP_METHOD(SoapClient, __getTypes)
|
||||
HashPosition pos;
|
||||
|
||||
FETCH_THIS_SDL(sdl);
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -3007,7 +3009,7 @@ PHP_METHOD(SoapClient, __getTypes)
|
||||
PHP_METHOD(SoapClient, __getLastRequest)
|
||||
{
|
||||
zval **tmp;
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -3030,7 +3032,7 @@ PHP_METHOD(SoapClient, __getLastResponse)
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__last_response", sizeof("__last_response"), (void **)&tmp) == SUCCESS &&
|
||||
Z_TYPE_PP(tmp) == IS_STRING) {
|
||||
RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
|
||||
@@ -3045,11 +3047,11 @@ PHP_METHOD(SoapClient, __getLastResponse)
|
||||
PHP_METHOD(SoapClient, __getLastRequestHeaders)
|
||||
{
|
||||
zval **tmp;
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__last_request_headers", sizeof("__last_request_headers"), (void **)&tmp) == SUCCESS &&
|
||||
Z_TYPE_PP(tmp) == IS_STRING) {
|
||||
RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
|
||||
@@ -3064,7 +3066,7 @@ PHP_METHOD(SoapClient, __getLastRequestHeaders)
|
||||
PHP_METHOD(SoapClient, __getLastResponseHeaders)
|
||||
{
|
||||
zval **tmp;
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -3209,10 +3211,10 @@ PHP_METHOD(SoapClient, __setSoapHeaders)
|
||||
|
||||
|
||||
/* {{{ proto string SoapClient::__setLocation([string new_location])
|
||||
Sets the location option (the endpoint URL that will be touched by the
|
||||
Sets the location option (the endpoint URL that will be touched by the
|
||||
following SOAP requests).
|
||||
If new_location is not specified or null then SoapClient will use endpoint
|
||||
from WSDL file.
|
||||
from WSDL file.
|
||||
The function returns old value of location options. */
|
||||
PHP_METHOD(SoapClient, __setLocation)
|
||||
{
|
||||
@@ -3261,10 +3263,10 @@ static void set_soap_fault(zval *obj, char *fault_code_ns, char *fault_code, cha
|
||||
if (Z_TYPE_P(obj) != IS_OBJECT) {
|
||||
object_init_ex(obj, soap_fault_class_entry);
|
||||
}
|
||||
|
||||
|
||||
add_property_string(obj, "faultstring", fault_string ? fault_string : "", 1);
|
||||
zend_update_property_string(zend_exception_get_default(TSRMLS_C), obj, "message", sizeof("message")-1, (fault_string ? fault_string : "") TSRMLS_CC);
|
||||
|
||||
|
||||
if (fault_code != NULL) {
|
||||
int soap_version = SOAP_GLOBAL(soap_version);
|
||||
|
||||
@@ -3689,7 +3691,7 @@ ignore_header:
|
||||
func = func->children;
|
||||
}
|
||||
deserialize_parameters(func, function, num_params, parameters TSRMLS_CC);
|
||||
|
||||
|
||||
encode_finish();
|
||||
|
||||
return function;
|
||||
@@ -3971,8 +3973,8 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
|
||||
}
|
||||
|
||||
if (fault_ns == NULL &&
|
||||
fault &&
|
||||
fault->details &&
|
||||
fault &&
|
||||
fault->details &&
|
||||
zend_hash_num_elements(fault->details) == 1) {
|
||||
sdlParamPtr sparam;
|
||||
|
||||
@@ -3996,7 +3998,7 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
|
||||
xmlChar *code = xmlBuildQName(BAD_CAST(str), nsptr->prefix, NULL, 0);
|
||||
xmlNodeSetContent(node, code);
|
||||
xmlFree(code);
|
||||
} else {
|
||||
} else {
|
||||
xmlNodeSetContentLen(node, BAD_CAST(str), (int)new_len);
|
||||
}
|
||||
efree(str);
|
||||
@@ -4022,7 +4024,7 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
|
||||
xmlChar *code = xmlBuildQName(BAD_CAST(str), nsptr->prefix, NULL, 0);
|
||||
xmlNodeSetContent(node, code);
|
||||
xmlFree(code);
|
||||
} else {
|
||||
} else {
|
||||
xmlNodeSetContentLen(node, BAD_CAST(str), (int)new_len);
|
||||
}
|
||||
efree(str);
|
||||
@@ -4194,7 +4196,7 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
|
||||
|
||||
encode_finish();
|
||||
|
||||
if (function && function->responseName == NULL &&
|
||||
if (function && function->responseName == NULL &&
|
||||
body->children == NULL && head == NULL) {
|
||||
xmlFreeDoc(doc);
|
||||
return NULL;
|
||||
@@ -4328,11 +4330,18 @@ static xmlDocPtr serialize_function_call(zval *this_ptr, sdlFunctionPtr function
|
||||
if (head) {
|
||||
zval** header;
|
||||
|
||||
zend_hash_internal_pointer_reset(soap_headers);
|
||||
while (zend_hash_get_current_data(soap_headers,(void**)&header) == SUCCESS) {
|
||||
HashTable *ht = Z_OBJPROP_PP(header);
|
||||
for(zend_hash_internal_pointer_reset(soap_headers);
|
||||
zend_hash_get_current_data(soap_headers,(void**)&header) == SUCCESS;
|
||||
zend_hash_move_forward(soap_headers)
|
||||
) {
|
||||
HashTable *ht;
|
||||
zval **name, **ns, **tmp;
|
||||
|
||||
if (Z_TYPE_PP(header) != IS_OBJECT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ht = Z_OBJPROP_PP(header);
|
||||
if (zend_hash_find(ht, "name", sizeof("name"), (void**)&name) == SUCCESS &&
|
||||
Z_TYPE_PP(name) == IS_STRING &&
|
||||
zend_hash_find(ht, "namespace", sizeof("namespace"), (void**)&ns) == SUCCESS &&
|
||||
@@ -4371,7 +4380,6 @@ static xmlDocPtr serialize_function_call(zval *this_ptr, sdlFunctionPtr function
|
||||
xmlSetNs(h, nsptr);
|
||||
set_soap_header_attributes(h, ht, version);
|
||||
}
|
||||
zend_hash_move_forward(soap_headers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4482,7 +4490,7 @@ static sdlParamPtr get_param(sdlFunctionPtr function, char *param_name, int inde
|
||||
return *tmp;
|
||||
} else {
|
||||
HashPosition pos;
|
||||
|
||||
|
||||
zend_hash_internal_pointer_reset_ex(ht, &pos);
|
||||
while (zend_hash_get_current_data_ex(ht, (void **)&tmp, &pos) != FAILURE) {
|
||||
if ((*tmp)->paramName && strcmp(param_name, (*tmp)->paramName) == 0) {
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
--TEST--
|
||||
Bug #70388 (SOAP serialize_function_call() type confusion / RCE)
|
||||
--SKIPIF--
|
||||
<?php require_once('skipif.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$dummy = unserialize('O:10:"SoapClient":3:{s:3:"uri";s:1:"X";s:8:"location";s:22:"http://localhost/a.xml";s:17:"__default_headers";a:1:{i:1;s:1337:"'.str_repeat("X", 1337).'";}}');
|
||||
try {
|
||||
var_dump($dummy->notexisting());
|
||||
} catch(Exception $e) {
|
||||
var_dump($e->getMessage());
|
||||
var_dump(get_class($e));
|
||||
}
|
||||
?>
|
||||
--EXPECTF--
|
||||
string(%d) "%s"
|
||||
string(9) "SoapFault"
|
||||
+50
-43
@@ -309,7 +309,7 @@ static zval **spl_array_get_dimension_ptr_ptr(int check_inherited, zval *object,
|
||||
if (!offset) {
|
||||
return &EG(uninitialized_zval_ptr);
|
||||
}
|
||||
|
||||
|
||||
if ((type == BP_VAR_W || type == BP_VAR_RW) && (ht->nApplyCount > 0)) {
|
||||
zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
|
||||
return &EG(error_zval_ptr);;
|
||||
@@ -341,8 +341,8 @@ static zval **spl_array_get_dimension_ptr_ptr(int check_inherited, zval *object,
|
||||
case IS_RESOURCE:
|
||||
zend_error(E_STRICT, "Resource ID#%ld used as offset, casting to integer (%ld)", Z_LVAL_P(offset), Z_LVAL_P(offset));
|
||||
case IS_DOUBLE:
|
||||
case IS_BOOL:
|
||||
case IS_LONG:
|
||||
case IS_BOOL:
|
||||
case IS_LONG:
|
||||
if (offset->type == IS_DOUBLE) {
|
||||
index = (long)Z_DVAL_P(offset);
|
||||
} else {
|
||||
@@ -386,7 +386,7 @@ static zval *spl_array_read_dimension_ex(int check_inherited, zval *object, zval
|
||||
} else {
|
||||
SEPARATE_ARG_IF_REF(offset);
|
||||
}
|
||||
zend_call_method_with_1_params(&object, Z_OBJCE_P(object), &intern->fptr_offset_get, "offsetGet", &rv, offset);
|
||||
zend_call_method_with_1_params(&object, Z_OBJCE_P(object), &intern->fptr_offset_get, "offsetGet", &rv, offset);
|
||||
zval_ptr_dtor(&offset);
|
||||
if (rv) {
|
||||
zval_ptr_dtor(&intern->retval);
|
||||
@@ -444,7 +444,7 @@ static void spl_array_write_dimension_ex(int check_inherited, zval *object, zval
|
||||
zval_ptr_dtor(&offset);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!offset) {
|
||||
ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
|
||||
if (ht->nApplyCount > 0) {
|
||||
@@ -467,8 +467,8 @@ static void spl_array_write_dimension_ex(int check_inherited, zval *object, zval
|
||||
return;
|
||||
case IS_DOUBLE:
|
||||
case IS_RESOURCE:
|
||||
case IS_BOOL:
|
||||
case IS_LONG:
|
||||
case IS_BOOL:
|
||||
case IS_LONG:
|
||||
ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
|
||||
if (ht->nApplyCount > 0) {
|
||||
zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
|
||||
@@ -556,13 +556,13 @@ static void spl_array_unset_dimension_ex(int check_inherited, zval *object, zval
|
||||
obj->std.properties_table[property_info->offset] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case IS_DOUBLE:
|
||||
case IS_RESOURCE:
|
||||
case IS_BOOL:
|
||||
case IS_LONG:
|
||||
case IS_BOOL:
|
||||
case IS_LONG:
|
||||
if (offset->type == IS_DOUBLE) {
|
||||
index = (long)Z_DVAL_P(offset);
|
||||
} else {
|
||||
@@ -608,7 +608,7 @@ static int spl_array_has_dimension_ex(int check_inherited, zval *object, zval *o
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
switch(Z_TYPE_P(offset)) {
|
||||
case IS_STRING:
|
||||
{
|
||||
@@ -627,9 +627,9 @@ static int spl_array_has_dimension_ex(int check_inherited, zval *object, zval *o
|
||||
return 0;
|
||||
case IS_DOUBLE:
|
||||
case IS_RESOURCE:
|
||||
case IS_BOOL:
|
||||
case IS_BOOL:
|
||||
case IS_LONG:
|
||||
{
|
||||
{
|
||||
HashTable *ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
|
||||
if (offset->type == IS_DOUBLE) {
|
||||
index = (long)Z_DVAL_P(offset);
|
||||
@@ -727,7 +727,7 @@ void spl_array_iterator_append(zval *object, zval *append_value TSRMLS_DC) /* {{
|
||||
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and is no longer an array");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (Z_TYPE_P(intern->array) == IS_OBJECT) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "Cannot append properties to objects, use %s::offsetSet() instead", Z_OBJCE_P(object)->name);
|
||||
return;
|
||||
@@ -771,7 +771,7 @@ SPL_METHOD(Array, getArrayCopy)
|
||||
{
|
||||
zval *object = getThis(), *tmp;
|
||||
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
|
||||
|
||||
array_init(return_value);
|
||||
zend_hash_copy(HASH_OF(return_value), spl_array_get_hash_table(intern, 0 TSRMLS_CC), (copy_ctor_func_t) zval_add_ref, &tmp, sizeof(zval*));
|
||||
} /* }}} */
|
||||
@@ -990,7 +990,7 @@ static void spl_array_it_dtor(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
|
||||
efree(iterator);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
static int spl_array_it_valid(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
spl_array_it *iterator = (spl_array_it *)iter;
|
||||
@@ -1037,7 +1037,7 @@ static int spl_array_it_get_current_key(zend_object_iterator *iter, char **str_k
|
||||
if (spl_array_object_verify_pos_ex(object, aht, "ArrayIterator::current(): " TSRMLS_CC) == FAILURE) {
|
||||
return HASH_KEY_NON_EXISTANT;
|
||||
}
|
||||
|
||||
|
||||
return zend_hash_get_current_key_ex(aht, str_key, str_key_len, int_key, 1, &object->pos);
|
||||
}
|
||||
}
|
||||
@@ -1057,7 +1057,7 @@ static void spl_array_it_move_forward(zend_object_iterator *iter TSRMLS_DC) /* {
|
||||
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "ArrayIterator::current(): Array was modified outside object and is no longer an array");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if ((object->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos_ex(object, aht TSRMLS_CC) == FAILURE) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "ArrayIterator::next(): Array was modified outside object and internal position is no longer valid");
|
||||
} else {
|
||||
@@ -1115,7 +1115,7 @@ static void spl_array_set_array(zval *object, spl_array_object *intern, zval **a
|
||||
if (just_array) {
|
||||
spl_array_object *other = (spl_array_object*)zend_object_store_get_object(*array TSRMLS_CC);
|
||||
ar_flags = other->ar_flags & ~SPL_ARRAY_INT_MASK;
|
||||
}
|
||||
}
|
||||
ar_flags |= SPL_ARRAY_USE_OTHER;
|
||||
intern->array = *array;
|
||||
} else {
|
||||
@@ -1173,7 +1173,7 @@ zend_object_iterator *spl_array_get_iterator(zend_class_entry *ce, zval *object,
|
||||
iterator->intern.ce = ce;
|
||||
iterator->intern.value = NULL;
|
||||
iterator->object = array_object;
|
||||
|
||||
|
||||
return (zend_object_iterator*)iterator;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -1238,7 +1238,7 @@ SPL_METHOD(Array, getIteratorClass)
|
||||
{
|
||||
zval *object = getThis();
|
||||
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -1253,11 +1253,11 @@ SPL_METHOD(Array, getFlags)
|
||||
{
|
||||
zval *object = getThis();
|
||||
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
RETURN_LONG(intern->ar_flags & ~SPL_ARRAY_INT_MASK);
|
||||
}
|
||||
/* }}} */
|
||||
@@ -1273,7 +1273,7 @@ SPL_METHOD(Array, setFlags)
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &ar_flags) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
intern->ar_flags = (intern->ar_flags & SPL_ARRAY_INT_MASK) | (ar_flags & ~SPL_ARRAY_INT_MASK);
|
||||
}
|
||||
/* }}} */
|
||||
@@ -1287,7 +1287,7 @@ SPL_METHOD(Array, exchangeArray)
|
||||
|
||||
array_init(return_value);
|
||||
zend_hash_copy(HASH_OF(return_value), spl_array_get_hash_table(intern, 0 TSRMLS_CC), (copy_ctor_func_t) zval_add_ref, &tmp, sizeof(zval*));
|
||||
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &array) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -1305,7 +1305,7 @@ SPL_METHOD(Array, getIterator)
|
||||
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
spl_array_object *iterator;
|
||||
HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -1328,7 +1328,7 @@ SPL_METHOD(Array, rewind)
|
||||
{
|
||||
zval *object = getThis();
|
||||
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -1361,9 +1361,9 @@ SPL_METHOD(Array, seek)
|
||||
if (position >= 0) { /* negative values are not supported */
|
||||
spl_array_rewind(intern TSRMLS_CC);
|
||||
result = SUCCESS;
|
||||
|
||||
|
||||
while (position-- > 0 && (result = spl_array_next(intern TSRMLS_CC)) == SUCCESS);
|
||||
|
||||
|
||||
if (result == SUCCESS && zend_hash_has_more_elements_ex(aht, &intern->pos) == SUCCESS) {
|
||||
return; /* ok */
|
||||
}
|
||||
@@ -1383,7 +1383,7 @@ int static spl_array_object_count_elements_helper(spl_array_object *intern, long
|
||||
}
|
||||
|
||||
if (Z_TYPE_P(intern->array) == IS_OBJECT) {
|
||||
/* We need to store the 'pos' since we'll modify it in the functions
|
||||
/* We need to store the 'pos' since we'll modify it in the functions
|
||||
* we're going to call and which do not support 'pos' as parameter. */
|
||||
pos = intern->pos;
|
||||
*count = 0;
|
||||
@@ -1427,7 +1427,7 @@ SPL_METHOD(Array, count)
|
||||
{
|
||||
long count;
|
||||
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -1443,11 +1443,11 @@ static void spl_array_method(INTERNAL_FUNCTION_PARAMETERS, char *fname, int fnam
|
||||
HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
|
||||
zval *tmp, *arg = NULL;
|
||||
zval *retval_ptr = NULL;
|
||||
|
||||
|
||||
MAKE_STD_ZVAL(tmp);
|
||||
Z_TYPE_P(tmp) = IS_ARRAY;
|
||||
Z_ARRVAL_P(tmp) = aht;
|
||||
|
||||
|
||||
if (!use_arg) {
|
||||
aht->nApplyCount++;
|
||||
zend_call_method(NULL, NULL, NULL, fname, fname_len, &retval_ptr, 1, tmp, NULL TSRMLS_CC);
|
||||
@@ -1524,7 +1524,7 @@ SPL_METHOD(Array, current)
|
||||
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
zval **entry;
|
||||
HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -1547,7 +1547,7 @@ SPL_METHOD(Array, key)
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
spl_array_iterator_key(getThis(), return_value TSRMLS_CC);
|
||||
} /* }}} */
|
||||
|
||||
@@ -1594,7 +1594,7 @@ SPL_METHOD(Array, next)
|
||||
|
||||
spl_array_next_no_verify(intern, aht TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto bool ArrayIterator::valid()
|
||||
Check whether array contains more entries */
|
||||
@@ -1623,7 +1623,7 @@ SPL_METHOD(Array, hasChildren)
|
||||
zval *object = getThis(), **entry;
|
||||
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -1647,7 +1647,7 @@ SPL_METHOD(Array, getChildren)
|
||||
zval *object = getThis(), **entry, *flags;
|
||||
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -1687,7 +1687,7 @@ SPL_METHOD(Array, serialize)
|
||||
php_serialize_data_t var_hash;
|
||||
smart_str buf = {0};
|
||||
zval *flags;
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -1747,7 +1747,7 @@ SPL_METHOD(Array, unserialize)
|
||||
zval *pmembers, *pflags = NULL;
|
||||
HashTable *aht;
|
||||
long flags;
|
||||
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf, &buf_len) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -1774,13 +1774,12 @@ SPL_METHOD(Array, unserialize)
|
||||
|
||||
ALLOC_INIT_ZVAL(pflags);
|
||||
if (!php_var_unserialize(&pflags, &p, s + buf_len, &var_hash TSRMLS_CC) || Z_TYPE_P(pflags) != IS_LONG) {
|
||||
zval_ptr_dtor(&pflags);
|
||||
goto outexcept;
|
||||
}
|
||||
|
||||
var_push_dtor(&var_hash, &pflags);
|
||||
--p; /* for ';' */
|
||||
flags = Z_LVAL_P(pflags);
|
||||
zval_ptr_dtor(&pflags);
|
||||
/* flags needs to be verified and we also need to verify whether the next
|
||||
* thing we get is ';'. After that we require an 'm' or somethign else
|
||||
* where 'm' stands for members and anything else should be an array. If
|
||||
@@ -1802,6 +1801,7 @@ SPL_METHOD(Array, unserialize)
|
||||
if (!php_var_unserialize(&intern->array, &p, s + buf_len, &var_hash TSRMLS_CC)) {
|
||||
goto outexcept;
|
||||
}
|
||||
var_push_dtor(&var_hash, &intern->array);
|
||||
}
|
||||
if (*p != ';') {
|
||||
goto outexcept;
|
||||
@@ -1820,6 +1820,7 @@ SPL_METHOD(Array, unserialize)
|
||||
goto outexcept;
|
||||
}
|
||||
|
||||
var_push_dtor(&var_hash, &pmembers);
|
||||
/* copy members */
|
||||
if (!intern->std.properties) {
|
||||
rebuild_object_properties(&intern->std);
|
||||
@@ -1830,10 +1831,16 @@ SPL_METHOD(Array, unserialize)
|
||||
/* done reading $serialized */
|
||||
|
||||
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
|
||||
if (pflags) {
|
||||
zval_ptr_dtor(&pflags);
|
||||
}
|
||||
return;
|
||||
|
||||
outexcept:
|
||||
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
|
||||
if (pflags) {
|
||||
zval_ptr_dtor(&pflags);
|
||||
}
|
||||
zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Error at offset %ld of %d bytes", (long)((char*)p - buf), buf_len);
|
||||
return;
|
||||
|
||||
@@ -1982,7 +1989,7 @@ PHP_MINIT_FUNCTION(spl_array)
|
||||
REGISTER_SPL_IMPLEMENTS(ArrayIterator, Countable);
|
||||
memcpy(&spl_handler_ArrayIterator, &spl_handler_ArrayObject, sizeof(zend_object_handlers));
|
||||
spl_ce_ArrayIterator->get_iterator = spl_array_get_iterator;
|
||||
|
||||
|
||||
REGISTER_SPL_SUB_CLASS_EX(RecursiveArrayIterator, ArrayIterator, spl_array_object_new, spl_funcs_RecursiveArrayIterator);
|
||||
REGISTER_SPL_IMPLEMENTS(RecursiveArrayIterator, RecursiveIterator);
|
||||
spl_ce_RecursiveArrayIterator->get_iterator = spl_array_get_iterator;
|
||||
|
||||
+14
-12
@@ -500,7 +500,7 @@ static int spl_dllist_object_count_elements(zval *object, long *count TSRMLS_DC)
|
||||
|
||||
*count = spl_ptr_llist_count(intern->llist);
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static HashTable* spl_dllist_object_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /* {{{{ */
|
||||
@@ -571,7 +571,7 @@ SPL_METHOD(SplDoublyLinkedList, push)
|
||||
spl_ptr_llist_push(intern->llist, value TSRMLS_CC);
|
||||
|
||||
RETURN_TRUE;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto bool SplDoublyLinkedList::unshift(mixed $value) U
|
||||
@@ -614,7 +614,7 @@ SPL_METHOD(SplDoublyLinkedList, pop)
|
||||
}
|
||||
|
||||
RETURN_ZVAL(value, 1, 1);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto mixed SplDoublyLinkedList::shift() U
|
||||
@@ -637,7 +637,7 @@ SPL_METHOD(SplDoublyLinkedList, shift)
|
||||
}
|
||||
|
||||
RETURN_ZVAL(value, 1, 1);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto mixed SplDoublyLinkedList::top() U
|
||||
@@ -1051,7 +1051,7 @@ static void spl_dllist_it_move_forward(zend_object_iterator *iter TSRMLS_DC) /*
|
||||
SPL_METHOD(SplDoublyLinkedList, key)
|
||||
{
|
||||
spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -1065,7 +1065,7 @@ SPL_METHOD(SplDoublyLinkedList, key)
|
||||
SPL_METHOD(SplDoublyLinkedList, prev)
|
||||
{
|
||||
spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -1079,7 +1079,7 @@ SPL_METHOD(SplDoublyLinkedList, prev)
|
||||
SPL_METHOD(SplDoublyLinkedList, next)
|
||||
{
|
||||
spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -1093,7 +1093,7 @@ SPL_METHOD(SplDoublyLinkedList, next)
|
||||
SPL_METHOD(SplDoublyLinkedList, valid)
|
||||
{
|
||||
spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -1107,7 +1107,7 @@ SPL_METHOD(SplDoublyLinkedList, valid)
|
||||
SPL_METHOD(SplDoublyLinkedList, rewind)
|
||||
{
|
||||
spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -1122,7 +1122,7 @@ SPL_METHOD(SplDoublyLinkedList, current)
|
||||
{
|
||||
spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
spl_ptr_llist_element *element = intern->traverse_pointer;
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -1177,7 +1177,7 @@ SPL_METHOD(SplDoublyLinkedList, serialize)
|
||||
} else {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
|
||||
} /* }}} */
|
||||
|
||||
/* {{{ proto void SplDoublyLinkedList::unserialize(string serialized)
|
||||
@@ -1190,7 +1190,7 @@ SPL_METHOD(SplDoublyLinkedList, unserialize)
|
||||
int buf_len;
|
||||
const unsigned char *p, *s;
|
||||
php_unserialize_data_t var_hash;
|
||||
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf, &buf_len) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -1209,6 +1209,7 @@ SPL_METHOD(SplDoublyLinkedList, unserialize)
|
||||
zval_ptr_dtor(&flags);
|
||||
goto error;
|
||||
}
|
||||
var_push_dtor(&var_hash, &flags);
|
||||
intern->flags = Z_LVAL_P(flags);
|
||||
zval_ptr_dtor(&flags);
|
||||
|
||||
@@ -1220,6 +1221,7 @@ SPL_METHOD(SplDoublyLinkedList, unserialize)
|
||||
zval_ptr_dtor(&elem);
|
||||
goto error;
|
||||
}
|
||||
var_push_dtor(&var_hash, &elem);
|
||||
|
||||
spl_ptr_llist_push(intern->llist, elem TSRMLS_CC);
|
||||
}
|
||||
|
||||
+37
-33
@@ -99,9 +99,9 @@ void spl_SplOjectStorage_free_storage(void *object TSRMLS_DC) /* {{{ */
|
||||
spl_SplObjectStorage *intern = (spl_SplObjectStorage *)object;
|
||||
|
||||
zend_object_std_dtor(&intern->std TSRMLS_CC);
|
||||
|
||||
|
||||
zend_hash_destroy(&intern->storage);
|
||||
|
||||
|
||||
if (intern->debug_info != NULL) {
|
||||
zend_hash_destroy(intern->debug_info);
|
||||
efree(intern->debug_info);
|
||||
@@ -196,7 +196,7 @@ spl_SplObjectStorageElement* spl_object_storage_get(spl_SplObjectStorage *intern
|
||||
void spl_object_storage_attach(spl_SplObjectStorage *intern, zval *this, zval *obj, zval *inf TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
spl_SplObjectStorageElement *pelement, element;
|
||||
|
||||
|
||||
int hash_len;
|
||||
char *hash = spl_object_storage_get_hash(intern, this, obj, &hash_len TSRMLS_CC);
|
||||
if (!hash) {
|
||||
@@ -232,7 +232,7 @@ int spl_object_storage_detach(spl_SplObjectStorage *intern, zval *this, zval *ob
|
||||
}
|
||||
ret = zend_hash_del(&intern->storage, hash, hash_len);
|
||||
spl_object_storage_free_hash(intern, hash);
|
||||
|
||||
|
||||
return ret;
|
||||
} /* }}}*/
|
||||
|
||||
@@ -372,7 +372,7 @@ static HashTable *spl_object_storage_get_gc(zval *obj, zval ***table, int *n TSR
|
||||
**gcdata_arr_pp;
|
||||
|
||||
props = std_object_handlers.get_properties(obj TSRMLS_CC);
|
||||
|
||||
|
||||
*table = NULL;
|
||||
*n = 0;
|
||||
|
||||
@@ -492,7 +492,7 @@ SPL_METHOD(SplObjectStorage, getHash)
|
||||
|
||||
hash = emalloc(33);
|
||||
php_spl_object_hash(obj, hash TSRMLS_CC);
|
||||
|
||||
|
||||
RETVAL_STRING(hash, 0);
|
||||
|
||||
} /* }}} */
|
||||
@@ -621,11 +621,11 @@ SPL_METHOD(SplObjectStorage, contains)
|
||||
SPL_METHOD(SplObjectStorage, count)
|
||||
{
|
||||
spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
RETURN_LONG(zend_hash_num_elements(&intern->storage));
|
||||
} /* }}} */
|
||||
|
||||
@@ -634,11 +634,11 @@ SPL_METHOD(SplObjectStorage, count)
|
||||
SPL_METHOD(SplObjectStorage, rewind)
|
||||
{
|
||||
spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos);
|
||||
intern->index = 0;
|
||||
} /* }}} */
|
||||
@@ -648,11 +648,11 @@ SPL_METHOD(SplObjectStorage, rewind)
|
||||
SPL_METHOD(SplObjectStorage, valid)
|
||||
{
|
||||
spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
RETURN_BOOL(zend_hash_has_more_elements_ex(&intern->storage, &intern->pos) == SUCCESS);
|
||||
} /* }}} */
|
||||
|
||||
@@ -661,11 +661,11 @@ SPL_METHOD(SplObjectStorage, valid)
|
||||
SPL_METHOD(SplObjectStorage, key)
|
||||
{
|
||||
spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
RETURN_LONG(intern->index);
|
||||
} /* }}} */
|
||||
|
||||
@@ -675,11 +675,11 @@ SPL_METHOD(SplObjectStorage, current)
|
||||
{
|
||||
spl_SplObjectStorageElement *element;
|
||||
spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (zend_hash_get_current_data_ex(&intern->storage, (void**)&element, &intern->pos) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -696,7 +696,7 @@ SPL_METHOD(SplObjectStorage, getInfo)
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (zend_hash_get_current_data_ex(&intern->storage, (void**)&element, &intern->pos) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -710,7 +710,7 @@ SPL_METHOD(SplObjectStorage, setInfo)
|
||||
spl_SplObjectStorageElement *element;
|
||||
spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
zval *inf;
|
||||
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &inf) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -728,11 +728,11 @@ SPL_METHOD(SplObjectStorage, setInfo)
|
||||
SPL_METHOD(SplObjectStorage, next)
|
||||
{
|
||||
spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
zend_hash_move_forward_ex(&intern->storage, &intern->pos);
|
||||
intern->index++;
|
||||
} /* }}} */
|
||||
@@ -754,7 +754,7 @@ SPL_METHOD(SplObjectStorage, serialize)
|
||||
}
|
||||
|
||||
PHP_VAR_SERIALIZE_INIT(var_hash);
|
||||
|
||||
|
||||
/* storage */
|
||||
smart_str_appendl(&buf, "x:", 2);
|
||||
MAKE_STD_ZVAL(flags);
|
||||
@@ -793,7 +793,7 @@ SPL_METHOD(SplObjectStorage, serialize)
|
||||
} else {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
|
||||
} /* }}} */
|
||||
|
||||
/* {{{ proto void SplObjectStorage::unserialize(string serialized)
|
||||
@@ -808,7 +808,7 @@ SPL_METHOD(SplObjectStorage, unserialize)
|
||||
php_unserialize_data_t var_hash;
|
||||
zval *pentry, *pmembers, *pcount = NULL, *pinf;
|
||||
long count;
|
||||
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf, &buf_len) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -832,14 +832,15 @@ SPL_METHOD(SplObjectStorage, unserialize)
|
||||
goto outexcept;
|
||||
}
|
||||
|
||||
var_push_dtor(&var_hash, &pcount);
|
||||
--p; /* for ';' */
|
||||
count = Z_LVAL_P(pcount);
|
||||
|
||||
|
||||
while(count-- > 0) {
|
||||
spl_SplObjectStorageElement *pelement;
|
||||
char *hash;
|
||||
int hash_len;
|
||||
|
||||
|
||||
if (*p != ';') {
|
||||
goto outexcept;
|
||||
}
|
||||
@@ -852,6 +853,7 @@ SPL_METHOD(SplObjectStorage, unserialize)
|
||||
zval_ptr_dtor(&pentry);
|
||||
goto outexcept;
|
||||
}
|
||||
var_push_dtor(&var_hash, &pentry);
|
||||
if(Z_TYPE_P(pentry) != IS_OBJECT) {
|
||||
zval_ptr_dtor(&pentry);
|
||||
goto outexcept;
|
||||
@@ -863,6 +865,7 @@ SPL_METHOD(SplObjectStorage, unserialize)
|
||||
zval_ptr_dtor(&pinf);
|
||||
goto outexcept;
|
||||
}
|
||||
var_push_dtor(&var_hash, &pinf);
|
||||
}
|
||||
|
||||
hash = spl_object_storage_get_hash(intern, getThis(), pentry, &hash_len TSRMLS_CC);
|
||||
@@ -880,7 +883,7 @@ SPL_METHOD(SplObjectStorage, unserialize)
|
||||
if(pelement->obj) {
|
||||
var_push_dtor(&var_hash, &pelement->obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
spl_object_storage_attach(intern, getThis(), pentry, pinf TSRMLS_CC);
|
||||
zval_ptr_dtor(&pentry);
|
||||
zval_ptr_dtor(&pinf);
|
||||
@@ -903,6 +906,7 @@ SPL_METHOD(SplObjectStorage, unserialize)
|
||||
goto outexcept;
|
||||
}
|
||||
|
||||
var_push_dtor(&var_hash, &pmembers);
|
||||
/* copy members */
|
||||
if (!intern->std.properties) {
|
||||
rebuild_object_properties(&intern->std);
|
||||
@@ -1020,7 +1024,7 @@ SPL_METHOD(MultipleIterator, __construct)
|
||||
SPL_METHOD(MultipleIterator, getFlags)
|
||||
{
|
||||
spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -1087,7 +1091,7 @@ SPL_METHOD(MultipleIterator, rewind)
|
||||
zval *it;
|
||||
|
||||
intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -1110,7 +1114,7 @@ SPL_METHOD(MultipleIterator, next)
|
||||
zval *it;
|
||||
|
||||
intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -1134,7 +1138,7 @@ SPL_METHOD(MultipleIterator, valid)
|
||||
long expect, valid;
|
||||
|
||||
intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -1180,7 +1184,7 @@ static void spl_multiple_iterator_get_all(spl_SplObjectStorage *intern, int get_
|
||||
}
|
||||
|
||||
array_init_size(return_value, num_elements);
|
||||
|
||||
|
||||
zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos);
|
||||
while (zend_hash_get_current_data_ex(&intern->storage, (void**)&element, &intern->pos) == SUCCESS && !EG(exception)) {
|
||||
it = element->obj;
|
||||
@@ -1242,7 +1246,7 @@ SPL_METHOD(MultipleIterator, current)
|
||||
{
|
||||
spl_SplObjectStorage *intern;
|
||||
intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -1257,7 +1261,7 @@ SPL_METHOD(MultipleIterator, key)
|
||||
{
|
||||
spl_SplObjectStorage *intern;
|
||||
intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
--TEST--
|
||||
Bug #70068 (Dangling pointer in the unserialization of ArrayObject items)
|
||||
--FILE--
|
||||
<?php
|
||||
$a = unserialize('a:3:{i:0;C:11:"ArrayObject":20:{x:i:0;r:3;;m:a:0:{};}i:1;d:11;i:2;S:31:"AAAAAAAABBBBCCCC\01\00\00\00\04\00\00\00\00\00\00\00\00\00\00";}');
|
||||
?>
|
||||
OK
|
||||
--EXPECT--
|
||||
OK
|
||||
@@ -0,0 +1,50 @@
|
||||
--TEST--
|
||||
SPL: Bug #70155 Use After Free Vulnerability in unserialize() with SPLArrayObject
|
||||
--FILE--
|
||||
<?php
|
||||
$inner = 'x:i:0;O:12:"DateInterval":1:{s:1:"y";i:3;};m:a:1:{i:0;R:2;}';
|
||||
$exploit = 'C:11:"ArrayObject":'.strlen($inner).':{'.$inner.'}';
|
||||
$data = unserialize($exploit);
|
||||
|
||||
var_dump($data);
|
||||
?>
|
||||
===DONE===
|
||||
--EXPECTF--
|
||||
object(ArrayObject)#1 (2) {
|
||||
[0]=>
|
||||
int(0)
|
||||
["storage":"ArrayObject":private]=>
|
||||
object(DateInterval)#2 (15) {
|
||||
["y"]=>
|
||||
int(3)
|
||||
["m"]=>
|
||||
int(-1)
|
||||
["d"]=>
|
||||
int(-1)
|
||||
["h"]=>
|
||||
int(-1)
|
||||
["i"]=>
|
||||
int(-1)
|
||||
["s"]=>
|
||||
int(-1)
|
||||
["weekday"]=>
|
||||
int(-1)
|
||||
["weekday_behavior"]=>
|
||||
int(-1)
|
||||
["first_last_day_of"]=>
|
||||
int(-1)
|
||||
["invert"]=>
|
||||
int(0)
|
||||
["days"]=>
|
||||
int(-1)
|
||||
["special_type"]=>
|
||||
int(0)
|
||||
["special_amount"]=>
|
||||
int(-1)
|
||||
["have_weekday_relative"]=>
|
||||
int(0)
|
||||
["have_special_relative"]=>
|
||||
int(0)
|
||||
}
|
||||
}
|
||||
===DONE===
|
||||
@@ -0,0 +1,29 @@
|
||||
--TEST--
|
||||
SPL: Bug #70166 Use After Free Vulnerability in unserialize() with SPLArrayObject
|
||||
--FILE--
|
||||
<?php
|
||||
$inner = 'x:i:1;a:0:{};m:a:0:{}';
|
||||
$exploit = 'a:2:{i:0;C:11:"ArrayObject":'.strlen($inner).':{'.$inner.'}i:1;R:5;}';
|
||||
|
||||
$data = unserialize($exploit);
|
||||
|
||||
for($i = 0; $i < 5; $i++) {
|
||||
$v[$i] = 'hi'.$i;
|
||||
}
|
||||
|
||||
var_dump($data);
|
||||
?>
|
||||
===DONE===
|
||||
--EXPECTF--
|
||||
array(2) {
|
||||
[0]=>
|
||||
object(ArrayObject)#%d (1) {
|
||||
["storage":"ArrayObject":private]=>
|
||||
array(0) {
|
||||
}
|
||||
}
|
||||
[1]=>
|
||||
array(0) {
|
||||
}
|
||||
}
|
||||
===DONE===
|
||||
@@ -0,0 +1,36 @@
|
||||
--TEST--
|
||||
SPL: Bug #70168 Use After Free Vulnerability in unserialize() with SplObjectStorage
|
||||
--FILE--
|
||||
<?php
|
||||
$inner = 'x:i:1;O:8:"stdClass":0:{};m:a:0:{}';
|
||||
$exploit = 'a:2:{i:0;C:16:"SplObjectStorage":'.strlen($inner).':{'.$inner.'}i:1;R:3;}';
|
||||
|
||||
$data = unserialize($exploit);
|
||||
|
||||
for($i = 0; $i < 5; $i++) {
|
||||
$v[$i] = 'hi'.$i;
|
||||
}
|
||||
|
||||
var_dump($data);
|
||||
?>
|
||||
===DONE===
|
||||
--EXPECTF--
|
||||
array(2) {
|
||||
[0]=>
|
||||
object(SplObjectStorage)#%d (1) {
|
||||
["storage":"SplObjectStorage":private]=>
|
||||
array(1) {
|
||||
["%s"]=>
|
||||
array(2) {
|
||||
["obj"]=>
|
||||
object(stdClass)#2 (0) {
|
||||
}
|
||||
["inf"]=>
|
||||
NULL
|
||||
}
|
||||
}
|
||||
}
|
||||
[1]=>
|
||||
int(1)
|
||||
}
|
||||
===DONE===
|
||||
@@ -0,0 +1,30 @@
|
||||
--TEST--
|
||||
SPL: Bug #70169 Use After Free Vulnerability in unserialize() with SplDoublyLinkedList
|
||||
--FILE--
|
||||
<?php
|
||||
$inner = 'i:1;';
|
||||
$exploit = 'a:2:{i:0;C:19:"SplDoublyLinkedList":'.strlen($inner).':{'.$inner.'}i:1;R:3;}';
|
||||
|
||||
$data = unserialize($exploit);
|
||||
|
||||
for($i = 0; $i < 5; $i++) {
|
||||
$v[$i] = 'hi'.$i;
|
||||
}
|
||||
|
||||
var_dump($data);
|
||||
?>
|
||||
===DONE===
|
||||
--EXPECTF--
|
||||
array(2) {
|
||||
[0]=>
|
||||
object(SplDoublyLinkedList)#%d (2) {
|
||||
["flags":"SplDoublyLinkedList":private]=>
|
||||
int(1)
|
||||
["dllist":"SplDoublyLinkedList":private]=>
|
||||
array(0) {
|
||||
}
|
||||
}
|
||||
[1]=>
|
||||
int(1)
|
||||
}
|
||||
===DONE===
|
||||
@@ -0,0 +1,50 @@
|
||||
--TEST--
|
||||
SPL: Bug #70365 use-after-free vulnerability in unserialize() with SplObjectStorage
|
||||
--FILE--
|
||||
<?php
|
||||
class obj {
|
||||
var $ryat;
|
||||
function __wakeup() {
|
||||
$this->ryat = 1;
|
||||
}
|
||||
}
|
||||
|
||||
$fakezval = ptr2str(1122334455);
|
||||
$fakezval .= ptr2str(0);
|
||||
$fakezval .= "\x00\x00\x00\x00";
|
||||
$fakezval .= "\x01";
|
||||
$fakezval .= "\x00";
|
||||
$fakezval .= "\x00\x00";
|
||||
|
||||
$inner = 'x:i:1;O:8:"stdClass":0:{},i:1;;m:a:0:{}';
|
||||
$exploit = 'a:5:{i:0;i:1;i:1;C:16:"SplObjectStorage":'.strlen($inner).':{'.$inner.'}i:2;O:3:"obj":1:{s:4:"ryat";R:3;}i:3;R:6;i:4;s:'.strlen($fakezval).':"'.$fakezval.'";}';
|
||||
|
||||
$data = unserialize($exploit);
|
||||
|
||||
var_dump($data);
|
||||
|
||||
function ptr2str($ptr)
|
||||
{
|
||||
$out = '';
|
||||
for ($i = 0; $i < 8; $i++) {
|
||||
$out .= chr($ptr & 0xff);
|
||||
$ptr >>= 8;
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
--EXPECTF--
|
||||
array(5) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
&int(1)
|
||||
[2]=>
|
||||
object(obj)#%d (1) {
|
||||
["ryat"]=>
|
||||
&int(1)
|
||||
}
|
||||
[3]=>
|
||||
int(1)
|
||||
[4]=>
|
||||
string(24) "%s"
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
--TEST--
|
||||
SPL: Bug #70366 use-after-free vulnerability in unserialize() with SplDoublyLinkedList
|
||||
--FILE--
|
||||
<?php
|
||||
class obj {
|
||||
var $ryat;
|
||||
function __wakeup() {
|
||||
$this->ryat = 1;
|
||||
}
|
||||
}
|
||||
|
||||
$fakezval = ptr2str(1122334455);
|
||||
$fakezval .= ptr2str(0);
|
||||
$fakezval .= "\x00\x00\x00\x00";
|
||||
$fakezval .= "\x01";
|
||||
$fakezval .= "\x00";
|
||||
$fakezval .= "\x00\x00";
|
||||
|
||||
$inner = 'i:1234;:i:1;';
|
||||
$exploit = 'a:5:{i:0;i:1;i:1;C:19:"SplDoublyLinkedList":'.strlen($inner).':{'.$inner.'}i:2;O:3:"obj":1:{s:4:"ryat";R:3;}i:3;a:1:{i:0;R:5;}i:4;s:'.strlen($fakezval).':"'.$fakezval.'";}';
|
||||
|
||||
$data = unserialize($exploit);
|
||||
|
||||
var_dump($data);
|
||||
|
||||
function ptr2str($ptr)
|
||||
{
|
||||
$out = '';
|
||||
for ($i = 0; $i < 8; $i++) {
|
||||
$out .= chr($ptr & 0xff);
|
||||
$ptr >>= 8;
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
?>
|
||||
--EXPECTF--
|
||||
array(5) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
&int(1)
|
||||
[2]=>
|
||||
object(obj)#%d (1) {
|
||||
["ryat"]=>
|
||||
&int(1)
|
||||
}
|
||||
[3]=>
|
||||
array(1) {
|
||||
[0]=>
|
||||
int(1)
|
||||
}
|
||||
[4]=>
|
||||
string(24) "%s"
|
||||
}
|
||||
+52570
-25129
File diff suppressed because it is too large.
Load diff
+1936
-836
File diff suppressed because it is too large.
Load diff
@@ -28,7 +28,7 @@ typedef struct sqlite3_api_routines sqlite3_api_routines;
|
||||
** WARNING: In order to maintain backwards compatibility, add new
|
||||
** interfaces to the end of this structure only. If you insert new
|
||||
** interfaces in the middle of this structure, then older different
|
||||
** versions of SQLite will not be able to load each others' shared
|
||||
** versions of SQLite will not be able to load each other's shared
|
||||
** libraries!
|
||||
*/
|
||||
struct sqlite3_api_routines {
|
||||
@@ -49,8 +49,10 @@ struct sqlite3_api_routines {
|
||||
int (*busy_timeout)(sqlite3*,int ms);
|
||||
int (*changes)(sqlite3*);
|
||||
int (*close)(sqlite3*);
|
||||
int (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*,int eTextRep,const char*));
|
||||
int (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*,int eTextRep,const void*));
|
||||
int (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*,
|
||||
int eTextRep,const char*));
|
||||
int (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*,
|
||||
int eTextRep,const void*));
|
||||
const void * (*column_blob)(sqlite3_stmt*,int iCol);
|
||||
int (*column_bytes)(sqlite3_stmt*,int iCol);
|
||||
int (*column_bytes16)(sqlite3_stmt*,int iCol);
|
||||
@@ -75,10 +77,18 @@ struct sqlite3_api_routines {
|
||||
void * (*commit_hook)(sqlite3*,int(*)(void*),void*);
|
||||
int (*complete)(const char*sql);
|
||||
int (*complete16)(const void*sql);
|
||||
int (*create_collation)(sqlite3*,const char*,int,void*,int(*)(void*,int,const void*,int,const void*));
|
||||
int (*create_collation16)(sqlite3*,const void*,int,void*,int(*)(void*,int,const void*,int,const void*));
|
||||
int (*create_function)(sqlite3*,const char*,int,int,void*,void (*xFunc)(sqlite3_context*,int,sqlite3_value**),void (*xStep)(sqlite3_context*,int,sqlite3_value**),void (*xFinal)(sqlite3_context*));
|
||||
int (*create_function16)(sqlite3*,const void*,int,int,void*,void (*xFunc)(sqlite3_context*,int,sqlite3_value**),void (*xStep)(sqlite3_context*,int,sqlite3_value**),void (*xFinal)(sqlite3_context*));
|
||||
int (*create_collation)(sqlite3*,const char*,int,void*,
|
||||
int(*)(void*,int,const void*,int,const void*));
|
||||
int (*create_collation16)(sqlite3*,const void*,int,void*,
|
||||
int(*)(void*,int,const void*,int,const void*));
|
||||
int (*create_function)(sqlite3*,const char*,int,int,void*,
|
||||
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
|
||||
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
|
||||
void (*xFinal)(sqlite3_context*));
|
||||
int (*create_function16)(sqlite3*,const void*,int,int,void*,
|
||||
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
|
||||
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
|
||||
void (*xFinal)(sqlite3_context*));
|
||||
int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*);
|
||||
int (*data_count)(sqlite3_stmt*pStmt);
|
||||
sqlite3 * (*db_handle)(sqlite3_stmt*);
|
||||
@@ -123,16 +133,19 @@ struct sqlite3_api_routines {
|
||||
void (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*));
|
||||
void (*result_value)(sqlite3_context*,sqlite3_value*);
|
||||
void * (*rollback_hook)(sqlite3*,void(*)(void*),void*);
|
||||
int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,const char*,const char*),void*);
|
||||
int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,
|
||||
const char*,const char*),void*);
|
||||
void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*));
|
||||
char * (*snprintf)(int,char*,const char*,...);
|
||||
int (*step)(sqlite3_stmt*);
|
||||
int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,char const**,char const**,int*,int*,int*);
|
||||
int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,
|
||||
char const**,char const**,int*,int*,int*);
|
||||
void (*thread_cleanup)(void);
|
||||
int (*total_changes)(sqlite3*);
|
||||
void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*);
|
||||
int (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*);
|
||||
void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*,sqlite_int64),void*);
|
||||
void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*,
|
||||
sqlite_int64),void*);
|
||||
void * (*user_data)(sqlite3_context*);
|
||||
const void * (*value_blob)(sqlite3_value*);
|
||||
int (*value_bytes)(sqlite3_value*);
|
||||
@@ -154,15 +167,19 @@ struct sqlite3_api_routines {
|
||||
int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
|
||||
int (*clear_bindings)(sqlite3_stmt*);
|
||||
/* Added by 3.4.1 */
|
||||
int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*,void (*xDestroy)(void *));
|
||||
int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*,
|
||||
void (*xDestroy)(void *));
|
||||
/* Added by 3.5.0 */
|
||||
int (*bind_zeroblob)(sqlite3_stmt*,int,int);
|
||||
int (*blob_bytes)(sqlite3_blob*);
|
||||
int (*blob_close)(sqlite3_blob*);
|
||||
int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64,int,sqlite3_blob**);
|
||||
int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64,
|
||||
int,sqlite3_blob**);
|
||||
int (*blob_read)(sqlite3_blob*,void*,int,int);
|
||||
int (*blob_write)(sqlite3_blob*,const void*,int,int);
|
||||
int (*create_collation_v2)(sqlite3*,const char*,int,void*,int(*)(void*,int,const void*,int,const void*),void(*)(void*));
|
||||
int (*create_collation_v2)(sqlite3*,const char*,int,void*,
|
||||
int(*)(void*,int,const void*,int,const void*),
|
||||
void(*)(void*));
|
||||
int (*file_control)(sqlite3*,const char*,int,void*);
|
||||
sqlite3_int64 (*memory_highwater)(int);
|
||||
sqlite3_int64 (*memory_used)(void);
|
||||
@@ -198,7 +215,11 @@ struct sqlite3_api_routines {
|
||||
int (*backup_step)(sqlite3_backup*,int);
|
||||
const char *(*compileoption_get)(int);
|
||||
int (*compileoption_used)(const char*);
|
||||
int (*create_function_v2)(sqlite3*,const char*,int,int,void*,void (*xFunc)(sqlite3_context*,int,sqlite3_value**),void (*xStep)(sqlite3_context*,int,sqlite3_value**),void (*xFinal)(sqlite3_context*),void(*xDestroy)(void*));
|
||||
int (*create_function_v2)(sqlite3*,const char*,int,int,void*,
|
||||
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
|
||||
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
|
||||
void (*xFinal)(sqlite3_context*),
|
||||
void(*xDestroy)(void*));
|
||||
int (*db_config)(sqlite3*,int,...);
|
||||
sqlite3_mutex *(*db_mutex)(sqlite3*);
|
||||
int (*db_status)(sqlite3*,int,int*,int*,int);
|
||||
@@ -212,11 +233,45 @@ struct sqlite3_api_routines {
|
||||
int (*wal_autocheckpoint)(sqlite3*,int);
|
||||
int (*wal_checkpoint)(sqlite3*,const char*);
|
||||
void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*);
|
||||
int (*blob_reopen)(sqlite3_blob*,sqlite3_int64);
|
||||
int (*vtab_config)(sqlite3*,int op,...);
|
||||
int (*vtab_on_conflict)(sqlite3*);
|
||||
/* Version 3.7.16 and later */
|
||||
int (*close_v2)(sqlite3*);
|
||||
const char *(*db_filename)(sqlite3*,const char*);
|
||||
int (*db_readonly)(sqlite3*,const char*);
|
||||
int (*db_release_memory)(sqlite3*);
|
||||
const char *(*errstr)(int);
|
||||
int (*stmt_busy)(sqlite3_stmt*);
|
||||
int (*stmt_readonly)(sqlite3_stmt*);
|
||||
int (*stricmp)(const char*,const char*);
|
||||
int (*uri_boolean)(const char*,const char*,int);
|
||||
sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64);
|
||||
const char *(*uri_parameter)(const char*,const char*);
|
||||
char *(*vsnprintf)(int,char*,const char*,va_list);
|
||||
int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*);
|
||||
/* Version 3.8.7 and later */
|
||||
int (*auto_extension)(void(*)(void));
|
||||
int (*bind_blob64)(sqlite3_stmt*,int,const void*,sqlite3_uint64,
|
||||
void(*)(void*));
|
||||
int (*bind_text64)(sqlite3_stmt*,int,const char*,sqlite3_uint64,
|
||||
void(*)(void*),unsigned char);
|
||||
int (*cancel_auto_extension)(void(*)(void));
|
||||
int (*load_extension)(sqlite3*,const char*,const char*,char**);
|
||||
void *(*malloc64)(sqlite3_uint64);
|
||||
sqlite3_uint64 (*msize)(void*);
|
||||
void *(*realloc64)(void*,sqlite3_uint64);
|
||||
void (*reset_auto_extension)(void);
|
||||
void (*result_blob64)(sqlite3_context*,const void*,sqlite3_uint64,
|
||||
void(*)(void*));
|
||||
void (*result_text64)(sqlite3_context*,const char*,sqlite3_uint64,
|
||||
void(*)(void*), unsigned char);
|
||||
int (*strglob)(const char*,const char*);
|
||||
};
|
||||
|
||||
/*
|
||||
** The following macros redefine the API routines so that they are
|
||||
** redirected throught the global sqlite3_api structure.
|
||||
** redirected through the global sqlite3_api structure.
|
||||
**
|
||||
** This header file is also used by the loadext.c source file
|
||||
** (part of the main SQLite library - not an extension) so that
|
||||
@@ -412,9 +467,51 @@ struct sqlite3_api_routines {
|
||||
#define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint
|
||||
#define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint
|
||||
#define sqlite3_wal_hook sqlite3_api->wal_hook
|
||||
#define sqlite3_blob_reopen sqlite3_api->blob_reopen
|
||||
#define sqlite3_vtab_config sqlite3_api->vtab_config
|
||||
#define sqlite3_vtab_on_conflict sqlite3_api->vtab_on_conflict
|
||||
/* Version 3.7.16 and later */
|
||||
#define sqlite3_close_v2 sqlite3_api->close_v2
|
||||
#define sqlite3_db_filename sqlite3_api->db_filename
|
||||
#define sqlite3_db_readonly sqlite3_api->db_readonly
|
||||
#define sqlite3_db_release_memory sqlite3_api->db_release_memory
|
||||
#define sqlite3_errstr sqlite3_api->errstr
|
||||
#define sqlite3_stmt_busy sqlite3_api->stmt_busy
|
||||
#define sqlite3_stmt_readonly sqlite3_api->stmt_readonly
|
||||
#define sqlite3_stricmp sqlite3_api->stricmp
|
||||
#define sqlite3_uri_boolean sqlite3_api->uri_boolean
|
||||
#define sqlite3_uri_int64 sqlite3_api->uri_int64
|
||||
#define sqlite3_uri_parameter sqlite3_api->uri_parameter
|
||||
#define sqlite3_uri_vsnprintf sqlite3_api->vsnprintf
|
||||
#define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2
|
||||
/* Version 3.8.7 and later */
|
||||
#define sqlite3_auto_extension sqlite3_api->auto_extension
|
||||
#define sqlite3_bind_blob64 sqlite3_api->bind_blob64
|
||||
#define sqlite3_bind_text64 sqlite3_api->bind_text64
|
||||
#define sqlite3_cancel_auto_extension sqlite3_api->cancel_auto_extension
|
||||
#define sqlite3_load_extension sqlite3_api->load_extension
|
||||
#define sqlite3_malloc64 sqlite3_api->malloc64
|
||||
#define sqlite3_msize sqlite3_api->msize
|
||||
#define sqlite3_realloc64 sqlite3_api->realloc64
|
||||
#define sqlite3_reset_auto_extension sqlite3_api->reset_auto_extension
|
||||
#define sqlite3_result_blob64 sqlite3_api->result_blob64
|
||||
#define sqlite3_result_text64 sqlite3_api->result_text64
|
||||
#define sqlite3_strglob sqlite3_api->strglob
|
||||
#endif /* SQLITE_CORE */
|
||||
|
||||
#define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api = 0;
|
||||
#define SQLITE_EXTENSION_INIT2(v) sqlite3_api = v;
|
||||
#ifndef SQLITE_CORE
|
||||
/* This case when the file really is being compiled as a loadable
|
||||
** extension */
|
||||
# define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0;
|
||||
# define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v;
|
||||
# define SQLITE_EXTENSION_INIT3 \
|
||||
extern const sqlite3_api_routines *sqlite3_api;
|
||||
#else
|
||||
/* This case when the file is being statically linked into the
|
||||
** application */
|
||||
# define SQLITE_EXTENSION_INIT1 /*no-op*/
|
||||
# define SQLITE_EXTENSION_INIT2(v) (void)v; /* unused parameter */
|
||||
# define SQLITE_EXTENSION_INIT3 /*no-op*/
|
||||
#endif
|
||||
|
||||
#endif /* _SQLITE3EXT_H_ */
|
||||
@@ -2113,7 +2113,7 @@ ZEND_BEGIN_ARG_INFO(arginfo_stream_set_write_buffer, 0)
|
||||
ZEND_ARG_INFO(0, fp)
|
||||
ZEND_ARG_INFO(0, buffer)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_stream_set_chunk_size, 0)
|
||||
ZEND_ARG_INFO(0, fp)
|
||||
ZEND_ARG_INFO(0, chunk_size)
|
||||
@@ -2308,7 +2308,7 @@ ZEND_END_ARG_INFO()
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_lcfirst, 0)
|
||||
ZEND_ARG_INFO(0, str)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_ucwords, 0, 0, 1)
|
||||
ZEND_ARG_INFO(0, str)
|
||||
ZEND_ARG_INFO(0, delimiters)
|
||||
@@ -3452,7 +3452,7 @@ static void basic_globals_ctor(php_basic_globals *basic_globals_p TSRMLS_DC) /*
|
||||
BG(user_tick_functions) = NULL;
|
||||
BG(user_filter_map) = NULL;
|
||||
BG(serialize_lock) = 0;
|
||||
|
||||
|
||||
memset(&BG(serialize), 0, sizeof(BG(serialize)));
|
||||
memset(&BG(unserialize), 0, sizeof(BG(unserialize)));
|
||||
|
||||
@@ -3980,8 +3980,8 @@ PHP_FUNCTION(getenv)
|
||||
int size;
|
||||
|
||||
SetLastError(0);
|
||||
/*If the given bugger is not large enough to hold the data, the return value is
|
||||
the buffer size, in characters, required to hold the string and its terminating
|
||||
/*If the given bugger is not large enough to hold the data, the return value is
|
||||
the buffer size, in characters, required to hold the string and its terminating
|
||||
null character. We use this return value to alloc the final buffer. */
|
||||
size = GetEnvironmentVariableA(str, &dummybuf, 0);
|
||||
if (GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
|
||||
@@ -4033,7 +4033,7 @@ PHP_FUNCTION(putenv)
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &setting, &setting_len) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if(setting_len == 0 || setting[0] == '=') {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid parameter syntax");
|
||||
RETURN_FALSE;
|
||||
@@ -4088,7 +4088,7 @@ PHP_FUNCTION(putenv)
|
||||
error_code = SetEnvironmentVariable(pe.key, value);
|
||||
# if _MSC_VER < 1500
|
||||
/* Yet another VC6 bug, unset may return env not found */
|
||||
if (error_code != 0 ||
|
||||
if (error_code != 0 ||
|
||||
(error_code == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND)) {
|
||||
# else
|
||||
if (error_code != 0) { /* success */
|
||||
@@ -4576,7 +4576,7 @@ PHP_FUNCTION(set_magic_quotes_runtime)
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &new_setting) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (new_setting) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_CORE_ERROR, "magic_quotes_runtime is not supported anymore");
|
||||
}
|
||||
@@ -4864,7 +4864,7 @@ PHP_FUNCTION(forward_static_call)
|
||||
instanceof_function(EG(called_scope), fci_cache.calling_scope TSRMLS_CC)) {
|
||||
fci_cache.called_scope = EG(called_scope);
|
||||
}
|
||||
|
||||
|
||||
if (zend_call_function(&fci, &fci_cache TSRMLS_CC) == SUCCESS && fci.retval_ptr_ptr && *fci.retval_ptr_ptr) {
|
||||
COPY_PZVAL_TO_ZVAL(*return_value, *fci.retval_ptr_ptr);
|
||||
}
|
||||
@@ -5437,7 +5437,7 @@ PHP_FUNCTION(set_include_path)
|
||||
int new_value_len;
|
||||
char *old_value;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &new_value, &new_value_len) == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &new_value, &new_value_len) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -5565,7 +5565,7 @@ PHP_FUNCTION(getservbyname)
|
||||
}
|
||||
|
||||
|
||||
/* empty string behaves like NULL on windows implementation of
|
||||
/* empty string behaves like NULL on windows implementation of
|
||||
getservbyname. Let be portable instead. */
|
||||
#ifdef PHP_WIN32
|
||||
if (proto_len == 0) {
|
||||
@@ -5993,7 +5993,7 @@ PHP_FUNCTION(parse_ini_string)
|
||||
/* }}} */
|
||||
|
||||
#if ZEND_DEBUG
|
||||
/* This function returns an array of ALL valid ini options with values and
|
||||
/* This function returns an array of ALL valid ini options with values and
|
||||
* is not the same as ini_get_all() which returns only registered ini options. Only useful for devs to debug php.ini scanner/parser! */
|
||||
PHP_FUNCTION(config_get_hash) /* {{{ */
|
||||
{
|
||||
|
||||
+31
-31
@@ -93,8 +93,8 @@ static zend_class_entry *dir_class_entry_ptr;
|
||||
dirp = (php_stream *) zend_fetch_resource(&id TSRMLS_CC, -1, "Directory", NULL, 1, php_file_le_stream()); \
|
||||
if (!dirp) \
|
||||
RETURN_FALSE; \
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* {{{ arginfo */
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_dir, 0, 0, 0)
|
||||
ZEND_ARG_INFO(0, dir_handle)
|
||||
@@ -118,7 +118,7 @@ static void php_set_default_dir(int id TSRMLS_DC)
|
||||
if (id != -1) {
|
||||
zend_list_addref(id);
|
||||
}
|
||||
|
||||
|
||||
DIRG(default_dir) = id;
|
||||
}
|
||||
|
||||
@@ -168,25 +168,25 @@ PHP_MINIT_FUNCTION(dir)
|
||||
|
||||
#ifdef GLOB_NOSORT
|
||||
REGISTER_LONG_CONSTANT("GLOB_NOSORT", GLOB_NOSORT, CONST_CS | CONST_PERSISTENT);
|
||||
#else
|
||||
#else
|
||||
# define GLOB_NOSORT 0
|
||||
#endif
|
||||
|
||||
#ifdef GLOB_NOCHECK
|
||||
REGISTER_LONG_CONSTANT("GLOB_NOCHECK", GLOB_NOCHECK, CONST_CS | CONST_PERSISTENT);
|
||||
#else
|
||||
#else
|
||||
# define GLOB_NOCHECK 0
|
||||
#endif
|
||||
|
||||
#ifdef GLOB_NOESCAPE
|
||||
REGISTER_LONG_CONSTANT("GLOB_NOESCAPE", GLOB_NOESCAPE, CONST_CS | CONST_PERSISTENT);
|
||||
#else
|
||||
#else
|
||||
# define GLOB_NOESCAPE 0
|
||||
#endif
|
||||
|
||||
#ifdef GLOB_ERR
|
||||
REGISTER_LONG_CONSTANT("GLOB_ERR", GLOB_ERR, CONST_CS | CONST_PERSISTENT);
|
||||
#else
|
||||
#else
|
||||
# define GLOB_ERR 0
|
||||
#endif
|
||||
|
||||
@@ -219,12 +219,12 @@ static void _php_do_opendir(INTERNAL_FUNCTION_PARAMETERS, int createobject)
|
||||
php_stream_context *context = NULL;
|
||||
php_stream *dirp;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r", &dirname, &dir_len, &zcontext) == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|r", &dirname, &dir_len, &zcontext) == FAILURE) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
context = php_stream_context_from_zval(zcontext, 0);
|
||||
|
||||
|
||||
dirp = php_stream_opendir(dirname, REPORT_ERRORS, context);
|
||||
|
||||
if (dirp == NULL) {
|
||||
@@ -232,7 +232,7 @@ static void _php_do_opendir(INTERNAL_FUNCTION_PARAMETERS, int createobject)
|
||||
}
|
||||
|
||||
dirp->flags |= PHP_STREAM_FLAG_NO_FCLOSE;
|
||||
|
||||
|
||||
php_set_default_dir(dirp->rsrc_id TSRMLS_CC);
|
||||
|
||||
if (createobject) {
|
||||
@@ -293,11 +293,11 @@ PHP_FUNCTION(chroot)
|
||||
{
|
||||
char *str;
|
||||
int ret, str_len;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) {
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &str, &str_len) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
|
||||
ret = chroot(str);
|
||||
if (ret != 0) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s (errno %d)", strerror(errno), errno);
|
||||
@@ -305,9 +305,9 @@ PHP_FUNCTION(chroot)
|
||||
}
|
||||
|
||||
php_clear_stat_cache(1, NULL, 0 TSRMLS_CC);
|
||||
|
||||
|
||||
ret = chdir("/");
|
||||
|
||||
|
||||
if (ret != 0) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s (errno %d)", strerror(errno), errno);
|
||||
RETURN_FALSE;
|
||||
@@ -324,7 +324,7 @@ PHP_FUNCTION(chdir)
|
||||
{
|
||||
char *str;
|
||||
int ret, str_len;
|
||||
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &str, &str_len) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
@@ -333,7 +333,7 @@ PHP_FUNCTION(chdir)
|
||||
RETURN_FALSE;
|
||||
}
|
||||
ret = VCWD_CHDIR(str);
|
||||
|
||||
|
||||
if (ret != 0) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s (errno %d)", strerror(errno), errno);
|
||||
RETURN_FALSE;
|
||||
@@ -358,7 +358,7 @@ PHP_FUNCTION(getcwd)
|
||||
{
|
||||
char path[MAXPATHLEN];
|
||||
char *ret=NULL;
|
||||
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -383,7 +383,7 @@ PHP_FUNCTION(rewinddir)
|
||||
{
|
||||
zval *id = NULL, **tmp, *myself;
|
||||
php_stream *dirp;
|
||||
|
||||
|
||||
FETCH_DIRP();
|
||||
|
||||
if (!(dirp->flags & PHP_STREAM_FLAG_IS_DIR)) {
|
||||
@@ -450,9 +450,9 @@ PHP_FUNCTION(glob)
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
#ifdef ZTS
|
||||
#ifdef ZTS
|
||||
if (!IS_ABSOLUTE_PATH(pattern, pattern_len)) {
|
||||
result = VCWD_GETCWD(cwd, MAXPATHLEN);
|
||||
result = VCWD_GETCWD(cwd, MAXPATHLEN);
|
||||
if (!result) {
|
||||
cwd[0] = '\0';
|
||||
}
|
||||
@@ -465,10 +465,10 @@ PHP_FUNCTION(glob)
|
||||
|
||||
snprintf(work_pattern, MAXPATHLEN, "%s%c%s", cwd, DEFAULT_SLASH, pattern);
|
||||
pattern = work_pattern;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
memset(&globbuf, 0, sizeof(glob_t));
|
||||
globbuf.gl_offs = 0;
|
||||
if (0 != (ret = glob(pattern, flags & GLOB_FLAGMASK, NULL, &globbuf))) {
|
||||
@@ -477,7 +477,7 @@ PHP_FUNCTION(glob)
|
||||
/* Some glob implementation simply return no data if no matches
|
||||
were found, others return the GLOB_NOMATCH error code.
|
||||
We don't want to treat GLOB_NOMATCH as an error condition
|
||||
so that PHP glob() behaves the same on both types of
|
||||
so that PHP glob() behaves the same on both types of
|
||||
implementations and so that 'foreach (glob() as ...'
|
||||
can be used for simple glob() calls without further error
|
||||
checking.
|
||||
@@ -517,11 +517,11 @@ no_results:
|
||||
}
|
||||
/* we need to do this everytime since GLOB_ONLYDIR does not guarantee that
|
||||
* all directories will be filtered. GNU libc documentation states the
|
||||
* following:
|
||||
* If the information about the type of the file is easily available
|
||||
* non-directories will be rejected but no extra work will be done to
|
||||
* determine the information for each file. I.e., the caller must still be
|
||||
* able to filter directories out.
|
||||
* following:
|
||||
* If the information about the type of the file is easily available
|
||||
* non-directories will be rejected but no extra work will be done to
|
||||
* determine the information for each file. I.e., the caller must still be
|
||||
* able to filter directories out.
|
||||
*/
|
||||
if (flags & GLOB_ONLYDIR) {
|
||||
struct stat s;
|
||||
@@ -545,7 +545,7 @@ no_results:
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* {{{ proto array scandir(string dir [, int sorting_order [, resource context]])
|
||||
List files & directories inside the specified path */
|
||||
@@ -583,7 +583,7 @@ PHP_FUNCTION(scandir)
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "(errno %d): %s", errno, strerror(errno));
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
|
||||
array_init(return_value);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
|
||||
+11
-1
@@ -281,9 +281,10 @@ PHPAPI char *php_escape_shell_cmd(char *str)
|
||||
break;
|
||||
#else
|
||||
/* % is Windows specific for enviromental variables, ^%PATH% will
|
||||
output PATH whil ^%PATH^% not. escapeshellcmd will escape all %.
|
||||
output PATH while ^%PATH^% will not. escapeshellcmd will escape all % and !.
|
||||
*/
|
||||
case '%':
|
||||
case '!':
|
||||
case '"':
|
||||
case '\'':
|
||||
#endif
|
||||
@@ -366,6 +367,7 @@ PHPAPI char *php_escape_shell_arg(char *str)
|
||||
#ifdef PHP_WIN32
|
||||
case '"':
|
||||
case '%':
|
||||
case '!':
|
||||
cmd[y++] = ' ';
|
||||
break;
|
||||
#else
|
||||
@@ -380,6 +382,14 @@ PHPAPI char *php_escape_shell_arg(char *str)
|
||||
}
|
||||
}
|
||||
#ifdef PHP_WIN32
|
||||
if (y > 0 && '\\' == cmd[y - 1]) {
|
||||
int k = 0, n = y - 1;
|
||||
for (; n >= 0 && '\\' == cmd[n]; n--, k++);
|
||||
if (k % 2) {
|
||||
cmd[y++] = '\\';
|
||||
}
|
||||
}
|
||||
|
||||
cmd[y++] = '"';
|
||||
#else
|
||||
cmd[y++] = '\'';
|
||||
|
||||
+5
-5
@@ -813,7 +813,7 @@ PHP_FUNCTION(tempnam)
|
||||
char *p;
|
||||
int fd;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ps", &dir, &dir_len, &prefix, &prefix_len) == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pp", &dir, &dir_len, &prefix, &prefix_len) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -825,7 +825,7 @@ PHP_FUNCTION(tempnam)
|
||||
if (p_len > 64) {
|
||||
p[63] = '\0';
|
||||
}
|
||||
|
||||
|
||||
RETVAL_FALSE;
|
||||
|
||||
if ((fd = php_open_temporary_fd_ex(dir, p, &opened_path, 1 TSRMLS_CC)) >= 0) {
|
||||
@@ -1340,7 +1340,7 @@ PHP_FUNCTION(rmdir)
|
||||
zval *zcontext = NULL;
|
||||
php_stream_context *context;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r", &dir, &dir_len, &zcontext) == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|r", &dir, &dir_len, &zcontext) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
@@ -1385,13 +1385,13 @@ PHP_FUNCTION(umask)
|
||||
{
|
||||
long arg1 = 0;
|
||||
int oldumask;
|
||||
|
||||
|
||||
oldumask = umask(077);
|
||||
|
||||
if (BG(umask) == -1) {
|
||||
BG(umask) = oldumask;
|
||||
}
|
||||
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &arg1) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
+46
-2
@@ -221,6 +221,44 @@ void php_mail_log_to_file(char *filename, char *message, size_t message_size TSR
|
||||
}
|
||||
|
||||
|
||||
static int php_mail_detect_multiple_crlf(char *hdr) {
|
||||
/* This function detects multiple/malformed multiple newlines. */
|
||||
size_t len;
|
||||
|
||||
if (!hdr || !strlen(hdr)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Should not have any newlines at the beginning. */
|
||||
/* RFC 2822 2.2. Header Fields */
|
||||
if (*hdr < 33 || *hdr > 126 || *hdr == ':') {
|
||||
return 1;
|
||||
}
|
||||
|
||||
while(*hdr) {
|
||||
if (*hdr == '\r') {
|
||||
if (*(hdr+1) == '\0' || *(hdr+1) == '\r' || (*(hdr+1) == '\n' && (*(hdr+2) == '\0' || *(hdr+2) == '\n' || *(hdr+2) == '\r'))) {
|
||||
/* Malformed or multiple newlines. */
|
||||
return 1;
|
||||
} else {
|
||||
hdr += 2;
|
||||
}
|
||||
} else if (*hdr == '\n') {
|
||||
if (*(hdr+1) == '\0' || *(hdr+1) == '\r' || *(hdr+1) == '\n') {
|
||||
/* Malformed or multiple newlines. */
|
||||
return 1;
|
||||
} else {
|
||||
hdr += 2;
|
||||
}
|
||||
} else {
|
||||
hdr++;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* {{{ php_mail
|
||||
*/
|
||||
PHPAPI int php_mail(char *to, char *subject, char *message, char *headers, char *extra_cmd TSRMLS_DC)
|
||||
@@ -266,6 +304,7 @@ PHPAPI int php_mail(char *to, char *subject, char *message, char *headers, char
|
||||
|
||||
efree(tmp);
|
||||
}
|
||||
|
||||
if (PG(mail_x_header)) {
|
||||
const char *tmp = zend_get_executed_filename(TSRMLS_C);
|
||||
char *f;
|
||||
@@ -273,7 +312,7 @@ PHPAPI int php_mail(char *to, char *subject, char *message, char *headers, char
|
||||
|
||||
php_basename(tmp, strlen(tmp), NULL, 0,&f, &f_len TSRMLS_CC);
|
||||
|
||||
if (headers != NULL) {
|
||||
if (headers != NULL && *headers) {
|
||||
spprintf(&hdr, 0, "X-PHP-Originating-Script: %ld:%s\n%s", php_getuid(TSRMLS_C), f, headers);
|
||||
} else {
|
||||
spprintf(&hdr, 0, "X-PHP-Originating-Script: %ld:%s", php_getuid(TSRMLS_C), f);
|
||||
@@ -281,6 +320,11 @@ PHPAPI int php_mail(char *to, char *subject, char *message, char *headers, char
|
||||
efree(f);
|
||||
}
|
||||
|
||||
if (hdr && php_mail_detect_multiple_crlf(hdr)) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Multiple or malformed newlines found in additional_header");
|
||||
MAIL_RET(0);
|
||||
}
|
||||
|
||||
if (!sendmail_path) {
|
||||
#if (defined PHP_WIN32 || defined NETWARE)
|
||||
/* handle old style win smtp sending */
|
||||
@@ -376,7 +420,7 @@ PHPAPI int php_mail(char *to, char *subject, char *message, char *headers, char
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not execute mail delivery program '%s'", sendmail_path);
|
||||
#if PHP_SIGCHILD
|
||||
if (sig_handler) {
|
||||
signal(SIGCHLD, sig_handler);
|
||||
signal(SIGCHLD, sig_handler);
|
||||
}
|
||||
#endif
|
||||
MAIL_RET(0);
|
||||
|
||||
Loaded 100 of 131 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user