After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 65877 - gdk_event_copy() should only read parts of union for that event type
gdk_event_copy() should only read parts of union for that event type
Status: RESOLVED OBSOLETE
Product: gtk+
Classification: Platform
Component: Backend: X11
1.3.x
Other Solaris
: Normal normal
: Small API
Assigned To: gtk-bugs
gtk-bugs
Depends on:
Blocks: 470161
 
 
Reported: 2001-12-01 01:50 UTC by Hidetoshi Tajima
Modified: 2017-08-28 12:06 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Use GdkEvent to allocate sufficient buffer (2.06 KB, patch)
2001-12-04 04:19 UTC, Hidetoshi Tajima
committed Details | Review
only copy meaningful fields from GdkEvent (3.66 KB, patch)
2007-05-04 16:00 UTC, Tilman Sauerbeck
needs-work Details | Review

Description Hidetoshi Tajima 2001-12-01 01:50:03 UTC
Purify reports Stack array bounds read error when gdk_event_copy is called
from the above function.

GdkEvent*
gdk_event_copy (GdkEvent *event)
{
  GdkEvent *new_event;
  
  g_return_val_if_fail (event != NULL, NULL);
  
  new_event = _gdk_event_new ();
  
  *new_event = *event;		<=== SBR errors reported here
  if (new_event->any.window)
    gdk_window_ref (new_event->any.window);
...

This is because the pointer to the GdkEventWindowState struct(sizeof 20) 
is cast to GdkEvent*(pointer to the sizeof 72) and passed to the
gdk_event_put() (gdkevents.c:line 981).
Comment 1 Hidetoshi Tajima 2001-12-04 04:16:06 UTC
function trace around the error is below.
      
  SBR: Stack array bounds read (13 times)
      This is occurring while in:
            gdk_event_copy [gdkgdkevents.c:289]
            gdk_event_put  [gdkgdkevents.c:238]
            gdk_synthesize_window_state [gdkgdkevents.c:980]
            show_window_internal [x11gdkwindow-x11.c:902]
            gdk_window_show [x11gdkwindow-x11.c:954]
            gtk_window_map [gtkgtkwindow.c:3083]
      Reading 4 bytes from 0xffbedfc0.
      Frame pointer 0xffbedf90
      Address 0xffbedfc0 is       48 bytes above stack pointer in
function show_window_internal.

A sample patch will be attached after tbis comment.
Comment 2 Hidetoshi Tajima 2001-12-04 04:19:21 UTC
Created attachment 6134 [details] [review]
Use GdkEvent to allocate sufficient buffer
Comment 3 Owen Taylor 2001-12-04 16:41:28 UTC
Will commit shortly.

Tue Dec  4 11:38:40 2001  Owen Taylor  <otaylor@redhat.com>

	* gdk/gdkevents.c (gdk_synthesize_window_state): Use 
	a full GdkEvent structure to avoid reads of uninitialized/
	invalid memory in gdk_event_put() (#65877, patch
	from Hidetoshi Tajima)

But eventually, I think it's better if gdk_event_copy() only
copied the part of the structure that is used for the current
event type to just eliminate bugs of this type ... this is
not the first we've had.
Comment 4 Hidetoshi Tajima 2001-12-04 20:50:15 UTC
I verified the fix. Do you want to keep this bug open and make a better
fix in gdk_event_copy()?
Comment 5 Owen Taylor 2001-12-04 21:10:41 UTC
Yes, I want to keep this open on the future milestone (post-2.0)
as an API enhancement (which is why I've changed the Subject:
line)

Thanks for verifying.
Comment 6 Luis Villa 2004-04-29 15:03:55 UTC
Comment on attachment 6134 [details] [review]
Use GdkEvent to allocate sufficient buffer

committed, two and a half years ago.
Comment 7 Tilman Sauerbeck 2007-05-04 16:00:04 UTC
Created attachment 87543 [details] [review]
only copy meaningful fields from GdkEvent

I was bored.

Is there a definitive test for gdk_event_copy() somewhere?
Comment 8 Tim Janik 2007-05-28 02:11:43 UTC
Comment on attachment 87543 [details] [review]
only copy meaningful fields from GdkEvent

(In reply to comment #7)
> Created an attachment (id=87543) [edit]
> only copy meaningful fields from GdkEvent
> 
> I was bored.

thanks.

> 
> Is there a definitive test for gdk_event_copy() somewhere?

no, it'd be very good to have one though, care to cook one up?

>Index: gdk/gdkevents.c
>===================================================================
>--- gdk/gdkevents.c	(revision 17786)
>+++ gdk/gdkevents.c	(working copy)
>@@ -361,10 +361,6 @@
>   new_event = gdk_event_new (GDK_NOTHING);
>   new_private = (GdkEventPrivate *)new_event;
> 
>-  *new_event = *event;
>-  if (new_event->any.window)
>-    g_object_ref (new_event->any.window);
>-
>   if (gdk_event_is_allocated (event))
>     {
>       GdkEventPrivate *private = (GdkEventPrivate *)event;
>@@ -374,13 +370,24 @@
>   
>   switch (event->any.type)
>     {
>+    case GDK_CLIENT_EVENT:
>+      new_event->client = event->client;
>+      break;
>+
>+    case GDK_CONFIGURE:
>+      new_event->configure = event->configure;
>+      break;
>+
>     case GDK_KEY_PRESS:
>     case GDK_KEY_RELEASE:
>+      new_event->key = event->key;
>       new_event->key.string = g_strdup (event->key.string);
>       break;
>       
>     case GDK_ENTER_NOTIFY:
>     case GDK_LEAVE_NOTIFY:
>+      new_event->crossing = event->crossing;
>+
>       if (event->crossing.subwindow != NULL)
> 	g_object_ref (event->crossing.subwindow);
>       break;
>@@ -391,36 +398,100 @@
>     case GDK_DRAG_STATUS:
>     case GDK_DROP_START:
>     case GDK_DROP_FINISHED:
>+      new_event->dnd = event->dnd;
>       g_object_ref (event->dnd.context);
>       break;
>       
>     case GDK_EXPOSE:
>+      new_event->expose = event->expose;
>+
>       if (event->expose.region)
> 	new_event->expose.region = gdk_region_copy (event->expose.region);
>       break;
>-      
>+
>+    case GDK_FOCUS_CHANGE:
>+      new_event->focus_change = event->focus_change;
>+      break;
>+
>+    case GDK_GRAB_BROKEN:
>+      new_event->grab_broken = event->grab_broken;
>+      break;
>+
>+    case GDK_NO_EXPOSE:
>+      new_event->no_expose = event->no_expose;
>+      break;
>+
>     case GDK_SETTING:
>+      new_event->setting = event->setting;
>       new_event->setting.name = g_strdup (new_event->setting.name);
>       break;
> 
>     case GDK_BUTTON_PRESS:
>     case GDK_BUTTON_RELEASE:
>-      if (event->button.axes) 
>-	new_event->button.axes = g_memdup (event->button.axes, 
>+      new_event->button = event->button;
>+
>+	  if (event->any.type == GDK_BUTTON_PRESS || event->any.type == GDK_BUTTON_RELEASE)

this check is redundant, we already switched on any.type above and only enter here for GDK_BUTTON_PRESS or GDK_BUTTON_RELEASE. the original condition of if(event->button.axes) makes more sense to have here.

>+		  	new_event->button.axes = g_memdup (event->button.axes, 
> 					     sizeof (gdouble) * event->button.device->num_axes);
>       break;
> 
>+    case GDK_2BUTTON_PRESS:
>+    case GDK_3BUTTON_PRESS:
>+	  new_event->button = event->button;

hm, it'd make sense to verify here that button.axes os always NULL, or have thy copying code here as well.

>+      break;
>+
>     case GDK_MOTION_NOTIFY:
>+      new_event->motion = event->motion;
>+
>       if (event->motion.axes) 
> 	new_event->motion.axes = g_memdup (event->motion.axes, 
> 					   sizeof (gdouble) * event->motion.device->num_axes);
>       
>       break;
>-      
>-    default:
>+
>+    case GDK_OWNER_CHANGE:
>+      new_event->owner_change = event->owner_change;
>       break;
>+
>+    case GDK_PROPERTY_NOTIFY:
>+      new_event->property = event->property;
>+      break;
>+
>+    case GDK_PROXIMITY_IN:
>+    case GDK_PROXIMITY_OUT:
>+      new_event->proximity = event->proximity;
>+      break;
>+
>+    case GDK_SCROLL:
>+      new_event->scroll = event->scroll;
>+      break;
>+
>+    case GDK_SELECTION_CLEAR:
>+    case GDK_SELECTION_REQUEST:
>+    case GDK_SELECTION_NOTIFY:
>+      new_event->selection = event->selection;
>+      break;
>+
>+    case GDK_VISIBILITY_NOTIFY:
>+      new_event->visibility = event->visibility;
>+      break;
>+
>+    case GDK_WINDOW_STATE:
>+      new_event->window_state = event->window_state;
>+      break;
>+
>+    case GDK_NOTHING:
>+    case GDK_DELETE:
>+    case GDK_DESTROY:
>+    case GDK_MAP:
>+    case GDK_UNMAP:
>+      new_event->any = event->any;
>+      break;
>     }
>   
>+  if (new_event->any.window)
>+    g_object_ref (new_event->any.window);
>+
>   return new_event;
> }
Comment 9 Eric 2009-11-28 07:17:22 UTC
(In reply to comment #0)
> Purify reports Stack array bounds read error when gdk_event_copy is called
> from the above function.
> 
> GdkEvent*
> gdk_event_copy (GdkEvent *event)
> {
>   GdkEvent *new_event;
>   
>   g_return_val_if_fail (event != NULL, NULL);
>   
>   new_event = _gdk_event_new ();
>   
>   *new_event = *event;		<=== SBR errors reported here
>   if (new_event->any.window)
>     gdk_window_ref (new_event->any.window);
> ...
> 
> This is because the pointer to the GdkEventWindowState struct(sizeof 20) 
> is cast to GdkEvent*(pointer to the sizeof 72) and passed to the
> gdk_event_put() (gdkevents.c:line 981).
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
*DOES THIS HELP IT WAS WRITTEN IN ANSI C99 International Standards Organization*
*Form:
*I do not even know why I chose this code I guess I wanted to try something    *
*in *C and help at the same time                                               *
///////////////////////////////////////////////////////////////////////////////
#ifndef GTK_Event_Copy_H
#define GTK_Event_Copy_H
///////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdbool.h>
#include <stdio.h>
#include <STL_Include_Packet.h>
///////////////////////////////////////////////////////////////////////////////
//Purify reports Stack array bounds read error when gdk_event_copy is called
//from the above function.
struct All_Events
  {
  };struct All_Events new_event;
/////////////////////////////////////////////////////
struct Any_Property
  {
  char* window[];
  };struct Any_Property Any;
/////////////////////////////////////////////////////
typedef char* GDK_Event[]; //recieving input

GDK_Event new_event; // creating a new event as: "new_event" //
////////////////////////////////////////////////////
//  g_return_val_if_fail (event != NULL, NULL);
// creating a new array of type: "GDK_Event" //
GDK_Event new_event, event_01, event_02;
/////////////////////////////////////////////////////////////////////////////////////////
char* gdk_event_new(void)
 {
 char* array_01[];
 return(array_01);
 };
/////////////////////////////////////////////////////////////////////////////////////////
void gdk_window_ref(char the_switch)
  {
  if(new_event-> *Any.window)
    {
    char* variable[];
    return(variable);// generating a new variable //
    };
  };
////////////////////////////////////////////////////////////////////////////////////////
void g_return_val_if_fail(char* event_array_01[], char* event_array_02[])
  {
  if(event_array_01[]!= false && event_array_02[]!= false)
    {
    new_event+= gdk_event_new;
    };
  if(new_event-> *Any.window)
    {
    gdk_window_ref();
    };
  };
#endif
Comment 10 Eric 2009-11-28 07:25:18 UTC
//Sorry here is a cleaner Header file
///////////////////////////////////////////////////////////////////////////////
#ifndef GTK_Event_Copy_H
#define GTK_Event_Copy_H
///////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdbool.h>
#include <stdio.h>
#include <STL_Include_Packet.h>
///////////////////////////////////////////////////////////////////////////////
struct Any_Property
  {
  char* window[];
  };struct Any_Property Any;
/////////////////////////////////////////////////////
typedef char* GDK_Event[]; //recieving input
GDK_Event new_event, event_01, event_02;
/////////////////////////////////////////////////////////////////////////////////////////
char* gdk_event_new(void)
 {
 char* array_01[];
 return(array_01);
 };
/////////////////////////////////////////////////////////////////////////////////////////
void gdk_window_ref(char the_switch)
  {
  if(new_event-> *Any.window)
    {
    char* variable[];
    return(variable);// generating a new variable //
    };
  };
////////////////////////////////////////////////////////////////////////////////////////
void g_return_val_if_fail(char* event_array_01[], char* event_array_02[])
  {
  if(event_array_01[]!= false && event_array_02[]!= false)
    {
    new_event+= gdk_event_new;
    };
  if(new_event-> *Any.window)
    {
    gdk_window_ref();
    };
  };
#endif
Comment 11 Daniel Boles 2017-08-28 12:02:46 UTC
...what
Comment 12 Emmanuele Bassi (:ebassi) 2017-08-28 12:06:49 UTC
This definitely goes onto the obsolete pile.