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_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) */
|
||||
#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
|
||||
*
|
||||
|
@ -4664,10 +4693,14 @@ static BOOL SetMenuItemInfo_common(MENUITEM * menu,
|
|||
if (menu->hSubMenu) {
|
||||
POPUPMENU *subMenu = MENU_GetMenu(menu->hSubMenu);
|
||||
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;
|
||||
menu->fType |= MF_POPUP;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
SetLastError( ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
@ -3018,6 +3018,7 @@ static void test_menu_maxdepth(void)
|
|||
int i;
|
||||
DWORD ret;
|
||||
|
||||
SetLastError(12345678);
|
||||
for( i = 0; i < NR_MENUS; i++) {
|
||||
hmenus[i] = CreatePopupMenu();
|
||||
if( !hmenus[i]) break;
|
||||
|
@ -3028,7 +3029,7 @@ static void test_menu_maxdepth(void)
|
|||
if( !ret) break;
|
||||
}
|
||||
trace("Maximum depth is %d\n", i);
|
||||
todo_wine
|
||||
ok( GetLastError() == 12345678, "unexpected error %d\n", GetLastError());
|
||||
ok( i < NR_MENUS ||
|
||||
broken( i == NR_MENUS), /* win98, NT */
|
||||
"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());
|
||||
/* 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");
|
||||
todo_wine
|
||||
ok( !ret ||
|
||||
broken( ret), /* win98, NT */
|
||||
"ModifyMenu should have failed.\n");
|
||||
|
|
Loading…
Reference in New Issue