AmendHub

Download:

jcs

/

subtext

/

amendments

/

333

bile: Cope with malloc/realloc failures gracefully when possible


jcs made amendment 333 about 1 year ago
--- bile.c Wed Mar 1 09:19:35 2023 +++ bile.c Thu Mar 2 09:32:44 2023 @@ -51,11 +51,15 @@ bile_create(const Str255 filename, short vrefnum, cons { struct bile *bile = NULL; size_t len; + short fh = -1; char *tmp; - short fh; _bile_error = 0; + bile = xmalloczero(sizeof(struct bile)); + if (bile == NULL) + return NULL; + /* create file */ _bile_error = Create(filename, vrefnum, creator, type); if (_bile_error) @@ -70,54 +74,56 @@ bile_create(const Str255 filename, short vrefnum, cons return NULL; SetFPos(fh, fsFromStart, 0); - bile = xmalloczero(sizeof(struct bile), "bile_create"); memcpy(bile->magic, BILE_MAGIC, sizeof(bile->magic)); bile->vrefnum = vrefnum; - bile->frefnum = fh; bile->map_ptr.type = BILE_TYPE_MAPPTR; memcpy(bile->filename, filename, sizeof(bile->filename)); /* write magic */ len = BILE_MAGIC_LEN; - tmp = xstrdup(BILE_MAGIC, "bile_create magic"); - _bile_error = FSWrite(bile->frefnum, &len, tmp); + tmp = xstrdup(BILE_MAGIC); + if (tmp == NULL) + goto create_bail; + _bile_error = FSWrite(fh, &len, tmp); xfree(&tmp); if (_bile_error) goto create_bail; /* write header pointing to blank map */ len = sizeof(bile->map_ptr); - _bile_error = FSWrite(bile->frefnum, &len, &bile->map_ptr); + _bile_error = FSWrite(fh, &len, &bile->map_ptr); if (_bile_error) goto create_bail; len = sizeof(bile->old_map_ptr); - _bile_error = FSWrite(bile->frefnum, &len, &bile->old_map_ptr); + _bile_error = FSWrite(fh, &len, &bile->old_map_ptr); if (_bile_error) goto create_bail; /* padding */ len = BILE_HEADER_LEN - BILE_MAGIC_LEN - BILE_OBJECT_SIZE - BILE_OBJECT_SIZE; - tmp = xmalloczero(len, "bile_create padding"); - _bile_error = FSWrite(bile->frefnum, &len, tmp); - if (_bile_error) + tmp = xmalloczero(len); + if (tmp == NULL) goto create_bail; + _bile_error = FSWrite(fh, &len, tmp); xfree(&tmp); + if (_bile_error) + goto create_bail; GetFPos(fh, &bile->file_size); if (bile->file_size != BILE_HEADER_LEN) panic("bile_create: incorrect length after writing: %ld (!= %ld)", bile->file_size, (long)BILE_HEADER_LEN); - + + bile->frefnum = fh; return bile; create_bail: - FSClose(bile->frefnum); - bile->frefnum = -1; - if (bile != NULL) - xfree(&bile); + if (fh != -1) + FSClose(fh); + xfree(&bile); return NULL; } @@ -127,14 +133,18 @@ bile_open(const Str255 filename, short vrefnum) struct bile *bile = NULL; char magic[BILE_MAGIC_LEN + 1]; size_t file_size, size; - short fh; + short fh = -1; _bile_error = 0; + bile = xmalloczero(sizeof(struct bile)); + if (bile == NULL) + return NULL; + /* open file */ _bile_error = FSOpen(filename, vrefnum, &fh); if (_bile_error) - return NULL; + goto open_bail; _bile_error = SetFPos(fh, fsFromLEOF, 0); if (_bile_error) @@ -142,10 +152,8 @@ bile_open(const Str255 filename, short vrefnum) GetFPos(fh, &file_size); SetFPos(fh, fsFromStart, 0); - bile = xmalloczero(sizeof(struct bile), "bile_open"); memcpy(bile->magic, BILE_MAGIC, sizeof(bile->magic)); bile->vrefnum = vrefnum; - bile->frefnum = fh; memcpy(bile->filename, filename, sizeof(bile->filename)); bile->file_size = file_size; @@ -165,13 +173,13 @@ bile_open(const Str255 filename, short vrefnum) /* load map pointer */ size = sizeof(bile->map_ptr); - _bile_error = FSRead(bile->frefnum, &size, &bile->map_ptr); + _bile_error = FSRead(fh, &size, &bile->map_ptr); if (_bile_error) goto open_bail; /* old map pointer */ size = sizeof(bile->old_map_ptr); - _bile_error = FSRead(bile->frefnum, &size, &bile->old_map_ptr); + _bile_error = FSRead(fh, &size, &bile->old_map_ptr); if (_bile_error) goto open_bail; @@ -181,6 +189,8 @@ bile_open(const Str255 filename, short vrefnum) bile->map_ptr = bile->old_map_ptr; } + bile->frefnum = fh; + if (bile->map_ptr.size) { if (bile_read_map(bile, &bile->map_ptr) != 0) { warn("bile_open: Failed reading map"); @@ -191,9 +201,9 @@ bile_open(const Str255 filename, short vrefnum) return bile; open_bail: - FSClose(fh); - if (bile != NULL) - xfree(&bile); + if (fh != -1) + FSClose(fh); + xfree(&bile); return NULL; } @@ -203,6 +213,10 @@ bile_check_sanity(struct bile *bile) if (bile == NULL) panic("bile_check_sanity: NULL bile"); + /* + * We check this at file open time, so if we got here and the magic + * is bad, we're pointing at a bogus address + */ if (memcmp(bile->magic, BILE_MAGIC, sizeof(bile->magic)) != 0) panic("bile_check_sanity: bogus magic"); } @@ -232,7 +246,7 @@ bile_flush(struct bile *bile, bool and_vol) short ret; bile_check_sanity(bile); - + memset(&pb, 0, sizeof(pb)); pb.ioRefNum = bile->frefnum; /* if we're not flushing the volume, write async */ @@ -268,7 +282,6 @@ struct bile_object * bile_find(struct bile *bile, const OSType type, const unsigned long id) { struct bile_object *o, *ocopy; - char note[MALLOC_NOTE_SIZE]; bile_check_sanity(bile); @@ -276,9 +289,12 @@ bile_find(struct bile *bile, const OSType type, const if (o == NULL) return NULL; - snprintf(note, sizeof(note), "bile_find %s %lu", OSTypeToString(type), - id); - ocopy = xmalloc(BILE_OBJECT_SIZE, note); + ocopy = xmalloc(BILE_OBJECT_SIZE); + if (ocopy == NULL) { + _bile_error = bile->last_error = BILE_ERR_NO_MEMORY; + return NULL; + } + memcpy(ocopy, o, BILE_OBJECT_SIZE); return ocopy; @@ -320,8 +336,13 @@ bile_ids_by_type(struct bile *bile, const OSType type, if (o->type != type) continue; - EXPAND_TO_FIT(ids, size, count * sizeof(size_t), sizeof(size_t), - 10 * sizeof(size_t)); + if (!grow_to_fit(&ids, &size, count * sizeof(size_t), sizeof(size_t), + 10 * sizeof(size_t))) { + if (ids != NULL) + xfree(&ids); + *ret = NULL; + return 0; + } ids[count++] = o->id; } @@ -337,7 +358,11 @@ bile_sorted_ids_by_type(struct bile *bile, const OSTyp unsigned long *ids = NULL; count = bile_ids_by_type(bile, type, &ids); - + if (count == 0) { + *ret = NULL; + return 0; + } + for (n = 0; n < count; n++) { for (j = 0; j < count - n - 1; j++) { if (ids[j] > ids[j + 1]) { @@ -358,7 +383,6 @@ bile_get_nth_of_type(struct bile *bile, const unsigned { struct bile_object *o, *ocopy; size_t n, count = 0; - char note[MALLOC_NOTE_SIZE]; bile_check_sanity(bile); @@ -370,9 +394,11 @@ bile_get_nth_of_type(struct bile *bile, const unsigned continue; if (count == index) { - snprintf(note, sizeof(note), "bile_get_nth %s %lu", - OSTypeToString(type), index); - ocopy = xmalloc(BILE_OBJECT_SIZE, note); + ocopy = xmalloc(BILE_OBJECT_SIZE); + if (ocopy == NULL) { + _bile_error = bile->last_error = BILE_ERR_NO_MEMORY; + return NULL; + } memcpy(ocopy, o, BILE_OBJECT_SIZE); return ocopy; } @@ -405,6 +431,8 @@ bile_next_id(struct bile *bile, const OSType type) if (highest > id) id = highest + 1; } + if (_bile_error) + return 0; return id; } @@ -424,7 +452,8 @@ bile_delete(struct bile *bile, const OSType type, cons o = bile_object_in_map(bile, type, id); if (o == NULL) { - _bile_error = bile->last_error = -1; + if (_bile_error) + return _bile_error; return -1; } @@ -466,6 +495,8 @@ bile_delete(struct bile *bile, const OSType type, cons /* store the type as the id, and the highest id as the data */ bile_write(bile, BILE_TYPE_HIGHESTID, type, &highest, sizeof(unsigned long)); + if (_bile_error) + return -1; /* bile_write wrote a new map for us */ } else if (flags & BILE_DELETE_FLAG_PURGE) { @@ -586,9 +617,7 @@ bile_read_alloc(struct bile *bile, const OSType type, const unsigned long id, void *data_ptr) { struct bile_object *o; - size_t ret; char **data; - char note[MALLOC_NOTE_SIZE]; bile_check_sanity(bile); @@ -605,12 +634,13 @@ bile_read_alloc(struct bile *bile, const OSType type, return 0; } - snprintf(note, sizeof(note), "bile_read_alloc %s %ld", - OSTypeToString(type), id); - *data = xmalloc(o->size, note); - ret = bile_read_object(bile, o, *data, o->size); + *data = xmalloc(o->size); + if (*data == NULL) { + _bile_error = bile->last_error = BILE_ERR_NO_MEMORY; + return 0; + } - return ret; + return bile_read_object(bile, o, *data, o->size); } size_t @@ -630,7 +660,11 @@ bile_resize(struct bile *bile, const OSType type, } /* if we're growing, fill new space with zero */ - data = xmalloczero(MAX(o->size, new_size), "bile_resize_object"); + data = xmalloczero(MAX(o->size, new_size)); + if (data == NULL) { + _bile_error = bile->last_error = BILE_ERR_NO_MEMORY; + } + ret = bile_read_object(bile, o, data, o->size); if (ret != o->size) { _bile_error = bile->last_error = -1; @@ -664,6 +698,10 @@ bile_write(struct bile *bile, const OSType type, const old->type = BILE_TYPE_PURGE; new_obj = bile_alloc(bile, type, id, len); + if (new_obj == NULL) { + _bile_error = bile->last_error = BILE_ERR_NO_MEMORY; + return 0; + } wrote = bile_xwriteat(bile, new_obj->pos, new_obj, BILE_OBJECT_SIZE); if (wrote != BILE_OBJECT_SIZE || bile->last_error) @@ -685,7 +723,7 @@ bile_write(struct bile *bile, const OSType type, const short bile_marshall_object(struct bile *bile, const struct bile_object_field *fields, const size_t nfields, - void *object, void *ret_ptr, size_t *ret_size, char *note) + void *object, void *ret_ptr, size_t *ret_size) { char **ret; char *data, *ptr; @@ -740,7 +778,11 @@ iterate_fields: } if (!write) { - data = xmalloc(size, note); + data = xmalloc(size); + if (data == NULL) { + _bile_error = bile->last_error = BILE_ERR_NO_MEMORY; + return BILE_ERR_NO_MEMORY; + } write = true; size = 0; goto iterate_fields; @@ -756,7 +798,7 @@ short bile_unmarshall_object(struct bile *bile, const struct bile_object_field *fields, const size_t nfields, const void *data, const size_t data_size, void *object, - const size_t object_size, bool deep, char *note) + const size_t object_size, bool deep) { size_t off, fsize = 0, n; char *ptr, *dptr; @@ -782,7 +824,11 @@ bile_unmarshall_object(struct bile *bile, memset(ptr, 0, sizeof(dptr)); continue; } - dptr = xmalloc(fsize, note); + dptr = xmalloc(fsize); + if (dptr == NULL) { + _bile_error = bile->last_error = BILE_ERR_NO_MEMORY; + return BILE_ERR_NO_MEMORY; + } memcpy(ptr, &dptr, sizeof(dptr)); ptr = dptr; } @@ -804,7 +850,6 @@ bile_unmarshall_object(struct bile *bile, return 0; } - short bile_verify(struct bile *bile) { @@ -859,6 +904,7 @@ bile_alloc(struct bile *bile, const OSType type, const { size_t last_pos = BILE_HEADER_LEN; size_t n, map_pos; + struct bile_object *new_map; bile_check_sanity(bile); @@ -890,9 +936,14 @@ bile_alloc(struct bile *bile, const OSType type, const } } + new_map = xreallocarray(bile->map, bile->nobjects + 1, + BILE_OBJECT_SIZE); + if (new_map == NULL) { + _bile_error = bile->last_error = BILE_ERR_NO_MEMORY; + return NULL; + } + bile->map = new_map; bile->nobjects++; - bile->map = xreallocarray(bile->map, bile->nobjects, BILE_OBJECT_SIZE); - if (map_pos + 1 < bile->nobjects) { /* shift remaining objects up */ memmove(&bile->map[map_pos + 1], &bile->map[map_pos], @@ -951,7 +1002,11 @@ bile_read_map(struct bile *bile, struct bile_object *m /* read entire map */ size = map_obj.size; - map = xmalloczero(size, "bile_read_map"); + map = xmalloczero(size); + if (map == NULL) { + _bile_error = bile->last_error = BILE_ERR_NO_MEMORY; + return -1; + } _bile_error = FSRead(bile->frefnum, &size, map); if (_bile_error) { xfree(&map); @@ -989,8 +1044,17 @@ bile_write_map(struct bile *bile) new_map_size = BILE_OBJECT_SIZE * new_nobjects; new_map_obj = bile_alloc(bile, BILE_TYPE_MAP, new_map_id, new_map_size); - new_map = xcalloc(BILE_OBJECT_SIZE, new_nobjects, "bile_write_map"); - + if (new_map_obj == NULL) { + _bile_error = bile->last_error = BILE_ERR_NO_MEMORY; + return BILE_ERR_NO_MEMORY; + } + new_map = xcalloc(BILE_OBJECT_SIZE, new_nobjects); + if (new_map == NULL) { + xfree(&new_map_obj); + _bile_error = bile->last_error = BILE_ERR_NO_MEMORY; + return BILE_ERR_NO_MEMORY; + } + for (n = 0, new_nobjects = 0; n < bile->nobjects; n++) { obj = &bile->map[n]; --- bile.h Wed Mar 1 09:19:35 2023 +++ bile.h Wed Mar 1 13:21:29 2023 @@ -76,6 +76,7 @@ struct bile_object { #define BILE_ERR_NEED_UPGRADE_1 -4000 #define BILE_ERR_BOGUS_OBJECT -4001 +#define BILE_ERR_NO_MEMORY -4002 #define BILE_DELETE_FLAG_ZERO (1 << 0) #define BILE_DELETE_FLAG_PURGE (1 << 1) @@ -146,11 +147,11 @@ short bile_verify(struct bile *bile); short bile_marshall_object(struct bile *bile, const struct bile_object_field *fields, const size_t nfields, void *object, - void *ret_ptr, size_t *ret_size, char *note); + void *ret_ptr, size_t *ret_size); short bile_unmarshall_object(struct bile *bile, const struct bile_object_field *fields, const size_t nfields, const void *data, const size_t data_size, void *object, - const size_t object_size, bool deep, char *note); + const size_t object_size, bool deep); #endif