[CDRIVER-509] GridFS crashes when creating empty file Created: 23/Jan/15  Updated: 23/Oct/15  Resolved: 17/Sep/15

Status: Closed
Project: C Driver
Component/s: GridFS
Affects Version/s: None
Fix Version/s: 1.3.0-beta0

Type: Bug Priority: Major - P3
Reporter: Samantha Ritter (Inactive) Assignee: Kyle Suarez
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Depends
depends on CDRIVER-839 Bad interpretation of GridFS "SEEK_EN... Closed
depends on CDRIVER-849 Allow GridFS seek past end-of-file Closed

 Description   

(ported from github)

When creating an empty file from a stream, GridFS crashes.

When create an empty file by calling mongoc_gridfs_create_file_from_stream() which will relocate the file pointer to the beginning of the created file after write all bytes(no byte written for empty file) into mongodb. Please notice my comments in the following code snippet:

int      
mongoc_gridfs_file_seek (mongoc_gridfs_file_t * file, /** Arthur Xie: the new created empty file */
                         uint64_t         delta, /** Arthur Xie: 0 */
                         int                   whence) /** Arthur Xie: SEEK_SET */
{     
   uint64_t offset;
 
   BSON_ASSERT(file);
 
   switch (whence) {
   case SEEK_SET:
      offset = delta;                                                                            
      break;
   case SEEK_CUR:                                                                                
      offset = file->pos + delta;                                                                
      break;                                                                                     
   case SEEK_END:                                                                                
      offset = (file->length - 1) + delta;                                                       
      break;
   default:                                                                                      
      errno = EINVAL;                                                                            
      return -1;                                                                                 
 
      break;                                                                                     
   }                                                                                             
   /** Arthur Xie: abort in debug mode because file->length = 0 and offset = 0*/                                                                                              
   BSON_ASSERT (file->length > (int64_t)offset);   
 
   /** Arthur Xie: offset = 0, file->pos = 0, file->page = NULL */    
 
   if (offset % file->chunk_size != file->pos % file->chunk_size)  { 
      /** no longer on the same page */
 
      if (file->page) {
         if (_mongoc_gridfs_file_page_is_dirty (file->page)) {
            _mongoc_gridfs_file_flush_page (file);
         } else {
            _mongoc_gridfs_file_page_destroy (file->page);
         }
      }
 
      /** we'll pick up the seek when we fetch a page on the next action.  We lazily load */
   } else {
      /** Arthur Xie: file->page = NULL */
      _mongoc_gridfs_file_page_seek (file->page, offset % file->chunk_size);
   }
 
   file->pos = offset;
 
   return 0;
}
 
bool
_mongoc_gridfs_file_page_seek (mongoc_gridfs_file_page_t *page,
                               uint32_t              offset)
{
   ENTRY;
 
   BSON_ASSERT (page); /** Arthur Xie: assert(page) or nothing happened if not define BSON_DISABLE_ASSERT */
 
   BSON_ASSERT (offset <= page->len); /** Arthur Xie: crash or nothing happened */
 
   page->offset = offset; /** Arthur Xie: crash */
 
   RETURN (1);            
}

How to fix it:

 
int
mongoc_gridfs_file_seek (mongoc_gridfs_file_t *file,
                         uint64_t         delta,
                         int                   whence)
{
   uint64_t offset;
 
   BSON_ASSERT(file);
 
   switch (whence) {
   case SEEK_SET:
      offset = delta;
      break;
   case SEEK_CUR:
      offset = file->pos + delta;
      break;
   case SEEK_END:
      offset = (file->length - 1) + delta;
      break;
   default:
      errno = EINVAL;
      return -1;
 
      break;
   }
 
   BSON_ASSERT (file->length >= (int64_t)offset);
   if (file->pos == offset)
      return 0;
   ...
}



 Comments   
Comment by Githook User [ 22/Sep/15 ]

Author:

{u'username': u'ajdavis', u'name': u'A. Jesse Jiryu Davis', u'email': u'jesse@emptysquare.net'}

Message: Merge pull request #272 from ksuarz/feature/test-empty

CDRIVER-509 and friends: test empty file
Branch: 1.3.0-dev
https://github.com/mongodb/mongo-c-driver/commit/25ed7f4b9d17c2b31a168bf242429a7f1c0846c8

Comment by Githook User [ 22/Sep/15 ]

Author:

{u'username': u'ksuarz', u'name': u'Kyle Suarez', u'email': u'ksuarz@gmail.com'}

Message: CDRIVER-509 style fixes in test
Branch: 1.3.0-dev
https://github.com/mongodb/mongo-c-driver/commit/3261bdd1934b8c9155c8cb93dfa63ee4b18e6d66

Comment by Githook User [ 22/Sep/15 ]

Author:

{u'username': u'ksuarz', u'name': u'Kyle Suarez', u'email': u'ksuarz@gmail.com'}

Message: CDRIVER-509 update empty file test
Branch: 1.3.0-dev
https://github.com/mongodb/mongo-c-driver/commit/2518073de3553cc21b2c2803582cb3ac59643ab2

Comment by Githook User [ 22/Sep/15 ]

Author:

{u'username': u'ksuarz', u'name': u'Kyle Suarez', u'email': u'ksuarz@gmail.com'}

Message: CDRIVER-509 add gridfs test on empty file
Branch: 1.3.0-dev
https://github.com/mongodb/mongo-c-driver/commit/b024ecc2c34a1733703d3477ad167f36746d8a78

Comment by Kyle Suarez [ 17/Sep/15 ]

The commit that fixes this is here on GitHub.

Comment by Kyle Suarez [ 17/Sep/15 ]

CDRIVER-849 removes the check altogether, allowing for arbitrary seeks beyond zero. This fixes this bug.

Generated at Wed Feb 07 21:09:43 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.