List:Commits« Previous MessageNext Message »
From:ahristov Date:July 12 2007 2:42pm
Subject:PHP mysqlnd svn commit: r735 - in trunk: mysqlnd tests/ext/mysql
View as plain text  
Author: ahristov
Date: 2007-07-12 16:42:24 +0200 (Thu, 12 Jul 2007)
New Revision: 735

Modified:
   trunk/mysqlnd/mysqlnd_result_meta.c
   trunk/mysqlnd/mysqlnd_wireprotocol.c
   trunk/mysqlnd/mysqlnd_wireprotocol.h
   trunk/mysqlnd/portability.h
   trunk/tests/ext/mysql/mysql_query.phpt
Log:
Fix crash and possible crashes in metadata cloning.
Added output to mysql_result.phpt which is needed after the
new addition to the test.


Modified: trunk/mysqlnd/mysqlnd_result_meta.c
===================================================================
--- trunk/mysqlnd/mysqlnd_result_meta.c	2007-07-12 14:08:44 UTC (rev 734)
+++ trunk/mysqlnd/mysqlnd_result_meta.c	2007-07-12 14:42:24 UTC (rev 735)
@@ -271,26 +271,26 @@
 		new_fields[i].root = pemalloc(orig_fields[i].root_len, persistent);
 		memcpy(new_fields[i].root, orig_fields[i].root, new_fields[i].root_len);
 
