mongo_ext 0.18.1 → 0.18.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
|