Uploaded image for project: 'C Driver'
  1. C Driver
  2. CDRIVER-509

GridFS crashes when creating empty file

    • Type: Icon: Bug Bug
    • Resolution: Done
    • Priority: Icon: Major - P3 Major - P3
    • 1.3.0-beta0
    • Affects Version/s: None
    • Component/s: GridFS
    • None

      (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;
         ...
      }
      
      

            Assignee:
            kyle.suarez@mongodb.com Kyle Suarez
            Reporter:
            samantha.ritter@mongodb.com Samantha Ritter (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: