mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-08 00:02:03 +02:00
LCL-GTK2: Fix double free in listview pixbuf due to wrong refcounting
The 'pixbuf' field in GtkCellRendererPixbuf is supposed to be private to Gtk which handles refcounting itself, but LCL modifies it directly which can cause refcounting mismatches, especially during the destruction of a listview with icons (images are unref'd by both the listview destructor and gtk itself). Since it is exposed as a property it can be modified using the g_object_set_property and g_value_xxx APIs which handle any necessary refcounting, so this patch replaces the direct modification of the pixbuf field with these APIs. This fixes the crashes due to refcounting mismatch.
This commit is contained in:
parent
a37599119b
commit
6a5e16239a
@ -445,8 +445,12 @@ var
|
||||
ImageList: TCustomImageList;
|
||||
Bmp: TBitmap;
|
||||
pixbuf: PGdkPixbuf;
|
||||
PixbufValue: TGValue;
|
||||
begin
|
||||
PGtkCellRendererPixbuf(cell)^.pixbuf := nil;
|
||||
PixbufValue:=Default(TGValue);
|
||||
g_value_init(@PixbufValue, GDK_TYPE_PIXBUF);
|
||||
g_object_set_property(G_OBJECT(cell), PChar('pixbuf'), @PixbufValue);
|
||||
g_value_unset(@PixbufValue);
|
||||
Widgets := PTVWidgets(WidgetInfo^.UserData);
|
||||
gtk_tree_model_get(tree_model, iter, [0, @ListItem, -1]);
|
||||
|
||||
@ -488,15 +492,19 @@ begin
|
||||
pixbuf := nil;
|
||||
ImageList.GetBitmap(ImageIndex, Bmp);
|
||||
Gtk2_PixBufFromBitmap(Bmp,pixbuf);
|
||||
PGtkCellRendererPixbuf(cell)^.pixbuf :=pixbuf;
|
||||
g_value_init(@PixbufValue, GDK_TYPE_PIXBUF);
|
||||
g_value_set_object(@PixbufValue, pixbuf);
|
||||
g_object_set_property(G_OBJECT(cell), PChar('pixbuf'), @PixbufValue);
|
||||
g_value_unset(@PixbufValue);
|
||||
finally
|
||||
Bmp.Free;
|
||||
end;
|
||||
end else
|
||||
if (ImageIndex > -1) and (ImageIndex <= Images.Count-1) then
|
||||
PGtkCellRendererPixbuf(cell)^.pixbuf := PGdkPixbuf(Images.Items[ImageIndex])
|
||||
else
|
||||
PGtkCellRendererPixbuf(cell)^.pixbuf := nil;
|
||||
g_value_init(@PixbufValue, GDK_TYPE_PIXBUF);
|
||||
if (ImageIndex > -1) and (ImageIndex <= Images.Count-1) and (Images.Items[ImageIndex] <> nil) then
|
||||
g_value_set_object(@PixbufValue, PGdkPixbuf(Images.Items[ImageIndex]));
|
||||
g_object_set_property(G_OBJECT(cell), PChar('pixbuf'), @PixbufValue);
|
||||
g_value_unset(@PixbufValue);
|
||||
end;
|
||||
|
||||
procedure Gtk2WSLV_ListViewGetPixbufDataFuncForIconView({%H-}cell_layout:PGtkCellLayout;
|
||||
@ -507,8 +515,12 @@ var
|
||||
Widgets: PTVWidgets;
|
||||
ImageIndex: Integer;
|
||||
APath: PGtkTreePath;
|
||||
PixbufValue: TGValue;
|
||||
begin
|
||||
PGtkCellRendererPixbuf(cell)^.pixbuf := nil;
|
||||
PixbufValue:=Default(TGValue);
|
||||
g_value_init(@PixbufValue, GDK_TYPE_PIXBUF);
|
||||
g_object_set_property(G_OBJECT(cell), 'pixbuf', @PixbufValue);
|
||||
g_value_unset(@PixbufValue);
|
||||
Widgets := PTVWidgets(WidgetInfo^.UserData);
|
||||
gtk_tree_model_get(tree_model, iter, [0, @ListItem, -1]);
|
||||
|
||||
@ -529,10 +541,11 @@ begin
|
||||
|
||||
ImageIndex := ListItem.ImageIndex;
|
||||
|
||||
g_value_init(@PixbufValue, GDK_TYPE_PIXBUF);
|
||||
if (ImageIndex > -1) and (ImageIndex <= Images.Count-1) then
|
||||
PGtkCellRendererPixbuf(cell)^.pixbuf := PGdkPixbuf(Images.Items[ImageIndex])
|
||||
else
|
||||
PGtkCellRendererPixbuf(cell)^.pixbuf := nil;
|
||||
g_value_set_object(@PixbufValue, PGdkPixbuf(Images.Items[ImageIndex]));
|
||||
g_object_set_property(G_OBJECT(cell), PChar('pixbuf'), @PixbufValue);
|
||||
g_value_unset(@PixbufValue);
|
||||
end;
|
||||
|
||||
{ TGtk2WSCustomListView }
|
||||
|
Loading…
Reference in New Issue
Block a user