mirror of
https://github.com/lvgl/lvgl.git
synced 2026-06-01 00:51:49 +08:00
fix(grid): fix segfault when row/column screen descriptor is missing (#9790)
This commit is contained in:
committed by
GitHub
parent
f9c059715d
commit
0bf96cba10
@@ -192,7 +192,10 @@ static void grid_update(lv_obj_t * cont, void * user_data)
|
|||||||
|
|
||||||
lv_grid_calc_t c;
|
lv_grid_calc_t c;
|
||||||
lv_result_t res = calc(cont, &c);
|
lv_result_t res = calc(cont, &c);
|
||||||
if(res != LV_RESULT_OK) return;
|
if(res != LV_RESULT_OK) {
|
||||||
|
calc_free(&c);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
item_repos_hint_t hint;
|
item_repos_hint_t hint;
|
||||||
lv_memzero(&hint, sizeof(hint));
|
lv_memzero(&hint, sizeof(hint));
|
||||||
@@ -230,8 +233,8 @@ static void grid_update(lv_obj_t * cont, void * user_data)
|
|||||||
*/
|
*/
|
||||||
static lv_result_t calc(lv_obj_t * cont, lv_grid_calc_t * calc_out)
|
static lv_result_t calc(lv_obj_t * cont, lv_grid_calc_t * calc_out)
|
||||||
{
|
{
|
||||||
|
lv_memzero(calc_out, sizeof(lv_grid_calc_t));
|
||||||
if(lv_obj_get_child(cont, 0) == NULL) {
|
if(lv_obj_get_child(cont, 0) == NULL) {
|
||||||
lv_memzero(calc_out, sizeof(lv_grid_calc_t));
|
|
||||||
return LV_RESULT_INVALID;
|
return LV_RESULT_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,12 +285,19 @@ static lv_result_t calc_cols(lv_obj_t * cont, lv_grid_calc_t * c)
|
|||||||
|
|
||||||
const int32_t * col_templ;
|
const int32_t * col_templ;
|
||||||
col_templ = get_col_dsc(cont);
|
col_templ = get_col_dsc(cont);
|
||||||
|
|
||||||
|
/*If there is no descriptor check if it's a subgrid*/
|
||||||
bool subgrid = false;
|
bool subgrid = false;
|
||||||
if(col_templ == NULL) {
|
if(col_templ == NULL) {
|
||||||
lv_obj_t * parent = lv_obj_get_parent(cont);
|
lv_obj_t * parent = lv_obj_get_parent(cont);
|
||||||
|
if(parent == NULL) {
|
||||||
|
LV_LOG_WARN("No column descriptor, and there is no parent for a screen to process subgrid");
|
||||||
|
return LV_RESULT_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
col_templ = get_col_dsc(parent);
|
col_templ = get_col_dsc(parent);
|
||||||
if(col_templ == NULL) {
|
if(col_templ == NULL) {
|
||||||
LV_LOG_WARN("No col descriptor found even on the parent");
|
LV_LOG_WARN("No column descriptor found even on the parent");
|
||||||
return LV_RESULT_INVALID;
|
return LV_RESULT_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -375,9 +385,16 @@ static lv_result_t calc_rows(lv_obj_t * cont, lv_grid_calc_t * c)
|
|||||||
{
|
{
|
||||||
const int32_t * row_templ;
|
const int32_t * row_templ;
|
||||||
row_templ = get_row_dsc(cont);
|
row_templ = get_row_dsc(cont);
|
||||||
|
|
||||||
|
/*If there is no descriptor check if it's a subgrid*/
|
||||||
bool subgrid = false;
|
bool subgrid = false;
|
||||||
if(row_templ == NULL) {
|
if(row_templ == NULL) {
|
||||||
lv_obj_t * parent = lv_obj_get_parent(cont);
|
lv_obj_t * parent = lv_obj_get_parent(cont);
|
||||||
|
if(parent == NULL) {
|
||||||
|
LV_LOG_WARN("No row descriptor, and there is no parent for a screen to process subgrid");
|
||||||
|
return LV_RESULT_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
row_templ = get_row_dsc(parent);
|
row_templ = get_row_dsc(parent);
|
||||||
if(row_templ == NULL) {
|
if(row_templ == NULL) {
|
||||||
LV_LOG_WARN("No row descriptor found even on the parent");
|
LV_LOG_WARN("No row descriptor found even on the parent");
|
||||||
@@ -471,14 +488,53 @@ static lv_result_t calc_rows(lv_obj_t * cont, lv_grid_calc_t * c)
|
|||||||
static void item_repos(lv_obj_t * item, lv_grid_calc_t * c, item_repos_hint_t * hint)
|
static void item_repos(lv_obj_t * item, lv_grid_calc_t * c, item_repos_hint_t * hint)
|
||||||
{
|
{
|
||||||
if(lv_obj_has_flag_any(item, LV_OBJ_FLAG_IGNORE_LAYOUT | LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) return;
|
if(lv_obj_has_flag_any(item, LV_OBJ_FLAG_IGNORE_LAYOUT | LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) return;
|
||||||
uint32_t col_span = get_col_span(item);
|
|
||||||
uint32_t row_span = get_row_span(item);
|
int32_t col_span = get_col_span(item);
|
||||||
if(row_span == 0 || col_span == 0) return;
|
if(col_span <= 0) {
|
||||||
|
LV_LOG_WARN("Column span was %" LV_PRId32 ", setting it to 1", col_span);
|
||||||
|
col_span = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t row_span = get_row_span(item);
|
||||||
|
if(row_span <= 0) {
|
||||||
|
LV_LOG_WARN("Row span was %" LV_PRId32 ", setting it to 1", row_span);
|
||||||
|
row_span = 1;
|
||||||
|
}
|
||||||
|
|
||||||
bool rev = lv_obj_get_style_base_dir(lv_obj_get_parent(item), LV_PART_MAIN) == LV_BASE_DIR_RTL;
|
bool rev = lv_obj_get_style_base_dir(lv_obj_get_parent(item), LV_PART_MAIN) == LV_BASE_DIR_RTL;
|
||||||
|
|
||||||
uint32_t col_pos = get_col_pos(item);
|
int32_t col_pos = get_col_pos(item);
|
||||||
uint32_t row_pos = get_row_pos(item);
|
if(col_pos < 0) {
|
||||||
|
LV_LOG_WARN("Column position was %" LV_PRId32 ", setting it to 0", col_pos);
|
||||||
|
col_pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(col_pos >= (int32_t)c->col_num) {
|
||||||
|
LV_LOG_WARN("Column position was %" LV_PRId32 ", setting to %" LV_PRId32, col_pos, c->col_num - 1);
|
||||||
|
col_pos = c->col_num - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t row_pos = get_row_pos(item);
|
||||||
|
if(row_pos < 0) {
|
||||||
|
LV_LOG_WARN("Row position was %" LV_PRId32 ", setting it to 0", row_pos);
|
||||||
|
row_pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(row_pos >= (int32_t)c->row_num) {
|
||||||
|
LV_LOG_WARN("Row position was %" LV_PRId32 ", setting to %" LV_PRId32, row_pos, c->row_num - 1);
|
||||||
|
row_pos = c->row_num - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(col_pos + col_span > (int32_t)c->col_num) {
|
||||||
|
col_span = c->col_num - col_pos;
|
||||||
|
LV_LOG_WARN("Column span is too large, limiting it to %" LV_PRId32, col_span);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(row_pos + row_span > (int32_t)c->row_num) {
|
||||||
|
row_span = c->row_num - row_pos;
|
||||||
|
LV_LOG_WARN("Row span is too large, limiting it to %" LV_PRId32, row_span);
|
||||||
|
}
|
||||||
|
|
||||||
lv_grid_align_t col_align = get_cell_col_align(item);
|
lv_grid_align_t col_align = get_cell_col_align(item);
|
||||||
lv_grid_align_t row_align = get_cell_row_align(item);
|
lv_grid_align_t row_align = get_cell_row_align(item);
|
||||||
|
|
||||||
|
|||||||
@@ -122,4 +122,59 @@ void test_grid_rtl(void)
|
|||||||
TEST_ASSERT_EQUAL_SCREENSHOT("grid_rtl.png");
|
TEST_ASSERT_EQUAL_SCREENSHOT("grid_rtl.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void test_grid_no_crash_on_invalid_settings(void)
|
||||||
|
{
|
||||||
|
/*Should't crash because of these*/
|
||||||
|
|
||||||
|
/*No col/row descriptors on screen*/
|
||||||
|
lv_obj_t * scr = lv_obj_create(NULL);
|
||||||
|
lv_screen_load(scr);
|
||||||
|
lv_obj_set_style_layout(scr, LV_LAYOUT_GRID, 0);
|
||||||
|
lv_refr_now(NULL);
|
||||||
|
|
||||||
|
/*No col/row descriptors on a widget*/
|
||||||
|
lv_obj_t * cont = lv_obj_create(scr);
|
||||||
|
lv_obj_set_style_layout(cont, LV_LAYOUT_GRID, 0);
|
||||||
|
lv_refr_now(NULL);
|
||||||
|
|
||||||
|
/*Set a cell without having row/col descriptor on the parent*/
|
||||||
|
lv_obj_set_grid_cell(cont, LV_GRID_ALIGN_CENTER, 0, 1, LV_GRID_ALIGN_CENTER, 0, 1);
|
||||||
|
lv_refr_now(NULL);
|
||||||
|
|
||||||
|
/*Add grid descriptors*/
|
||||||
|
const int32_t col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
|
||||||
|
const int32_t row_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
|
||||||
|
lv_obj_set_grid_dsc_array(cont, col_dsc, row_dsc);
|
||||||
|
lv_refr_now(NULL);
|
||||||
|
|
||||||
|
lv_obj_t * label = lv_label_create(cont);
|
||||||
|
|
||||||
|
/*Zero span*/
|
||||||
|
lv_obj_set_grid_cell(label, LV_GRID_ALIGN_CENTER, 0, 0, LV_GRID_ALIGN_CENTER, 0, 0);
|
||||||
|
lv_refr_now(NULL);
|
||||||
|
|
||||||
|
/*Too large span*/
|
||||||
|
lv_obj_set_grid_cell(label, LV_GRID_ALIGN_CENTER, 0, 20, LV_GRID_ALIGN_CENTER, 0, 30);
|
||||||
|
lv_refr_now(NULL);
|
||||||
|
|
||||||
|
/*Negative span*/
|
||||||
|
lv_obj_set_grid_cell(label, LV_GRID_ALIGN_CENTER, 0, -50, LV_GRID_ALIGN_CENTER, 0, -20);
|
||||||
|
lv_refr_now(NULL);
|
||||||
|
|
||||||
|
/*Too large position*/
|
||||||
|
lv_obj_set_grid_cell(label, LV_GRID_ALIGN_CENTER, 30, 1, LV_GRID_ALIGN_CENTER, 20, 1);
|
||||||
|
lv_refr_now(NULL);
|
||||||
|
|
||||||
|
/*Negative position*/
|
||||||
|
lv_obj_set_grid_cell(label, LV_GRID_ALIGN_CENTER, -100, 1, LV_GRID_ALIGN_CENTER, -20, 1);
|
||||||
|
lv_refr_now(NULL);
|
||||||
|
|
||||||
|
/*Valid settings*/
|
||||||
|
lv_obj_set_grid_cell(label, LV_GRID_ALIGN_CENTER, 1, 2, LV_GRID_ALIGN_CENTER, 0, 1);
|
||||||
|
lv_refr_now(NULL);
|
||||||
|
TEST_PASS();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user