[alsa-devel] [PATCH 02/16] ALSA: line6: Fix memory leak at probe error path

Takashi Iwai tiwai at suse.de
Mon Jan 26 13:47:34 CET 2015


At Sun, 25 Jan 2015 02:06:19 -0600,
Chris Rorvick wrote:
> 
> On Fri, Jan 23, 2015 at 11:13 AM, Takashi Iwai <tiwai at suse.de> wrote:
> > --- a/sound/usb/line6/driver.c
> > +++ b/sound/usb/line6/driver.c
> > @@ -507,10 +507,32 @@ int line6_probe(struct usb_interface *interface,
> >         int interface_number;
> >         int ret;
> >
> > +       ret = snd_card_new(line6->ifcdev,
> > +                          SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
> > +                          THIS_MODULE, 0, &card);
> 
> The `ifcdev' member has not been initialized yet.

Good catch.

> You need something
> like the following squashed in:
> 
> >8------------------------------------------------------8<
> diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c
> index 2eed6fb..25d6b0f 100644
> --- a/sound/usb/line6/driver.c
> +++ b/sound/usb/line6/driver.c
> @@ -507,6 +507,11 @@ int line6_probe(struct usb_interface *interface,
>         int interface_number;
>         int ret;
> 
> +       /* store basic data: */
> +       line6->properties = properties;
> +       line6->usbdev = usbdev;
> +       line6->ifcdev = &interface->dev;
> +
>         ret = snd_card_new(line6->ifcdev,
>                            SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
>                            THIS_MODULE, 0, &card);
> @@ -548,11 +553,6 @@ int line6_probe(struct usb_interface *interface,
>                 goto error;
>         }
> 
> -       /* store basic data: */
> -       line6->properties = properties;
> -       line6->usbdev = usbdev;
> -       line6->ifcdev = &interface->dev;
> -
>         line6_get_interval(line6);
> 
>         if (properties->capabilities & LINE6_CAP_CONTROL) {

Right, but there will be another round of cleanup patches and the
allocation of line6 will be dropped there, so I took an easier fixup,
just use &interface->dev to the argument.

The revised patch is found below.  The test/line6 branch was updated
with this (and more fixes I'll send shortly later).


thanks,

Takashi

-- 8< --
From: Takashi Iwai <tiwai at suse.de>
Subject: [PATCH] ALSA: line6: Fix memory leak at probe error path

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.

Signed-off-by: Takashi Iwai <tiwai at suse.de>
---
 sound/usb/line6/driver.c | 59 ++++++++++++++++++++++++------------------------
 1 file changed, 30 insertions(+), 29 deletions(-)

diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c
index b783c0788e45..bf9630cd2395 100644
--- a/sound/usb/line6/driver.c
+++ b/sound/usb/line6/driver.c
@@ -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);
-- 
2.2.2



More information about the Alsa-devel mailing list