Hi,
Clearly documents says TVM_GETITEM message can fail.
https://msdn.microsoft.com/en-us/library/windows/desktop/bb773596(v=vs.85).aspx

Iupwin_tree.c there are lot calls to TVM_GETITEM message, without check
result.

Check if this works?

--- a\src\win\iupwin_tree.c     Sat Feb 10 21:58:52 2018
+++ b\src\win\iupwin_tree.c     Sat Feb 10 22:56:21 2018
@@ -199,14 +199,16 @@
 
   if (hPrevItem)
   {
-    int kindPrev;
+    int kindPrev = ITREE_BRANCH;
     TVITEM tviPrevItem;
 
     /* get the KIND attribute of reference node */ 
     tviPrevItem.hItem = hPrevItem;
     tviPrevItem.mask = TVIF_PARAM|TVIF_CHILDREN; 
     SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&tviPrevItem);
-    kindPrev = ((winTreeItemData*)tviPrevItem.lParam)->kind;
+    if (tviPrevItem.lParam) {
+       kindPrev = ((winTreeItemData*)tviPrevItem.lParam)->kind;
+    }
 
     /* Define the parent and the position to the new node inside
        the list, using the KIND attribute of reference node */
@@ -264,29 +266,41 @@
 static int winTreeIsItemExpanded(Ihandle* ih, HTREEITEM hItem)
 {
   TVITEM item;
+
   item.hItem = hItem;
   item.mask = TVIF_HANDLE | TVIF_STATE;
   SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&item);
-  return (item.state & TVIS_EXPANDED) != 0;
+  if (item.lParam)
+  {
+     return (item.state & TVIS_EXPANDED) != 0;
+  } 
+  else
+  {
+     return 0;
+  }
 }
 
 static int winTreeIsBranch(Ihandle* ih, HTREEITEM hItem)
 {
   TVITEM item;
-  winTreeItemData* itemData;
+  int kind = ITREE_BRANCH;
 
   item.mask = TVIF_HANDLE | TVIF_PARAM;
   item.hItem = hItem;
   SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&item);
-  itemData = (winTreeItemData*)item.lParam;
+  if (item.lParam)
+  {
+    winTreeItemData* itemData = (winTreeItemData*)item.lParam;
 
-  return (itemData->kind == ITREE_BRANCH);
+    kind = itemData->kind;
+  }
+
+  return (kind == ITREE_BRANCH);
 }
 
 static void winTreeExpandItem(Ihandle* ih, HTREEITEM hItem, int expand)
 {
   TVITEM item;
-  winTreeItemData* itemData;
 
   iupAttribSet(ih, "_IUPTREE_IGNORE_BRANCH_CB", "1");
   /* it only works if the branch has children */
@@ -297,15 +311,21 @@
   item.hItem = hItem;
   item.mask = TVIF_HANDLE|TVIF_PARAM;
   SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&item);
-  itemData = (winTreeItemData*)item.lParam;
-
-  if (expand)
-    item.iSelectedImage = item.iImage = (itemData->image_expanded!=-1)? 
itemData->image_expanded: (int)ih->data->def_image_expanded;
-  else
-    item.iSelectedImage = item.iImage = (itemData->image!=-1)? 
itemData->image: (int)ih->data->def_image_collapsed;
+  if (item.lParam)
+  {
+     winTreeItemData* itemData;
 
-  item.hItem = hItem;
-  item.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
+     itemData = (winTreeItemData*)item.lParam;
+     if (expand)
+        item.iSelectedImage = item.iImage = (itemData->image_expanded!=-1)? 
itemData->image_expanded: (int)ih->data->def_image_expanded;
+     else
+        item.iSelectedImage = item.iImage = (itemData->image!=-1)? 
itemData->image: (int)ih->data->def_image_collapsed;
+     item.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
+  }
+  else 
+  {
+     item.mask = TVIF_HANDLE;;
+  }
   SendMessage(ih->handle, TVM_SETITEM, 0, (LPARAM)(LPTVITEM)&item);
 }
 
@@ -493,13 +513,17 @@
   HTREEITEM new_hItem;
   TVITEM item; 
   TVINSERTSTRUCT tvins;
-  TCHAR title[255];
+  TCHAR title[256];
 
   item.hItem = hItem;
   item.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE | 
TVIF_TEXT | TVIF_STATE | TVIF_PARAM;
   item.pszText = title;
-  item.cchTextMax = 255;
+  item.cchTextMax = sizeof(title) - 1;
   SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&item);
