summaryrefslogtreecommitdiff
path: root/README.PARAMETER_PARSING_API
diff options
context:
space:
mode:
authorMark A. Hershberger <mah@debian.(none)>2009-03-25 19:39:21 -0400
committerMark A. Hershberger <mah@debian.(none)>2009-03-25 19:39:21 -0400
commit6821b67124604da690c5e9276d5370d679c63ac8 (patch)
treebefb4ca2520eb577950cef6cb76d10b914cbf67a /README.PARAMETER_PARSING_API
parentcd0b49c72aee33b3e44a9c589fcd93b9e1c7a64f (diff)
downloadphp-6821b67124604da690c5e9276d5370d679c63ac8.tar.gz
Imported Upstream version 5.3.0RC1upstream/5.3.0_RC1upstream/5.3.0RC1
Diffstat (limited to 'README.PARAMETER_PARSING_API')
-rw-r--r--README.PARAMETER_PARSING_API177
1 files changed, 132 insertions, 45 deletions
diff --git a/README.PARAMETER_PARSING_API b/README.PARAMETER_PARSING_API
index 052489d24..530b2b560 100644
--- a/README.PARAMETER_PARSING_API
+++ b/README.PARAMETER_PARSING_API
@@ -31,28 +31,67 @@ resources cannot be auto-converted.
Type specifiers
---------------
- a - array
- b - boolean, stored in zend_bool
- d - double
- f - function or array containing php method call info (returned as
- zend_fcall_info* and zend_fcall_info_cache*)
- h - array (returned as HashTable*)
- l - long
- o - object (of any type)
- O - object (of specific type, specified by class entry)
- r - resource (stored in zval)
- s - string (with possible null bytes) and its length
- z - the actual zval
+ The following list shows the type specifier, its meaning and the parameter
+ types that need to be passed by address. All passed paramaters are set
+ if the PHP parameter is non optional and untouched if optional and the
+ parameter is not present. The only exception is O where the zend_class_entry*
+ has to be provided on input and is used to verify the PHP parameter is an
+ instance of that class.
+
+ a - array (zval*)
+ A - array or object (zval *)
+ b - boolean (zend_bool)
+ C - class (zend_class_entry*)
+ d - double (double)
+ f - function or array containing php method call info (returned as
+ zend_fcall_info and zend_fcall_info_cache)
+ h - array (returned as HashTable*)
+ H - array or HASH_OF(object) (returned as HashTable*)
+ l - long (long)
+ o - object of any type (zval*)
+ O - object of specific type given by class entry (zval*, zend_class_entry)
+ r - resource (zval*)
+ s - string (with possible null bytes) and its length (char*, int)
+ z - the actual zval (zval*)
+ Z - the actual zval (zval**)
+ * - variable arguments list (0 or more)
+ + - variable arguments list (1 or more)
The following characters also have a meaning in the specifier string:
- | - indicates that the remaining parameters are optional, they
- should be initialized to default values by the extension since they
- will not be touched by the parsing function if they are not
- passed to it.
- / - use SEPARATE_ZVAL_IF_NOT_REF() on the parameter it follows
- ! - the parameter it follows can be of specified type or NULL (only applies
- to 's', 'a', 'o', 'O', 'r', 'h', 'C', 'z', and 'Z'). If NULL is passed,
- the results pointer is set to NULL as well.
+ | - indicates that the remaining parameters are optional, they
+ should be initialized to default values by the extension since they
+ will not be touched by the parsing function if they are not
+ passed to it.
+ / - use SEPARATE_ZVAL_IF_NOT_REF() on the parameter it follows
+ ! - the parameter it follows can be of specified type or NULL (applies
+ to all specifiers except for 'b', 'l', and 'd'). If NULL is passed, the
+ results pointer is set to NULL as well.
+
+
+Note on 64bit compatibility
+---------------------------
+Please do not forget that int and long are two different things on 64bit
+OSes (int is 4 bytes and long is 8 bytes), so make sure you pass longs to "l"
+and ints to strings length (i.e. for "s" you need to pass char * and int),
+not the other way round!
+Remember: "l" is the only case when you need to pass long (and that's why
+it's "l", not "i" btw).
+
+Both mistakes cause memory corruptions and segfaults on 64bit OSes:
+1)
+ char *str;
+ long str_len; /* XXX THIS IS WRONG!! Use int instead. */
+ zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len)
+
+2)
+ int num; /* XXX THIS IS WRONG!! Use long instead. */
+ zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &num)
+
+If you're in doubt, use check_parameters.php script to the parameters
+and their types (it can be found in ./scripts/dev/ directory of PHP sources):
+
+# php ./scripts/dev/check_parameters.php /path/to/your/sources/
+
Examples
--------
@@ -62,8 +101,8 @@ char *s;
int s_len;
zval *param;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lsz",
- &l, &s, &s_len, &param) == FAILURE) {
- return;
+ &l, &s, &s_len, &param) == FAILURE) {
+ return;
}
@@ -72,8 +111,8 @@ zval *obj;
double d = 0.5;
zend_class_entry *my_ce;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|d",
- &obj, my_ce, &d) == FAILURE) {
- return;
+ &obj, my_ce, &d) == FAILURE) {
+ return;
}
@@ -82,29 +121,18 @@ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|d",
zval *obj;
zval *arr;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o!a",
- &obj, &arr) == FAILURE) {
- return;
+ &obj, &arr) == FAILURE) {
+ return;
}
/* Gets a separated array which can also be null. */
zval *arr;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/!",
- &arr) == FAILURE) {
- return;
-}
-
-
-/* Get only the first three parameters (useful for varargs functions). */
-zval *z;
-zend_bool b;
-zval *r;
-if (zend_parse_parameters(3 TSRMLS_CC, "zbr!",
- &z, &b, &r) == FAILURE) {
- return;
+ &arr) == FAILURE) {
+ return;
}
-
/* Get either a set of 3 longs or a string. */
long l1, l2, l3;
char *s;
@@ -118,13 +146,72 @@ char *s;
int length;
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC,
- "lll", &l1, &l2, &l3) == SUCCESS) {
- /* manipulate longs */
+ "lll", &l1, &l2, &l3) == SUCCESS) {
+ /* manipulate longs */
} else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC,
- "s", &s, &length) == SUCCESS) {
- /* manipulate string */
+ "s", &s, &length) == SUCCESS) {
+ /* manipulate string */
} else {
- /* output error */
+ /* output error */
+
+ return;
+}
+
+
+/* Function that accepts only varargs (0 or more) */
- return;
+int i, num_varargs;
+zval ***varargs = NULL;
+
+
+if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "*", &varargs, &num_varargs) == FAILURE) {
+ return;
}
+
+for (i = 0; i < num_varargs; i++) {
+ /* do something with varargs[i] */
+}
+
+if (varargs) {
+ efree(varargs);
+}
+
+
+/* Function that accepts a string, followed by varargs (1 or more) */
+
+char *str;
+int str_len;
+int i, num_varargs;
+zval ***varargs = NULL;
+
+if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s+", &str, &str_len, &varargs, &num_varargs) == FAILURE) {
+ return;
+}
+
+for (i = 0; i < num_varargs; i++) {
+ /* do something with varargs[i] */
+}
+
+if (varargs) {
+ efree(varargs);
+}
+
+
+/* Function that takes an array, followed by varargs, and ending with a long */
+long num;
+zval *array;
+int i, num_varargs;
+zval ***varargs = NULL;
+
+if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a*l", &array, &varargs, &num_varargs, &num) == FAILURE) {
+ return;
+}
+
+for (i = 0; i < num_varargs; i++) {
+ /* do something with varargs[i] */
+}
+
+if (varargs) {
+ efree(varargs);
+}
+