This patch separates the label parsing functionality from the program
termination and memory allocation duties of parse_label(). This will
ultimately help in creating simple helper functions that simply need to
check if a label contains a namespace.

Signed-off-by: Tyler Hicks <[email protected]>
---
 parser/parser_misc.c | 94 +++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 75 insertions(+), 19 deletions(-)

diff --git a/parser/parser_misc.c b/parser/parser_misc.c
index 2348189..d0d8115 100644
--- a/parser/parser_misc.c
+++ b/parser/parser_misc.c
@@ -569,24 +569,44 @@ int parse_X_mode(const char *X, int valid, const char 
*str_mode, int *mode, int
        return 1;
 }
 
-void parse_label(char **ns, char **name, const char *label)
+/**
+ * parse_label - break a label down to the namespace and profile name
+ * @ns: Will point to the first char in the namespace upon return or NULL
+ *      if no namespace is present
+ * @ns_len: Number of chars in the namespace string or 0 if no namespace
+ *          is present
+ * @name: Will point to the first char in the profile name upon return
+ * @name_len: Number of chars in the name string
+ * @label: The label to parse into namespace and profile name
+ *
+ * The returned pointers will point to locations within the original
+ * @label string. No new strings are allocated.
+ *
+ * Returns 0 upon success or non-zero with @ns, @ns_len, @name, and
+ * @name_len undefined upon error. Error codes are:
+ *
+ * 1) Namespace is not terminated despite @label starting with ':'
+ * 2) Namespace is empty meaning @label starts with "::"
+ * 3) Profile name is empty
+ */
+static int _parse_label(char **ns, size_t *ns_len,
+                       char **name, size_t *name_len,
+                       const char *label)
 {
        const char *name_start = NULL;
-       char *_ns = NULL;
-       char *_name = NULL;
+       const char *ns_start = NULL;
+       const char *ns_end = NULL;
 
        if (label[0] != ':') {
                /* There is no namespace specified in the label */
                name_start = label;
        } else {
                /* A leading ':' indicates that a namespace is specified */
-               const char *ns_start = label + 1;
-               const char *ns_end = strstr(ns_start, ":");
+               ns_start = label + 1;
+               ns_end = strstr(ns_start, ":");
 
                if (!ns_end)
-                       yyerror(_("Namespace not terminated: %s\n"), label);
-               else if (ns_end - ns_start == 0)
-                       yyerror(_("Empty namespace: %s\n"), label);
+                       return 1;
 
                /**
                 * Handle either of the two namespace formats:
@@ -596,23 +616,59 @@ void parse_label(char **ns, char **name, const char 
*label)
                name_start = ns_end + 1;
                if (!strncmp(name_start, "//", 2))
                        name_start += 2;
-
-               _ns = strndup(ns_start, ns_end - ns_start);
-               if (!_ns)
-                       yyerror(_("Memory allocation error."));
        }
 
-       if (!strlen(name_start))
+       /**
+        * The casts below are to allow @label to be const, signifying
+        * that this function doesn't modify it, while allowing callers to
+        * decide if they want to pass in pointers to const or non-const
+        * strings.
+        */
+       *ns = (char *)ns_start;
+       *name = (char *)name_start;
+       *ns_len = ns_end - ns_start;
+       *name_len = strlen(name_start);
+
+       if (*ns && *ns_len == 0)
+               return 2;
+       else if (*name_len == 0)
+               return 3;
+
+       return 0;
+}
+
+void parse_label(char **_ns, char **_name, const char *label)
+{
+       char *ns = NULL;
+       char *name = NULL;
+       size_t ns_len = 0;
+       size_t name_len = 0;
+       int res;
+
+       res = _parse_label(&ns, &ns_len, &name, &name_len, label);
+       if (res == 1) {
+               yyerror(_("Namespace not terminated: %s\n"), label);
+       } else if (res == 2) {
+               yyerror(_("Empty namespace: %s\n"), label);
+       } else if (res == 3) {
                yyerror(_("Empty named transition profile name: %s\n"), label);
+       } else if (res != 0) {
+               yyerror(_("Unknown error while parsing label: %s\n"), label);
+       }
 
-       _name = strdup(name_start);
-       if (!_name) {
-               free(_ns);
-               yyerror(_("Memory allocation error."));
+       if (ns) {
+               *_ns = strndup(ns, ns_len);
+               if (!*_ns)
+                       yyerror(_("Memory allocation error."));
+       } else {
+               *_ns = NULL;
        }
 
-       *ns = _ns;
-       *name = _name;
+       *_name = strndup(name, name_len);
+       if (!*_name) {
+               free(*_ns);
+               yyerror(_("Memory allocation error."));
+       }
 }
 
 void parse_named_transition_target(struct named_transition *nt,
-- 
2.7.0


-- 
AppArmor mailing list
[email protected]
Modify settings or unsubscribe at: 
https://lists.ubuntu.com/mailman/listinfo/apparmor

Reply via email to