fix(obj): add missing alloc check for children and spec_attr (#9795)

This commit is contained in:
André Costa
2026-04-03 09:51:51 +02:00
committed by GitHub
parent ff65e702e6
commit ec2e040806
12 changed files with 135 additions and 76 deletions
+4 -2
View File
@@ -129,10 +129,12 @@ void lv_group_add_obj(lv_group_t * group, lv_obj_t * obj)
LV_LOG_TRACE("begin");
if(!lv_obj_allocate_spec_attr(obj)) {
return;
}
/*Be sure the object is removed from its current group*/
lv_group_remove_obj(obj);
if(obj->spec_attr == NULL) lv_obj_allocate_spec_attr(obj);
obj->spec_attr->group_p = group;
lv_obj_t ** next = lv_ll_ins_tail(&group->obj_ll);
+56 -9
View File
@@ -411,20 +411,67 @@ lv_group_t * lv_obj_get_group(const lv_obj_t * obj)
* OTHER FUNCTIONS
*------------------*/
void lv_obj_allocate_spec_attr(lv_obj_t * obj)
lv_result_t lv_obj_add_child(lv_obj_t * parent, lv_obj_t * child)
{
LV_ASSERT_OBJ(parent, MY_CLASS);
uint16_t new_child_cnt = parent->spec_attr->child_cnt + 1;
lv_obj_t ** children = lv_realloc(parent->spec_attr->children,
new_child_cnt * (sizeof(lv_obj_t *)));
if(!children) {
return LV_RESULT_INVALID;
}
children[new_child_cnt - 1] = child;
parent->spec_attr->child_cnt = new_child_cnt;
parent->spec_attr->children = children;
return LV_RESULT_OK;
}
void lv_obj_remove_child(lv_obj_t * parent, lv_obj_t * child)
{
LV_ASSERT_OBJ(parent, MY_CLASS);
LV_ASSERT_OBJ(child, MY_CLASS);
for(int32_t i = lv_obj_get_index(child); i < (int32_t)parent->spec_attr->child_cnt - 1; i++) {
parent->spec_attr->children[i] = parent->spec_attr->children[i + 1];
}
/* No more children*/
if(parent->spec_attr->child_cnt == 1) {
lv_free(parent->spec_attr->children);
parent->spec_attr->children = NULL;
parent->spec_attr->child_cnt = 0;
return;
}
parent->spec_attr->child_cnt--;
parent->spec_attr->children = lv_realloc(parent->spec_attr->children,
parent->spec_attr->child_cnt * (sizeof(lv_obj_t *)));
/* Reallocating a smaller size should never fail, so assert it here*/
LV_ASSERT_MALLOC(parent->spec_attr->children);
}
lv_obj_spec_attr_t * lv_obj_allocate_spec_attr(lv_obj_t * obj)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
if(obj->spec_attr == NULL) {
obj->spec_attr = lv_malloc_zeroed(sizeof(lv_obj_spec_attr_t));
LV_ASSERT_MALLOC(obj->spec_attr);
if(obj->spec_attr == NULL) return;
obj->spec_attr->scroll_dir = LV_DIR_ALL;
obj->spec_attr->scrollbar_mode = LV_SCROLLBAR_MODE_AUTO;
if(obj->spec_attr) {
return obj->spec_attr;
}
lv_obj_spec_attr_t * spec_attr = lv_malloc_zeroed(sizeof(lv_obj_spec_attr_t));
LV_ASSERT_MALLOC(spec_attr);
if(!spec_attr) {
return NULL;
}
spec_attr->scroll_dir = LV_DIR_ALL;
spec_attr->scrollbar_mode = LV_SCROLLBAR_MODE_AUTO;
obj->spec_attr = spec_attr;
return spec_attr;
}
bool lv_obj_check_type(const lv_obj_t * obj, const lv_obj_class_t * class_p)
{
if(obj == NULL) return false;
-6
View File
@@ -313,12 +313,6 @@ void * lv_obj_get_user_data(lv_obj_t * obj);
* Other functions
*======================*/
/**
* Allocate special data for an object if not allocated yet.
* @param obj pointer to an object
*/
void lv_obj_allocate_spec_attr(lv_obj_t * obj);
/**
* Check the type of obj.
* @param obj pointer to an object
+8 -7
View File
@@ -88,14 +88,15 @@ lv_obj_t * lv_obj_class_create_obj(const lv_obj_class_t * class_p, lv_obj_t * pa
else {
LV_TRACE_OBJ_CREATE("creating normal object");
LV_ASSERT_OBJ(parent, MY_CLASS);
if(parent->spec_attr == NULL) {
lv_obj_allocate_spec_attr(parent);
}
parent->spec_attr->child_cnt++;
parent->spec_attr->children = lv_realloc(parent->spec_attr->children,
sizeof(lv_obj_t *) * parent->spec_attr->child_cnt);
parent->spec_attr->children[parent->spec_attr->child_cnt - 1] = obj;
if(!lv_obj_allocate_spec_attr(parent)) {
lv_free(obj);
return NULL;
}
if(lv_obj_add_child(parent, obj) != LV_RESULT_OK) {
lv_free(obj);
return NULL;
}
}
return obj;
+4 -1
View File
@@ -411,7 +411,10 @@ void lv_obj_refresh_ext_draw_size(lv_obj_t * obj)
/*Allocate spec. attrs. only if the result is not zero.
*Zero is the default value if the spec. attr. are not defined.*/
else if(s_new != 0) {
lv_obj_allocate_spec_attr(obj);
if(!lv_obj_allocate_spec_attr(obj)) {
LV_PROFILER_DRAW_END;
return;
}
obj->spec_attr->ext_draw_size = s_new;
}
+3 -1
View File
@@ -102,7 +102,9 @@ lv_result_t lv_obj_event_base(const lv_obj_class_t * class_p, lv_event_t * e)
lv_event_dsc_t * lv_obj_add_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb, lv_event_code_t filter, void * user_data)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
lv_obj_allocate_spec_attr(obj);
if(!lv_obj_allocate_spec_attr(obj)) {
return NULL;
}
return lv_event_add(&obj->spec_attr->event_list, event_cb, filter, user_data);
}
+7 -2
View File
@@ -1213,7 +1213,9 @@ void lv_obj_set_ext_click_area(lv_obj_t * obj, int32_t size)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
lv_obj_allocate_spec_attr(obj);
if(!lv_obj_allocate_spec_attr(obj)) {
return;
}
obj->spec_attr->ext_click_pad = size;
}
@@ -1274,7 +1276,10 @@ void lv_obj_set_transform(lv_obj_t * obj, const lv_matrix_t * matrix)
return;
}
lv_obj_allocate_spec_attr(obj);
if(!lv_obj_allocate_spec_attr(obj)) {
return;
}
if(!obj->spec_attr->matrix) {
obj->spec_attr->matrix = lv_malloc(sizeof(lv_matrix_t));
LV_ASSERT_MALLOC(obj->spec_attr->matrix);
+14 -2
View File
@@ -28,7 +28,7 @@ extern "C" {
* Special, rarely used attributes.
* They are allocated automatically if any elements is set.
*/
struct _lv_obj_spec_attr_t {
typedef struct _lv_obj_spec_attr_t {
lv_obj_t ** children; /**< Store the pointer of the children in an array.*/
lv_group_t * group_p;
#if LV_DRAW_TRANSFORM_USE_MATRIX
@@ -50,7 +50,9 @@ struct _lv_obj_spec_attr_t {
uint16_t scroll_dir : 4; /**< The allowed scroll direction(s), see `lv_dir_t`*/
uint16_t layer_type : 2; /**< Cache the layer type here. Element of lv_intermediate_layer_type_t */
uint16_t name_static : 1; /**< 1: `name` was not dynamically allocated */
};
} lv_obj_spec_attr_t;
struct _lv_obj_t {
#if LV_USE_EXT_DATA
@@ -92,6 +94,16 @@ struct _lv_obj_t {
* GLOBAL PROTOTYPES
**********************/
/**
* Allocate special data for an object if not allocated yet.
* @param obj pointer to an object
* @return the spec_attr created or NULL if something went wrong
*/
lv_obj_spec_attr_t * lv_obj_allocate_spec_attr(lv_obj_t * obj);
lv_result_t lv_obj_add_child(lv_obj_t * parent, lv_obj_t * child);
void lv_obj_remove_child(lv_obj_t * parent, lv_obj_t * child);
/**********************
* MACROS
**********************/
+15 -5
View File
@@ -63,7 +63,9 @@ void lv_obj_set_scrollbar_mode(lv_obj_t * obj, lv_scrollbar_mode_t mode)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
lv_obj_allocate_spec_attr(obj);
if(!lv_obj_allocate_spec_attr(obj)) {
return;
}
if(obj->spec_attr->scrollbar_mode == mode) return;
obj->spec_attr->scrollbar_mode = mode;
@@ -72,7 +74,9 @@ void lv_obj_set_scrollbar_mode(lv_obj_t * obj, lv_scrollbar_mode_t mode)
void lv_obj_set_scroll_dir(lv_obj_t * obj, lv_dir_t dir)
{
lv_obj_allocate_spec_attr(obj);
if(!lv_obj_allocate_spec_attr(obj)) {
return;
}
if(dir != obj->spec_attr->scroll_dir) {
obj->spec_attr->scroll_dir = dir;
@@ -81,13 +85,17 @@ void lv_obj_set_scroll_dir(lv_obj_t * obj, lv_dir_t dir)
void lv_obj_set_scroll_snap_x(lv_obj_t * obj, lv_scroll_snap_t align)
{
lv_obj_allocate_spec_attr(obj);
if(!lv_obj_allocate_spec_attr(obj)) {
return;
}
obj->spec_attr->scroll_snap_x = align;
}
void lv_obj_set_scroll_snap_y(lv_obj_t * obj, lv_scroll_snap_t align)
{
lv_obj_allocate_spec_attr(obj);
if(!lv_obj_allocate_spec_attr(obj)) {
return;
}
obj->spec_attr->scroll_snap_y = align;
}
@@ -418,7 +426,9 @@ lv_result_t lv_obj_scroll_by_raw(lv_obj_t * obj, int32_t x, int32_t y)
{
if(x == 0 && y == 0) return LV_RESULT_OK;
lv_obj_allocate_spec_attr(obj);
if(!lv_obj_allocate_spec_attr(obj)) {
return LV_RESULT_INVALID;
}
obj->spec_attr->scroll.x += x;
obj->spec_attr->scroll.y += y;
+3 -1
View File
@@ -637,7 +637,9 @@ void lv_obj_update_layer_type(lv_obj_t * obj)
lv_layer_type_t layer_type = calculate_layer_type(obj);
if(obj->spec_attr) obj->spec_attr->layer_type = layer_type;
else if(layer_type != LV_LAYER_TYPE_NONE) {
lv_obj_allocate_spec_attr(obj);
if(!lv_obj_allocate_spec_attr(obj)) {
return;
}
obj->spec_attr->layer_type = layer_type;
}
}
+21 -38
View File
@@ -163,38 +163,25 @@ void lv_obj_set_parent(lv_obj_t * obj, lv_obj_t * parent)
return;
}
lv_obj_invalidate(obj);
lv_obj_allocate_spec_attr(parent);
lv_obj_t * old_parent = obj->parent;
/*Remove the object from the old parent's child list*/
int32_t i;
for(i = lv_obj_get_index(obj); i <= (int32_t)lv_obj_get_child_count(old_parent) - 2; i++) {
old_parent->spec_attr->children[i] = old_parent->spec_attr->children[i + 1];
}
old_parent->spec_attr->child_cnt--;
if(old_parent->spec_attr->child_cnt) {
old_parent->spec_attr->children = lv_realloc(old_parent->spec_attr->children,
old_parent->spec_attr->child_cnt * (sizeof(lv_obj_t *)));
}
else {
lv_free(old_parent->spec_attr->children);
old_parent->spec_attr->children = NULL;
if(!lv_obj_allocate_spec_attr(parent)) {
return;
}
/*Add the child to the new parent as the last (newest child)*/
parent->spec_attr->child_cnt++;
parent->spec_attr->children = lv_realloc(parent->spec_attr->children,
parent->spec_attr->child_cnt * (sizeof(lv_obj_t *)));
parent->spec_attr->children[lv_obj_get_child_count(parent) - 1] = obj;
/*Add the object to the new parents list first*/
if(lv_obj_add_child(parent, obj) != LV_RESULT_OK) {
LV_LOG_WARN("Failed to attach child to parent");
return;
}
obj->parent = parent;
/*Remove the object from the old parent's child list
* This should never fail, thus we do only do it after adding it to the new parent's list*/
lv_obj_remove_child(obj->parent, obj);
/*Notify the original parent because one of its children is lost*/
lv_obj_scrollbar_invalidate(old_parent);
lv_obj_send_event(old_parent, LV_EVENT_CHILD_CHANGED, obj);
lv_obj_send_event(old_parent, LV_EVENT_CHILD_DELETED, NULL);
lv_obj_scrollbar_invalidate(obj->parent);
lv_obj_send_event(obj->parent, LV_EVENT_CHILD_CHANGED, obj);
lv_obj_send_event(obj->parent, LV_EVENT_CHILD_DELETED, NULL);
obj->parent = parent;
/*Notify the new parent about the child*/
lv_obj_send_event(parent, LV_EVENT_CHILD_CHANGED, obj);
@@ -426,7 +413,9 @@ void lv_obj_set_name(lv_obj_t * obj, const char * name)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
lv_obj_allocate_spec_attr(obj);
if(!lv_obj_allocate_spec_attr(obj)) {
return;
}
if(!obj->spec_attr->name_static && obj->spec_attr->name) lv_free((void *)obj->spec_attr->name);
@@ -444,8 +433,9 @@ void lv_obj_set_name_static(lv_obj_t * obj, const char * name)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
lv_obj_allocate_spec_attr(obj);
if(!lv_obj_allocate_spec_attr(obj)) {
return;
}
if(!obj->spec_attr->name_static && obj->spec_attr->name) lv_free((void *)obj->spec_attr->name);
obj->spec_attr->name = name;
@@ -740,14 +730,7 @@ static void obj_delete_core(lv_obj_t * obj)
}
/*Remove the object from the child list of its parent*/
else {
int32_t id = lv_obj_get_index(obj);
uint16_t i;
for(i = id; i < obj->parent->spec_attr->child_cnt - 1; i++) {
obj->parent->spec_attr->children[i] = obj->parent->spec_attr->children[i + 1];
}
obj->parent->spec_attr->child_cnt--;
obj->parent->spec_attr->children = lv_realloc(obj->parent->spec_attr->children,
obj->parent->spec_attr->child_cnt * sizeof(lv_obj_t *));
lv_obj_remove_child(obj->parent, obj);
}
/*Free the object itself*/
-2
View File
@@ -188,8 +188,6 @@ typedef struct _lv_hit_test_info_t lv_hit_test_info_t;
typedef struct _lv_cover_check_info_t lv_cover_check_info_t;
typedef struct _lv_obj_spec_attr_t lv_obj_spec_attr_t;
typedef struct _lv_image_t lv_image_t;
typedef struct _lv_animimg_t lv_animimg_t;