summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2013-05-29 06:48:33 +0200
committerThomas Martitz <kugel@rockbox.org>2013-06-24 15:24:34 +0200
commit46ea8bfe7c690c8db230fff3a582a69779f8e432 (patch)
tree38367d14c1997b3b4d5b4c6c7fbd31d2c3de979e /firmware
parentd938ae692cfc720210236eccd7910abe15c761c0 (diff)
downloadrockbox-46ea8bfe7c690c8db230fff3a582a69779f8e432.tar.gz
rockbox-46ea8bfe7c690c8db230fff3a582a69779f8e432.zip
buflib: Allow handle to be freed entirely during the shrink callback.
Change-Id: I3a069dcb99bbd4022faf37596b03beb926d2ea82 Reviewed-on: http://gerrit.rockbox.org/480 Reviewed-by: Thomas Martitz <kugel@rockbox.org> Tested-by: Thomas Martitz <kugel@rockbox.org>
Diffstat (limited to 'firmware')
-rw-r--r--firmware/buflib.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/firmware/buflib.c b/firmware/buflib.c
index 9b591ad786..2ceb7fcb16 100644
--- a/firmware/buflib.c
+++ b/firmware/buflib.c
@@ -165,7 +165,7 @@ static union buflib_data* handle_to_block(struct buflib_context* ctx, int handle
165 union buflib_data* name_field = 165 union buflib_data* name_field =
166 (union buflib_data*)buflib_get_name(ctx, handle); 166 (union buflib_data*)buflib_get_name(ctx, handle);
167 167
168 return name_field - 3; 168 return name_field ? name_field - 3 : NULL;
169} 169}
170 170
171/* Shrink the handle table, returning true if its size was reduced, false if 171/* Shrink the handle table, returning true if its size was reduced, false if
@@ -353,11 +353,15 @@ buflib_compact_and_shrink(struct buflib_context *ctx, unsigned shrink_hints)
353 ret = this[2].ops->shrink_callback(handle, shrink_hints, 353 ret = this[2].ops->shrink_callback(handle, shrink_hints,
354 data, (char*)(this+this->val)-data); 354 data, (char*)(this+this->val)-data);
355 result |= (ret == BUFLIB_CB_OK); 355 result |= (ret == BUFLIB_CB_OK);
356 /* this might have changed in the callback (if 356 /* 'this' might have changed in the callback (if it shrinked
357 * it shrinked from the top), get it again */ 357 * from the top or even freed the handle), get it again */
358 this = handle_to_block(ctx, handle); 358 this = handle_to_block(ctx, handle);
359 /* The handle was possibly be freed in the callback,
360 * re-run the loop with the handle before */
361 if (!this)
362 this = before;
359 /* could also change with shrinking from back */ 363 /* could also change with shrinking from back */
360 if (last) 364 else if (last)
361 ctx->alloc_end = this + this->val; 365 ctx->alloc_end = this + this->val;
362 } 366 }
363 } 367 }
@@ -780,6 +784,8 @@ buflib_shrink(struct buflib_context* ctx, int handle, void* new_start, size_t ne
780const char* buflib_get_name(struct buflib_context *ctx, int handle) 784const char* buflib_get_name(struct buflib_context *ctx, int handle)
781{ 785{
782 union buflib_data *data = ALIGN_DOWN(buflib_get_data(ctx, handle), sizeof (*data)); 786 union buflib_data *data = ALIGN_DOWN(buflib_get_data(ctx, handle), sizeof (*data));
787 if (!data)
788 return NULL;
783 size_t len = data[-1].val; 789 size_t len = data[-1].val;
784 if (len <= 1) 790 if (len <= 1)
785 return NULL; 791 return NULL;