diff mbox

[for-2.11,v3,01/25] qom: cpu: fix parsed feature string length

Message ID 1503592308-93913-2-git-send-email-imammedo@redhat.com
State New
Headers show

Commit Message

Igor Mammedov Aug. 24, 2017, 4:31 p.m. UTC
since commit ( 9262685b cpu: Factor out cpu_generic_init() )
features parsed by it were truncated only to the 1st feature
after CPU name due to fact that

   featurestr = strtok(NULL, ",");
   cc->parse_features(cpu, featurestr, &err);

would extract exactly one feature and parse_features() callback
would parse it and only it leaving the rest of features ignored.

Reuse approach from x86 custom impl. i.e. replace strtok() token
parsing with g_strsplit(), which would split feature string in
2 parts name and features list and pass the later to
parse_features() callback.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
CC: Eduardo Habkost <ehabkost@redhat.com>
CC: Andreas Färber <afaerber@suse.de>

Probably due to existing users not actualy using/having any
features to parse bug were unnoticed for 2 years but switching
from custom cpu_foo_init() to cpu_generic_init() triggered it.
---
 qom/cpu.c | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

Comments

Philippe Mathieu-Daudé Aug. 24, 2017, 5 p.m. UTC | #1
Hi Igor,

On 08/24/2017 01:31 PM, Igor Mammedov wrote:
> since commit ( 9262685b cpu: Factor out cpu_generic_init() )
> features parsed by it were truncated only to the 1st feature
> after CPU name due to fact that
> 
>     featurestr = strtok(NULL, ",");
>     cc->parse_features(cpu, featurestr, &err);
> 
> would extract exactly one feature and parse_features() callback
> would parse it and only it leaving the rest of features ignored.
> 
> Reuse approach from x86 custom impl. i.e. replace strtok() token
> parsing with g_strsplit(), which would split feature string in
> 2 parts name and features list and pass the later to
> parse_features() callback.
> 
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> ---
> CC: Eduardo Habkost <ehabkost@redhat.com>
> CC: Andreas Färber <afaerber@suse.de>
> 
> Probably due to existing users not actualy using/having any
> features to parse bug were unnoticed for 2 years but switching
> from custom cpu_foo_init() to cpu_generic_init() triggered it.
> ---
>   qom/cpu.c | 14 ++++++--------
>   1 file changed, 6 insertions(+), 8 deletions(-)
> 
> diff --git a/qom/cpu.c b/qom/cpu.c
> index 4f38db0..caf5c14 100644
> --- a/qom/cpu.c
> +++ b/qom/cpu.c
> @@ -50,28 +50,26 @@ bool cpu_exists(int64_t id)
>   
>   CPUState *cpu_generic_init(const char *typename, const char *cpu_model)
>   {
> -    char *str, *name, *featurestr;
>       CPUState *cpu = NULL;
>       ObjectClass *oc;
>       CPUClass *cc;
>       Error *err = NULL;
> +    gchar **model_pieces;
>   
> -    str = g_strdup(cpu_model);
> -    name = strtok(str, ",");
> +    model_pieces = g_strsplit(cpu_model, ",", 2);
>   
> -    oc = cpu_class_by_name(typename, name);
> +    oc = cpu_class_by_name(typename, model_pieces[0]);
>       if (oc == NULL) {
> -        g_free(str);
> +        g_strfreev(model_pieces);
>           return NULL;
>       }
>   
>       cc = CPU_CLASS(oc);
> -    featurestr = strtok(NULL, ",");
>       /* TODO: all callers of cpu_generic_init() need to be converted to
>        * call parse_features() only once, before calling cpu_generic_init().
>        */
> -    cc->parse_features(object_class_get_name(oc), featurestr, &err);
> -    g_free(str);

I feel safer adding:

        if (g_strv_length(model_pieces) > 1) {

> +    cc->parse_features(object_class_get_name(oc), model_pieces[1], &err);

        }

> +    g_strfreev(model_pieces);
>       if (err != NULL) {
>           goto out;
>       }
>
Igor Mammedov Aug. 25, 2017, 8:11 a.m. UTC | #2
On Thu, 24 Aug 2017 14:00:21 -0300
Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:

> Hi Igor,
> 
> On 08/24/2017 01:31 PM, Igor Mammedov wrote:
> > since commit ( 9262685b cpu: Factor out cpu_generic_init() )
> > features parsed by it were truncated only to the 1st feature
> > after CPU name due to fact that
> > 
> >     featurestr = strtok(NULL, ",");
> >     cc->parse_features(cpu, featurestr, &err);
> > 
> > would extract exactly one feature and parse_features() callback
> > would parse it and only it leaving the rest of features ignored.
> > 
> > Reuse approach from x86 custom impl. i.e. replace strtok() token
> > parsing with g_strsplit(), which would split feature string in
> > 2 parts name and features list and pass the later to
> > parse_features() callback.
> > 
> > Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> > ---
> > CC: Eduardo Habkost <ehabkost@redhat.com>
> > CC: Andreas Färber <afaerber@suse.de>
> > 
> > Probably due to existing users not actualy using/having any
> > features to parse bug were unnoticed for 2 years but switching
> > from custom cpu_foo_init() to cpu_generic_init() triggered it.
> > ---
> >   qom/cpu.c | 14 ++++++--------
> >   1 file changed, 6 insertions(+), 8 deletions(-)
> > 
> > diff --git a/qom/cpu.c b/qom/cpu.c
> > index 4f38db0..caf5c14 100644
> > --- a/qom/cpu.c
> > +++ b/qom/cpu.c
> > @@ -50,28 +50,26 @@ bool cpu_exists(int64_t id)
> >   
> >   CPUState *cpu_generic_init(const char *typename, const char *cpu_model)
> >   {
> > -    char *str, *name, *featurestr;
> >       CPUState *cpu = NULL;
> >       ObjectClass *oc;
> >       CPUClass *cc;
> >       Error *err = NULL;
> > +    gchar **model_pieces;
> >   
> > -    str = g_strdup(cpu_model);
> > -    name = strtok(str, ",");
> > +    model_pieces = g_strsplit(cpu_model, ",", 2);
> >   
> > -    oc = cpu_class_by_name(typename, name);
> > +    oc = cpu_class_by_name(typename, model_pieces[0]);
> >       if (oc == NULL) {
> > -        g_free(str);
> > +        g_strfreev(model_pieces);
> >           return NULL;
> >       }
> >   
> >       cc = CPU_CLASS(oc);
> > -    featurestr = strtok(NULL, ",");
> >       /* TODO: all callers of cpu_generic_init() need to be converted to
> >        * call parse_features() only once, before calling cpu_generic_init().
> >        */
> > -    cc->parse_features(object_class_get_name(oc), featurestr, &err);
> > -    g_free(str);  
> 
> I feel safer adding:
> 
>         if (g_strv_length(model_pieces) > 1) {
all current callbacks (i386/sparc/cpu_common_parse_features) deal with

  cc->parse_features(,NULL,)

by explicitly checking for NULL, so there is no need for check here.

Though, it's possible to avoid calling callback at all
if model_pieces[1] == NULL

Would you like to post a patch on top?

> 
> > +    cc->parse_features(object_class_get_name(oc), model_pieces[1], &err);  
> 
>         }
> 
> > +    g_strfreev(model_pieces);
> >       if (err != NULL) {
> >           goto out;
> >       }
> >   
>
Philippe Mathieu-Daudé Aug. 25, 2017, 11:55 a.m. UTC | #3
On 08/25/2017 05:11 AM, Igor Mammedov wrote:
> Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>> On 08/24/2017 01:31 PM, Igor Mammedov wrote:
>>> since commit ( 9262685b cpu: Factor out cpu_generic_init() )
>>> features parsed by it were truncated only to the 1st feature
>>> after CPU name due to fact that
>>>
>>>      featurestr = strtok(NULL, ",");
>>>      cc->parse_features(cpu, featurestr, &err);
>>>
>>> would extract exactly one feature and parse_features() callback
>>> would parse it and only it leaving the rest of features ignored.
>>>
>>> Reuse approach from x86 custom impl. i.e. replace strtok() token
>>> parsing with g_strsplit(), which would split feature string in
>>> 2 parts name and features list and pass the later to
>>> parse_features() callback.
>>>
>>> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
>>> ---
>>> CC: Eduardo Habkost <ehabkost@redhat.com>
>>> CC: Andreas Färber <afaerber@suse.de>
>>>
>>> Probably due to existing users not actualy using/having any
>>> features to parse bug were unnoticed for 2 years but switching
>>> from custom cpu_foo_init() to cpu_generic_init() triggered it.
>>> ---
>>>    qom/cpu.c | 14 ++++++--------
>>>    1 file changed, 6 insertions(+), 8 deletions(-)
>>>
>>> diff --git a/qom/cpu.c b/qom/cpu.c
>>> index 4f38db0..caf5c14 100644
>>> --- a/qom/cpu.c
>>> +++ b/qom/cpu.c
>>> @@ -50,28 +50,26 @@ bool cpu_exists(int64_t id)
>>>    
>>>    CPUState *cpu_generic_init(const char *typename, const char *cpu_model)
>>>    {
>>> -    char *str, *name, *featurestr;
>>>        CPUState *cpu = NULL;
>>>        ObjectClass *oc;
>>>        CPUClass *cc;
>>>        Error *err = NULL;
>>> +    gchar **model_pieces;
>>>    
>>> -    str = g_strdup(cpu_model);
>>> -    name = strtok(str, ",");
>>> +    model_pieces = g_strsplit(cpu_model, ",", 2);
>>>    
>>> -    oc = cpu_class_by_name(typename, name);
>>> +    oc = cpu_class_by_name(typename, model_pieces[0]);
>>>        if (oc == NULL) {
>>> -        g_free(str);
>>> +        g_strfreev(model_pieces);
>>>            return NULL;
>>>        }
>>>    
>>>        cc = CPU_CLASS(oc);
>>> -    featurestr = strtok(NULL, ",");
>>>        /* TODO: all callers of cpu_generic_init() need to be converted to
>>>         * call parse_features() only once, before calling cpu_generic_init().
>>>         */
>>> -    cc->parse_features(object_class_get_name(oc), featurestr, &err);
>>> -    g_free(str);
>>
>> I feel safer adding:
>>
>>          if (g_strv_length(model_pieces) > 1) {
> all current callbacks (i386/sparc/cpu_common_parse_features) deal with
> 
>    cc->parse_features(,NULL,)
> 
> by explicitly checking for NULL, so there is no need for check here.
> 
> Though, it's possible to avoid calling callback at all
> if model_pieces[1] == NULL
> 
> Would you like to post a patch on top?

Ok so it is safe. I might eventually but this not a big win, so no worries.

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

> 
>>
>>> +    cc->parse_features(object_class_get_name(oc), model_pieces[1], &err);
>>
>>          }
>>
>>> +    g_strfreev(model_pieces);
>>>        if (err != NULL) {
>>>            goto out;
>>>        }
>>>    
>>
>
Eduardo Habkost Aug. 25, 2017, 1:16 p.m. UTC | #4
On Thu, Aug 24, 2017 at 06:31:24PM +0200, Igor Mammedov wrote:
> since commit ( 9262685b cpu: Factor out cpu_generic_init() )
> features parsed by it were truncated only to the 1st feature
> after CPU name due to fact that
> 
>    featurestr = strtok(NULL, ",");
>    cc->parse_features(cpu, featurestr, &err);
> 
> would extract exactly one feature and parse_features() callback
> would parse it and only it leaving the rest of features ignored.
> 
> Reuse approach from x86 custom impl. i.e. replace strtok() token
> parsing with g_strsplit(), which would split feature string in
> 2 parts name and features list and pass the later to
> parse_features() callback.
> 
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>

Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
diff mbox

Patch

diff --git a/qom/cpu.c b/qom/cpu.c
index 4f38db0..caf5c14 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -50,28 +50,26 @@  bool cpu_exists(int64_t id)
 
 CPUState *cpu_generic_init(const char *typename, const char *cpu_model)
 {
-    char *str, *name, *featurestr;
     CPUState *cpu = NULL;
     ObjectClass *oc;
     CPUClass *cc;
     Error *err = NULL;
+    gchar **model_pieces;
 
-    str = g_strdup(cpu_model);
-    name = strtok(str, ",");
+    model_pieces = g_strsplit(cpu_model, ",", 2);
 
-    oc = cpu_class_by_name(typename, name);
+    oc = cpu_class_by_name(typename, model_pieces[0]);
     if (oc == NULL) {
-        g_free(str);
+        g_strfreev(model_pieces);
         return NULL;
     }
 
     cc = CPU_CLASS(oc);
-    featurestr = strtok(NULL, ",");
     /* TODO: all callers of cpu_generic_init() need to be converted to
      * call parse_features() only once, before calling cpu_generic_init().
      */
-    cc->parse_features(object_class_get_name(oc), featurestr, &err);
-    g_free(str);
+    cc->parse_features(object_class_get_name(oc), model_pieces[1], &err);
+    g_strfreev(model_pieces);
     if (err != NULL) {
         goto out;
     }