pkgsrc-Changes archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
CVS commit: pkgsrc/lang/php56
Module Name: pkgsrc
Committed By: taca
Date: Tue Oct 27 15:30:49 UTC 2026
Modified Files:
pkgsrc/lang/php56: Makefile distinfo
pkgsrc/lang/php56/patches: patch-Zend_zend__multiply.h
Added Files:
pkgsrc/lang/php56/patches: patch-Zend_zend.c patch-Zend_zend__alloc.c
patch-Zend_zend__alloc.h patch-Zend_zend__execute__API.c
patch-Zend_zend__globals.h patch-Zend_zend__llist.c
patch-Zend_zend__vm__execute.h patch-Zend_zend__vm__execute.skl
patch-ext_session_session.c patch-ext_standard_basic__functions.h
patch-ext_standard_php__incomplete__class.h
patch-ext_standard_var.c patch-ext_standard_var__unserializer.c
patch-ext_standard_var__unserializer.re patch-main_SAPI.c
patch-main_main.c patch-main_php__variables.c patch-main_rfc1867.c
Log Message:
lang/php56: fix CVE-2026-109618 and CVE-2026-109619
Apply patch for CVE-2026-109618 and CVE-2026-109619.
Thanks to sborrill@ providing patch information.
Bump PKGREVISION.
To generate a diff of this commit:
cvs rdiff -u -r1.49 -r1.50 pkgsrc/lang/php56/Makefile
cvs rdiff -u -r1.67 -r1.68 pkgsrc/lang/php56/distinfo
cvs rdiff -u -r0 -r1.1 pkgsrc/lang/php56/patches/patch-Zend_zend.c \
pkgsrc/lang/php56/patches/patch-Zend_zend__alloc.c \
pkgsrc/lang/php56/patches/patch-Zend_zend__alloc.h \
pkgsrc/lang/php56/patches/patch-Zend_zend__execute__API.c \
pkgsrc/lang/php56/patches/patch-Zend_zend__globals.h \
pkgsrc/lang/php56/patches/patch-Zend_zend__llist.c \
pkgsrc/lang/php56/patches/patch-Zend_zend__vm__execute.h \
pkgsrc/lang/php56/patches/patch-Zend_zend__vm__execute.skl \
pkgsrc/lang/php56/patches/patch-ext_session_session.c \
pkgsrc/lang/php56/patches/patch-ext_standard_basic__functions.h \
pkgsrc/lang/php56/patches/patch-ext_standard_php__incomplete__class.h \
pkgsrc/lang/php56/patches/patch-ext_standard_var.c \
pkgsrc/lang/php56/patches/patch-ext_standard_var__unserializer.c \
pkgsrc/lang/php56/patches/patch-ext_standard_var__unserializer.re \
pkgsrc/lang/php56/patches/patch-main_SAPI.c \
pkgsrc/lang/php56/patches/patch-main_main.c \
pkgsrc/lang/php56/patches/patch-main_php__variables.c \
pkgsrc/lang/php56/patches/patch-main_rfc1867.c
cvs rdiff -u -r1.1 -r1.2 \
pkgsrc/lang/php56/patches/patch-Zend_zend__multiply.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: pkgsrc/lang/php56/Makefile
diff -u pkgsrc/lang/php56/Makefile:1.49 pkgsrc/lang/php56/Makefile:1.50
--- pkgsrc/lang/php56/Makefile:1.49 Sat Aug 29 02:43:37 2026
+++ pkgsrc/lang/php56/Makefile Tue Oct 27 15:30:48 2026
@@ -1,10 +1,10 @@
-# $NetBSD: Makefile,v 1.49 2026/08/29 02:43:37 mef Exp $
+# $NetBSD: Makefile,v 1.50 2026/10/27 15:30:48 taca Exp $
#
# We can't omit PKGNAME here to handle PKG_OPTIONS.
#
PKGNAME= ${PHP_PKG_PREFIX}-${PHP_VERSION}
-PKGREVISION= 6
+PKGREVISION= 7
CATEGORIES= lang
COMMENT= PHP Hypertext Preprocessor version 5.6
Index: pkgsrc/lang/php56/distinfo
diff -u pkgsrc/lang/php56/distinfo:1.67 pkgsrc/lang/php56/distinfo:1.68
--- pkgsrc/lang/php56/distinfo:1.67 Sat Aug 29 02:43:37 2026
+++ pkgsrc/lang/php56/distinfo Tue Oct 27 15:30:48 2026
@@ -1,4 +1,4 @@
-$NetBSD: distinfo,v 1.67 2026/08/29 02:43:37 mef Exp $
+$NetBSD: distinfo,v 1.68 2026/10/27 15:30:48 taca Exp $
BLAKE2s (PHP-5.6.31-OpenSSL-1.1.0-compatibility-20170801.patch) = 9eaf6505d80e90147fd0b993fb501620030eea24ccd69e42c49d8faf50d47775
SHA512 (PHP-5.6.31-OpenSSL-1.1.0-compatibility-20170801.patch) = bbe39ad27a5a82c705692c921b214c5630227ed9852f0432340f74533b5e618d9bea01bff75a4b7a1f1b72876b6d092d2db4533758d9a927f274cff7361f3eb4
@@ -8,7 +8,15 @@ SHA512 (php-5.6.40.tar.xz) = 997b5a952a6
Size (php-5.6.40.tar.xz) = 12472236 bytes
SHA1 (patch-Makefile.global) = cf4dec0e4adf4ceceffb498919c1b463db9c6e66
SHA1 (patch-TSRM_threads.m4) = 83c51ef32371598689f2610726a2902e503b1d55
-SHA1 (patch-Zend_zend__multiply.h) = b51442f44e5b5853162a1ac7e451359d292b8210
+SHA1 (patch-Zend_zend.c) = faed48a92db61da305ab30cadc98df01c1436fb2
+SHA1 (patch-Zend_zend__alloc.c) = a011b5bab60d1775a4fdaeff50df31fc2f9ba77c
+SHA1 (patch-Zend_zend__alloc.h) = a9ef44b5880ff72ecccbb3269b126e72105f10bf
+SHA1 (patch-Zend_zend__execute__API.c) = 068bf1d940915073062d2dfb1ae407d1a4872d8d
+SHA1 (patch-Zend_zend__globals.h) = 3b3a499420f42c2211a653c140c11078ac9c374d
+SHA1 (patch-Zend_zend__llist.c) = 988d9882d48a94b69e97570a4a9a4e79f04ff81c
+SHA1 (patch-Zend_zend__multiply.h) = a2d1286e16971a406a4cfa13575f004d1f3af794
+SHA1 (patch-Zend_zend__vm__execute.h) = 2364bdcde9e9dff85820b35e54bb1fe2e8226907
+SHA1 (patch-Zend_zend__vm__execute.skl) = 0615c7f0ed6e5f98f0782df41922d498794c4dc9
SHA1 (patch-acinclude.m4) = 46ee41b151927673b0d17fbd13a3159b2f7aab0a
SHA1 (patch-aclocal.m4) = f24f25d8da5d846902ba94ec59fe4838bd24dda1
SHA1 (patch-configure.in) = 67ed9f97785ba4bf3f6405d4af07fc32b972ba4e
@@ -37,12 +45,22 @@ SHA1 (patch-ext_pdo_config.m4) = 2cd85e7
SHA1 (patch-ext_phar_Makefile.frag) = b39927055edd6fd3a02fb1d954e8fc69089ef01c
SHA1 (patch-ext_phar_phar_phar.php) = 159f7934c3ca35e036739aa446f84fe2b7f72026
SHA1 (patch-ext_recode_recode.c) = a97a1815d6a41410f68c289debbb9396128a2159
+SHA1 (patch-ext_session_session.c) = 4a2bffc26711f8258632433ddda1d612459d9855
SHA1 (patch-ext_sqlite3_config0.m4) = 2435e1518a88c7d05eb93cf3c8e716fe4ea0748b
SHA1 (patch-ext_standard_basic__functions.c) = ca1de427a3d793c3a3e99581fbd2d1fcf99aeb30
+SHA1 (patch-ext_standard_basic__functions.h) = 04506f91783498421e0d1b32b8bcc9477e41a077
SHA1 (patch-ext_standard_php__dns.h) = 8e544eb637044e9428a0becb7402336f64a3a23d
+SHA1 (patch-ext_standard_php__incomplete__class.h) = 5123320a7e1d7ddac12b5e752b130277bf970fea
+SHA1 (patch-ext_standard_var.c) = 4618e6acf10de73226f5741d6246ae113a3489fb
+SHA1 (patch-ext_standard_var__unserializer.c) = 4d532463190fdaee4b39996be17ffd0b5c216b70
+SHA1 (patch-ext_standard_var__unserializer.re) = defcc69425eac0ac8ca7d47a699716a0e98bb254
SHA1 (patch-ext_tidy_tidy.c) = 8f075f17ac913f21e65f4b704574c0ae5ffdfc84
SHA1 (patch-ext_xml_compat.c) = fbea14c738728d33cdaf38405688ed6361f8894d
SHA1 (patch-ext_xsl_php__xsl.h) = a9877bff7bacc77926a4541a0ac171c00ad1a627
+SHA1 (patch-main_SAPI.c) = db0702693307616062379e767bb84994ad20dd03
+SHA1 (patch-main_main.c) = c90a96a8d66bf2191df097bde97693ae870d1d8d
+SHA1 (patch-main_php__variables.c) = 0b351a7e30716f3ca861c8a21ad9f1fb7083cfc6
+SHA1 (patch-main_rfc1867.c) = 72f92bd0ffd34247ea9e2f6eef806e0e7dbc218d
SHA1 (patch-makedist) = 091d5c0ba3e890ade475faa33446c8f97bcb7bc3
SHA1 (patch-php.ini-development) = e1a187070a9dfc28762d7476d9acc796a93c7fac
SHA1 (patch-php.ini-production) = f978e200175a161893669391f784f8072488ff24
Index: pkgsrc/lang/php56/patches/patch-Zend_zend__multiply.h
diff -u pkgsrc/lang/php56/patches/patch-Zend_zend__multiply.h:1.1 pkgsrc/lang/php56/patches/patch-Zend_zend__multiply.h:1.2
--- pkgsrc/lang/php56/patches/patch-Zend_zend__multiply.h:1.1 Sat Aug 29 02:43:37 2026
+++ pkgsrc/lang/php56/patches/patch-Zend_zend__multiply.h Tue Oct 27 15:30:49 2026
@@ -1,18 +1,17 @@
-$NetBSD: patch-Zend_zend__multiply.h,v 1.1 2026/08/29 02:43:37 mef Exp $
+$NetBSD: patch-Zend_zend__multiply.h,v 1.2 2026/10/27 15:30:49 taca Exp $
https://mail-index.netbsd.org/pkgsrc-users/2026/08/28/msg043351.html
Quick hack by importing from php85
---- Zend/zend_multiply.h.orig 2019-01-09 18:54:13.000000000 +0900
-+++ Zend/zend_multiply.h 2026-08-29 09:48:42.223797552 +0900
-@@ -56,14 +56,17 @@
- } while (0)
+--- Zend/zend_multiply.h.orig 2019-01-09 09:54:13.000000000 +0000
++++ Zend/zend_multiply.h
+@@ -57,13 +57,16 @@
#elif defined(__aarch64__) && defined(__GNUC__)
-+
+
+typedef int64_t zend_long;
+
-
++
#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
- long __tmpvar; \
+ zend_long __tmpvar; \
Added files:
Index: pkgsrc/lang/php56/patches/patch-Zend_zend.c
diff -u /dev/null pkgsrc/lang/php56/patches/patch-Zend_zend.c:1.1
--- /dev/null Tue Oct 27 15:30:49 2026
+++ pkgsrc/lang/php56/patches/patch-Zend_zend.c Tue Oct 27 15:30:48 2026
@@ -0,0 +1,24 @@
+$NetBSD: patch-Zend_zend.c,v 1.1 2026/10/27 15:30:48 taca Exp $
+
+https://raw.githubusercontent.com/Anton-Barinov/php2shell-patches/refs/heads/main/patches/php-5.6-enhanced-universal.patch
+
+--- Zend/zend.c.orig 2019-01-09 09:54:13.000000000 +0000
++++ Zend/zend.c
+@@ -577,6 +577,7 @@ static void executor_globals_ctor(zend_e
+ #endif
+ EG(saved_fpu_cw_ptr) = NULL;
+ EG(active) = 0;
++ EG(delayed_oom) = ZEND_OOM_STATE_NONE;
+ }
+ /* }}} */
+
+@@ -1339,6 +1340,9 @@ ZEND_API int zend_execute_scripts(int ty
+ if (EG(active_op_array)) {
+ EG(return_value_ptr_ptr) = retval ? retval : NULL;
+ zend_execute(EG(active_op_array) TSRMLS_CC);
++ if (ZEND_OOM_PENDING()) {
++ zend_handle_delayed_oom(TSRMLS_C);
++ }
+ zend_exception_restore(TSRMLS_C);
+ if (EG(exception)) {
+ if (EG(user_exception_handler)) {
Index: pkgsrc/lang/php56/patches/patch-Zend_zend__alloc.c
diff -u /dev/null pkgsrc/lang/php56/patches/patch-Zend_zend__alloc.c:1.1
--- /dev/null Tue Oct 27 15:30:49 2026
+++ pkgsrc/lang/php56/patches/patch-Zend_zend__alloc.c Tue Oct 27 15:30:48 2026
@@ -0,0 +1,455 @@
+$NetBSD: patch-Zend_zend__alloc.c,v 1.1 2026/10/27 15:30:48 taca Exp $
+
+https://raw.githubusercontent.com/Anton-Barinov/php2shell-patches/refs/heads/main/patches/php-5.6-enhanced-universal.patch
+
+--- Zend/zend_alloc.c.orig 2019-01-09 09:54:13.000000000 +0000
++++ Zend/zend_alloc.c
+@@ -426,12 +426,17 @@ struct _zend_mm_heap {
+ size_t real_size;
+ size_t real_peak;
+ size_t limit;
++ size_t hard_limit; /* see zend_mm_update_hard_limit() */
+ size_t size;
+ size_t peak;
+ size_t reserve_size;
+ void *reserve;
+ int overflow;
+ int internal;
++ /* Delayed OOM error, raised by zend_handle_delayed_oom() */
++ uint oom_lineno;
++ char oom_filename[1024];
++ char oom_message[1024];
+ #if ZEND_MM_CACHE
+ unsigned int cached;
+ zend_mm_free_block *cache[ZEND_MM_NUM_BUCKETS];
+@@ -1117,6 +1122,7 @@ ZEND_API zend_mm_heap *zend_mm_startup_e
+ heap->overflow = 0;
+ heap->real_peak = 0;
+ heap->limit = ZEND_MM_LONG_CONST(1)<<(ZEND_MM_NUM_BUCKETS-2);
++ heap->hard_limit = heap->limit;
+ heap->size = 0;
+ heap->peak = 0;
+ heap->internal = internal;
+@@ -1598,6 +1604,27 @@ static int zend_mm_check_heap(zend_mm_he
+ }
+ #endif
+
++/* The hard limit leaves room above memory_limit for the request to reach the
++ * next safe point: 200% of memory_limit, or memory_limit + 1G above 1G. */
++static void zend_mm_update_hard_limit(zend_mm_heap *heap)
++{
++ size_t headroom = MIN(heap->limit, (size_t) 1024 * 1024 * 1024);
++ size_t hard_limit = (heap->limit > (size_t) -1 - headroom) ? (size_t) -1 : heap->limit + headroom;
++
++ if (heap->real_size > heap->limit) {
++ /* memory_limit is changed while exceeded (e.g. reset by the fatal
++ * error handler): neither move the hard limit up again, nor below
++ * the current usage */
++ if (heap->hard_limit > hard_limit && heap->hard_limit >= heap->real_size) {
++ hard_limit = heap->hard_limit;
++ }
++ if (hard_limit < heap->real_size) {
++ hard_limit = (heap->real_size > (size_t) -1 - headroom) ? (size_t) -1 : heap->real_size + headroom;
++ }
++ }
++ heap->hard_limit = hard_limit;
++}
++
+ ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, int full_shutdown, int silent TSRMLS_DC)
+ {
+ zend_mm_storage *storage;
+@@ -1737,73 +1764,122 @@ ZEND_API void zend_mm_shutdown(zend_mm_h
+ heap->reserve = _zend_mm_alloc_int(heap, heap->reserve_size ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
+ }
+ heap->overflow = 0;
++ zend_mm_update_hard_limit(heap);
+ }
+ }
+
+-static void zend_mm_safe_error(zend_mm_heap *heap,
+- const char *format,
+- size_t limit,
+-#if ZEND_DEBUG
+- const char *filename,
+- uint lineno,
+-#endif
+- size_t size)
++static void zend_mm_error_location(const char **error_filename, uint *error_lineno)
+ {
+- if (heap->reserve) {
+- _zend_mm_free_int(heap, heap->reserve ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
+- heap->reserve = NULL;
++ TSRMLS_FETCH();
++
++ if (zend_is_compiling(TSRMLS_C)) {
++ *error_filename = zend_get_compiled_filename(TSRMLS_C);
++ *error_lineno = zend_get_compiled_lineno(TSRMLS_C);
++ } else if (EG(in_execution)) {
++ *error_filename = EG(active_op_array)?EG(active_op_array)->filename:NULL;
++ *error_lineno = EG(opline_ptr)?(*EG(opline_ptr))->lineno:0;
++ } else {
++ *error_filename = NULL;
++ *error_lineno = 0;
+ }
+- if (heap->overflow == 0) {
+- const char *error_filename;
+- uint error_lineno;
+- TSRMLS_FETCH();
+- if (zend_is_compiling(TSRMLS_C)) {
+- error_filename = zend_get_compiled_filename(TSRMLS_C);
+- error_lineno = zend_get_compiled_lineno(TSRMLS_C);
+- } else if (EG(in_execution)) {
+- error_filename = EG(active_op_array)?EG(active_op_array)->filename:NULL;
+- error_lineno = EG(opline_ptr)?(*EG(opline_ptr))->lineno:0;
+- } else {
+- error_filename = NULL;
+- error_lineno = 0;
+- }
+- if (!error_filename) {
+- error_filename = "Unknown";
+- }
+- heap->overflow = 1;
+- zend_try {
+- zend_error_noreturn(E_ERROR,
+- format,
+- limit,
+-#if ZEND_DEBUG
+- filename,
+- lineno,
++ if (!*error_filename) {
++ *error_filename = "Unknown";
++ }
++}
++
++/* Real allocation failure (mmap/malloc): there is no safe way to continue */
++#if (defined (__GNUC__) && __GNUC__ > 2 ) && !defined(__INTEL_COMPILER) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX)
++static void zend_mm_out_of_memory(zend_mm_heap *heap, size_t size) __attribute__ ((noreturn));
+ #endif
+- size);
+- } zend_catch {
+- if (heap->overflow == 2) {
+- fprintf(stderr, "\nFatal error: ");
+- fprintf(stderr,
+- format,
+- limit,
+-#if ZEND_DEBUG
+- filename,
+- lineno,
++static void zend_mm_out_of_memory(zend_mm_heap *heap, size_t size)
++{
++ const char *error_filename;
++ uint error_lineno;
++
++ zend_mm_error_location(&error_filename, &error_lineno);
++ fprintf(stderr, "Out of memory (allocated %ld) (tried to allocate %lu bytes) in %s on line %d\n",
++ (long) heap->real_size, (unsigned long) size, error_filename, error_lineno);
++/* See http://support.microsoft.com/kb/190351 */
++#ifdef PHP_WIN32
++ fflush(stderr);
+ #endif
+- size);
+- fprintf(stderr, " in %s on line %d\n", error_filename, error_lineno);
+- }
++ exit(1);
++}
++
++#if (defined (__GNUC__) && __GNUC__ > 2 ) && !defined(__INTEL_COMPILER) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX)
++static void zend_mm_hard_limit_error(zend_mm_heap *heap, size_t size) __attribute__ ((noreturn));
++#endif
++static void zend_mm_hard_limit_error(zend_mm_heap *heap, size_t size)
++{
++ const char *error_filename;
++ uint error_lineno;
++
++ zend_mm_error_location(&error_filename, &error_lineno);
++ fprintf(stderr, "Hard memory limit of %lu bytes exhausted (tried to allocate %lu bytes) in %s on line %d\n",
++ (unsigned long) heap->hard_limit, (unsigned long) size, error_filename, error_lineno);
+ /* See http://support.microsoft.com/kb/190351 */
+ #ifdef PHP_WIN32
+- fflush(stderr);
++ fflush(stderr);
++#endif
++ _exit(137);
++}
++
++/* Record a memory limit error, to be raised at the next safe point by
++ * zend_handle_delayed_oom(). Bailing out from here would leave whatever the
++ * caller was in the middle of initializing reachable by the shutdown
++ * sequence (CVE-2026-109618). */
++static void zend_mm_delayed_error(zend_mm_heap *heap, const char *format, ...)
++{
++ const char *error_filename;
++ uint error_lineno;
++ va_list args;
++ TSRMLS_FETCH();
++
++ if (EG(delayed_oom) != ZEND_OOM_STATE_NONE) {
++ return;
++ }
++
++ zend_mm_error_location(&error_filename, &error_lineno);
++
++ va_start(args, format);
++ vsnprintf(heap->oom_message, sizeof(heap->oom_message), format, args);
++ va_end(args);
++ snprintf(heap->oom_filename, sizeof(heap->oom_filename), "%s", error_filename);
++ heap->oom_lineno = error_lineno;
++
++ EG(delayed_oom) = ZEND_OOM_STATE_PENDING;
++}
++
++/* Called when an allocation of add_size bytes makes the heap grow beyond the
++ * soft limit (memory_limit). Does not return when the hard limit would be
++ * exceeded. */
++static void zend_mm_limit_exceeded(zend_mm_heap *heap, size_t add_size
++#if ZEND_DEBUG
++ , const char *filename, uint lineno
++#endif
++ , size_t size)
++{
++ if (add_size > heap->hard_limit || heap->real_size > heap->hard_limit - add_size) {
++ zend_mm_hard_limit_error(heap, size);
++ }
++ if (heap->overflow == 0) {
++#if ZEND_DEBUG
++ zend_mm_delayed_error(heap, "Allowed memory size of %ld bytes exhausted at %s:%d (tried to allocate %lu bytes)", (long) heap->limit, filename, lineno, (unsigned long) size);
++#else
++ zend_mm_delayed_error(heap, "Allowed memory size of %ld bytes exhausted (tried to allocate %lu bytes)", (long) heap->limit, (unsigned long) size);
+ #endif
+- } zend_end_try();
+- } else {
+- heap->overflow = 2;
+ }
+- zend_bailout();
+ }
+
++#if ZEND_DEBUG
++# define ZEND_MM_LIMIT_EXCEEDED(heap, add_size, size) \
++ zend_mm_limit_exceeded(heap, add_size, __zend_filename, __zend_lineno, size)
++#else
++# define ZEND_MM_LIMIT_EXCEEDED(heap, add_size, size) \
++ zend_mm_limit_exceeded(heap, add_size, size)
++#endif
++
++
+ static zend_mm_free_block *zend_mm_search_large_block(zend_mm_heap *heap, size_t true_size)
+ {
+ zend_mm_free_block *best_fit;
+@@ -1965,18 +2041,14 @@ static void *_zend_mm_alloc_int(zend_mm_
+ segment_size = heap->block_size;
+ }
+
+- if (segment_size < true_size ||
+- heap->real_size + segment_size > heap->limit) {
+- /* Memory limit overflow */
+-#if ZEND_MM_CACHE
+- zend_mm_free_cache(heap);
+-#endif
++ if (segment_size < true_size) {
++ /* Integer overflow */
+ HANDLE_UNBLOCK_INTERRUPTIONS();
+-#if ZEND_DEBUG
+- zend_mm_safe_error(heap, "Allowed memory size of %ld bytes exhausted at %s:%d (tried to allocate %lu bytes)", heap->limit, __zend_filename, __zend_lineno, size);
+-#else
+- zend_mm_safe_error(heap, "Allowed memory size of %ld bytes exhausted (tried to allocate %lu bytes)", heap->limit, size);
+-#endif
++ zend_mm_out_of_memory(heap, size);
++ }
++ if (heap->real_size + segment_size > heap->limit) {
++ /* Memory limit overflow: report it later, see zend_mm_delayed_error() */
++ ZEND_MM_LIMIT_EXCEEDED(heap, segment_size, size);
+ }
+
+ segment = (zend_mm_segment *) ZEND_MM_STORAGE_ALLOC(segment_size);
+@@ -1988,11 +2060,7 @@ static void *_zend_mm_alloc_int(zend_mm_
+ #endif
+ out_of_memory:
+ HANDLE_UNBLOCK_INTERRUPTIONS();
+-#if ZEND_DEBUG
+- zend_mm_safe_error(heap, "Out of memory (allocated %ld) at %s:%d (tried to allocate %lu bytes)", heap->real_size, __zend_filename, __zend_lineno, size);
+-#else
+- zend_mm_safe_error(heap, "Out of memory (allocated %ld) (tried to allocate %lu bytes)", heap->real_size, size);
+-#endif
++ zend_mm_out_of_memory(heap, size);
+ return NULL;
+ }
+
+@@ -2276,21 +2344,15 @@ realloc_segment:
+ }
+
+ segment_copy = (zend_mm_segment *) ((char *)mm_block - ZEND_MM_ALIGNED_SEGMENT_SIZE);
+- if (segment_size < true_size ||
+- heap->real_size + segment_size - segment_copy->size > heap->limit) {
+- if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
+- zend_mm_add_to_free_list(heap, (zend_mm_free_block *) next_block);
+- }
+-#if ZEND_MM_CACHE
+- zend_mm_free_cache(heap);
+-#endif
++ if (segment_size < true_size) {
++ /* Integer overflow */
+ HANDLE_UNBLOCK_INTERRUPTIONS();
+-#if ZEND_DEBUG
+- zend_mm_safe_error(heap, "Allowed memory size of %ld bytes exhausted at %s:%d (tried to allocate %ld bytes)", heap->limit, __zend_filename, __zend_lineno, size);
+-#else
+- zend_mm_safe_error(heap, "Allowed memory size of %ld bytes exhausted (tried to allocate %ld bytes)", heap->limit, size);
+-#endif
+- return NULL;
++ zend_mm_out_of_memory(heap, size);
++ }
++ if (segment_size > segment_copy->size &&
++ heap->real_size + (segment_size - segment_copy->size) > heap->limit) {
++ /* Memory limit overflow: report it later, see zend_mm_delayed_error() */
++ ZEND_MM_LIMIT_EXCEEDED(heap, segment_size - segment_copy->size, size);
+ }
+
+ segment = ZEND_MM_STORAGE_REALLOC(segment_copy, segment_size);
+@@ -2300,11 +2362,7 @@ realloc_segment:
+ #endif
+ out_of_memory:
+ HANDLE_UNBLOCK_INTERRUPTIONS();
+-#if ZEND_DEBUG
+- zend_mm_safe_error(heap, "Out of memory (allocated %ld) at %s:%d (tried to allocate %ld bytes)", heap->real_size, __zend_filename, __zend_lineno, size);
+-#else
+- zend_mm_safe_error(heap, "Out of memory (allocated %ld) (tried to allocate %ld bytes)", heap->real_size, size);
+-#endif
++ zend_mm_out_of_memory(heap, size);
+ return NULL;
+ }
+ heap->real_size += segment_size - segment->size;
+@@ -2458,6 +2516,20 @@ ZEND_API size_t _zend_mem_block_size(voi
+ return _zend_mm_block_size(AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+ }
+
++/* Not reporting this as a fatal error: bailing out from an allocation leaves
++ * the caller's state inconsistent (CVE-2026-109618) */
++#if (defined (__GNUC__) && __GNUC__ > 2 ) && !defined(__INTEL_COMPILER) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX)
++static void zend_mm_safe_address_overflow(size_t nmemb, size_t size, size_t offset) __attribute__ ((noreturn));
++#endif
++static void zend_mm_safe_address_overflow(size_t nmemb, size_t size, size_t offset)
++{
++ char buf[256];
++
++ snprintf(buf, sizeof(buf), "Possible integer overflow in memory allocation (%lu * %lu + %lu)",
++ (unsigned long) nmemb, (unsigned long) size, (unsigned long) offset);
++ zend_mm_panic(buf);
++}
++
+ #if defined(__GNUC__) && (defined(__native_client__) || defined(i386))
+
+ static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
+@@ -2472,7 +2544,7 @@ static inline size_t safe_address(size_t
+ "rm"(offset));
+
+ if (UNEXPECTED(overflow)) {
+- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
++ zend_mm_safe_address_overflow(nmemb, size, offset);
+ return 0;
+ }
+ return res;
+@@ -2501,7 +2573,7 @@ static inline size_t safe_address(size_t
+
+ #undef LP_SUFF
+ if (UNEXPECTED(overflow)) {
+- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
++ zend_mm_safe_address_overflow(nmemb, size, offset);
+ return 0;
+ }
+ return res;
+@@ -2522,7 +2594,7 @@ static inline size_t safe_address(size_t
+ "1"(0));
+
+ if (UNEXPECTED(overflow)) {
+- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
++ zend_mm_safe_address_overflow(nmemb, size, offset);
+ return 0;
+ }
+ return res;
+@@ -2542,7 +2614,7 @@ static inline size_t safe_address(size_t
+ "r"(offset));
+
+ if (UNEXPECTED(overflow)) {
+- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
++ zend_mm_safe_address_overflow(nmemb, size, offset);
+ return 0;
+ }
+ return res;
+@@ -2555,7 +2627,7 @@ static inline size_t safe_address(size_t
+ zend_ulong64 res = (zend_ulong64)nmemb * (zend_ulong64)size + (zend_ulong64)offset;
+
+ if (UNEXPECTED(res > (zend_ulong64)0xFFFFFFFFL)) {
+- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
++ zend_mm_safe_address_overflow(nmemb, size, offset);
+ return 0;
+ }
+ return (size_t) res;
+@@ -2570,7 +2642,7 @@ static inline size_t safe_address(size_t
+ double _delta = (double)res - _d;
+
+ if (UNEXPECTED((_d + _delta ) != _d)) {
+- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
++ zend_mm_safe_address_overflow(nmemb, size, offset);
+ return 0;
+ }
+ return res;
+@@ -2582,7 +2654,10 @@ ZEND_API void *_safe_emalloc_string(size
+ {
+ size_t str_size = safe_address(nmemb, size, offset);
+ if (UNEXPECTED(str_size > INT_MAX)) {
+- zend_error_noreturn(E_ERROR, "String allocation overflow, max size is %d", INT_MAX);
++ char buf[64];
++
++ snprintf(buf, sizeof(buf), "String allocation overflow, max size is %d", INT_MAX);
++ zend_mm_panic(buf);
+ }
+ return emalloc_rel(str_size);
+ }
+@@ -2691,11 +2766,48 @@ ZEND_API char *zend_strndup(const char *
+ }
+
+
++static void zend_mm_error_cb(int type, const char *error_filename, uint error_lineno, const char *format, ...)
++{
++ va_list args;
++
++ va_start(args, format);
++ zend_error_cb(type, error_filename, error_lineno, format, args);
++ va_end(args);
++}
++
++ZEND_API void zend_handle_delayed_oom(TSRMLS_D)
++{
++ zend_mm_heap *heap = AG(mm_heap);
++
++ if (EG(delayed_oom) != ZEND_OOM_STATE_PENDING) {
++ return;
++ }
++ EG(delayed_oom) = ZEND_OOM_STATE_HANDLING;
++
++ /* Let error reporting allocate beyond the soft limit */
++ heap->overflow = 1;
++
++ /* An exception may be in flight. Reporting it may run user code
++ * (__toString()), which must not happen now. */
++ EG(exception) = NULL;
++
++ zend_try {
++ zend_mm_error_cb(E_ERROR, heap->oom_filename, heap->oom_lineno, "%s", heap->oom_message);
++ } zend_catch {
++ } zend_end_try();
++
++ heap->overflow = 0;
++ EG(delayed_oom) = ZEND_OOM_STATE_HANDLED;
++
++ zend_bailout();
++}
++
+ ZEND_API int zend_set_memory_limit(size_t memory_limit)
+ {
+ TSRMLS_FETCH();
+
+ AG(mm_heap)->limit = (memory_limit >= AG(mm_heap)->block_size) ? memory_limit : AG(mm_heap)->block_size;
++ zend_mm_update_hard_limit(AG(mm_heap));
+
+ return SUCCESS;
+ }
Index: pkgsrc/lang/php56/patches/patch-Zend_zend__alloc.h
diff -u /dev/null pkgsrc/lang/php56/patches/patch-Zend_zend__alloc.h:1.1
--- /dev/null Tue Oct 27 15:30:49 2026
+++ pkgsrc/lang/php56/patches/patch-Zend_zend__alloc.h Tue Oct 27 15:30:48 2026
@@ -0,0 +1,40 @@
+$NetBSD: patch-Zend_zend__alloc.h,v 1.1 2026/10/27 15:30:48 taca Exp $
+
+https://raw.githubusercontent.com/Anton-Barinov/php2shell-patches/refs/heads/main/patches/php-5.6-enhanced-universal.patch
+
+--- Zend/zend_alloc.h.orig 2019-01-09 09:54:13.000000000 +0000
++++ Zend/zend_alloc.h
+@@ -50,6 +50,25 @@ typedef struct _zend_leak_info {
+ uint orig_lineno;
+ } zend_leak_info;
+
++/* Delayed out of memory handling (CVE-2026-109618).
++ *
++ * Exceeding memory_limit no longer bails out (longjmp) from inside the
++ * allocator, where the caller may have left request memory in an
++ * inconsistent state. Instead the allocation succeeds, the error is recorded
++ * and raised as a fatal error at the next safe point (between two opcodes, or
++ * once request startup has finished parsing the request). Memory usage beyond
++ * a hard limit (twice memory_limit, or memory_limit + 1G for limits above 1G)
++ * terminates the process immediately with _exit(). */
++typedef enum _zend_oom_state {
++ ZEND_OOM_STATE_NONE = 0,
++ ZEND_OOM_STATE_PENDING,
++ ZEND_OOM_STATE_HANDLING,
++ ZEND_OOM_STATE_HANDLED
++} zend_oom_state;
++
++#define ZEND_HAS_OOM() (UNEXPECTED(EG(delayed_oom) != ZEND_OOM_STATE_NONE))
++#define ZEND_OOM_PENDING() (UNEXPECTED(EG(delayed_oom) == ZEND_OOM_STATE_PENDING))
++
+ BEGIN_EXTERN_C()
+
+ ZEND_API char *zend_strndup(const char *s, unsigned int length) ZEND_ATTRIBUTE_MALLOC;
+@@ -142,6 +161,7 @@ inline static void * __zend_realloc(void
+ #define safe_estrndup(ptr, len) ((ptr)?(estrndup((ptr), (len))):STR_EMPTY_ALLOC())
+
+ ZEND_API int zend_set_memory_limit(size_t memory_limit);
++ZEND_API void zend_handle_delayed_oom(TSRMLS_D);
+
+ ZEND_API void start_memory_manager(TSRMLS_D);
+ ZEND_API void shutdown_memory_manager(int silent, int full_shutdown TSRMLS_DC);
Index: pkgsrc/lang/php56/patches/patch-Zend_zend__execute__API.c
diff -u /dev/null pkgsrc/lang/php56/patches/patch-Zend_zend__execute__API.c:1.1
--- /dev/null Tue Oct 27 15:30:49 2026
+++ pkgsrc/lang/php56/patches/patch-Zend_zend__execute__API.c Tue Oct 27 15:30:48 2026
@@ -0,0 +1,41 @@
+$NetBSD: patch-Zend_zend__execute__API.c,v 1.1 2026/10/27 15:30:48 taca Exp $
+
+https://raw.githubusercontent.com/Anton-Barinov/php2shell-patches/refs/heads/main/patches/php-5.6-enhanced-universal.patch
+
+--- Zend/zend_execute_API.c.orig 2019-01-09 09:54:13.000000000 +0000
++++ Zend/zend_execute_API.c
+@@ -330,6 +330,23 @@ void shutdown_executor(TSRMLS_D) /* {{{
+
+ zend_shutdown_fpu(TSRMLS_C);
+
++ /* A bailout may have skipped the resets above. zend_error() may use these
++ * before the next init_executor(), e.g. for INI warnings or upload
++ * progress during request startup (CVE-2026-109619). */
++ EG(user_error_handler) = NULL;
++ EG(user_exception_handler) = NULL;
++ EG(error_handling) = EH_NORMAL;
++ EG(exception_class) = NULL;
++ EG(exception) = NULL;
++ EG(prev_exception) = NULL;
++ EG(current_execute_data) = NULL;
++ EG(active_symbol_table) = NULL;
++ EG(active_op_array) = NULL;
++ EG(opline_ptr) = NULL;
++ EG(in_execution) = 0;
++ EG(in_autoload) = NULL;
++ EG(autoload_func) = NULL;
++
+ EG(active) = 0;
+ }
+ /* }}} */
+@@ -639,6 +656,10 @@ int zend_call_function(zend_fcall_info *
+ return FAILURE; /* executor is already inactive */
+ }
+
++ if (ZEND_OOM_PENDING()) {
++ zend_handle_delayed_oom(TSRMLS_C);
++ }
++
+ if (EG(exception)) {
+ return FAILURE; /* we would result in an instable executor otherwise */
+ }
Index: pkgsrc/lang/php56/patches/patch-Zend_zend__globals.h
diff -u /dev/null pkgsrc/lang/php56/patches/patch-Zend_zend__globals.h:1.1
--- /dev/null Tue Oct 27 15:30:49 2026
+++ pkgsrc/lang/php56/patches/patch-Zend_zend__globals.h Tue Oct 27 15:30:48 2026
@@ -0,0 +1,17 @@
+$NetBSD: patch-Zend_zend__globals.h,v 1.1 2026/10/27 15:30:48 taca Exp $
+
+https://raw.githubusercontent.com/Anton-Barinov/php2shell-patches/refs/heads/main/patches/php-5.6-enhanced-universal.patch
+
+--- Zend/zend_globals.h.orig 2019-01-09 09:54:13.000000000 +0000
++++ Zend/zend_globals.h
+@@ -265,6 +265,10 @@ struct _zend_executor_globals {
+ #endif
+
+ void *reserved[ZEND_MAX_RESERVED_RESOURCES];
++
++ /* zend_oom_state, see zend_alloc.h. Kept last so that the offsets of the
++ * fields above do not change. */
++ zend_uchar delayed_oom;
+ };
+
+ struct _zend_ini_scanner_globals {
Index: pkgsrc/lang/php56/patches/patch-Zend_zend__llist.c
diff -u /dev/null pkgsrc/lang/php56/patches/patch-Zend_zend__llist.c:1.1
--- /dev/null Tue Oct 27 15:30:49 2026
+++ pkgsrc/lang/php56/patches/patch-Zend_zend__llist.c Tue Oct 27 15:30:49 2026
@@ -0,0 +1,15 @@
+$NetBSD: patch-Zend_zend__llist.c,v 1.1 2026/10/27 15:30:49 taca Exp $
+
+https://raw.githubusercontent.com/Anton-Barinov/php2shell-patches/refs/heads/main/patches/php-5.6-enhanced-universal.patch
+
+--- Zend/zend_llist.c.orig 2019-01-09 09:54:13.000000000 +0000
++++ Zend/zend_llist.c
+@@ -115,6 +115,8 @@ ZEND_API void zend_llist_destroy(zend_ll
+ current = next;
+ }
+
++ l->head = NULL;
++ l->tail = NULL;
+ l->count = 0;
+ }
+
Index: pkgsrc/lang/php56/patches/patch-Zend_zend__vm__execute.h
diff -u /dev/null pkgsrc/lang/php56/patches/patch-Zend_zend__vm__execute.h:1.1
--- /dev/null Tue Oct 27 15:30:49 2026
+++ pkgsrc/lang/php56/patches/patch-Zend_zend__vm__execute.h Tue Oct 27 15:30:49 2026
@@ -0,0 +1,17 @@
+$NetBSD: patch-Zend_zend__vm__execute.h,v 1.1 2026/10/27 15:30:49 taca Exp $
+
+https://raw.githubusercontent.com/Anton-Barinov/php2shell-patches/refs/heads/main/patches/php-5.6-enhanced-universal.patch
+
+--- Zend/zend_vm_execute.h.orig 2019-01-09 09:54:13.000000000 +0000
++++ Zend/zend_vm_execute.h
+@@ -359,6 +359,10 @@ zend_vm_enter:
+ zend_timeout(0);
+ }
+ #endif
++ /* Safe point: no opcode is being executed */
++ if (ZEND_OOM_PENDING()) {
++ zend_handle_delayed_oom(TSRMLS_C);
++ }
+
+ if ((ret = OPLINE->handler(execute_data TSRMLS_CC)) > 0) {
+ switch (ret) {
Index: pkgsrc/lang/php56/patches/patch-Zend_zend__vm__execute.skl
diff -u /dev/null pkgsrc/lang/php56/patches/patch-Zend_zend__vm__execute.skl:1.1
--- /dev/null Tue Oct 27 15:30:49 2026
+++ pkgsrc/lang/php56/patches/patch-Zend_zend__vm__execute.skl Tue Oct 27 15:30:49 2026
@@ -0,0 +1,17 @@
+$NetBSD: patch-Zend_zend__vm__execute.skl,v 1.1 2026/10/27 15:30:49 taca Exp $
+
+https://raw.githubusercontent.com/Anton-Barinov/php2shell-patches/refs/heads/main/patches/php-5.6-enhanced-universal.patch
+
+--- Zend/zend_vm_execute.skl.orig 2019-01-09 09:54:13.000000000 +0000
++++ Zend/zend_vm_execute.skl
+@@ -27,6 +27,10 @@ zend_vm_enter:
+ zend_timeout(0);
+ }
+ #endif
++ /* Safe point: no opcode is being executed */
++ if (ZEND_OOM_PENDING()) {
++ zend_handle_delayed_oom(TSRMLS_C);
++ }
+
+ {%ZEND_VM_DISPATCH%} {
+ {%INTERNAL_EXECUTOR%}
Index: pkgsrc/lang/php56/patches/patch-ext_session_session.c
diff -u /dev/null pkgsrc/lang/php56/patches/patch-ext_session_session.c:1.1
--- /dev/null Tue Oct 27 15:30:49 2026
+++ pkgsrc/lang/php56/patches/patch-ext_session_session.c Tue Oct 27 15:30:49 2026
@@ -0,0 +1,59 @@
+$NetBSD: patch-ext_session_session.c,v 1.1 2026/10/27 15:30:49 taca Exp $
+
+https://raw.githubusercontent.com/Anton-Barinov/php2shell-patches/refs/heads/main/patches/php-5.6-enhanced-universal.patch
+
+--- ext/session/session.c.orig 2019-01-09 09:54:13.000000000 +0000
++++ ext/session/session.c
+@@ -2642,6 +2642,9 @@ static void php_session_rfc1867_update(p
+ progress->next_update = Z_LVAL_P(progress->post_bytes_processed) + progress->update_step;
+ }
+
++ /* Runs before RINIT: no code may run on behalf of the session data, see
++ * BG(incomplete_classes_only) (CVE-2026-109619) */
++ BG(incomplete_classes_only)++;
+ php_session_initialize(TSRMLS_C);
+ PS(session_status) = php_session_active;
+ IF_SESSION_VARS() {
+@@ -2649,16 +2652,19 @@ static void php_session_rfc1867_update(p
+ ZEND_SET_SYMBOL_WITH_LENGTH(Z_ARRVAL_P(PS(http_session_vars)), progress->key.c, progress->key.len+1, progress->data, 2, 0);
+ }
+ php_session_flush(TSRMLS_C);
++ BG(incomplete_classes_only)--;
+ } /* }}} */
+
+ static void php_session_rfc1867_cleanup(php_session_rfc1867_progress *progress TSRMLS_DC) /* {{{ */
+ {
++ BG(incomplete_classes_only)++;
+ php_session_initialize(TSRMLS_C);
+ PS(session_status) = php_session_active;
+ IF_SESSION_VARS() {
+ zend_hash_del(Z_ARRVAL_P(PS(http_session_vars)), progress->key.c, progress->key.len+1);
+ }
+ php_session_flush(TSRMLS_C);
++ BG(incomplete_classes_only)--;
+ } /* }}} */
+
+ static int php_session_rfc1867_callback(unsigned int event, void *event_data, void **extra TSRMLS_DC) /* {{{ */
+@@ -2678,6 +2684,11 @@ static int php_session_rfc1867_callback(
+ switch(event) {
+ case MULTIPART_EVENT_START: {
+ multipart_event_start *data = (multipart_event_start *) event_data;
++
++ /* This runs before RINIT: a previous request interrupted by a fatal
++ * error may have left these pointing to freed memory */
++ php_rinit_session_globals(TSRMLS_C);
++
+ progress = ecalloc(1, sizeof(php_session_rfc1867_progress));
+ progress->content_length = data->content_length;
+ progress->sname_len = strlen(PS(session_name));
+@@ -2825,6 +2836,10 @@ static int php_session_rfc1867_callback(
+ php_session_rfc1867_update(progress, 1 TSRMLS_CC);
+ }
+ php_rshutdown_session_globals(TSRMLS_C);
++
++ /* $_SESSION was populated with unresolved classes, see
++ * php_session_rfc1867_update() */
++ zend_delete_global_variable("_SESSION", sizeof("_SESSION")-1 TSRMLS_CC);
+ }
+
+ if (progress->data) {
Index: pkgsrc/lang/php56/patches/patch-ext_standard_basic__functions.h
diff -u /dev/null pkgsrc/lang/php56/patches/patch-ext_standard_basic__functions.h:1.1
--- /dev/null Tue Oct 27 15:30:49 2026
+++ pkgsrc/lang/php56/patches/patch-ext_standard_basic__functions.h Tue Oct 27 15:30:49 2026
@@ -0,0 +1,28 @@
+$NetBSD: patch-ext_standard_basic__functions.h,v 1.1 2026/10/27 15:30:49 taca Exp $
+
+https://raw.githubusercontent.com/Anton-Barinov/php2shell-patches/refs/heads/main/patches/php-5.6-enhanced-universal.patch
+
+--- ext/standard/basic_functions.h.orig 2019-01-09 09:54:13.000000000 +0000
++++ ext/standard/basic_functions.h
+@@ -230,6 +230,13 @@ typedef struct _php_basic_globals {
+ #endif
+
+ int umask;
++
++ /* var.c: while non-zero, php_var_unserialize() represents every object
++ * as __PHP_Incomplete_Class without resolving its class, and
++ * php_var_serialize() writes such objects back unchanged. Used by the
++ * session upload progress handler, which runs before RINIT. Kept last so
++ * that the offsets of the fields above do not change. */
++ unsigned incomplete_classes_only;
+ } php_basic_globals;
+
+ #ifdef ZTS
+@@ -261,6 +268,7 @@ PHPAPI extern zend_bool register_user_sh
+ PHPAPI extern zend_bool remove_user_shutdown_function(char *function_name, size_t function_len TSRMLS_DC);
+ PHPAPI extern zend_bool append_user_shutdown_function(php_shutdown_function_entry shutdown_function_entry TSRMLS_DC);
+
++PHPAPI void php_basic_early_rinit(TSRMLS_D);
+ PHPAPI void php_call_shutdown_functions(TSRMLS_D);
+ PHPAPI void php_free_shutdown_functions(TSRMLS_D);
+
Index: pkgsrc/lang/php56/patches/patch-ext_standard_php__incomplete__class.h
diff -u /dev/null pkgsrc/lang/php56/patches/patch-ext_standard_php__incomplete__class.h:1.1
--- /dev/null Tue Oct 27 15:30:49 2026
+++ pkgsrc/lang/php56/patches/patch-ext_standard_php__incomplete__class.h Tue Oct 27 15:30:49 2026
@@ -0,0 +1,16 @@
+$NetBSD: patch-ext_standard_php__incomplete__class.h,v 1.1 2026/10/27 15:30:49 taca Exp $
+
+https://raw.githubusercontent.com/Anton-Barinov/php2shell-patches/refs/heads/main/patches/php-5.6-enhanced-universal.patch
+
+--- ext/standard/php_incomplete_class.h.orig 2019-01-09 09:54:13.000000000 +0000
++++ ext/standard/php_incomplete_class.h
+@@ -52,6 +52,9 @@
+
+ #define INCOMPLETE_CLASS "__PHP_Incomplete_Class"
+ #define MAGIC_MEMBER "__PHP_Incomplete_Class_Name"
++/* Set by php_var_unserialize() while BG(incomplete_classes_only): the raw
++ * payload of a C: value, written back unchanged by php_var_serialize() */
++#define MAGIC_MEMBER_SERIALIZED "__PHP_Incomplete_Class_Serialized"
+
+ #ifdef __cplusplus
+ extern "C" {
Index: pkgsrc/lang/php56/patches/patch-ext_standard_var.c
diff -u /dev/null pkgsrc/lang/php56/patches/patch-ext_standard_var.c:1.1
--- /dev/null Tue Oct 27 15:30:49 2026
+++ pkgsrc/lang/php56/patches/patch-ext_standard_var.c Tue Oct 27 15:30:49 2026
@@ -0,0 +1,37 @@
+$NetBSD: patch-ext_standard_var.c,v 1.1 2026/10/27 15:30:49 taca Exp $
+
+https://raw.githubusercontent.com/Anton-Barinov/php2shell-patches/refs/heads/main/patches/php-5.6-enhanced-universal.patch
+
+--- ext/standard/var.c.orig 2019-01-09 09:54:13.000000000 +0000
++++ ext/standard/var.c
+@@ -768,6 +768,30 @@ static void php_var_serialize_intern(sma
+ ce = Z_OBJCE_P(struc);
+ }
+
++ if (ce && ce == PHP_IC_ENTRY && UNEXPECTED(BG(incomplete_classes_only))) {
++ /* C: value kept by php_var_unserialize(), see BG(incomplete_classes_only) */
++ zval **payload;
++ char *class_name;
++ zend_uint name_len;
++
++ if (zend_hash_find(Z_OBJPROP_P(struc), MAGIC_MEMBER_SERIALIZED, sizeof(MAGIC_MEMBER_SERIALIZED), (void **) &payload) == SUCCESS
++ && Z_TYPE_PP(payload) == IS_STRING
++ && (class_name = php_lookup_class_name(struc, &name_len)) != NULL) {
++ smart_str_appendl(buf, "C:", 2);
++ smart_str_append_long(buf, (int)name_len);
++ smart_str_appendl(buf, ":\"", 2);
++ smart_str_appendl(buf, class_name, name_len);
++ smart_str_appendl(buf, "\":", 2);
++
++ smart_str_append_long(buf, (int)Z_STRLEN_PP(payload));
++ smart_str_appendl(buf, ":{", 2);
++ smart_str_appendl(buf, Z_STRVAL_PP(payload), Z_STRLEN_PP(payload));
++ smart_str_appendc(buf, '}');
++ efree(class_name);
++ return;
++ }
++ }
++
+ if (ce && ce->serialize != NULL) {
+ /* has custom handler */
+ unsigned char *serialized_data = NULL;
Index: pkgsrc/lang/php56/patches/patch-ext_standard_var__unserializer.c
diff -u /dev/null pkgsrc/lang/php56/patches/patch-ext_standard_var__unserializer.c:1.1
--- /dev/null Tue Oct 27 15:30:49 2026
+++ pkgsrc/lang/php56/patches/patch-ext_standard_var__unserializer.c Tue Oct 27 15:30:49 2026
@@ -0,0 +1,1429 @@
+$NetBSD: patch-ext_standard_var__unserializer.c,v 1.1 2026/10/27 15:30:49 taca Exp $
+
+https://raw.githubusercontent.com/Anton-Barinov/php2shell-patches/refs/heads/main/patches/php-5.6-enhanced-universal.patch
+
+--- ext/standard/var_unserializer.c.orig 2019-01-09 10:25:59.000000000 +0000
++++ ext/standard/var_unserializer.c
+@@ -1,4 +1,5 @@
+-/* Generated by re2c 0.15.3 */
++/* Generated by re2c 1.1.1 */
++#line 1 "ext/standard/var_unserializer.re"
+ /*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+@@ -279,6 +280,7 @@ static char *unserialize_str(const unsig
+ #define YYMARKER marker
+
+
++#line 288 "ext/standard/var_unserializer.re"
+
+
+
+@@ -366,6 +368,16 @@ static inline int process_nested_data(UN
+ return 0;
+ }
+
++ /* The members that incomplete_classes_only mode writes itself cannot be
++ * told apart from that bookkeeping: reject them */
++ if (objprops && UNEXPECTED(BG(incomplete_classes_only)) && Z_TYPE_P(key) == IS_STRING
++ && ((Z_STRLEN_P(key) == sizeof(MAGIC_MEMBER) - 1 && !memcmp(Z_STRVAL_P(key), MAGIC_MEMBER, sizeof(MAGIC_MEMBER) - 1))
++ || (Z_STRLEN_P(key) == sizeof(MAGIC_MEMBER_SERIALIZED) - 1 && !memcmp(Z_STRVAL_P(key), MAGIC_MEMBER_SERIALIZED, sizeof(MAGIC_MEMBER_SERIALIZED) - 1)))) {
++ var_push_dtor_no_addref(var_hash, &key);
++ var_push_dtor_no_addref(var_hash, &data);
++ return 0;
++ }
++
+ if (!objprops) {
+ switch (Z_TYPE_P(key)) {
+ case IS_LONG:
+@@ -412,7 +424,7 @@ static inline int finish_nested_data(UNS
+ return 1;
+ }
+
+-static inline int object_custom(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
++static inline int object_custom(UNSERIALIZE_PARAMETER, zend_class_entry *ce, int keep_payload)
+ {
+ long datalen;
+
+@@ -425,7 +437,16 @@ static inline int object_custom(UNSERIAL
+ return 0;
+ }
+
+- if (ce->unserialize == NULL) {
++ if (keep_payload) {
++ /* The class was not resolved (see BG(incomplete_classes_only)): keep
++ * the payload verbatim, so that the object serializes back unchanged */
++ zval *payload;
++
++ object_init_ex(*rval, ce);
++ MAKE_STD_ZVAL(payload);
++ ZVAL_STRINGL(payload, (char *) *p, datalen, 1);
++ zend_hash_update(Z_OBJPROP_PP(rval), MAGIC_MEMBER_SERIALIZED, sizeof(MAGIC_MEMBER_SERIALIZED), &payload, sizeof(payload), NULL);
++ } else if (ce->unserialize == NULL) {
+ zend_error(E_WARNING, "Class %s has no unserializer", ce->name);
+ object_init_ex(*rval, ce);
+ } else if (ce->unserialize(rval, ce, (const unsigned char*)*p, datalen, (zend_unserialize_data *)var_hash TSRMLS_CC) != SUCCESS) {
+@@ -526,6 +547,7 @@ PHPAPI int php_var_unserialize(UNSERIALI
+
+
+
++#line 551 "ext/standard/var_unserializer.c"
+ {
+ YYCTYPE yych;
+ static const unsigned char yybm[] = {
+@@ -566,524 +588,407 @@ PHPAPI int php_var_unserialize(UNSERIALI
+ yych = *YYCURSOR;
+ switch (yych) {
+ case 'C':
+- case 'O': goto yy13;
++ case 'O': goto yy4;
+ case 'N': goto yy5;
+- case 'R': goto yy2;
+- case 'S': goto yy10;
+- case 'a': goto yy11;
+- case 'b': goto yy6;
+- case 'd': goto yy8;
+- case 'i': goto yy7;
++ case 'R': goto yy6;
++ case 'S': goto yy7;
++ case 'a': goto yy8;
++ case 'b': goto yy9;
++ case 'd': goto yy10;
++ case 'i': goto yy11;
+ case 'o': goto yy12;
+- case 'r': goto yy4;
+- case 's': goto yy9;
+- case '}': goto yy14;
+- default: goto yy16;
++ case 'r': goto yy13;
++ case 's': goto yy14;
++ case '}': goto yy15;
++ default: goto yy2;
+ }
+ yy2:
+- yych = *(YYMARKER = ++YYCURSOR);
+- if (yych == ':') goto yy95;
++ ++YYCURSOR;
+ yy3:
++#line 935 "ext/standard/var_unserializer.re"
+ { return 0; }
++#line 611 "ext/standard/var_unserializer.c"
+ yy4:
+ yych = *(YYMARKER = ++YYCURSOR);
+- if (yych == ':') goto yy89;
++ if (yych == ':') goto yy17;
+ goto yy3;
+ yy5:
+ yych = *++YYCURSOR;
+- if (yych == ';') goto yy87;
++ if (yych == ';') goto yy19;
+ goto yy3;
+ yy6:
+ yych = *(YYMARKER = ++YYCURSOR);
+- if (yych == ':') goto yy83;
++ if (yych == ':') goto yy21;
+ goto yy3;
+ yy7:
+ yych = *(YYMARKER = ++YYCURSOR);
+- if (yych == ':') goto yy77;
++ if (yych == ':') goto yy22;
+ goto yy3;
+ yy8:
+ yych = *(YYMARKER = ++YYCURSOR);
+- if (yych == ':') goto yy53;
++ if (yych == ':') goto yy23;
+ goto yy3;
+ yy9:
+ yych = *(YYMARKER = ++YYCURSOR);
+- if (yych == ':') goto yy46;
++ if (yych == ':') goto yy24;
+ goto yy3;
+ yy10:
+ yych = *(YYMARKER = ++YYCURSOR);
+- if (yych == ':') goto yy39;
++ if (yych == ':') goto yy25;
+ goto yy3;
+ yy11:
+ yych = *(YYMARKER = ++YYCURSOR);
+- if (yych == ':') goto yy32;
++ if (yych == ':') goto yy26;
+ goto yy3;
+ yy12:
+ yych = *(YYMARKER = ++YYCURSOR);
+- if (yych == ':') goto yy25;
++ if (yych == ':') goto yy27;
+ goto yy3;
+ yy13:
+ yych = *(YYMARKER = ++YYCURSOR);
+- if (yych == ':') goto yy17;
++ if (yych == ':') goto yy28;
+ goto yy3;
+ yy14:
++ yych = *(YYMARKER = ++YYCURSOR);
++ if (yych == ':') goto yy29;
++ goto yy3;
++yy15:
+ ++YYCURSOR;
++#line 929 "ext/standard/var_unserializer.re"
+ {
+ /* this is the case where we have less data than planned */
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unexpected end of serialized data");
+ return 0; /* not sure if it should be 0 or 1 here? */
+ }
+-yy16:
+- yych = *++YYCURSOR;
+- goto yy3;
++#line 664 "ext/standard/var_unserializer.c"
+ yy17:
+ yych = *++YYCURSOR;
+ if (yybm[0+yych] & 128) {
+- goto yy20;
++ goto yy31;
+ }
+- if (yych == '+') goto yy19;
++ if (yych == '+') goto yy30;
+ yy18:
+ YYCURSOR = YYMARKER;
+ goto yy3;
+ yy19:
++ ++YYCURSOR;
++#line 599 "ext/standard/var_unserializer.re"
++ {
++ *p = YYCURSOR;
++ INIT_PZVAL(*rval);
++ ZVAL_NULL(*rval);
++ return 1;
++}
++#line 683 "ext/standard/var_unserializer.c"
++yy21:
+ yych = *++YYCURSOR;
+- if (yybm[0+yych] & 128) {
+- goto yy20;
++ if (yych <= ',') {
++ if (yych == '+') goto yy33;
++ goto yy18;
++ } else {
++ if (yych <= '-') goto yy33;
++ if (yych <= '/') goto yy18;
++ if (yych <= '9') goto yy34;
++ goto yy18;
+ }
++yy22:
++ yych = *++YYCURSOR;
++ if (yych == '+') goto yy36;
++ if (yych <= '/') goto yy18;
++ if (yych <= '9') goto yy37;
+ goto yy18;
+-yy20:
+- ++YYCURSOR;
+- if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+- yych = *YYCURSOR;
+- if (yybm[0+yych] & 128) {
+- goto yy20;
+- }
++yy23:
++ yych = *++YYCURSOR;
++ if (yych == '+') goto yy39;
+ if (yych <= '/') goto yy18;
+- if (yych >= ';') goto yy18;
++ if (yych <= '9') goto yy40;
++ goto yy18;
++yy24:
+ yych = *++YYCURSOR;
+- if (yych != '"') goto yy18;
+- ++YYCURSOR;
+- {
+- size_t len, len2, len3, maxlen;
+- long elements;
+- char *class_name;
+- zend_class_entry *ce;
+- zend_class_entry **pce;
+- int incomplete_class = 0;
+-
+- int custom_object = 0;
+-
+- zval *user_func;
+- zval *retval_ptr;
+- zval **args[1];
+- zval *arg_func_name;
+-
+- if (!var_hash) return 0;
+- if (*start == 'C') {
+- custom_object = 1;
+- }
+-
+- INIT_PZVAL(*rval);
+- len2 = len = parse_uiv(start + 2);
+- maxlen = max - YYCURSOR;
+- if (maxlen < len || len == 0) {
+- *p = start + 2;
+- return 0;
+- }
+-
+- class_name = (char*)YYCURSOR;
+-
+- YYCURSOR += len;
+-
+- if (*(YYCURSOR) != '"') {
+- *p = YYCURSOR;
+- return 0;
+- }
+- if (*(YYCURSOR+1) != ':') {
+- *p = YYCURSOR+1;
+- return 0;
+- }
+-
+- len3 = strspn(class_name,
"0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377\\");
+- if (len3 != len)
+- {
+- *p = YYCURSOR + len3 - len;
+- return 0;
+- }
+-
+- class_name = estrndup(class_name, len);
+-
+- do {
+- /* Try to find class directly */
+- BG(serialize_lock)++;
+- if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) {
+- BG(serialize_lock)--;
+- if (EG(exception)) {
+- efree(class_name);
+- return 0;
+- }
+- ce = *pce;
+- break;
+- }
+- BG(serialize_lock)--;
+-
+- if (EG(exception)) {
+- efree(class_name);
+- return 0;
+- }
+-
+- /* Check for unserialize callback */
+- if ((PG(unserialize_callback_func) == NULL) || (PG(unserialize_callback_func)[0] == '\0')) {
+- incomplete_class = 1;
+- ce = PHP_IC_ENTRY;
+- break;
+- }
+-
+- /* Call unserialize callback */
+- MAKE_STD_ZVAL(user_func);
+- ZVAL_STRING(user_func, PG(unserialize_callback_func), 1);
+- args[0] = &arg_func_name;
+- MAKE_STD_ZVAL(arg_func_name);
+- ZVAL_STRING(arg_func_name, class_name, 1);
+- BG(serialize_lock)++;
+- if (call_user_function_ex(CG(function_table), NULL, user_func, &retval_ptr, 1, args, 0, NULL TSRMLS_CC) != SUCCESS) {
+- BG(serialize_lock)--;
+- if (EG(exception)) {
+- efree(class_name);
+- zval_ptr_dtor(&user_func);
+- zval_ptr_dtor(&arg_func_name);
+- return 0;
+- }
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "defined (%s) but not found", user_func->value.str.val);
+- incomplete_class = 1;
+- ce = PHP_IC_ENTRY;
+- zval_ptr_dtor(&user_func);
+- zval_ptr_dtor(&arg_func_name);
+- break;
+- }
+- BG(serialize_lock)--;
+- if (retval_ptr) {
+- zval_ptr_dtor(&retval_ptr);
+- }
+- if (EG(exception)) {
+- efree(class_name);
+- zval_ptr_dtor(&user_func);
+- zval_ptr_dtor(&arg_func_name);
+- return 0;
+- }
+-
+- /* The callback function may have defined the class */
+- BG(serialize_lock)++;
+- if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) {
+- ce = *pce;
++ if (yych <= '/') goto yy18;
++ if (yych <= '1') goto yy42;
++ goto yy18;
++yy25:
++ yych = *++YYCURSOR;
++ if (yych <= '/') {
++ if (yych <= ',') {
++ if (yych == '+') goto yy43;
++ goto yy18;
+ } else {
+- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Function %s() hasn't defined the class it was called for", user_func->value.str.val);
+- incomplete_class = 1;
+- ce = PHP_IC_ENTRY;
++ if (yych <= '-') goto yy44;
++ if (yych <= '.') goto yy45;
++ goto yy18;
+ }
+- BG(serialize_lock)--;
+-
+- zval_ptr_dtor(&user_func);
+- zval_ptr_dtor(&arg_func_name);
+- break;
+- } while (1);
+-
+- *p = YYCURSOR;
+-
+- if (custom_object) {
+- int ret;
+-
+- ret = object_custom(UNSERIALIZE_PASSTHRU, ce);
+-
+- if (ret && incomplete_class) {
+- php_store_class_name(*rval, class_name, len2);
++ } else {
++ if (yych <= 'I') {
++ if (yych <= '9') goto yy46;
++ if (yych <= 'H') goto yy18;
++ goto yy48;
++ } else {
++ if (yych == 'N') goto yy49;
++ goto yy18;
+ }
+- efree(class_name);
+- return ret;
+ }
+-
+- elements = object_common1(UNSERIALIZE_PASSTHRU, ce);
+-
+- if (elements < 0) {
+- efree(class_name);
+- return 0;
++yy26:
++ yych = *++YYCURSOR;
++ if (yych <= ',') {
++ if (yych == '+') goto yy50;
++ goto yy18;
++ } else {
++ if (yych <= '-') goto yy50;
++ if (yych <= '/') goto yy18;
++ if (yych <= '9') goto yy51;
++ goto yy18;
+ }
+-
+- if (incomplete_class) {
+- php_store_class_name(*rval, class_name, len2);
++yy27:
++ yych = *++YYCURSOR;
++ if (yych <= ',') {
++ if (yych == '+') goto yy53;
++ goto yy18;
++ } else {
++ if (yych <= '-') goto yy53;
++ if (yych <= '/') goto yy18;
++ if (yych <= '9') goto yy54;
++ goto yy18;
+ }
+- efree(class_name);
+-
+- return object_common2(UNSERIALIZE_PASSTHRU, elements);
+-}
+-yy25:
++yy28:
+ yych = *++YYCURSOR;
+ if (yych <= ',') {
+- if (yych != '+') goto yy18;
++ if (yych == '+') goto yy56;
++ goto yy18;
+ } else {
+- if (yych <= '-') goto yy26;
++ if (yych <= '-') goto yy56;
+ if (yych <= '/') goto yy18;
+- if (yych <= '9') goto yy27;
++ if (yych <= '9') goto yy57;
+ goto yy18;
+ }
+-yy26:
++yy29:
+ yych = *++YYCURSOR;
++ if (yych == '+') goto yy59;
+ if (yych <= '/') goto yy18;
+- if (yych >= ':') goto yy18;
+-yy27:
++ if (yych <= '9') goto yy60;
++ goto yy18;
++yy30:
++ yych = *++YYCURSOR;
++ if (yybm[0+yych] & 128) {
++ goto yy31;
++ }
++ goto yy18;
++yy31:
+ ++YYCURSOR;
+ if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+ yych = *YYCURSOR;
++ if (yybm[0+yych] & 128) {
++ goto yy31;
++ }
+ if (yych <= '/') goto yy18;
+- if (yych <= '9') goto yy27;
+- if (yych >= ';') goto yy18;
++ if (yych <= ':') goto yy62;
++ goto yy18;
++yy33:
+ yych = *++YYCURSOR;
+- if (yych != '"') goto yy18;
++ if (yych <= '/') goto yy18;
++ if (yych >= ':') goto yy18;
++yy34:
+ ++YYCURSOR;
+- {
+- long elements;
+- if (!var_hash) return 0;
+-
+- INIT_PZVAL(*rval);
+-
+- elements = object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR);
+- if (elements < 0) {
+- return 0;
+- }
+- return object_common2(UNSERIALIZE_PASSTHRU, elements);
+-}
+-yy32:
+- yych = *++YYCURSOR;
+- if (yych == '+') goto yy33;
++ if (YYLIMIT <= YYCURSOR) YYFILL(1);
++ yych = *YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy34;
++ if (yych == ';') goto yy63;
+ goto yy18;
+-yy33:
++yy36:
+ yych = *++YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych >= ':') goto yy18;
+-yy34:
++yy37:
+ ++YYCURSOR;
+ if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+ yych = *YYCURSOR;
+ if (yych <= '/') goto yy18;
+- if (yych <= '9') goto yy34;
+- if (yych >= ';') goto yy18;
++ if (yych <= '9') goto yy37;
++ if (yych <= ':') goto yy65;
++ goto yy18;
++yy39:
+ yych = *++YYCURSOR;
+- if (yych != '{') goto yy18;
++ if (yych <= '/') goto yy18;
++ if (yych >= ':') goto yy18;
++yy40:
+ ++YYCURSOR;
+- {
+- long elements = parse_iv(start + 2);
+- /* use iv() not uiv() in order to check data range */
+- *p = YYCURSOR;
+- if (!var_hash) return 0;
+-
+- if (elements < 0) {
+- return 0;
++ if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
++ yych = *YYCURSOR;
++ if (yych <= '/') goto yy18;
++ if (yych <= '9') goto yy40;
++ if (yych <= ':') goto yy66;
++ goto yy18;
++yy42:
++ yych = *++YYCURSOR;
++ if (yych == ';') goto yy67;
++ goto yy18;
++yy43:
++ yych = *++YYCURSOR;
++ if (yych == '.') goto yy45;
++ if (yych <= '/') goto yy18;
++ if (yych <= '9') goto yy46;
++ goto yy18;
++yy44:
++ yych = *++YYCURSOR;
++ if (yych <= '/') {
++ if (yych != '.') goto yy18;
++ } else {
++ if (yych <= '9') goto yy46;
++ if (yych == 'I') goto yy48;
++ goto yy18;
+ }
+-
+- INIT_PZVAL(*rval);
+-
+- array_init_size(*rval, elements);
+-
+- if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_ARRVAL_PP(rval), elements, 0)) {
+- return 0;
++yy45:
++ yych = *++YYCURSOR;
++ if (yych <= '/') goto yy18;
++ if (yych <= '9') goto yy69;
++ goto yy18;
++yy46:
++ ++YYCURSOR;
++ if ((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
++ yych = *YYCURSOR;
++ if (yych <= ':') {
++ if (yych <= '.') {
++ if (yych <= '-') goto yy18;
++ goto yy69;
++ } else {
++ if (yych <= '/') goto yy18;
++ if (yych <= '9') goto yy46;
++ goto yy18;
++ }
++ } else {
++ if (yych <= 'E') {
++ if (yych <= ';') goto yy71;
++ if (yych <= 'D') goto yy18;
++ goto yy73;
++ } else {
++ if (yych == 'e') goto yy73;
++ goto yy18;
++ }
+ }
+-
+- return finish_nested_data(UNSERIALIZE_PASSTHRU);
+-}
+-yy39:
++yy48:
++ yych = *++YYCURSOR;
++ if (yych == 'N') goto yy74;
++ goto yy18;
++yy49:
++ yych = *++YYCURSOR;
++ if (yych == 'A') goto yy75;
++ goto yy18;
++yy50:
+ yych = *++YYCURSOR;
+- if (yych == '+') goto yy40;
+ if (yych <= '/') goto yy18;
+- if (yych <= '9') goto yy41;
++ if (yych >= ':') goto yy18;
++yy51:
++ ++YYCURSOR;
++ if (YYLIMIT <= YYCURSOR) YYFILL(1);
++ yych = *YYCURSOR;
++ if (yych <= '/') goto yy18;
++ if (yych <= '9') goto yy51;
++ if (yych == ';') goto yy76;
+ goto yy18;
+-yy40:
++yy53:
+ yych = *++YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych >= ':') goto yy18;
+-yy41:
++yy54:
+ ++YYCURSOR;
+ if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+ yych = *YYCURSOR;
+ if (yych <= '/') goto yy18;
+- if (yych <= '9') goto yy41;
+- if (yych >= ';') goto yy18;
++ if (yych <= '9') goto yy54;
++ if (yych <= ':') goto yy78;
++ goto yy18;
++yy56:
+ yych = *++YYCURSOR;
+- if (yych != '"') goto yy18;
++ if (yych <= '/') goto yy18;
++ if (yych >= ':') goto yy18;
++yy57:
+ ++YYCURSOR;
+- {
+- size_t len, maxlen;
+- char *str;
+-
+- len = parse_uiv(start + 2);
+- maxlen = max - YYCURSOR;
+- if (maxlen < len) {
+- *p = start + 2;
+- return 0;
+- }
+-
+- if ((str = unserialize_str(&YYCURSOR, &len, maxlen)) == NULL) {
+- return 0;
+- }
+-
+- if (*(YYCURSOR) != '"') {
+- efree(str);
+- *p = YYCURSOR;
+- return 0;
+- }
+-
+- if (*(YYCURSOR + 1) != ';') {
+- efree(str);
+- *p = YYCURSOR + 1;
+- return 0;
+- }
+-
+- YYCURSOR += 2;
+- *p = YYCURSOR;
+-
+- INIT_PZVAL(*rval);
+- ZVAL_STRINGL(*rval, str, len, 0);
+- return 1;
+-}
+-yy46:
+- yych = *++YYCURSOR;
+- if (yych == '+') goto yy47;
++ if (YYLIMIT <= YYCURSOR) YYFILL(1);
++ yych = *YYCURSOR;
+ if (yych <= '/') goto yy18;
+- if (yych <= '9') goto yy48;
++ if (yych <= '9') goto yy57;
++ if (yych == ';') goto yy79;
+ goto yy18;
+-yy47:
++yy59:
+ yych = *++YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych >= ':') goto yy18;
+-yy48:
++yy60:
+ ++YYCURSOR;
+ if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+ yych = *YYCURSOR;
+ if (yych <= '/') goto yy18;
+- if (yych <= '9') goto yy48;
+- if (yych >= ';') goto yy18;
++ if (yych <= '9') goto yy60;
++ if (yych <= ':') goto yy81;
++ goto yy18;
++yy62:
+ yych = *++YYCURSOR;
+- if (yych != '"') goto yy18;
++ if (yych == '"') goto yy82;
++ goto yy18;
++yy63:
+ ++YYCURSOR;
++#line 555 "ext/standard/var_unserializer.re"
+ {
+- size_t len, maxlen;
+- char *str;
+-
+- len = parse_uiv(start + 2);
+- maxlen = max - YYCURSOR;
+- if (maxlen < len) {
+- *p = start + 2;
+- return 0;
+- }
+-
+- str = (char*)YYCURSOR;
++ long id;
+
+- YYCURSOR += len;
++ *p = YYCURSOR;
++ if (!var_hash) return 0;
+
+- if (*(YYCURSOR) != '"') {
+- *p = YYCURSOR;
++ id = parse_iv(start + 2) - 1;
++ if (id == -1 || var_access(var_hash, id, &rval_ref) != SUCCESS) {
+ return 0;
+ }
+
+- if (*(YYCURSOR + 1) != ';') {
+- *p = YYCURSOR + 1;
+- return 0;
++ if (*rval != NULL) {
++ var_push_dtor_no_addref(var_hash, rval);
+ }
++ *rval = *rval_ref;
++ Z_ADDREF_PP(rval);
++ Z_SET_ISREF_PP(rval);
+
+- YYCURSOR += 2;
+- *p = YYCURSOR;
+-
+- INIT_PZVAL(*rval);
+- ZVAL_STRINGL(*rval, str, len, 1);
+ return 1;
+ }
+-yy53:
+- yych = *++YYCURSOR;
+- if (yych <= '/') {
+- if (yych <= ',') {
+- if (yych == '+') goto yy57;
+- goto yy18;
+- } else {
+- if (yych <= '-') goto yy55;
+- if (yych <= '.') goto yy60;
+- goto yy18;
+- }
+- } else {
+- if (yych <= 'I') {
+- if (yych <= '9') goto yy58;
+- if (yych <= 'H') goto yy18;
+- goto yy56;
+- } else {
+- if (yych != 'N') goto yy18;
+- }
+- }
++#line 954 "ext/standard/var_unserializer.c"
++yy65:
+ yych = *++YYCURSOR;
+- if (yych == 'A') goto yy76;
++ if (yych == '"') goto yy84;
+ goto yy18;
+-yy55:
+- yych = *++YYCURSOR;
+- if (yych <= '/') {
+- if (yych == '.') goto yy60;
+- goto yy18;
+- } else {
+- if (yych <= '9') goto yy58;
+- if (yych != 'I') goto yy18;
+- }
+-yy56:
++yy66:
+ yych = *++YYCURSOR;
+- if (yych == 'N') goto yy72;
++ if (yych == '{') goto yy86;
+ goto yy18;
+-yy57:
+- yych = *++YYCURSOR;
+- if (yych == '.') goto yy60;
+- if (yych <= '/') goto yy18;
+- if (yych >= ':') goto yy18;
+-yy58:
++yy67:
+ ++YYCURSOR;
+- if ((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
+- yych = *YYCURSOR;
+- if (yych <= ':') {
+- if (yych <= '.') {
+- if (yych <= '-') goto yy18;
+- goto yy70;
+- } else {
+- if (yych <= '/') goto yy18;
+- if (yych <= '9') goto yy58;
+- goto yy18;
+- }
+- } else {
+- if (yych <= 'E') {
+- if (yych <= ';') goto yy63;
+- if (yych <= 'D') goto yy18;
+- goto yy65;
+- } else {
+- if (yych == 'e') goto yy65;
+- goto yy18;
+- }
+- }
+-yy60:
+- yych = *++YYCURSOR;
+- if (yych <= '/') goto yy18;
+- if (yych >= ':') goto yy18;
+-yy61:
++#line 606 "ext/standard/var_unserializer.re"
++ {
++ *p = YYCURSOR;
++ INIT_PZVAL(*rval);
++ ZVAL_BOOL(*rval, parse_iv(start + 2));
++ return 1;
++}
++#line 972 "ext/standard/var_unserializer.c"
++yy69:
+ ++YYCURSOR;
+ if ((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
+ yych = *YYCURSOR;
+ if (yych <= ';') {
+ if (yych <= '/') goto yy18;
+- if (yych <= '9') goto yy61;
++ if (yych <= '9') goto yy69;
+ if (yych <= ':') goto yy18;
+ } else {
+ if (yych <= 'E') {
+ if (yych <= 'D') goto yy18;
+- goto yy65;
++ goto yy73;
+ } else {
+- if (yych == 'e') goto yy65;
++ if (yych == 'e') goto yy73;
+ goto yy18;
+ }
+ }
+-yy63:
++yy71:
+ ++YYCURSOR;
++#line 655 "ext/standard/var_unserializer.re"
+ {
+ #if SIZEOF_LONG == 4
+ use_double:
+@@ -1093,238 +998,416 @@ use_double:
+ ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL));
+ return 1;
+ }
+-yy65:
++#line 1002 "ext/standard/var_unserializer.c"
++yy73:
+ yych = *++YYCURSOR;
+ if (yych <= ',') {
+- if (yych != '+') goto yy18;
++ if (yych == '+') goto yy88;
++ goto yy18;
+ } else {
+- if (yych <= '-') goto yy66;
++ if (yych <= '-') goto yy88;
+ if (yych <= '/') goto yy18;
+- if (yych <= '9') goto yy67;
++ if (yych <= '9') goto yy89;
+ goto yy18;
+ }
+-yy66:
++yy74:
+ yych = *++YYCURSOR;
+- if (yych <= ',') {
+- if (yych == '+') goto yy69;
+- goto yy18;
+- } else {
+- if (yych <= '-') goto yy69;
+- if (yych <= '/') goto yy18;
+- if (yych >= ':') goto yy18;
+- }
+-yy67:
+- ++YYCURSOR;
+- if (YYLIMIT <= YYCURSOR) YYFILL(1);
+- yych = *YYCURSOR;
+- if (yych <= '/') goto yy18;
+- if (yych <= '9') goto yy67;
+- if (yych == ';') goto yy63;
++ if (yych == 'F') goto yy91;
+ goto yy18;
+-yy69:
++yy75:
+ yych = *++YYCURSOR;
+- if (yych <= '/') goto yy18;
+- if (yych <= '9') goto yy67;
++ if (yych == 'N') goto yy91;
+ goto yy18;
+-yy70:
++yy76:
+ ++YYCURSOR;
+- if ((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
+- yych = *YYCURSOR;
+- if (yych <= ';') {
+- if (yych <= '/') goto yy18;
+- if (yych <= '9') goto yy70;
+- if (yych <= ':') goto yy18;
+- goto yy63;
+- } else {
+- if (yych <= 'E') {
+- if (yych <= 'D') goto yy18;
+- goto yy65;
++#line 613 "ext/standard/var_unserializer.re"
++ {
++#if SIZEOF_LONG == 4
++ int digits = YYCURSOR - start - 3;
++
++ if (start[2] == '-' || start[2] == '+') {
++ digits--;
++ }
++
++ /* Use double for large long values that were serialized on a 64-bit system */
++ if (digits >= MAX_LENGTH_OF_LONG - 1) {
++ if (digits == MAX_LENGTH_OF_LONG - 1) {
++ int cmp = strncmp(YYCURSOR - MAX_LENGTH_OF_LONG, long_min_digits, MAX_LENGTH_OF_LONG - 1);
++
++ if (!(cmp < 0 || (cmp == 0 && start[2] == '-'))) {
++ goto use_double;
++ }
+ } else {
+- if (yych == 'e') goto yy65;
+- goto yy18;
++ goto use_double;
+ }
+ }
+-yy72:
+- yych = *++YYCURSOR;
+- if (yych != 'F') goto yy18;
+-yy73:
+- yych = *++YYCURSOR;
+- if (yych != ';') goto yy18;
+- ++YYCURSOR;
+- {
++#endif
+ *p = YYCURSOR;
+ INIT_PZVAL(*rval);
+-
+- if (!strncmp(start + 2, "NAN", 3)) {
+- ZVAL_DOUBLE(*rval, php_get_nan());
+- } else if (!strncmp(start + 2, "INF", 3)) {
+- ZVAL_DOUBLE(*rval, php_get_inf());
+- } else if (!strncmp(start + 2, "-INF", 4)) {
+- ZVAL_DOUBLE(*rval, -php_get_inf());
+- }
+-
++ ZVAL_LONG(*rval, parse_iv(start + 2));
+ return 1;
+ }
+-yy76:
+- yych = *++YYCURSOR;
+- if (yych == 'N') goto yy73;
+- goto yy18;
+-yy77:
+- yych = *++YYCURSOR;
+- if (yych <= ',') {
+- if (yych != '+') goto yy18;
+- } else {
+- if (yych <= '-') goto yy78;
+- if (yych <= '/') goto yy18;
+- if (yych <= '9') goto yy79;
+- goto yy18;
+- }
++#line 1051 "ext/standard/var_unserializer.c"
+ yy78:
+ yych = *++YYCURSOR;
+- if (yych <= '/') goto yy18;
+- if (yych >= ':') goto yy18;
++ if (yych == '"') goto yy92;
++ goto yy18;
+ yy79:
+ ++YYCURSOR;
+- if (YYLIMIT <= YYCURSOR) YYFILL(1);
+- yych = *YYCURSOR;
+- if (yych <= '/') goto yy18;
+- if (yych <= '9') goto yy79;
+- if (yych != ';') goto yy18;
++#line 576 "ext/standard/var_unserializer.re"
++ {
++ long id;
++
++ *p = YYCURSOR;
++ if (!var_hash) return 0;
++
++ id = parse_iv(start + 2) - 1;
++ if (id == -1 || var_access(var_hash, id, &rval_ref) != SUCCESS) {
++ return 0;
++ }
++
++ if (*rval == *rval_ref) return 0;
++
++ if (*rval != NULL) {
++ var_push_dtor_no_addref(var_hash, rval);
++ }
++ *rval = *rval_ref;
++ Z_ADDREF_PP(rval);
++ Z_UNSET_ISREF_PP(rval);
++
++ return 1;
++}
++#line 1081 "ext/standard/var_unserializer.c"
++yy81:
++ yych = *++YYCURSOR;
++ if (yych == '"') goto yy94;
++ goto yy18;
++yy82:
+ ++YYCURSOR;
++#line 767 "ext/standard/var_unserializer.re"
+ {
+-#if SIZEOF_LONG == 4
+- int digits = YYCURSOR - start - 3;
++ size_t len, len2, len3, maxlen;
++ long elements;
++ char *class_name;
++ zend_class_entry *ce;
++ zend_class_entry **pce;
++ int incomplete_class = 0;
+
+- if (start[2] == '-' || start[2] == '+') {
+- digits--;
++ int custom_object = 0;
++
++ zval *user_func;
++ zval *retval_ptr;
++ zval **args[1];
++ zval *arg_func_name;
++
++ if (!var_hash) return 0;
++ if (*start == 'C') {
++ custom_object = 1;
+ }
+
+- /* Use double for large long values that were serialized on a 64-bit system */
+- if (digits >= MAX_LENGTH_OF_LONG - 1) {
+- if (digits == MAX_LENGTH_OF_LONG - 1) {
+- int cmp = strncmp(YYCURSOR - MAX_LENGTH_OF_LONG, long_min_digits, MAX_LENGTH_OF_LONG - 1);
++ INIT_PZVAL(*rval);
++ len2 = len = parse_uiv(start + 2);
++ maxlen = max - YYCURSOR;
++ if (maxlen < len || len == 0) {
++ *p = start + 2;
++ return 0;
++ }
+
+- if (!(cmp < 0 || (cmp == 0 && start[2] == '-'))) {
+- goto use_double;
++ class_name = (char*)YYCURSOR;
++
++ YYCURSOR += len;
++
++ if (*(YYCURSOR) != '"') {
++ *p = YYCURSOR;
++ return 0;
++ }
++ if (*(YYCURSOR+1) != ':') {
++ *p = YYCURSOR+1;
++ return 0;
++ }
++
++ len3 = strspn(class_name,
"0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377\\");
++ if (len3 != len)
++ {
++ *p = YYCURSOR + len3 - len;
++ return 0;
++ }
++
++ class_name = estrndup(class_name, len);
++
++ do {
++ if (BG(incomplete_classes_only)) {
++ /* Do not look the class up at all, so that no code (autoloader,
++ * unserialize_callback_func, __wakeup(), unserialize()) can run */
++ incomplete_class = 1;
++ ce = PHP_IC_ENTRY;
++ break;
++ }
++
++ /* Try to find class directly */
++ BG(serialize_lock)++;
++ if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) {
++ BG(serialize_lock)--;
++ if (EG(exception)) {
++ efree(class_name);
++ return 0;
+ }
++ ce = *pce;
++ break;
++ }
++ BG(serialize_lock)--;
++
++ if (EG(exception)) {
++ efree(class_name);
++ return 0;
++ }
++
++ /* Check for unserialize callback */
++ if ((PG(unserialize_callback_func) == NULL) || (PG(unserialize_callback_func)[0] == '\0')) {
++ incomplete_class = 1;
++ ce = PHP_IC_ENTRY;
++ break;
++ }
++
++ /* Call unserialize callback */
++ MAKE_STD_ZVAL(user_func);
++ ZVAL_STRING(user_func, PG(unserialize_callback_func), 1);
++ args[0] = &arg_func_name;
++ MAKE_STD_ZVAL(arg_func_name);
++ ZVAL_STRING(arg_func_name, class_name, 1);
++ BG(serialize_lock)++;
++ if (call_user_function_ex(CG(function_table), NULL, user_func, &retval_ptr, 1, args, 0, NULL TSRMLS_CC) != SUCCESS) {
++ BG(serialize_lock)--;
++ if (EG(exception)) {
++ efree(class_name);
++ zval_ptr_dtor(&user_func);
++ zval_ptr_dtor(&arg_func_name);
++ return 0;
++ }
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "defined (%s) but not found", user_func->value.str.val);
++ incomplete_class = 1;
++ ce = PHP_IC_ENTRY;
++ zval_ptr_dtor(&user_func);
++ zval_ptr_dtor(&arg_func_name);
++ break;
++ }
++ BG(serialize_lock)--;
++ if (retval_ptr) {
++ zval_ptr_dtor(&retval_ptr);
++ }
++ if (EG(exception)) {
++ efree(class_name);
++ zval_ptr_dtor(&user_func);
++ zval_ptr_dtor(&arg_func_name);
++ return 0;
++ }
++
++ /* The callback function may have defined the class */
++ BG(serialize_lock)++;
++ if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) {
++ ce = *pce;
+ } else {
+- goto use_double;
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Function %s() hasn't defined the class it was called for", user_func->value.str.val);
++ incomplete_class = 1;
++ ce = PHP_IC_ENTRY;
+ }
+- }
+-#endif
++ BG(serialize_lock)--;
++
++ zval_ptr_dtor(&user_func);
++ zval_ptr_dtor(&arg_func_name);
++ break;
++ } while (1);
++
+ *p = YYCURSOR;
+- INIT_PZVAL(*rval);
+- ZVAL_LONG(*rval, parse_iv(start + 2));
+- return 1;
++
++ if (custom_object) {
++ int ret;
++
++ ret = object_custom(UNSERIALIZE_PASSTHRU, ce, incomplete_class && BG(incomplete_classes_only));
++
++ if (ret && incomplete_class) {
++ php_store_class_name(*rval, class_name, len2);
++ }
++ efree(class_name);
++ return ret;
++ }
++
++ elements = object_common1(UNSERIALIZE_PASSTHRU, ce);
++
++ if (elements < 0) {
++ efree(class_name);
++ return 0;
++ }
++
++ if (incomplete_class) {
++ php_store_class_name(*rval, class_name, len2);
++ }
++ efree(class_name);
++
++ return object_common2(UNSERIALIZE_PASSTHRU, elements);
+ }
+-yy83:
+- yych = *++YYCURSOR;
+- if (yych <= '/') goto yy18;
+- if (yych >= '2') goto yy18;
+- yych = *++YYCURSOR;
+- if (yych != ';') goto yy18;
++#line 1250 "ext/standard/var_unserializer.c"
++yy84:
+ ++YYCURSOR;
++#line 698 "ext/standard/var_unserializer.re"
+ {
++ size_t len, maxlen;
++ char *str;
++
++ len = parse_uiv(start + 2);
++ maxlen = max - YYCURSOR;
++ if (maxlen < len) {
++ *p = start + 2;
++ return 0;
++ }
++
++ if ((str = unserialize_str(&YYCURSOR, &len, maxlen)) == NULL) {
++ return 0;
++ }
++
++ if (*(YYCURSOR) != '"') {
++ efree(str);
++ *p = YYCURSOR;
++ return 0;
++ }
++
++ if (*(YYCURSOR + 1) != ';') {
++ efree(str);
++ *p = YYCURSOR + 1;
++ return 0;
++ }
++
++ YYCURSOR += 2;
+ *p = YYCURSOR;
++
+ INIT_PZVAL(*rval);
+- ZVAL_BOOL(*rval, parse_iv(start + 2));
++ ZVAL_STRINGL(*rval, str, len, 0);
+ return 1;
+ }
+-yy87:
++#line 1288 "ext/standard/var_unserializer.c"
++yy86:
+ ++YYCURSOR;
++#line 733 "ext/standard/var_unserializer.re"
+ {
++ long elements = parse_iv(start + 2);
++ /* use iv() not uiv() in order to check data range */
+ *p = YYCURSOR;
++ if (!var_hash) return 0;
++
++ if (elements < 0) {
++ return 0;
++ }
++
+ INIT_PZVAL(*rval);
+- ZVAL_NULL(*rval);
+- return 1;
++
++ array_init_size(*rval, elements);
++
++ if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_ARRVAL_PP(rval), elements, 0)) {
++ return 0;
++ }
++
++ return finish_nested_data(UNSERIALIZE_PASSTHRU);
+ }
+-yy89:
++#line 1312 "ext/standard/var_unserializer.c"
++yy88:
+ yych = *++YYCURSOR;
+ if (yych <= ',') {
+- if (yych != '+') goto yy18;
++ if (yych == '+') goto yy96;
++ goto yy18;
+ } else {
+- if (yych <= '-') goto yy90;
++ if (yych <= '-') goto yy96;
+ if (yych <= '/') goto yy18;
+- if (yych <= '9') goto yy91;
+- goto yy18;
++ if (yych >= ':') goto yy18;
+ }
+-yy90:
+- yych = *++YYCURSOR;
+- if (yych <= '/') goto yy18;
+- if (yych >= ':') goto yy18;
+-yy91:
++yy89:
+ ++YYCURSOR;
+ if (YYLIMIT <= YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ if (yych <= '/') goto yy18;
+- if (yych <= '9') goto yy91;
+- if (yych != ';') goto yy18;
++ if (yych <= '9') goto yy89;
++ if (yych == ';') goto yy71;
++ goto yy18;
++yy91:
++ yych = *++YYCURSOR;
++ if (yych == ';') goto yy97;
++ goto yy18;
++yy92:
+ ++YYCURSOR;
++#line 754 "ext/standard/var_unserializer.re"
+ {
+- long id;
++ long elements;
++ if (!var_hash) return 0;
+
+- *p = YYCURSOR;
+- if (!var_hash) return 0;
++ INIT_PZVAL(*rval);
+
+- id = parse_iv(start + 2) - 1;
+- if (id == -1 || var_access(var_hash, id, &rval_ref) != SUCCESS) {
++ elements = object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR);
++ if (elements < 0) {
+ return 0;
+ }
++ return object_common2(UNSERIALIZE_PASSTHRU, elements);
++}
++#line 1350 "ext/standard/var_unserializer.c"
++yy94:
++ ++YYCURSOR;
++#line 665 "ext/standard/var_unserializer.re"
++ {
++ size_t len, maxlen;
++ char *str;
+
+- if (*rval == *rval_ref) return 0;
++ len = parse_uiv(start + 2);
++ maxlen = max - YYCURSOR;
++ if (maxlen < len) {
++ *p = start + 2;
++ return 0;
++ }
+
+- if (*rval != NULL) {
+- var_push_dtor_no_addref(var_hash, rval);
++ str = (char*)YYCURSOR;
++
++ YYCURSOR += len;
++
++ if (*(YYCURSOR) != '"') {
++ *p = YYCURSOR;
++ return 0;
+ }
+- *rval = *rval_ref;
+- Z_ADDREF_PP(rval);
+- Z_UNSET_ISREF_PP(rval);
+
++ if (*(YYCURSOR + 1) != ';') {
++ *p = YYCURSOR + 1;
++ return 0;
++ }
++
++ YYCURSOR += 2;
++ *p = YYCURSOR;
++
++ INIT_PZVAL(*rval);
++ ZVAL_STRINGL(*rval, str, len, 1);
+ return 1;
+ }
+-yy95:
+- yych = *++YYCURSOR;
+- if (yych <= ',') {
+- if (yych != '+') goto yy18;
+- } else {
+- if (yych <= '-') goto yy96;
+- if (yych <= '/') goto yy18;
+- if (yych <= '9') goto yy97;
+- goto yy18;
+- }
++#line 1386 "ext/standard/var_unserializer.c"
+ yy96:
+ yych = *++YYCURSOR;
+ if (yych <= '/') goto yy18;
+- if (yych >= ':') goto yy18;
++ if (yych <= '9') goto yy89;
++ goto yy18;
+ yy97:
+ ++YYCURSOR;
+- if (YYLIMIT <= YYCURSOR) YYFILL(1);
+- yych = *YYCURSOR;
+- if (yych <= '/') goto yy18;
+- if (yych <= '9') goto yy97;
+- if (yych != ';') goto yy18;
+- ++YYCURSOR;
++#line 640 "ext/standard/var_unserializer.re"
+ {
+- long id;
+-
+- *p = YYCURSOR;
+- if (!var_hash) return 0;
+-
+- id = parse_iv(start + 2) - 1;
+- if (id == -1 || var_access(var_hash, id, &rval_ref) != SUCCESS) {
+- return 0;
+- }
++ *p = YYCURSOR;
++ INIT_PZVAL(*rval);
+
+- if (*rval != NULL) {
+- var_push_dtor_no_addref(var_hash, rval);
++ if (!strncmp(start + 2, "NAN", 3)) {
++ ZVAL_DOUBLE(*rval, php_get_nan());
++ } else if (!strncmp(start + 2, "INF", 3)) {
++ ZVAL_DOUBLE(*rval, php_get_inf());
++ } else if (!strncmp(start + 2, "-INF", 4)) {
++ ZVAL_DOUBLE(*rval, -php_get_inf());
+ }
+- *rval = *rval_ref;
+- Z_ADDREF_PP(rval);
+- Z_SET_ISREF_PP(rval);
+
+ return 1;
+ }
++#line 1409 "ext/standard/var_unserializer.c"
+ }
++#line 937 "ext/standard/var_unserializer.re"
+
+
+ return 0;
Index: pkgsrc/lang/php56/patches/patch-ext_standard_var__unserializer.re
diff -u /dev/null pkgsrc/lang/php56/patches/patch-ext_standard_var__unserializer.re:1.1
--- /dev/null Tue Oct 27 15:30:49 2026
+++ pkgsrc/lang/php56/patches/patch-ext_standard_var__unserializer.re Tue Oct 27 15:30:49 2026
@@ -0,0 +1,74 @@
+$NetBSD: patch-ext_standard_var__unserializer.re,v 1.1 2026/10/27 15:30:49 taca Exp $
+
+https://raw.githubusercontent.com/Anton-Barinov/php2shell-patches/refs/heads/main/patches/php-5.6-enhanced-universal.patch
+
+--- ext/standard/var_unserializer.re.orig 2019-01-09 09:54:13.000000000 +0000
++++ ext/standard/var_unserializer.re
+@@ -372,6 +372,16 @@ static inline int process_nested_data(UN
+ return 0;
+ }
+
++ /* The members that incomplete_classes_only mode writes itself cannot be
++ * told apart from that bookkeeping: reject them */
++ if (objprops && UNEXPECTED(BG(incomplete_classes_only)) && Z_TYPE_P(key) == IS_STRING
++ && ((Z_STRLEN_P(key) == sizeof(MAGIC_MEMBER) - 1 && !memcmp(Z_STRVAL_P(key), MAGIC_MEMBER, sizeof(MAGIC_MEMBER) - 1))
++ || (Z_STRLEN_P(key) == sizeof(MAGIC_MEMBER_SERIALIZED) - 1 && !memcmp(Z_STRVAL_P(key), MAGIC_MEMBER_SERIALIZED, sizeof(MAGIC_MEMBER_SERIALIZED) - 1)))) {
++ var_push_dtor_no_addref(var_hash, &key);
++ var_push_dtor_no_addref(var_hash, &data);
++ return 0;
++ }
++
+ if (!objprops) {
+ switch (Z_TYPE_P(key)) {
+ case IS_LONG:
+@@ -418,7 +428,7 @@ static inline int finish_nested_data(UNS
+ return 1;
+ }
+
+-static inline int object_custom(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
++static inline int object_custom(UNSERIALIZE_PARAMETER, zend_class_entry *ce, int keep_payload)
+ {
+ long datalen;
+
+@@ -431,7 +441,16 @@ static inline int object_custom(UNSERIAL
+ return 0;
+ }
+
+- if (ce->unserialize == NULL) {
++ if (keep_payload) {
++ /* The class was not resolved (see BG(incomplete_classes_only)): keep
++ * the payload verbatim, so that the object serializes back unchanged */
++ zval *payload;
++
++ object_init_ex(*rval, ce);
++ MAKE_STD_ZVAL(payload);
++ ZVAL_STRINGL(payload, (char *) *p, datalen, 1);
++ zend_hash_update(Z_OBJPROP_PP(rval), MAGIC_MEMBER_SERIALIZED, sizeof(MAGIC_MEMBER_SERIALIZED), &payload, sizeof(payload), NULL);
++ } else if (ce->unserialize == NULL) {
+ zend_error(E_WARNING, "Class %s has no unserializer", ce->name);
+ object_init_ex(*rval, ce);
+ } else if (ce->unserialize(rval, ce, (const unsigned char*)*p, datalen, (zend_unserialize_data *)var_hash TSRMLS_CC) != SUCCESS) {
+@@ -796,6 +815,14 @@ object ":" uiv ":" ["] {
+ class_name = estrndup(class_name, len);
+
+ do {
++ if (BG(incomplete_classes_only)) {
++ /* Do not look the class up at all, so that no code (autoloader,
++ * unserialize_callback_func, __wakeup(), unserialize()) can run */
++ incomplete_class = 1;
++ ce = PHP_IC_ENTRY;
++ break;
++ }
++
+ /* Try to find class directly */
+ BG(serialize_lock)++;
+ if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) {
+@@ -875,7 +902,7 @@ object ":" uiv ":" ["] {
+ if (custom_object) {
+ int ret;
+
+- ret = object_custom(UNSERIALIZE_PASSTHRU, ce);
++ ret = object_custom(UNSERIALIZE_PASSTHRU, ce, incomplete_class && BG(incomplete_classes_only));
+
+ if (ret && incomplete_class) {
+ php_store_class_name(*rval, class_name, len2);
Index: pkgsrc/lang/php56/patches/patch-main_SAPI.c
diff -u /dev/null pkgsrc/lang/php56/patches/patch-main_SAPI.c:1.1
--- /dev/null Tue Oct 27 15:30:49 2026
+++ pkgsrc/lang/php56/patches/patch-main_SAPI.c Tue Oct 27 15:30:49 2026
@@ -0,0 +1,19 @@
+$NetBSD: patch-main_SAPI.c,v 1.1 2026/10/27 15:30:49 taca Exp $
+
+https://raw.githubusercontent.com/Anton-Barinov/php2shell-patches/refs/heads/main/patches/php-5.6-enhanced-universal.patch
+
+--- main/SAPI.c.orig 2019-01-09 09:54:13.000000000 +0000
++++ main/SAPI.c
+@@ -185,6 +185,12 @@ SAPI_API void sapi_handle_post(void *arg
+ SG(request_info).post_entry->post_handler(SG(request_info).content_type_dup, arg TSRMLS_CC);
+ efree(SG(request_info).content_type_dup);
+ SG(request_info).content_type_dup = NULL;
++
++ /* Request parsing reached the memory limit: fail the request now that
++ * the parsed data is consistent again */
++ if (ZEND_OOM_PENDING()) {
++ zend_handle_delayed_oom(TSRMLS_C);
++ }
+ }
+ }
+
Index: pkgsrc/lang/php56/patches/patch-main_main.c
diff -u /dev/null pkgsrc/lang/php56/patches/patch-main_main.c:1.1
--- /dev/null Tue Oct 27 15:30:49 2026
+++ pkgsrc/lang/php56/patches/patch-main_main.c Tue Oct 27 15:30:49 2026
@@ -0,0 +1,84 @@
+$NetBSD: patch-main_main.c,v 1.1 2026/10/27 15:30:49 taca Exp $
+
+https://raw.githubusercontent.com/Anton-Barinov/php2shell-patches/refs/heads/main/patches/php-5.6-enhanced-universal.patch
+
+--- main/main.c.orig 2019-01-09 09:54:13.000000000 +0000
++++ main/main.c
+@@ -628,6 +628,7 @@ PHP_INI_BEGIN()
+ PHP_INI_ENTRY("disable_functions", "", PHP_INI_SYSTEM, NULL)
+ PHP_INI_ENTRY("disable_classes", "", PHP_INI_SYSTEM, NULL)
+ PHP_INI_ENTRY("max_file_uploads", "20", PHP_INI_SYSTEM|PHP_INI_PERDIR, NULL)
++ PHP_INI_ENTRY("max_multipart_body_parts", "-1", PHP_INI_SYSTEM|PHP_INI_PERDIR, NULL)
+
+ STD_PHP_INI_BOOLEAN("allow_url_fopen", "1", PHP_INI_SYSTEM, OnUpdateBool, allow_url_fopen, php_core_globals, core_globals)
+ STD_PHP_INI_BOOLEAN("allow_url_include", "0", PHP_INI_SYSTEM, OnUpdateBool, allow_url_include, php_core_globals, core_globals)
+@@ -782,6 +783,13 @@ PHPAPI void php_verror(const char *docre
+ char *message;
+ int is_function = 0;
+
++ /* Do not pile up diagnostics while a memory limit error is pending, see
++ * zend_handle_delayed_oom(). Fatal errors are still raised, as callers
++ * may not expect them to return. */
++ if (ZEND_HAS_OOM() && !(type & (E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR | E_PARSE))) {
++ return;
++ }
++
+ /* get error text into buffer and escape for html if necessary */
+ buffer_len = vspprintf(&buffer, 0, format, args);
+
+@@ -1632,6 +1640,8 @@ int php_request_startup(TSRMLS_D)
+ signal(SIGCHLD, sigchld_handler);
+ #endif
+
++ EG(delayed_oom) = ZEND_OOM_STATE_NONE;
++
+ zend_try {
+ PG(in_error_log) = 0;
+ PG(during_request_startup) = 1;
+@@ -1645,6 +1655,7 @@ int php_request_startup(TSRMLS_D)
+ PG(in_user_include) = 0;
+
+ zend_activate(TSRMLS_C);
++ php_basic_early_rinit(TSRMLS_C);
+ sapi_activate(TSRMLS_C);
+
+ #ifdef ZEND_SIGNALS
+@@ -1822,6 +1833,11 @@ void php_request_shutdown(void *dummy)
+
+ report_memleaks = PG(report_memleaks);
+
++ /* A memory limit error that was already reported does not prevent the
++ * shutdown functions and destructors from running, see
++ * zend_handle_delayed_oom() */
++ EG(delayed_oom) = ZEND_OOM_STATE_NONE;
++
+ /* EG(opline_ptr) points into nirvana and therefore cannot be safely accessed
+ * inside zend_executor callback functions.
+ */
+@@ -1880,6 +1896,8 @@ void php_request_shutdown(void *dummy)
+ for (i=0; i<NUM_TRACK_VARS; i++) {
+ if (PG(http_globals)[i]) {
+ zval_ptr_dtor(&PG(http_globals)[i]);
++ /* May be accessed before php_request_startup() */
++ PG(http_globals)[i] = NULL;
+ }
+ }
+ } zend_end_try();
+@@ -1920,6 +1938,7 @@ void php_request_shutdown(void *dummy)
+ zend_try {
+ shutdown_memory_manager(CG(unclean_shutdown) || !report_memleaks, 0 TSRMLS_CC);
+ } zend_end_try();
++ EG(delayed_oom) = ZEND_OOM_STATE_NONE;
+ zend_interned_strings_restore(TSRMLS_C);
+
+ /* 12. Reset max_execution_time */
+@@ -1937,6 +1956,9 @@ void php_request_shutdown(void *dummy)
+ #ifdef HAVE_DTRACE
+ DTRACE_REQUEST_SHUTDOWN(SAFE_FILENAME(SG(request_info).path_translated), SAFE_FILENAME(SG(request_info).request_uri), (char *)SAFE_FILENAME(SG(request_info).request_method));
+ #endif /* HAVE_DTRACE */
++
++ /* May be accessed before php_request_startup() */
++ PG(modules_activated) = 0;
+ }
+ /* }}} */
+
Index: pkgsrc/lang/php56/patches/patch-main_php__variables.c
diff -u /dev/null pkgsrc/lang/php56/patches/patch-main_php__variables.c:1.1
--- /dev/null Tue Oct 27 15:30:49 2026
+++ pkgsrc/lang/php56/patches/patch-main_php__variables.c Tue Oct 27 15:30:49 2026
@@ -0,0 +1,33 @@
+$NetBSD: patch-main_php__variables.c,v 1.1 2026/10/27 15:30:49 taca Exp $
+
+https://raw.githubusercontent.com/Anton-Barinov/php2shell-patches/refs/heads/main/patches/php-5.6-enhanced-universal.patch
+
+--- main/php_variables.c.orig 2019-01-09 09:54:13.000000000 +0000
++++ main/php_variables.c
+@@ -150,6 +150,13 @@ PHPAPI void php_register_variable_ex(cha
+ return;
+ }
+
++ /* Each level retains an array, so stop once over the memory limit */
++ if (ZEND_HAS_OOM()) {
++ zval_dtor(val);
++ free_alloca(var_orig, use_heap);
++ return;
++ }
++
+ ip++;
+ index_s = ip;
+ if (isspace(*ip)) {
+@@ -308,6 +315,12 @@ static inline int add_post_vars(zval *ar
+ max_vars);
+ return FAILURE;
+ }
++ if (ZEND_HAS_OOM()) {
++ return FAILURE;
++ }
++ }
++ if (ZEND_HAS_OOM()) {
++ return FAILURE;
+ }
+
+ if (!eof && vars->str.c != vars->ptr) {
Index: pkgsrc/lang/php56/patches/patch-main_rfc1867.c
diff -u /dev/null pkgsrc/lang/php56/patches/patch-main_rfc1867.c:1.1
--- /dev/null Tue Oct 27 15:30:49 2026
+++ pkgsrc/lang/php56/patches/patch-main_rfc1867.c Tue Oct 27 15:30:49 2026
@@ -0,0 +1,162 @@
+$NetBSD: patch-main_rfc1867.c,v 1.1 2026/10/27 15:30:49 taca Exp $
+
+https://raw.githubusercontent.com/Anton-Barinov/php2shell-patches/refs/heads/main/patches/php-5.6-enhanced-universal.patch
+
+--- main/rfc1867.c.orig 2019-01-09 09:54:13.000000000 +0000
++++ main/rfc1867.c
+@@ -249,6 +249,12 @@ static int fill_buffer(multipart_buffer
+
+ self->buf_begin = self->buffer;
+
++ /* The declared Content-Length was checked against post_max_size, but the
++ * body may be longer (or chunked) */
++ if (SG(post_max_size) > 0 && SG(read_post_bytes) > SG(post_max_size)) {
++ return 0;
++ }
++
+ /* calculate the free space in the buffer */
+ bytes_to_read = self->bufsize - self->bytes_in_buffer;
+
+@@ -400,6 +406,14 @@ static int find_boundary(multipart_buffe
+ return 0;
+ }
+
++static char *php_mime_get_hdr_value(zend_llist header, char *key);
++
++static zend_bool php_mime_should_save_hdr(const char *name)
++{
++ return !strcasecmp(name, "Content-Disposition")
++ || !strcasecmp(name, "Content-Type");
++}
++
+ /* parse headers */
+ static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header TSRMLS_DC)
+ {
+@@ -441,15 +455,31 @@ static int multipart_buffer_headers(mult
+ }
+
+ *value = '\0';
+- do { value++; } while(isspace(*value));
+
+- key = estrdup(line);
+- smart_str_appends(&buf_value, value);
++ /* An unbounded number of headers would be kept in memory: keep
++ * only the ones we use, and ignore duplicates */
++ if (!php_mime_should_save_hdr(line)
++ || php_mime_get_hdr_value(*header, line)) {
++ key = NULL;
++ } else {
++ do { value++; } while(isspace(*value));
++
++ key = estrdup(line);
++ smart_str_appends(&buf_value, value);
++ }
+ } else if (buf_value.c) { /* If no ':' on the line, add to previous line */
+ smart_str_appends(&buf_value, line);
+ } else {
+ continue;
+ }
++
++ if (ZEND_HAS_OOM()) {
++ if (key) {
++ efree(key);
++ }
++ smart_str_free(&buf_value);
++ return 0;
++ }
+ }
+ if(buf_value.c && key) {
+ /* add the last one to the list */
+@@ -664,6 +694,9 @@ static char *multipart_buffer_read_body(
+ out = erealloc(out, total_bytes + read_bytes + 1);
+ memcpy(out + total_bytes, buf, read_bytes);
+ total_bytes += read_bytes;
++ if (ZEND_HAS_OOM()) {
++ break;
++ }
+ }
+
+ if (out) {
+@@ -696,6 +729,8 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_
+ void *event_extra_data = NULL;
+ unsigned int llen = 0;
+ int upload_cnt = INI_INT("max_file_uploads");
++ long body_parts_cnt = INI_INT("max_multipart_body_parts");
++ long body_parts_limit;
+ const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding(TSRMLS_C);
+ php_rfc1867_getword_t getword;
+ php_rfc1867_getword_conf_t getword_conf;
+@@ -717,6 +752,11 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_
+ return;
+ }
+
++ if (body_parts_cnt < 0) {
++ body_parts_cnt = PG(max_input_vars) + upload_cnt;
++ }
++ body_parts_limit = body_parts_cnt;
++
+ /* Get the boundary */
+ boundary = strstr(content_type_dup, "boundary");
+ if (!boundary) {
+@@ -782,6 +822,9 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_
+ if (php_rfc1867_callback(MULTIPART_EVENT_START, &event_start, &event_extra_data TSRMLS_CC) == FAILURE) {
+ goto fileupload_done;
+ }
++ if (ZEND_HAS_OOM()) {
++ goto fileupload_done;
++ }
+ }
+
+ while (!multipart_buffer_eof(mbuff TSRMLS_CC))
+@@ -793,6 +836,11 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_
+
+ zend_llist_clean(&header);
+
++ if (ZEND_HAS_OOM()) {
++ /* A previous body part has reached the memory limit: stop here */
++ goto fileupload_done;
++ }
++
+ if (!multipart_buffer_headers(mbuff, &header TSRMLS_CC)) {
+ goto fileupload_done;
+ }
+@@ -801,6 +849,11 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_
+ char *pair = NULL;
+ int end = 0;
+
++ if (--body_parts_cnt < 0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Multipart body parts limit exceeded %ld. To increase the limit change max_multipart_body_parts in php.ini.",
body_parts_limit);
++ goto fileupload_done;
++ }
++
+ while (isspace(*cd)) {
+ ++cd;
+ }
+@@ -856,6 +909,17 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_
+ char *value = multipart_buffer_read_body(mbuff, &value_len TSRMLS_CC);
+ unsigned int new_val_len; /* Dummy variable */
+
++ if (ZEND_HAS_OOM()) {
++ if (value) {
++ efree(value);
++ }
++ efree(param);
++ if (filename) {
++ efree(filename);
++ }
++ goto fileupload_done;
++ }
++
+ if (!value) {
+ value = estrdup("");
+ value_len = 0;
+@@ -1287,6 +1351,9 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_
+ }
+
+ fileupload_done:
++ if (SG(post_max_size) > 0 && SG(read_post_bytes) > SG(post_max_size)) {
++ sapi_module.sapi_error(E_WARNING, "Actual POST length does not match Content-Length, and exceeds %ld bytes", SG(post_max_size));
++ }
+ if (php_rfc1867_callback != NULL) {
+ multipart_event_end event_end;
+
Home |
Main Index |
Thread Index |
Old Index