Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit ec39911

Browse files
CDRIVER-6125 fix GridFS chunk size handling (#2146)
* validate chunk size from server document * test negative and zero length * check for negative length * Not strictly needed. But gives an earlier error.
1 parent a2c33be commit ec39911

File tree

2 files changed

+196
-0
lines changed

2 files changed

+196
-0
lines changed

‎src/libmongoc/src/mongoc/mongoc-gridfs-bucket.c‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ mongoc_gridfs_bucket_open_upload_stream_with_id(mongoc_gridfs_bucket_t *bucket,
182182
file->bucket = bucket;
183183
file->chunk_size = gridfs_opts.chunkSizeBytes;
184184
file->metadata = bson_copy(&gridfs_opts.metadata);
185+
BSON_ASSERT(gridfs_opts.chunkSizeBytes > 0); // Validated in _mongoc_gridfs_bucket_opts_parse.
185186
file->buffer = bson_malloc((size_t)gridfs_opts.chunkSizeBytes);
186187
file->in_buffer = 0;
187188

@@ -347,6 +348,26 @@ mongoc_gridfs_bucket_open_download_stream(mongoc_gridfs_bucket_t *bucket,
347348

348349
bson_destroy(&file_doc);
349350

351+
if (file->chunk_size <= 0) {
352+
_mongoc_set_error(error,
353+
MONGOC_ERROR_GRIDFS,
354+
MONGOC_ERROR_GRIDFS_CORRUPT,
355+
"File document contains invalid chunk size: %" PRId32,
356+
file->chunk_size);
357+
_mongoc_gridfs_bucket_file_destroy(file);
358+
return NULL;
359+
}
360+
361+
if (file->length < 0) {
362+
_mongoc_set_error(error,
363+
MONGOC_ERROR_GRIDFS,
364+
MONGOC_ERROR_GRIDFS_CORRUPT,
365+
"File document contains invalid length: %" PRId64,
366+
file->length);
367+
_mongoc_gridfs_bucket_file_destroy(file);
368+
return NULL;
369+
}
370+
350371
file->file_id = (bson_value_t *)bson_malloc0(sizeof *(file->file_id));
351372
bson_value_copy(file_id, file->file_id);
352373
file->bucket = bucket;

‎src/libmongoc/tests/test-mongoc-gridfs-bucket.c‎

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1048,6 +1048,180 @@ test_gridfs_bucket_opts(void)
10481048
mongoc_client_destroy(client);
10491049
}
10501050

1051+
// Regression test for CDRIVER-6125
1052+
static void
1053+
test_bad_sizes(void)
1054+
{
1055+
mongoc_client_t *client = test_framework_new_default_client();
1056+
bson_error_t error;
1057+
1058+
mongoc_database_t *db = mongoc_client_get_database(client, "test_bad_sizes");
1059+
mongoc_database_drop(db, NULL);
1060+
1061+
// Test negative chunkSize:
1062+
{
1063+
bson_t *doc = tmp_bson(BSON_STR({
1064+
"_id" : 0,
1065+
"filename" : "foo.txt",
1066+
"length" : 1000,
1067+
"chunkSize" : -1, // Negative!
1068+
"uploadDate" : {"$date" : 1234567890000}
1069+
}));
1070+
1071+
bson_iter_t id_iter;
1072+
ASSERT(bson_iter_init_find(&id_iter, doc, "_id"));
1073+
const bson_value_t *id_value = bson_iter_value(&id_iter);
1074+
1075+
// Insert manually:
1076+
{
1077+
mongoc_collection_t *files = mongoc_database_get_collection(db, "fs.files");
1078+
mongoc_collection_insert_one(files, doc, NULL, NULL, &error);
1079+
mongoc_collection_destroy(files);
1080+
}
1081+
1082+
// Try to read:
1083+
{
1084+
mongoc_gridfs_bucket_t *bucket = mongoc_gridfs_bucket_new(db, NULL, NULL, &error);
1085+
ASSERT_OR_PRINT(bucket, error);
1086+
mongoc_stream_t *stream = mongoc_gridfs_bucket_open_download_stream(bucket, id_value, &error);
1087+
ASSERT(!stream);
1088+
ASSERT_ERROR_CONTAINS(error, MONGOC_ERROR_GRIDFS, MONGOC_ERROR_GRIDFS_CORRUPT, "invalid chunk size");
1089+
mongoc_gridfs_bucket_destroy(bucket);
1090+
}
1091+
1092+
// Try to write:
1093+
{
1094+
mongoc_gridfs_bucket_t *bucket = mongoc_gridfs_bucket_new(db, NULL, NULL, &error);
1095+
ASSERT_OR_PRINT(bucket, error);
1096+
bson_t *opts = tmp_bson(BSON_STR({"chunkSizeBytes" : 0}));
1097+
mongoc_stream_t *stream = mongoc_gridfs_bucket_open_upload_stream(bucket, "foo.txt", opts, NULL, &error);
1098+
ASSERT(!stream);
1099+
ASSERT_ERROR_CONTAINS(
1100+
error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "should be greater than 0");
1101+
mongoc_gridfs_bucket_destroy(bucket);
1102+
}
1103+
}
1104+
1105+
mongoc_database_drop(db, NULL);
1106+
1107+
// Test zero chunkSize:
1108+
{
1109+
bson_t *doc = tmp_bson(BSON_STR({
1110+
"_id" : 0,
1111+
"filename" : "foo.txt",
1112+
"length" : 1000,
1113+
"chunkSize" : 0, // Zero!
1114+
"uploadDate" : {"$date" : 1234567890000}
1115+
}));
1116+
1117+
bson_iter_t id_iter;
1118+
ASSERT(bson_iter_init_find(&id_iter, doc, "_id"));
1119+
const bson_value_t *id_value = bson_iter_value(&id_iter);
1120+
1121+
// Insert manually:
1122+
{
1123+
mongoc_collection_t *files = mongoc_database_get_collection(db, "fs.files");
1124+
mongoc_collection_insert_one(files, doc, NULL, NULL, &error);
1125+
mongoc_collection_destroy(files);
1126+
}
1127+
1128+
// Try to read:
1129+
{
1130+
mongoc_gridfs_bucket_t *bucket = mongoc_gridfs_bucket_new(db, NULL, NULL, &error);
1131+
ASSERT_OR_PRINT(bucket, error);
1132+
mongoc_stream_t *stream = mongoc_gridfs_bucket_open_download_stream(bucket, id_value, &error);
1133+
ASSERT(!stream);
1134+
ASSERT_ERROR_CONTAINS(error, MONGOC_ERROR_GRIDFS, MONGOC_ERROR_GRIDFS_CORRUPT, "invalid chunk size");
1135+
mongoc_gridfs_bucket_destroy(bucket);
1136+
}
1137+
1138+
// Try to write:
1139+
{
1140+
mongoc_gridfs_bucket_t *bucket = mongoc_gridfs_bucket_new(db, NULL, NULL, &error);
1141+
ASSERT_OR_PRINT(bucket, error);
1142+
bson_t *opts = tmp_bson(BSON_STR({"chunkSizeBytes" : -1}));
1143+
mongoc_stream_t *stream = mongoc_gridfs_bucket_open_upload_stream(bucket, "foo.txt", opts, NULL, &error);
1144+
ASSERT(!stream);
1145+
ASSERT_ERROR_CONTAINS(
1146+
error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "should be greater than 0");
1147+
mongoc_gridfs_bucket_destroy(bucket);
1148+
}
1149+
}
1150+
1151+
mongoc_database_drop(db, NULL);
1152+
1153+
// Test negative length:
1154+
{
1155+
bson_t *doc = tmp_bson(BSON_STR({
1156+
"_id" : 0,
1157+
"filename" : "foo.txt",
1158+
"length" : -1, // Negative!
1159+
"chunkSize" : 10,
1160+
"uploadDate" : {"$date" : 1234567890000}
1161+
}));
1162+
1163+
bson_iter_t id_iter;
1164+
ASSERT(bson_iter_init_find(&id_iter, doc, "_id"));
1165+
const bson_value_t *id_value = bson_iter_value(&id_iter);
1166+
1167+
// Insert manually:
1168+
{
1169+
mongoc_collection_t *files = mongoc_database_get_collection(db, "fs.files");
1170+
mongoc_collection_insert_one(files, doc, NULL, NULL, &error);
1171+
mongoc_collection_destroy(files);
1172+
}
1173+
1174+
// Try to read:
1175+
{
1176+
mongoc_gridfs_bucket_t *bucket = mongoc_gridfs_bucket_new(db, NULL, NULL, &error);
1177+
mongoc_stream_t *stream = mongoc_gridfs_bucket_open_download_stream(bucket, id_value, &error);
1178+
ASSERT(!stream);
1179+
ASSERT_ERROR_CONTAINS(error, MONGOC_ERROR_GRIDFS, MONGOC_ERROR_GRIDFS_CORRUPT, "invalid length");
1180+
mongoc_gridfs_bucket_destroy(bucket);
1181+
}
1182+
}
1183+
1184+
mongoc_database_drop(db, NULL);
1185+
1186+
// Test a zero length (OK):
1187+
{
1188+
bson_t *doc = tmp_bson(BSON_STR({
1189+
"_id" : 0,
1190+
"filename" : "foo.txt",
1191+
"length" : 0, // Zero!
1192+
"chunkSize" : 10,
1193+
"uploadDate" : {"$date" : 1234567890000}
1194+
}));
1195+
1196+
bson_iter_t id_iter;
1197+
ASSERT(bson_iter_init_find(&id_iter, doc, "_id"));
1198+
const bson_value_t *id_value = bson_iter_value(&id_iter);
1199+
1200+
// Insert manually:
1201+
{
1202+
mongoc_collection_t *files = mongoc_database_get_collection(db, "fs.files");
1203+
mongoc_collection_insert_one(files, doc, NULL, NULL, &error);
1204+
mongoc_collection_destroy(files);
1205+
}
1206+
1207+
// Try to read:
1208+
{
1209+
mongoc_gridfs_bucket_t *bucket = mongoc_gridfs_bucket_new(db, NULL, NULL, &error);
1210+
mongoc_stream_t *stream = mongoc_gridfs_bucket_open_download_stream(bucket, id_value, &error);
1211+
ASSERT(stream);
1212+
// OK. Gets back an empty read.
1213+
uint8_t buf[64];
1214+
ssize_t r = mongoc_stream_read(stream, buf, sizeof buf, 0, 0);
1215+
ASSERT_CMPINT(r, ==, 0);
1216+
mongoc_stream_destroy(stream);
1217+
mongoc_gridfs_bucket_destroy(bucket);
1218+
}
1219+
}
1220+
1221+
mongoc_database_destroy(db);
1222+
mongoc_client_destroy(client);
1223+
}
1224+
10511225
void
10521226
test_gridfs_bucket_install(TestSuite *suite)
10531227
{
@@ -1070,4 +1244,5 @@ test_gridfs_bucket_install(TestSuite *suite)
10701244
test_framework_skip_if_no_sessions,
10711245
test_framework_skip_if_no_crypto);
10721246
TestSuite_AddLive(suite, "/gridfs/options", test_gridfs_bucket_opts);
1247+
TestSuite_AddLive(suite, "/gridfs/bad_sizes", test_bad_sizes);
10731248
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /