diff options
author | Mathias Gumz <akira at fluxbox dot org> | 2008-09-23 07:13:53 (GMT) |
---|---|---|
committer | Mathias Gumz <akira at fluxbox dot org> | 2008-09-23 07:13:53 (GMT) |
commit | acd690ff653d83e4a24f88445526449d345f81bd (patch) | |
tree | 2f74d3faa688ed3f70213f0487ac2bbf237e21db | |
parent | 769ca8f1c8e156d919f6cacf90e0651530c4d943 (diff) | |
download | fluxbox_pavel-acd690ff653d83e4a24f88445526449d345f81bd.zip fluxbox_pavel-acd690ff653d83e4a24f88445526449d345f81bd.tar.bz2 |
fixed detection of bad values in the _NET_WM_ICON property. eg, tvtime.sf.net
is not aware of how to correctly feed icon data into the property on 64bit architecture
which caused the dimensions of the icon beeing corrupt and due to overflow arithmetics
fluxbox crashed.
-rw-r--r-- | src/Ewmh.cc | 72 |
1 files changed, 58 insertions, 14 deletions
diff --git a/src/Ewmh.cc b/src/Ewmh.cc index 14c74c6..2a9e1ab 100644 --- a/src/Ewmh.cc +++ b/src/Ewmh.cc | |||
@@ -76,16 +76,30 @@ namespace { | |||
76 | * byte being B. The first two cardinals are width, height. Data is in rows, | 76 | * byte being B. The first two cardinals are width, height. Data is in rows, |
77 | * left to right and top to bottom. | 77 | * left to right and top to bottom. |
78 | * | 78 | * |
79 | *** | ||
80 | * | ||
81 | * NOTE: the returned data for XA_CARDINAL is long if the rfmt equals | ||
82 | * 32. sizeof(long) on 64bit machines is 8. to quote from | ||
83 | * "man XGetWindowProperty": | ||
84 | * | ||
85 | * If the returned format is 32, the property data will be stored as | ||
86 | * an array of longs (which in a 64-bit application will be 64-bit | ||
87 | * values that are padded in the upper 4 bytes). | ||
88 | * | ||
89 | * this is especially true on 64bit machines when some of the clients | ||
90 | * (eg: tvtime, konqueror3) have problems to feed in the right data | ||
91 | * into the _NET_WM_ICON property. we faced some segfaults because | ||
92 | * width and height were not quite right because of ignoring 64bit | ||
93 | * behaviour on client side. | ||
94 | * | ||
79 | * TODO: maybe move the pixmap-creation code to FbTk? */ | 95 | * TODO: maybe move the pixmap-creation code to FbTk? */ |
80 | void extractNetWmIcon(Atom net_wm_icon, WinClient& winclient) { | 96 | void extractNetWmIcon(Atom net_wm_icon, WinClient& winclient) { |
81 | 97 | ||
82 | typedef std::pair<int, int> Size; | 98 | typedef std::pair<int, int> Size; |
83 | typedef std::map<Size, const unsigned long*> IconContainer; | 99 | typedef std::map<Size, const unsigned long*> IconContainer; |
84 | 100 | ||
85 | // attention: the returned data for XA_CARDINAL is long if the rfmt equals | ||
86 | // 32. sizeof(long) on 64bit machines is 8. | ||
87 | unsigned long* raw_data = 0; | 101 | unsigned long* raw_data = 0; |
88 | long nr_icon_data = 0; | 102 | unsigned long nr_icon_data = 0; |
89 | 103 | ||
90 | { | 104 | { |
91 | Atom rtype; | 105 | Atom rtype; |
@@ -106,7 +120,10 @@ void extractNetWmIcon(Atom net_wm_icon, WinClient& winclient) { | |||
106 | 120 | ||
107 | // actually there is some data in _NET_WM_ICON | 121 | // actually there is some data in _NET_WM_ICON |
108 | nr_icon_data = nr_bytes_left / sizeof(CARD32); | 122 | nr_icon_data = nr_bytes_left / sizeof(CARD32); |
109 | 123 | #ifdef DEBUG | |
124 | std::cerr << "extractNetWmIcon: " << winclient.title() << "\n"; | ||
125 | std::cerr << "nr_icon_data: " << nr_icon_data << "\n"; | ||
126 | #endif | ||
110 | // read all the icons stored in _NET_WM_ICON | 127 | // read all the icons stored in _NET_WM_ICON |
111 | if (raw_data) | 128 | if (raw_data) |
112 | XFree(raw_data); | 129 | XFree(raw_data); |
@@ -118,30 +135,57 @@ void extractNetWmIcon(Atom net_wm_icon, WinClient& winclient) { | |||
118 | 135 | ||
119 | return; | 136 | return; |
120 | } | 137 | } |
138 | #ifdef DEBUG | ||
139 | std::cerr << "nr_read: " << nr_read << "|" << nr_bytes_left << "\n"; | ||
140 | #endif | ||
121 | } | 141 | } |
122 | 142 | ||
123 | IconContainer icon_data; // stores all available data, sorted by size (width x height) | 143 | IconContainer icon_data; // stores all available data, sorted by size (width x height) |
124 | int width; | 144 | unsigned long width; |
125 | int height; | 145 | unsigned long height; |
126 | 146 | ||
127 | // analyze the available icons | 147 | // analyze the available icons |
128 | long i; | 148 | // |
129 | 149 | // check also for invalid values coming in from "bad" applications | |
150 | unsigned long i; | ||
130 | for (i = 0; i + 2 < nr_icon_data; i += width * height ) { | 151 | for (i = 0; i + 2 < nr_icon_data; i += width * height ) { |
131 | 152 | ||
132 | width = raw_data[i++]; | 153 | width = raw_data[i++]; |
154 | if (width >= nr_icon_data) { | ||
155 | #ifdef DEBUG | ||
156 | std::cerr << "Ewmh.cc extractNetWmIcon found strange _NET_WM_ICON width (" | ||
157 | << width << ") for " << winclient.title() << "\n"; | ||
158 | #endif | ||
159 | break; | ||
160 | } | ||
161 | |||
133 | height = raw_data[i++]; | 162 | height = raw_data[i++]; |
163 | if (height >= nr_icon_data) { | ||
164 | #ifdef DEBUG | ||
165 | std::cerr << "Ewmh.cc extractNetWmIcon found strange _NET_WM_ICON height (" | ||
166 | << height << ") for " << winclient.title() << "\n"; | ||
167 | #endif | ||
168 | break; | ||
169 | } | ||
134 | 170 | ||
135 | // strange values stored in the NETWM_ICON | 171 | // strange values stored in the NETWM_ICON |
136 | if (width <= 0 || height <= 0 || i + width * height > nr_icon_data) { | 172 | if (i + width * height > nr_icon_data) { |
137 | std::cerr << "Ewmh.cc extractNetWmIcon found strange _NET_WM_ICON dimensions for " << winclient.title() << "\n"; | 173 | #ifdef DEBUG |
138 | XFree(raw_data); | 174 | std::cerr << "Ewmh.cc extractNetWmIcon found strange _NET_WM_ICON dimensions (" |
139 | return; | 175 | << width << "x" << height << ")for " << winclient.title() << "\n"; |
176 | #endif | ||
177 | break; | ||
140 | } | 178 | } |
141 | 179 | ||
142 | icon_data[Size(width, height)] = &raw_data[i]; | 180 | icon_data[Size(width, height)] = &raw_data[i]; |
143 | } | 181 | } |
144 | 182 | ||
183 | // no valid icons found at all | ||
184 | if (icon_data.empty()) { | ||
185 | XFree(raw_data); | ||
186 | return; | ||
187 | } | ||
188 | |||
145 | Display* dpy = FbTk::App::instance()->display(); | 189 | Display* dpy = FbTk::App::instance()->display(); |
146 | int scrn = winclient.screen().screenNumber(); | 190 | int scrn = winclient.screen().screenNumber(); |
147 | 191 | ||
@@ -178,8 +222,8 @@ void extractNetWmIcon(Atom net_wm_icon, WinClient& winclient) { | |||
178 | const unsigned long* src = icon_data.begin()->second; | 222 | const unsigned long* src = icon_data.begin()->second; |
179 | unsigned int rgba; | 223 | unsigned int rgba; |
180 | unsigned long pixel; | 224 | unsigned long pixel; |
181 | int x; | 225 | unsigned long x; |
182 | int y; | 226 | unsigned long y; |
183 | unsigned char r, g, b, a; | 227 | unsigned char r, g, b, a; |
184 | 228 | ||
185 | for (y = 0; y < height; y++) { | 229 | for (y = 0; y < height; y++) { |