+  if (!item.lParam)
+  {
+     return NULL;
+  }
 
   if (is_copy) /* during a copy the itemdata reference is not reused */
   {
@@ -551,19 +575,23 @@
   TVITEM item;
   winTreeItemData* itemDataDst;
   int id_new, count, id_src, id_dst;
+  int old_count;
 
-  int old_count = ih->data->node_count;
+  /* Get DST node attributes */
+  item.hItem = hItemDst;
+  item.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_STATE;
+  SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&item);
+  if (!item.lParam)
+  {
+     return NULL;
+  }
 
+  old_count = ih->data->node_count;
   id_src = iupTreeFindNodeId(ih, hItemSrc);
   id_dst = iupTreeFindNodeId(ih, hItemDst);
   id_new = id_dst+1; /* contains the position for a copy operation */
 
-  /* Get DST node attributes */
-  item.hItem = hItemDst;
-  item.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_STATE;
-  SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&item);
   itemDataDst = (winTreeItemData*)item.lParam;
-
   if (itemDataDst->kind == ITREE_BRANCH && (item.state & TVIS_EXPANDED))
   {
     /* copy as first child of expanded branch */
@@ -574,8 +602,7 @@
   {                                    
     if (itemDataDst->kind == ITREE_BRANCH)
     {
-      int child_count = iupdrvTreeTotalChildCount(ih, hItemDst);
-      id_new += child_count;
+      id_new += iupdrvTreeTotalChildCount(ih, hItemDst);
     }
 
     /* copy as next brother of item or collapsed branch */
@@ -633,6 +660,10 @@
     item.hItem = hItem;
     item.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE | 
TVIF_STATE;
     SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&item);
+    if (!item.lParam)
+    {
+       continue;
+    }
     itemData = (winTreeItemData*)item.lParam;
 
     if (itemData->kind == ITREE_BRANCH)

Best,
Ranier Vilela
________________________________________
De: 云风 Cloud Wu <[email protected]>
Enviado: sexta-feira, 9 de fevereiro de 2018 14:08
Para: [email protected]
Assunto: [Iup-users] winiup tree bug: Message from an item already deleted

I found a bug can crash the program today. It crash in

static int winTreeCallBranchLeafCb(Ihandle* ih, HTREEITEM hItem)   
@iupwin_tree.c

  SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&item);
  itemData = (winTreeItemData*)item.lParam;
  if (itemData->kind == ITREE_BRANCH)

SendMessage may return false, and itemData  will be NULL .

It may caused by delete nodes in `executeleaf_cb` .

It seems that windows may push a notify message before an item deleted, and 
then it recv this message, but the item is gone.

I try to make a minimal working example , but it doesn't work every time.

-------
local tree = iup.tree {
HIDEBUTTONS = "yes",
HIDELINES = "yes",
}

local dlg = iup.dialog {
tree,
margin = "4x4",
size = "HALFxHALF",
shrink="yes",
title = "Shader Compiler",
}

local function do_some_systemcall()
for i=1,100 do
                -- c:\\windows\\win.ini should be exist.
local f = io.open("c:\\windows\\win.ini","rb")
if f then
f:close()
end
end
end

local function rebuild_tree(flag, id)
tree.delnode0 = "CHILDREN"
tree.title0 = "foobar"
if flag then
tree.addbranch0 = "xxx"
tree.value = 1
do_some_systemcall()
for i=1,3 do
tree.addleaf1 = "xxx"
tree.image2 = "IMGCOLLAPSED"
end
do_some_systemcall()
else
tree.addleaf0 = "Click Me (may crash)"
tree.image1 = "IMGCOLLAPSED"
for i=0,3 do
do_some_systemcall()
tree.addleaf0 = "xxx"
tree.image1 = "IMGCOLLAPSED"
end
tree.value = id
end

function tree:executeleaf_cb(id)
rebuild_tree(not flag, id)
end

function tree:branchclose_cb(id)
rebuild_tree(not flag, id)
return iup.IGNORE
end
end

dlg:showxy(iup.CENTER,iup.CENTER)

rebuild_tree(false)

iup.MainLoop()
iup.Close()
-------

Run this program, and click the last item (named "Click Me") , it may crash on 
windows 10 64bit (1709/16299.192) .

I think we should check the result of  `SendMessage(ih->handle, TVM_GETITEM, 0, 
(LPARAM)(LPTVITEM)&item)` to fix it, or it there a better way ?

Attachment: iupwin_tree.patch
Description: iupwin_tree.patch

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Iup-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/iup-users

Reply via email to