Skip to content

Commit 342d57e

Browse files
in php 5.3 environments, not all code was correctly initialized which resulted in access to uninitialized data
1 parent da37069 commit 342d57e

File tree

3 files changed

+43
-19
lines changed

3 files changed

+43
-19
lines changed

include/argument.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,16 @@ class Argument
7171
* @internal
7272
*/
7373
void fill(struct _zend_arg_info *info) const;
74+
75+
/**
76+
* Is this a required argument?
77+
* @return bool
78+
* @internal
79+
*/
80+
bool required() const
81+
{
82+
return _required;
83+
}
7484

7585
private:
7686
/**

src/callable.cpp

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -70,37 +70,50 @@ void Callable::initialize(zend_function_entry *entry, const char *classname, int
7070
entry->flags = flags;
7171

7272
// we should fill the first argument as well
73-
#if PHP_VERSION_ID >= 50400
74-
initialize((zend_internal_function_info *)entry->arg_info, classname);
75-
#endif
73+
initialize((zend_arg_info *)entry->arg_info, classname);
7674
}
7775

7876
/**
7977
* Fill a function entry
8078
* @param info Info to be filled
8179
* @param classname Optional classname
8280
*/
83-
#if PHP_VERSION_ID >= 50400
84-
void Callable::initialize(zend_internal_function_info *info, const char *classname) const
81+
void Callable::initialize(zend_arg_info *info, const char *classname) const
8582
{
83+
#if PHP_VERSION_ID >= 50400
84+
// up until php 5.3, the first info object is filled with alternative information,
85+
// later it is casted to a zend_internal_function object
86+
auto *finfo = (zend_internal_function_info *)info;
87+
8688
// fill in all the members, note that return reference is false by default,
8789
// because we do not support returning references in PHP-CPP, although Zend
8890
// engine allows it. Inside the name we hide a pointer to the current object
89-
info->_name = _ptr;
90-
info->_name_len = strlen(_ptr);
91-
info->_class_name = classname;
91+
finfo->_name = _ptr;
92+
finfo->_name_len = strlen(_ptr);
93+
finfo->_class_name = classname;
9294

9395
// number of required arguments, and the expected return type
94-
info->required_num_args = _required;
95-
info->_type_hint = (unsigned char)_return;
96+
finfo->required_num_args = _required;
97+
finfo->_type_hint = (unsigned char)_return;
9698

9799
// we do not support return-by-reference
98-
info->return_reference = false;
100+
finfo->return_reference = false;
99101

100102
// passing by reference is not used
101-
info->pass_rest_by_reference = false;
102-
}
103+
finfo->pass_rest_by_reference = false;
104+
#else
105+
// php 5.3 code
106+
info->name = nullptr;
107+
info->name_len = 0;
108+
info->class_name = nullptr;
109+
info->class_name_len = 0;
110+
info->array_type_hint = false;
111+
info->allow_null = false;
112+
info->pass_by_reference = false;
113+
info->return_reference = false;
114+
info->required_num_args = _required;
103115
#endif
116+
}
104117

105118
/**
106119
* End of namespace

src/callable.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
* Forward definitions
1313
*/
1414
struct _zend_function_entry;
15-
struct _zend_internal_function_info;
15+
struct _zend_arg_info;
1616

1717
/**
1818
* Set up namespace
@@ -36,18 +36,19 @@ class Callable
3636
_argc = arguments.size();
3737
_argv = new zend_arg_info[_argc+1];
3838

39-
// counter
39+
// the first record is initialized with information about the function,
40+
// so we skip that here
4041
int i=1;
4142

4243
// loop through the arguments
4344
for (auto it = arguments.begin(); it != arguments.end(); it++)
4445
{
46+
// increment required
47+
if (it->required()) _required++;
48+
4549
// fill the arg info
4650
it->fill(&_argv[i++]);
4751
}
48-
49-
// @todo find out number of required arguments
50-
_required = _argc;
5152
}
5253

5354
/**
@@ -106,7 +107,7 @@ class Callable
106107
* @param ns Active namespace
107108
* @param classname Optional class name
108109
*/
109-
void initialize(struct _zend_internal_function_info *info, const char *classname = nullptr) const;
110+
void initialize(struct _zend_arg_info *info, const char *classname = nullptr) const;
110111

111112

112113
protected:

0 commit comments

Comments
 (0)