Bug #42276 mysql_stmt_bind_result should be not assert with bad MYSQL_BIND

Submitted: 22 Jan 2009 19:22 Modified: 5 Nov 2009 0:28
Reporter: Jeremy Cole (Basic Quality Contributor) (OCA) Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: C API (client library) Severity:S3 (Non-critical)
Version:5.0.75, 4.1, 5.0, 5.1, 6.0 bzr OS:Any
Assigned to: CPU Architecture:Any
Tags: assert, C API, mysql_bind, mysql_stmt_bind_result, prepared statement, qc

[22 Jan 2009 19:22] Jeremy Cole
Description:
The MySQL C API behaves quite poorly with badly behaved prepared statement code.  Isn't it possible to issue an error message rather than a DBUG_ASSERT in a debug library (or ignoring the condition in a release build)?

From libmysql.c, in setup_one_fetch_function as called by mysql_stmt_bind_result:

  case MYSQL_TYPE_TINY_BLOB:
  case MYSQL_TYPE_MEDIUM_BLOB:
  case MYSQL_TYPE_LONG_BLOB:
  case MYSQL_TYPE_BLOB:
  case MYSQL_TYPE_BIT:
    DBUG_ASSERT(param->buffer_length != 0);
    param->fetch_result= fetch_result_bin;
    break;
  case MYSQL_TYPE_VAR_STRING:
  case MYSQL_TYPE_STRING:
  case MYSQL_TYPE_DECIMAL:
  case MYSQL_TYPE_NEWDECIMAL:
  case MYSQL_TYPE_NEWDATE:
    DBUG_ASSERT(param->buffer_length != 0);
    param->fetch_result= fetch_result_str;
    break;

How to repeat:
Pass a 0 as param->buffer_length for one of the MYSQL_TYPE_* fields as above.

Suggested fix:
Return some reasonable error/failure case for all errors in the C API.  Why should we ever assert() or ignore an error condition *deep* inside someone else's code?
[22 Jan 2009 21:01] Sveta Smirnova
Thank you for the report.

Verified as described.
[22 Jan 2009 21:05] Sveta Smirnova
Test used to verify:

#include "mysql.h"
#include <stdio.h>
#include <strings.h>

int main()
{
  MYSQL *mysql;
  char out[10];
  int len;
  int OK;
  char *query;
  MYSQL_ROW row;
  MYSQL_RES *result;
  
  MYSQL_STMT    *stmt;
  MYSQL_BIND    bind[1];

  mysql= mysql_init(NULL);
  mysql= mysql_real_connect(mysql, "127.0.0.1", "root", "", "test", 4040, NULL, 0);

  query = "select 'foo'";

  stmt = mysql_stmt_init(mysql);

  OK = mysql_stmt_prepare(stmt, query, strlen(query));
  
  OK = mysql_stmt_execute(stmt);
  
  memset(bind, 0, sizeof(bind));
 
  bind[0].buffer_type= MYSQL_TYPE_STRING;
  bind[0].buffer= (void*) "some";
  bind[0].is_null= 0;
  bind[0].length= 0;

  OK = mysql_stmt_bind_result(stmt, bind);

  mysql_stmt_close(stmt);

  mysql_close(mysql);

  return 0;
}
[4 Nov 2009 19:03] Byron Campen
I am not convinced that this is an error at all; setting a buffer_length to 0 will cause MYSQL_DATA_TRUNCATED to be returned when mysql_stmt_fetch is called, allowing the caller to determine the needed buffer length. (ie; this can be used as a "peek" operation to determine how large a buffer to create)
[5 Nov 2009 0:28] Jeremy Cole
Hi Byron,

The point is that a reasonable error is NOT returned when using a debug library, instead the library asserts, which means that the user's program loses control.

Regards,

Jeremy

Portions of this website are copyright © 2001, 2002 The PHP Group

Page generated in 0.039 sec. using MySQL 8.4.7-u6-cloud

Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the respective copyright holders.
It is not reviewed in advance by Oracle and does not necessarily represent the opinion of Oracle or any other party.