[PATCH v2] xenParseVif: Refactor parser

Peter Krempa posted 1 patch 3 years, 1 month ago
Test syntax-check failed
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/libvirt tags/patchew/9832f390e51c6c6b07d5fdbfb24bdf70bde60fc0.1615479689.git.pkrempa@redhat.com
src/libxl/xen_common.c | 130 +++++++++++++----------------------------
1 file changed, 39 insertions(+), 91 deletions(-)
[PATCH v2] xenParseVif: Refactor parser
Posted by Peter Krempa 3 years, 1 month ago
Use g_strsplit to split the string and avoid use of stack'd strings.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
---
 src/libxl/xen_common.c | 130 +++++++++++++----------------------------
 1 file changed, 39 insertions(+), 91 deletions(-)

v2:
 - helper variables are made const and strings are borrowed from the
   array returned by g_strsplit instead of copying/freeing
 - second argument of xenParseVifBridge turned const to silence compiler

diff --git a/src/libxl/xen_common.c b/src/libxl/xen_common.c
index c56815d7fc..0d3a3f994a 100644
--- a/src/libxl/xen_common.c
+++ b/src/libxl/xen_common.c
@@ -1027,7 +1027,7 @@ xenParseCharDev(virConfPtr conf, virDomainDefPtr def, const char *nativeFormat)


 static int