-		if (orig_fields[i].name) {
+		if (orig_fields[i].name && orig_fields[i].name != mysqlnd_empty_string) {
 			new_fields[i].name = new_fields[i].root +
 								 (orig_fields[i].name - orig_fields[i].root);
 		}
-		if (orig_fields[i].org_name) {
+		if (orig_fields[i].org_name && orig_fields[i].org_name != mysqlnd_empty_string)
{
 			new_fields[i].org_name = new_fields[i].root +
 									 (orig_fields[i].org_name - orig_fields[i].root);
 		}
-		if (orig_fields[i].table) {
+		if (orig_fields[i].table && orig_fields[i].table != mysqlnd_empty_string) {
 			new_fields[i].table	= new_fields[i].root +
 								  (orig_fields[i].table - orig_fields[i].root);
 		}
-		if (orig_fields[i].org_table) {
+		if (orig_fields[i].org_table && orig_fields[i].org_table !=
mysqlnd_empty_string) {
 			new_fields[i].org_table	= new_fields[i].root +
 									  (orig_fields[i].org_table - orig_fields[i].root);
 		}
-		if (orig_fields[i].db) {
+		if (orig_fields[i].db && orig_fields[i].db != mysqlnd_empty_string) {
 			new_fields[i].db = new_fields[i].root + (orig_fields[i].db - orig_fields[i].root);
 		}
-		if (orig_fields[i].catalog) {
+		if (orig_fields[i].catalog && orig_fields[i].catalog != mysqlnd_empty_string) {
 			new_fields[i].catalog = new_fields[i].root + (orig_fields[i].catalog -
orig_fields[i].root);
 		}
 		/* def is not on the root, if allocated at all */

Modified: trunk/mysqlnd/mysqlnd_wireprotocol.c
===================================================================
--- trunk/mysqlnd/mysqlnd_wireprotocol.c	2007-07-12 14:08:44 UTC (rev 734)
+++ trunk/mysqlnd/mysqlnd_wireprotocol.c	2007-07-12 14:42:24 UTC (rev 735)
@@ -59,9 +59,11 @@
 
 extern mysqlnd_packet_methods packet_methods[];
 
-static const char	*unknown_sqlstate= "HY000";
+static const char *unknown_sqlstate= "HY000";
 
+char * const mysqlnd_empty_string = "";
 
+
 /* {{{ mysqlnd_command_to_text 
  */
 const char * const mysqlnd_command_to_text[COM_END] =
@@ -950,7 +952,23 @@
 }
 /* }}} */
 
+static size_t rset_field_offsets[] =
+{
+	STRUCT_OFFSET(MYSQLND_FIELD, catalog),
+	STRUCT_OFFSET(MYSQLND_FIELD, catalog_length),
+	STRUCT_OFFSET(MYSQLND_FIELD, db),
+	STRUCT_OFFSET(MYSQLND_FIELD, db_length),
+	STRUCT_OFFSET(MYSQLND_FIELD, table),
+	STRUCT_OFFSET(MYSQLND_FIELD, table_length),
+	STRUCT_OFFSET(MYSQLND_FIELD, org_table),
+	STRUCT_OFFSET(MYSQLND_FIELD, org_table_length),
+	STRUCT_OFFSET(MYSQLND_FIELD, name),
+	STRUCT_OFFSET(MYSQLND_FIELD, name_length),
+	STRUCT_OFFSET(MYSQLND_FIELD, org_name),
+	STRUCT_OFFSET(MYSQLND_FIELD, org_name_length)
+};
 
+
 /* {{{ php_mysqlnd_rset_field_read */
 static enum_func_status
 php_mysqlnd_rset_field_read(void *_packet, MYSQLND *conn TSRMLS_DC)
@@ -963,6 +981,7 @@
 	char *root_ptr;
 	size_t buf_len = conn->net.cmd_buffer.length, len, total_len = 0;
 	MYSQLND_FIELD *meta;
+	unsigned int i, field_count = sizeof(rset_field_offsets)/sizeof(size_t);
 
 	PACKET_READ_HEADER_AND_BODY(packet, conn, buf, buf_len, "field");
 
@@ -971,55 +990,24 @@
 	}
 
 	meta = packet->metadata;
-	if ((len = php_mysqlnd_net_field_length(&p)) && len != MYSQLND_NULL_LENGTH)
{
-		meta->catalog = (char *)p;
-		p += (meta->catalog_length = len);
-		total_len += len + 1;
-	} else if (len == MYSQLND_NULL_LENGTH) {
-		goto faulty_fake;
-	}
 
-	if ((len = php_mysqlnd_net_field_length(&p)) && len != MYSQLND_NULL_LENGTH)
{
-		meta->db = (char *)p;
-		p += (meta->db_length = len);
-		total_len += len + 1;
-	} else if (len == MYSQLND_NULL_LENGTH) {
-		goto faulty_fake;
+	for (i = 0; i < field_count; i += 2) {
+		switch ((len = php_mysqlnd_net_field_length(&p))) {
+			case 0:
+				*(char **)(((char*)meta) + rset_field_offsets[i]) = mysqlnd_empty_string;
+				*(unsigned int *)(((char*)meta) + rset_field_offsets[i+1]) = 0;
+				break;
+			case MYSQLND_NULL_LENGTH:
+				goto faulty_fake;
+			default:
+				*(char **)(((char *)meta) + rset_field_offsets[i]) = p;
+				*(unsigned int *)(((char*)meta) + rset_field_offsets[i+1]) = len;
+				p += len;
+				total_len += len + 1;
+				break;
+		}
 	}
 
-	if ((len = php_mysqlnd_net_field_length(&p)) && len != MYSQLND_NULL_LENGTH)
{
-		meta->table = (char *)p;
-		p += (meta->table_length = len);
-		total_len += len + 1;
-	} else if (len == MYSQLND_NULL_LENGTH) {
-		goto faulty_fake;
-	}
-
-	if ((len = php_mysqlnd_net_field_length(&p)) && len != MYSQLND_NULL_LENGTH)
{
-		meta->org_table = (char *)p;
-		p += (meta->org_table_length = len);
-		total_len += len + 1;
-	} else if (len == MYSQLND_NULL_LENGTH) {
-		goto faulty_fake;
-	}
-
-	if ((len = php_mysqlnd_net_field_length(&p)) && len != MYSQLND_NULL_LENGTH)
{
-		meta->name = (char *)p;
-		p += (meta->name_length = len);
-		total_len += len + 1;
-	} else if (len == MYSQLND_NULL_LENGTH) {
-		goto faulty_fake;
-	}
-
-	if ((len = php_mysqlnd_net_field_length(&p)) && len != MYSQLND_NULL_LENGTH)
{
-		meta->org_name = (char *)p;
-		p += (meta->org_name_length = len);
-		total_len += len + 1;
-	} else if (len == MYSQLND_NULL_LENGTH) {
-		goto faulty_fake;
-	}
-
-
 	/* 1 byte filler */
 	p++;
 
@@ -1068,41 +1056,41 @@
 	root_ptr = meta->root = emalloc(total_len);
 	meta->root_len = total_len;
 	/* Now do allocs */
-	if (meta->catalog) {
+	if (meta->catalog && meta->catalog != mysqlnd_empty_string) {
 		len = meta->catalog_length;
 		meta->catalog = memcpy(root_ptr, meta->catalog, len);
 		*(root_ptr +=len) = '\0';
 		root_ptr++;
 	}
 
-	if (meta->db) {
+	if (meta->db && meta->db != mysqlnd_empty_string) {
 		len = meta->db_length;
 		meta->db = memcpy(root_ptr, meta->db, len);
 		*(root_ptr + len) = '\0';
 	}
 
-	if (meta->table) {
+	if (meta->table && meta->table != mysqlnd_empty_string) {
 		len = meta->table_length;
 		meta->table = memcpy(root_ptr, meta->table, len);
 		*(root_ptr +=len) = '\0';
 		root_ptr++;
 	}
 
-	if (meta->org_table) {
+	if (meta->org_table && meta->org_table != mysqlnd_empty_string) {
 		len = meta->org_table_length;
 		meta->org_table = memcpy(root_ptr, meta->org_table, len);
 		*(root_ptr +=len) = '\0';
 		root_ptr++;
 	}
 
-	if (meta->name) {
+	if (meta->name && meta->name != mysqlnd_empty_string) {
 		len = meta->name_length;
 		meta->name = memcpy(root_ptr, meta->name, len);
 		*(root_ptr +=len) = '\0';
 		root_ptr++;
 	}
 
-	if (meta->org_name) {
+	if (meta->org_name && meta->org_name != mysqlnd_empty_string) {
 		len = meta->org_name_length;
 		meta->org_name = memcpy(root_ptr, meta->org_name, len);
 		*(root_ptr +=len) = '\0';

Modified: trunk/mysqlnd/mysqlnd_wireprotocol.h
===================================================================
--- trunk/mysqlnd/mysqlnd_wireprotocol.h	2007-07-12 14:08:44 UTC (rev 734)
+++ trunk/mysqlnd/mysqlnd_wireprotocol.h	2007-07-12 14:42:24 UTC (rev 735)
@@ -311,6 +311,8 @@
 unsigned long	php_mysqlnd_net_field_length(zend_uchar **packet);
 zend_uchar *	php_mysqlnd_net_store_length(zend_uchar *packet, mynd_ulonglong length);
 
+extern char * const mysqlnd_empty_string;
+
 #endif /* MYSQLND_WIREPROTOCOL_H */
 
 /*

Modified: trunk/mysqlnd/portability.h
===================================================================
--- trunk/mysqlnd/portability.h	2007-07-12 14:08:44 UTC (rev 734)
+++ trunk/mysqlnd/portability.h	2007-07-12 14:42:24 UTC (rev 735)
@@ -11,6 +11,9 @@
 
 #include <main/php_config.h>
 
+/* Comes from global.h as OFFSET, renamed to STRUCT_OFFSET */
+#define STRUCT_OFFSET(t, f)   ((size_t)(char *)&((t *)0)->f)
+
 #ifndef __attribute
 #if !defined(__GNUC__)
 #define __attribute(A)

Modified: trunk/tests/ext/mysql/mysql_query.phpt
===================================================================
--- trunk/tests/ext/mysql/mysql_query.phpt	2007-07-12 14:08:44 UTC (rev 734)
+++ trunk/tests/ext/mysql/mysql_query.phpt	2007-07-12 14:42:24 UTC (rev 735)
@@ -93,6 +93,10 @@
   ["valid"]=>
   string(30) "this is sql but with semicolon"
 }
+array(1) {
+  [""]=>
+  string(1) "a"
+}
 
 Warning: mysql_query(): %d is not a valid MySQL-Link resource in %s on line %d
 done! 
@@ -101,6 +105,10 @@
   [u"valid"]=>
   unicode(30) "this is sql but with semicolon"
 }
+array(1) {
+  [u""]=>
+  unicode(1) "a"
+}
 
 Warning: mysql_query(): %d is not a valid MySQL-Link resource in %s on line %d
 done! 

Thread
PHP mysqlnd svn commit: r735 - in trunk: mysqlnd tests/ext/mysqlahristov12 Jul