Bug Summary

File:nested_input.c
Location:line 346, column 13
Description:Potential memory leak

Annotated Source Code

1/*
2 * Permission is hereby granted, free of charge, to any person obtaining a
3 * copy of this software and associated documentation files (the "Software"),
4 * to deal in the Software without restriction, including without limitation
5 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
6 * and/or sell copies of the Software, and to permit persons to whom the
7 * Software is furnished to do so, subject to the following conditions:
8 *
9 * The above copyright notice and this permission notice (including the next
10 * paragraph) shall be included in all copies or substantial portions of the
11 * Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
16 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19 * DEALINGS IN THE SOFTWARE.
20 *
21 * Authors:
22 *
23 * Paulo Zanoni <pzanoni@mandriva.com>
24 * Tuan Bui <tuanbui918@gmail.com>
25 * Colin Cornaby <colin.cornaby@mac.com>
26 * Timothy Fleck <tim.cs.pdx@gmail.com>
27 * Colin Hill <colin.james.hill@gmail.com>
28 * Weseung Hwang <weseung@gmail.com>
29 * Nathaniel Way <nathanielcw@hotmail.com>
30 */
31
32#include <errno(*__error()).h>
33#include <fcntl.h>
34#include <stdlib.h>
35#include <stdio.h>
36#include <string.h>
37#include <unistd.h>
38
39#include <xorg-server.h>
40#include <fb.h>
41#include <micmap.h>
42#include <mipointer.h>
43#include <shadow.h>
44#include <xf86.h>
45#include <xf86Module.h>
46#include <xf86str.h>
47#include <xf86_OSproc.h>
48#include <xkbsrv.h>
49
50#ifdef HAVE_CONFIG_H1
51#include "config.h"
52#endif
53
54#include "client.h"
55#include "nested_input.h"
56
57#define SYSCALL(call)while (((call) == -1) && ((*__error()) == 4)) while (((call) == -1) && (errno(*__error()) == EINTR4))
58
59#define NUM_MOUSE_BUTTONS6 6
60#define NUM_MOUSE_AXES2 2
61
62static pointer
63NestedInputPlug(pointer module, pointer options, int *errmaj, int *errmin);
64static void
65NestedInputUnplug(pointer p);
66
67static void
68NestedInputReadInput(InputInfoPtr pInfo);
69static int
70NestedInputControl(DeviceIntPtr device,int what);
71
72static int
73_nested_input_init_keyboard(DeviceIntPtr device);
74static int
75_nested_input_init_buttons(DeviceIntPtr device);
76static int
77_nested_input_init_axes(DeviceIntPtr device);
78
79typedef struct _NestedInputDeviceRec {
80 NestedClientPrivatePtr clientData;
81 int version;
82} NestedInputDeviceRec, *NestedInputDevicePtr;
83
84static XF86ModuleVersionInfo NestedInputVersionRec = {
85 "nestedinput",
86 MODULEVENDORSTRING"X.Org Foundation",
87 MODINFOSTRING10xef23fdc5,
88 MODINFOSTRING20x10dc023a,
89 XORG_VERSION_CURRENT(((1) * 10000000) + ((18) * 100000) + ((99) * 1000) + 1),
90 PACKAGE_VERSION_MAJOR0, PACKAGE_VERSION_MINOR1,
91 PACKAGE_VERSION_PATCHLEVEL0,
92 ABI_CLASS_XINPUT"X.Org XInput driver",
93 ABI_XINPUT_VERSION((((22) << 16) & 0xFFFF0000) | ((1) & 0x0000FFFF
))
,
94 MOD_CLASS_XINPUT"X.Org XInput Driver",
95 {0, 0, 0, 0}
96};
97
98_X_EXPORT__attribute__((visibility("default"))) XF86ModuleData nestedInputModuleData = {
99 &NestedInputVersionRec,
100 &NestedInputPlug,
101 &NestedInputUnplug
102};
103
104int
105NestedInputPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags) {
106 NestedInputDevicePtr pNestedInput;
107
108 pNestedInput = calloc(1, sizeof(NestedInputDeviceRec));
109
110 if (!pNestedInput)
111 return BadAlloc11;
112
113 pInfo->private = pNestedInput;
114 pInfo->type_name = XI_MOUSE"MOUSE"; // This is really both XI_MOUSE and XI_KEYBOARD... but oh well.
115 pInfo->read_input = NestedInputReadInput; // new data available.
116 pInfo->switch_mode = NULL((void*)0); // Toggle absolute/relative mode.
117 pInfo->device_control = NestedInputControl; // Enable/disable device.
118
119 return Success0;
120}
121
122void
123NestedInputUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags) {
124}
125
126static pointer
127NestedInputPlug(pointer module, pointer options, int *errmaj, int *errmin) {
128 return NULL((void*)0);
129}
130
131static void
132NestedInputUnplug(pointer p) {
133}
134
135static void
136NestedInputUpdateKeymap(DeviceIntPtr device) {
137 InputInfoPtr pInfo = device->public.devicePrivate;
138 NestedInputDevicePtr pNestedInput = pInfo->private;
139 KeySymsRec keySyms;
140 XkbControlsRec ctrls;
141 CARD8 modmap[MAP_LENGTH256];
142
143 if(!NestedClientGetKeyboardMappings(pNestedInput->clientData, &keySyms, modmap, &ctrls)) {
144 xf86Msg(X_ERROR, "%s: Failed to get keyboard mappings.\n", pInfo->name);
145 return;
146 }
147
148#ifdef _XSERVER641
149 {
150 unsigned long *keymap64 = (unsigned long *)keySyms.map;
151 size_t len = (keySyms.maxKeyCode - keySyms.minKeyCode + 1) * keySyms.mapWidth;
152 size_t i;
153
154 keySyms.map = malloc(len * sizeof(KeySym));
155 if (!keySyms.map) {
156 xf86Msg(X_ERROR, "%s: Failed to get keyboard mappings.\n", pInfo->name);
157 free(keymap64);
158 return;
159 }
160
161 for(i = 0; i < len; ++i)
162 keySyms.map[i] = keymap64[i];
163 free(keymap64);
164 }
165#endif
166
167 XkbApplyMappingChange(device, &keySyms, keySyms.minKeyCode,
168 keySyms.maxKeyCode - keySyms.minKeyCode + 1,
169 modmap, serverClient);
170 XkbDDXChangeControls(device, &ctrls, &ctrls);
171
172 free(keySyms.map);
173
174 if (inputInfo.keyboard != device)
175 XkbCopyDeviceKeymap(inputInfo.keyboard, device);
176}
177
178static int
179_nested_input_init_keyboard(DeviceIntPtr device) {
180 InputInfoPtr pInfo = device->public.devicePrivate;
181
182 if (!InitKeyboardDeviceStruct(device, NULL((void*)0), NULL((void*)0), NULL((void*)0))) {
183 xf86Msg(X_ERROR, "%s: Failed to register keyboard.\n", pInfo->name);
184 return BadAlloc11;
185 }
186
187 return Success0;
188}
189static int
190_nested_input_init_buttons(DeviceIntPtr device) {
191 InputInfoPtr pInfo = device->public.devicePrivate;
192 CARD8 *map;
193 Atom buttonLabels[NUM_MOUSE_BUTTONS6] = {0};
194
195 map = calloc(NUM_MOUSE_BUTTONS6, sizeof(CARD8));
196
197 int i;
198 for (i = 0; i < NUM_MOUSE_BUTTONS6; i++)
199 map[i] = i;
200
201 if (!InitButtonClassDeviceStruct(device, NUM_MOUSE_BUTTONS6, buttonLabels, map)) {
202 xf86Msg(X_ERROR, "%s: Failed to register buttons.\n", pInfo->name);
203
204 free(map);
205 return BadAlloc11;
206 }
207
208 return Success0;
209}
210
211static int
212_nested_input_init_axes(DeviceIntPtr device) {
213 if (!InitValuatorClassDeviceStruct(device,
214 NUM_MOUSE_AXES2,
215 (Atom*)GetMotionHistory, // Not sure about this.
216 GetMotionHistorySize(),
217 (Atom)0)) {
218 return BadAlloc11;
219 }
220
221 int i;
222 for (i = 0; i < NUM_MOUSE_AXES2; i++) {
223 xf86InitValuatorAxisStruct(device, i, (Atom)0, -1, -1, 1, 1, 1, Absolute1);
224 xf86InitValuatorDefaults(device, i);
225 }
226
227 return Success0;
228}
229
230static CARD32
231nested_input_on(OsTimerPtr timer, CARD32 time, pointer arg) {
232 DeviceIntPtr device = arg;
233 InputInfoPtr pInfo = device->public.devicePrivate;
234 NestedInputDevicePtr pNestedInput = pInfo->private;
235
236 if(device->public.on)
237 {
238 pInfo->fd = NestedClientGetFileDescriptor(pNestedInput->clientData);
239 xf86FlushInput(pInfo->fd);
240 xf86AddEnabledDevice(pInfo);
241 }
242 return 0;
243}
244
245static int
246NestedInputControl(DeviceIntPtr device, int what) {
247 int err;
248 InputInfoPtr pInfo = device->public.devicePrivate;
249
250 switch (what) {
251 case DEVICE_INIT0:
252 err = _nested_input_init_keyboard(device);
253 if (err != Success0)
254 return err;
255
256 err = _nested_input_init_buttons(device);
257 if (err != Success0)
258 return err;
259
260 err = _nested_input_init_axes(device);
261 if (err != Success0)
262 return err;
263
264 break;
265 case DEVICE_ON1:
266 xf86Msg(X_INFO, "%s: On.\n", pInfo->name);
267
268 if (device->public.on)
269 break;
270
271 device->public.on = TRUE1;
272 TimerSet(NULL((void*)0), 0, 1, nested_input_on, device);
273 break;
274 case DEVICE_OFF2:
275 xf86Msg(X_INFO, "%s: Off.\n", pInfo->name);
276
277 if (!device->public.on)
278 break;
279
280 xf86RemoveEnabledDevice(pInfo);
281
282 pInfo->fd = -1;
283 device->public.on = FALSE0;
284 break;
285 case DEVICE_CLOSE3:
286 break;
287 }
288
289 return Success0;
290}
291
292static CARD32
293nested_input_ready(OsTimerPtr timer, CARD32 time, pointer arg) {
294 NestedClientPrivatePtr clientData = arg;
295 NestedClientCheckEvents(clientData);
296 return 0;
297}
298
299static void
300NestedInputReadInput(InputInfoPtr pInfo) {
301 NestedInputDevicePtr pNestedInput = pInfo->private;
302 TimerSet(NULL((void*)0), 0, 1, nested_input_ready, pNestedInput->clientData);
303}
304
305#if GET_ABI_MAJOR(ABI_XINPUT_VERSION)(((((((22) << 16) & 0xFFFF0000) | ((1) & 0x0000FFFF
))) & 0xFFFF0000) >> 16)
< 14
306static InputOption*
307input_option_new(InputOption* list, char *key, char *value)
308{
309 InputOption *tmp;
310
311 tmp = calloc(1, sizeof(*tmp));
312 tmp->key = key;
313 tmp->value = value;
314 tmp->next = list;
315
316 return tmp;
317}
318
319static void
320input_option_free_list(InputOption **list)
321{
322 InputOption *iopts = *list;
323
324 while(iopts)
325 {
326 InputOption *tmp = iopts->next;
327 free(iopts->key);
328 free(iopts->value);
329 free(iopts);
330 iopts = tmp;
331 }
332
333 *list = NULL((void*)0);
334}
335#endif
336
337
338void
339NestedInputLoadDriver(NestedClientPrivatePtr clientData) {
340 DeviceIntPtr dev;
341 InputInfoPtr pInfo;
342 NestedInputDevicePtr pNestedInput;
343
344 // Create input options for our invocation to NewInputDeviceRequest.
345 InputOption* options = NULL((void*)0);
346 options = input_option_new(options, strdup("identifier"), strdup("nestedinput"));
1
Memory is allocated
2
Potential memory leak
347 options = input_option_new(options, strdup("driver"), strdup("nestedinput"));
348
349 // Invoke NewInputDeviceRequest to call the PreInit function of
350 // the driver.
351 int ret = NewInputDeviceRequest(options, NULL((void*)0), &dev);
352
353 input_option_free_list(&options);
354
355 if (ret != Success0) {
356 FatalError("Failed to load input driver.\n");
357 }
358
359 pInfo = dev->public.devicePrivate;
360 pNestedInput = pInfo->private;
361 pNestedInput->clientData = clientData;
362
363 // Set our keymap to be the same as the server's
364 NestedInputUpdateKeymap(dev);
365
366 // Send the device to the client so that the client can send the
367 // device back to the input driver when events are being posted.
368 NestedClientSetDevicePtr(clientData, dev);
369}
370
371void
372NestedInputPostMouseMotionEvent(DeviceIntPtr dev, int x, int y) {
373 xf86PostMotionEvent(dev, TRUE1, 0, 2, x, y);
374}
375
376void
377NestedInputPostButtonEvent(DeviceIntPtr dev, int button, int isDown) {
378 xf86PostButtonEvent(dev, 0, button, isDown, 0, 0);
379}
380
381void
382NestedInputPostKeyboardEvent(DeviceIntPtr dev, unsigned int keycode, int isDown) {
383 xf86PostKeyboardEvent(dev, keycode, isDown);
384}