cvs: php-src(PHP_4_3) /ext/standard var_unserializer.re
| From: | Marcus Boerger | Date: | Fri, 24 Sep 2004 21:56:59 +0000 |
| Subject: | cvs: php-src(PHP_4_3) /ext/standard var_unserializer.re | ||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-28750@lists.php.net to get a copy of this message | ||
helly Fri Sep 24 17:56:59 2004 EDT
Modified files: (Branch: PHP_4_3)
/php-src/ext/standard var_unserializer.re
Log:
- MFH Several serialize/unserialize fixes
# first commit .re
http://cvs.php.net/diff.php/php-src/ext/standard/var_unserializer.re?r1=1.11.4.3&r2=1.11.4.4&ty=u
Index: php-src/ext/standard/var_unserializer.re
diff -u php-src/ext/standard/var_unserializer.re:1.11.4.3
php-src/ext/standard/var_unserializer.re:1.11.4.4
--- php-src/ext/standard/var_unserializer.re:1.11.4.3 Fri Mar 26 20:17:06 2004
+++ php-src/ext/standard/var_unserializer.re Fri Sep 24 17:56:59 2004
@@ -1,3 +1,22 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 4 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2003 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 2.02 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available at through the world-wide-web at |
+ | http://www.php.net/license/2_02.txt.
|
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Sascha Schumann <sascha@schumann.cx> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: var_unserializer.re,v 1.11.4.4 2004/09/24 21:56:59 helly Exp $ */
#include "php.h"
#include "ext/standard/php_var.h"
@@ -100,7 +119,7 @@
-static inline int parse_iv2(const char *p, const char **q)
+static inline int parse_iv2(const unsigned char *p, const unsigned char **q)
{
char cursor;
int result = 0;
@@ -115,7 +134,7 @@
}
while (1) {
- cursor = *p;
+ cursor = (char)*p;
if (cursor >= '0' && cursor <= '9') {
result = result * 10 + cursor - '0';
} else {
@@ -128,12 +147,34 @@
return result;
}
-static inline int parse_iv(const char *p)
+static inline int parse_iv(const unsigned char *p)
{
return parse_iv2(p, NULL);
}
-#define UNSERIALIZE_PARAMETER zval **rval, const char **p, const char *max, php_unserialize_data_t
*var_hash TSRMLS_DC
+/* no need to check for length - re2c already did */
+static inline size_t parse_uiv(const unsigned char *p)
+{
+ unsigned char cursor;
+ size_t result = 0;
+
+ if (*p == '+') {
+ p++;
+ }
+
+ while (1) {
+ cursor = *p;
+ if (cursor >= '0' && cursor <= '9') {
+ result = result * 10 + (size_t)(cursor - (unsigned char)'0');
+ } else {
+ break;
+ }
+ p++;
+ }
+ return result;
+}
+
+#define UNSERIALIZE_PARAMETER zval **rval, const unsigned char **p, const unsigned char *max,
php_unserialize_data_t *var_hash TSRMLS_DC
#define UNSERIALIZE_PASSTHRU rval, p, max, var_hash TSRMLS_CC
static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, int elements)
@@ -149,6 +190,12 @@
return 0;
}
+ if (Z_TYPE_P(key) != IS_LONG && Z_TYPE_P(key) != IS_STRING) {
+ zval_dtor(key);
+ FREE_ZVAL(key);
+ return 0;
+ }
+
ALLOC_INIT_ZVAL(data);
if (!php_var_unserialize(&data, p, max, var_hash TSRMLS_CC)) {
@@ -166,11 +213,15 @@
case IS_STRING:
zend_hash_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &data, sizeof(data), NULL);
break;
-
}
zval_dtor(key);
FREE_ZVAL(key);
+
+ if (elements && *(*p-1) != ';' && *(*p-1) != '}') {
+ (*p)--;
+ return 0;
+ }
}
return 1;
@@ -219,6 +270,20 @@
}
+static char *str_tolower_copy(char *dest, const char *source, unsigned int length)
+{
+ register unsigned char *str = (unsigned char*)source;
+ register unsigned char *result = (unsigned char*)dest;
+ register unsigned char *end = str + length;
+
+ while (str < end) {
+ *result++ = tolower((int)*str++);
+ }
+ *result = *end;
+
+ return dest;
+}
+
PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
{
const unsigned char *cursor, *limit, *marker, *start;
@@ -247,7 +312,9 @@
return 0;
}
+ if (*rval != NULL) {
zval_ptr_dtor(rval);
+ }
*rval = *rval_ref;
(*rval)->refcount++;
(*rval)->is_ref = 1;
@@ -262,7 +329,7 @@
return 1;
}
-"b:" iv ";" {
+"b:" [01] ";" {
*p = YYCURSOR;
INIT_PZVAL(*rval);
ZVAL_BOOL(*rval, parse_iv(start + 2));
@@ -301,22 +368,30 @@
}
"s:" uiv ":" ["] {
- int len;
+ size_t len, maxlen;
char *str;
- len = parse_iv(start + 2);
+ len = parse_uiv(start + 2);
+ maxlen = max - YYCURSOR;
+ if (maxlen < len) {
+ *p = start + 2;
+ return 0;
+ }
+
+ str = (char*)YYCURSOR;
- if (len == 0) {
- str = empty_string;
- } else {
- str = estrndup(YYCURSOR, len);
+ YYCURSOR += len;
+
+ if (*(YYCURSOR) != '"') {
+ *p = YYCURSOR;
+ return 0;
}
- YYCURSOR += len + 2;
+ YYCURSOR += 2;
*p = YYCURSOR;
INIT_PZVAL(*rval);
- ZVAL_STRINGL(*rval, str, len, 0);
+ ZVAL_STRINGL(*rval, str, len, 1);
return 1;
}
@@ -347,9 +422,8 @@
}
"O:" uiv ":" ["] {
- int len;
+ size_t len, len2, maxlen;
int elements;
- int len2;
char *class_name;
zend_class_entry *ce;
int incomplete_class = 0;
@@ -360,20 +434,30 @@
zval *arg_func_name;
INIT_PZVAL(*rval);
- len2 = len = parse_iv(start + 2);
- if (len == 0)
+ len2 = len = parse_uiv(start + 2);
+ maxlen = max - YYCURSOR;
+ if (maxlen < len || len == 0) {
+ *p = start + 2;
return 0;
+ }
+
+ class_name = (char*)YYCURSOR;
- class_name = estrndup(YYCURSOR, len);
YYCURSOR += len;
- while (len-- > 0) {
- if (class_name[len] >= 'A' && class_name[len] <= 'Z') {
- class_name[len] = class_name[len] - 'A' + 'a';
- }
+ if (*(YYCURSOR) != '"') {
+ *p = YYCURSOR;
+ return 0;
}
-
- if (zend_hash_find(CG(class_table), class_name, len2 + 1, (void **) &ce) != SUCCESS) {
+ if (*(YYCURSOR+1) != ':') {
+ *p = YYCURSOR+1;
+ return 0;
+ }
+
+ class_name = str_tolower_copy((char *)emalloc(len+1), class_name, len);
+ class_name[len] = '\0';
+
+ if (zend_hash_find(CG(class_table), class_name, len + 1, (void **) &ce) != SUCCESS) {
if ((PG(unserialize_callback_func) == NULL) || (PG(unserialize_callback_func)[0] ==
'\0')) {
incomplete_class = 1;
ce = PHP_IC_ENTRY;
@@ -390,7 +474,7 @@
incomplete_class = 1;
ce = PHP_IC_ENTRY;
} else {
- if (zend_hash_find(CG(class_table), class_name, len2 + 1, (void **) &ce) != SUCCESS) {
+ if (zend_hash_find(CG(class_table), class_name, len + 1, (void **) &ce) != SUCCESS) {
zend_error(E_WARNING, "'unserialize_callback_func' (%s) hasn't defined the
class it was called for", user_func->value.str.val);
incomplete_class = 1;
ce = PHP_IC_ENTRY;
@@ -398,7 +482,6 @@
#ifdef ZEND_ENGINE_2
ce = *(zend_class_entry **)ce; /* Bad hack, TBF! */
#endif
- efree(class_name);
}
}
}
@@ -406,7 +489,6 @@
#ifdef ZEND_ENGINE_2
ce = *(zend_class_entry **)ce; /* Bad hack, TBF! */
#endif
- efree(class_name);
}
*p = YYCURSOR;
@@ -414,15 +496,15 @@
if (incomplete_class) {
php_store_class_name(*rval, class_name, len2 TSRMLS_CC);
- efree(class_name);
}
+ efree(class_name);
return object_common2(UNSERIALIZE_PASSTHRU, elements);
}
"}" {
/* this is the case where we have less data than planned */
- zend_error(E_NOTICE, "Unexpected end of serialized data");
+ 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? */
}