user32: Fail if inserting a submenu would create a loop in the menu hierarchy.
This commit is contained in:
parent
9baf7864c5
commit
38dbe067c3
@ -147,6 +147,11 @@ typedef struct
|
|||||||
#define MENU_TOP_MARGIN 3
|
#define MENU_TOP_MARGIN 3
|
||||||
#define MENU_BOTTOM_MARGIN 2
|
#define MENU_BOTTOM_MARGIN 2
|
||||||
|
|
||||||
|
/* maximum allowed depth of any branch in the menu tree.
|
||||||
|
* This value is slightly larger than in windows (25) to
|
||||||
|
* stay on the safe side. */
|
||||||
|
#define MAXMENUDEPTH 30
|
||||||
|
|
||||||
/* (other menu->FocusedItem values give the position of the focused item) */
|
/* (other menu->FocusedItem values give the position of the focused item) */
|
||||||
#define NO_SELECTED_ITEM 0xffff
|
#define NO_SELECTED_ITEM 0xffff
|
||||||
|
|
||||||
@ -4626,6 +4631,30 @@ static inline void set_menu_item_text( MENUITEM *menu, LPCWSTR text, BOOL unicod
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* MENU_depth
|
||||||
|
*
|
||||||
|
* detect if there are loops in the menu tree (or the depth is too large)
|
||||||
|
*/
|
||||||
|
static int MENU_depth( POPUPMENU *pmenu, int depth)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
MENUITEM *item;
|
||||||
|
|
||||||
|
depth++;
|
||||||
|
if( depth > MAXMENUDEPTH) return depth;
|
||||||
|
item = pmenu->items;
|
||||||
|
for( i = 0; i < pmenu->nItems && depth <= MAXMENUDEPTH; i++, item++){
|
||||||
|
POPUPMENU *psubmenu = MENU_GetMenu( item->hSubMenu);
|
||||||
|
if( psubmenu){
|
||||||
|
int bdepth = MENU_depth( psubmenu, depth);
|
||||||
|
if( bdepth > depth) depth = bdepth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* SetMenuItemInfo_common
|
* SetMenuItemInfo_common
|
||||||
*
|
*
|
||||||
@ -4664,10 +4693,14 @@ static BOOL SetMenuItemInfo_common(MENUITEM * menu,
|
|||||||
if (menu->hSubMenu) {
|
if (menu->hSubMenu) {
|
||||||
POPUPMENU *subMenu = MENU_GetMenu(menu->hSubMenu);
|
POPUPMENU *subMenu = MENU_GetMenu(menu->hSubMenu);
|
||||||
if (subMenu) {
|
if (subMenu) {
|
||||||
|
if( MENU_depth( subMenu, 0) > MAXMENUDEPTH) {
|
||||||
|
ERR( "Loop detected in menu hierarchy or maximum menu depth exceeded!\n");
|
||||||
|
menu->hSubMenu = 0;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
subMenu->wFlags |= MF_POPUP;
|
subMenu->wFlags |= MF_POPUP;
|
||||||
menu->fType |= MF_POPUP;
|
menu->fType |= MF_POPUP;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
SetLastError( ERROR_INVALID_PARAMETER);
|
SetLastError( ERROR_INVALID_PARAMETER);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -3018,6 +3018,7 @@ static void test_menu_maxdepth(void)
|
|||||||
int i;
|
int i;
|
||||||
DWORD ret;
|
DWORD ret;
|
||||||
|
|
||||||
|
SetLastError(12345678);
|
||||||
for( i = 0; i < NR_MENUS; i++) {
|
for( i = 0; i < NR_MENUS; i++) {
|
||||||
hmenus[i] = CreatePopupMenu();
|
hmenus[i] = CreatePopupMenu();
|
||||||
if( !hmenus[i]) break;
|
if( !hmenus[i]) break;
|
||||||
@ -3028,7 +3029,7 @@ static void test_menu_maxdepth(void)
|
|||||||
if( !ret) break;
|
if( !ret) break;
|
||||||
}
|
}
|
||||||
trace("Maximum depth is %d\n", i);
|
trace("Maximum depth is %d\n", i);
|
||||||
todo_wine
|
ok( GetLastError() == 12345678, "unexpected error %d\n", GetLastError());
|
||||||
ok( i < NR_MENUS ||
|
ok( i < NR_MENUS ||
|
||||||
broken( i == NR_MENUS), /* win98, NT */
|
broken( i == NR_MENUS), /* win98, NT */
|
||||||
"no ( or very large) limit on menu depth!\n");
|
"no ( or very large) limit on menu depth!\n");
|
||||||
@ -3055,7 +3056,6 @@ static void test_menu_circref(void)
|
|||||||
ok( ret, "AppendMenu failed, error is %d\n", GetLastError());
|
ok( ret, "AppendMenu failed, error is %d\n", GetLastError());
|
||||||
/* now attempt to change the string of the first item of menu1 */
|
/* now attempt to change the string of the first item of menu1 */
|
||||||
ret = ModifyMenuA( menu1, (UINT_PTR)menu2, MF_POPUP, (UINT_PTR)menu2, "menu 2");
|
ret = ModifyMenuA( menu1, (UINT_PTR)menu2, MF_POPUP, (UINT_PTR)menu2, "menu 2");
|
||||||
todo_wine
|
|
||||||
ok( !ret ||
|
ok( !ret ||
|
||||||
broken( ret), /* win98, NT */
|
broken( ret), /* win98, NT */
|
||||||
"ModifyMenu should have failed.\n");
|
"ModifyMenu should have failed.\n");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user