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

Alexandre Julliard julliard at winehq.org
Fri Jul 24 08:49:56 CDT 2009


Module: wine
Branch: master
Commit: 38dbe067c370610d0a2423d1ce7702e36ddd2679
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=38dbe067c370610d0a2423d1ce7702e36ddd2679

Author: Rein Klazes <wijn at online.nl>
Date:   Fri Jul 24 09:18:34 2009 +0200

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

---

 dlls/user32/menu.c       |   37 +++++++++++++++++++++++++++++++++++--
 dlls/user32/tests/menu.c |    4 ++--
 2 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c
index 460378c..203340a 100644
--- a/dlls/user32/menu.c
+++ b/dlls/user32/menu.c
@@ -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
 
@@ -4627,6 +4632,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
  *
  * Note: does not support the MIIM_TYPE flag. Use the MIIM_FTYPE,
@@ -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;
             }
diff --git a/dlls/user32/tests/menu.c b/dlls/user32/tests/menu.c
index 7382ec0..a1af944 100644
--- a/dlls/user32/tests/menu.c
+++ b/dlls/user32/tests/menu.c
@@ -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");




More information about the wine-cvs mailing list