mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 02:49:02 -04:00
Fix 32-bit integer truncation in block metadata allocations and file_block
This commit is contained in:
parent
527bd69129
commit
c7b8068e36
5 changed files with 85 additions and 11 deletions
|
|
@ -462,18 +462,30 @@ struct snapraid_file* file_alloc(unsigned block_size, const char* sub, data_off_
|
|||
{
|
||||
struct snapraid_file* file;
|
||||
block_off_t i;
|
||||
block_off_t blockmax;
|
||||
|
||||
blockmax = size / block_size;
|
||||
if (size % block_size != 0)
|
||||
++blockmax;
|
||||
|
||||
#if SIZE_MAX == UINT32_MAX
|
||||
if (blockmax > (block_off_t)(SIZE_MAX / block_sizeof())) {
|
||||
log_fatal(ESOFT, "File '%s' with %" PRIu64 " blocks is too large for a 32-bit build. Use a 64-bit build or increase the block size.\n", sub, blockmax);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
file = malloc_nofail(sizeof(struct snapraid_file));
|
||||
file->sub = strdup_nofail(sub);
|
||||
file->size = size;
|
||||
file->blockmax = (size + block_size - 1) / block_size;
|
||||
file->blockmax = blockmax;
|
||||
file->mtime_sec = mtime_sec;
|
||||
file->mtime_nsec = mtime_nsec;
|
||||
file->inode = inode;
|
||||
file->physical = physical;
|
||||
file->flag = 0;
|
||||
file->shared_flag = 0;
|
||||
file->blockvec = nalloc_nofail(file->blockmax, block_sizeof());
|
||||
file->blockvec = nalloc_nofail((size_t)file->blockmax, block_sizeof());
|
||||
|
||||
for (i = 0; i < file->blockmax; ++i) {
|
||||
struct snapraid_block* block = file_block(file, i);
|
||||
|
|
@ -489,6 +501,13 @@ struct snapraid_file* file_dup(struct snapraid_file* copy)
|
|||
struct snapraid_file* file;
|
||||
block_off_t i;
|
||||
|
||||
#if SIZE_MAX == UINT32_MAX
|
||||
if (copy->blockmax > (block_off_t)(SIZE_MAX / block_sizeof())) {
|
||||
log_fatal(ESOFT, "File '%s' with %" PRIu64 " blocks is too large for a 32-bit build. Use a 64-bit build or increase the block size.\n", copy->sub, copy->blockmax);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
file = malloc_nofail(sizeof(struct snapraid_file));
|
||||
file->sub = strdup_nofail(copy->sub);
|
||||
file->size = copy->size;
|
||||
|
|
@ -499,7 +518,7 @@ struct snapraid_file* file_dup(struct snapraid_file* copy)
|
|||
file->physical = copy->physical;
|
||||
file->flag = copy->flag;
|
||||
file->shared_flag = 0;
|
||||
file->blockvec = nalloc_nofail(file->blockmax, block_sizeof());
|
||||
file->blockvec = nalloc_nofail((size_t)file->blockmax, block_sizeof());
|
||||
|
||||
for (i = 0; i < file->blockmax; ++i) {
|
||||
struct snapraid_block* block = file_block(file, i);
|
||||
|
|
@ -847,14 +866,26 @@ int dir_name_compare(const void* void_arg, const void* void_data)
|
|||
struct snapraid_dealloc* dealloc_alloc(unsigned block_size, const char* sub, data_off_t size, int64_t mtime_sec, int32_t mtime_nsec)
|
||||
{
|
||||
struct snapraid_dealloc* dealloc;
|
||||
block_off_t blockmax;
|
||||
|
||||
blockmax = size / block_size;
|
||||
if (size % block_size != 0)
|
||||
++blockmax;
|
||||
|
||||
#if SIZE_MAX == UINT32_MAX
|
||||
if (blockmax > (block_off_t)(SIZE_MAX / BLOCK_HASH_SIZE)) {
|
||||
log_fatal(ESOFT, "File '%s' with %" PRIu64 " blocks is too large for a 32-bit build. Use a 64-bit build or increase the block size.\n", sub, blockmax);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
dealloc = malloc_nofail(sizeof(struct snapraid_dealloc));
|
||||
dealloc->sub = strdup_nofail(sub);
|
||||
dealloc->size = size;
|
||||
dealloc->mtime_sec = mtime_sec;
|
||||
dealloc->mtime_nsec = mtime_nsec;
|
||||
dealloc->blockmax = (size + block_size - 1) / block_size;
|
||||
dealloc->blockhash = nalloc_nofail(dealloc->blockmax, BLOCK_HASH_SIZE);
|
||||
dealloc->blockmax = blockmax;
|
||||
dealloc->blockhash = nalloc_nofail((size_t)dealloc->blockmax, BLOCK_HASH_SIZE);
|
||||
|
||||
return dealloc;
|
||||
}
|
||||
|
|
@ -1488,6 +1519,15 @@ void fs_allocate(struct snapraid_disk* disk, block_off_t parity_pos, struct snap
|
|||
struct snapraid_extent* parity_extent;
|
||||
struct snapraid_extent* file_extent;
|
||||
|
||||
#if SIZE_MAX == UINT32_MAX
|
||||
if (parity_pos > (block_off_t)(SIZE_MAX - 4096)) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal(ESOFT, "Parity position %" PRIu64 " is too large for a 32-bit build. Use a 64-bit build or increase the block size.\n", parity_pos);
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
#endif
|
||||
|
||||
fs_lock(disk);
|
||||
|
||||
if (file_pos > 0) {
|
||||
|
|
|
|||
|
|
@ -866,7 +866,7 @@ void file_copy(struct snapraid_file* src_file, struct snapraid_file* dest_file);
|
|||
*
|
||||
* Note that the block size if a runtime value.
|
||||
*/
|
||||
static inline struct snapraid_block* file_block(struct snapraid_file* file, size_t pos)
|
||||
static inline struct snapraid_block* file_block(struct snapraid_file* file, block_off_t pos)
|
||||
{
|
||||
unsigned char* ptr = (unsigned char*)file->blockvec;
|
||||
|
||||
|
|
|
|||
|
|
@ -49,12 +49,24 @@ static void import_file(struct snapraid_state* state, const char* path, uint64_t
|
|||
int flags;
|
||||
unsigned block_size = state->block_size;
|
||||
struct advise_struct advise;
|
||||
block_off_t blockmax;
|
||||
|
||||
blockmax = size / block_size;
|
||||
if (size % block_size != 0)
|
||||
++blockmax;
|
||||
|
||||
#if SIZE_MAX == UINT32_MAX
|
||||
if (blockmax > (block_off_t)(SIZE_MAX / sizeof(struct snapraid_import_block))) {
|
||||
log_fatal(ESOFT, "File '%s' with %" PRIu64 " blocks is too large for a 32-bit build. Use a 64-bit build or increase the block size.\n", path, blockmax);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
file = malloc_nofail(sizeof(struct snapraid_import_file));
|
||||
file->path = strdup_nofail(path);
|
||||
file->size = size;
|
||||
file->blockmax = (size + block_size - 1) / block_size;
|
||||
file->blockimp = nalloc_nofail(file->blockmax, sizeof(struct snapraid_import_block));
|
||||
file->blockmax = blockmax;
|
||||
file->blockimp = nalloc_nofail((size_t)file->blockmax, sizeof(struct snapraid_import_block));
|
||||
file->is_runtime = 1;
|
||||
|
||||
buffer = malloc_nofail(block_size);
|
||||
|
|
@ -148,6 +160,7 @@ static void import_dealloc(struct snapraid_state* state, const char* dir, struct
|
|||
char path[PATH_MAX];
|
||||
struct snapraid_import_file* file;
|
||||
block_off_t i;
|
||||
block_off_t blockmax;
|
||||
data_off_t offset;
|
||||
data_off_t size;
|
||||
unsigned block_size = state->block_size;
|
||||
|
|
@ -156,11 +169,22 @@ static void import_dealloc(struct snapraid_state* state, const char* dir, struct
|
|||
pathcat(path, sizeof(path), dealloc->sub);
|
||||
size = dealloc->size;
|
||||
|
||||
blockmax = size / block_size;
|
||||
if (size % block_size != 0)
|
||||
++blockmax;
|
||||
|
||||
#if SIZE_MAX == UINT32_MAX
|
||||
if (blockmax > (block_off_t)(SIZE_MAX / sizeof(struct snapraid_import_block))) {
|
||||
log_fatal(ESOFT, "File '%s' with %" PRIu64 " blocks is too large for a 32-bit build. Use a 64-bit build or increase the block size.\n", path, blockmax);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
file = malloc_nofail(sizeof(struct snapraid_import_file));
|
||||
file->path = strdup_nofail(path);
|
||||
file->size = size;
|
||||
file->blockmax = (size + block_size - 1) / block_size;
|
||||
file->blockimp = nalloc_nofail(file->blockmax, sizeof(struct snapraid_import_block));
|
||||
file->blockmax = blockmax;
|
||||
file->blockimp = nalloc_nofail((size_t)file->blockmax, sizeof(struct snapraid_import_block));
|
||||
file->is_runtime = 0;
|
||||
|
||||
offset = 0;
|
||||
|
|
|
|||
|
|
@ -2004,6 +2004,16 @@ static void state_content_check(struct snapraid_state* state, const char* path)
|
|||
{
|
||||
tommy_node* i;
|
||||
|
||||
#if SIZE_MAX == UINT32_MAX
|
||||
block_off_t blockmax = parity_allocated_size(state);
|
||||
if (blockmax > (block_off_t)(SIZE_MAX - 4096)) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal(ESOFT, "Array with %" PRIu64 " blocks in '%s' is too large for a 32-bit build. Use a 64-bit build or increase the block size.\n", blockmax, path);
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* check that any map has different name and position */
|
||||
for (i = state->maplist; i != 0; i = i->next) {
|
||||
struct snapraid_map* map = i->data;
|
||||
|
|
|
|||
|
|
@ -269,7 +269,7 @@ typedef unsigned char bit_vect_t;
|
|||
|
||||
static inline size_t bit_vect_size(size_t max)
|
||||
{
|
||||
return (max + BIT_VECT_SIZE - 1) / BIT_VECT_SIZE;
|
||||
return (max / BIT_VECT_SIZE) + ((max % BIT_VECT_SIZE) != 0);
|
||||
}
|
||||
|
||||
static inline void bit_vect_set(bit_vect_t* bit_vect, size_t off)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue