ALSA: line6: Fix memory leak at probe error path
authorTakashi Iwai <tiwai@suse.de>
Fri, 23 Jan 2015 11:27:39 +0000 (12:27 +0100)
committerTakashi Iwai <tiwai@suse.de>
Wed, 28 Jan 2015 06:20:21 +0000 (07:20 +0100)
Fix memory leak at probe error path by rearranging the call order in
line6_destruct() so that the common destructor is always called.
Also this simplifies the error path to a single goto label.

Tested-by: Chris Rorvick <chris@rorvick.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/usb/line6/driver.c

index b783c07..bf9630c 100644 (file)
@@ -507,39 +507,20 @@ int line6_probe(struct usb_interface *interface,
        int interface_number;
        int ret;
 
-       /* we don't handle multiple configurations */
-       if (usbdev->descriptor.bNumConfigurations != 1) {
-               ret = -ENODEV;
-               goto err_put;
-       }
-
-       /* initialize device info: */
-       dev_info(&interface->dev, "Line 6 %s found\n", properties->name);
-
-       /* query interface number */
-       interface_number = interface->cur_altsetting->desc.bInterfaceNumber;
-
-       ret = usb_set_interface(usbdev, interface_number,
-                       properties->altsetting);
+       ret = snd_card_new(&interface->dev,
+                          SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+                          THIS_MODULE, 0, &card);
        if (ret < 0) {
-               dev_err(&interface->dev, "set_interface failed\n");
-               goto err_put;
+               kfree(line6);
+               return ret;
        }
 
        /* store basic data: */
+       line6->card = card;
        line6->properties = properties;
        line6->usbdev = usbdev;
        line6->ifcdev = &interface->dev;
 
-       line6_get_interval(line6);
-
-       ret = snd_card_new(line6->ifcdev,
-                          SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
-                          THIS_MODULE, 0, &card);
-       if (ret < 0)
-               goto err_put;
-
-       line6->card = card;
        strcpy(card->id, line6->properties->id);
        strcpy(card->driver, DRIVER_NAME);
        strcpy(card->shortname, line6->properties->name);
@@ -553,16 +534,37 @@ int line6_probe(struct usb_interface *interface,
        /* increment reference counters: */
        usb_get_dev(usbdev);
 
+       /* we don't handle multiple configurations */
+       if (usbdev->descriptor.bNumConfigurations != 1) {
+               ret = -ENODEV;
+               goto error;
+       }
+
+       /* initialize device info: */
+       dev_info(&interface->dev, "Line 6 %s found\n", properties->name);
+
+       /* query interface number */
+       interface_number = interface->cur_altsetting->desc.bInterfaceNumber;
+
+       ret = usb_set_interface(usbdev, interface_number,
+                       properties->altsetting);
+       if (ret < 0) {
+               dev_err(&interface->dev, "set_interface failed\n");
+               goto error;
+       }
+
+       line6_get_interval(line6);
+
        if (properties->capabilities & LINE6_CAP_CONTROL) {
                ret = line6_init_cap_control(line6);
                if (ret < 0)
-                       goto err_destruct;
+                       goto error;
        }
 
        /* initialize device data based on device: */
        ret = private_init(interface, line6);
        if (ret < 0)
-               goto err_destruct;
+               goto error;
 
        /* creation of additional special files should go here */
 
@@ -571,11 +573,10 @@ int line6_probe(struct usb_interface *interface,
 
        return 0;
 
- err_destruct:
+ error:
        if (line6->disconnect)
                line6->disconnect(interface);
        snd_card_free(card);
- err_put:
        return ret;
 }
 EXPORT_SYMBOL_GPL(line6_probe);