mongo_ext 0.18.1 → 0.18.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +7 -13
- data/ext/cbson/cbson.c +46 -20
- data/ext/cbson/encoding_helpers.c +24 -13
- data/ext/cbson/encoding_helpers.h +8 -1
- data/ext/cbson/extconf.rb +2 -0
- data/ext/cbson/version.h +1 -1
- data/mongo-extensions.gemspec +1 -1
- metadata +6 -4
data/Rakefile
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# -*- mode: ruby; -*-
|
1
2
|
require 'rubygems'
|
2
3
|
require 'rubygems/specification'
|
3
4
|
require 'fileutils'
|
@@ -12,9 +13,6 @@ require 'rbconfig'
|
|
12
13
|
include Config
|
13
14
|
ENV['TEST_MODE'] = 'TRUE'
|
14
15
|
|
15
|
-
gem_command = "gem"
|
16
|
-
gem_command = "gem1.9" if $0.match(/1\.9$/) # use gem1.9 if we used rake1.9
|
17
|
-
|
18
16
|
desc "Test the MongoDB Ruby driver."
|
19
17
|
task :test do
|
20
18
|
puts "\nThis option has changed."
|
@@ -95,20 +93,16 @@ namespace :gem do
|
|
95
93
|
|
96
94
|
desc "Install the gem locally"
|
97
95
|
task :install do
|
98
|
-
sh
|
99
|
-
|
100
|
-
|
101
|
-
rm mongo-*.gem
|
102
|
-
EOS
|
96
|
+
sh "gem build mongo-ruby-driver.gemspec"
|
97
|
+
sh "gem install mongo-*.gem"
|
98
|
+
sh "rm mongo-*.gem"
|
103
99
|
end
|
104
100
|
|
105
101
|
desc "Install the optional c extensions"
|
106
102
|
task :install_extensions do
|
107
|
-
sh
|
108
|
-
|
109
|
-
|
110
|
-
rm mongo_ext-*.gem
|
111
|
-
EOS
|
103
|
+
sh "gem build mongo-extensions.gemspec"
|
104
|
+
sh "gem install mongo_ext-*.gem"
|
105
|
+
sh "rm mongo_ext-*.gem"
|
112
106
|
end
|
113
107
|
|
114
108
|
end
|
data/ext/cbson/cbson.c
CHANGED
@@ -51,7 +51,7 @@
|
|
51
51
|
|
52
52
|
#define SAFE_WRITE_AT_POS(buffer, position, data, size) \
|
53
53
|
if (buffer_write_at_position((buffer), (position), (data), (size)) != 0) \
|
54
|
-
rb_raise(
|
54
|
+
rb_raise(rb_eRuntimeError, "invalid write at position in buffer.c")
|
55
55
|
|
56
56
|
#define MAX_HOSTNAME_LENGTH 256
|
57
57
|
|
@@ -64,6 +64,7 @@ static VALUE RegexpOfHolding;
|
|
64
64
|
static VALUE OrderedHash;
|
65
65
|
static VALUE InvalidName;
|
66
66
|
static VALUE InvalidStringEncoding;
|
67
|
+
static VALUE InvalidDocument;
|
67
68
|
static VALUE DigestMD5;
|
68
69
|
|
69
70
|
#if HAVE_RUBY_ENCODING_H
|
@@ -71,15 +72,26 @@ static VALUE DigestMD5;
|
|
71
72
|
#define STR_NEW(p,n) rb_enc_str_new((p), (n), rb_utf8_encoding())
|
72
73
|
/* MUST call TO_UTF8 before calling write_utf8. */
|
73
74
|
#define TO_UTF8(string) rb_str_export_to_enc((string), rb_utf8_encoding())
|
74
|
-
static void write_utf8(buffer_t buffer, VALUE string) {
|
75
|
+
static void write_utf8(buffer_t buffer, VALUE string, char check_null) {
|
76
|
+
result_t status = check_string(RSTRING_PTR(string), RSTRING_LEN(string),
|
77
|
+
0, check_null);
|
78
|
+
if (status == HAS_NULL) {
|
79
|
+
buffer_free(buffer);
|
80
|
+
rb_raise(InvalidDocument, "Key names / regex patterns must not contain the NULL byte");
|
81
|
+
}
|
75
82
|
SAFE_WRITE(buffer, RSTRING_PTR(string), RSTRING_LEN(string));
|
76
83
|
}
|
77
84
|
#else
|
78
85
|
#define STR_NEW(p,n) rb_str_new((p), (n))
|
79
86
|
/* MUST call TO_UTF8 before calling write_utf8. */
|
80
87
|
#define TO_UTF8(string) (string)
|
81
|
-
static void write_utf8(buffer_t buffer, VALUE string) {
|
82
|
-
|
88
|
+
static void write_utf8(buffer_t buffer, VALUE string, char check_null) {
|
89
|
+
result_t status = check_string(RSTRING_PTR(string), RSTRING_LEN(string),
|
90
|
+
1, check_null);
|
91
|
+
if (status == HAS_NULL) {
|
92
|
+
buffer_free(buffer);
|
93
|
+
rb_raise(InvalidDocument, "Key names / regex patterns must not contain the NULL byte");
|
94
|
+
} else if (status == NOT_UTF_8) {
|
83
95
|
buffer_free(buffer);
|
84
96
|
rb_raise(InvalidStringEncoding, "String not valid UTF-8");
|
85
97
|
}
|
@@ -100,7 +112,9 @@ static void write_utf8(buffer_t buffer, VALUE string) {
|
|
100
112
|
|
101
113
|
/* TODO we ought to check that the malloc or asprintf was successful
|
102
114
|
* and raise an exception if not. */
|
103
|
-
|
115
|
+
/* TODO maybe we can use something more portable like vsnprintf instead
|
116
|
+
* of this hack. And share it with the Python extension ;) */
|
117
|
+
#ifndef HAVE_ASPRINTF
|
104
118
|
#define INT2STRING(buffer, i) \
|
105
119
|
{ \
|
106
120
|
int vslength = _scprintf("%d", i) + 1; \
|
@@ -112,9 +126,8 @@ static void write_utf8(buffer_t buffer, VALUE string) {
|
|
112
126
|
#endif
|
113
127
|
|
114
128
|
// this sucks too.
|
115
|
-
#ifndef
|
116
|
-
#define
|
117
|
-
#define RREGEXP_SRC_LEN(r) RREGEXP(r)->len
|
129
|
+
#ifndef RREGEXP_SRC
|
130
|
+
#define RREGEXP_SRC(r) rb_str_new(RREGEXP((r))->str, RREGEXP((r))->len)
|
118
131
|
#endif
|
119
132
|
|
120
133
|
static char zero = 0;
|
@@ -135,7 +148,7 @@ static VALUE pack_extra(buffer_t buffer, VALUE check_keys) {
|
|
135
148
|
static void write_name_and_type(buffer_t buffer, VALUE name, char type) {
|
136
149
|
SAFE_WRITE(buffer, &type, 1);
|
137
150
|
name = TO_UTF8(name);
|
138
|
-
write_utf8(buffer, name);
|
151
|
+
write_utf8(buffer, name, 1);
|
139
152
|
SAFE_WRITE(buffer, &zero, 1);
|
140
153
|
}
|
141
154
|
|
@@ -285,7 +298,7 @@ static int write_element_allow_id(VALUE key, VALUE value, VALUE extra, int allow
|
|
285
298
|
value = TO_UTF8(value);
|
286
299
|
length = RSTRING_LEN(value) + 1;
|
287
300
|
SAFE_WRITE(buffer, (char*)&length, 4);
|
288
|
-
write_utf8(buffer, value);
|
301
|
+
write_utf8(buffer, value, 0);
|
289
302
|
SAFE_WRITE(buffer, &zero, 1);
|
290
303
|
break;
|
291
304
|
}
|
@@ -356,6 +369,9 @@ static int write_element_allow_id(VALUE key, VALUE value, VALUE extra, int allow
|
|
356
369
|
SAFE_WRITE_AT_POS(buffer, length_location, (const char*)&obj_length, 4);
|
357
370
|
break;
|
358
371
|
}
|
372
|
+
buffer_free(buffer);
|
373
|
+
rb_raise(InvalidDocument, "Unsupported type for BSON (%d)", TYPE(value));
|
374
|
+
break;
|
359
375
|
}
|
360
376
|
case T_DATA:
|
361
377
|
{
|
@@ -371,14 +387,14 @@ static int write_element_allow_id(VALUE key, VALUE value, VALUE extra, int allow
|
|
371
387
|
}
|
372
388
|
case T_REGEXP:
|
373
389
|
{
|
374
|
-
|
375
|
-
char* pattern = (char*)RREGEXP_SRC_PTR(value);
|
390
|
+
VALUE pattern = RREGEXP_SRC(value);
|
376
391
|
long flags = RREGEXP(value)->ptr->options;
|
377
392
|
VALUE has_extra;
|
378
393
|
|
379
394
|
write_name_and_type(buffer, key, 0x0B);
|
380
395
|
|
381
|
-
|
396
|
+
pattern = TO_UTF8(pattern);
|
397
|
+
write_utf8(buffer, pattern, 1);
|
382
398
|
SAFE_WRITE(buffer, &zero, 1);
|
383
399
|
|
384
400
|
if (flags & IGNORECASE) {
|
@@ -408,7 +424,7 @@ static int write_element_allow_id(VALUE key, VALUE value, VALUE extra, int allow
|
|
408
424
|
default:
|
409
425
|
{
|
410
426
|
buffer_free(buffer);
|
411
|
-
rb_raise(
|
427
|
+
rb_raise(InvalidDocument, "Unsupported type for BSON (%d)", TYPE(value));
|
412
428
|
break;
|
413
429
|
}
|
414
430
|
}
|
@@ -455,6 +471,13 @@ static void write_doc(buffer_t buffer, VALUE hash, VALUE check_keys) {
|
|
455
471
|
// write null byte and fill in length
|
456
472
|
SAFE_WRITE(buffer, &zero, 1);
|
457
473
|
length = buffer_get_position(buffer) - start_position;
|
474
|
+
|
475
|
+
// make sure that length doesn't exceed 4MB
|
476
|
+
if (length > 4 * 1024 * 1024) {
|
477
|
+
buffer_free(buffer);
|
478
|
+
rb_raise(InvalidDocument, "Document too large: BSON documents are limited to 4MB.");
|
479
|
+
return;
|
480
|
+
}
|
458
481
|
SAFE_WRITE_AT_POS(buffer, length_location, &length, 4);
|
459
482
|
}
|
460
483
|
|
@@ -489,8 +512,8 @@ static VALUE get_value(const char* buffer, int* position, int type) {
|
|
489
512
|
case 13:
|
490
513
|
{
|
491
514
|
int value_length;
|
515
|
+
value_length = *(int*)(buffer + *position) - 1;
|
492
516
|
*position += 4;
|
493
|
-
value_length = strlen(buffer + *position);
|
494
517
|
value = STR_NEW(buffer + *position, value_length);
|
495
518
|
*position += value_length + 1;
|
496
519
|
break;
|
@@ -500,10 +523,11 @@ static VALUE get_value(const char* buffer, int* position, int type) {
|
|
500
523
|
int size;
|
501
524
|
memcpy(&size, buffer + *position, 4);
|
502
525
|
if (strcmp(buffer + *position + 5, "$ref") == 0) { // DBRef
|
503
|
-
int offset = *position +
|
526
|
+
int offset = *position + 10;
|
504
527
|
VALUE argv[2];
|
505
|
-
int collection_length =
|
528
|
+
int collection_length = *(int*)(buffer + offset) - 1;
|
506
529
|
char id_type;
|
530
|
+
offset += 4;
|
507
531
|
|
508
532
|
argv[0] = STR_NEW(buffer + offset, collection_length);
|
509
533
|
offset += collection_length + 1;
|
@@ -629,8 +653,8 @@ static VALUE get_value(const char* buffer, int* position, int type) {
|
|
629
653
|
{
|
630
654
|
int collection_length;
|
631
655
|
VALUE collection, str, oid, id, argv[2];
|
656
|
+
collection_length = *(int*)(buffer + *position) - 1;
|
632
657
|
*position += 4;
|
633
|
-
collection_length = strlen(buffer + *position);
|
634
658
|
collection = STR_NEW(buffer + *position, collection_length);
|
635
659
|
*position += collection_length + 1;
|
636
660
|
|
@@ -656,8 +680,9 @@ static VALUE get_value(const char* buffer, int* position, int type) {
|
|
656
680
|
{
|
657
681
|
int code_length, scope_size;
|
658
682
|
VALUE code, scope, argv[2];
|
659
|
-
*position +=
|
660
|
-
code_length =
|
683
|
+
*position += 4;
|
684
|
+
code_length = *(int*)(buffer + *position) - 1;
|
685
|
+
*position += 4;
|
661
686
|
code = STR_NEW(buffer + *position, code_length);
|
662
687
|
*position += code_length + 1;
|
663
688
|
|
@@ -799,6 +824,7 @@ void Init_cbson() {
|
|
799
824
|
rb_require("mongo/errors");
|
800
825
|
InvalidName = rb_const_get(mongo, rb_intern("InvalidName"));
|
801
826
|
InvalidStringEncoding = rb_const_get(mongo, rb_intern("InvalidStringEncoding"));
|
827
|
+
InvalidDocument = rb_const_get(mongo, rb_intern("InvalidDocument"));
|
802
828
|
rb_require("mongo/util/ordered_hash");
|
803
829
|
OrderedHash = rb_const_get(rb_cObject, rb_intern("OrderedHash"));
|
804
830
|
|
@@ -14,8 +14,10 @@
|
|
14
14
|
* limitations under the License.
|
15
15
|
*/
|
16
16
|
|
17
|
+
#include "encoding_helpers.h"
|
18
|
+
|
17
19
|
/*
|
18
|
-
* Copyright 2001 Unicode, Inc.
|
20
|
+
* Portions Copyright 2001 Unicode, Inc.
|
19
21
|
*
|
20
22
|
* Disclaimer
|
21
23
|
*
|
@@ -85,23 +87,32 @@ static unsigned char isLegalUTF8(const unsigned char* source, int length) {
|
|
85
87
|
return 1;
|
86
88
|
}
|
87
89
|
|
88
|
-
|
89
|
-
|
90
|
-
/*
|
91
|
-
* Return whether a string containing UTF-8 is legal.
|
92
|
-
*/
|
93
|
-
unsigned char is_legal_utf8_string(const unsigned char* string, const int length) {
|
90
|
+
result_t check_string(const unsigned char* string, const int length,
|
91
|
+
const char check_utf8, const char check_null) {
|
94
92
|
int position = 0;
|
93
|
+
/* By default we go character by character. Will be different for checking
|
94
|
+
* UTF-8 */
|
95
|
+
int sequence_length = 1;
|
96
|
+
|
97
|
+
if (!check_utf8 && !check_null) {
|
98
|
+
return VALID;
|
99
|
+
}
|
95
100
|
|
96
101
|
while (position < length) {
|
97
|
-
|
98
|
-
|
99
|
-
return 0;
|
102
|
+
if (check_null && *(string + position) == 0) {
|
103
|
+
return HAS_NULL;
|
100
104
|
}
|
101
|
-
if (
|
102
|
-
|
105
|
+
if (check_utf8) {
|
106
|
+
sequence_length = trailingBytesForUTF8[*(string + position)] + 1;
|
107
|
+
if ((position + sequence_length) > length) {
|
108
|
+
return NOT_UTF_8;
|
109
|
+
}
|
110
|
+
if (!isLegalUTF8(string + position, sequence_length)) {
|
111
|
+
return NOT_UTF_8;
|
112
|
+
}
|
103
113
|
}
|
104
114
|
position += sequence_length;
|
105
115
|
}
|
106
|
-
|
116
|
+
|
117
|
+
return VALID;
|
107
118
|
}
|
@@ -17,6 +17,13 @@
|
|
17
17
|
#ifndef ENCODING_HELPERS_H
|
18
18
|
#define ENCODING_HELPERS_H
|
19
19
|
|
20
|
-
|
20
|
+
typedef enum {
|
21
|
+
VALID,
|
22
|
+
NOT_UTF_8,
|
23
|
+
HAS_NULL
|
24
|
+
} result_t;
|
25
|
+
|
26
|
+
result_t check_string(const unsigned char* string, const int length,
|
27
|
+
const char check_utf8, const char check_null);
|
21
28
|
|
22
29
|
#endif
|
data/ext/cbson/extconf.rb
CHANGED
data/ext/cbson/version.h
CHANGED
data/mongo-extensions.gemspec
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'lib/mongo'
|
2
|
-
VERSION_HEADER = File.open(File.join(File.dirname(__FILE__), 'ext', 'cbson', 'version.h'), "r")
|
2
|
+
VERSION_HEADER = File.open(File.join(File.dirname(__FILE__), 'ext', 'cbson', 'version.h'), "r")
|
3
3
|
VERSION = VERSION_HEADER.read.scan(/VERSION\s+"(\d+\.\d+(\.\d+)?)\"/)[0][0]
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = 'mongo_ext'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongo_ext
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.18.
|
4
|
+
version: 0.18.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Dirolf
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-12-
|
12
|
+
date: 2009-12-29 00:00:00 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -33,6 +33,8 @@ files:
|
|
33
33
|
- ext/cbson/version.h
|
34
34
|
has_rdoc: false
|
35
35
|
homepage: http://www.mongodb.org
|
36
|
+
licenses: []
|
37
|
+
|
36
38
|
post_install_message:
|
37
39
|
rdoc_options: []
|
38
40
|
|
@@ -53,9 +55,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
53
55
|
requirements: []
|
54
56
|
|
55
57
|
rubyforge_project:
|
56
|
-
rubygems_version: 1.3.
|
58
|
+
rubygems_version: 1.3.5
|
57
59
|
signing_key:
|
58
|
-
specification_version:
|
60
|
+
specification_version: 3
|
59
61
|
summary: C extensions for the MongoDB Ruby driver
|
60
62
|
test_files: []
|
61
63
|
|