Skip to content

Commit e45b54a

Browse files
committed
Rename macro GetMysql2Result to GET_RESULT
Switch from DATA_PTR to Data_Get_Struct. This protects against calling methods that need the result wrapper on hand-built Mysql2::Result objects. They will raise a TypeError instead of segfaulting.
1 parent 18d988a commit e45b54a

File tree

3 files changed

+20
-19
lines changed

3 files changed

+20
-19
lines changed

ext/mysql2/result.c

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ static rb_encoding *binaryEncoding;
5050
#define MYSQL2_MIN_TIME 62171150401ULL
5151
#endif
5252

53+
#define GET_RESULT(obj) \
54+
mysql2_result_wrapper *wrapper; \
55+
Data_Get_Struct(self, mysql2_result_wrapper, wrapper);
56+
5357
typedef struct {
5458
int symbolizeKeys;
5559
int asArray;
@@ -141,9 +145,8 @@ static void *nogvl_stmt_fetch(void *ptr) {
141145

142146

143147
static VALUE rb_mysql_result_fetch_field(VALUE self, unsigned int idx, short int symbolize_keys) {
144-
mysql2_result_wrapper * wrapper;
145148
VALUE rb_field;
146-
GetMysql2Result(self, wrapper);
149+
GET_RESULT(self);
147150

148151
if (wrapper->fields == Qnil) {
149152
wrapper->numberOfFields = mysql_num_fields(wrapper->result);
@@ -231,8 +234,7 @@ static unsigned int msec_char_to_uint(char *msec_char, size_t len)
231234

232235
static void rb_mysql_result_alloc_result_buffers(VALUE self, MYSQL_FIELD *fields) {
233236
unsigned int i;
234-
mysql2_result_wrapper * wrapper;
235-
GetMysql2Result(self, wrapper);
237+
GET_RESULT(self);
236238

237239
if (wrapper->result_buffers != NULL) return;
238240

@@ -309,14 +311,13 @@ static void rb_mysql_result_alloc_result_buffers(VALUE self, MYSQL_FIELD *fields
309311
static VALUE rb_mysql_result_fetch_row_stmt(VALUE self, MYSQL_FIELD * fields, const result_each_args *args)
310312
{
311313
VALUE rowVal;
312-
mysql2_result_wrapper *wrapper;
313314
unsigned int i = 0;
314315

315316
#ifdef HAVE_RUBY_ENCODING_H
316317
rb_encoding *default_internal_enc;
317318
rb_encoding *conn_enc;
318319
#endif
319-
GetMysql2Result(self, wrapper);
320+
GET_RESULT(self);
320321

321322
#ifdef HAVE_RUBY_ENCODING_H
322323
default_internal_enc = rb_default_internal_encoding();
@@ -509,7 +510,6 @@ static VALUE rb_mysql_result_fetch_row_stmt(VALUE self, MYSQL_FIELD * fields, co
509510
static VALUE rb_mysql_result_fetch_row(VALUE self, MYSQL_FIELD * fields, const result_each_args *args)
510511
{
511512
VALUE rowVal;
512-
mysql2_result_wrapper * wrapper;
513513
MYSQL_ROW row;
514514
unsigned int i = 0;
515515
unsigned long * fieldLengths;
@@ -518,7 +518,7 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, MYSQL_FIELD * fields, const r
518518
rb_encoding *default_internal_enc;
519519
rb_encoding *conn_enc;
520520
#endif
521-
GetMysql2Result(self, wrapper);
521+
GET_RESULT(self);
522522

523523
#ifdef HAVE_RUBY_ENCODING_H
524524
default_internal_enc = rb_default_internal_encoding();
@@ -729,12 +729,11 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, MYSQL_FIELD * fields, const r
729729
}
730730

731731
static VALUE rb_mysql_result_fetch_fields(VALUE self) {
732-
mysql2_result_wrapper * wrapper;
733732
unsigned int i = 0;
734733
short int symbolizeKeys = 0;
735734
VALUE defaults;
736735

737-
GetMysql2Result(self, wrapper);
736+
GET_RESULT(self);
738737

739738
defaults = rb_iv_get(self, "@query_options");
740739
Check_Type(defaults, T_HASH);
@@ -760,12 +759,11 @@ static VALUE rb_mysql_result_each_(VALUE self,
760759
VALUE(*fetch_row_func)(VALUE, MYSQL_FIELD *fields, const result_each_args *args),
761760
const result_each_args *args)
762761
{
763-
mysql2_result_wrapper *wrapper;
764762
unsigned long i;
765763
const char *errstr;
766764
MYSQL_FIELD *fields = NULL;
767765

768-
GetMysql2Result(self, wrapper);
766+
GET_RESULT(self);
769767

770768
if (wrapper->is_streaming) {
771769
/* When streaming, we will only yield rows, not return them. */
@@ -850,10 +848,9 @@ static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
850848
result_each_args args;
851849
VALUE defaults, opts, block, (*fetch_row_func)(VALUE, MYSQL_FIELD *fields, const result_each_args *args);
852850
ID db_timezone, app_timezone, dbTz, appTz;
853-
mysql2_result_wrapper * wrapper;
854851
int symbolizeKeys, asArray, castBool, cacheRows, cast;
855852

856-
GetMysql2Result(self, wrapper);
853+
GET_RESULT(self);
857854

858855
defaults = rb_iv_get(self, "@query_options");
859856
Check_Type(defaults, T_HASH);
@@ -931,9 +928,8 @@ static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
931928
}
932929

933930
static VALUE rb_mysql_result_count(VALUE self) {
934-
mysql2_result_wrapper *wrapper;
931+
GET_RESULT(self);
935932

936-
GetMysql2Result(self, wrapper);
937933
if (wrapper->is_streaming) {
938934
/* This is an unsigned long per result.h */
939935
return ULONG2NUM(wrapper->numberOfRows);
@@ -957,7 +953,6 @@ VALUE rb_mysql_result_to_obj(VALUE client, VALUE encoding, VALUE options, MYSQL_
957953
VALUE obj;
958954
mysql2_result_wrapper * wrapper;
959955

960-
961956
obj = Data_Make_Struct(cMysql2Result, mysql2_result_wrapper, rb_mysql_result_mark, rb_mysql_result_free, wrapper);
962957
wrapper->numberOfFields = 0;
963958
wrapper->numberOfRows = 0;

ext/mysql2/result.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,4 @@ typedef struct {
2525
unsigned long *length;
2626
} mysql2_result_wrapper;
2727

28-
#define GetMysql2Result(obj, sval) (sval = (mysql2_result_wrapper*)DATA_PTR(obj));
29-
3028
#endif

spec/mysql2/result_spec.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@
66
@result = @client.query "SELECT 1"
77
end
88

9+
it "should raise a TypeError exception when it doesn't wrap a result set" do
10+
r = Mysql2::Result.new
11+
expect { r.count }.to raise_error(TypeError)
12+
expect { r.fields }.to raise_error(TypeError)
13+
expect { r.size }.to raise_error(TypeError)
14+
expect { r.each }.to raise_error(TypeError)
15+
end
16+
917
it "should have included Enumerable" do
1018
expect(Mysql2::Result.ancestors.include?(Enumerable)).to be true
1119
end

0 commit comments

Comments
 (0)