[{"id":18123,"web_url":"https://patchwork.libcamera.org/comment/18123/","msgid":"<037438f3-64ae-3f25-681e-6f60efae9477@ideasonboard.com>","date":"2021-07-12T15:10:47","subject":"Re: [libcamera-devel] [PATCH 11/30] cam: options: Avoid copies of\n\tOptionvValue and KeyValueParser::Options","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"On 07/07/2021 03:19, Laurent Pinchart wrote:\n> The OptionValue toKeyValues() and toArray() functions return a copy of\n> the values. This is unnecessary, and can cause use-after-free issues\n> when taking references to the return values. Return references instead\n> to optimize the implementation and avoid issues.\n> \n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> ---\n>  src/cam/options.cpp | 22 ++++++++++------------\n>  src/cam/options.h   |  4 ++--\n>  2 files changed, 12 insertions(+), 14 deletions(-)\n> \n> diff --git a/src/cam/options.cpp b/src/cam/options.cpp\n> index 319fab6143c5..9de3dd77fd15 100644\n> --- a/src/cam/options.cpp\n> +++ b/src/cam/options.cpp\n> @@ -632,27 +632,25 @@ std::string OptionValue::toString() const\n>  \n>  /**\n>   * \\brief Retrieve the value as a key-value list\n> - * \\return The option value as a KeyValueParser::Options, or an empty list if\n> - * the value type isn't ValueType::ValueKeyValue\n> + *\n> + * The behaviour is undefined if the value type isn't ValueType::ValueKeyValue.\n> + *\n> + * \\return The option value as a KeyValueParser::Options\n>   */\n> -KeyValueParser::Options OptionValue::toKeyValues() const\n> +const KeyValueParser::Options &OptionValue::toKeyValues() const\n>  {\n> -\tif (type_ != ValueKeyValue)\n> -\t\treturn KeyValueParser::Options();\n\nI guess you could have a static empty list here to return a reference\nof, but if it's not supposed to happen - perhaps it doesn't matter.\n\nBut should you at least put in an ASSERT() in here?\n\n\n> -\n>  \treturn keyValues_;\n>  }\n>  \n>  /**\n>   * \\brief Retrieve the value as an array\n> - * \\return The option value as a std::vector of OptionValue, or an empty vector\n> - * if the value type isn't ValueType::ValueArray\n> + *\n> + * The behaviour is undefined if the value type isn't ValueType::ValueArray.\n> + *\n> + * \\return The option value as a std::vector of OptionValue\n>   */\n> -std::vector<OptionValue> OptionValue::toArray() const\n> +const std::vector<OptionValue> &OptionValue::toArray() const\n>  {\n> -\tif (type_ != ValueArray)\n> -\t\treturn std::vector<OptionValue>{};\n\nSame comment, if we're not going to return a static local - I'd put in\nan assert to be sure.\n\n\n> -\n>  \treturn array_;\n>  }\n>  \n> diff --git a/src/cam/options.h b/src/cam/options.h\n> index 210e502a24e1..09cbc8339dd0 100644\n> --- a/src/cam/options.h\n> +++ b/src/cam/options.h\n> @@ -141,8 +141,8 @@ public:\n>  \n>  \tint toInteger() const;\n>  \tstd::string toString() const;\n> -\tKeyValueParser::Options toKeyValues() const;\n> -\tstd::vector<OptionValue> toArray() const;\n> +\tconst KeyValueParser::Options &toKeyValues() const;\n> +\tconst std::vector<OptionValue> &toArray() const;\n>  \n>  \tconst OptionsParser::Options &children() const;\n>  \n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 56977C3226\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 12 Jul 2021 15:10:57 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id F0ED468524;\n\tMon, 12 Jul 2021 17:10:51 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id DC6CA68513\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 12 Jul 2021 17:10:50 +0200 (CEST)","from [192.168.0.20]\n\t(cpc89244-aztw30-2-0-cust3082.18-1.cable.virginm.net [86.31.172.11])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 5F91CCC;\n\tMon, 12 Jul 2021 17:10:50 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"HX5yzzzo\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1626102650;\n\tbh=s/ELstdNyFzkFFpj+o9O2h9z8lAkYwzJtS5givoSJTQ=;\n\th=Subject:To:References:From:Date:In-Reply-To:From;\n\tb=HX5yzzzogwylNkVQ+Ug3nZEd1Ivm8sfYQAdoTymn+aO36I55e/PSlrhByI2IeGZUv\n\tLtLx+A+ZEMMmmtYqaOSjd5xNTvInRlWUAck45uUby0w12u8aY36ZEaI+JZTt1+1a19\n\tiHKYmV75Xk9t0oESx4rsAU3kElTv5Hx/NQINB+28=","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","References":"<20210707021941.20804-1-laurent.pinchart@ideasonboard.com>\n\t<20210707021941.20804-12-laurent.pinchart@ideasonboard.com>","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Message-ID":"<037438f3-64ae-3f25-681e-6f60efae9477@ideasonboard.com>","Date":"Mon, 12 Jul 2021 16:10:47 +0100","User-Agent":"Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101\n\tThunderbird/78.11.0","MIME-Version":"1.0","In-Reply-To":"<20210707021941.20804-12-laurent.pinchart@ideasonboard.com>","Content-Type":"text/plain; charset=utf-8","Content-Language":"en-GB","Content-Transfer-Encoding":"7bit","Subject":"Re: [libcamera-devel] [PATCH 11/30] cam: options: Avoid copies of\n\tOptionvValue and KeyValueParser::Options","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":18146,"web_url":"https://patchwork.libcamera.org/comment/18146/","msgid":"<YOyKdI4lE+I3pHiM@pendragon.ideasonboard.com>","date":"2021-07-12T18:31:16","subject":"Re: [libcamera-devel] [PATCH 11/30] cam: options: Avoid copies of\n\tOptionvValue and KeyValueParser::Options","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Kieran,\n\nOn Mon, Jul 12, 2021 at 04:10:47PM +0100, Kieran Bingham wrote:\n> On 07/07/2021 03:19, Laurent Pinchart wrote:\n> > The OptionValue toKeyValues() and toArray() functions return a copy of\n> > the values. This is unnecessary, and can cause use-after-free issues\n> > when taking references to the return values. Return references instead\n> > to optimize the implementation and avoid issues.\n> > \n> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> > ---\n> >  src/cam/options.cpp | 22 ++++++++++------------\n> >  src/cam/options.h   |  4 ++--\n> >  2 files changed, 12 insertions(+), 14 deletions(-)\n> > \n> > diff --git a/src/cam/options.cpp b/src/cam/options.cpp\n> > index 319fab6143c5..9de3dd77fd15 100644\n> > --- a/src/cam/options.cpp\n> > +++ b/src/cam/options.cpp\n> > @@ -632,27 +632,25 @@ std::string OptionValue::toString() const\n> >  \n> >  /**\n> >   * \\brief Retrieve the value as a key-value list\n> > - * \\return The option value as a KeyValueParser::Options, or an empty list if\n> > - * the value type isn't ValueType::ValueKeyValue\n> > + *\n> > + * The behaviour is undefined if the value type isn't ValueType::ValueKeyValue.\n> > + *\n> > + * \\return The option value as a KeyValueParser::Options\n> >   */\n> > -KeyValueParser::Options OptionValue::toKeyValues() const\n> > +const KeyValueParser::Options &OptionValue::toKeyValues() const\n> >  {\n> > -\tif (type_ != ValueKeyValue)\n> > -\t\treturn KeyValueParser::Options();\n> \n> I guess you could have a static empty list here to return a reference\n> of, but if it's not supposed to happen - perhaps it doesn't matter.\n\nNote that if type_ != ValueKeyValue, the keyValues_ member will be\ndefault-initialized, so the function will return an empty list. Same for\nthe array case below.\n\n> But should you at least put in an ASSERT() in here?\n\nI'll do that.\n\n> > -\n> >  \treturn keyValues_;\n> >  }\n> >  \n> >  /**\n> >   * \\brief Retrieve the value as an array\n> > - * \\return The option value as a std::vector of OptionValue, or an empty vector\n> > - * if the value type isn't ValueType::ValueArray\n> > + *\n> > + * The behaviour is undefined if the value type isn't ValueType::ValueArray.\n> > + *\n> > + * \\return The option value as a std::vector of OptionValue\n> >   */\n> > -std::vector<OptionValue> OptionValue::toArray() const\n> > +const std::vector<OptionValue> &OptionValue::toArray() const\n> >  {\n> > -\tif (type_ != ValueArray)\n> > -\t\treturn std::vector<OptionValue>{};\n> \n> Same comment, if we're not going to return a static local - I'd put in\n> an assert to be sure.\n> \n> > -\n> >  \treturn array_;\n> >  }\n> >  \n> > diff --git a/src/cam/options.h b/src/cam/options.h\n> > index 210e502a24e1..09cbc8339dd0 100644\n> > --- a/src/cam/options.h\n> > +++ b/src/cam/options.h\n> > @@ -141,8 +141,8 @@ public:\n> >  \n> >  \tint toInteger() const;\n> >  \tstd::string toString() const;\n> > -\tKeyValueParser::Options toKeyValues() const;\n> > -\tstd::vector<OptionValue> toArray() const;\n> > +\tconst KeyValueParser::Options &toKeyValues() const;\n> > +\tconst std::vector<OptionValue> &toArray() const;\n> >  \n> >  \tconst OptionsParser::Options &children() const;\n> >","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id AAEA3C3226\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 12 Jul 2021 18:32:05 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 2539368524;\n\tMon, 12 Jul 2021 20:32:05 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 2168B68513\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 12 Jul 2021 20:32:03 +0200 (CEST)","from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi\n\t[62.78.145.57])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 8C3A0CC;\n\tMon, 12 Jul 2021 20:32:02 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"JO7h51ds\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1626114722;\n\tbh=CyzwatQ5LDmkBOHf4NzPA4BpLHryJrLDi4rskoNaKAg=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=JO7h51dsVAahpSb/SAUpNzPOQR7bGWUnDBpVSMYQ0Ue9kUrGvuAHcI2YmW2DS6Mej\n\tl0Sa2FBaV5vhObvtjvkTEIs5+IL4oQBDokjQG4l5Q2usLxBjA+gsV/eRoP3L1Lsgst\n\t1HpbdIlBFPhVcxO8vsQi4mRw+FXQ6ErX4N/QbuYA=","Date":"Mon, 12 Jul 2021 21:31:16 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Message-ID":"<YOyKdI4lE+I3pHiM@pendragon.ideasonboard.com>","References":"<20210707021941.20804-1-laurent.pinchart@ideasonboard.com>\n\t<20210707021941.20804-12-laurent.pinchart@ideasonboard.com>\n\t<037438f3-64ae-3f25-681e-6f60efae9477@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<037438f3-64ae-3f25-681e-6f60efae9477@ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH 11/30] cam: options: Avoid copies of\n\tOptionvValue and KeyValueParser::Options","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]