-xenParseVifBridge(virDomainNetDefPtr net, char *bridge)
+xenParseVifBridge(virDomainNetDefPtr net, const char *bridge)
 {
     char *vlanstr;
     unsigned int tag;
@@ -1141,104 +1141,53 @@ xenParseVif(char *entry, const char *vif_typename)
 {
     virDomainNetDefPtr net = NULL;
     virDomainNetDefPtr ret = NULL;
-    char *script = NULL;
-    char model[10];
-    char type[10];
-    char ip[128];
-    char mac[18];
-    char bridge[50];
-    char vifname[50];
-    char rate[50];
-    char *key;
-
-    bridge[0] = '\0';
-    mac[0] = '\0';
-    ip[0] = '\0';
-    model[0] = '\0';
-    type[0] = '\0';
-    vifname[0] = '\0';
-    rate[0] = '\0';
-
-    key = entry;
-    while (key) {
-        char *data;
-        char *nextkey = strchr(key, ',');
-
-        if (!(data = strchr(key, '=')))
+    g_auto(GStrv) keyvals = NULL;
+    GStrv keyval;
+    const char *script = NULL;
+    const char *model = NULL;
+    const char *type = NULL;
+    const char *ip = NULL;
+    const char *mac = NULL;
+    const char *bridge = NULL;
+    const char *vifname = NULL;
+    const char *rate = NULL;
+
+    keyvals = g_strsplit(entry, ",", 0);
+
+    for (keyval = keyvals; keyval && *keyval; keyval++) {
+        const char *key = *keyval;
+        char *val = strchr(key, '=');
+
+        virSkipSpaces(&key);
+
+        if (!val)
             return NULL;
-        data++;
+
+        val++;

         if (STRPREFIX(key, "mac=")) {
-            int len = nextkey ? (nextkey - data) : strlen(data);
-            if (virStrncpy(mac, data, len, sizeof(mac)) < 0) {
-                virReportError(VIR_ERR_INTERNAL_ERROR,
-                               _("MAC address %s too big for destination"),
-                               data);
-                return NULL;
-            }
+            mac = val;
         } else if (STRPREFIX(key, "bridge=")) {
-            int len = nextkey ? (nextkey - data) : strlen(data);
-            if (virStrncpy(bridge, data, len, sizeof(bridge)) < 0) {
-                virReportError(VIR_ERR_INTERNAL_ERROR,
-                               _("Bridge %s too big for destination"),
-                               data);
-                return NULL;
-            }
+            bridge = val;
         } else if (STRPREFIX(key, "script=")) {
-            int len = nextkey ? (nextkey - data) : strlen(data);
-            VIR_FREE(script);
-            script = g_strndup(data, len);
+            script = val;
         } else if (STRPREFIX(key, "model=")) {
-            int len = nextkey ? (nextkey - data) : strlen(data);
-            if (virStrncpy(model, data, len, sizeof(model)) < 0) {
-                virReportError(VIR_ERR_INTERNAL_ERROR,
-                               _("Model %s too big for destination"),
-                               data);
-                return NULL;
-            }
+            model = val;
         } else if (STRPREFIX(key, "type=")) {
-            int len = nextkey ? (nextkey - data) : strlen(data);
-            if (virStrncpy(type, data, len, sizeof(type)) < 0) {
-                virReportError(VIR_ERR_INTERNAL_ERROR,
-                               _("Type %s too big for destination"),
-                               data);
-                return NULL;
-            }
+            type = val;
         } else if (STRPREFIX(key, "vifname=")) {
-            int len = nextkey ? (nextkey - data) : strlen(data);
-            if (virStrncpy(vifname, data, len, sizeof(vifname)) < 0) {
-                virReportError(VIR_ERR_INTERNAL_ERROR,
-                               _("Vifname %s too big for destination"),
-                               data);
-                return NULL;
-            }
+            vifname = val;
         } else if (STRPREFIX(key, "ip=")) {
-            int len = nextkey ? (nextkey - data) : strlen(data);
-            if (virStrncpy(ip, data, len, sizeof(ip)) < 0) {
-                virReportError(VIR_ERR_INTERNAL_ERROR,
-                               _("IP %s too big for destination"), data);
-                return NULL;
-            }
+            ip = val;
         } else if (STRPREFIX(key, "rate=")) {
-            int len = nextkey ? (nextkey - data) : strlen(data);
-            if (virStrncpy(rate, data, len, sizeof(rate)) < 0) {
-                virReportError(VIR_ERR_INTERNAL_ERROR,
-                               _("rate %s too big for destination"), data);
-                return NULL;
-            }
+            rate = val;
         }
-
-        while (nextkey && (nextkey[0] == ',' ||
-                           nextkey[0] == ' ' ||
-                           nextkey[0] == '\t'))
-            nextkey++;
-        key = nextkey;
     }

     if (!(net = virDomainNetDefNew(NULL)))
         goto cleanup;

-    if (mac[0]) {
+    if (mac) {
         if (virMacAddrParse(mac, &net->mac) < 0) {
             virReportError(VIR_ERR_INTERNAL_ERROR,
                            _("malformed mac address '%s'"), mac);
@@ -1246,18 +1195,18 @@ xenParseVif(char *entry, const char *vif_typename)
         }
     }

-    if (bridge[0] || STREQ_NULLABLE(script, "vif-bridge") ||
+    if (bridge || STREQ_NULLABLE(script, "vif-bridge") ||
         STREQ_NULLABLE(script, "vif-vnic")) {
         net->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
     } else {
         net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
     }

-    if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE && bridge[0]) {
+    if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE && bridge) {
         if (xenParseVifBridge(net, bridge) < 0)
             goto cleanup;
     }
-    if (ip[0]) {
+    if (ip) {
         char **ip_list = g_strsplit(ip, " ", 0);
         size_t i;

@@ -1276,18 +1225,18 @@ xenParseVif(char *entry, const char *vif_typename)
     if (script && script[0])
         net->script = g_strdup(script);

-    if (model[0]) {
+    if (model) {
         if (virDomainNetSetModelString(net, model) < 0)
             goto cleanup;
     } else {
-        if (type[0] && STREQ(type, vif_typename))
+        if (type && STREQ(type, vif_typename))
             net->model = VIR_DOMAIN_NET_MODEL_NETFRONT;
     }

-    if (vifname[0])
+    if (vifname && vifname[0])
         net->ifname = g_strdup(vifname);

-    if (rate[0]) {
+    if (rate) {
         virNetDevBandwidthPtr bandwidth;
         unsigned long long kbytes_per_sec;

@@ -1304,7 +1253,6 @@ xenParseVif(char *entry, const char *vif_typename)

  cleanup:
     virDomainNetDefFree(net);
-    VIR_FREE(script);
     return ret;
 }

-- 
2.29.2

Re: [PATCH v2] xenParseVif: Refactor parser
Posted by Michal Privoznik 3 years, 1 month ago
On 3/11/21 5:23 PM, Peter Krempa wrote:
> Use g_strsplit to split the string and avoid use of stack'd strings.
> 
> Signed-off-by: Peter Krempa <pkrempa@redhat.com>
> ---
>   src/libxl/xen_common.c | 130 +++++++++++++----------------------------
>   1 file changed, 39 insertions(+), 91 deletions(-)

Reviewed-by: Michal Privoznik <mprivozn@redhat.com>

Michal