Skip to content

Commit

Permalink
SECBUG-240 Fix out-of-bounds reads (backport to 4.15-stable) (#326)
Browse files Browse the repository at this point in the history
* SECBUG-240 Fix out-of-bounds reads (#325)

* final tweaks for BSON 5 release

* SECBUG-240 strlen might read beyond end of buffer

* ruby 2.6 isn't supported

* nix 2.6

* version bump
  • Loading branch information
jamis committed Apr 2, 2024
1 parent a9d0671 commit dfbb4ed
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 4 deletions.
21 changes: 18 additions & 3 deletions ext/bson/read.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ static VALUE pvt_get_symbol(byte_buffer_t *b, VALUE rb_buffer, int argc, VALUE *
static VALUE pvt_get_boolean(byte_buffer_t *b);
static VALUE pvt_read_field(byte_buffer_t *b, VALUE rb_buffer, uint8_t type, int argc, VALUE *argv);
static void pvt_skip_cstring(byte_buffer_t *b);
static size_t pvt_strnlen(const byte_buffer_t *b);

void pvt_raise_decode_error(volatile VALUE msg) {
VALUE klass = pvt_const_get_3("BSON", "Error", "BSONDecodeError");
Expand Down Expand Up @@ -128,7 +129,7 @@ VALUE rb_bson_byte_buffer_get_bytes(VALUE self, VALUE i)
}

VALUE pvt_get_boolean(byte_buffer_t *b){
VALUE result;
VALUE result = Qnil;
char byte_value;
ENSURE_BSON_READ(b, 1);
byte_value = *READ_PTR(b);
Expand Down Expand Up @@ -221,7 +222,7 @@ VALUE rb_bson_byte_buffer_get_cstring(VALUE self)
int length;

TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
length = (int)strlen(READ_PTR(b));
length = (int)pvt_strnlen(b);
ENSURE_BSON_READ(b, length);
string = rb_enc_str_new(READ_PTR(b), length, rb_utf8_encoding());
b->read_position += length + 1;
Expand All @@ -234,7 +235,7 @@ VALUE rb_bson_byte_buffer_get_cstring(VALUE self)
void pvt_skip_cstring(byte_buffer_t *b)
{
int length;
length = (int)strlen(READ_PTR(b));
length = (int)pvt_strnlen(b);
ENSURE_BSON_READ(b, length);
b->read_position += length + 1;
}
Expand Down Expand Up @@ -438,3 +439,17 @@ VALUE rb_bson_byte_buffer_get_array(int argc, VALUE *argv, VALUE self){

return array;
}

/**
* Returns the length of the given string `str`. If no null-terminating byte
* is present when `len` bytes have been scanned, then `len` is
* returned.
*/
size_t pvt_strnlen(const byte_buffer_t *b) {
const char *ptr = memchr(READ_PTR(b), '\0', READ_SIZE(b));

if (!ptr)
rb_raise(rb_eRangeError, "string is too long (possibly not null-terminated)");

return (size_t)(ptr - READ_PTR(b));
}
4 changes: 4 additions & 0 deletions ext/bson/write.c
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,10 @@ void pvt_put_array_index(byte_buffer_t *b, int32_t index)
c_str = buffer;
snprintf(buffer, sizeof(buffer), "%d", index);
}
// strlen is a potential vector for out-of-bounds errors, but
// the only way for that to happen here, specifically, is if `index`
// is greater than 10e16 - 1, which is far beyond the domain of an
// int32.
length = strlen(c_str) + 1;
ENSURE_BSON_WRITE(b, length);
memcpy(WRITE_PTR(b), c_str, length);
Expand Down
2 changes: 1 addition & 1 deletion lib/bson/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@
# limitations under the License.

module BSON
VERSION = "4.15.0"
VERSION = "4.15.1"
end

0 comments on commit dfbb4ed

Please sign in to comment.