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/mysql | ahristov | 12 Jul |