/** * Replace a 32 bit integer int the byte buffer. */ VALUE rb_bson_byte_buffer_replace_int32(VALUE self, VALUE index, VALUE i) { byte_buffer_t *b; const int32_t position = NUM2LONG(index); const int32_t i32 = BSON_UINT32_TO_LE(NUM2LONG(i)); TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b); memcpy(READ_PTR(b) + position, &i32, 4); return self; }
/** * Writes a 32 bit integer to the byte buffer. */ VALUE rb_bson_byte_buffer_put_int32(VALUE self, VALUE i) { byte_buffer_t *b; const int32_t i32 = BSON_UINT32_TO_LE(NUM2INT(i)); TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b); ENSURE_BSON_WRITE(b, 4); memcpy(WRITE_PTR(b), (char*)&i32, 4); b->write_position += 4; return self; }
/** * Writes a string to the byte buffer. */ VALUE rb_bson_byte_buffer_put_string(VALUE self, VALUE string) { byte_buffer_t *b; int32_t length_le; char *str = RSTRING_PTR(string); const int32_t length = RSTRING_LEN(string) + 1; length_le = BSON_UINT32_TO_LE(length); if (!rb_bson_utf8_validate(str, length - 1, true)) { rb_raise(rb_eArgError, "String %s is not valid UTF-8.", str); } TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b); ENSURE_BSON_WRITE(b, length + 4); memcpy(WRITE_PTR(b), (char*)&length_le, 4); b->write_position += 4; memcpy(WRITE_PTR(b), str, length); b->write_position += length; return self; }
static void test_bson_iter_fuzz (void) { uint8_t *data; uint32_t len = 512; uint32_t len_le; uint32_t r; bson_iter_t iter; bson_t *b; uint32_t i; int pass; len_le = BSON_UINT32_TO_LE(len); for (pass = 0; pass < FUZZ_N_PASSES; pass++) { data = bson_malloc0(len); memcpy(data, &len_le, sizeof (len_le)); for (i = 4; i < len; i += 4) { r = rand(); memcpy(&data[i], &r, sizeof (r)); } if (!(b = bson_new_from_data(data, len))) { /* * It could fail on buffer length or missing trailing null byte. */ bson_free (data); continue; } BSON_ASSERT(b); /* * TODO: Most of the following ignores the key. That should be fixed * but has it's own perils too. */ assert(bson_iter_init(&iter, b)); while (bson_iter_next(&iter)) { assert(iter.next_off < len); switch (bson_iter_type(&iter)) { case BSON_TYPE_ARRAY: case BSON_TYPE_DOCUMENT: { const uint8_t *child = NULL; uint32_t child_len = 0; bson_iter_document(&iter, &child_len, &child); if (child_len) { assert(child); assert(child_len >= 5); assert((iter.off + child_len) < b->len); assert(child_len < (uint32_t) -1); memcpy(&child_len, child, sizeof (child_len)); child_len = BSON_UINT32_FROM_LE(child_len); assert(child_len >= 5); } } break; case BSON_TYPE_DOUBLE: case BSON_TYPE_UTF8: case BSON_TYPE_BINARY: case BSON_TYPE_UNDEFINED: break; case BSON_TYPE_OID: assert(iter.off + 12 < iter.len); break; case BSON_TYPE_BOOL: case BSON_TYPE_DATE_TIME: case BSON_TYPE_NULL: case BSON_TYPE_REGEX: /* TODO: check for 2 valid cstring. */ case BSON_TYPE_DBPOINTER: case BSON_TYPE_CODE: case BSON_TYPE_SYMBOL: case BSON_TYPE_CODEWSCOPE: case BSON_TYPE_INT32: case BSON_TYPE_TIMESTAMP: case BSON_TYPE_INT64: case BSON_TYPE_DECIMAL128: case BSON_TYPE_MAXKEY: case BSON_TYPE_MINKEY: break; case BSON_TYPE_EOD: default: /* Code should not be reached. */ assert(false); break; } } bson_destroy(b); bson_free(data); } }