-
Notifications
You must be signed in to change notification settings - Fork 7.8k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Replace zend_object object with its header to prevent the "using flexible array in the middle of another struct" problem in its inheritted classes (static analyzer report) #17598
Comments
Hmm, as of PHP 7.0.0, |
php-src/Zend/zend_object_handlers.h Line 206 in b14469b
Appears to be somewhat outdated. |
Should we make changes to them? Or are they left for compatibility with the old code? |
Well, the comment should probably be updated, and the struct layouts should be changed. |
I am not very familiar with the code base. I can draft patches for them but I still need other developers to help me to prevent possible mistakes. I will try to resolve one of them in recent days and open a PR. Thank you for your replies. |
See the following for a yet incomplete patch for com_saproxy`(ignore the changes to build.ninja): ext/com_dotnet/com_saproxy.c | 19 ++++++++++++-------
win32/build/build.ninja | 2 +-
2 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/ext/com_dotnet/com_saproxy.c b/ext/com_dotnet/com_saproxy.c
index ea0e9e47a1..3e12d695fe 100644
--- a/ext/com_dotnet/com_saproxy.c
+++ b/ext/com_dotnet/com_saproxy.c
@@ -33,7 +33,6 @@
#include "Zend/zend_exceptions.h"
typedef struct {
- zend_object std;
/* the object we a proxying for; we hold a refcount to it */
php_com_dotnet_object *obj;
@@ -42,7 +41,7 @@ typedef struct {
/* this is an array whose size_is(dimensions) */
zval *indices;
-
+ zend_object std;
} php_com_saproxy;
typedef struct {
@@ -55,13 +54,19 @@ typedef struct {
LONG *indices;
} php_com_saproxy_iter;
-#define SA_FETCH(zv) (php_com_saproxy*)Z_OBJ_P(zv)
+static inline php_com_saproxy *php_com_saproxy_from_obj(zend_object *obj) {
+ return (php_com_saproxy *) ((char *) obj - XtOffsetOf(php_com_saproxy, std));
+}
+
+#define SA_FETCH(zv) php_com_saproxy_from_obj(Z_OBJ_P(zv))
zend_object *php_com_saproxy_create_object(zend_class_entry *class_type)
{
- php_com_saproxy *intern = emalloc(sizeof(*intern));
- memset(intern, 0, sizeof(*intern));
+ size_t block_len = sizeof(php_com_saproxy) + zend_object_properties_size(class_type);
+ php_com_saproxy *intern = emalloc(block_len);
+ memset(intern, 0, block_len);
zend_object_std_init(&intern->std, class_type);
+ object_properties_init(&intern->std, class_type);
return &intern->std;
}
@@ -364,7 +369,7 @@ static zend_result saproxy_count_elements(zend_object *object, zend_long *count)
static void saproxy_free_storage(zend_object *object)
{
- php_com_saproxy *proxy = (php_com_saproxy *)object;
+ php_com_saproxy *proxy = php_com_saproxy_from_obj(object);
//??? int i;
//???
//??? for (i = 0; i < proxy->dimensions; i++) {
@@ -398,7 +403,7 @@ static zend_object* saproxy_clone(zend_object *object)
}
zend_object_handlers php_com_saproxy_handlers = {
- 0,
+ XtOffsetOf(php_com_saproxy, std),
saproxy_free_storage,
zend_objects_destroy_object,
saproxy_clone,
diff --git a/win32/build/build.ninja b/win32/build/build.ninja
index 71db89e375..45580ce028 100644
--- a/win32/build/build.ninja
+++ b/win32/build/build.ninja
@@ -23,7 +23,7 @@ PGOMGR="${PGOMGR}"
PHP_BUILD=${PHP_BUILD}
# See https://ninja-build.org/manual.html#_deps
-# msvc_deps_prefix = Hinweis: Einlesen der Datei:
+msvc_deps_prefix = Hinweis: Einlesen der Datei:
MCFILE=${BUILD_DIR}\wsyslog.rc |
See phpGH-17598 for more details
I've submitted #17606 for the |
To make it clear, I added checkboxes to each case to be fixed. |
I am working on |
As of PHP 7 [1] the `std` should be at the end of the struct instead of at the beginning. See GH-17598 for more UB related details. [1] https://www.npopov.com/2015/06/19/Internal-value-representation-in-PHP-7-part-2.html#objects-in-php-7
@cmb69 I tried to make a change to zend_generator (Snape3058@ebe9ffc). However. it seems that the generators returned from a function (related to execute_data) cannot be addressed correctly after the change. Could you please help me with this patch? Where can I find the places creating and assigning the return values? |
@Snape3058, |
@cmb69 The current version (Snape3058@ebe9ffc) contains the changes to all cases that I can find. But it cannot pass the test cases. Is it OK to draft a PR now? |
Yes, sure. :) |
I don't think tackling the Zend or Opcache ones is the easiest first step. Fixing the ext/intl are probably the easiest. |
I thought we had the zend_object on purpose as the first member on those classes which don't use properties. IIRC it was worth the extra 8 bytes allocated. |
Hmm, possibly. I always thought that the layout change has just been missed for com_dotnet (like a lot of other improvements). If we want to stick with the order, we should at least document that (including a comment in the respective code). |
Class
zend_object
is defined as a flexible array of length 1. The flexible array defined with size 1 and 0 is not the standard behavior. It is suggested to use the unsized definition (https://people.kernel.org/kees/bounded-flexible-arrays-in-c). Besides, not all its subclasses will use the array fieldproperties_table
of thezend_object
class. If I understand the code correctly, when theproperties_table[0]
field is not used, it will store a ZVAL_UNDEF zval indicating the end of the iteration. Whereas when theproperties_table[0]
field is used, the flags and array length are checked first before accessing the data in the array.If the
properties_table[0]
field is not used in these sub-classes, will it be better to replace thezend_object
in these classes with only the header part ofzend_object
?i.e. (as suggested in case 2 of https://lpc.events/event/18/contributions/1722/attachments/1591/3303/Wfamnae_lpceu2024.pdf)
We can define another struct with only the header part (let's name it
zend_object_header_part
), but leave thezend_object
struct with both the header and the flexible array part.When only the header is needed, we can use the
zend_object_header_part
(e.g. in the class inheritance), whereas for those requiring the array part, or using the object through azend_object
pointer, we can still use the full definition.Usages of
zend_object
in the middle of other structs whose array field is potentially never used through the composite struct:php-src/Zend/zend_generators.h
Lines 58 to 59 in c2fddac
php-src/Zend/zend_interfaces.c
Lines 490 to 491 in c2fddac
php-src/Zend/zend_closures.c
Lines 31 to 32 in c2fddac
php-src/Zend/zend_fibers.h
Lines 102 to 104 in c2fddac
php-src/Zend/zend_iterators.h
Lines 64 to 65 in c2fddac
php-src/ext/opcache/jit/zend_jit_ir.c
Lines 8451 to 8452 in c2fddac
php-src/ext/com_dotnet/com_saproxy.c
Lines 35 to 36 in c2fddac
php-src/ext/com_dotnet/php_com_dotnet_internal.h
Lines 28 to 29 in c2fddac
php-src/ext/com_dotnet/com_persist.c
Lines 278 to 279 in c2fddac
php-src/ext/ffi/ffi.c
Lines 169 to 170 in c2fddac
php-src/ext/ffi/ffi.c
Lines 191 to 192 in c2fddac
php-src/ext/ffi/ffi.c
Lines 199 to 200 in c2fddac
php-src/ext/pdo/php_pdo_driver.h
Lines 645 to 646 in c2fddac
php-src/ext/zend_test/fiber.h
Lines 24 to 25 in c2fddac
php-src/ext/intl/normalizer/normalizer_class.h
Lines 25 to 26 in c2fddac
php-src/ext/intl/locale/locale_class.h
Lines 25 to 26 in c2fddac
report ids: 250106-1639:1-6,8-17 (16 reports in total)
The text was updated successfully, but these errors were encountered: