user32: Fail if inserting a submenu would create a loop in the menu hierarchy.

oldstable
Rein Klazes 2009-07-24 09:18:34 +02:00 committed by Alexandre Julliard
parent 9baf7864c5
commit 38dbe067c3
2 changed files with 37 additions and 4 deletions

View File

@ -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;
}

View File

@ -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");